diff --git a/src/device/hwm_gl518sm.c b/src/device/hwm_gl518sm.c index d0aeee193..33c9e6be3 100644 --- a/src/device/hwm_gl518sm.c +++ b/src/device/hwm_gl518sm.c @@ -103,13 +103,16 @@ gl518sm_i2c_read(void *bus, uint8_t addr, void *priv) uint16_t read = gl518sm_read(dev, dev->addr_register); uint8_t ret = 0; + if (dev->i2c_state == 0) + dev->i2c_state = 1; + if ((dev->i2c_state == 1) && (dev->addr_register >= 0x07) && (dev->addr_register <= 0x0c)) { /* two-byte registers: read MSB first */ dev->i2c_state = 2; ret = read >> 8; - } else + } else { ret = read; - - dev->addr_register++; + dev->addr_register++; + } return ret; } @@ -178,6 +181,7 @@ gl518sm_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv) break; default: + dev->i2c_state = 3; return 0; } diff --git a/src/device/hwm_lm75.c b/src/device/hwm_lm75.c index 8ee1aa06f..21d2b9b5c 100644 --- a/src/device/hwm_lm75.c +++ b/src/device/hwm_lm75.c @@ -35,7 +35,7 @@ static uint8_t lm75_i2c_read(void *bus, uint8_t addr, void *priv); static uint8_t lm75_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv); static void lm75_reset(lm75_t *dev); - +#define ENABLE_LM75_LOG 1 #ifdef ENABLE_LM75_LOG int lm75_do_log = ENABLE_LM75_LOG; @@ -86,23 +86,39 @@ lm75_i2c_read(void *bus, uint8_t addr, void *priv) lm75_t *dev = (lm75_t *) priv; uint8_t ret = 0; - switch (dev->addr_register & 0x3) { - case 0x0: /* temperature */ - ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x1 : 0x0); - break; + if (dev->i2c_state == 0) + dev->i2c_state = 1; - case 0x1: /* configuration */ - ret = lm75_read(dev, 0x2); - break; + /* The AS99127F hardware monitor uses the addresses of its LM75 devices + to access some of its proprietary registers. Pass this operation on to + the main monitor address through an internal I2C call, if necessary. */ + if ((dev->addr_register > 0x7) && ((dev->addr_register & 0xf8) != 0x50) && (dev->as99127f_i2c_addr < 0x80)) { + i2c_start(i2c_smbus, dev->as99127f_i2c_addr); + i2c_write(i2c_smbus, dev->as99127f_i2c_addr, dev->addr_register); + ret = i2c_read(i2c_smbus, dev->as99127f_i2c_addr); + i2c_stop(i2c_smbus, dev->as99127f_i2c_addr); + } else { + switch (dev->addr_register & 0x3) { + case 0x0: /* temperature */ + ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x0 : 0x1); + break; - case 0x2: /* Thyst */ - ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x4 : 0x3); - break; - case 0x3: /* Tos */ - ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x6 : 0x5); - break; + case 0x1: /* configuration */ + ret = lm75_read(dev, 0x2); + break; + + case 0x2: /* Thyst */ + ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x3 : 0x4); + break; + case 0x3: /* Tos */ + ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x5 : 0x6); + break; + } } + if (++dev->i2c_state > 2) + dev->i2c_state = 2; + return ret; } @@ -112,15 +128,7 @@ lm75_read(lm75_t *dev, uint8_t reg) { uint8_t ret; - /* The AS99127F hardware monitor uses the addresses of its LM75 devices - to access some of its proprietary registers. Pass this operation on to - the main monitor address through an internal I2C call, if necessary. */ - if ((reg > 0x7) && ((reg & 0xf8) != 0x50) && (dev->as99127f_i2c_addr < 0x80)) { - i2c_start(i2c_smbus, dev->as99127f_i2c_addr); - i2c_write(i2c_smbus, dev->as99127f_i2c_addr, reg); - ret = i2c_read(i2c_smbus, dev->as99127f_i2c_addr); - i2c_stop(i2c_smbus, dev->as99127f_i2c_addr); - } else if ((reg & 0x7) == 0x0) /* temperature high byte */ + if ((reg & 0x7) == 0x0) /* temperature high byte */ ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]) >> 8; else if ((reg & 0x7) == 0x1) /* temperature low byte */ ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]); @@ -145,23 +153,37 @@ lm75_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv) return 1; } - switch (dev->addr_register & 0x3) { - case 0x0: /* temperature */ - lm75_write(dev, (dev->i2c_state == 1) ? 0x1 : 0x0, data); - break; + /* The AS99127F hardware monitor uses the addresses of its LM75 devices + to access some of its proprietary registers. Pass this operation on to + the main monitor address through an internal I2C call, if necessary. */ + if ((dev->addr_register > 0x7) && ((dev->addr_register & 0xf8) != 0x50) && (dev->as99127f_i2c_addr < 0x80)) { + i2c_start(i2c_smbus, dev->as99127f_i2c_addr); + i2c_write(i2c_smbus, dev->as99127f_i2c_addr, dev->addr_register); + i2c_write(i2c_smbus, dev->as99127f_i2c_addr, data); + i2c_stop(i2c_smbus, dev->as99127f_i2c_addr); + return 1; + } else { + switch (dev->addr_register & 0x3) { + case 0x0: /* temperature */ + lm75_write(dev, (dev->i2c_state == 1) ? 0x0 : 0x1, data); + break; - case 0x1: /* configuration */ - lm75_write(dev, 0x2, data); - break; + case 0x1: /* configuration */ + lm75_write(dev, 0x2, data); + break; - case 0x2: /* Thyst */ - lm75_write(dev, (dev->i2c_state == 1) ? 0x4 : 0x3, data); - break; - case 0x3: /* Tos */ - lm75_write(dev, (dev->i2c_state == 1) ? 0x6 : 0x5, data); - break; + case 0x2: /* Thyst */ + lm75_write(dev, (dev->i2c_state == 1) ? 0x3 : 0x4, data); + break; + case 0x3: /* Tos */ + lm75_write(dev, (dev->i2c_state == 1) ? 0x5 : 0x6, data); + break; + } } + if (++dev->i2c_state > 2) + dev->i2c_state = 2; + return 1; } @@ -171,17 +193,6 @@ lm75_write(lm75_t *dev, uint8_t reg, uint8_t val) { lm75_log("LM75: write(%02X, %02X)\n", reg, val); - /* The AS99127F hardware monitor uses the addresses of its LM75 devices - to access some of its proprietary registers. Pass this operation on to - the main monitor address through an internal I2C call, if necessary. */ - if ((reg > 0x7) && ((reg & 0xf8) != 0x50) && (dev->as99127f_i2c_addr < 0x80)) { - i2c_start(i2c_smbus, dev->as99127f_i2c_addr); - i2c_write(i2c_smbus, dev->as99127f_i2c_addr, reg); - i2c_write(i2c_smbus, dev->as99127f_i2c_addr, val); - i2c_stop(i2c_smbus, dev->as99127f_i2c_addr); - return 1; - } - uint8_t reg_idx = (reg & 0x7); if ((reg_idx <= 0x1) || (reg_idx == 0x7)) diff --git a/src/device/hwm_lm78.c b/src/device/hwm_lm78.c index 486e622c8..351fe7165 100644 --- a/src/device/hwm_lm78.c +++ b/src/device/hwm_lm78.c @@ -69,7 +69,7 @@ static uint8_t lm78_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv) static uint8_t lm78_write(lm78_t *dev, uint8_t reg, uint8_t val, uint8_t bank); static void lm78_reset(lm78_t *dev, uint8_t initialization); - +#define ENABLE_LM78_LOG 1 #ifdef ENABLE_LM78_LOG int lm78_do_log = ENABLE_LM78_LOG; diff --git a/src/device/i2c.c b/src/device/i2c.c index 7dabc9908..a4562deaf 100644 --- a/src/device/i2c.c +++ b/src/device/i2c.c @@ -194,6 +194,8 @@ i2c_has_device(void *bus_handle, uint8_t addr) if (!bus) return 0; + i2c_log("I2C: has_device(%s, %02X) = %d\n", bus->name, addr, !!bus->devices[addr]); + return(!!bus->devices[addr]); } diff --git a/src/device/i2c_eeprom.c b/src/device/i2c_eeprom.c index 7696955e8..dac00aeb2 100644 --- a/src/device/i2c_eeprom.c +++ b/src/device/i2c_eeprom.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * Emulation of the AT24Cxx series of I2C EEPROMs. + * Emulation of the 24Cxx series of I2C EEPROMs. * * * @@ -27,22 +27,42 @@ typedef struct { void *i2c; - uint8_t addr; - uint8_t *data; - uint8_t writable; + uint8_t addr, *data, writable; - uint16_t addr_mask; - uint8_t addr_register; + uint16_t addr_mask, addr_register; uint8_t i2c_state; } i2c_eeprom_t; +#define ENABLE_I2C_EEPROM_LOG 1 +#ifdef ENABLE_I2C_EEPROM_LOG +int i2c_eeprom_do_log = ENABLE_I2C_EEPROM_LOG; + + +static void +i2c_eeprom_log(const char *fmt, ...) +{ + va_list ap; + + if (i2c_eeprom_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define i2c_eeprom_log(fmt, ...) +#endif + void i2c_eeprom_start(void *bus, uint8_t addr, void *priv) { i2c_eeprom_t *dev = (i2c_eeprom_t *) priv; + i2c_eeprom_log("I2C EEPROM: start()\n"); + dev->i2c_state = 0; + dev->addr_register = (addr << 8) & dev->addr_mask; } @@ -50,8 +70,13 @@ uint8_t i2c_eeprom_read(void *bus, uint8_t addr, void *priv) { i2c_eeprom_t *dev = (i2c_eeprom_t *) priv; + uint8_t ret = dev->data[dev->addr_register]; - return dev->data[((addr << 8) | dev->addr_register++) & dev->addr_mask]; + i2c_eeprom_log("I2C EEPROM: read(%04X) = %02X\n", dev->addr_register, ret); + if (++dev->addr_register > dev->addr_mask) /* roll-over */ + dev->addr_register = 0; + + return ret; } @@ -62,11 +87,16 @@ i2c_eeprom_write(void *bus, uint8_t addr, uint8_t data, void *priv) if (dev->i2c_state == 0) { dev->i2c_state = 1; - dev->addr_register = data; - } else if (dev->writable) - dev->data[((addr << 8) | dev->addr_register++) & dev->addr_mask] = data; - else - return 0; + dev->addr_register = ((addr << 8) | data) & dev->addr_mask; + i2c_eeprom_log("I2C EEPROM: write(address, %04X)\n", dev->addr_register); + } else { + i2c_eeprom_log("I2C EEPROM: write(%04X, %02X) = %s\n", dev->addr_register, data, dev->writable ? "accepted" : "blocked"); + if (dev->writable) + dev->data[dev->addr_register] = data; + if (++dev->addr_register > dev->addr_mask) /* roll-over */ + dev->addr_register = 0; + return dev->writable; + } return 1; } @@ -78,6 +108,8 @@ i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint16_t size, uint8_t w i2c_eeprom_t *dev = (i2c_eeprom_t *) malloc(sizeof(i2c_eeprom_t)); memset(dev, 0, sizeof(i2c_eeprom_t)); + i2c_eeprom_log("I2C EEPROM: init(%02X, %d, %d)\n", addr, size, writable); + dev->i2c = i2c; dev->addr = addr; dev->data = data; @@ -96,6 +128,8 @@ i2c_eeprom_close(void *dev_handle) { i2c_eeprom_t *dev = (i2c_eeprom_t *) dev_handle; + i2c_eeprom_log("I2C EEPROM: close()\n"); + i2c_removehandler(dev->i2c, dev->addr & ~(dev->addr_mask >> 8), (dev->addr_mask >> 8) + 1, i2c_eeprom_start, i2c_eeprom_read, i2c_eeprom_write, NULL, dev); free(dev); diff --git a/src/device/i2c_gpio.c b/src/device/i2c_gpio.c index e2b844200..aff3d1960 100644 --- a/src/device/i2c_gpio.c +++ b/src/device/i2c_gpio.c @@ -52,19 +52,43 @@ enum { }; typedef struct { + char *bus_name; void *i2c; uint8_t scl, sda, state, slave_state, slave_addr, slave_rw, last_sda, pos, transmit, byte; } i2c_gpio_t; +#ifdef ENABLE_I2C_GPIO_LOG +int i2c_gpio_do_log = ENABLE_I2C_GPIO_LOG; + + +static void +i2c_gpio_log(int level, const char *fmt, ...) +{ + va_list ap; + + if (i2c_gpio_do_log >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define i2c_gpio_log(fmt, ...) +#endif + + void * i2c_gpio_init(char *bus_name) { i2c_gpio_t *dev = (i2c_gpio_t *) malloc(sizeof(i2c_gpio_t)); memset(dev, 0, sizeof(i2c_gpio_t)); - dev->i2c = i2c_addbus(bus_name); + i2c_gpio_log(1, "I2C GPIO %s: init()\n", bus_name); + + dev->bus_name = bus_name; + dev->i2c = i2c_addbus(dev->bus_name); dev->scl = dev->sda = 1; dev->slave_addr = 0xff; @@ -77,6 +101,8 @@ i2c_gpio_close(void *dev_handle) { i2c_gpio_t *dev = (i2c_gpio_t *) dev_handle; + i2c_gpio_log(1, "I2C GPIO %s: close()\n", dev->bus_name); + i2c_removebus(dev->i2c); free(dev); @@ -87,6 +113,7 @@ void i2c_gpio_next_byte(i2c_gpio_t *dev) { dev->byte = i2c_read(dev->i2c, dev->slave_addr); + i2c_gpio_log(1, "I2C GPIO %s: next_byte() = %02X\n", dev->bus_name, dev->byte); } @@ -101,6 +128,8 @@ i2c_gpio_write(i2c_gpio_t *dev) dev->slave_addr = dev->byte >> 1; dev->slave_rw = dev->byte & 1; + i2c_gpio_log(1, "I2C GPIO %s: Initiating transfer to address %02X rw %d\n", dev->bus_name, dev->slave_addr, dev->slave_rw); + if (!i2c_has_device(dev->i2c, dev->slave_addr)) { dev->slave_state = SLAVE_INVALID; break; @@ -120,11 +149,13 @@ i2c_gpio_write(i2c_gpio_t *dev) break; case SLAVE_RECEIVEADDR: + i2c_gpio_log(1, "I2C GPIO %s: Receiving address %02X\n", dev->bus_name, dev->byte); i2c_write(dev->i2c, dev->slave_addr, dev->byte); dev->slave_state = dev->slave_rw ? SLAVE_SENDDATA : SLAVE_RECEIVEDATA; break; case SLAVE_RECEIVEDATA: + i2c_gpio_log(1, "I2C GPIO %s: Receiving data %02X\n", dev->bus_name, dev->byte); i2c_write(dev->i2c, dev->slave_addr, dev->byte); break; } @@ -134,7 +165,10 @@ i2c_gpio_write(i2c_gpio_t *dev) void i2c_gpio_stop(i2c_gpio_t *dev) { - i2c_stop(dev->i2c, dev->slave_addr); + i2c_gpio_log(1, "I2C GPIO %s: Stopping transfer\n", dev->bus_name); + + if (dev->slave_addr != 0xff) + i2c_stop(dev->i2c, dev->slave_addr); dev->slave_addr = 0xff; dev->slave_state = SLAVE_IDLE; @@ -149,7 +183,9 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda) switch (dev->state) { case I2C_IDLE: - if (dev->scl && scl && dev->last_sda && !sda) { /* start bit */ + /* !dev->scl check breaks NCR SDMS. */ + if (/*!dev->scl &&*/ scl && dev->last_sda && !sda) { /* start bit */ + i2c_gpio_log(2, "I2C GPIO %s: Start bit received (from IDLE)\n", dev->bus_name); dev->state = I2C_RECEIVE; dev->pos = 0; } @@ -173,9 +209,11 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda) } } else if (dev->scl && scl) { if (sda && !dev->last_sda) { /* stop bit */ + i2c_gpio_log(2, "I2C GPIO %s: Stop bit received (from RECEIVE)\n", dev->bus_name); dev->state = I2C_IDLE; i2c_gpio_stop(dev); } else if (!sda && dev->last_sda) { /* start bit */ + i2c_gpio_log(2, "I2C GPIO %s: Start bit received (from RECEIVE)\n", dev->bus_name); dev->pos = 0; dev->slave_state = SLAVE_IDLE; } @@ -184,6 +222,7 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda) case I2C_ACKNOWLEDGE: if (!dev->scl && scl) { + i2c_gpio_log(2, "I2C GPIO %s: Acknowledging transfer\n", dev->bus_name); sda = 0; dev->pos = 0; dev->state = (dev->transmit == TRANSMITTER_MASTER) ? I2C_RECEIVE_WAIT : I2C_TRANSMIT; @@ -193,12 +232,14 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda) case I2C_TRANSACKNOWLEDGE: if (!dev->scl && scl) { if (sda) { /* not acknowledged; must be end of transfer */ + i2c_gpio_log(2, "I2C GPIO %s: End of transfer\n", dev->bus_name); dev->state = I2C_IDLE; i2c_gpio_stop(dev); } else { /* next byte to transfer */ dev->state = I2C_TRANSMIT_START; i2c_gpio_next_byte(dev); dev->pos = 0; + i2c_gpio_log(2, "I2C GPIO %s: Next byte = %02X\n", dev->bus_name, dev->byte); } } break; @@ -208,8 +249,10 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda) if (dev->last_sda && !sda) { /* start bit */ i2c_gpio_next_byte(dev); dev->pos = 0; + i2c_gpio_log(2, "I2C GPIO %s: Next byte = %02X\n", dev->bus_name, dev->byte); } if (!dev->last_sda && sda) { /* stop bit */ + i2c_gpio_log(2, "I2C GPIO %s: Stop bit received (from TRANSMIT_WAIT)\n", dev->bus_name); dev->state = I2C_IDLE; i2c_gpio_stop(dev); } @@ -220,6 +263,7 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda) if (!dev->scl && scl) dev->state = I2C_TRANSMIT; if (dev->scl && scl && !dev->last_sda && sda) { /* stop bit */ + i2c_gpio_log(2, "I2C GPIO %s: Stop bit received (from TRANSMIT_START)\n", dev->bus_name); dev->state = I2C_IDLE; i2c_gpio_stop(dev); } @@ -228,13 +272,18 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda) case I2C_TRANSMIT: if (!dev->scl && scl) { dev->scl = scl; + if (!dev->pos) + i2c_gpio_log(2, "I2C GPIO %s: Transmit byte %02X\n", dev->bus_name, dev->byte); dev->sda = sda = dev->byte & 0x80; + i2c_gpio_log(2, "I2C GPIO %s: Transmit bit %02X %d\n", dev->bus_name, dev->byte, dev->pos); dev->byte <<= 1; dev->pos++; return; } - if (dev->scl && !scl && (dev->pos == 8)) + if (dev->scl && !scl && (dev->pos == 8)) { dev->state = I2C_TRANSACKNOWLEDGE; + i2c_gpio_log(2, "I2C GPIO %s: Acknowledge mode\n", dev->bus_name); + } break; } diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index bb467781f..507bf339b 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -43,6 +43,7 @@ #include <86box/device.h> #include <86box/nvr.h> #include <86box/plat.h> +#include <86box/i2c.h> #include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/scsi_ncr53c8xx.h> @@ -225,14 +226,8 @@ typedef struct { int msg_action; int msg_len; uint8_t msg[NCR_MAX_MSGIN_LEN]; -#ifdef USE_NVRAM - uint16_t nvram; - uint8_t nvram_t; - uint8_t nvram_op; - uint8_t nvram_param; - uint8_t nvram_start; - uint8_t nvram_index; -#endif + uint8_t nvram[2048]; /* 24C16 EEPROM (16 kbit) */ + void *i2c, *eeprom; uint8_t ram[NCR_BUF_SIZE]; /* NCR 53c875 RAM (4 kB). */ /* 0 if SCRIPTS are running or stopped. * 1 if a Wait Reselect instruction has been issued. @@ -434,10 +429,7 @@ ncr53c8xx_soft_reset(ncr53c8xx_t *dev) dev->gpreg = 0; dev->slpar = 0; dev->sstop = 1; - dev->gpcntl = 0x0f; -#ifdef USE_NVRAM - dev->nvram_t = dev->nvram_index = 0; -#endif + dev->gpcntl = 0x03; if (dev->chip >= CHIP_825) { /* This *IS* a wide SCSI controller, so reset all SCSI @@ -474,7 +466,7 @@ ncr53c8xx_read(ncr53c8xx_t *dev, uint32_t addr, uint8_t *buf, uint32_t len) buf[i] = inb((uint16_t) (addr + i)); } else { ncr53c8xx_log("NCR 810: Reading from memory address %08X\n", addr); - dma_bm_read(addr, buf, len, 4); + dma_bm_read(addr, buf, len, 4); } } @@ -492,7 +484,7 @@ ncr53c8xx_write(ncr53c8xx_t *dev, uint32_t addr, uint8_t *buf, uint32_t len) outb((uint16_t) (addr + i), buf[i]); } else { ncr53c8xx_log("NCR 810: Writing to memory address %08X\n", addr); - dma_bm_write(addr, buf, len, 4); + dma_bm_write(addr, buf, len, 4); } } @@ -511,10 +503,10 @@ static void do_irq(ncr53c8xx_t *dev, int level) { if (level) { - pci_set_irq(dev->pci_slot, PCI_INTA); + pci_set_irq(dev->pci_slot, PCI_INTA); ncr53c8xx_log("Raising IRQ...\n"); } else { - pci_clear_irq(dev->pci_slot, PCI_INTA); + pci_clear_irq(dev->pci_slot, PCI_INTA); ncr53c8xx_log("Lowering IRQ...\n"); } } @@ -852,8 +844,8 @@ ncr53c8xx_do_msgin(ncr53c8xx_t *dev) switch to PHASE_MO. */ switch (dev->msg_action) { case 0: - ncr53c8xx_set_phase(dev, PHASE_CMD); - break; + ncr53c8xx_set_phase(dev, PHASE_CMD); + break; case 1: ncr53c8xx_disconnect(dev); break; @@ -1444,7 +1436,7 @@ ncr53c8xx_callback(void *p) if (dev->waiting) timer_on_auto(&dev->timer, 40.0); else - ncr53c8xx_process_script(dev); + ncr53c8xx_process_script(dev); } if (dev->sstop) @@ -1452,146 +1444,22 @@ ncr53c8xx_callback(void *p) } -#ifdef USE_NVRAM static void -ncr53c8xx_eeprom(ncr53c8xx_t *dev, int save) +ncr53c8xx_eeprom(ncr53c8xx_t *dev, uint8_t save) { FILE *f; - if (save) - f = nvr_fopen(dev->nvr_path, L"wb"); - else - f = nvr_fopen(dev->nvr_path, L"rb"); - if (f) - { - if (save) { - fwrite((uint8_t *) &dev->nvram, 1, 1, f); - fwrite(((uint8_t *) &dev->nvram) + 1, 1, 1, f); - } else { - fread((uint8_t *) &dev->nvram, 1, 1, f); - fread(((uint8_t *) &dev->nvram) + 1, 1, 1, f); - } + f = nvr_fopen(dev->nvr_path, save ? L"wb": L"rb"); + if (f) { + if (save) + fwrite(&dev->nvram, sizeof(dev->nvram), 1, f); + else + fread(&dev->nvram, sizeof(dev->nvram), 1, f); fclose(f); - f = NULL; } } -#define ADDRESS_LENGTH 9 -#define ADDRESS_END (ADDRESS_LENGTH + 2) -#define ADDRESS_SHIFT (ADDRESS_LENGTH - 2) -#define ADDRESS_MASK 0x3f -#define DATA_LENGTH 8 -#define DATA_START (ADDRESS_END + 1) -#define DATA_END (ADDRESS_END + DATA_LENGTH) - - -static void -ncr53c8xx_serial_eeprom_write(ncr53c8xx_t *dev, uint8_t val) -{ - uint8_t temp, old = dev->nvram_t; - dev->nvram_t = val & 0x03; - - if (val & 0x02) { - if (!dev->nvram_index) { - /* First signal clocked in after clock is high, start bit. */ - dev->nvram_start = 1; - ncr53c8xx_log("[W] Serial EEPROM: Start bit\n"); - dev->nvram_op = 0; - } else if ((dev->nvram_index == 1) || (dev->nvram_index == 2)) { - if (!dev->nvram_start) - return; - - dev->nvram_op = (val & 0x01) << (dev->nvram_index - 1); - if (dev->nvram_index == 2) { - // ncr53c8xx_log("[W] Serial EEPROM: Opcode: %01X\n", dev->nvram_op); - dev->nvram_param = 0; - } - } else if ((dev->nvram_index >= 3) && (dev->nvram_index <= ADDRESS_END)) { - if (!dev->nvram_start) - return; - - dev->nvram_param = (val & 0x01) << (dev->nvram_index - 3); - if (dev->nvram_index < ADDRESS_END) { - dev->nvram_index++; - return; - } - - switch (dev->nvram_op) { - case 0x00: - temp = dev->nvram_param >> ADDRESS_SHIFT; - switch(temp) { - case 0x00: - ncr53c8xx_log("[W] Serial EEPROM: EWDS\n"); - break; - case 0x01: - ncr53c8xx_log("[W] Serial EEPROM: WRAL\n"); - break; - case 0x02: - ncr53c8xx_log("[W] Serial EEPROM: ERAL\n"); - break; - case 0x03: - ncr53c8xx_log("[W] Serial EEPROM: EWEN\n"); - break; - default: - ncr53c8xx_log("[W] Serial EEPROM: UNKNOWN 00\n"); - break; - } - dev->nvram_start = dev->nvram_index = dev->nvram_op = dev->nvram_param = 0; - return; - case 0x01: - ncr53c8xx_log("[W] Serial EEPROM: WRITE\n"); - break; - case 0x02: - ncr53c8xx_log("[W] Serial EEPROM: READ\n"); - break; - case 0x03: - ncr53c8xx_log("[W] Serial EEPROM: ERASE\n"); - break; - default: - ncr53c8xx_log("[W] Serial EEPROM: UNKNOWN\n"); - break; - } - } else if ((dev->nvram_index >= DATA_START) && (dev->nvram_index <= DATA_END)) { - if (!dev->nvram_start) - return; - - if (dev->nvram_index == DATA_END) { - ncr53c8xx_log("[W] Serial EEPROM: Data end\n"); - dev->nvram_start = dev->nvram_index = dev->nvram_op = dev->nvram_param = 0; - return; - } - } - dev->nvram_index++; - } -} - - -static uint8_t -ncr53c8xx_serial_eeprom_read(ncr53c8xx_t *dev) -{ - uint8_t temp = 0; - - if (dev->gpreg & 0x02) { - if ((dev->nvram_index >= DATA_START) && (dev->nvram_index <= DATA_END)) { - if (!dev->nvram_start) - return temp; - - dev->nvram_index++; - - if (dev->nvram_index == DATA_END) { - ncr53c8xx_log("[R] Serial EEPROM: Data end\n"); - dev->nvram_start = dev->nvram_index = dev->nvram_op = dev->nvram_param = 0; - return temp; - } - } - } - - return temp; -} -#endif - - static void ncr53c8xx_reg_writeb(ncr53c8xx_t *dev, uint32_t offset, uint8_t val) { @@ -1659,12 +1527,8 @@ ncr53c8xx_reg_writeb(ncr53c8xx_t *dev, uint32_t offset, uint8_t val) break; case 0x07: /* GPREG */ ncr53c8xx_log("NCR 810: GPREG write %02X\n", val); - tmp = dev->gpreg; - dev->gpreg = val & 0xfe; -#ifdef USE_NVRAM - if ((dev->gpcntl & 0xc3) == 0x00) - ncr53c8xx_serial_eeprom_write(dev, val & 0x03); -#endif + dev->gpreg = val; + i2c_gpio_set(dev->i2c, !!(dev->gpreg & 0x02), !!(dev->gpreg & 0x01)); break; case 0x08: /* SFBR */ /* The CPU is not allowed to write to this register. However the @@ -1893,13 +1757,18 @@ ncr53c8xx_reg_readb(ncr53c8xx_t *dev, uint32_t offset) ncr53c8xx_log("NCR 810: Read SDID %02X\n", dev->sdid); return dev->sdid; case 0x07: /* GPREG */ -#ifdef USE_NVRAM - tmp = (dev->gpreg & (dev->gpcntl ^ 0x1f)) & 0x1e; - if ((dev->gpcntl & 0xc3) == 0x01) - tmp |= ncr53c8xx_serial_eeprom_read(dev); -#else - tmp = ((dev->gpreg & (dev->gpcntl ^ 0x1f)) & 0x1e) | 0x01; -#endif + tmp = (dev->gpreg & (dev->gpcntl ^ 0x1f)) & 0x1f; + if ((dev->gpcntl & 0x41) == 0x01) { + tmp &= 0xfe; + if (i2c_gpio_get_sda(dev->i2c)) + tmp |= 0x01; + } + if ((dev->gpcntl & 0x82) == 0x02) { + tmp &= 0xfd; + if (i2c_gpio_get_scl(dev->i2c)) + tmp |= 0x02; + } + ncr53c8xx_log("NCR 810: Read GPREG %02X\n", tmp); return tmp; case 0x08: /* Revision ID */ @@ -2677,8 +2546,8 @@ ncr53c8xx_init(const device_t *info) dev->chip_rev = 0x26; dev->nvr_path = L"ncr53c825a.nvr"; } - ncr53c8xx_pci_bar[2].addr_regs[0] = 0; - ncr53c8xx_pci_bar[3].addr = 0xffff0000; + ncr53c8xx_pci_bar[2].addr_regs[0] = 0; + ncr53c8xx_pci_bar[3].addr = 0xffff0000; /* Need to make it align on a 16k boundary as that's this emulator's memory mapping granularity. */ ncr53c8xx_ram_init(dev, 0x0fffc000); @@ -2695,10 +2564,11 @@ ncr53c8xx_init(const device_t *info) dev->nvr_path = L"ncr53c810.nvr"; } -#ifdef USE_NVRAM + dev->i2c = i2c_gpio_init("nvr_ncr53c8xx"); + dev->eeprom = i2c_eeprom_init(i2c_gpio_get_bus(dev->i2c), 0x50, dev->nvram, sizeof(dev->nvram), 1); + /* Load the serial EEPROM. */ ncr53c8xx_eeprom(dev, 0); -#endif ncr53c8xx_soft_reset(dev); @@ -2714,6 +2584,15 @@ ncr53c8xx_close(void *priv) ncr53c8xx_t *dev = (ncr53c8xx_t *)priv; if (dev) { + /* Save the serial EEPROM. */ + ncr53c8xx_eeprom(dev, 1); + + if (dev->eeprom) + i2c_eeprom_close(dev->eeprom); + + if (dev->i2c) + i2c_gpio_close(dev->i2c); + free(dev); dev = NULL; } diff --git a/src/video/vid_ddc.c b/src/video/vid_ddc.c index 45788842e..f84d790e9 100644 --- a/src/video/vid_ddc.c +++ b/src/video/vid_ddc.c @@ -38,7 +38,7 @@ static uint8_t edid_data[128] = { 0x08, /* Analog input, separate sync */ 34, 0, /* Landscape, 4:3 */ 0, /* Gamma */ - 0x08, /* RGB colour */ + 0x08, /* RGB color */ 0x81, 0xf1, 0xa3, 0x57, 0x53, 0x9f, 0x27, 0x0a, 0x50, /* Chromaticity */ 0xff, 0xff, 0xff, /* Established timing bitmap */