I2C overhaul part 3: "we finally figured out NCR NVRAM" edition
This commit is contained in:
@@ -103,13 +103,16 @@ gl518sm_i2c_read(void *bus, uint8_t addr, void *priv)
|
|||||||
uint16_t read = gl518sm_read(dev, dev->addr_register);
|
uint16_t read = gl518sm_read(dev, dev->addr_register);
|
||||||
uint8_t ret = 0;
|
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 */
|
if ((dev->i2c_state == 1) && (dev->addr_register >= 0x07) && (dev->addr_register <= 0x0c)) { /* two-byte registers: read MSB first */
|
||||||
dev->i2c_state = 2;
|
dev->i2c_state = 2;
|
||||||
ret = read >> 8;
|
ret = read >> 8;
|
||||||
} else
|
} else {
|
||||||
ret = read;
|
ret = read;
|
||||||
|
|
||||||
dev->addr_register++;
|
dev->addr_register++;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -178,6 +181,7 @@ gl518sm_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
dev->i2c_state = 3;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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 uint8_t lm75_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv);
|
||||||
static void lm75_reset(lm75_t *dev);
|
static void lm75_reset(lm75_t *dev);
|
||||||
|
|
||||||
|
#define ENABLE_LM75_LOG 1
|
||||||
#ifdef ENABLE_LM75_LOG
|
#ifdef ENABLE_LM75_LOG
|
||||||
int lm75_do_log = ENABLE_LM75_LOG;
|
int lm75_do_log = ENABLE_LM75_LOG;
|
||||||
|
|
||||||
@@ -86,9 +86,21 @@ lm75_i2c_read(void *bus, uint8_t addr, void *priv)
|
|||||||
lm75_t *dev = (lm75_t *) priv;
|
lm75_t *dev = (lm75_t *) priv;
|
||||||
uint8_t ret = 0;
|
uint8_t ret = 0;
|
||||||
|
|
||||||
|
if (dev->i2c_state == 0)
|
||||||
|
dev->i2c_state = 1;
|
||||||
|
|
||||||
|
/* 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) {
|
switch (dev->addr_register & 0x3) {
|
||||||
case 0x0: /* temperature */
|
case 0x0: /* temperature */
|
||||||
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x1 : 0x0);
|
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x0 : 0x1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1: /* configuration */
|
case 0x1: /* configuration */
|
||||||
@@ -96,12 +108,16 @@ lm75_i2c_read(void *bus, uint8_t addr, void *priv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2: /* Thyst */
|
case 0x2: /* Thyst */
|
||||||
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x4 : 0x3);
|
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x3 : 0x4);
|
||||||
break;
|
break;
|
||||||
case 0x3: /* Tos */
|
case 0x3: /* Tos */
|
||||||
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x6 : 0x5);
|
ret = lm75_read(dev, (dev->i2c_state == 1) ? 0x5 : 0x6);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++dev->i2c_state > 2)
|
||||||
|
dev->i2c_state = 2;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -112,15 +128,7 @@ lm75_read(lm75_t *dev, uint8_t reg)
|
|||||||
{
|
{
|
||||||
uint8_t ret;
|
uint8_t ret;
|
||||||
|
|
||||||
/* The AS99127F hardware monitor uses the addresses of its LM75 devices
|
if ((reg & 0x7) == 0x0) /* temperature high byte */
|
||||||
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 */
|
|
||||||
ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]) >> 8;
|
ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]) >> 8;
|
||||||
else if ((reg & 0x7) == 0x1) /* temperature low byte */
|
else if ((reg & 0x7) == 0x1) /* temperature low byte */
|
||||||
ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]);
|
ret = LM75_TEMP_TO_REG(dev->values->temperatures[dev->local >> 8]);
|
||||||
@@ -145,9 +153,19 @@ lm75_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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) {
|
switch (dev->addr_register & 0x3) {
|
||||||
case 0x0: /* temperature */
|
case 0x0: /* temperature */
|
||||||
lm75_write(dev, (dev->i2c_state == 1) ? 0x1 : 0x0, data);
|
lm75_write(dev, (dev->i2c_state == 1) ? 0x0 : 0x1, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1: /* configuration */
|
case 0x1: /* configuration */
|
||||||
@@ -155,12 +173,16 @@ lm75_i2c_write(void *bus, uint8_t addr, uint8_t data, void *priv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2: /* Thyst */
|
case 0x2: /* Thyst */
|
||||||
lm75_write(dev, (dev->i2c_state == 1) ? 0x4 : 0x3, data);
|
lm75_write(dev, (dev->i2c_state == 1) ? 0x3 : 0x4, data);
|
||||||
break;
|
break;
|
||||||
case 0x3: /* Tos */
|
case 0x3: /* Tos */
|
||||||
lm75_write(dev, (dev->i2c_state == 1) ? 0x6 : 0x5, data);
|
lm75_write(dev, (dev->i2c_state == 1) ? 0x5 : 0x6, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++dev->i2c_state > 2)
|
||||||
|
dev->i2c_state = 2;
|
||||||
|
|
||||||
return 1;
|
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);
|
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);
|
uint8_t reg_idx = (reg & 0x7);
|
||||||
|
|
||||||
if ((reg_idx <= 0x1) || (reg_idx == 0x7))
|
if ((reg_idx <= 0x1) || (reg_idx == 0x7))
|
||||||
|
@@ -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 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);
|
static void lm78_reset(lm78_t *dev, uint8_t initialization);
|
||||||
|
|
||||||
|
#define ENABLE_LM78_LOG 1
|
||||||
#ifdef ENABLE_LM78_LOG
|
#ifdef ENABLE_LM78_LOG
|
||||||
int lm78_do_log = ENABLE_LM78_LOG;
|
int lm78_do_log = ENABLE_LM78_LOG;
|
||||||
|
|
||||||
|
@@ -194,6 +194,8 @@ i2c_has_device(void *bus_handle, uint8_t addr)
|
|||||||
if (!bus)
|
if (!bus)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
i2c_log("I2C: has_device(%s, %02X) = %d\n", bus->name, addr, !!bus->devices[addr]);
|
||||||
|
|
||||||
return(!!bus->devices[addr]);
|
return(!!bus->devices[addr]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the 86Box distribution.
|
* 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 {
|
typedef struct {
|
||||||
void *i2c;
|
void *i2c;
|
||||||
uint8_t addr;
|
uint8_t addr, *data, writable;
|
||||||
uint8_t *data;
|
|
||||||
uint8_t writable;
|
|
||||||
|
|
||||||
uint16_t addr_mask;
|
uint16_t addr_mask, addr_register;
|
||||||
uint8_t addr_register;
|
|
||||||
uint8_t i2c_state;
|
uint8_t i2c_state;
|
||||||
} i2c_eeprom_t;
|
} 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
|
void
|
||||||
i2c_eeprom_start(void *bus, uint8_t addr, void *priv)
|
i2c_eeprom_start(void *bus, uint8_t addr, void *priv)
|
||||||
{
|
{
|
||||||
i2c_eeprom_t *dev = (i2c_eeprom_t *) priv;
|
i2c_eeprom_t *dev = (i2c_eeprom_t *) priv;
|
||||||
|
|
||||||
|
i2c_eeprom_log("I2C EEPROM: start()\n");
|
||||||
|
|
||||||
dev->i2c_state = 0;
|
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_read(void *bus, uint8_t addr, void *priv)
|
||||||
{
|
{
|
||||||
i2c_eeprom_t *dev = (i2c_eeprom_t *) 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) {
|
if (dev->i2c_state == 0) {
|
||||||
dev->i2c_state = 1;
|
dev->i2c_state = 1;
|
||||||
dev->addr_register = data;
|
dev->addr_register = ((addr << 8) | data) & dev->addr_mask;
|
||||||
} else if (dev->writable)
|
i2c_eeprom_log("I2C EEPROM: write(address, %04X)\n", dev->addr_register);
|
||||||
dev->data[((addr << 8) | dev->addr_register++) & dev->addr_mask] = data;
|
} else {
|
||||||
else
|
i2c_eeprom_log("I2C EEPROM: write(%04X, %02X) = %s\n", dev->addr_register, data, dev->writable ? "accepted" : "blocked");
|
||||||
return 0;
|
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;
|
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));
|
i2c_eeprom_t *dev = (i2c_eeprom_t *) malloc(sizeof(i2c_eeprom_t));
|
||||||
memset(dev, 0, 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->i2c = i2c;
|
||||||
dev->addr = addr;
|
dev->addr = addr;
|
||||||
dev->data = data;
|
dev->data = data;
|
||||||
@@ -96,6 +128,8 @@ i2c_eeprom_close(void *dev_handle)
|
|||||||
{
|
{
|
||||||
i2c_eeprom_t *dev = (i2c_eeprom_t *) 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);
|
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);
|
free(dev);
|
||||||
|
@@ -52,19 +52,43 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
char *bus_name;
|
||||||
void *i2c;
|
void *i2c;
|
||||||
uint8_t scl, sda, state, slave_state, slave_addr,
|
uint8_t scl, sda, state, slave_state, slave_addr,
|
||||||
slave_rw, last_sda, pos, transmit, byte;
|
slave_rw, last_sda, pos, transmit, byte;
|
||||||
} i2c_gpio_t;
|
} 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 *
|
void *
|
||||||
i2c_gpio_init(char *bus_name)
|
i2c_gpio_init(char *bus_name)
|
||||||
{
|
{
|
||||||
i2c_gpio_t *dev = (i2c_gpio_t *) malloc(sizeof(i2c_gpio_t));
|
i2c_gpio_t *dev = (i2c_gpio_t *) malloc(sizeof(i2c_gpio_t));
|
||||||
memset(dev, 0, 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->scl = dev->sda = 1;
|
||||||
dev->slave_addr = 0xff;
|
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_t *dev = (i2c_gpio_t *) dev_handle;
|
||||||
|
|
||||||
|
i2c_gpio_log(1, "I2C GPIO %s: close()\n", dev->bus_name);
|
||||||
|
|
||||||
i2c_removebus(dev->i2c);
|
i2c_removebus(dev->i2c);
|
||||||
|
|
||||||
free(dev);
|
free(dev);
|
||||||
@@ -87,6 +113,7 @@ void
|
|||||||
i2c_gpio_next_byte(i2c_gpio_t *dev)
|
i2c_gpio_next_byte(i2c_gpio_t *dev)
|
||||||
{
|
{
|
||||||
dev->byte = i2c_read(dev->i2c, dev->slave_addr);
|
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_addr = dev->byte >> 1;
|
||||||
dev->slave_rw = 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)) {
|
if (!i2c_has_device(dev->i2c, dev->slave_addr)) {
|
||||||
dev->slave_state = SLAVE_INVALID;
|
dev->slave_state = SLAVE_INVALID;
|
||||||
break;
|
break;
|
||||||
@@ -120,11 +149,13 @@ i2c_gpio_write(i2c_gpio_t *dev)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SLAVE_RECEIVEADDR:
|
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);
|
i2c_write(dev->i2c, dev->slave_addr, dev->byte);
|
||||||
dev->slave_state = dev->slave_rw ? SLAVE_SENDDATA : SLAVE_RECEIVEDATA;
|
dev->slave_state = dev->slave_rw ? SLAVE_SENDDATA : SLAVE_RECEIVEDATA;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SLAVE_RECEIVEDATA:
|
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);
|
i2c_write(dev->i2c, dev->slave_addr, dev->byte);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -134,6 +165,9 @@ i2c_gpio_write(i2c_gpio_t *dev)
|
|||||||
void
|
void
|
||||||
i2c_gpio_stop(i2c_gpio_t *dev)
|
i2c_gpio_stop(i2c_gpio_t *dev)
|
||||||
{
|
{
|
||||||
|
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);
|
i2c_stop(dev->i2c, dev->slave_addr);
|
||||||
|
|
||||||
dev->slave_addr = 0xff;
|
dev->slave_addr = 0xff;
|
||||||
@@ -149,7 +183,9 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
|||||||
|
|
||||||
switch (dev->state) {
|
switch (dev->state) {
|
||||||
case I2C_IDLE:
|
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->state = I2C_RECEIVE;
|
||||||
dev->pos = 0;
|
dev->pos = 0;
|
||||||
}
|
}
|
||||||
@@ -173,9 +209,11 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
|||||||
}
|
}
|
||||||
} else if (dev->scl && scl) {
|
} else if (dev->scl && scl) {
|
||||||
if (sda && !dev->last_sda) { /* stop bit */
|
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;
|
dev->state = I2C_IDLE;
|
||||||
i2c_gpio_stop(dev);
|
i2c_gpio_stop(dev);
|
||||||
} else if (!sda && dev->last_sda) { /* start bit */
|
} 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->pos = 0;
|
||||||
dev->slave_state = SLAVE_IDLE;
|
dev->slave_state = SLAVE_IDLE;
|
||||||
}
|
}
|
||||||
@@ -184,6 +222,7 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
|||||||
|
|
||||||
case I2C_ACKNOWLEDGE:
|
case I2C_ACKNOWLEDGE:
|
||||||
if (!dev->scl && scl) {
|
if (!dev->scl && scl) {
|
||||||
|
i2c_gpio_log(2, "I2C GPIO %s: Acknowledging transfer\n", dev->bus_name);
|
||||||
sda = 0;
|
sda = 0;
|
||||||
dev->pos = 0;
|
dev->pos = 0;
|
||||||
dev->state = (dev->transmit == TRANSMITTER_MASTER) ? I2C_RECEIVE_WAIT : I2C_TRANSMIT;
|
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:
|
case I2C_TRANSACKNOWLEDGE:
|
||||||
if (!dev->scl && scl) {
|
if (!dev->scl && scl) {
|
||||||
if (sda) { /* not acknowledged; must be end of transfer */
|
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;
|
dev->state = I2C_IDLE;
|
||||||
i2c_gpio_stop(dev);
|
i2c_gpio_stop(dev);
|
||||||
} else { /* next byte to transfer */
|
} else { /* next byte to transfer */
|
||||||
dev->state = I2C_TRANSMIT_START;
|
dev->state = I2C_TRANSMIT_START;
|
||||||
i2c_gpio_next_byte(dev);
|
i2c_gpio_next_byte(dev);
|
||||||
dev->pos = 0;
|
dev->pos = 0;
|
||||||
|
i2c_gpio_log(2, "I2C GPIO %s: Next byte = %02X\n", dev->bus_name, dev->byte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -208,8 +249,10 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
|||||||
if (dev->last_sda && !sda) { /* start bit */
|
if (dev->last_sda && !sda) { /* start bit */
|
||||||
i2c_gpio_next_byte(dev);
|
i2c_gpio_next_byte(dev);
|
||||||
dev->pos = 0;
|
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 */
|
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;
|
dev->state = I2C_IDLE;
|
||||||
i2c_gpio_stop(dev);
|
i2c_gpio_stop(dev);
|
||||||
}
|
}
|
||||||
@@ -220,6 +263,7 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
|||||||
if (!dev->scl && scl)
|
if (!dev->scl && scl)
|
||||||
dev->state = I2C_TRANSMIT;
|
dev->state = I2C_TRANSMIT;
|
||||||
if (dev->scl && scl && !dev->last_sda && sda) { /* stop bit */
|
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;
|
dev->state = I2C_IDLE;
|
||||||
i2c_gpio_stop(dev);
|
i2c_gpio_stop(dev);
|
||||||
}
|
}
|
||||||
@@ -228,13 +272,18 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
|||||||
case I2C_TRANSMIT:
|
case I2C_TRANSMIT:
|
||||||
if (!dev->scl && scl) {
|
if (!dev->scl && scl) {
|
||||||
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;
|
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->byte <<= 1;
|
||||||
dev->pos++;
|
dev->pos++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (dev->scl && !scl && (dev->pos == 8))
|
if (dev->scl && !scl && (dev->pos == 8)) {
|
||||||
dev->state = I2C_TRANSACKNOWLEDGE;
|
dev->state = I2C_TRANSACKNOWLEDGE;
|
||||||
|
i2c_gpio_log(2, "I2C GPIO %s: Acknowledge mode\n", dev->bus_name);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,6 +43,7 @@
|
|||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
#include <86box/nvr.h>
|
#include <86box/nvr.h>
|
||||||
#include <86box/plat.h>
|
#include <86box/plat.h>
|
||||||
|
#include <86box/i2c.h>
|
||||||
#include <86box/scsi.h>
|
#include <86box/scsi.h>
|
||||||
#include <86box/scsi_device.h>
|
#include <86box/scsi_device.h>
|
||||||
#include <86box/scsi_ncr53c8xx.h>
|
#include <86box/scsi_ncr53c8xx.h>
|
||||||
@@ -225,14 +226,8 @@ typedef struct {
|
|||||||
int msg_action;
|
int msg_action;
|
||||||
int msg_len;
|
int msg_len;
|
||||||
uint8_t msg[NCR_MAX_MSGIN_LEN];
|
uint8_t msg[NCR_MAX_MSGIN_LEN];
|
||||||
#ifdef USE_NVRAM
|
uint8_t nvram[2048]; /* 24C16 EEPROM (16 kbit) */
|
||||||
uint16_t nvram;
|
void *i2c, *eeprom;
|
||||||
uint8_t nvram_t;
|
|
||||||
uint8_t nvram_op;
|
|
||||||
uint8_t nvram_param;
|
|
||||||
uint8_t nvram_start;
|
|
||||||
uint8_t nvram_index;
|
|
||||||
#endif
|
|
||||||
uint8_t ram[NCR_BUF_SIZE]; /* NCR 53c875 RAM (4 kB). */
|
uint8_t ram[NCR_BUF_SIZE]; /* NCR 53c875 RAM (4 kB). */
|
||||||
/* 0 if SCRIPTS are running or stopped.
|
/* 0 if SCRIPTS are running or stopped.
|
||||||
* 1 if a Wait Reselect instruction has been issued.
|
* 1 if a Wait Reselect instruction has been issued.
|
||||||
@@ -434,10 +429,7 @@ ncr53c8xx_soft_reset(ncr53c8xx_t *dev)
|
|||||||
dev->gpreg = 0;
|
dev->gpreg = 0;
|
||||||
dev->slpar = 0;
|
dev->slpar = 0;
|
||||||
dev->sstop = 1;
|
dev->sstop = 1;
|
||||||
dev->gpcntl = 0x0f;
|
dev->gpcntl = 0x03;
|
||||||
#ifdef USE_NVRAM
|
|
||||||
dev->nvram_t = dev->nvram_index = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (dev->chip >= CHIP_825) {
|
if (dev->chip >= CHIP_825) {
|
||||||
/* This *IS* a wide SCSI controller, so reset all SCSI
|
/* This *IS* a wide SCSI controller, so reset all SCSI
|
||||||
@@ -1452,146 +1444,22 @@ ncr53c8xx_callback(void *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_NVRAM
|
|
||||||
static void
|
static void
|
||||||
ncr53c8xx_eeprom(ncr53c8xx_t *dev, int save)
|
ncr53c8xx_eeprom(ncr53c8xx_t *dev, uint8_t save)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
|
f = nvr_fopen(dev->nvr_path, save ? L"wb": L"rb");
|
||||||
|
if (f) {
|
||||||
if (save)
|
if (save)
|
||||||
f = nvr_fopen(dev->nvr_path, L"wb");
|
fwrite(&dev->nvram, sizeof(dev->nvram), 1, f);
|
||||||
else
|
else
|
||||||
f = nvr_fopen(dev->nvr_path, L"rb");
|
fread(&dev->nvram, sizeof(dev->nvram), 1, f);
|
||||||
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);
|
|
||||||
}
|
|
||||||
fclose(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
|
static void
|
||||||
ncr53c8xx_reg_writeb(ncr53c8xx_t *dev, uint32_t offset, uint8_t val)
|
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;
|
break;
|
||||||
case 0x07: /* GPREG */
|
case 0x07: /* GPREG */
|
||||||
ncr53c8xx_log("NCR 810: GPREG write %02X\n", val);
|
ncr53c8xx_log("NCR 810: GPREG write %02X\n", val);
|
||||||
tmp = dev->gpreg;
|
dev->gpreg = val;
|
||||||
dev->gpreg = val & 0xfe;
|
i2c_gpio_set(dev->i2c, !!(dev->gpreg & 0x02), !!(dev->gpreg & 0x01));
|
||||||
#ifdef USE_NVRAM
|
|
||||||
if ((dev->gpcntl & 0xc3) == 0x00)
|
|
||||||
ncr53c8xx_serial_eeprom_write(dev, val & 0x03);
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case 0x08: /* SFBR */
|
case 0x08: /* SFBR */
|
||||||
/* The CPU is not allowed to write to this register. However the
|
/* 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);
|
ncr53c8xx_log("NCR 810: Read SDID %02X\n", dev->sdid);
|
||||||
return dev->sdid;
|
return dev->sdid;
|
||||||
case 0x07: /* GPREG */
|
case 0x07: /* GPREG */
|
||||||
#ifdef USE_NVRAM
|
tmp = (dev->gpreg & (dev->gpcntl ^ 0x1f)) & 0x1f;
|
||||||
tmp = (dev->gpreg & (dev->gpcntl ^ 0x1f)) & 0x1e;
|
if ((dev->gpcntl & 0x41) == 0x01) {
|
||||||
if ((dev->gpcntl & 0xc3) == 0x01)
|
tmp &= 0xfe;
|
||||||
tmp |= ncr53c8xx_serial_eeprom_read(dev);
|
if (i2c_gpio_get_sda(dev->i2c))
|
||||||
#else
|
tmp |= 0x01;
|
||||||
tmp = ((dev->gpreg & (dev->gpcntl ^ 0x1f)) & 0x1e) | 0x01;
|
}
|
||||||
#endif
|
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);
|
ncr53c8xx_log("NCR 810: Read GPREG %02X\n", tmp);
|
||||||
return tmp;
|
return tmp;
|
||||||
case 0x08: /* Revision ID */
|
case 0x08: /* Revision ID */
|
||||||
@@ -2695,10 +2564,11 @@ ncr53c8xx_init(const device_t *info)
|
|||||||
dev->nvr_path = L"ncr53c810.nvr";
|
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. */
|
/* Load the serial EEPROM. */
|
||||||
ncr53c8xx_eeprom(dev, 0);
|
ncr53c8xx_eeprom(dev, 0);
|
||||||
#endif
|
|
||||||
|
|
||||||
ncr53c8xx_soft_reset(dev);
|
ncr53c8xx_soft_reset(dev);
|
||||||
|
|
||||||
@@ -2714,6 +2584,15 @@ ncr53c8xx_close(void *priv)
|
|||||||
ncr53c8xx_t *dev = (ncr53c8xx_t *)priv;
|
ncr53c8xx_t *dev = (ncr53c8xx_t *)priv;
|
||||||
|
|
||||||
if (dev) {
|
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);
|
free(dev);
|
||||||
dev = NULL;
|
dev = NULL;
|
||||||
}
|
}
|
||||||
|
@@ -38,7 +38,7 @@ static uint8_t edid_data[128] = {
|
|||||||
0x08, /* Analog input, separate sync */
|
0x08, /* Analog input, separate sync */
|
||||||
34, 0, /* Landscape, 4:3 */
|
34, 0, /* Landscape, 4:3 */
|
||||||
0, /* Gamma */
|
0, /* Gamma */
|
||||||
0x08, /* RGB colour */
|
0x08, /* RGB color */
|
||||||
0x81, 0xf1, 0xa3, 0x57, 0x53, 0x9f, 0x27, 0x0a, 0x50, /* Chromaticity */
|
0x81, 0xf1, 0xa3, 0x57, 0x53, 0x9f, 0x27, 0x0a, 0x50, /* Chromaticity */
|
||||||
|
|
||||||
0xff, 0xff, 0xff, /* Established timing bitmap */
|
0xff, 0xff, 0xff, /* Established timing bitmap */
|
||||||
|
Reference in New Issue
Block a user