Patchwork [RFC,2/2] hw: add Embedded Controller chip emulation

login
register
mail settings
Submitter liguang
Date April 17, 2013, 7:23 a.m.
Message ID <1366183380-24333-2-git-send-email-lig.fnst@cn.fujitsu.com>
Download mbox | patch
Permalink /patch/237157/
State New
Headers show

Comments

liguang - April 17, 2013, 7:23 a.m.
this work implemented Embedded Controller chip emulation
which was defined at ACPI SEPC v5 chapter 12:
"ACPI Embedded Controller Interface Specification"

commonly Embedded Controller will emulate keyboard,
mouse, handle ACPI defined operations and some
low-speed devices like SMbus.

Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
---
 hw/ec.c |  113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ec.h |   20 +++++++++++
 2 files changed, 133 insertions(+), 0 deletions(-)
 create mode 100644 hw/ec.c
 create mode 100644 hw/ec.h
Mark Marshall - April 17, 2013, 10:41 a.m.
Hi.

At least one major bug (noted below), have you tested all of this yet?

MM


On 17 April 2013 09:23, liguang <lig.fnst@cn.fujitsu.com> wrote:

> this work implemented Embedded Controller chip emulation
> which was defined at ACPI SEPC v5 chapter 12:
> "ACPI Embedded Controller Interface Specification"
>
> commonly Embedded Controller will emulate keyboard,
> mouse, handle ACPI defined operations and some
> low-speed devices like SMbus.
>
> Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
> ---
>  hw/ec.c |  113
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/ec.h |   20 +++++++++++
>  2 files changed, 133 insertions(+), 0 deletions(-)
>  create mode 100644 hw/ec.c
>  create mode 100644 hw/ec.h
>
> diff --git a/hw/ec.c b/hw/ec.c
> new file mode 100644
> index 0000000..69c92cf
> --- /dev/null
> +++ b/hw/ec.c
> @@ -0,0 +1,113 @@
> +#include "ec.h"
> +#include "hw/hw.h"
> +#include "hw/isa/isa.h"
> +#include "sysemu/sysemu.h"
> +
> +#define TYPE_EC_DEV
> +#define EC_DEV(obj) \
> +    OBJECT_CHECK(ECState, (obj), TYPE_EC_DEV)
> +
> +static char ec_acpi_space[EC_ACPI_SPACE_SIZE] = {0};
> +
> +typedef struct ECState {
> +    ISADevice dev;
> +    char cmd;
> +    char status;
> +    char data;
> +    char irq;
> +    char buf;
> +    MemoryRegion io;
> +} ECState;
> +
> +
> +static void io62_write(void *opaque, hwaddr addr, uint64_t val, unsigned
> size)
> +{
> +    ECState *s = opaque;
> +    char tmp = val & 0xff;
> +
> +    if (s->status & EC_ACPI_CMD) {
> +        s->buf = tmp;
> +        s->status &= ~EC_ACPI_CMD;
> +    } else {
> +        if (tmp < EC_ACPI_SPACE_SIZE) {
> +            ec_acpi_space[s->buf] = tmp;
> +        }
> +    }
> +}
> +
> +static uint64_t io62_read(void *opaque, hwaddr addr, unsigned size)
> +{
> +    return s->data;
> +}
> +
> +static void io66_write(void *opaque, hwaddr addr, uint64_t val, unsigned
> size)
> +{
> +    ECState *s = opaque;
> +
> +    s->status = EC_ACPI_CMD | EC_ACPI_IBF;
> +
> +    switch (val & 0xff) {
> +    case EC_ACPI_CMD_READ:
> +    case EC_ACPI_CMD_WRITE:
> +    case EC_ACPI_CMD_BURST_EN:
> +        s->statu |= EC_ACPI_BST;
> +    case EC_ACPI_CMD_BURST_DN:
> +        s->statu &= ~EC_ACPI_BST;
> +    case EC_ACPI_CMD_QUERY:
> +        s->cmd = val & 0xff;
> +    case default:
> +        break;
> +    }
> +}
>

You've missed 'break' here a few times.


