Commit 0ff596d02fd9d876a31d038255a6d4f89da9dfed

Authored by pbrook
1 parent c6fdf5fc

I2C/SMBus framework.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2845 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
@@ -402,6 +402,8 @@ SOUND_HW += fmopl.o adlib.o @@ -402,6 +402,8 @@ SOUND_HW += fmopl.o adlib.o
402 endif 402 endif
403 AUDIODRV+= wavcapture.o 403 AUDIODRV+= wavcapture.o
404 404
  405 +VL_OBJS += i2c.o smbus.o
  406 +
405 # SCSI layer 407 # SCSI layer
406 VL_OBJS+= scsi-disk.o cdrom.o lsi53c895a.o 408 VL_OBJS+= scsi-disk.o cdrom.o lsi53c895a.o
407 409
hw/acpi.c
@@ -35,7 +35,7 @@ typedef struct PIIX4PMState { @@ -35,7 +35,7 @@ typedef struct PIIX4PMState {
35 uint8_t apms; 35 uint8_t apms;
36 QEMUTimer *tmr_timer; 36 QEMUTimer *tmr_timer;
37 int64_t tmr_overflow_time; 37 int64_t tmr_overflow_time;
38 - SMBusDevice *smb_dev[128]; 38 + i2c_bus *smbus;
39 uint8_t smb_stat; 39 uint8_t smb_stat;
40 uint8_t smb_ctl; 40 uint8_t smb_ctl;
41 uint8_t smb_cmd; 41 uint8_t smb_cmd;
@@ -63,9 +63,6 @@ typedef struct PIIX4PMState { @@ -63,9 +63,6 @@ typedef struct PIIX4PMState {
63 #define SMBHSTDAT1 0x06 63 #define SMBHSTDAT1 0x06
64 #define SMBBLKDAT 0x07 64 #define SMBBLKDAT 0x07
65 65
66 -/* Note: only used for piix4_smbus_register_device */  
67 -static PIIX4PMState *piix4_pm_state;  
68 -  
69 static uint32_t get_pmtmr(PIIX4PMState *s) 66 static uint32_t get_pmtmr(PIIX4PMState *s)
70 { 67 {
71 uint32_t d; 68 uint32_t d;
@@ -258,59 +255,44 @@ static void smb_transaction(PIIX4PMState *s) @@ -258,59 +255,44 @@ static void smb_transaction(PIIX4PMState *s)
258 uint8_t read = s->smb_addr & 0x01; 255 uint8_t read = s->smb_addr & 0x01;
259 uint8_t cmd = s->smb_cmd; 256 uint8_t cmd = s->smb_cmd;
260 uint8_t addr = s->smb_addr >> 1; 257 uint8_t addr = s->smb_addr >> 1;
261 - SMBusDevice *dev = s->smb_dev[addr]; 258 + i2c_bus *bus = s->smbus;
262 259
263 #ifdef DEBUG 260 #ifdef DEBUG
264 printf("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot); 261 printf("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
265 #endif 262 #endif
266 - if (!dev) goto error;  
267 -  
268 switch(prot) { 263 switch(prot) {
269 case 0x0: 264 case 0x0:
270 - if (!dev->quick_cmd) goto error;  
271 - (*dev->quick_cmd)(dev, read); 265 + smbus_quick_command(bus, addr, read);
272 break; 266 break;
273 case 0x1: 267 case 0x1:
274 if (read) { 268 if (read) {
275 - if (!dev->receive_byte) goto error;  
276 - s->smb_data0 = (*dev->receive_byte)(dev);  
277 - }  
278 - else {  
279 - if (!dev->send_byte) goto error;  
280 - (*dev->send_byte)(dev, cmd); 269 + s->smb_data0 = smbus_receive_byte(bus, addr);
  270 + } else {
  271 + smbus_send_byte(bus, addr, cmd);
281 } 272 }
282 break; 273 break;
283 case 0x2: 274 case 0x2:
284 if (read) { 275 if (read) {
285 - if (!dev->read_byte) goto error;  
286 - s->smb_data0 = (*dev->read_byte)(dev, cmd);  
287 - }  
288 - else {  
289 - if (!dev->write_byte) goto error;  
290 - (*dev->write_byte)(dev, cmd, s->smb_data0); 276 + s->smb_data0 = smbus_read_byte(bus, addr, cmd);
  277 + } else {
  278 + smbus_write_byte(bus, addr, cmd, s->smb_data0);
291 } 279 }
292 break; 280 break;
293 case 0x3: 281 case 0x3:
294 if (read) { 282 if (read) {
295 uint16_t val; 283 uint16_t val;
296 - if (!dev->read_word) goto error;  
297 - val = (*dev->read_word)(dev, cmd); 284 + val = smbus_read_word(bus, addr, cmd);
298 s->smb_data0 = val; 285 s->smb_data0 = val;
299 s->smb_data1 = val >> 8; 286 s->smb_data1 = val >> 8;
300 - }  
301 - else {  
302 - if (!dev->write_word) goto error;  
303 - (*dev->write_word)(dev, cmd, (s->smb_data1 << 8) | s->smb_data0); 287 + } else {
  288 + smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
304 } 289 }
305 break; 290 break;
306 case 0x5: 291 case 0x5:
307 if (read) { 292 if (read) {
308 - if (!dev->read_block) goto error;  
309 - s->smb_data0 = (*dev->read_block)(dev, cmd, s->smb_data);  
310 - }  
311 - else {  
312 - if (!dev->write_block) goto error;  
313 - (*dev->write_block)(dev, cmd, s->smb_data0, s->smb_data); 293 + s->smb_data0 = smbus_read_block(bus, addr, cmd, s->smb_data);
  294 + } else {
  295 + smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
314 } 296 }
315 break; 297 break;
316 default: 298 default:
@@ -469,7 +451,7 @@ static int pm_load(QEMUFile* f,void* opaque,int version_id) @@ -469,7 +451,7 @@ static int pm_load(QEMUFile* f,void* opaque,int version_id)
469 return 0; 451 return 0;
470 } 452 }
471 453
472 -void piix4_pm_init(PCIBus *bus, int devfn) 454 +i2c_bus *piix4_pm_init(PCIBus *bus, int devfn)
473 { 455 {
474 PIIX4PMState *s; 456 PIIX4PMState *s;
475 uint8_t *pci_conf; 457 uint8_t *pci_conf;
@@ -514,10 +496,7 @@ void piix4_pm_init(PCIBus *bus, int devfn) @@ -514,10 +496,7 @@ void piix4_pm_init(PCIBus *bus, int devfn)
514 s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s); 496 s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
515 497
516 register_savevm("piix4_pm", 0, 1, pm_save, pm_load, s); 498 register_savevm("piix4_pm", 0, 1, pm_save, pm_load, s);
517 - piix4_pm_state = s;  
518 -}  
519 499
520 -void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr)  
521 -{  
522 - piix4_pm_state->smb_dev[addr] = dev; 500 + s->smbus = i2c_init_bus();
  501 + return s->smbus;
523 } 502 }
hw/i2c.c 0 โ†’ 100644
  1 +/*
  2 + * QEMU I2C bus interface.
  3 + *
  4 + * Copyright (c) 2007 CodeSourcery.
  5 + * Written by Paul Brook
  6 + *
  7 + * This code is licenced under the LGPL.
  8 + */
  9 +
  10 +#include "vl.h"
  11 +
  12 +struct i2c_bus
  13 +{
  14 + i2c_slave *current_dev;
  15 + i2c_slave *dev;
  16 +};
  17 +
  18 +/* Create a new I2C bus. */
  19 +i2c_bus *i2c_init_bus(void)
  20 +{
  21 + i2c_bus *bus;
  22 +
  23 + bus = (i2c_bus *)qemu_mallocz(sizeof(i2c_bus));
  24 + return bus;
  25 +}
  26 +
  27 +/* Create a new slave device. */
  28 +i2c_slave *i2c_slave_init(i2c_bus *bus, int address, int size)
  29 +{
  30 + i2c_slave *dev;
  31 +
  32 + if (size < sizeof(i2c_slave))
  33 + cpu_abort(cpu_single_env, "I2C struct too small");
  34 +
  35 + dev = (i2c_slave *)qemu_mallocz(size);
  36 + dev->address = address;
  37 + dev->next = bus->dev;
  38 + bus->dev = dev;
  39 +
  40 + return dev;
  41 +}
  42 +
  43 +void i2c_set_slave_address(i2c_slave *dev, int address)
  44 +{
  45 + dev->address = address;
  46 +}
  47 +
  48 +/* Return nonzero if bus is busy. */
  49 +int i2c_bus_busy(i2c_bus *bus)
  50 +{
  51 + return bus->current_dev != NULL;
  52 +}
  53 +
  54 +/* Returns nonzero if the bus is already busy, or is the address is not
  55 + valid. */
  56 +/* TODO: Make this handle multiple masters. */
  57 +int i2c_start_transfer(i2c_bus *bus, int address, int recv)
  58 +{
  59 + i2c_slave *dev;
  60 +
  61 + for (dev = bus->dev; dev; dev = dev->next) {
  62 + if (dev->address == address)
  63 + break;
  64 + }
  65 +
  66 + if (!dev)
  67 + return 1;
  68 +
  69 + /* If the bus is already busy, assume this is a repeated
  70 + start condition. */
  71 + bus->current_dev = dev;
  72 + dev->event(dev, recv ? I2C_START_RECV : I2C_START_SEND);
  73 + return 0;
  74 +}
  75 +
  76 +void i2c_end_transfer(i2c_bus *bus)
  77 +{
  78 + i2c_slave *dev = bus->current_dev;
  79 +
  80 + if (!dev)
  81 + return;
  82 +
  83 + dev->event(dev, I2C_FINISH);
  84 +
  85 + bus->current_dev = NULL;
  86 +}
  87 +
  88 +int i2c_send(i2c_bus *bus, uint8_t data)
  89 +{
  90 + i2c_slave *dev = bus->current_dev;
  91 +
  92 + if (!dev)
  93 + return -1;
  94 +
  95 + return dev->send(dev, data);
  96 +}
  97 +
  98 +int i2c_recv(i2c_bus *bus)
  99 +{
  100 + i2c_slave *dev = bus->current_dev;
  101 +
  102 + if (!dev)
  103 + return -1;
  104 +
  105 + return dev->recv(dev);
  106 +}
  107 +
  108 +void i2c_nack(i2c_bus *bus)
  109 +{
  110 + i2c_slave *dev = bus->current_dev;
  111 +
  112 + if (!dev)
  113 + return;
  114 +
  115 + dev->event(dev, I2C_NACK);
  116 +}
  117 +
hw/i2c.h 0 โ†’ 100644
  1 +#ifndef QEMU_I2C_H
  2 +#define QEMU_I2C_H
  3 +
  4 +/* The QEMU I2C implementation only supports simple transfers that complete
  5 + immediately. It does not support slave devices that need to be able to
  6 + defer their response (eg. CPU slave interfaces where the data is supplied
  7 + by the device driver in response to an interrupt). */
  8 +
  9 +enum i2c_event {
  10 + I2C_START_RECV,
  11 + I2C_START_SEND,
  12 + I2C_FINISH,
  13 + I2C_NACK /* Masker NACKed a recieve byte. */
  14 +};
  15 +
  16 +typedef struct i2c_slave i2c_slave;
  17 +
  18 +/* Master to slave. */
  19 +typedef int (*i2c_send_cb)(i2c_slave *s, uint8_t data);
  20 +/* Slave to master. */
  21 +typedef int (*i2c_recv_cb)(i2c_slave *s);
  22 +/* Notify the slave of a bus state change. */
  23 +typedef void (*i2c_event_cb)(i2c_slave *s, enum i2c_event event);
  24 +
  25 +struct i2c_slave
  26 +{
  27 + /* Callbacks to be set by the device. */
  28 + i2c_event_cb event;
  29 + i2c_recv_cb recv;
  30 + i2c_send_cb send;
  31 +
  32 + /* Remaining fields for internal use by the I2C code. */
  33 + int address;
  34 + void *next;
  35 +};
  36 +
  37 +typedef struct i2c_bus i2c_bus;
  38 +
  39 +i2c_bus *i2c_init_bus(void);
  40 +i2c_slave *i2c_slave_init(i2c_bus *bus, int address, int size);
  41 +void i2c_set_slave_address(i2c_slave *dev, int address);
  42 +int i2c_bus_busy(i2c_bus *bus);
  43 +int i2c_start_transfer(i2c_bus *bus, int address, int recv);
  44 +void i2c_end_transfer(i2c_bus *bus);
  45 +void i2c_nack(i2c_bus *bus);
  46 +int i2c_send(i2c_bus *bus, uint8_t data);
  47 +int i2c_recv(i2c_bus *bus);
  48 +
  49 +#endif
@@ -897,11 +897,12 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device, @@ -897,11 +897,12 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
897 897
898 if (pci_enabled && acpi_enabled) { 898 if (pci_enabled && acpi_enabled) {
899 uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */ 899 uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
900 - piix4_pm_init(pci_bus, piix3_devfn + 3); 900 + i2c_bus *smbus;
  901 +
  902 + /* TODO: Populate SPD eeprom data. */
  903 + smbus = piix4_pm_init(pci_bus, piix3_devfn + 3);
901 for (i = 0; i < 8; i++) { 904 for (i = 0; i < 8; i++) {
902 - SMBusDevice *eeprom = smbus_eeprom_device_init(0x50 + i,  
903 - eeprom_buf + (i * 256));  
904 - piix4_smbus_register_device(eeprom, 0x50 + i); 905 + smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));
905 } 906 }
906 } 907 }
907 908
hw/smbus.c 0 โ†’ 100644
  1 +/*
  2 + * QEMU SMBus device emulation.
  3 + *
  4 + * Copyright (c) 2007 CodeSourcery.
  5 + * Written by Paul Brook
  6 + *
  7 + * This code is licenced under the LGPL.
  8 + */
  9 +
  10 +/* TODO: Implement PEC. */
  11 +
  12 +#include "vl.h"
  13 +
  14 +//#define DEBUG_SMBUS 1
  15 +
  16 +#ifdef DEBUG_SMBUS
  17 +#define DPRINTF(fmt, args...) \
  18 +do { printf("smbus(%02x): " fmt , dev->i2c.address, ##args); } while (0)
  19 +#define BADF(fmt, args...) \
  20 +do { fprintf(stderr, "smbus: error: " fmt , ##args); exit(1);} while (0)
  21 +#else
  22 +#define DPRINTF(fmt, args...) do {} while(0)
  23 +#define BADF(fmt, args...) \
  24 +do { fprintf(stderr, "smbus: error: " fmt , ##args);} while (0)
  25 +#endif
  26 +
  27 +enum {
  28 + SMBUS_IDLE,
  29 + SMBUS_WRITE_DATA,
  30 + SMBUS_RECV_BYTE,
  31 + SMBUS_READ_DATA,
  32 + SMBUS_DONE,
  33 + SMBUS_CONFUSED = -1
  34 +};
  35 +
  36 +static void smbus_do_quick_cmd(SMBusDevice *dev, int recv)
  37 +{
  38 + DPRINTF("Quick Command %d\n", recv);
  39 + if (dev->quick_cmd)
  40 + dev->quick_cmd(dev, recv);
  41 +}
  42 +
  43 +static void smbus_do_write(SMBusDevice *dev)
  44 +{
  45 + if (dev->data_len == 0) {
  46 + smbus_do_quick_cmd(dev, 0);
  47 + } else if (dev->data_len == 1) {
  48 + DPRINTF("Send Byte\n");
  49 + if (dev->send_byte) {
  50 + dev->send_byte(dev, dev->data_buf[0]);
  51 + }
  52 + } else {
  53 + dev->command = dev->data_buf[0];
  54 + DPRINTF("Command %d len %d\n", dev->command, dev->data_len - 1);
  55 + if (dev->write_data) {
  56 + dev->write_data(dev, dev->command, dev->data_buf + 1,
  57 + dev->data_len - 1);
  58 + }
  59 + }
  60 +}
  61 +
  62 +void smbus_i2c_event(i2c_slave *s, enum i2c_event event)
  63 +{
  64 + SMBusDevice *dev = (SMBusDevice *)s;
  65 + switch (event) {
  66 + case I2C_START_SEND:
  67 + switch (dev->mode) {
  68 + case SMBUS_IDLE:
  69 + DPRINTF("Incoming data\n");
  70 + dev->mode = SMBUS_WRITE_DATA;
  71 + break;
  72 + default:
  73 + BADF("Unexpected send start condition in state %d\n", dev->mode);
  74 + dev->mode = SMBUS_CONFUSED;
  75 + break;
  76 + }
  77 + break;
  78 +
  79 + case I2C_START_RECV:
  80 + switch (dev->mode) {
  81 + case SMBUS_IDLE:
  82 + DPRINTF("Read mode\n");
  83 + dev->mode = SMBUS_RECV_BYTE;
  84 + break;
  85 + case SMBUS_WRITE_DATA:
  86 + if (dev->data_len == 0) {
  87 + BADF("Read after write with no data\n");
  88 + dev->mode = SMBUS_CONFUSED;
  89 + } else {
  90 + if (dev->data_len > 1) {
  91 + smbus_do_write(dev);
  92 + } else {
  93 + dev->command = dev->data_buf[0];
  94 + DPRINTF("%02x: Command %d\n", dev->i2c.address,
  95 + dev->command);
  96 + }
  97 + DPRINTF("Read mode\n");
  98 + dev->data_len = 0;
  99 + dev->mode = SMBUS_READ_DATA;
  100 + }
  101 + break;
  102 + default:
  103 + BADF("Unexpected recv start condition in state %d\n", dev->mode);
  104 + dev->mode = SMBUS_CONFUSED;
  105 + break;
  106 + }
  107 + break;
  108 +
  109 + case I2C_FINISH:
  110 + switch (dev->mode) {
  111 + case SMBUS_WRITE_DATA:
  112 + smbus_do_write(dev);
  113 + break;
  114 + case SMBUS_RECV_BYTE:
  115 + smbus_do_quick_cmd(dev, 1);
  116 + break;
  117 + case SMBUS_READ_DATA:
  118 + BADF("Unexpected stop during receive\n");
  119 + break;
  120 + default:
  121 + /* Nothing to do. */
  122 + break;
  123 + }
  124 + dev->mode = SMBUS_IDLE;
  125 + dev->data_len = 0;
  126 + break;
  127 +
  128 + case I2C_NACK:
  129 + switch (dev->mode) {
  130 + case SMBUS_DONE:
  131 + /* Nothing to do. */
  132 + break;
  133 + case SMBUS_READ_DATA:
  134 + dev->mode = SMBUS_DONE;
  135 + break;
  136 + default:
  137 + BADF("Unexpected NACK in state %d\n", dev->mode);
  138 + dev->mode = SMBUS_CONFUSED;
  139 + break;
  140 + }
  141 + }
  142 +}
  143 +
  144 +static int smbus_i2c_recv(i2c_slave *s)
  145 +{
  146 + SMBusDevice *dev = (SMBusDevice *)s;
  147 + int ret;
  148 +
  149 + switch (dev->mode) {
  150 + case SMBUS_RECV_BYTE:
  151 + if (dev->receive_byte) {
  152 + ret = dev->receive_byte(dev);
  153 + } else {
  154 + ret = 0;
  155 + }
  156 + DPRINTF("Receive Byte %02x\n", ret);
  157 + dev->mode = SMBUS_DONE;
  158 + break;
  159 + case SMBUS_READ_DATA:
  160 + if (dev->read_data) {
  161 + ret = dev->read_data(dev, dev->command, dev->data_len);
  162 + dev->data_len++;
  163 + } else {
  164 + ret = 0;
  165 + }
  166 + DPRINTF("Read data %02x\n", ret);
  167 + break;
  168 + default:
  169 + BADF("Unexpected read in state %d\n", dev->mode);
  170 + dev->mode = SMBUS_CONFUSED;
  171 + ret = 0;
  172 + break;
  173 + }
  174 + return ret;
  175 +}
  176 +
  177 +static int smbus_i2c_send(i2c_slave *s, uint8_t data)
  178 +{
  179 + SMBusDevice *dev = (SMBusDevice *)s;
  180 + switch (dev->mode) {
  181 + case SMBUS_WRITE_DATA:
  182 + DPRINTF("Write data %02x\n", data);
  183 + dev->data_buf[dev->data_len++] = data;
  184 + break;
  185 + default:
  186 + BADF("Unexpected write in state %d\n", dev->mode);
  187 + break;
  188 + }
  189 + return 0;
  190 +}
  191 +
  192 +SMBusDevice *smbus_device_init(i2c_bus *bus, int address, int size)
  193 +{
  194 + SMBusDevice *dev;
  195 +
  196 + dev = (SMBusDevice *)i2c_slave_init(bus, address, size);
  197 + dev->i2c.event = smbus_i2c_event;
  198 + dev->i2c.recv = smbus_i2c_recv;
  199 + dev->i2c.send = smbus_i2c_send;
  200 +
  201 + return dev;
  202 +}
  203 +
  204 +/* Master device commands. */
  205 +void smbus_quick_command(i2c_bus *bus, int addr, int read)
  206 +{
  207 + i2c_start_transfer(bus, addr, read);
  208 + i2c_end_transfer(bus);
  209 +}
  210 +
  211 +uint8_t smbus_receive_byte(i2c_bus *bus, int addr)
  212 +{
  213 + uint8_t data;
  214 +
  215 + i2c_start_transfer(bus, addr, 1);
  216 + data = i2c_recv(bus);
  217 + i2c_nack(bus);
  218 + i2c_end_transfer(bus);
  219 + return data;
  220 +}
  221 +
  222 +void smbus_send_byte(i2c_bus *bus, int addr, uint8_t data)
  223 +{
  224 + i2c_start_transfer(bus, addr, 0);
  225 + i2c_send(bus, data);
  226 + i2c_end_transfer(bus);
  227 +}
  228 +
  229 +uint8_t smbus_read_byte(i2c_bus *bus, int addr, uint8_t command)
  230 +{
  231 + uint8_t data;
  232 + i2c_start_transfer(bus, addr, 0);
  233 + i2c_send(bus, command);
  234 + i2c_start_transfer(bus, addr, 1);
  235 + data = i2c_recv(bus);
  236 + i2c_nack(bus);
  237 + i2c_end_transfer(bus);
  238 + return data;
  239 +}
  240 +
  241 +void smbus_write_byte(i2c_bus *bus, int addr, uint8_t command, uint8_t data)
  242 +{
  243 + i2c_start_transfer(bus, addr, 0);
  244 + i2c_send(bus, command);
  245 + i2c_send(bus, data);
  246 + i2c_end_transfer(bus);
  247 +}
  248 +
  249 +uint16_t smbus_read_word(i2c_bus *bus, int addr, uint8_t command)
  250 +{
  251 + uint16_t data;
  252 + i2c_start_transfer(bus, addr, 0);
  253 + i2c_send(bus, command);
  254 + i2c_start_transfer(bus, addr, 1);
  255 + data = i2c_recv(bus);
  256 + data |= i2c_recv(bus) << 8;
  257 + i2c_nack(bus);
  258 + i2c_end_transfer(bus);
  259 + return data;
  260 +}
  261 +
  262 +void smbus_write_word(i2c_bus *bus, int addr, uint8_t command, uint16_t data)
  263 +{
  264 + i2c_start_transfer(bus, addr, 0);
  265 + i2c_send(bus, command);
  266 + i2c_send(bus, data & 0xff);
  267 + i2c_send(bus, data >> 8);
  268 + i2c_end_transfer(bus);
  269 +}
  270 +
  271 +int smbus_read_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data)
  272 +{
  273 + int len;
  274 + int i;
  275 +
  276 + i2c_start_transfer(bus, addr, 0);
  277 + i2c_send(bus, command);
  278 + i2c_start_transfer(bus, addr, 1);
  279 + len = i2c_recv(bus);
  280 + if (len > 32)
  281 + len = 0;
  282 + for (i = 0; i < len; i++)
  283 + data[i] = i2c_recv(bus);
  284 + i2c_nack(bus);
  285 + i2c_end_transfer(bus);
  286 + return len;
  287 +}
  288 +
  289 +void smbus_write_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data,
  290 + int len)
  291 +{
  292 + int i;
  293 +
  294 + if (len > 32)
  295 + len = 32;
  296 +
  297 + i2c_start_transfer(bus, addr, 0);
  298 + i2c_send(bus, command);
  299 + i2c_send(bus, len);
  300 + for (i = 0; i < len; i++)
  301 + i2c_send(bus, data[i]);
  302 + i2c_end_transfer(bus);
  303 +}
hw/smbus.h
@@ -25,14 +25,46 @@ @@ -25,14 +25,46 @@
25 typedef struct SMBusDevice SMBusDevice; 25 typedef struct SMBusDevice SMBusDevice;
26 26
27 struct SMBusDevice { 27 struct SMBusDevice {
28 - uint8_t addr; 28 + /* The SMBus protocol is implemented on top of I2C. */
  29 + i2c_slave i2c;
  30 +
  31 + /* Callbacks set by the device. */
29 void (*quick_cmd)(SMBusDevice *dev, uint8_t read); 32 void (*quick_cmd)(SMBusDevice *dev, uint8_t read);
30 void (*send_byte)(SMBusDevice *dev, uint8_t val); 33 void (*send_byte)(SMBusDevice *dev, uint8_t val);
31 uint8_t (*receive_byte)(SMBusDevice *dev); 34 uint8_t (*receive_byte)(SMBusDevice *dev);
32 - void (*write_byte)(SMBusDevice *dev, uint8_t cmd, uint8_t val);  
33 - uint8_t (*read_byte)(SMBusDevice *dev, uint8_t cmd);  
34 - void (*write_word)(SMBusDevice *dev, uint8_t cmd, uint16_t val);  
35 - uint16_t (*read_word)(SMBusDevice *dev, uint8_t cmd);  
36 - void (*write_block)(SMBusDevice *dev, uint8_t cmd, uint8_t len, uint8_t *buf);  
37 - uint8_t (*read_block)(SMBusDevice *dev, uint8_t cmd, uint8_t *buf); 35 + /* We can't distinguish between a word write and a block write with
  36 + length 1, so pass the whole data block including the length byte
  37 + (if present). The device is responsible figuring out what type of
  38 + command this is. */
  39 + void (*write_data)(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int len);
  40 + /* Likewise we can't distinguish between defferent reads, or even know
  41 + the length of the read until the read is complete, so read data a
  42 + byte at a time. The device is responsible for adding the length
  43 + byte on block reads. */
  44 + uint8_t (*read_data)(SMBusDevice *dev, uint8_t cmd, int n);
  45 +
  46 + /* Remaining fields for internal use only. */
  47 + int mode;
  48 + int data_len;
  49 + uint8_t data_buf[34]; /* command + len + 32 bytes of data. */
  50 + uint8_t command;
38 }; 51 };
  52 +
  53 +/* Create a slave device. */
  54 +SMBusDevice *smbus_device_init(i2c_bus *bus, int address, int size);
  55 +
  56 +/* Master device commands. */
  57 +void smbus_quick_command(i2c_bus *bus, int addr, int read);
  58 +uint8_t smbus_receive_byte(i2c_bus *bus, int addr);
  59 +void smbus_send_byte(i2c_bus *bus, int addr, uint8_t data);
  60 +uint8_t smbus_read_byte(i2c_bus *bus, int addr, uint8_t command);
  61 +void smbus_write_byte(i2c_bus *bus, int addr, uint8_t command, uint8_t data);
  62 +uint16_t smbus_read_word(i2c_bus *bus, int addr, uint8_t command);
  63 +void smbus_write_word(i2c_bus *bus, int addr, uint8_t command, uint16_t data);
  64 +int smbus_read_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data);
  65 +void smbus_write_block(i2c_bus *bus, int addr, uint8_t command, uint8_t *data,
  66 + int len);
  67 +
  68 +/* smbus_eeprom.c */
  69 +void smbus_eeprom_device_init(i2c_bus *bus, uint8_t addr, uint8_t *buf);
  70 +
hw/smbus_eeprom.c
@@ -58,37 +58,51 @@ static uint8_t eeprom_receive_byte(SMBusDevice *dev) @@ -58,37 +58,51 @@ static uint8_t eeprom_receive_byte(SMBusDevice *dev)
58 return val; 58 return val;
59 } 59 }
60 60
61 -static void eeprom_write_byte(SMBusDevice *dev, uint8_t cmd, uint8_t val) 61 +static void eeprom_write_data(SMBusDevice *dev, uint8_t cmd, uint8_t *buf, int len)
62 { 62 {
63 SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev; 63 SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
  64 + int n;
64 #ifdef DEBUG 65 #ifdef DEBUG
65 printf("eeprom_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n", dev->addr, 66 printf("eeprom_write_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n", dev->addr,
66 - cmd, val); 67 + cmd, buf[0]);
67 #endif 68 #endif
68 - eeprom->data[cmd] = val; 69 + /* An page write operation is not a valid SMBus command.
  70 + It is a block write without a length byte. Fortunately we
  71 + get the full block anyway. */
  72 + /* TODO: Should this set the current location? */
  73 + if (cmd + len > 256)
  74 + n = 256 - cmd;
  75 + else
  76 + n = len;
  77 + memcpy(eeprom->data + cmd, buf, n);
  78 + len -= n;
  79 + if (len)
  80 + memcpy(eeprom->data, buf + n, len);
69 } 81 }
70 82
71 -static uint8_t eeprom_read_byte(SMBusDevice *dev, uint8_t cmd) 83 +static uint8_t eeprom_read_data(SMBusDevice *dev, uint8_t cmd, int n)
72 { 84 {
73 SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev; 85 SMBusEEPROMDevice *eeprom = (SMBusEEPROMDevice *) dev;
74 - uint8_t val = eeprom->data[cmd];  
75 -#ifdef DEBUG  
76 - printf("eeprom_read_byte: addr=0x%02x cmd=0x%02x val=0x%02x\n", dev->addr,  
77 - cmd, val);  
78 -#endif  
79 - return val; 86 + /* If this is the first byte then set the current position. */
  87 + if (n == 0)
  88 + eeprom->offset = cmd;
  89 + /* As with writes, we implement block reads without the
  90 + SMBus length byte. */
  91 + return eeprom_receive_byte(dev);
80 } 92 }
81 93
82 -SMBusDevice *smbus_eeprom_device_init(uint8_t addr, uint8_t *buf) 94 +void smbus_eeprom_device_init(i2c_bus *bus, uint8_t addr, uint8_t *buf)
83 { 95 {
84 - SMBusEEPROMDevice *eeprom = qemu_mallocz(sizeof(SMBusEEPROMDevice));  
85 - eeprom->dev.addr = addr; 96 + SMBusEEPROMDevice *eeprom;
  97 +
  98 + eeprom = (SMBusEEPROMDevice *)smbus_device_init(bus, addr,
  99 + sizeof(SMBusEEPROMDevice));
  100 +
86 eeprom->dev.quick_cmd = eeprom_quick_cmd; 101 eeprom->dev.quick_cmd = eeprom_quick_cmd;
87 eeprom->dev.send_byte = eeprom_send_byte; 102 eeprom->dev.send_byte = eeprom_send_byte;
88 eeprom->dev.receive_byte = eeprom_receive_byte; 103 eeprom->dev.receive_byte = eeprom_receive_byte;
89 - eeprom->dev.write_byte = eeprom_write_byte;  
90 - eeprom->dev.read_byte = eeprom_read_byte; 104 + eeprom->dev.write_data = eeprom_write_data;
  105 + eeprom->dev.read_data = eeprom_read_data;
91 eeprom->data = buf; 106 eeprom->data = buf;
92 eeprom->offset = 0; 107 eeprom->offset = 0;
93 - return (SMBusDevice *) eeprom;  
94 } 108 }
@@ -1126,17 +1126,16 @@ int pit_get_out(PITState *pit, int channel, int64_t current_time); @@ -1126,17 +1126,16 @@ int pit_get_out(PITState *pit, int channel, int64_t current_time);
1126 void pcspk_init(PITState *); 1126 void pcspk_init(PITState *);
1127 int pcspk_audio_init(AudioState *, qemu_irq *pic); 1127 int pcspk_audio_init(AudioState *, qemu_irq *pic);
1128 1128
  1129 +#include "hw/i2c.h"
  1130 +
1129 #include "hw/smbus.h" 1131 #include "hw/smbus.h"
1130 1132
1131 /* acpi.c */ 1133 /* acpi.c */
1132 extern int acpi_enabled; 1134 extern int acpi_enabled;
1133 -void piix4_pm_init(PCIBus *bus, int devfn); 1135 +i2c_bus *piix4_pm_init(PCIBus *bus, int devfn);
1134 void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr); 1136 void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr);
1135 void acpi_bios_init(void); 1137 void acpi_bios_init(void);
1136 1138
1137 -/* smbus_eeprom.c */  
1138 -SMBusDevice *smbus_eeprom_device_init(uint8_t addr, uint8_t *buf);  
1139 -  
1140 /* pc.c */ 1139 /* pc.c */
1141 extern QEMUMachine pc_machine; 1140 extern QEMUMachine pc_machine;
1142 extern QEMUMachine isapc_machine; 1141 extern QEMUMachine isapc_machine;