From a6086c451e1bfc9d83d8582800ff71f049865ba5 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 8 May 2023 00:50:00 +0600 Subject: [PATCH] usb: Start finalizing work on OHCI --- src/include/86box/usb.h | 53 ++++++++++++++++------------- src/usb.c | 75 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 25 deletions(-) diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index 4c6fc289b..1f5413cd7 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -24,6 +24,33 @@ extern "C" { typedef struct usb_t usb_t; +/* USB endpoint device struct. Incomplete and unused. */ +typedef struct +{ + uint16_t vendor_id; + uint16_t device_id; + + /* Reads from endpoint. Non-zero value indicates error. */ + uint8_t (*device_in)(void* priv, uint8_t* data, uint32_t len); + /* Writes to endpoint. Non-zero value indicates error. */ + uint8_t (*device_out)(void* priv, uint8_t* data, uint32_t len); + /* Process setup packets. */ + uint8_t (*device_setup)(void* priv, uint8_t* data); + /* Device reset. */ + void (*device_reset)(void* priv); + /* Get address. */ + uint8_t (*device_get_address)(void* priv); + + void* priv; +} usb_device_t; + +enum usb_bus_types +{ + USB_BUS_OHCI = 0, + USB_BUS_UHCI, + USB_BUS_MAX +}; + /* USB device creation parameters struct */ typedef struct { @@ -52,6 +79,8 @@ typedef struct usb_t pc_timer_t ohci_frame_timer; pc_timer_t ohci_port_reset_timer[2]; uint8_t ohci_interrupt_counter : 3; + usb_device_t* ohci_devices[2]; + usb_device_t* uhci_devices[2]; usb_params_t* usb_params; } usb_t; @@ -79,30 +108,6 @@ typedef struct #pragma pack(pop) -/* USB endpoint device struct. Incomplete and unused. */ -typedef struct -{ - uint16_t vendor_id; - uint16_t device_id; - - /* Reads from endpoint. Non-zero value indicates error. */ - uint8_t (*device_in)(void* priv, uint8_t* data, uint32_t len); - /* Writes to endpoint. Non-zero value indicates error. */ - uint8_t (*device_out)(void* priv, uint8_t* data, uint32_t len); - /* Process setup packets. */ - uint8_t (*device_setup)(void* priv, uint8_t* data); - /* Device reset */ - void (*device_reset)(void* priv); - - void* priv; -} usb_device_t; - -enum usb_bus_types -{ - USB_BUS_OHCI = 0, - USB_BUS_UHCI = 1 -}; - /* Global variables. */ extern const device_t usb_device; diff --git a/src/usb.c b/src/usb.c index 03b5f6546..0b9a8255f 100644 --- a/src/usb.c +++ b/src/usb.c @@ -371,12 +371,85 @@ ohci_set_interrupt(usb_t *dev, uint8_t bit) ohci_update_irq(dev); } +/* Next two functions ported over from QEMU. */ +static int ohci_copy_td_input(usb_t* dev, usb_td_t *td, + uint8_t *buf, int len) +{ + uint32_t ptr, n; + + ptr = td->CBP; + n = 0x1000 - (ptr & 0xfff); + if (n > len) { + n = len; + } + dma_bm_write(ptr, buf, n, 1); + if (n == len) { + return 0; + } + ptr = td->BE & ~0xfffu; + buf += n; + dma_bm_write(ptr, buf, len - n, 1); + return 0; +} + +static int ohci_copy_td_output(usb_t* dev, usb_td_t *td, + uint8_t *buf, int len) +{ + uint32_t ptr, n; + + ptr = td->CBP; + n = 0x1000 - (ptr & 0xfff); + if (n > len) { + n = len; + } + dma_bm_read(ptr, buf, n, 1); + if (n == len) { + return 0; + } + ptr = td->BE & ~0xfffu; + buf += n; + dma_bm_read(ptr, buf, len - n, 1); + return 0; +} + +uint8_t +ohci_service_transfer_desc(usb_t* dev, usb_ed_t* endpoint_desc) +{ + +} + uint8_t ohci_service_endpoint_desc(usb_t* dev, uint32_t head) { usb_ed_t endpoint_desc; + uint8_t active = 0; + uint32_t next = 0; + uint32_t cur = 0; + uint32_t limit_counter = 0; + + if (head == 0) + return 0; - return 0; + for (cur = head; cur && limit_counter++ < ENDPOINT_DESC_LIMIT; cur = next) { + dma_bm_read(cur, (uint8_t*)&endpoint_desc, sizeof(usb_ed_t), 4); + + next = endpoint_desc.NextED & ~(0xFu); + + if (endpoint_desc.flags.Skip || endpoint_desc.flags_2.Halted) + continue; + + if (endpoint_desc.flags.Format) { + fatal("OHCI: Isochronous transfers not implemented!\n"); + } + + while ((endpoint_desc.HeadP & ~(0xFu)) != endpoint_desc.TailP) { + ohci_service_transfer_desc(dev, &endpoint_desc); + } + + dma_bm_write(cur, (uint8_t*)&endpoint_desc, sizeof(usb_ed_t), 4); + } + + return active; } void