> +
> +static uint64_t io66_read(void *opaque, hwaddr addr, unsigned size)
> +{
> +    ECState *s = opaque;
> +
> +    return s->status;
> +}
> +
> +static const MemoryRegionOps io62_io_ops = {
> +    .write = io62_write,
> +    .read = io62_read,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +    .impl = {
> +        .min_access_size = 1,
> +        .max_access_size = 1,
> +    },
> +};
> +
> +static const MemoryRegionOps io66_io_ops = {
> +    .write = io66_write,
> +    .read = io66_read,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +    .impl = {
> +        .min_access_size = 1,
> +        .max_access_size = 1,
> +    },
> +};
> +
> +static void ec_realizefn(DeviceState *dev, Error **err)
> +{
> +    ISADevice *isadev = ISA_DEVICE(dev);
> +    ECState *s = EC_DEV(dev);
> +
> +    isa_init_irq(isadev, &s->irq, 0xb);
> +
> +    memory_region_init_io(&s->io, &io62_io_ops, NULL, "ec-acpi-data", 1);
> +    isa_register_ioport(isadev, &s->io, 0x62);
> +
> +    memory_region_init_io(&s->io, &io66_io_ops, NULL, "ec-acpi-cmd", 1);
> +    isa_register_ioport(isadev, &s->io, 0x66);
> +
> +    s->status = 0;
> +    s->data = 0;
> +}
> +
> +static void ec_class_initfn(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = ec_realizefn;
> +    dc->no_user = 1;
> +}
> diff --git a/hw/ec.h b/hw/ec.h
> new file mode 100644
> index 0000000..110ce04
> --- /dev/null
> +++ b/hw/ec.h
> @@ -0,0 +1,20 @@
> +#inndef __EC_H
> +#define __EC_H
> +
> +#define EC_ACPI_SPACE_SIZE 0x80
> +
> +#define EC_ACPI_CMD_PORT 0x66
> +#define EC_ACPI_DATA_PORT 0x62
> +
> +#define EC_ACPI_OBF 0x1
> +#define EC_ACPI_IBF 0x2
> +#define EC_ACPI_CMD 0x8
> +#define EC_ACPI_BST 0x10
> +
> +#define EC_ACPI_CMD_READ 0x80
> +#define EC_ACPI_CMD_WRITE 0x81
> +#define EC_ACPI_BURST_EN 0x82
> +#define EC_ACPI_BURST_DN 0x83
> +#define EC_ACPI_CMD_QUERY 0x84
> +
> +#endif
> --
> 1.7.2.5
>
>
> _______________________________________________
> SeaBIOS mailing list
> SeaBIOS@seabios.org
> http://www.seabios.org/mailman/listinfo/seabios
>
Andreas Färber - April 17, 2013, 5:54 p.m.
Am 17.04.2013 09:23, schrieb liguang:
> this work implemented Embedded Controller chip emulation
> which was defined at ACPI SEPC v5 chapter 12:
> "ACPI Embedded Controller Interface Specification"
> 
> commonly Embedded Controller will emulate keyboard,
> mouse, handle ACPI defined operations and some
> low-speed devices like SMbus.
> 
> Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
> ---
>  hw/ec.c |  113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

hw/misc/ec.c? hw/i386/ec.c? Not directly in hw/ anymore.

>  hw/ec.h |   20 +++++++++++
>  2 files changed, 133 insertions(+), 0 deletions(-)
>  create mode 100644 hw/ec.c
>  create mode 100644 hw/ec.h
> 
> diff --git a/hw/ec.c b/hw/ec.c
> new file mode 100644
> index 0000000..69c92cf
> --- /dev/null
> +++ b/hw/ec.c
> @@ -0,0 +1,113 @@
> +#include "ec.h"
> +#include "hw/hw.h"
> +#include "hw/isa/isa.h"
> +#include "sysemu/sysemu.h"
> +
> +#define TYPE_EC_DEV

Missing string value.

