Warning, cross-references for /kernel/drivers/usb/uhci_hcd.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <smp/apic.h>
0019 #include <drivers/usb/usb.h>
0020 #include <drivers/usb/uhci.h>
0021 #include <util/printf.h>
0022 #include <mem/virtual.h>
0023 #include <mem/pow2.h>
0024 #include <arch/i386-div64.h>
0025 #include <kernel.h>
0026 #include "sched/sched.h"
0027
0028 #define DEBUG_UHCI
0029
0030
0031 #ifdef DEBUG_UHCI
0032 #define DLOG(fmt,...) DLOG_PREFIX("UHCI",fmt,##__VA_ARGS__)
0033 #else
0034 #define DLOG(fmt,...) ;
0035 #endif
0036
0037 #ifdef DEBUG_UHCI_VERBOSE
0038 #define DLOGV(fmt,...) DLOG_PREFIX("UHCI",fmt,##__VA_ARGS__)
0039 #else
0040 #define DLOGV(fmt,...) ;
0041 #endif
0042
0043 static int bus;
0044 static int dev;
0045 static int func;
0046
0047 static uint32 uhci_irq_handler (uint8 vec);
0048
0049
0050 static uint32_t usb_base = 0x0;
0051
0052
0053 static frm_lst_ptr frame_list[1024] ALIGNED(0x1000);
0054 static UHCI_TD td[TD_POOL_SIZE] ALIGNED(0x1000);
0055 static UHCI_QH qh[QH_POOL_SIZE] ALIGNED(0x10);
0056 static frm_lst_ptr *phys_frm;
0057 static UHCI_QH *int_qh = 0;
0058 static UHCI_QH *ctl_qh = 0;
0059 static UHCI_QH *blk_qh = 0;
0060 static uint32 toggles[128];
0061
0062 uint32 td_phys, qh_phys;
0063
0064
0065 #define TD_V2P(ty,p) ((ty)((((uint) (p)) - ((uint) td))+td_phys))
0066 #define QH_V2P(ty,p) ((ty)((((uint) (p)) - ((uint) qh))+qh_phys))
0067
0068 #define TD_P2V(ty,p) ((ty)((((uint) (p)) - td_phys)+((uint) td)))
0069 #define QH_P2V(ty,p) ((ty)((((uint) (p)) - qh_phys)+((uint) qh)))
0070
0071 static task_id uhci_waitq = 0;
0072
0073 #define TERMINATE 1
0074 #define SELECT_TD 0
0075 #define SELECT_QH 2
0076 #define DEPTH_FIRST 4
0077 #define LINK_MASK (~0xFL)
0078
0079
0080
0081
0082
0083
0084
0085 static void *
0086 sched_alloc (int type)
0087 {
0088 int i = 0;
0089
0090 switch (type) {
0091 case TYPE_TD:
0092 for (i = 0; i < TD_POOL_SIZE; i++) {
0093 if (td[i].link_ptr == 0) {
0094 td[i].link_ptr = TERMINATE;
0095 return &td[i];
0096 }
0097 }
0098 break;
0099
0100 case TYPE_QH:
0101 for (i = 0; i < QH_POOL_SIZE; i++) {
0102 if (qh[i].qh_ptr == 0 && qh[i].qe_ptr == 0) {
0103 qh[i].qh_ptr = qh[i].qe_ptr = TERMINATE;
0104 return &qh[i];
0105 }
0106 }
0107 break;
0108
0109 default:
0110 DLOG("Unsupported Descriptor Type: %d", type);
0111 return (void *) 0;
0112
0113 }
0114
0115 DLOG("Error! Not enough descriptor in the pool! (type=%s)",
0116 (type == TYPE_TD ? "TD" : "QH"));
0117 return (void *) 0;
0118 }
0119
0120 static int
0121 sched_free (int type, void *res)
0122 {
0123 UHCI_TD *res_td;
0124 UHCI_QH *res_qh;
0125
0126 switch (type) {
0127 case TYPE_TD:
0128 res_td = (UHCI_TD *) res;
0129 res_td->link_ptr = 0;
0130 res_td->raw2 = 0;
0131 res_td->raw3 = 0;
0132 res_td->buf_ptr = 0;
0133 res_td->buf_vptr = 0;
0134 res_td->call_back = 0;
0135 break;
0136
0137 case TYPE_QH:
0138 res_qh = (UHCI_QH *) res;
0139 res_qh->qh_ptr = 0;
0140 res_qh->qe_ptr = 0;
0141 break;
0142
0143 default:
0144 return -1;
0145 }
0146
0147 return 0;
0148 }
0149
0150
0151 static int
0152 free_tds (UHCI_TD * tds, int len)
0153 {
0154 int count = 0, i = 0, end = 0;
0155 uint32 link_ptr;
0156
0157 for (i = 0; i < len; i++) {
0158 link_ptr = tds->link_ptr;
0159
0160 if (tds->link_ptr & TERMINATE) {
0161 end++;
0162 }
0163
0164 sched_free (TYPE_TD, tds);
0165 count++;
0166
0167 if (end)
0168 break;
0169
0170 tds = TD_P2V (UHCI_TD *, link_ptr & LINK_MASK);
0171 }
0172
0173 return count;
0174 }
0175
0176 static void
0177 disable_ehci (void)
0178 {
0179 int func = 0x7;
0180 uint32_t pa_ubase = 0;
0181 unsigned long eecp = 0;
0182 uint32_t va_ubase = 0;
0183 uint32_t opregs = 0;
0184 uint32_t config_flag = 0;
0185 uint8_t hcbiossem = 0;
0186
0187 DLOG ("EHCI: Routing all ports to companion controllers...");
0188
0189
0190 pa_ubase = pci_config_rd32 (bus, dev, func, 0x10);
0191 pa_ubase = pa_ubase & 0xFFFFFF00;
0192
0193
0194 va_ubase = (uint32_t) map_virtual_page ((pa_ubase & 0xFFFFF000) + 0x3);
0195 va_ubase += (pa_ubase & 0x0FFF);
0196
0197 #if 0
0198 DLOG ("EHCI Base Phys=%p Base Virt=%p", pa_ubase, va_ubase);
0199 #endif
0200
0201 eecp = (*((unsigned int *) (((char *) va_ubase) + 0x08)) & 0x0FF00) >> 8;
0202
0203 #if 0
0204 DLOG ("EECP=%p", eecp);
0205 #endif
0206
0207 hcbiossem = pci_config_rd8 (bus, dev, func, eecp + 0x02) & 0x01;
0208 DLOG ("HC BIOS SEM: %p", hcbiossem);
0209 pci_config_wr8 (bus, dev, func, eecp + 0x03, 0x01);
0210
0211 for (;;) {
0212 if (((pci_config_rd8 (bus, dev, func, eecp + 0x02) & 0x01) == 0x0) &&
0213 ((pci_config_rd8 (bus, dev, func, eecp + 0x03) & 0x01)) == 0x01)
0214 break;
0215 }
0216
0217 DLOG ("Quest got ownership of EHCI!");
0218
0219 opregs = va_ubase + *(char *) va_ubase;
0220 config_flag = *((uint32_t *) ((char *) opregs + 0x40));
0221
0222
0223 *((uint32_t *) ((char *) opregs + 0x40)) = 0x0;
0224 delay (100);
0225 }
0226
0227 static void
0228 init_schedule (void)
0229 {
0230 UHCI_QH *q;
0231 int i = 0;
0232
0233 phys_frm = (frm_lst_ptr *) get_phys_addr ((void *) frame_list);
0234
0235 for (i = 0; i < 1024; i++) {
0236 frame_list[i] = TERMINATE;
0237 }
0238
0239 memset ((void *) td, 0, 32 * TD_POOL_SIZE);
0240 memset ((void *) qh, 0, 16 * QH_POOL_SIZE);
0241
0242 int_qh = sched_alloc (TYPE_QH);
0243 ctl_qh = sched_alloc (TYPE_QH);
0244 blk_qh = sched_alloc (TYPE_QH);
0245
0246
0247 int_qh->qh_ptr =
0248 (((uint32_t) get_phys_addr ((void *) ctl_qh)) & LINK_MASK) + SELECT_QH;
0249 int_qh->qe_ptr = TERMINATE;
0250
0251
0252 ctl_qh->qh_ptr =
0253 (((uint32_t) get_phys_addr ((void *) blk_qh)) & LINK_MASK) + SELECT_QH;
0254 ctl_qh->qe_ptr = TERMINATE;
0255
0256
0257 blk_qh->qh_ptr = TERMINATE;
0258 blk_qh->qe_ptr = TERMINATE;
0259
0260
0261 q = sched_alloc (TYPE_QH);
0262 q->qh_ptr = qh->qe_ptr = TERMINATE;
0263
0264 blk_qh->qe_ptr =
0265 (((uint32_t) get_phys_addr ((void *) q)) & LINK_MASK) + SELECT_QH;
0266
0267 blk_qh = q;
0268
0269 #if 0
0270 DLOG ("int_qh va=%p ctl_qh va=%p qhp va=%p",
0271 int_qh, ctl_qh, qh);
0272 #endif
0273
0274 #if 0
0275 DLOG ("frame_list va=%p pa=%p", frame_list, phys_frm);
0276 #endif
0277
0278
0279 for (i = 0; i < 1024; i++) {
0280 frame_list[i] =
0281 (((uint32_t) get_phys_addr ((void *) int_qh)) & LINK_MASK) + SELECT_QH;
0282 }
0283 }
0284
0285 static void
0286 debug_dump_sched (UHCI_TD * tx_tds)
0287 {
0288
0289
0290 for (;;) {
0291 DLOG ("TD dump: %p %p %p %p %p",
0292 tx_tds->link_ptr, tx_tds->raw2, tx_tds->raw3,
0293 tx_tds->buf_ptr, tx_tds->buf_vptr);
0294 DLOG (" act_len=%d status=%p ioc=%d iso=%d ls=%d c_err=%d spd=%d",
0295 tx_tds->act_len, tx_tds->status, tx_tds->ioc, tx_tds->iso,
0296 tx_tds->ls, tx_tds->c_err, tx_tds->spd);
0297 DLOG (" pid=0x%.02X addr=%d ep=%d tog=%d max_len=%d",
0298 tx_tds->pid, tx_tds->addr, tx_tds->endp, tx_tds->toggle, tx_tds->max_len);
0299 #if 0
0300 if (tx_tds->buf_vptr) {
0301 uint32 *p = (uint32 *)tx_tds->buf_vptr;
0302 DLOG (" %.08X %.08X %.08X %.08X",
0303 p[0], p[1], p[2], p[3]);
0304 }
0305 #endif
0306 if (tx_tds->link_ptr & TERMINATE) break;
0307 if (tx_tds->link_ptr == 0) break;
0308 tx_tds = TD_P2V (UHCI_TD *, tx_tds->link_ptr & LINK_MASK);
0309 }
0310 }
0311
0312
0313
0314
0315
0316
0317 static void
0318 fixup_tds (u32 *p_tdp)
0319 {
0320 while (!(*p_tdp & TERMINATE) && *p_tdp) {
0321 UHCI_TD *t = TD_P2V (UHCI_TD *, (*p_tdp) & LINK_MASK);
0322 if (t->status == 0)
0323 *p_tdp = t->link_ptr & (~DEPTH_FIRST);
0324 else
0325 break;
0326 p_tdp = &t->link_ptr;
0327 }
0328 }
0329
0330 static u64 uhci_bytes = 0, uhci_timestamps = 0;
0331
0332 extern u32
0333 uhci_sample_bps (void)
0334 {
0335 extern u32 tsc_freq_msec;
0336 u64 uhci_msec = div64_64 (uhci_timestamps, (u64) tsc_freq_msec);
0337 u32 bytes_sec = 0;
0338 if (uhci_msec)
0339 bytes_sec = (u32) div64_64 (uhci_bytes * 1000, uhci_msec);
0340 uhci_bytes = 0;
0341 uhci_timestamps = 0;
0342 return bytes_sec;
0343 }
0344
0345 extern void
0346 debug_dump_bulk_qhs (void)
0347 {
0348 UHCI_QH *q = blk_qh;
0349 uint32 link_ptr;
0350 DLOG ("cmd=0x%.04X sts=0x%.04X frame=%d bps=%d",
0351 GET_USBCMD (usb_base), GET_USBSTS (usb_base), GET_FRNUM (usb_base),
0352 uhci_sample_bps ());
0353 for (;;) {
0354 link_ptr = q->qe_ptr;
0355 if (link_ptr & TERMINATE) {
0356 DLOG ("QH %p has no TDs", q);
0357 } else {
0358 DLOG ("QH %p has TD %p:", q, q->qe_ptr);
0359 debug_dump_sched (TD_P2V (UHCI_TD *, q->qe_ptr & LINK_MASK));
0360 }
0361 fixup_tds (&q->qe_ptr);
0362 link_ptr = q->qh_ptr;
0363 if (link_ptr & TERMINATE)
0364 break;
0365 q = QH_P2V (UHCI_QH *, link_ptr & LINK_MASK);
0366 }
0367 }
0368
0369 static int
0370 check_tds (UHCI_QH *tx_qh, UHCI_TD *tx_tds, uint32 *act_len)
0371 {
0372 int status_count = 1;
0373 int status = 0;
0374 int len = 0;
0375
0376 while (status_count) {
0377 UHCI_TD *tds = tx_tds;
0378 status_count = 0;
0379
0380 fixup_tds (&tx_qh->qe_ptr);
0381
0382
0383 if (mp_enabled) {
0384 DLOGV ("wait %d", status_count);
0385 queue_append (&uhci_waitq, str ());
0386 schedule ();
0387 }
0388
0389 len = 0;
0390 while (tds != TD_P2V (UHCI_TD *, 0)) {
0391 if (tds->status & 0x80) {
0392 status_count++;
0393 } else {
0394 len += (tds->act_len + 1) & 0x7FF;
0395
0396 if (tds->act_len != tds->max_len) {
0397 DLOG ("Short Packet! after %d bytes", len);
0398 #if 1
0399 *act_len = len;
0400 return status;
0401 #else
0402 debug_dump_sched (tx_tds);
0403 #endif
0404 }
0405 }
0406
0407
0408 if (tds->status & 0x40) {
0409 status = tds->status & 0x7F;
0410
0411 debug_dump_sched (tx_tds);
0412
0413 return status;
0414 }
0415
0416
0417 if (tds->status & 0x04) {
0418 status = tds->status & 0x7F;
0419 return status;
0420 }
0421
0422 #if 0
0423
0424 if (tds->status & 0x08) {
0425 DLOG ("NAK! after %d bytes", len);
0426 *act_len = len;
0427 return status;
0428 }
0429 #endif
0430
0431
0432 tds = TD_P2V (UHCI_TD *, tds->link_ptr & LINK_MASK);
0433 }
0434 }
0435
0436 *act_len = len;
0437 return status;
0438 }
0439
0440 int
0441 port_reset (uint8_t port)
0442 {
0443 uint16_t portsc = 0;
0444 switch (port) {
0445 case 0:
0446 portsc = GET_PORTSC0 (usb_base);
0447 SET_PORTSC0 (usb_base, portsc | 0x0200);
0448 delay (10);
0449 SET_PORTSC0 (usb_base, portsc & ~0x0200);
0450 delay (1);
0451 SET_PORTSC0 (usb_base, portsc | 0x0004);
0452 delay (50);
0453 break;
0454
0455 case 1:
0456 portsc = GET_PORTSC1 (usb_base);
0457 SET_PORTSC1 (usb_base, portsc | 0x0200);
0458 delay (10);
0459 SET_PORTSC1 (usb_base, portsc & ~0x0200);
0460 delay (1);
0461 SET_PORTSC1 (usb_base, portsc | 0x0004);
0462 delay (50);
0463 break;
0464
0465 default:
0466 return -1;
0467 }
0468
0469 return 0;
0470 }
0471
0472 int
0473 uhci_reset (void)
0474 {
0475 if (usb_base == 0)
0476 return -1;
0477
0478
0479 SET_USBCMD (usb_base, 0x0004);
0480 delay (100);
0481 SET_USBCMD (usb_base, 0x0000);
0482 delay (100);
0483
0484 SET_USBINTR (usb_base, 0x0F);
0485 SET_PCICMD (bus, dev, func, GET_PCICMD (bus, dev, func) & 0xFBFF);
0486
0487
0488 SET_FRBASEADD (usb_base, (uint32_t) phys_frm);
0489
0490 SET_SOFMOD (usb_base, 0x40);
0491
0492 SET_FRNUM (usb_base, 0x0);
0493
0494 SET_USBCMD (usb_base, 0x0001);
0495
0496 return 0;
0497 }
0498
0499 #define USB_MAX_DEVICES 32
0500 static USB_DEVICE_INFO devinfo[USB_MAX_DEVICES+1];
0501 static uint next_address = 1;
0502
0503 #define USB_MAX_DEVICE_DRIVERS 32
0504 static USB_DRIVER drivers[USB_MAX_DEVICE_DRIVERS];
0505 static uint num_drivers = 0;
0506
0507 void
0508 find_device_driver (USB_DEVICE_INFO *info, USB_CFG_DESC *cfgd, USB_IF_DESC *ifd)
0509 {
0510 int d;
0511 for (d=0; d<num_drivers; d++) {
0512 if (drivers[d].probe (info, cfgd, ifd))
0513 return;
0514 }
0515 }
0516
0517 void
0518 dlog_devd (USB_DEV_DESC *devd)
0519 {
0520 DLOG ("DEVICE DESCRIPTOR len=%d type=%d bcdUSB=0x%x",
0521 devd->bLength, devd->bDescriptorType, devd->bcdUSB);
0522 DLOG (" class=0x%x subclass=0x%x proto=0x%x maxpkt0=%d",
0523 devd->bDeviceClass, devd->bDeviceSubClass, devd->bDeviceProtocol,
0524 devd->bMaxPacketSize0);
0525 DLOG (" vendor=0x%x product=0x%x bcdDevice=0x%x numcfgs=%d",
0526 devd->idVendor, devd->idProduct, devd->bcdDevice,
0527 devd->bNumConfigurations);
0528 }
0529
0530 void
0531 dlog_info (USB_DEVICE_INFO *info)
0532 {
0533 DLOG ("ADDRESS %d", info->address);
0534 dlog_devd (&info->devd);
0535
0536 #if 0
0537 uint8 strbuf[64];
0538 uint8 str[32];
0539 #define do_str(slot,label) \
0540 if (info->devd.slot != 0 && \
0541 uhci_get_string (info->address, info->devd.slot, 0, \
0542 sizeof (strbuf), strbuf, \
0543 info->devd.bMaxPacketSize0) \
0544 == 0) { \
0545 memset (str, 0, sizeof (str)); \
0546 if (uhci_interp_string ((USB_STR_DESC *)strbuf, sizeof (strbuf), 0, \
0547 str, sizeof (str)-1) > 0) { \
0548 DLOG (" "label": %s", str); \
0549 } \
0550 }
0551
0552 do_str (iManufacturer, "Manufacturer");
0553 do_str (iProduct, "Product");
0554 #undef do_str
0555 #endif
0556 }
0557
0558
0559 bool
0560 uhci_enumerate (void)
0561 {
0562 USB_DEV_DESC devd;
0563 USB_CFG_DESC *cfgd;
0564 USB_IF_DESC *ifd;
0565 #define TEMPSZ 256
0566 uint8 temp[TEMPSZ], *ptr;
0567 uint curdev = next_address;
0568 sint status, c, i, total_length=0;
0569 USB_DEVICE_INFO *info;
0570
0571 if (curdev > USB_MAX_DEVICES) {
0572 DLOG ("uhci_enumerate: too many devices");
0573 return FALSE;
0574 }
0575
0576 DLOG ("uhci_enumerate: curdev=%d", curdev);
0577
0578
0579 info = &devinfo[curdev];
0580 memset (info, 0, sizeof (USB_DEVICE_INFO));
0581 info->address = 0;
0582 info->host_type = USB_TYPE_HC_UHCI;
0583
0584
0585
0586
0587
0588
0589
0590
0591 info->devd.bMaxPacketSize0 = 64;
0592
0593 memset (&devd, 0, sizeof (USB_DEV_DESC));
0594
0595
0596 status = usb_get_descriptor (info, USB_TYPE_DEV_DESC, 0, 0,
0597 sizeof (USB_DEV_DESC), &devd);
0598 if (status != 0)
0599 goto abort;
0600
0601 if (devd.bMaxPacketSize0 == 8) {
0602
0603 info->devd.bMaxPacketSize0 = 8;
0604 status = usb_get_descriptor (info, USB_TYPE_DEV_DESC, 0, 0,
0605 sizeof (USB_DEV_DESC), &devd);
0606 if (status != 0)
0607 goto abort;
0608 }
0609
0610 if (devd.bNumConfigurations == 255)
0611 devd.bNumConfigurations = 1;
0612
0613
0614 memcpy (&info->devd, &devd, sizeof (USB_DEV_DESC));
0615
0616
0617 if (usb_set_address (info, curdev) != 0)
0618 goto abort;
0619 DLOG ("uhci_enumerate: set (0x%x, 0x%x, 0x%x) to addr %d",
0620 devd.bDeviceClass, devd.idVendor, devd.idProduct, curdev);
0621 delay (2);
0622
0623 DLOG ("uhci_enumerate: num configs=%d", devd.bNumConfigurations);
0624
0625
0626 info->address = curdev;
0627
0628 dlog_info (info);
0629
0630 for (c=0; c<devd.bNumConfigurations; c++) {
0631
0632 memset (temp, 0, TEMPSZ);
0633 status = usb_get_descriptor (info, USB_TYPE_CFG_DESC, c, 0,
0634 sizeof (USB_CFG_DESC), temp);
0635 if (status != 0) {
0636 DLOG ("uhci_enumerate: failed to get config descriptor for c=%d", c);
0637 goto abort;
0638 }
0639
0640 cfgd = (USB_CFG_DESC *)temp;
0641 DLOG ("uhci_enumerate: c=%d cfgd->wTotalLength=%d", c, cfgd->wTotalLength);
0642 total_length += cfgd->wTotalLength;
0643 }
0644
0645 DLOG ("uhci_enumerate: total_length=%d", total_length);
0646
0647
0648 pow2_alloc (total_length, &info->raw);
0649 if (!info->raw) {
0650 DLOG ("uhci_enumerate: pow2_alloc (%d) failed", total_length);
0651 goto abort;
0652 }
0653
0654
0655 ptr = info->raw;
0656 for (c=0; c<devd.bNumConfigurations; c++) {
0657
0658 memset (temp, 0, TEMPSZ);
0659 status = usb_get_descriptor (info, USB_TYPE_CFG_DESC, c, 0,
0660 sizeof (USB_CFG_DESC), temp);
0661 if (status != 0) {
0662 DLOG ("uhci_enumerate: failed to get config descriptor for c=%d", c);
0663 goto abort_mem;
0664 }
0665 cfgd = (USB_CFG_DESC *)temp;
0666
0667
0668 status =
0669 usb_get_descriptor (info, USB_TYPE_CFG_DESC, c, 0, cfgd->wTotalLength, ptr);
0670 if (status != 0)
0671 goto abort_mem;
0672
0673 cfgd = (USB_CFG_DESC *)ptr;
0674 DLOG ("uhci_enumerate: cfg %d has num_if=%d", c, cfgd->bNumInterfaces);
0675 ptr += cfgd->wTotalLength;
0676 }
0677
0678
0679 next_address++;
0680
0681
0682 ptr = info->raw;
0683 for (c=0; c<devd.bNumConfigurations; c++) {
0684 cfgd = (USB_CFG_DESC *) ptr;
0685 ptr += cfgd->bLength;
0686 for (i=0; i<cfgd->bNumInterfaces; i++) {
0687
0688 for (ifd = (USB_IF_DESC *) ptr;
0689 ifd->bDescriptorType != USB_TYPE_IF_DESC;
0690 ifd = (USB_IF_DESC *)((uint8 *)ifd + ifd->bLength)) {
0691
0692 }
0693 ptr = (uint8 *) ifd;
0694 DLOG ("uhci_enumerate: examining (%d, %d) if_class=0x%X sub=0x%X proto=0x%X #endp=%d",
0695 c, i, ifd->bInterfaceClass,
0696 ifd->bInterfaceSubClass,
0697 ifd->bInterfaceProtocol,
0698 ifd->bNumEndpoints);
0699
0700
0701 find_device_driver (info, cfgd, ifd);
0702
0703 ptr += ifd->bLength;
0704 }
0705 ptr = ((uint8 *)cfgd) + cfgd->wTotalLength;
0706 }
0707
0708
0709
0710 return TRUE;
0711
0712 abort_mem:
0713 pow2_free (info->raw);
0714 abort:
0715 return FALSE;
0716 }
0717
0718 bool
0719 usb_register_driver (USB_DRIVER *driver)
0720 {
0721 if (num_drivers >= USB_MAX_DEVICE_DRIVERS) return FALSE;
0722 memcpy (&drivers[num_drivers], driver, sizeof (USB_DRIVER));
0723 num_drivers++;
0724 return TRUE;
0725 }
0726
0727 static bool uhci_operational = FALSE;
0728 bool
0729 usb_do_enumeration (void)
0730 {
0731 int i;
0732 #include <drivers/usb/usb_tests.h>
0733 if (!uhci_operational) return FALSE;
0734 DLOG ("begin enumeration");
0735
0736 for (i=0;i<2;i++) {
0737 port_reset (i);
0738
0739 uhci_enumerate ();
0740 show_usb_regs (bus, dev, func);
0741 }
0742 DLOG ("end enumeration");
0743 return TRUE;
0744 }
0745
0746 static uint irq_line;
0747
0748 bool
0749 uhci_init (void)
0750 {
0751 uint i, device_index, irq_pin;
0752 pci_device uhci_device;
0753 pci_irq_t irq;
0754
0755 memset (toggles, 0, sizeof (toggles));
0756
0757 if (mp_ISA_PC) {
0758 DLOG ("Cannot operate without PCI");
0759 return FALSE;
0760 }
0761
0762
0763 device_index = ~0;
0764 i=0;
0765 while (pci_find_device (0xFFFF, 0xFFFF, 0x0C, 0x03, i, &i)) {
0766 if (pci_get_device (i, &uhci_device)) {
0767 if (uhci_device.progIF == 0) {
0768 device_index = i;
0769 break;
0770 }
0771 i++;
0772 } else break;
0773 }
0774
0775 if (device_index == ~0) {
0776 DLOG ("Unable to find compatible device on PCI bus");
0777 return FALSE;
0778 }
0779
0780 if (!pci_get_device (device_index, &uhci_device)) {
0781 DLOG ("Unable to get PCI device from PCI subsystem");
0782 return FALSE;
0783 }
0784
0785 bus = uhci_device.bus;
0786 dev = uhci_device.slot;
0787 func = uhci_device.func;
0788
0789 DLOG ("Using PCI bus=%x dev=%x func=%x", bus, dev, func);
0790
0791 if (!pci_get_interrupt (device_index, &irq_line, &irq_pin)) {
0792 DLOG ("Unable to get IRQ");
0793 return FALSE;
0794 }
0795
0796 DLOG ("Using IRQ pin=%X", irq_pin);
0797
0798 if (pci_irq_find (bus, dev, irq_pin, &irq)) {
0799
0800 DLOG ("Found PCI routing entry irq.gsi=0x%x", irq.gsi);
0801 if (!pci_irq_map_handler (&irq, uhci_irq_handler, 0x01,
0802 IOAPIC_DESTINATION_LOGICAL,
0803 IOAPIC_DELIVERY_FIXED)) {
0804 DLOG ("Unable to map IRQ handler");
0805 return FALSE;
0806 }
0807 irq_line = irq.gsi;
0808 }
0809
0810 td_phys = (uint32) get_phys_addr ((void *) td);
0811 qh_phys = (uint32) get_phys_addr ((void *) qh);
0812 DLOG ("td@%p td_phys@%p qh@%p qh_phys@%p",
0813 td, td_phys, qh, qh_phys);
0814
0815
0816 if (uhci_device.device != 0x7020)
0817 disable_ehci ();
0818
0819
0820 DLOG ("UHCI LEGSUP: %p", GET_LEGACY (bus, dev, func));
0821 SET_LEGACY(bus, dev, func, 0x2000);
0822 DLOG ("Set PIRQDEN");
0823
0824 if (!pci_decode_bar (device_index, 4, NULL, &usb_base, NULL)) {
0825 DLOG ("unable to decode BAR4");
0826 return FALSE;
0827 }
0828
0829 DLOG ("usb_base=0x%.04X", usb_base);
0830
0831
0832 init_schedule ();
0833
0834 uhci_reset ();
0835
0836 uhci_operational = TRUE;
0837 return TRUE;
0838 }
0839
0840 int
0841 uhci_isochronous_transfer (
0842 uint8_t address,
0843 uint8_t endpoint,
0844 addr_t data,
0845 int data_len,
0846 int *act_len,
0847 uint16_t frm,
0848 uint8_t direction,
0849 void (*func)(addr_t))
0850 {
0851 UHCI_TD *iso_td = 0;
0852 UHCI_TD *idx_td = 0;
0853 int max_packet_len = USB_MAX_LEN;
0854 frm_lst_ptr entry = 0;
0855
0856 if ((data_len - 1) > max_packet_len)
0857 return -1;
0858
0859 iso_td = sched_alloc (TYPE_TD);
0860 iso_td->status = 0x80;
0861 iso_td->c_err = 0;
0862 iso_td->ioc = 0;
0863 iso_td->iso = 1;
0864 iso_td->spd = 0;
0865 iso_td->pid = (direction == DIR_IN) ? UHCI_PID_IN : UHCI_PID_OUT;
0866 iso_td->addr = address;
0867 iso_td->endp = endpoint;
0868 iso_td->toggle = 0;
0869 iso_td->max_len = data_len - 1;
0870 iso_td->buf_ptr = (uint32_t) get_phys_addr ((void *) data);
0871 iso_td->buf_vptr = data;
0872 iso_td->call_back = func;
0873
0874 entry = frame_list[frm];
0875
0876 if (!(entry & TERMINATE) && !(entry & SELECT_QH)) {
0877 idx_td = TD_P2V (UHCI_TD *, entry & LINK_MASK);
0878
0879 while (!(idx_td->link_ptr & TERMINATE) && !(idx_td->link_ptr & SELECT_QH)) {
0880 idx_td = TD_P2V (UHCI_TD *, idx_td->link_ptr & LINK_MASK);
0881 }
0882
0883 iso_td->link_ptr = idx_td->link_ptr;
0884 idx_td->link_ptr =
0885 (uint32_t) get_phys_addr ((void *) iso_td) & LINK_MASK;
0886 } else {
0887 iso_td->link_ptr =
0888 (((uint32_t) get_phys_addr ((void *) int_qh)) & LINK_MASK) + SELECT_QH;
0889 frame_list[frm] = (uint32_t) get_phys_addr ((void *) iso_td) & LINK_MASK;
0890 }
0891
0892
0893
0894 while (iso_td->status & 0x80);
0895
0896 *act_len = iso_td->act_len + 1;
0897 frame_list[frm] = iso_td->link_ptr;
0898 sched_free (TYPE_TD, iso_td);
0899
0900 #if 0
0901 delay (500);
0902 delay (1000);
0903 DLOG ("The status of iso_td: %p ActLen: %p", iso_td->status, iso_td->act_len);
0904 frame_list[frm] = iso_td->link_ptr;
0905 sched_free (TYPE_TD, iso_td);
0906 #endif
0907
0908 return 0;
0909 }
0910
0911
0912 static UHCI_QH *
0913 link_td_to_free_qh (UHCI_QH *q, UHCI_TD *t)
0914 {
0915 for (;;) {
0916
0917 if (q->qe_ptr & TERMINATE) {
0918 q->qe_ptr = TD_V2P (uint32, t) & LINK_MASK;
0919
0920 return q;
0921 }
0922 if (q->qh_ptr & TERMINATE) {
0923 UHCI_QH *newq = sched_alloc (TYPE_QH);
0924 if (newq == NULL) return NULL;
0925 newq->qe_ptr = (TD_V2P (uint32, t) & LINK_MASK) | SELECT_TD;
0926 newq->qh_ptr = TERMINATE;
0927 q->qh_ptr = (QH_V2P (uint32, newq) & LINK_MASK) | SELECT_QH;
0928
0929 return newq;
0930 }
0931
0932
0933 q = QH_P2V (UHCI_QH *, q->qh_ptr & LINK_MASK);
0934 }
0935 }
0936
0937 int
0938 uhci_bulk_transfer(
0939 uint8_t address,
0940 uint8_t endpoint,
0941 addr_t data,
0942 int data_len,
0943 int packet_len,
0944 uint8_t direction,
0945 uint32 *act_len)
0946 {
0947 UHCI_TD *tx_tds = 0;
0948 UHCI_TD *data_td = 0;
0949 UHCI_TD *idx_td = 0;
0950 UHCI_QH *act_qh;
0951 int max_packet_len = ((packet_len - 1) >= USB_MAX_LEN) ? USB_MAX_LEN : packet_len - 1;
0952 int i = 0, num_data_packets = 0, data_left = 0, return_status = 0, tog_idx;
0953
0954 DLOGV ("bulk: %d %d %d %c", address, endpoint, data_len,
0955 direction == DIR_IN ? 'I' : 'O');
0956 num_data_packets = (data_len + max_packet_len) / (max_packet_len + 1);
0957 data_left = data_len;
0958
0959 for(i = 0; i < num_data_packets; i++) {
0960 data_td = sched_alloc(TYPE_TD);
0961 data_td->link_ptr = TERMINATE;
0962 if(tx_tds == 0)
0963 tx_tds = data_td;
0964 else
0965 idx_td->link_ptr = (((uint32_t)get_phys_addr((void*)data_td)) & LINK_MASK) + DEPTH_FIRST;
0966
0967 idx_td = data_td;
0968 data_td->status = 0x80;
0969 data_td->c_err = 3;
0970 data_td->ioc = data_td->iso = 0;
0971 data_td->spd = (direction == DIR_IN ? 1 : 0);
0972
0973 data_td->pid = (direction == DIR_IN) ? UHCI_PID_IN : UHCI_PID_OUT;
0974 data_td->addr = address;
0975 data_td->endp = endpoint;
0976
0977 tog_idx = (address * 32 + (endpoint + ((direction == DIR_IN) << 4)));
0978 data_td->toggle = (BITMAP_TST (toggles, tog_idx) ? 1 : 0);
0979 if (data_td->toggle)
0980 BITMAP_CLR (toggles, tog_idx);
0981 else
0982 BITMAP_SET (toggles, tog_idx);
0983
0984 data_td->max_len = (data_left > (max_packet_len + 1)) ? max_packet_len : data_left - 1;
0985 data_td->buf_ptr = (uint32_t)get_phys_addr((void*)data);
0986 data_td->buf_vptr = data;
0987
0988 if(data_left <= (max_packet_len + 1)) {
0989 data_td->ioc = 1;
0990 break;
0991 } else {
0992 data += (data_td->max_len + 1);
0993 data_left -= (data_td->max_len + 1);
0994 }
0995
0996
0997 if (i == num_data_packets - 1)
0998 data_td->ioc = 1;
0999 }
1000
1001
1002 #if 0
1003 DLOG ("Dumping tx_tds...");
1004 debug_dump_sched (tx_tds);
1005 DLOG ("... done");
1006 #endif
1007
1008
1009 act_qh = link_td_to_free_qh (blk_qh, tx_tds);
1010
1011 if (act_qh == NULL) {
1012 DLOG ("act_qh == NULL");
1013 return -1;
1014 }
1015
1016 u64 start, finish;
1017
1018 RDTSC (start);
1019
1020
1021 return_status = check_tds(act_qh, tx_tds, act_len);
1022 if (return_status != 0) {
1023 DLOG ("bulk: return_status != 0");
1024 } else {
1025 DLOGV ("complete: %d len %d", return_status, *act_len);
1026 }
1027
1028 RDTSC (finish);
1029
1030 if (return_status == 0) {
1031 uhci_bytes += *act_len;
1032 uhci_timestamps += finish - start;
1033 }
1034
1035
1036 if (*act_len != data_len)
1037 act_qh->qe_ptr = TERMINATE;
1038
1039 free_tds(tx_tds, num_data_packets);
1040
1041 return return_status;
1042 }
1043
1044 int
1045 uhci_control_transfer (
1046 uint8_t address,
1047 addr_t setup_req,
1048 int setup_len,
1049 addr_t setup_data,
1050 int data_len,
1051 int packet_len)
1052 {
1053 UHCI_TD *tx_tds = 0;
1054 UHCI_TD *td_idx = 0;
1055 UHCI_TD *status_td = 0;
1056 UHCI_TD *data_td = 0;
1057 int i = 0, num_data_packets = 0, data_left = 0, return_status = 0;
1058 uint8_t pid = 0, toggle = 0;
1059 addr_t data = 0;
1060
1061 uint8_t endpoint = 0;
1062 uint32_t act_len;
1063
1064
1065
1066
1067
1068
1069 int max_packet_len =
1070 ((packet_len - 1) >= USB_MAX_LEN) ? USB_MAX_LEN : packet_len - 1;
1071 num_data_packets = (data_len + max_packet_len) / (max_packet_len + 1);
1072
1073
1074 tx_tds = sched_alloc (TYPE_TD);
1075 tx_tds->status = 0x80;
1076 tx_tds->c_err = 3;
1077 tx_tds->ioc = tx_tds->iso = tx_tds->spd = 0;
1078
1079 tx_tds->pid = UHCI_PID_SETUP;
1080 tx_tds->addr = address;
1081 tx_tds->endp = endpoint;
1082 tx_tds->toggle = toggle;
1083 tx_tds->max_len = setup_len - 1;
1084
1085 tx_tds->buf_ptr = (uint32_t) get_phys_addr ((void *) setup_req);
1086 tx_tds->buf_vptr = setup_req;
1087
1088
1089 td_idx = tx_tds;
1090 toggle = 1;
1091 data_left = data_len;
1092 data = setup_data;
1093 pid = (*((char *) setup_req) & 0x80) ? UHCI_PID_IN : UHCI_PID_OUT;
1094
1095 for (i = 0; i < num_data_packets; i++) {
1096 data_td = sched_alloc (TYPE_TD);
1097
1098
1099 td_idx->link_ptr =
1100 (((uint32_t) get_phys_addr ((void *) data_td)) & LINK_MASK) + DEPTH_FIRST;
1101 td_idx = data_td;
1102
1103 data_td->status = 0x80;
1104 data_td->c_err = 3;
1105 data_td->ioc = data_td->iso = data_td->spd = 0;
1106 data_td->pid = pid;
1107 data_td->addr = address;
1108 data_td->endp = endpoint;
1109 data_td->toggle = toggle;
1110 data_td->max_len =
1111 (data_left > (max_packet_len + 1)) ? max_packet_len : data_left - 1;
1112 data_td->buf_ptr = (uint32_t) get_phys_addr ((void *) data);
1113 data_td->buf_vptr = data;
1114
1115 if (data_left <= (max_packet_len + 1)) {
1116 break;
1117 } else {
1118 data += (data_td->max_len + 1);
1119 data_left -= (data_td->max_len + 1);
1120 toggle = (toggle == 1) ? 0 : 1;
1121 }
1122 }
1123
1124
1125 pid = (pid == UHCI_PID_IN) ? UHCI_PID_OUT : UHCI_PID_IN;
1126 toggle = 1;
1127 status_td = sched_alloc (TYPE_TD);
1128 td_idx->link_ptr =
1129 (((uint32_t) get_phys_addr ((void *) status_td)) & LINK_MASK) + DEPTH_FIRST;
1130
1131 status_td->link_ptr = TERMINATE;
1132 status_td->status = 0x80;
1133 status_td->c_err = 3;
1134 status_td->ioc = status_td->iso = status_td->spd = 0;
1135 status_td->ioc = 1;
1136 status_td->pid = pid;
1137 status_td->addr = address;
1138 status_td->endp = endpoint;
1139 status_td->toggle = toggle;
1140 status_td->max_len = USB_NULL_PACKET;
1141
1142
1143
1144
1145 ctl_qh->qe_ptr =
1146 (((uint32_t) get_phys_addr ((void *) tx_tds)) & LINK_MASK) + 0x0;
1147
1148
1149 return_status = check_tds (ctl_qh, tx_tds, &act_len);
1150
1151 free_tds (tx_tds, num_data_packets + 2);
1152
1153 return return_status;
1154 }
1155
1156 int
1157 uhci_get_descriptor (
1158 uint8_t address,
1159 uint16_t dtype,
1160 uint16_t dindex,
1161 uint16_t index,
1162 uint16_t length,
1163 addr_t desc,
1164 uint8_t packet_size)
1165 {
1166 USB_DEV_REQ setup_req;
1167 setup_req.bmRequestType = 0x80;
1168 setup_req.bRequest = USB_GET_DESCRIPTOR;
1169 setup_req.wValue = (dtype << 8) + dindex;
1170 setup_req.wIndex = index;
1171 setup_req.wLength = length;
1172
1173 return uhci_control_transfer (address,
1174 (addr_t) & setup_req, sizeof (USB_DEV_REQ),
1175 desc, length, packet_size);
1176 }
1177
1178 sint
1179 uhci_get_string (uint8_t address, uint16_t index, uint16_t lang,
1180 uint16_t length, void *buffer, uint8_t pktsize)
1181 {
1182 return uhci_get_descriptor (address, USB_TYPE_STR_DESC, index, lang,
1183 length, buffer, pktsize);
1184 }
1185
1186 sint
1187 uhci_interp_string (USB_STR_DESC *string, uint16_t length, uint16_t lang,
1188 uint8 *output, uint16_t out_len)
1189 {
1190 sint i, j;
1191 if (lang == 0) {
1192
1193 length = (length < string->bLength ? length : string->bLength);
1194
1195 length -= 2;
1196 for (i=0, j=0; i<length && j<out_len; i+=2, j++) {
1197 output[j] = string->bString[i];
1198 }
1199 return j;
1200 } else {
1201
1202 DLOG ("unimplemented: lang!=0");
1203 return 0;
1204 }
1205 }
1206
1207 int
1208 uhci_set_address (uint8_t old_addr, uint8_t new_addr, uint8_t packet_size)
1209 {
1210 sint status;
1211 USB_DEV_REQ setup_req;
1212 setup_req.bmRequestType = 0x0;
1213 setup_req.bRequest = USB_SET_ADDRESS;
1214 setup_req.wValue = new_addr;
1215 setup_req.wIndex = 0;
1216 setup_req.wLength = 0;
1217
1218 status = uhci_control_transfer (old_addr,
1219 (addr_t) & setup_req, sizeof (USB_DEV_REQ), 0,
1220 0, packet_size);
1221 if (status == 0) {
1222 toggles[old_addr] = toggles[new_addr] = 0;
1223 }
1224 return status;
1225 }
1226
1227 int
1228 uhci_get_configuration (uint8_t addr, uint8_t packet_size)
1229 {
1230 USB_DEV_REQ setup_req;
1231 uint8_t num = -1;
1232 setup_req.bmRequestType = 0x80;
1233 setup_req.bRequest = USB_GET_CONFIGURATION;
1234 setup_req.wValue = 0;
1235 setup_req.wIndex = 0;
1236 setup_req.wLength = 1;
1237
1238 uhci_control_transfer (addr, (addr_t) & setup_req, sizeof (USB_DEV_REQ),
1239 (addr_t) & num, 1, packet_size);
1240
1241 return num;
1242 }
1243
1244 int
1245 uhci_set_configuration (uint8_t addr, uint8_t conf, uint8_t packet_size)
1246 {
1247 USB_DEV_REQ setup_req;
1248 setup_req.bmRequestType = 0x0;
1249 setup_req.bRequest = USB_SET_CONFIGURATION;
1250 setup_req.wValue = conf;
1251 setup_req.wIndex = 0;
1252 setup_req.wLength = 0;
1253
1254
1255
1256
1257 toggles[addr] = 0;
1258
1259
1260 return uhci_control_transfer (addr,
1261 (addr_t) & setup_req, sizeof (USB_DEV_REQ), 0,
1262 0, packet_size);
1263 }
1264
1265 int
1266 uhci_set_interface (uint8_t addr, uint16_t alt, uint16_t interface,
1267 uint8_t packet_size)
1268 {
1269 USB_DEV_REQ setup_req;
1270 setup_req.bmRequestType = 0x01;
1271 setup_req.bRequest = USB_SET_INTERFACE;
1272 setup_req.wValue = alt;
1273 setup_req.wIndex = interface;
1274 setup_req.wLength = 0;
1275
1276 return uhci_control_transfer (addr,
1277 (addr_t) & setup_req, sizeof (USB_DEV_REQ), 0,
1278 0, packet_size);
1279 }
1280
1281 int
1282 uhci_get_interface (uint8_t addr, uint16_t interface, uint8_t packet_size)
1283 {
1284 USB_DEV_REQ setup_req;
1285 uint8_t alt = -1;
1286 setup_req.bmRequestType = 0x81;
1287 setup_req.bRequest = USB_GET_INTERFACE;
1288 setup_req.wValue = 0;
1289 setup_req.wIndex = interface;
1290 setup_req.wLength = 1;
1291
1292 uhci_control_transfer (addr, (addr_t) & setup_req, sizeof (USB_DEV_REQ),
1293 (addr_t) & alt, 1, packet_size);
1294
1295 return alt;
1296 }
1297
1298 static uint32
1299 uhci_irq_handler (uint8 vec)
1300 {
1301 uint64 v;
1302 uint16 status;
1303
1304 lock_kernel ();
1305
1306 #if 0
1307 v = IOAPIC_read64 (0x10 + (irq_line * 2));
1308 DLOG ("(1) IOAPIC (irq_line=0x%x) says %p %p",
1309 irq_line, (uint32) (v >> 32), (uint32) v);
1310 #endif
1311
1312
1313
1314
1315
1316 status = 0;
1317 status = GET_USBSTS(usb_base);
1318
1319 #if 0
1320 DLOG ("An interrupt is caught from usb IRQ_LN! (USBSTS=0x%x PCISTS=0x%x)",
1321 status,
1322 pci_config_rd16 (bus, dev, func, 0x06));
1323 #endif
1324
1325 if((status & 0x3F) == 0) {
1326 DLOG("Interrupt is probably not from UHCI. Nothing will be done.");
1327 goto finish;
1328 }
1329
1330 if(status & 0x20) {
1331
1332 DLOG("HCHalted detected!");
1333 status |= 0x20;
1334 debug_dump_bulk_qhs ();
1335 }
1336
1337 if(status & 0x10) {
1338
1339 DLOG("HC Process Error detected!");
1340 status |= 0x10;
1341 }
1342
1343 if(status & 0x08) {
1344
1345 DLOG("Host System Error detected!");
1346 status |= 0x08;
1347 }
1348
1349 if(status & 0x04) {
1350
1351 DLOG("Resume detected!");
1352 status |= 0x04;
1353 }
1354
1355 if(status & 0x02) {
1356
1357 DLOG("USB Error Interrupt detected!");
1358 status |= 0x02;
1359
1360
1361 wakeup_queue (&uhci_waitq);
1362 }
1363
1364 if(status & 0x01) {
1365 DLOGV ("IRQ");
1366
1367
1368
1369
1370
1371 status |= 0x01;
1372
1373
1374 wakeup_queue (&uhci_waitq);
1375
1376 #if 0
1377 int i;
1378 for(i = 0; i < TD_POOL_SIZE; i++) {
1379 if(td[i].link_ptr && !(td[i].status & 0x80)) {
1380
1381 if(td[i].ioc) {
1382
1383 if(td[i].call_back) {
1384 (td[i].call_back)(td[i].buf_vptr);
1385 DLOG("Call back function called: 0x%x, buf_vptr: 0x%x",
1386 td[i].call_back, td[i].buf_vptr);
1387 }
1388
1389 if(td[i].iso) sched_free(TYPE_TD, &td[i]);
1390 }
1391
1392
1393 if(td[i].spd) {
1394
1395 if(td[i].iso) sched_free(TYPE_TD, &td[i]);
1396 }
1397 }
1398 }
1399 #endif
1400 }
1401
1402 finish:
1403
1404
1405 SET_USBSTS (usb_base, status);
1406
1407 #if 0
1408 v = IOAPIC_read64 (0x10 + (irq_line * 2));
1409 DLOG ("(2) IOAPIC (irq_line=0x%x) says %p %p",
1410 irq_line, (uint32) (v >> 32), (uint32) v);
1411 #endif
1412
1413
1414
1415
1416 unlock_kernel ();
1417
1418 return 0;
1419 }
1420
1421 #define printf com1_printf
1422 #define print com1_puts
1423 #define putx com1_putx
1424 #define putchar com1_putc
1425
1426 extern void
1427 uhci_show_regs (void)
1428 {
1429 uint16_t base_addr = 0;
1430 uint32_t ldata = 0;
1431 uint16_t wdata = 0;
1432 uint8_t bdata = 0;
1433 #if 1
1434 print ("\nUHCI Controller PCI Register Address Map\n\n");
1435
1436 wdata = pci_config_rd16 (bus, dev, func, 0x00);
1437 print ("VID: 0x");
1438 putx (wdata);
1439 putchar ('\n');
1440
1441 wdata = pci_config_rd16 (bus, dev, func, 0x02);
1442 print ("DID: 0x");
1443 putx (wdata);
1444 putchar ('\n');
1445
1446 wdata = pci_config_rd16 (bus, dev, func, 0x04);
1447 print ("PCICMD: 0x");
1448 putx (wdata);
1449 putchar ('\n');
1450
1451 wdata = pci_config_rd16 (bus, dev, func, 0x06);
1452 print ("PCISTS: 0x");
1453 putx (wdata);
1454 putchar ('\n');
1455
1456 bdata = pci_config_rd8 (bus, dev, func, 0x08);
1457 print ("RID: 0x");
1458 putx (bdata);
1459 putchar ('\n');
1460
1461 bdata = pci_config_rd8 (bus, dev, func, 0x09);
1462 print ("PI: 0x");
1463 putx (bdata);
1464 putchar ('\n');
1465
1466 bdata = pci_config_rd8 (bus, dev, func, 0x0A);
1467 print ("SCC: 0x");
1468 putx (bdata);
1469 putchar ('\n');
1470
1471 bdata = pci_config_rd8 (bus, dev, func, 0x0B);
1472 print ("BCC: 0x");
1473 putx (bdata);
1474 putchar ('\n');
1475
1476 bdata = pci_config_rd8 (bus, dev, func, 0x0D);
1477 print ("MLT: 0x");
1478 putx (bdata);
1479 putchar ('\n');
1480
1481 bdata = pci_config_rd8 (bus, dev, func, 0x0E);
1482 print ("HEADTYP: 0x");
1483 putx (bdata);
1484 putchar ('\n');
1485
1486 wdata = pci_config_rd16 (bus, dev, func, 0x20);
1487 print ("BASE: 0x");
1488 putx (wdata);
1489 putchar ('\n');
1490
1491 wdata = pci_config_rd16 (bus, dev, func, 0x2C);
1492 print ("SVID: 0x");
1493 putx (wdata);
1494 putchar ('\n');
1495
1496 wdata = pci_config_rd16 (bus, dev, func, 0x2E);
1497 print ("SID: 0x");
1498 putx (wdata);
1499 putchar ('\n');
1500
1501 bdata = pci_config_rd8 (bus, dev, func, 0x3C);
1502 print ("INT_LN: 0x");
1503 putx (bdata);
1504 putchar ('\n');
1505
1506 bdata = pci_config_rd8 (bus, dev, func, 0x3D);
1507 print ("INT_PN: 0x");
1508 putx (bdata);
1509 putchar ('\n');
1510
1511 bdata = pci_config_rd8 (bus, dev, func, 0x60);
1512 print ("USB_RELNUM: 0x");
1513 putx (bdata);
1514 putchar ('\n');
1515
1516 wdata = pci_config_rd16 (bus, dev, func, 0xC0);
1517 print ("USB_LEGKEY: 0x");
1518 putx (wdata);
1519 putchar ('\n');
1520
1521 bdata = pci_config_rd8 (bus, dev, func, 0xC4);
1522 print ("USB_RES: 0x");
1523 putx (bdata);
1524 putchar ('\n');
1525
1526 bdata = pci_config_rd8 (bus, dev, func, 0xC8);
1527 print ("CWP: 0x");
1528 putx (bdata);
1529 putchar ('\n');
1530 #endif
1531 base_addr = pci_config_rd16 (bus, dev, func, 0x20);
1532 base_addr &= 0xFFE0;
1533
1534 print ("\nBase address for USB I/O Registers: 0x");
1535 putx (base_addr);
1536 putchar ('\n');
1537
1538 print ("\nUSB I/O Registers\n\n");
1539
1540 wdata = inw (base_addr + 0x00);
1541 print ("USBCMD: 0x");
1542 putx (wdata);
1543 putchar ('\n');
1544
1545 wdata = inw (base_addr + 0x02);
1546 print ("USBSTS: 0x");
1547 putx (wdata);
1548 putchar ('\n');
1549
1550 wdata = inw (base_addr + 0x04);
1551 print ("USBINTR: 0x");
1552 putx (wdata);
1553 putchar ('\n');
1554
1555 wdata = inw (base_addr + 0x06);
1556 print ("FRNUM: 0x");
1557 putx (wdata);
1558 putchar ('\n');
1559
1560 ldata = inl (base_addr + 0x08);
1561 print ("FRBASEADD: 0x");
1562 putx (ldata);
1563 putchar ('\n');
1564
1565 bdata = inb (base_addr + 0x0C);
1566 print ("SOFMOD: 0x");
1567 putx (bdata);
1568 putchar ('\n');
1569
1570 wdata = inw (base_addr + 0x10);
1571 print ("PORTSC0: 0x");
1572 putx (wdata);
1573 putchar ('\n');
1574
1575 wdata = inw (base_addr + 0x12);
1576 print ("PORTSC1: 0x");
1577 putx (wdata);
1578 putchar ('\n');
1579
1580 bdata = pci_config_rd8 (bus, dev, func, 0x3C);
1581 print ("INT_LN: 0x");
1582 putx (bdata);
1583 putchar ('\n');
1584
1585 bdata = pci_config_rd8 (bus, dev, func, 0x3D);
1586 print ("INT_PN: 0x");
1587 putx (bdata);
1588 putchar ('\n');
1589
1590 return;
1591 }
1592
1593 #include "module/header.h"
1594
1595 static const struct module_ops mod_ops = {
1596 .init = uhci_init
1597 };
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610