Clean up SMBus PIIX4 code

This commit is contained in:
RichardG867
2020-10-11 18:52:00 -03:00
committed by David Hrdlička
parent 88c4fdb93e
commit 88e396f852

View File

@@ -39,9 +39,9 @@ smbus_piix4_log(const char *fmt, ...)
va_list ap; va_list ap;
if (smbus_piix4_do_log) { if (smbus_piix4_do_log) {
va_start(ap, fmt); va_start(ap, fmt);
pclog_ex(fmt, ap); pclog_ex(fmt, ap);
va_end(ap); va_end(ap);
} }
} }
#else #else
@@ -56,30 +56,30 @@ smbus_piix4_read(uint16_t addr, void *priv)
uint8_t ret = 0x00; uint8_t ret = 0x00;
switch (addr - dev->io_base) { switch (addr - dev->io_base) {
case 0x00: case 0x00:
ret = dev->stat; ret = dev->stat;
break; break;
case 0x02: case 0x02:
dev->index = 0; /* reading from this resets the block data index */ dev->index = 0; /* reading from this resets the block data index */
ret = dev->ctl; ret = dev->ctl;
break; break;
case 0x03: case 0x03:
ret = dev->cmd; ret = dev->cmd;
break; break;
case 0x04: case 0x04:
ret = dev->addr; ret = dev->addr;
break; break;
case 0x05: case 0x05:
ret = dev->data0; ret = dev->data0;
break; break;
case 0x06: case 0x06:
ret = dev->data1; ret = dev->data1;
break; break;
case 0x07: case 0x07:
ret = dev->data[dev->index++]; ret = dev->data[dev->index++];
if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE) if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE)
dev->index = 0; dev->index = 0;
break; break;
} }
smbus_piix4_log("SMBus PIIX4: read(%02x) = %02x\n", addr, ret); smbus_piix4_log("SMBus PIIX4: read(%02x) = %02x\n", addr, ret);
@@ -100,99 +100,100 @@ smbus_piix4_write(uint16_t addr, uint8_t val, void *priv)
prev_stat = dev->next_stat; prev_stat = dev->next_stat;
dev->next_stat = 0; dev->next_stat = 0;
switch (addr - dev->io_base) { switch (addr - dev->io_base) {
case 0x00: case 0x00:
/* some status bits are reset by writing 1 to them */ /* some status bits are reset by writing 1 to them */
for (smbus_addr = 0x02; smbus_addr <= 0x10; smbus_addr <<= 1) { for (smbus_addr = 0x02; smbus_addr <= 0x10; smbus_addr <<= 1) {
if (val & smbus_addr) if (val & smbus_addr)
dev->stat &= ~smbus_addr; dev->stat &= ~smbus_addr;
} }
break; break;
case 0x02: case 0x02:
dev->ctl = val & ~(0x40); /* START always reads 0 */ dev->ctl = val & ~(0x40); /* START always reads 0 */
if (val & 0x02) { /* cancel an in-progress command if KILL is set */ if (val & 0x02) { /* cancel an in-progress command if KILL is set */
/* cancel only if a command is in progress */ /* cancel only if a command is in progress */
if (prev_stat) { if (prev_stat) {
dev->stat = 0x10; /* raise FAILED */ dev->stat = 0x10; /* raise FAILED */
timer_disable(&dev->response_timer); timer_disable(&dev->response_timer);
} }
} }
if (val & 0x40) { /* dispatch command if START is set */ if (val & 0x40) { /* dispatch command if START is set */
smbus_addr = (dev->addr >> 1); smbus_addr = (dev->addr >> 1);
if (!smbus_has_device(smbus_addr)) { if (!smbus_has_device(smbus_addr)) {
/* raise DEV_ERR if no device is at this address */ /* raise DEV_ERR if no device is at this address */
dev->next_stat = 0x4; dev->next_stat = 0x4;
break; break;
} }
smbus_read = (dev->addr & 0x01); smbus_read = (dev->addr & 0x01);
/* decode the 3-bit command protocol */ /* decode the 3-bit command protocol */
switch ((val >> 2) & 0x7) { dev->next_stat = 0x2; /* raise INTER (command completed) by default */
case 0x0: /* quick R/W */ switch ((val >> 2) & 0x7) {
dev->next_stat = 0x2; case 0x0: /* quick R/W */
break; break;
case 0x1: /* byte R/W */
if (smbus_read) case 0x1: /* byte R/W */
dev->data0 = smbus_read_byte(smbus_addr); if (smbus_read)
else dev->data0 = smbus_read_byte(smbus_addr);
smbus_write_byte(smbus_addr, dev->data0); else
dev->next_stat = 0x2; smbus_write_byte(smbus_addr, dev->data0);
break; break;
case 0x2: /* byte data R/W */
if (smbus_read) case 0x2: /* byte data R/W */
dev->data0 = smbus_read_byte_cmd(smbus_addr, dev->cmd); if (smbus_read)
else dev->data0 = smbus_read_byte_cmd(smbus_addr, dev->cmd);
smbus_write_byte_cmd(smbus_addr, dev->cmd, dev->data0); else
dev->next_stat = 0x2; smbus_write_byte_cmd(smbus_addr, dev->cmd, dev->data0);
break; break;
case 0x3: /* word data R/W */
if (smbus_read) { case 0x3: /* word data R/W */
temp = smbus_read_word_cmd(smbus_addr, dev->cmd); if (smbus_read) {
dev->data0 = (temp & 0xFF); temp = smbus_read_word_cmd(smbus_addr, dev->cmd);
dev->data1 = (temp >> 8); dev->data0 = (temp & 0xFF);
} else { dev->data1 = (temp >> 8);
temp = ((dev->data1 << 8) | dev->data0); } else {
smbus_write_word_cmd(smbus_addr, dev->cmd, temp); temp = ((dev->data1 << 8) | dev->data0);
} smbus_write_word_cmd(smbus_addr, dev->cmd, temp);
dev->next_stat = 0x2; }
break; break;
case 0x5: /* block R/W */
if (smbus_read) case 0x5: /* block R/W */
dev->data0 = smbus_read_block_cmd(smbus_addr, dev->cmd, dev->data, SMBUS_PIIX4_BLOCK_DATA_SIZE); if (smbus_read)
else dev->data0 = smbus_read_block_cmd(smbus_addr, dev->cmd, dev->data, SMBUS_PIIX4_BLOCK_DATA_SIZE);
smbus_write_block_cmd(smbus_addr, dev->cmd, dev->data, dev->data0); else
dev->next_stat = 0x2; smbus_write_block_cmd(smbus_addr, dev->cmd, dev->data, dev->data0);
break; break;
default:
/* other command protocols have undefined behavior, but raise DEV_ERR to be safe */ default:
dev->next_stat = 0x4; /* other command protocols have undefined behavior, but raise DEV_ERR to be safe */
break; dev->next_stat = 0x4;
} break;
} }
break; }
case 0x03: break;
dev->cmd = val; case 0x03:
break; dev->cmd = val;
case 0x04: break;
dev->addr = val; case 0x04:
break; dev->addr = val;
case 0x05: break;
dev->data0 = val; case 0x05:
break; dev->data0 = val;
case 0x06: break;
dev->data1 = val; case 0x06:
break; dev->data1 = val;
case 0x07: break;
dev->data[dev->index++] = val; case 0x07:
if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE) dev->data[dev->index++] = val;
dev->index = 0; if (dev->index >= SMBUS_PIIX4_BLOCK_DATA_SIZE)
break; dev->index = 0;
break;
} }
/* if a status register update was given, dispatch it after 10ms to ensure nothing breaks */ /* if a status register update was given, dispatch it after 10ms to ensure nothing breaks */
if (dev->next_stat) { if (dev->next_stat) {
dev->stat = 0x1; /* raise HOST_BUSY while waiting */ dev->stat = 0x1; /* raise HOST_BUSY while waiting */
timer_disable(&dev->response_timer); timer_disable(&dev->response_timer);
timer_set_delay_u64(&dev->response_timer, 10 * TIMER_USEC); timer_set_delay_u64(&dev->response_timer, 10 * TIMER_USEC);
} }
} }
@@ -210,13 +211,13 @@ smbus_piix4_response(void *priv)
void void
smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable) smbus_piix4_remap(smbus_piix4_t *dev, uint16_t new_io_base, uint8_t enable)
{ {
if (dev->io_base != 0x0000) if (dev->io_base)
io_removehandler(dev->io_base, 0x10, smbus_piix4_read, NULL, NULL, smbus_piix4_write, NULL, NULL, dev); io_removehandler(dev->io_base, 0x10, smbus_piix4_read, NULL, NULL, smbus_piix4_write, NULL, NULL, dev);
dev->io_base = new_io_base; dev->io_base = new_io_base;
smbus_piix4_log("SMBus PIIX4: remap to %04Xh (enable %d)\n", dev->io_base, !!enable); smbus_piix4_log("SMBus PIIX4: remap to %04Xh (%sabled)\n", dev->io_base, enable ? "en" : "dis");
if ((enable) && (dev->io_base != 0x0000)) if (enable && dev->io_base)
io_sethandler(dev->io_base, 0x10, smbus_piix4_read, NULL, NULL, smbus_piix4_write, NULL, NULL, dev); io_sethandler(dev->io_base, 0x10, smbus_piix4_read, NULL, NULL, smbus_piix4_write, NULL, NULL, dev);
} }