> +#define EC_DEV(obj) \
> +    OBJECT_CHECK(ECState, (obj), TYPE_EC_DEV)
> +
> +static char ec_acpi_space[EC_ACPI_SPACE_SIZE] = {0};
> +
> +typedef struct ECState {
> +    ISADevice dev;

parent_obj and white line please.

> +    char cmd;
> +    char status;
> +    char data;
> +    char irq;
> +    char buf;

char seems a bit unsafe here, since it might be signed or unsigned.
Suggest uint8_t.

> +    MemoryRegion io;
> +} ECState;
> +
> +
> +static void io62_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
> +{
> +    ECState *s = opaque;
> +    char tmp = val & 0xff;
> +
> +    if (s->status & EC_ACPI_CMD) {
> +        s->buf = tmp;
> +        s->status &= ~EC_ACPI_CMD;
> +    } else {
> +        if (tmp < EC_ACPI_SPACE_SIZE) {
> +            ec_acpi_space[s->buf] = tmp;
> +        }
> +    }
> +}
> +
> +static uint64_t io62_read(void *opaque, hwaddr addr, unsigned size)
> +{
> +    return s->data;
> +}
> +
> +static void io66_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
> +{
> +    ECState *s = opaque;
> +
> +    s->status = EC_ACPI_CMD | EC_ACPI_IBF;
> +
> +    switch (val & 0xff) {
> +    case EC_ACPI_CMD_READ:
> +    case EC_ACPI_CMD_WRITE:
> +    case EC_ACPI_CMD_BURST_EN:
> +        s->statu |= EC_ACPI_BST;

s->status

> +    case EC_ACPI_CMD_BURST_DN:
> +        s->statu &= ~EC_ACPI_BST;

s->status

> +    case EC_ACPI_CMD_QUERY:
> +        s->cmd = val & 0xff;
> +    case default:
> +        break;
> +    }
> +}
> +
> +static uint64_t io66_read(void *opaque, hwaddr addr, unsigned size)
> +{
> +    ECState *s = opaque;
> +
> +    return s->status;
> +}
> +
> +static const MemoryRegionOps io62_io_ops = {
> +    .write = io62_write,
> +    .read = io62_read,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +    .impl = {
> +        .min_access_size = 1,
> +        .max_access_size = 1,
> +    },
> +};
> +
> +static const MemoryRegionOps io66_io_ops = {
> +    .write = io66_write,
> +    .read = io66_read,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +    .impl = {
> +        .min_access_size = 1,
> +        .max_access_size = 1,
> +    },
> +};
> +
> +static void ec_realizefn(DeviceState *dev, Error **err)
> +{
> +    ISADevice *isadev = ISA_DEVICE(dev);
> +    ECState *s = EC_DEV(dev);
> +
> +    isa_init_irq(isadev, &s->irq, 0xb);
> +

> +    memory_region_init_io(&s->io, &io62_io_ops, NULL, "ec-acpi-data", 1);
> +    isa_register_ioport(isadev, &s->io, 0x62);
> +
> +    memory_region_init_io(&s->io, &io66_io_ops, NULL, "ec-acpi-cmd", 1);
> +    isa_register_ioport(isadev, &s->io, 0x66);

Since you are not defining any properties, all of this could go into a
.instance_init function.

But I am glad to see a realize function being used. :)

> +
> +    s->status = 0;
> +    s->data = 0;

This is probably not necessary here, since all fields get
zero-initialized. It should rather go into a reset function.

> +}
> +
> +static void ec_class_initfn(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = ec_realizefn;
> +    dc->no_user = 1;
> +}

This file ends with an unused static function, it's missing type
registration.

I figure this device should rather be a specific (real) model, reflected
in a particular name, similar to how we have different watchdog devices
rather than a "watchdog" device.

> diff --git a/hw/ec.h b/hw/ec.h
> new file mode 100644
> index 0000000..110ce04
> --- /dev/null
> +++ b/hw/ec.h
> @@ -0,0 +1,20 @@
> +#inndef __EC_H

#ifndef and no leading underscores, please.

> +#define __EC_H
> +
> +#define EC_ACPI_SPACE_SIZE 0x80
> +
> +#define EC_ACPI_CMD_PORT 0x66
> +#define EC_ACPI_DATA_PORT 0x62
> +
> +#define EC_ACPI_OBF 0x1
> +#define EC_ACPI_IBF 0x2
> +#define EC_ACPI_CMD 0x8
> +#define EC_ACPI_BST 0x10
> +
> +#define EC_ACPI_CMD_READ 0x80
> +#define EC_ACPI_CMD_WRITE 0x81
> +#define EC_ACPI_BURST_EN 0x82
> +#define EC_ACPI_BURST_DN 0x83
> +#define EC_ACPI_CMD_QUERY 0x84
> +
> +#endif

