diff --git a/drivers/usb/uhci/detect.inc b/drivers/usb/uhci/detect.inc index 8ae16f99ab..975f9ed777 100644 --- a/drivers/usb/uhci/detect.inc +++ b/drivers/usb/uhci/detect.inc @@ -41,6 +41,9 @@ bool FindUSBControllers() hc->pciId = PciRead32(bus,devfn, 0); hc->PciTag = pciTag(bus,(devfn>>3)&0x1F,devfn&0x7); + hc->irq_line = PciRead32(bus,devfn, 0x3C) & 0xFF; + dbgprintf("Host IRQ %d\n", hc->irq_line); + for (i = 0; i < 6; i++) { u32_t base; diff --git a/drivers/usb/uhci/hcd.inc b/drivers/usb/uhci/hcd.inc index 37eff3f31d..986f1b0cb4 100644 --- a/drivers/usb/uhci/hcd.inc +++ b/drivers/usb/uhci/hcd.inc @@ -1,9 +1,12 @@ #define UHCI_USBLEGSUP 0x00c0 /* legacy support */ -#define UHCI_USBCMD 0 /* command register */ -#define UHCI_USBINTR 4 /* interrupt register */ +#define UHCI_USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ #define UHCI_USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ #define UHCI_USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ + + +#define UHCI_USBCMD 0 /* command register */ +#define UHCI_USBINTR 4 /* interrupt register */ #define UHCI_USBCMD_RUN 0x0001 /* RUN/STOP bit */ #define UHCI_USBCMD_HCRESET 0x0002 /* Host Controller reset */ #define UHCI_USBCMD_EGSM 0x0008 /* Global Suspend Mode */ @@ -117,12 +120,38 @@ reset_needed: return 1; } +void hc_interrupt() +{ + hc_t *hc; + + printf("USB interrupt\n"); + + hc = (hc_t*)hc_list.next; + + while( &hc->list != &hc_list) + { + hc_t *tmp; + u16_t status; + + tmp = hc; + hc = (hc_t*)hc->list.next; + + status = in16(tmp->iobase + USBSTS); + if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */ + continue; + out16(tmp->iobase + USBSTS, status); /* Clear it */ + } + +}; + + bool init_hc(hc_t *hc) { int port; u32_t ifl; u16_t dev_status; + td_t *td; int i; dbgprintf("\n\ninit uhci %x\n\n", hc->pciId); @@ -166,18 +195,42 @@ bool init_hc(hc_t *hc) hc->frame_dma = GetPgAddr(hc->frame_base); hc->frame_number = 0; + + for (i = 0; i < UHCI_NUM_SKELQH; i++) + { qh_t *qh = alloc_qh(); qh->qlink = 1; qh->qelem = 1; - hc->qh1 = qh; + hc->qh[i] = qh; + } + for (i = SKEL_ISO + 1; i < SKEL_ASYNC; ++i) + hc->qh[i]->qlink = hc->qh[SKEL_ASYNC]->dma | 2; - // dbgprintf("alloc qh %x dma %x\n", qh, qh->dma); +/* + td = alloc_td(); - for(i=0; i<1024; i++) - hc->frame_base[i] = qh->dma | 2; + td->link = 1; + td->status = (1<<24) | (1<<23) ; + td->token = TOKEN( 0x7FF, DATA0, 0, 0, 0xE1); + td->buffer = 0; + td->bk = NULL; +*/ + for (i = 0; i < 1024; i++) + { + int qnum; + + qnum = 8 - (int) __bsf( i | 1024); + + if (qnum <= 1) + qnum = 9; + + hc->frame_base[i] = hc->qh[qnum]->dma | 2; + } + + mb(); /* Set the frame length to the default: 1 ms exactly */ out8(hc->iobase + USBSOF, USBSOF_DEFAULT); @@ -189,6 +242,13 @@ bool init_hc(hc_t *hc) out16(hc->iobase + USBFRNUM, 0); out16(hc->iobase + USBSTS, 0x3F); + + out16(hc->iobase + UHCI_USBINTR, 4); + + AttachIntHandler(hc->irq_line, hc_interrupt, 0); + + pciWriteWord(hc->PciTag, UHCI_USBLEGSUP, UHCI_USBLEGSUP_DEFAULT); + out16(hc->iobase + USBCMD, USBCMD_RS | USBCMD_CF | USBCMD_MAXP); @@ -347,7 +407,7 @@ request_t *create_request(udev_t *dev, endp_t *enp, u32_t dir, if( td_prev ) td_prev->link = td->dma | 4; - td->status = 0x00800000 | dev->speed; + td->status = TD_CTRL_ACTIVE | dev->speed; td->token = TOKEN(packet_size,enp->toggle,enp->address, dev->addr,dir); td->buffer = data_dma; @@ -358,17 +418,10 @@ request_t *create_request(udev_t *dev, endp_t *enp, u32_t dir, data_dma+= packet_size; size-= packet_size; enp->toggle ^= DATA1; - } + }; + + td->status |= TD_CTRL_IOC; rq->td_tail = td; -/* - dbgprintf("create request %x\n" - "head %x\n" - "tail %x\n" - "data %x\n" - "size %x\n", - rq, rq->td_head, rq->td_tail, - rq->data, rq->size); -*/ return rq; } @@ -405,7 +458,7 @@ bool ctrl_request(udev_t *dev, void *req, u32_t pid, td = alloc_td(); td_prev->link = td->dma | 4; - td->status = 0x00800000 | dev->speed; + td->status = TD_CTRL_ACTIVE | dev->speed; td->token = TOKEN(packet_size, toggle, 0,dev->addr, pid); td->buffer = data_dma; td->bk = td_prev; @@ -423,15 +476,17 @@ bool ctrl_request(udev_t *dev, void *req, u32_t pid, pid = (pid == DIN) ? DOUT : DIN; td->link = 1; - td->status = 0x00800000 | dev->speed; + td->status = TD_CTRL_ACTIVE | TD_CTRL_IOC | dev->speed ; td->token = (0x7FF<<21)|DATA1|(dev->addr<<8)|pid; td->buffer = 0; td->bk = td_prev; - qh = dev->host->qh1; + qh = dev->host->qh[SKEL_ASYNC]; qh->qelem = td0->dma; - __asm__ __volatile__ ("":::"memory"); + + mb(); + // __asm__ __volatile__ ("":::"memory"); count_t timeout = 25; while(timeout--){ diff --git a/drivers/usb/uhci/hid.inc b/drivers/usb/uhci/hid.inc index 265cb74e45..698d5b73b1 100644 --- a/drivers/usb/uhci/hid.inc +++ b/drivers/usb/uhci/hid.inc @@ -112,7 +112,7 @@ bool mouse_handler(udev_t *dev, struct tag_request *rq) pkt = (struct boot_packet *)rq->data; SetMouseData(pkt->buttons, pkt->x, -pkt->y, -pkt->z, 0); }; - td->status = 0x00800000 | dev->speed; + td->status = TD_CTRL_ACTIVE | TD_CTRL_IOC | dev->speed; td->token ^= DATA1; return true; @@ -145,6 +145,7 @@ void create_hid_mouse(udev_t *dev, endpoint_descr_t *en_d) packet = kzalloc(enp.size, 0); rq = create_request(dev, &enp, DIN, packet, enp.size); + rq->qnum = 6; rq->handler = &mouse_handler; list_add_tail(&rq->list, &rq_list); diff --git a/drivers/usb/uhci/usb.c b/drivers/usb/uhci/usb.c index 68afba4e4e..365a610ae6 100644 --- a/drivers/usb/uhci/usb.c +++ b/drivers/usb/uhci/usb.c @@ -113,11 +113,12 @@ u32_t drvEntry(int action, char *cmdline) td = rq->td_head; dev = rq->dev; - qh = dev->host->qh1; + qh = dev->host->qh[rq->qnum]; qh->qelem = td->dma; - __asm__ __volatile__ ("":::"memory"); + mb(); + rq = (request_t*)rq->list.next; }; diff --git a/drivers/usb/uhci/usb.h b/drivers/usb/uhci/usb.h index e04283f79f..30c590cf71 100644 --- a/drivers/usb/uhci/usb.h +++ b/drivers/usb/uhci/usb.h @@ -38,6 +38,23 @@ typedef struct }qh_t __attribute__((aligned(16))); + +#define UHCI_NUM_SKELQH 11 + +#define SKEL_ISO 1 +#define SKEL_ASYNC 9 + +/* +#define QH_1 0 +#define QH_2 1 +#define QH_4 2 +#define QH_8 3 +#define QH_16 4 +#define QH_32 5 +#define QH_64 6 +*/ + + typedef struct { list_t list; @@ -48,7 +65,7 @@ typedef struct count_t frame_number; addr_t frame_dma; - qh_t *qh1; + qh_t *qh[UHCI_NUM_SKELQH]; u32_t *data; addr_t data_dma; @@ -63,6 +80,7 @@ typedef struct addr_t memBase[6]; size_t memSize[6]; u32_t memType[6]; + u32_t irq_line; }hc_t; typedef struct tag_td @@ -214,6 +232,7 @@ typedef struct tag_request size_t size; udev_t *dev; u32_t type; + int qnum; bool (*handler)(udev_t *dev, struct tag_request *rq); }request_t; @@ -248,3 +267,13 @@ struct boot_packet #define DATA0 (0<<19) #define DATA1 (1<<19) + + +static inline u32_t __bsf(u32_t val) +{ + asm("bsf %1,%0" + :"=r" (val) + :"rm" (val)); + return val; +} +