diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index 6d03b3a12..00146c90e 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -1430,7 +1430,7 @@ ali7101_read(int func, int addr, void *priv) } static void -ali5237_usb_raise_interrupt(void *priv) +ali5237_usb_raise_interrupt(usb_t* usb, void *priv) { ali1543_t *dev = (ali1543_t *) priv; diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index 39ddf9cf6..af1922570 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -36,7 +36,13 @@ typedef struct /* USB Host Controller device struct */ typedef struct usb_t { - uint8_t uhci_io[32], ohci_mmio[4096]; + union + { + uint8_t ohci_mmio[4096]; + uint16_t ohci_mmio_w[2048]; + uint32_t ohci_mmio_l[1024]; + }; + uint8_t uhci_io[32]; uint16_t uhci_io_base; int uhci_enable, ohci_enable; uint32_t ohci_mem_base; diff --git a/src/usb.c b/src/usb.c index 0951412d6..cde3ee4a9 100644 --- a/src/usb.c +++ b/src/usb.c @@ -63,7 +63,7 @@ enum OHCI_HcBulkHeadED = 0x28, OHCI_HcBulkCurrentED = 0x2C, OHCI_HcDoneHead = 0x30, - OHCI_HcFMInterval = 0x34, + OHCI_HcFmInterval = 0x34, OHCI_HcFmRemaining = 0x38, OHCI_HcFmNumber = 0x3C, OHCI_HcPeriodicStart = 0x40, @@ -223,10 +223,50 @@ ohci_mmio_read(uint32_t addr, void *p) return ret; } +void +ohci_set_interrupt(usb_t* usb, uint8_t bit) +{ + if (!(usb->ohci_mmio[OHCI_HcInterruptEnable + 3] & 0x80)) + return; + + if (!(usb->ohci_mmio[OHCI_HcInterruptEnable] & bit)) + return; + + if (usb->ohci_mmio[OHCI_HcInterruptDisable] & bit) + return; + + usb->ohci_mmio[OHCI_HcInterruptStatus] |= bit; + usb_interrupt_ohci(usb); +} + +void +ohci_end_of_frame(usb_t* dev) +{ + /* TODO: Put endpoint and transfer descriptor processing here. */ +} + +void +ohci_start_of_frame(usb_t* dev) +{ + ohci_set_interrupt(dev, OHCI_HcInterruptEnable_SO); +} + void ohci_update_frame_counter(void* priv) { usb_t *dev = (usb_t *) priv; + + dev->ohci_mmio_w[OHCI_HcFmRemaining / 2] &= 0x3fff; + if (dev->ohci_mmio_w[OHCI_HcFmRemaining / 2] == 0) { + ohci_end_of_frame(dev); + dev->ohci_mmio_w[OHCI_HcFmRemaining / 2] = dev->ohci_mmio_w[OHCI_HcFmInterval / 2] & 0x3fff; + dev->ohci_mmio_l[OHCI_HcFmRemaining / 4] &= ~(1 << 31); + dev->ohci_mmio_l[OHCI_HcFmRemaining / 4] |= dev->ohci_mmio_l[OHCI_HcFmInterval / 4] & (1 << 31); + dev->ohci_mmio_w[OHCI_HcFmNumber / 2]++; + ohci_start_of_frame(dev); + } + if (dev->ohci_mmio_w[OHCI_HcFmRemaining / 2]) dev->ohci_mmio_w[OHCI_HcFmRemaining / 2]--; + timer_on_auto(&dev->ohci_frame_timer, 1. / (12. * 1000. * 1000.)); } void @@ -257,23 +297,6 @@ ohci_port_reset_callback_2(void* priv) dev->ohci_mmio[OHCI_HcRhPortStatus2] &= ~0x10; dev->ohci_mmio[OHCI_HcRhPortStatus2 + 2] |= 0x10; } - -void -ohci_set_interrupt(usb_t* usb, uint8_t bit) -{ - if (!(usb->ohci_mmio[OHCI_HcInterruptEnable + 3] & 0x80)) - return; - - if (!(usb->ohci_mmio[OHCI_HcInterruptEnable] & bit)) - return; - - if (usb->ohci_mmio[OHCI_HcInterruptDisable] & bit) - return; - - usb->ohci_mmio[OHCI_HcInterruptStatus] |= bit; - usb_interrupt_ohci(usb); -} - static void ohci_mmio_write(uint32_t addr, uint8_t val, void *p) {