Regards,
Andreas
liguang - April 18, 2013, 12:23 a.m.
在 2013-04-17三的 19:54 +0200,Andreas Färber写道:
> Am 17.04.2013 09:23, schrieb liguang:
> > this work implemented Embedded Controller chip emulation
> > which was defined at ACPI SEPC v5 chapter 12:
> > "ACPI Embedded Controller Interface Specification"
> > 
> > commonly Embedded Controller will emulate keyboard,
> > mouse, handle ACPI defined operations and some
> > low-speed devices like SMbus.
> > 
> > Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
> > ---
> >  hw/ec.c |  113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 
> hw/misc/ec.c? hw/i386/ec.c? Not directly in hw/ anymore.
> 
> >  hw/ec.h |   20 +++++++++++
> >  2 files changed, 133 insertions(+), 0 deletions(-)
> >  create mode 100644 hw/ec.c
> >  create mode 100644 hw/ec.h
> > 
> > diff --git a/hw/ec.c b/hw/ec.c
> > new file mode 100644
> > index 0000000..69c92cf
> > --- /dev/null
> > +++ b/hw/ec.c
> > @@ -0,0 +1,113 @@
> > +#include "ec.h"
> > +#include "hw/hw.h"
> > +#include "hw/isa/isa.h"
> > +#include "sysemu/sysemu.h"
> > +
> > +#define TYPE_EC_DEV
> 
> Missing string value.
> 
> > +#define EC_DEV(obj) \
> > +    OBJECT_CHECK(ECState, (obj), TYPE_EC_DEV)
> > +
> > +static char ec_acpi_space[EC_ACPI_SPACE_SIZE] = {0};
> > +
> > +typedef struct ECState {
> > +    ISADevice dev;
> 
> parent_obj and white line please.
> 
> > +    char cmd;
> > +    char status;
> > +    char data;
> > +    char irq;
> > +    char buf;
> 
> char seems a bit unsafe here, since it might be signed or unsigned.
> Suggest uint8_t.
> 
> > +    MemoryRegion io;
> > +} ECState;
> > +
> > +
> > +static void io62_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
> > +{
> > +    ECState *s = opaque;
> > +    char tmp = val & 0xff;
> > +
> > +    if (s->status & EC_ACPI_CMD) {
> > +        s->buf = tmp;
> > +        s->status &= ~EC_ACPI_CMD;
> > +    } else {
> > +        if (tmp < EC_ACPI_SPACE_SIZE) {
> > +            ec_acpi_space[s->buf] = tmp;
> > +        }
> > +    }
> > +}
> > +
> > +static uint64_t io62_read(void *opaque, hwaddr addr, unsigned size)
> > +{
> > +    return s->data;
> > +}
> > +
> > +static void io66_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
> > +{
> > +    ECState *s = opaque;
> > +
> > +    s->status = EC_ACPI_CMD | EC_ACPI_IBF;
> > +
> > +    switch (val & 0xff) {
> > +    case EC_ACPI_CMD_READ:
> > +    case EC_ACPI_CMD_WRITE:
> > +    case EC_ACPI_CMD_BURST_EN:
> > +        s->statu |= EC_ACPI_BST;
> 
> s->status
> 
> > +    case EC_ACPI_CMD_BURST_DN:
> > +        s->statu &= ~EC_ACPI_BST;
> 
> s->status
> 
> > +    case EC_ACPI_CMD_QUERY:
> > +        s->cmd = val & 0xff;
> > +    case default:
> > +        break;
> > +    }
> > +}
> > +
> > +static uint64_t io66_read(void *opaque, hwaddr addr, unsigned size)
> > +{
> > +    ECState *s = opaque;
> > +
> > +    return s->status;
> > +}
> > +
> > +static const MemoryRegionOps io62_io_ops = {
> > +    .write = io62_write,
> > +    .read = io62_read,
> > +    .endianness = DEVICE_NATIVE_ENDIAN,
> > +    .impl = {
> > +        .min_access_size = 1,
> > +        .max_access_size = 1,
> > +    },
> > +};
> > +
> > +static const MemoryRegionOps io66_io_ops = {
> > +    .write = io66_write,
> > +    .read = io66_read,
> > +    .endianness = DEVICE_NATIVE_ENDIAN,
> > +    .impl = {
> > +        .min_access_size = 1,
> > +        .max_access_size = 1,
> > +    },
> > +};
> > +
> > +static void ec_realizefn(DeviceState *dev, Error **err)
> > +{
> > +    ISADevice *isadev = ISA_DEVICE(dev);
> > +    ECState *s = EC_DEV(dev);
> > +
> > +    isa_init_irq(isadev, &s->irq, 0xb);
> > +
> 
> > +    memory_region_init_io(&s->io, &io62_io_ops, NULL, "ec-acpi-data", 1);
> > +    isa_register_ioport(isadev, &s->io, 0x62);
> > +
> > +    memory_region_init_io(&s->io, &io66_io_ops, NULL, "ec-acpi-cmd", 1);
> > +    isa_register_ioport(isadev, &s->io, 0x66);
> 
> Since you are not defining any properties, all of this could go into a
> .instance_init function.
> 
> But I am glad to see a realize function being used. :)
> 
> > +
> > +    s->status = 0;
> > +    s->data = 0;
> 
> This is probably not necessary here, since all fields get
> zero-initialized. It should rather go into a reset function.
> 
> > +}
> > +
> > +static void ec_class_initfn(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > +    dc->realize = ec_realizefn;
> > +    dc->no_user = 1;
> > +}
> 
> This file ends with an unused static function, it's missing type
> registration.

