Here's a revised patch with the mmap stuff removed. I'll refine the
persistence support, but in the meantime the EEPROM device is usable
even if it forgets its contents when qemu exits.
--Ed
Index: qemu-0.8.2/hw/acpi.c
===
--- qemu-0.8.2.orig/hw/acpi.c
+++ qemu-0.8.2/hw/acpi.c
@@ -27,6 +27,7 @@
#define PM_IO_BASE0xb000
#define SMI_CMD_IO_ADDR 0xb040
#define ACPI_DBG_IO_ADDR 0xb044
+#define SMB_IO_BASE 0xb100
typedef struct PIIX4PMState {
PCIDevice dev;
@@ -35,6 +36,15 @@ typedef struct PIIX4PMState {
uint16_t pmcntrl;
QEMUTimer *tmr_timer;
int64_t tmr_overflow_time;
+SMBusDevice *smb_dev[128];
+uint8_t smb_stat;
+uint8_t smb_ctl;
+uint8_t smb_cmd;
+uint8_t smb_addr;
+uint8_t smb_data0;
+uint8_t smb_data1;
+uint8_t smb_data[32];
+uint8_t smb_index;
} PIIX4PMState;
#define RTC_EN (1 10)
@@ -46,8 +56,6 @@ typedef struct PIIX4PMState {
#define SUS_EN (1 13)
-/* Note: only used for ACPI bios init. Could be deleted when ACPI init
- is integrated in Bochs BIOS */
static PIIX4PMState *piix4_pm_state;
static uint32_t get_pmtmr(PIIX4PMState *s)
@@ -218,13 +226,163 @@ static void acpi_dbg_writel(void *opaque
#endif
}
+static void smb_transaction(PIIX4PMState *s)
+{
+uint8_t prot = (s-smb_ctl 2) 0x07;
+uint8_t read = s-smb_addr 0x01;
+uint8_t cmd = s-smb_cmd;
+uint8_t addr = s-smb_addr 1;
+SMBusDevice *dev = s-smb_dev[addr];
+
+#ifdef DEBUG
+printf(SMBus trans addr=0x%02x prot=0x%02x\n, addr, prot);
+#endif
+if (!dev) goto error;
+
+switch(prot) {
+case 0x0:
+if (!dev-quick_cmd) goto error;
+(*dev-quick_cmd)(dev, read);
+break;
+case 0x1:
+if (read) {
+if (!dev-receive_byte) goto error;
+s-smb_data0 = (*dev-receive_byte)(dev);
+}
+else {
+if (!dev-send_byte) goto error;
+(*dev-send_byte)(dev, cmd);
+}
+break;
+case 0x2:
+if (read) {
+if (!dev-read_byte) goto error;
+s-smb_data0 = (*dev-read_byte)(dev, cmd);
+}
+else {
+if (!dev-write_byte) goto error;
+(*dev-write_byte)(dev, cmd, s-smb_data0);
+}
+break;
+case 0x3:
+if (read) {
+uint16_t val;
+if (!dev-read_word) goto error;
+val = (*dev-read_word)(dev, cmd);
+s-smb_data0 = val;
+s-smb_data1 = val 8;
+}
+else {
+if (!dev-write_word) goto error;
+(*dev-write_word)(dev, cmd, (s-smb_data1 8) | s-smb_data0);
+}
+break;
+case 0x5:
+if (read) {
+if (!dev-read_block) goto error;
+s-smb_data0 = (*dev-read_block)(dev, cmd, s-smb_data);
+}
+else {
+if (!dev-write_block) goto error;
+(*dev-write_block)(dev, cmd, s-smb_data0, s-smb_data);
+}
+break;
+default:
+goto error;
+}
+return;
+
+ error:
+s-smb_stat |= 0x04;
+}
+
+static void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+PIIX4PMState *s = opaque;
+addr = 0x3f;
+#ifdef DEBUG
+printf(SMB writeb port=0x%04x val=0x%02x\n, addr, val);
+#endif
+switch(addr) {
+case 0x00: /* SMBHSTSTS */
+s-smb_stat = 0;
+s-smb_index = 0;
+break;
+case 0x02: /* SMBHSTCNT */
+s-smb_ctl = val;
+if (val 0x40)
+smb_transaction(s);
+break;
+case 0x03: /* SMBHSTCMD */
+s-smb_cmd = val;
+break;
+case 0x04: /* SMBHSTADD */
+s-smb_addr = val;
+break;
+case 0x05: /* SMBHSTDAT0 */
+s-smb_data0 = val;
+break;
+case 0x06: /* SMBHSTDAT1 */
+s-smb_data1 = val;
+break;
+case 0x07: /* SMBBLKDAT */
+s-smb_data[s-smb_index++] = val;
+if (s-smb_index 31)
+s-smb_index = 0;
+break;
+default:
+break;
+}
+}
+
+static uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
+{
+PIIX4PMState *s = opaque;
+uint32_t val;
+
+addr = 0x3f;
+switch(addr) {
+case 0x00: /* SMBHSTSTS */
+val = s-smb_stat;
+break;
+case 0x02: /* SMBHSTCNT */
+s-smb_index = 0;
+val = s-smb_ctl 0x1f;
+break;
+case 0x03: /* SMBHSTCMD */
+val = s-smb_cmd;
+break;
+case 0x04: /* SMBHSTADD */
+val = s-smb_addr;
+break;
+case 0x05: /* SMBHSTDAT0 */
+val = s-smb_data0;
+break;
+case 0x06: /* SMBHSTDAT1 */
+val = s-smb_data1;
+break;
+case 0x07: /* SMBBLKDAT */
+val = s-smb_data[s-smb_index++];
+if (s-smb_index 31)
+s-smb_index = 0;
+break;
+default:
+val = 0;
+break;
+}
+#ifdef DEBUG
+printf(SMB readb port=0x%04x