Implement SLC90E66 OHCI USB

This commit is contained in:
RichardG867
2020-04-11 14:41:59 -03:00
parent e3e482b29a
commit 4184391200

View File

@@ -97,6 +97,8 @@ typedef struct
uint16_t func0_id,
nvr_io_base,
usb_io_base, power_io_base;
uint8_t *usb_smsc_mmio;
mem_mapping_t *usb_smsc_mmio_mapping;
sff8038i_t *bm[2];
ddma_t ddma[2];
power_t power;
@@ -105,7 +107,7 @@ typedef struct
nvr_t * nvr;
} piix_t;
#define ENABLE_PIIX_LOG 1
#ifdef ENABLE_PIIX_LOG
int piix_do_log = ENABLE_PIIX_LOG;
@@ -351,6 +353,65 @@ usb_update_io_mapping(piix_t *dev)
}
static void
usb_smsc_update_mem_mapping(piix_t *dev)
{
uint8_t *fregs;
uint32_t usb_bar;
if (!dev->usb_smsc_mmio_mapping)
return;
mem_mapping_disable(dev->usb_smsc_mmio_mapping);
if (!dev->usb_smsc_mmio)
return;
fregs = (uint8_t *) dev->regs[2];
usb_bar = fregs[0x10] | (fregs[0x11] << 8) | (fregs[0x12] << 16) | (fregs[0x13] << 24);
piix_log("smsc usb bar %08x\n", usb_bar);
if ((usb_bar != 0x00000000) && (usb_bar < 0xFF000000))
mem_mapping_set_addr(dev->usb_smsc_mmio_mapping, usb_bar, 0x1000);
}
static uint8_t
usb_smsc_mmio_read(uint32_t addr, void *p)
{
piix_t *dev = (piix_t *) p;
uint8_t ret;
ret = dev->usb_smsc_mmio[addr & 0xFFF];
piix_log("usb_smsc_mmio_read(%08x) = %02x\n", addr, ret);
return ret;
}
static void
usb_smsc_mmio_write(uint32_t addr, uint8_t val, void *p)
{
piix_t *dev = (piix_t *) p;
switch (addr & 0xFFF) {
case 0x08: /* HCCOMMANDSTATUS */
/* bit HostControllerReset must be cleared for the controller to be seen as initialized */
val = val & ~(0x01);
/* bit OwnershipChangeRequest triggers an ownership change (SMM <-> OS) */
if (val & 0x0F) {
dev->usb_smsc_mmio[0x0F] = 0x40;
dev->usb_smsc_mmio[0x05] &= ~(dev->usb_smsc_mmio[0x05] & 0x01);
}
break;
}
dev->usb_smsc_mmio[addr & 0xFFF] = val;
piix_log("usb_smsc_mmio_write(%08x, %02x)\n", addr, val);
}
static uint32_t
power_reg_readl(uint16_t addr, void *p)
{
@@ -799,6 +860,14 @@ piix_write(int func, int addr, uint8_t val, void *priv)
case 0x0d:
fregs[0x0d] = val & 0xf0;
break;
case 0x11:
fregs[addr] = val & ~(0x10);
usb_smsc_update_mem_mapping(dev);
break;
case 0x12: case 0x13:
fregs[addr] = val;
usb_smsc_update_mem_mapping(dev);
break;
case 0x20:
fregs[0x20] = (val & 0xe0) | 1;
usb_update_io_mapping(dev);
@@ -1010,7 +1079,7 @@ piix_reset_hard(piix_t *dev)
for (i = 0; i < 4; i++) {
memset(dev->regs[i], 0, 256);
if (dev->type == 5) {
dev->regs[i][0x00] = 0x55; dev->regs[i][0x01] = 0x10; /* SMSC */
dev->regs[i][0x00] = 0x55; dev->regs[i][0x01] = 0x10; /* SMSC/EFAR */
if (i == 1) { /* IDE controller is 9130, breaking convention */
dev->regs[i][0x02] = 0x30;
dev->regs[i][0x03] = 0x91;
@@ -1086,6 +1155,8 @@ piix_reset_hard(piix_t *dev)
fregs[0x08] = dev->rev & 0x07;
else
fregs[0x08] = dev->rev;
if (dev->type == 5)
fregs[0x09] = 0x10; /* SMSC has OHCI rather than UHCI */
fregs[0x0a] = 0x03; fregs[0x0b] = 0x0c;
fregs[0x20] = 0x01;
fregs[0x3d] = 0x04;
@@ -1094,6 +1165,14 @@ piix_reset_hard(piix_t *dev)
fregs[0xc1] = 0x20;
fregs[0xff] = (dev->type > 3) ? 0x10 : 0x00;
dev->max_func = 1; /* It starts with USB disabled, then enables it. */
/* SMSC OHCI memory-mapped registers */
if (dev->usb_smsc_mmio) {
memset(dev->usb_smsc_mmio, 0, 4096);
dev->usb_smsc_mmio[0x00] = 0x10;
dev->usb_smsc_mmio[0x01] = 0x01;
dev->usb_smsc_mmio[0x48] = 0x02;
}
}
/* Function 3: Power Management */
@@ -1164,6 +1243,17 @@ static void
if (dev->type > 3)
dev->nvr = device_add(&piix4_nvr_device);
if (dev->type == 5) {
dev->usb_smsc_mmio = malloc(4096);
dev->usb_smsc_mmio_mapping = malloc(sizeof(mem_mapping_t));
mem_mapping_add(dev->usb_smsc_mmio_mapping, 0, 0,
usb_smsc_mmio_read, NULL, NULL,
usb_smsc_mmio_write, NULL, NULL,
NULL, MEM_MAPPING_EXTERNAL, dev);
mem_mapping_disable(dev->usb_smsc_mmio_mapping);
}
piix_reset_hard(dev);
dev->smbus = device_add(&piix4_smbus_device);