OK, will fix all,

Thanks you so much!

> 
> I figure this device should rather be a specific (real) model, reflected
> in a particular name, similar to how we have different watchdog devices
> rather than a "watchdog" device.

does it has to be specific model?
my reason to be generic like "generic-sdhci"(SD host controller) device
is mostly all EC devices play a similar role, and we do not have to
know the difference between EC chip from different vendors

> 
> > diff --git a/hw/ec.h b/hw/ec.h
> > new file mode 100644
> > index 0000000..110ce04
> > --- /dev/null
> > +++ b/hw/ec.h
> > @@ -0,0 +1,20 @@
> > +#inndef __EC_H
> 
> #ifndef and no leading underscores, please.
> 
> > +#define __EC_H
> > +
> > +#define EC_ACPI_SPACE_SIZE 0x80
> > +
> > +#define EC_ACPI_CMD_PORT 0x66
> > +#define EC_ACPI_DATA_PORT 0x62
> > +
> > +#define EC_ACPI_OBF 0x1
> > +#define EC_ACPI_IBF 0x2
> > +#define EC_ACPI_CMD 0x8
> > +#define EC_ACPI_BST 0x10
> > +
> > +#define EC_ACPI_CMD_READ 0x80
> > +#define EC_ACPI_CMD_WRITE 0x81
> > +#define EC_ACPI_BURST_EN 0x82
> > +#define EC_ACPI_BURST_DN 0x83
> > +#define EC_ACPI_CMD_QUERY 0x84
> > +
> > +#endif
> 
> Regards,
> Andreas
>
liguang - April 18, 2013, 1:22 a.m.
No, sorry.
As this is RFC patch,
I sent it only for demo my thought.

在 2013-04-17三的 12:41 +0200,Mark Marshall写道:
> Hi.
> 
> 
> At least one major bug (noted below), have you tested all of this yet?
> 
> 
> MM
> 
> 
> On 17 April 2013 09:23, liguang <lig.fnst@cn.fujitsu.com> wrote:
>         this work implemented Embedded Controller chip emulation
>         which was defined at ACPI SEPC v5 chapter 12:
>         "ACPI Embedded Controller Interface Specification"
>         
>         commonly Embedded Controller will emulate keyboard,
>         mouse, handle ACPI defined operations and some
>         low-speed devices like SMbus.
>         
>         Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
>         ---
>          hw/ec.c |  113
>         +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>          hw/ec.h |   20 +++++++++++
>          2 files changed, 133 insertions(+), 0 deletions(-)
>          create mode 100644 hw/ec.c
>          create mode 100644 hw/ec.h
>         
>         diff --git a/hw/ec.c b/hw/ec.c
>         new file mode 100644
>         index 0000000..69c92cf
>         --- /dev/null
>         +++ b/hw/ec.c
>         @@ -0,0 +1,113 @@
>         +#include "ec.h"
>         +#include "hw/hw.h"
>         +#include "hw/isa/isa.h"
>         +#include "sysemu/sysemu.h"
>         +
>         +#define TYPE_EC_DEV
>         +#define EC_DEV(obj) \
>         +    OBJECT_CHECK(ECState, (obj), TYPE_EC_DEV)
>         +
>         +static char ec_acpi_space[EC_ACPI_SPACE_SIZE] = {0};
>         +
>         +typedef struct ECState {
>         +    ISADevice dev;
>         +    char cmd;
>         +    char status;
>         +    char data;
>         +    char irq;
>         +    char buf;
>         +    MemoryRegion io;
>         +} ECState;
>         +
>         +
>         +static void io62_write(void *opaque, hwaddr addr, uint64_t
>         val, unsigned size)
>         +{
>         +    ECState *s = opaque;
>         +    char tmp = val & 0xff;
>         +
>         +    if (s->status & EC_ACPI_CMD) {
>         +        s->buf = tmp;
>         +        s->status &= ~EC_ACPI_CMD;
>         +    } else {
>         +        if (tmp < EC_ACPI_SPACE_SIZE) {
>         +            ec_acpi_space[s->buf] = tmp;
>         +        }
>         +    }
>         +}
>         +
>         +static uint64_t io62_read(void *opaque, hwaddr addr, unsigned
>         size)
>         +{
>         +    return s->data;
>         +}
>         +
>         +static void io66_write(void *opaque, hwaddr addr, uint64_t
>         val, unsigned size)
>         +{
>         +    ECState *s = opaque;
>         +
>         +    s->status = EC_ACPI_CMD | EC_ACPI_IBF;
>         +
>         +    switch (val & 0xff) {
>         +    case EC_ACPI_CMD_READ:
>         +    case EC_ACPI_CMD_WRITE:
>         +    case EC_ACPI_CMD_BURST_EN:
>         +        s->statu |= EC_ACPI_BST;
>         +    case EC_ACPI_CMD_BURST_DN:
>         +        s->statu &= ~EC_ACPI_BST;
>         +    case EC_ACPI_CMD_QUERY:
>         +        s->cmd = val & 0xff;
>         +    case default:
>         +        break;
>         +    }
>         +}
> 
> You've missed 'break' here a few times.
>  
> 
>         +
>         +static uint64_t io66_read(void *opaque, hwaddr addr, unsigned
>         size)
>         +{
>         +    ECState *s = opaque;
>         +
>         +    return s->status;
>         +}
>         +
>         +static const MemoryRegionOps io62_io_ops = {
>         +    .write = io62_write,
>         +    .read = io62_read,
>         +    .endianness = DEVICE_NATIVE_ENDIAN,
>         +    .impl = {
>         +        .min_access_size = 1,
>         +        .max_access_size = 1,
>         +    },
>         +};
>         +
>         +static const MemoryRegionOps io66_io_ops = {
>         +    .write = io66_write,
>         +    .read = io66_read,
>         +    .endianness = DEVICE_NATIVE_ENDIAN,
>         +    .impl = {
>         +        .min_access_size = 1,
>         +        .max_access_size = 1,
>         +    },
>         +};
>         +
>         +static void ec_realizefn(DeviceState *dev, Error **err)
>         +{
>         +    ISADevice *isadev = ISA_DEVICE(dev);
>         +    ECState *s = EC_DEV(dev);
>         +
>         +    isa_init_irq(isadev, &s->irq, 0xb);
>         +
>         +    memory_region_init_io(&s->io, &io62_io_ops, NULL,
>         "ec-acpi-data", 1);
>         +    isa_register_ioport(isadev, &s->io, 0x62);
>         +
>         +    memory_region_init_io(&s->io, &io66_io_ops, NULL,
>         "ec-acpi-cmd", 1);
>         +    isa_register_ioport(isadev, &s->io, 0x66);
>         +
>         +    s->status = 0;
>         +    s->data = 0;
>         +}
>         +
>         +static void ec_class_initfn(ObjectClass *klass, void *data)
>         +{
>         +    DeviceClass *dc = DEVICE_CLASS(klass);
>         +
>         +    dc->realize = ec_realizefn;
>         +    dc->no_user = 1;
>         +}
>         diff --git a/hw/ec.h b/hw/ec.h
>         new file mode 100644
>         index 0000000..110ce04
>         --- /dev/null
>         +++ b/hw/ec.h
>         @@ -0,0 +1,20 @@
>         +#inndef __EC_H
>         +#define __EC_H
>         +
>         +#define EC_ACPI_SPACE_SIZE 0x80
>         +
>         +#define EC_ACPI_CMD_PORT 0x66
>         +#define EC_ACPI_DATA_PORT 0x62
>         +
>         +#define EC_ACPI_OBF 0x1
>         +#define EC_ACPI_IBF 0x2
>         +#define EC_ACPI_CMD 0x8
>         +#define EC_ACPI_BST 0x10
>         +
>         +#define EC_ACPI_CMD_READ 0x80
>         +#define EC_ACPI_CMD_WRITE 0x81
>         +#define EC_ACPI_BURST_EN 0x82
>         +#define EC_ACPI_BURST_DN 0x83
>         +#define EC_ACPI_CMD_QUERY 0x84
>         +
>         +#endif
>         --
>         1.7.2.5
>         
>         
>         _______________________________________________
>         SeaBIOS mailing list
>         SeaBIOS@seabios.org
>         http://www.seabios.org/mailman/listinfo/seabios
> 
>

Patch

diff --git a/hw/ec.c b/hw/ec.c
new file mode 100644
index 0000000..69c92cf
--- /dev/null
+++ b/hw/ec.c
@@ -0,0 +1,113 @@ 
+#include "ec.h"
+#include "hw/hw.h"
+#include "hw/isa/isa.h"
+#include "sysemu/sysemu.h"
+
+#define TYPE_EC_DEV
+#define EC_DEV(obj) \
+    OBJECT_CHECK(ECState, (obj), TYPE_EC_DEV)
+
+static char ec_acpi_space[EC_ACPI_SPACE_SIZE] = {0};
+
+typedef struct ECState {
+    ISADevice dev;
+    char cmd;
+    char status;
+    char data;
+    char irq;
+    char buf;
+    MemoryRegion io;
+} ECState;
+
+
+static void io62_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+    ECState *s = opaque;
+    char tmp = val & 0xff;
+
+    if (s->status & EC_ACPI_CMD) {
+        s->buf = tmp;
+        s->status &= ~EC_ACPI_CMD;
+    } else {
+        if (tmp < EC_ACPI_SPACE_SIZE) {
+            ec_acpi_space[s->buf] = tmp;
+        }
+    }
+}
+
+static uint64_t io62_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return s->data;
+}
+
+static void io66_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+    ECState *s = opaque;
+
+    s->status = EC_ACPI_CMD | EC_ACPI_IBF;
+
+    switch (val & 0xff) {
+    case EC_ACPI_CMD_READ:
+    case EC_ACPI_CMD_WRITE:
+    case EC_ACPI_CMD_BURST_EN:
+        s->statu |= EC_ACPI_BST;
+    case EC_ACPI_CMD_BURST_DN:
+        s->statu &= ~EC_ACPI_BST;
+    case EC_ACPI_CMD_QUERY:
+        s->cmd = val & 0xff;
+    case default:
+        break;
+    }
+}
+
+static uint64_t io66_read(void *opaque, hwaddr addr, unsigned size)
+{
+    ECState *s = opaque;
+
+    return s->status;
+}
+
+static const MemoryRegionOps io62_io_ops = {
+    .write = io62_write,
+    .read = io62_read,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+static const MemoryRegionOps io66_io_ops = {
+    .write = io66_write,
+    .read = io66_read,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+static void ec_realizefn(DeviceState *dev, Error **err)
+{
+    ISADevice *isadev = ISA_DEVICE(dev);
+    ECState *s = EC_DEV(dev);
+
+    isa_init_irq(isadev, &s->irq, 0xb);
+
+    memory_region_init_io(&s->io, &io62_io_ops, NULL, "ec-acpi-data", 1);
+    isa_register_ioport(isadev, &s->io, 0x62);
+
+    memory_region_init_io(&s->io, &io66_io_ops, NULL, "ec-acpi-cmd", 1);
+    isa_register_ioport(isadev, &s->io, 0x66);
+
+    s->status = 0;
+    s->data = 0;
+}
+
+static void ec_class_initfn(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = ec_realizefn;
+    dc->no_user = 1;
+}
diff --git a/hw/ec.h b/hw/ec.h
new file mode 100644
index 0000000..110ce04
--- /dev/null
+++ b/hw/ec.h
@@ -0,0 +1,20 @@ 
+#inndef __EC_H
+#define __EC_H
+
+#define EC_ACPI_SPACE_SIZE 0x80
+
+#define EC_ACPI_CMD_PORT 0x66
+#define EC_ACPI_DATA_PORT 0x62
+
+#define EC_ACPI_OBF 0x1
+#define EC_ACPI_IBF 0x2
+#define EC_ACPI_CMD 0x8
+#define EC_ACPI_BST 0x10
+
+#define EC_ACPI_CMD_READ 0x80
+#define EC_ACPI_CMD_WRITE 0x81
+#define EC_ACPI_BURST_EN 0x82
+#define EC_ACPI_BURST_DN 0x83
+#define EC_ACPI_CMD_QUERY 0x84
+
+#endif