1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * OHCI device driver File: ohci.c 5 * 6 * Open Host Controller Interface low-level routines 7 * 8 * Author: Mitch Lichtenberg (mpl@broadcom.com) 9 * 10 ********************************************************************* 11 * 12 * Copyright 2000,2001,2002,2003 13 * Broadcom Corporation. All rights reserved. 14 * 15 * This software is furnished under license and may be used and 16 * copied only in accordance with the following terms and 17 * conditions. Subject to these conditions, you may download, 18 * copy, install, use, modify and distribute modified or unmodified 19 * copies of this software in source and/or binary form. No title 20 * or ownership is transferred hereby. 21 * 22 * 1) Any source code used, modified or distributed must reproduce 23 * and retain this copyright notice and list of conditions 24 * as they appear in the source file. 25 * 26 * 2) No right is granted to use any trade name, trademark, or 27 * logo of Broadcom Corporation. The "Broadcom Corporation" 28 * name may not be used to endorse or promote products derived 29 * from this software without the prior written permission of 30 * Broadcom Corporation. 31 * 32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 44 * THE POSSIBILITY OF SUCH DAMAGE. 45 ********************************************************************* */ 46 47 48#ifndef _CFE_ 49#include <stdio.h> 50#include <stdlib.h> 51#include <unistd.h> 52#include <string.h> 53#include <stdint.h> 54#include "usbhack.h" 55#define CPUCFG_COHERENT_DMA 1 /* hack runs on a PC, PCs are coherent */ 56#else 57#include "lib_types.h" 58#include "lib_printf.h" 59#include "lib_string.h" 60#include "lib_physio.h" 61#include "addrspace.h" 62#include "cpu_config.h" /* for CPUCFG_COHERENT_DMA */ 63#endif 64 65#include "lib_malloc.h" 66#include "lib_queue.h" 67#include "usbchap9.h" 68#include "usbd.h" 69#include "ohci.h" 70 71 72/* ********************************************************************* 73 * Macros for dealing with hardware 74 * 75 * This is all yucky stuff that needs to be made more 76 * processor-independent. It's mostly here now to help us with 77 * our test harness. 78 ********************************************************************* */ 79 80#if defined(_CFE_) && defined(__MIPSEB) 81#define BSWAP32(x) __swap32(x) 82static inline uint32_t __swap32(uint32_t x) 83{ 84 uint32_t y; 85 86 y = ((x & 0xFF) << 24) | 87 ((x & 0xFF00) << 8) | 88 ((x & 0xFF0000) >> 8) | 89 ((x & 0xFF000000) >> 24); 90 91 return y; 92} 93#else 94#define BSWAP32(x) (x) 95#endif 96 97 98#ifndef _CFE_ 99extern uint32_t vtop(void *ptr); 100extern void *ptov(uint32_t x); 101#define OHCI_VTOP(ptr) vtop(ptr) 102#define OHCI_PTOV(ptr) ptov(ptr) 103#define OHCI_WRITECSR(softc,x,y) \ 104 *((volatile uint32_t *) ((softc)->ohci_regs + ((x)/sizeof(uint32_t)))) = (y) 105#define OHCI_READCSR(softc,x) \ 106 *((volatile uint32_t *) ((softc)->ohci_regs + ((x)/sizeof(uint32_t)))) 107#else 108#define OHCI_VTOP(ptr) ((uint32_t)PHYSADDR((long)(ptr))) 109 110#if CPUCFG_COHERENT_DMA 111#define OHCI_PTOV(ptr) ((void *)(KERNADDR(ptr))) 112#else 113#define OHCI_PTOV(ptr) ((void *)(UNCADDR(ptr))) 114#endif 115 116#define OHCI_WRITECSR(softc,x,y) \ 117 phys_write32(((softc)->ohci_regs + (x)),(y)) 118#define OHCI_READCSR(softc,x) \ 119 phys_read32(((softc)->ohci_regs + (x))) 120#endif 121 122#if CPUCFG_COHERENT_DMA 123#define OHCI_INVAL_RANGE(s,l) 124#define OHCI_FLUSH_RANGE(s,l) 125#else /* not coherent */ 126#define CFE_CACHE_INVAL_RANGE 32 127#define CFE_CACHE_FLUSH_RANGE 64 128extern void _cfe_flushcache(int,uint8_t *,uint8_t *); 129#define OHCI_INVAL_RANGE(s,l) _cfe_flushcache(CFE_CACHE_INVAL_RANGE,((uint8_t *) (s)),((uint8_t *) (s))+(l)) 130#define OHCI_FLUSH_RANGE(s,l) _cfe_flushcache(CFE_CACHE_FLUSH_RANGE,((uint8_t *) (s)),((uint8_t *) (s))+(l)) 131#endif 132 133 134/* ********************************************************************* 135 * Bit-reverse table - this table consists of the numbers 136 * at its index, listed in reverse. So, the reverse of 0000 0010 137 * is 0100 0000. 138 ********************************************************************* */ 139 140const static int ohci_revbits[OHCI_INTTABLE_SIZE] = { 141 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c, 142 0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e, 143 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d, 144 0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f 145}; 146 147 148/* ********************************************************************* 149 * Macros to convert from "hardware" endpoint and transfer 150 * descriptors (ohci_ed_t, ohci_td_t) to "software" 151 * data structures (ohci_transfer_t, ohci_endpoint_t). 152 * 153 * Basically, there are two tables, indexed by the same value 154 * By subtracting the base of one pool from a pointer, we get 155 * the index into the other table. 156 * 157 * We *could* have included the ed and td in the software 158 * data structures, but placing all the hardware stuff in one 159 * pool will make it easier for hardware that does not handle 160 * coherent DMA, since we can be less careful about what we flush 161 * and what we invalidate. 162 ********************************************************************* */ 163 164#define ohci_td_from_transfer(softc,transfer) \ 165 ((softc)->ohci_hwtdpool + ((transfer) - (softc)->ohci_transfer_pool)) 166 167#define ohci_transfer_from_td(softc,td) \ 168 ((softc)->ohci_transfer_pool + ((td) - (softc)->ohci_hwtdpool)) 169 170#define ohci_ed_from_endpoint(softc,endpoint) \ 171 ((softc)->ohci_hwedpool + ((endpoint) - (softc)->ohci_endpoint_pool)) 172 173#define ohci_endpoint_from_ed(softc,ed) \ 174 ((softc)->ohci_endpoint_pool + ((ed) - (softc)->ohci_hwedpool)) 175 176/* ********************************************************************* 177 * Forward declarations 178 ********************************************************************* */ 179 180static int ohci_roothub_xfer(usbbus_t *bus,usb_ept_t *uept,usbreq_t *ur); 181static void ohci_roothub_statchg(ohci_softc_t *softc); 182extern usb_hcdrv_t ohci_driver; 183 184/* ********************************************************************* 185 * Globals 186 ********************************************************************* */ 187 188int ohcidebug = 0; 189void ohci_dumprhstat(uint32_t reg); 190void ohci_dumpportstat(int idx,uint32_t reg); 191void ohci_dumptd(ohci_td_t *td); 192void ohci_dumptdchain(ohci_td_t *td); 193void ohci_dumped(ohci_ed_t *ed); 194void ohci_dumpedchain(ohci_ed_t *ed); 195 196 197/* ********************************************************************* 198 * Some debug routines 199 ********************************************************************* */ 200 201void ohci_dumprhstat(uint32_t reg) 202{ 203 printf("HubStatus: %08X ",reg); 204 205 if (reg & M_OHCI_RHSTATUS_LPS) printf("LocalPowerStatus "); 206 if (reg & M_OHCI_RHSTATUS_OCI) printf("OverCurrent "); 207 if (reg & M_OHCI_RHSTATUS_DRWE) printf("DeviceRemoteWakeupEnable "); 208 if (reg & M_OHCI_RHSTATUS_LPSC) printf("LocalPowerStatusChange "); 209 if (reg & M_OHCI_RHSTATUS_OCIC) printf("OverCurrentIndicatorChange "); 210 printf("\n"); 211 212} 213 214void ohci_dumpportstat(int idx,uint32_t reg) 215{ 216 printf("Port %d: %08X ",idx,reg); 217 if (reg & M_OHCI_RHPORTSTAT_CCS) printf("Connected "); 218 if (reg & M_OHCI_RHPORTSTAT_PES) printf("PortEnabled "); 219 if (reg & M_OHCI_RHPORTSTAT_PSS) printf("PortSuspended "); 220 if (reg & M_OHCI_RHPORTSTAT_POCI) printf("PortOverCurrent "); 221 if (reg & M_OHCI_RHPORTSTAT_PRS) printf("PortReset "); 222 if (reg & M_OHCI_RHPORTSTAT_PPS) printf("PortPowered "); 223 if (reg & M_OHCI_RHPORTSTAT_LSDA) printf("LowSpeed "); 224 if (reg & M_OHCI_RHPORTSTAT_CSC) printf("ConnectStatusChange "); 225 if (reg & M_OHCI_RHPORTSTAT_PESC) printf("PortEnableStatusChange "); 226 if (reg & M_OHCI_RHPORTSTAT_PSSC) printf("PortSuspendStatusChange "); 227 if (reg & M_OHCI_RHPORTSTAT_OCIC) printf("OverCurrentIndicatorChange "); 228 if (reg & M_OHCI_RHPORTSTAT_PRSC) printf("PortResetStatusChange "); 229 printf("\n"); 230} 231 232void ohci_dumptd(ohci_td_t *td) 233{ 234 uint32_t ctl; 235 static char *pids[4] = {"SETUP","OUT","IN","RSVD"}; 236 237 ctl = BSWAP32(td->td_control); 238 239 printf("[%08X] ctl=%08X (DP=%s,DI=%d,T=%d,EC=%d,CC=%d%s) cbp=%08X be=%08X next=%08X\n", 240 OHCI_VTOP(td), 241 ctl, 242 pids[G_OHCI_TD_PID(ctl)], 243 G_OHCI_TD_DI(ctl), 244 G_OHCI_TD_DT(ctl), 245 G_OHCI_TD_EC(ctl), 246 G_OHCI_TD_CC(ctl), 247 (ctl & M_OHCI_TD_SHORTOK) ? ",R" : "", 248 BSWAP32(td->td_cbp), 249 BSWAP32(td->td_be), 250 BSWAP32(td->td_next_td)); 251} 252 253void ohci_dumptdchain(ohci_td_t *td) 254{ 255 int idx = 0; 256 for (;;) { 257 printf("%d:[%08X] ctl=%08X cbp=%08X be=%08X next=%08X\n", 258 idx, 259 OHCI_VTOP(td), 260 BSWAP32(td->td_control), 261 BSWAP32(td->td_cbp), 262 BSWAP32(td->td_be), 263 BSWAP32(td->td_next_td)); 264 if (!td->td_next_td) break; 265 td = (ohci_td_t *) OHCI_PTOV(BSWAP32(td->td_next_td)); 266 idx++; 267 } 268} 269 270void ohci_dumped(ohci_ed_t *ed) 271{ 272 uint32_t ctl; 273 static char *pids[4] = {"FTD","OUT","IN","FTD"}; 274 275 ctl = BSWAP32(ed->ed_control), 276 277 printf("[%08X] Ctl=%08X (MPS=%d%s%s%s,EN=%d,FA=%d,D=%s) Tailp=%08X headp=%08X next=%08X %s\n", 278 OHCI_VTOP(ed), 279 ctl, 280 G_OHCI_ED_MPS(ctl), 281 (ctl & M_OHCI_ED_LOWSPEED) ? ",LS" : "", 282 (ctl & M_OHCI_ED_SKIP) ? ",SKIP" : "", 283 (ctl & M_OHCI_ED_ISOCFMT) ? ",ISOC" : "", 284 G_OHCI_ED_EN(ctl), 285 G_OHCI_ED_FA(ctl), 286 pids[G_OHCI_ED_DIR(ctl)], 287 BSWAP32(ed->ed_tailp), 288 BSWAP32(ed->ed_headp), 289 BSWAP32(ed->ed_next_ed), 290 BSWAP32(ed->ed_headp) & M_OHCI_ED_HALT ? "HALT" : ""); 291 if ((ed->ed_headp & M_OHCI_ED_PTRMASK) == 0) return; 292 ohci_dumptdchain(OHCI_PTOV(BSWAP32(ed->ed_headp) & M_OHCI_ED_PTRMASK)); 293} 294 295void ohci_dumpedchain(ohci_ed_t *ed) 296{ 297 int idx = 0; 298 for (;;) { 299 printf("---\nED#%d -> ",idx); 300 ohci_dumped(ed); 301 if (!ed->ed_next_ed) break; 302 if (idx > 50) break; 303 ed = (ohci_ed_t *) OHCI_PTOV(BSWAP32(ed->ed_next_ed)); 304 idx++; 305 } 306} 307 308 309 310static void eptstats(ohci_softc_t *softc) 311{ 312 int cnt; 313 ohci_endpoint_t *e; 314 cnt = 0; 315 316 e = softc->ohci_endpoint_freelist; 317 while (e) { e = e->ep_next; cnt++; } 318 printf("%d left, %d inuse\n",cnt,OHCI_EDPOOL_SIZE-cnt); 319} 320 321/* ********************************************************************* 322 * _ohci_allocept(softc) 323 * 324 * Allocate an endpoint data structure from the pool, and 325 * make it ready for use. The endpoint is NOT attached to 326 * the hardware at this time. 327 * 328 * Input parameters: 329 * softc - our OHCI controller 330 * 331 * Return value: 332 * pointer to endpoint or NULL 333 ********************************************************************* */ 334 335static ohci_endpoint_t *_ohci_allocept(ohci_softc_t *softc) 336{ 337 ohci_endpoint_t *e; 338 ohci_ed_t *ed; 339 340 if (ohcidebug > 2) { 341 printf("AllocEpt: ");eptstats(softc); 342 } 343 344 e = softc->ohci_endpoint_freelist; 345 346 if (!e) { 347 printf("No endpoints left!\n"); 348 return NULL; 349 } 350 351 softc->ohci_endpoint_freelist = e->ep_next; 352 353 ed = ohci_ed_from_endpoint(softc,e); 354 355 ed->ed_control = BSWAP32(M_OHCI_ED_SKIP); 356 ed->ed_tailp = BSWAP32(0); 357 ed->ed_headp = BSWAP32(0); 358 ed->ed_next_ed = BSWAP32(0); 359 360 e->ep_phys = OHCI_VTOP(ed); 361 e->ep_next = NULL; 362 363 return e; 364} 365 366/* ********************************************************************* 367 * _ohci_allocxfer(softc) 368 * 369 * Allocate a transfer descriptor. It is prepared for use 370 * but not attached to the hardware. 371 * 372 * Input parameters: 373 * softc - our OHCI controller 374 * 375 * Return value: 376 * transfer descriptor, or NULL 377 ********************************************************************* */ 378 379static ohci_transfer_t *_ohci_allocxfer(ohci_softc_t *softc) 380{ 381 ohci_transfer_t *t; 382 ohci_td_t *td; 383 384 if (ohcidebug > 2) { 385 int cnt; 386 cnt = 0; 387 t = softc->ohci_transfer_freelist; 388 while (t) { t = t->t_next; cnt++; } 389 printf("AllocXfer: %d left, %d inuse\n",cnt,OHCI_TDPOOL_SIZE-cnt); 390 } 391 392 t = softc->ohci_transfer_freelist; 393 394 if (!t) { 395 printf("No more transfer descriptors!\n"); 396 return NULL; 397 } 398 399 softc->ohci_transfer_freelist = t->t_next; 400 401 td = ohci_td_from_transfer(softc,t); 402 403 td->td_control = BSWAP32(0); 404 td->td_cbp = BSWAP32(0); 405 td->td_next_td = BSWAP32(0); 406 td->td_be = BSWAP32(0); 407 408 t->t_ref = NULL; 409 t->t_next = NULL; 410 411 return t; 412} 413 414/* ********************************************************************* 415 * _ohci_freeept(softc,e) 416 * 417 * Free an endpoint, returning it to the pool. 418 * 419 * Input parameters: 420 * softc - our OHCI controller 421 * e - endpoint descriptor to return 422 * 423 * Return value: 424 * nothing 425 ********************************************************************* */ 426 427static void _ohci_freeept(ohci_softc_t *softc,ohci_endpoint_t *e) 428{ 429 if (ohcidebug > 2) { 430 int cnt; 431 ohci_endpoint_t *ee; 432 cnt = 0; 433 ee = softc->ohci_endpoint_freelist; 434 while (ee) { ee = ee->ep_next; cnt++; } 435 printf("FreeEpt[%p]: %d left, %d inuse\n",e,cnt,OHCI_EDPOOL_SIZE-cnt); 436 } 437 438 e->ep_next = softc->ohci_endpoint_freelist; 439 softc->ohci_endpoint_freelist = e; 440} 441 442/* ********************************************************************* 443 * _ohci_freexfer(softc,t) 444 * 445 * Free a transfer descriptor, returning it to the pool. 446 * 447 * Input parameters: 448 * softc - our OHCI controller 449 * t - transfer descriptor to return 450 * 451 * Return value: 452 * nothing 453 ********************************************************************* */ 454 455static void _ohci_freexfer(ohci_softc_t *softc,ohci_transfer_t *t) 456{ 457 t->t_next = softc->ohci_transfer_freelist; 458 softc->ohci_transfer_freelist = t; 459} 460 461/* ********************************************************************* 462 * _ohci_initpools(softc) 463 * 464 * Allocate and initialize the various pools of things that 465 * we use in the OHCI driver. We do this by allocating some 466 * big chunks from the heap and carving them up. 467 * 468 * Input parameters: 469 * softc - our OHCI controller 470 * 471 * Return value: 472 * 0 if ok 473 * else error code 474 ********************************************************************* */ 475 476static int _ohci_initpools(ohci_softc_t *softc) 477{ 478 int idx; 479 480 /* 481 * Do the transfer descriptor pool 482 */ 483 484 softc->ohci_transfer_pool = KMALLOC(OHCI_TDPOOL_SIZE*sizeof(ohci_transfer_t),0); 485 softc->ohci_hwtdpool = KMALLOC(OHCI_TDPOOL_SIZE*sizeof(ohci_td_t),OHCI_TD_ALIGN); 486 487 /* 488 * In the case of noncoherent DMA, make these uncached addresses. 489 * This way all our descriptors will be uncached. Makes life easier, as we 490 * do not need to worry about flushing descriptors, etc. 491 */ 492 493#if !CPUCFG_COHERENT_DMA 494 softc->ohci_hwtdpool = (void *) UNCADDR(PHYSADDR((uint32_t)(softc->ohci_hwtdpool))); 495#endif 496 497 if (!softc->ohci_transfer_pool || !softc->ohci_hwtdpool) { 498 printf("Could not allocate transfer descriptors\n"); 499 return -1; 500 } 501 502 softc->ohci_transfer_freelist = NULL; 503 504 for (idx = 0; idx < OHCI_TDPOOL_SIZE; idx++) { 505 _ohci_freexfer(softc,softc->ohci_transfer_pool+idx); 506 } 507 508 /* 509 * Do the endpoint descriptor pool 510 */ 511 512 softc->ohci_endpoint_pool = KMALLOC(OHCI_EDPOOL_SIZE*sizeof(ohci_endpoint_t),0); 513 514 softc->ohci_hwedpool = KMALLOC(OHCI_EDPOOL_SIZE*sizeof(ohci_ed_t),OHCI_ED_ALIGN); 515 516#if !CPUCFG_COHERENT_DMA 517 softc->ohci_hwedpool = (void *) UNCADDR(PHYSADDR((uint32_t)(softc->ohci_hwedpool))); 518#endif 519 520 if (!softc->ohci_endpoint_pool || !softc->ohci_hwedpool) { 521 printf("Could not allocate transfer descriptors\n"); 522 return -1; 523 } 524 525 softc->ohci_endpoint_freelist = NULL; 526 527 for (idx = 0; idx < OHCI_EDPOOL_SIZE; idx++) { 528 _ohci_freeept(softc,softc->ohci_endpoint_pool+idx); 529 } 530 531 /* 532 * Finally the host communications area 533 */ 534 535 softc->ohci_hcca = KMALLOC(sizeof(ohci_hcca_t),sizeof(ohci_hcca_t)); 536 537#if !CPUCFG_COHERENT_DMA 538 softc->ohci_hcca = (void *) UNCADDR(PHYSADDR((uint32_t)(softc->ohci_hcca))); 539#endif 540 541 memset(softc->ohci_hcca,0,sizeof(ohci_hcca_t)); 542 543 return 0; 544} 545 546 547/* ********************************************************************* 548 * ohci_start(bus) 549 * 550 * Start the OHCI controller. After this routine is called, 551 * the hardware will be operational and ready to accept 552 * descriptors and interrupt calls. 553 * 554 * Input parameters: 555 * bus - bus structure, from ohci_create 556 * 557 * Return value: 558 * 0 if ok 559 * else error code 560 ********************************************************************* */ 561 562static int ohci_start(usbbus_t *bus) 563{ 564 ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc; 565 uint32_t frameint; 566 uint32_t reg; 567 int idx; 568 569 /* 570 * Force a reset to the controller, followed by a short delay 571 */ 572 573 OHCI_WRITECSR(softc,R_OHCI_CONTROL,V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_RESET)); 574 usb_delay_ms(bus,OHCI_RESET_DELAY); 575 576 /* Host controller state is now "RESET" */ 577 578 /* 579 * We need the frame interval later, so get a copy of it now. 580 */ 581 frameint = G_OHCI_FMINTERVAL_FI(OHCI_READCSR(softc,R_OHCI_FMINTERVAL)); 582 583 /* 584 * Reset the host controller. When you set the HCR bit 585 * if self-clears when the reset is complete. 586 */ 587 588 OHCI_WRITECSR(softc,R_OHCI_CMDSTATUS,M_OHCI_CMDSTATUS_HCR); 589 for (idx = 0; idx < 10000; idx++) { 590 if (!(OHCI_READCSR(softc,R_OHCI_CMDSTATUS) & M_OHCI_CMDSTATUS_HCR)) break; 591 } 592 593 if (OHCI_READCSR(softc,R_OHCI_CMDSTATUS) & M_OHCI_CMDSTATUS_HCR) { 594 /* controller never came out of reset */ 595 return -1; 596 } 597 598 /* 599 * Host controller state is now "SUSPEND". We must exit 600 * from this state within 2ms. (5.1.1.4) 601 * 602 * Set up pointers to data structures. 603 */ 604 605 OHCI_WRITECSR(softc,R_OHCI_HCCA,OHCI_VTOP(softc->ohci_hcca)); 606 OHCI_WRITECSR(softc,R_OHCI_CONTROLHEADED,softc->ohci_ctl_list->ep_phys); 607 OHCI_WRITECSR(softc,R_OHCI_BULKHEADED,softc->ohci_bulk_list->ep_phys); 608 609 /* 610 * Our driver is polled, turn off interrupts 611 */ 612 613 OHCI_WRITECSR(softc,R_OHCI_INTDISABLE,M_OHCI_INT_ALL); 614 615 /* 616 * Set up the control register. 617 */ 618 619 reg = OHCI_READCSR(softc,R_OHCI_CONTROL); 620 621 reg = M_OHCI_CONTROL_PLE | M_OHCI_CONTROL_CLE | M_OHCI_CONTROL_BLE | 622 M_OHCI_CONTROL_IE | 623 V_OHCI_CONTROL_CBSR(K_OHCI_CBSR_41) | 624 V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_OPERATIONAL); 625 626 OHCI_WRITECSR(softc,R_OHCI_CONTROL,reg); 627 628 629 /* 630 * controller state is now OPERATIONAL 631 */ 632 633 reg = OHCI_READCSR(softc,R_OHCI_FMINTERVAL); 634 reg &= M_OHCI_FMINTERVAL_FIT; 635 reg ^= M_OHCI_FMINTERVAL_FIT; 636 reg |= V_OHCI_FMINTERVAL_FSMPS(OHCI_CALC_FSMPS(frameint)) | 637 V_OHCI_FMINTERVAL_FI(frameint); 638 OHCI_WRITECSR(softc,R_OHCI_FMINTERVAL,reg); 639 640 reg = frameint * 9 / 10; /* calculate 90% */ 641 OHCI_WRITECSR(softc,R_OHCI_PERIODICSTART,reg); 642 643 usb_delay_ms(softc->ohci_bus,10); 644 645 /* 646 * Remember how many ports we have 647 */ 648 649 reg = OHCI_READCSR(softc,R_OHCI_RHDSCRA); 650 softc->ohci_ndp = G_OHCI_RHDSCRA_NDP(reg); 651 652 653 /* 654 * Enable port power 655 */ 656 657 OHCI_WRITECSR(softc,R_OHCI_RHSTATUS,M_OHCI_RHSTATUS_LPSC); 658 usb_delay_ms(softc->ohci_bus,10); 659 660 return 0; 661} 662 663 664/* ********************************************************************* 665 * _ohci_setupepts(softc) 666 * 667 * Set up the endpoint tree, as described in the OHCI manual. 668 * Basically the hardware knows how to scan lists of lists, 669 * so we build a tree where each level is pointed to by two 670 * parent nodes. We can choose our scanning rate by attaching 671 * endpoints anywhere within this tree. 672 * 673 * Input parameters: 674 * softc - our OHCI controller 675 * 676 * Return value: 677 * 0 if ok 678 * else error (out of descriptors) 679 ********************************************************************* */ 680 681static int _ohci_setupepts(ohci_softc_t *softc) 682{ 683 int idx; 684 ohci_endpoint_t *e; 685 ohci_ed_t *ed; 686 ohci_endpoint_t *child; 687 688 /* 689 * Set up the list heads for the isochronous, control, 690 * and bulk transfer lists. They don't get the same "tree" 691 * treatment that the interrupt devices get. 692 * 693 * For the purposes of CFE, it's probably not necessary 694 * to be this fancy. The only device we're planning to 695 * talk to is the keyboard and some hubs, which should 696 * have pretty minimal requirements. It's conceivable 697 * that this firmware may find a new home in other 698 * devices, so we'll meet halfway and do some things 699 * "fancy." 700 */ 701 702 softc->ohci_isoc_list = _ohci_allocept(softc); 703 softc->ohci_ctl_list = _ohci_allocept(softc); 704 softc->ohci_bulk_list = _ohci_allocept(softc); 705 706 /* 707 * Set up a tree of empty endpoint descriptors. This is 708 * tree is scanned by the hardware from the leaves up to 709 * the root. Once a millisecond, the hardware picks the 710 * next leaf and starts scanning descriptors looking 711 * for something to do. It traverses all of the endpoints 712 * along the way until it gets to the root. 713 * 714 * The idea here is if you put a transfer descriptor on the 715 * root node, the hardware will see it every millisecond, 716 * since the root will be examined each time. If you 717 * put the TD on the leaf, it will be 1/32 millisecond. 718 * The tree therefore is six levels deep. 719 */ 720 721 for (idx = 0; idx < OHCI_INTTREE_SIZE; idx++) { 722 e = _ohci_allocept(softc); /* allocated with sKip bit set */ 723 softc->ohci_edtable[idx] = e; 724 child = (idx == 0) ? softc->ohci_isoc_list : softc->ohci_edtable[(idx-1)/2]; 725 ed = ohci_ed_from_endpoint(softc,e); 726 ed->ed_next_ed = BSWAP32(child->ep_phys); 727 e->ep_next = child; 728 } 729 730 /* 731 * We maintain both physical and virtual copies of the interrupt 732 * table (leaves of the tree). 733 */ 734 735 for (idx = 0; idx < OHCI_INTTABLE_SIZE; idx++) { 736 child = softc->ohci_edtable[OHCI_INTTREE_SIZE-OHCI_INTTABLE_SIZE+idx]; 737 softc->ohci_inttable[ohci_revbits[idx]] = child; 738 softc->ohci_hcca->hcca_inttable[ohci_revbits[idx]] = BSWAP32(child->ep_phys); 739 } 740 741 /* 742 * Okay, at this point the tree is built. 743 */ 744 return 0; 745} 746 747/* ********************************************************************* 748 * ohci_stop(bus) 749 * 750 * Stop the OHCI hardware. 751 * 752 * Input parameters: 753 * bus - our bus structure 754 * 755 * Return value: 756 * nothing 757 ********************************************************************* */ 758 759static void ohci_stop(usbbus_t *bus) 760{ 761 ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc; 762 763 OHCI_WRITECSR(softc,R_OHCI_CONTROL,V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_RESET)); 764} 765 766 767/* ********************************************************************* 768 * _ohci_queueept(softc,queue,e) 769 * 770 * Add an endpoint to a list of endpoints. This routine 771 * does things in a particular way according to the OHCI 772 * spec so we can add endpoints while the hardware is running. 773 * 774 * Input parameters: 775 * queue - endpoint descriptor for head of queue 776 * e - endpoint to add to queue 777 * 778 * Return value: 779 * nothing 780 ********************************************************************* */ 781 782static void _ohci_queueept(ohci_softc_t *softc,ohci_endpoint_t *queue,ohci_endpoint_t *newept) 783{ 784 ohci_ed_t *qed; 785 ohci_ed_t *newed; 786 787 qed = ohci_ed_from_endpoint(softc,queue); 788 newed = ohci_ed_from_endpoint(softc,newept); 789 790 newept->ep_next = queue->ep_next; 791 newed->ed_next_ed = qed->ed_next_ed; 792 793 queue->ep_next = newept; 794 qed->ed_next_ed = BSWAP32(newept->ep_phys); 795 796 if (ohcidebug > 1) ohci_dumped(newed); 797 798} 799 800/* ********************************************************************* 801 * _ohci_deqept(queue,e) 802 * 803 * Remove and endpoint from the list of endpoints. This 804 * routine does things in a particular way according to 805 * the OHCI specification, since we are operating on 806 * a running list. 807 * 808 * Input parameters: 809 * queue - base of queue to look for endpoint on 810 * e - endpoint to remove 811 * 812 * Return value: 813 * nothing 814 ********************************************************************* */ 815 816static void _ohci_deqept(ohci_softc_t *softc,ohci_endpoint_t *queue,ohci_endpoint_t *e) 817{ 818 ohci_endpoint_t *cur; 819 ohci_ed_t *cured; 820 ohci_ed_t *ed; 821 822 cur = queue; 823 824 while (cur && (cur->ep_next != e)) cur = cur->ep_next; 825 826 if (cur == NULL) { 827 printf("Could not remove EP %08X: not on the list!\n",(uint32_t) (intptr_t)e); 828 return; 829 } 830 831 /* 832 * Remove from our regular list 833 */ 834 835 cur->ep_next = e->ep_next; 836 837 /* 838 * now remove from the hardware's list 839 */ 840 841 cured = ohci_ed_from_endpoint(softc,cur); 842 ed = ohci_ed_from_endpoint(softc,e); 843 844 cured->ed_next_ed = ed->ed_next_ed; 845} 846 847 848/* ********************************************************************* 849 * ohci_intr_procdoneq(softc) 850 * 851 * Process the "done" queue for this ohci controller. As 852 * descriptors are retired, the hardware links them to the 853 * "done" queue so we can examine the results. 854 * 855 * Input parameters: 856 * softc - our OHCI controller 857 * 858 * Return value: 859 * nothing 860 ********************************************************************* */ 861 862static void ohci_intr_procdoneq(ohci_softc_t *softc) 863{ 864 uint32_t doneq; 865 ohci_transfer_t *transfer; 866 ohci_td_t *td; 867 int val; 868 usbreq_t *ur; 869 870 /* 871 * Get the head of the queue 872 */ 873 874 doneq = softc->ohci_hcca->hcca_donehead; 875 doneq = BSWAP32(doneq); 876 877 td = (ohci_td_t *) OHCI_PTOV(doneq); 878 transfer = ohci_transfer_from_td(softc,td); 879 880 /* 881 * Process all elements from the queue 882 */ 883 884 while (doneq) { 885 886 ohci_ed_t *ed; 887 ohci_endpoint_t *ept; 888 usbreq_t *xur = transfer->t_ref; 889 890 if (ohcidebug > 1) { 891 if (xur) { 892 ept = (ohci_endpoint_t *) xur->ur_pipe->up_hwendpoint; 893 ed = ohci_ed_from_endpoint(softc,ept); 894// printf("ProcDoneQ:ED [%08X] -> ",ept->ep_phys); 895// ohci_dumped(ed); 896 } 897 } 898 899 /* 900 * Get the pointer to next one before freeing this one 901 */ 902 903 if (ohcidebug > 1) { 904 ur = transfer->t_ref; 905 printf("Done(%d): ",ur ? ur->ur_tdcount : -1); 906 ohci_dumptd(td); 907 } 908 909 doneq = BSWAP32(td->td_next_td); 910 911 val = G_OHCI_TD_CC(BSWAP32(td->td_control)); 912 913 if (val != 0) printf("[Transfer error: %d]\n",val); 914 915 /* 916 * See if it's time to call the callback. 917 */ 918 ur = transfer->t_ref; 919 if (ur) { 920 ur->ur_status = val; 921 ur->ur_tdcount--; 922 if (BSWAP32(td->td_cbp) == 0) { 923 ur->ur_xferred += transfer->t_length; 924 } 925 else { 926 ur->ur_xferred += transfer->t_length - 927 (BSWAP32(td->td_be) - BSWAP32(td->td_cbp) + 1); 928 } 929 if (ur->ur_tdcount == 0) { 930 /* Noncoherent DMA: need to invalidate, since data is in phys mem */ 931 OHCI_INVAL_RANGE(ur->ur_buffer,ur->ur_xferred); 932 usb_complete_request(ur,val); 933 } 934 } 935 936 937 /* 938 * Free up the request 939 */ 940 _ohci_freexfer(softc,transfer); 941 942 943 /* 944 * Advance to the next request. 945 */ 946 947 td = (ohci_td_t *) OHCI_PTOV(doneq); 948 transfer = ohci_transfer_from_td(softc,td); 949 } 950 951} 952 953/* ********************************************************************* 954 * ohci_intr(bus) 955 * 956 * Process pending interrupts for the OHCI controller. 957 * 958 * Input parameters: 959 * bus - our bus structure 960 * 961 * Return value: 962 * 0 if we did nothing 963 * nonzero if we did something. 964 ********************************************************************* */ 965 966static int ohci_intr(usbbus_t *bus) 967{ 968 uint32_t reg; 969 ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc; 970 971 /* 972 * Read the interrupt status register. 973 */ 974 975 reg = OHCI_READCSR(softc,R_OHCI_INTSTATUS); 976 977 /* 978 * Don't bother doing anything if nothing happened. 979 */ 980 if (reg == 0) { 981 return 0; 982 } 983 984 /* Scheduling Overruns */ 985 if (reg & M_OHCI_INT_SO) { 986 printf("SchedOverrun\n"); 987 } 988 989 /* Done Queue */ 990 if (reg & M_OHCI_INT_WDH) { 991 /* printf("DoneQueue\n"); */ 992 ohci_intr_procdoneq(softc); 993 } 994 995 /* Start of Frame */ 996 if (reg & M_OHCI_INT_SF) { 997 /* don't be noisy about this */ 998 } 999 1000 /* Resume Detect */ 1001 if (reg & M_OHCI_INT_RD) { 1002 printf("ResumeDetect\n"); 1003 } 1004 1005 /* Unrecoverable errors */ 1006 if (reg & M_OHCI_INT_UE) { 1007 printf("UnrecoverableError\n"); 1008 } 1009 1010 /* Frame number overflow */ 1011 if (reg & M_OHCI_INT_FNO) { 1012 /*printf("FrameNumberOverflow\n"); */ 1013 } 1014 1015 /* Root Hub Status Change */ 1016 if ((reg & ~softc->ohci_intdisable) & M_OHCI_INT_RHSC) { 1017 uint32_t reg; 1018 if (ohcidebug > 0) { 1019 printf("RootHubStatusChange: "); 1020 reg = OHCI_READCSR(softc,R_OHCI_RHSTATUS); 1021 ohci_dumprhstat(reg); 1022 reg = OHCI_READCSR(softc,R_OHCI_RHPORTSTATUS(1)); 1023 ohci_dumpportstat(1,reg); 1024 reg = OHCI_READCSR(softc,R_OHCI_RHPORTSTATUS(2)); 1025 ohci_dumpportstat(2,reg); 1026 } 1027 ohci_roothub_statchg(softc); 1028 } 1029 1030 /* Ownership Change */ 1031 if (reg & M_OHCI_INT_OC) { 1032 printf("OwnershipChange\n"); 1033 } 1034 1035 /* 1036 * Write the value back to the interrupt 1037 * register to clear the bits that were set. 1038 */ 1039 1040 OHCI_WRITECSR(softc,R_OHCI_INTSTATUS,reg); 1041 1042 return 1; 1043} 1044 1045 1046/* ********************************************************************* 1047 * ohci_delete(bus) 1048 * 1049 * Remove an OHCI bus structure and all resources allocated to 1050 * it (used when shutting down USB) 1051 * 1052 * Input parameters: 1053 * bus - our USB bus structure 1054 * 1055 * Return value: 1056 * nothing 1057 ********************************************************************* */ 1058 1059static void ohci_delete(usbbus_t *bus) 1060{ 1061 // xxx fill in later. 1062} 1063 1064 1065/* ********************************************************************* 1066 * ohci_create(addr) 1067 * 1068 * Create a USB bus structure and associate it with our OHCI 1069 * controller device. 1070 * 1071 * Input parameters: 1072 * addr - physical address of controller 1073 * 1074 * Return value: 1075 * usbbus structure pointer 1076 ********************************************************************* */ 1077 1078static usbbus_t *ohci_create(physaddr_t addr) 1079{ 1080 int res; 1081 ohci_softc_t *softc; 1082 usbbus_t *bus; 1083 1084 softc = KMALLOC(sizeof(ohci_softc_t),0); 1085 if (!softc) return NULL; 1086 1087 bus = KMALLOC(sizeof(usbbus_t),0); 1088 if (!bus) return NULL; 1089 1090 memset(softc,0,sizeof(ohci_softc_t)); 1091 memset(bus,0,sizeof(usbbus_t)); 1092 1093 bus->ub_hwsoftc = (usb_hc_t *) softc; 1094 bus->ub_hwdisp = &ohci_driver; 1095 1096 q_init(&(softc->ohci_rh_intrq)); 1097 1098#ifdef _CFE_ 1099 softc->ohci_regs = addr; 1100#else 1101 softc->ohci_regs = (volatile uint32_t *) addr; 1102#endif 1103 1104 softc->ohci_rh_newaddr = -1; 1105 softc->ohci_bus = bus; 1106 1107 if ((res = _ohci_initpools(softc)) != 0) goto error; 1108 if ((res = _ohci_setupepts(softc)) != 0) goto error; 1109 1110 OHCI_WRITECSR(softc,R_OHCI_CONTROL,V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_RESET)); 1111 1112 return bus; 1113 1114error: 1115 KFREE(softc); 1116 return NULL; 1117} 1118 1119 1120/* ********************************************************************* 1121 * ohci_ept_create(bus,usbaddr,eptnum,mps,flags) 1122 * 1123 * Create a hardware endpoint structure and attach it to 1124 * the hardware's endpoint list. The hardware manages lists 1125 * of queues, and this routine adds a new queue to the appropriate 1126 * list of queues for the endpoint in question. It roughly 1127 * corresponds to the information in the OHCI specification. 1128 * 1129 * Input parameters: 1130 * bus - the USB bus we're dealing with 1131 * usbaddr - USB address (0 means default address) 1132 * eptnum - the endpoint number 1133 * mps - the packet size for this endpoint 1134 * flags - various flags to control endpoint creation 1135 * 1136 * Return value: 1137 * endpoint structure poihter, or NULL 1138 ********************************************************************* */ 1139 1140static usb_ept_t *ohci_ept_create(usbbus_t *bus, 1141 int usbaddr, 1142 int eptnum, 1143 int mps, 1144 int flags) 1145{ 1146 uint32_t eptflags; 1147 ohci_endpoint_t *ept; 1148 ohci_ed_t *ed; 1149 ohci_transfer_t *tailtransfer; 1150 ohci_td_t *tailtd; 1151 ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc; 1152 1153 ept = _ohci_allocept(softc); 1154 ed = ohci_ed_from_endpoint(softc,ept); 1155 1156 tailtransfer = _ohci_allocxfer(softc); 1157 tailtd = ohci_td_from_transfer(softc,tailtransfer); 1158 1159 /* 1160 * Set up functional address, endpoint number, and packet size 1161 */ 1162 1163 eptflags = V_OHCI_ED_FA(usbaddr) | 1164 V_OHCI_ED_EN(eptnum) | 1165 V_OHCI_ED_MPS(mps) | 1166 0; 1167 1168 /* 1169 * Set up the endpoint type based on the flags 1170 * passed to us 1171 */ 1172 1173 if (flags & UP_TYPE_IN) { 1174 eptflags |= V_OHCI_ED_DIR(K_OHCI_ED_DIR_IN); 1175 } 1176 else if (flags & UP_TYPE_OUT) { 1177 eptflags |= V_OHCI_ED_DIR(K_OHCI_ED_DIR_OUT); 1178 } 1179 else { 1180 eptflags |= V_OHCI_ED_DIR(K_OHCI_ED_DIR_FROMTD); 1181 } 1182 1183 /* 1184 * Don't forget about lowspeed devices. 1185 */ 1186 1187 if (flags & UP_TYPE_LOWSPEED) { 1188 eptflags |= M_OHCI_ED_LOWSPEED; 1189 } 1190 1191 if (ohcidebug > 0) { 1192 printf("Create endpoint %d addr %d flags %08X mps %d\n", 1193 eptnum,usbaddr,eptflags,mps); 1194 } 1195 1196 /* 1197 * Transfer this info into the endpoint descriptor. 1198 * No need to flush the cache here, it'll get done when 1199 * we add to the hardware list. 1200 */ 1201 1202 ed->ed_control = BSWAP32(eptflags); 1203 ed->ed_tailp = BSWAP32(OHCI_VTOP(tailtd)); 1204 ed->ed_headp = BSWAP32(OHCI_VTOP(tailtd)); 1205 ept->ep_flags = flags; 1206 ept->ep_mps = mps; 1207 ept->ep_num = eptnum; 1208 1209 /* 1210 * Put it on the right queue 1211 */ 1212 1213 if (flags & UP_TYPE_CONTROL) { 1214 _ohci_queueept(softc,softc->ohci_ctl_list,ept); 1215 } 1216 else if (flags & UP_TYPE_BULK) { 1217 _ohci_queueept(softc,softc->ohci_bulk_list,ept); 1218 } 1219 else if (flags & UP_TYPE_INTR) { 1220 _ohci_queueept(softc,softc->ohci_inttable[0],ept); 1221 } 1222 1223 return (usb_ept_t *) ept; 1224} 1225 1226/* ********************************************************************* 1227 * ohci_ept_setaddr(bus,ept,usbaddr) 1228 * 1229 * Change the functional address for a USB endpoint. We do this 1230 * when we switch the device's state from DEFAULT to ADDRESSED 1231 * and we've already got the default pipe open. This 1232 * routine mucks with the descriptor and changes its address 1233 * bits. 1234 * 1235 * Input parameters: 1236 * bus - usb bus structure 1237 * ept - an open endpoint descriptor 1238 * usbaddr - new address for this endpoint 1239 * 1240 * Return value: 1241 * nothing 1242 ********************************************************************* */ 1243 1244static void ohci_ept_setaddr(usbbus_t *bus,usb_ept_t *uept,int usbaddr) 1245{ 1246 uint32_t eptflags; 1247 ohci_endpoint_t *ept = (ohci_endpoint_t *) uept; 1248 ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc; 1249 ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept); 1250 1251 eptflags = BSWAP32(ed->ed_control); 1252 eptflags &= ~M_OHCI_ED_FA; 1253 eptflags |= V_OHCI_ED_FA(usbaddr); 1254 ed->ed_control = BSWAP32(eptflags); 1255} 1256 1257 1258/* ********************************************************************* 1259 * ohci_ept_setmps(bus,ept,mps) 1260 * 1261 * Set the maximum packet size of this endpoint. This is 1262 * normally used during the processing of endpoint 0 (default 1263 * pipe) after we find out how big ep0's packets can be. 1264 * 1265 * Input parameters: 1266 * bus - our USB bus structure 1267 * ept - endpoint structure 1268 * mps - new packet size 1269 * 1270 * Return value: 1271 * nothing 1272 ********************************************************************* */ 1273 1274static void ohci_ept_setmps(usbbus_t *bus,usb_ept_t *uept,int mps) 1275{ 1276 uint32_t eptflags; 1277 ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc; 1278 ohci_endpoint_t *ept = (ohci_endpoint_t *) uept; 1279 ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept); 1280 1281 eptflags = BSWAP32(ed->ed_control); 1282 eptflags &= ~M_OHCI_ED_MPS; 1283 eptflags |= V_OHCI_ED_MPS(mps); 1284 ed->ed_control = BSWAP32(eptflags); 1285 ept->ep_mps = mps; 1286 1287} 1288 1289/* ********************************************************************* 1290 * ohci_ept_cleartoggle(bus,ept,mps) 1291 * 1292 * Clear the data toggle for the specified endpoint. 1293 * 1294 * Input parameters: 1295 * bus - our USB bus structure 1296 * ept - endpoint structure 1297 * 1298 * Return value: 1299 * nothing 1300 ********************************************************************* */ 1301 1302static void ohci_ept_cleartoggle(usbbus_t *bus,usb_ept_t *uept) 1303{ 1304 uint32_t eptflags; 1305 ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc; 1306 ohci_endpoint_t *ept = (ohci_endpoint_t *) uept; 1307 ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept); 1308 1309 eptflags = BSWAP32(ed->ed_headp); 1310 eptflags &= ~(M_OHCI_ED_HALT | M_OHCI_ED_TOGGLECARRY); 1311 ed->ed_headp = BSWAP32(eptflags); 1312 1313 OHCI_WRITECSR(softc,R_OHCI_CMDSTATUS,M_OHCI_CMDSTATUS_CLF); 1314} 1315 1316/* ********************************************************************* 1317 * ohci_ept_delete(bus,ept) 1318 * 1319 * Deletes an endpoint from the OHCI controller. This 1320 * routine also completes pending transfers for the 1321 * endpoint and gets rid of the hardware ept (queue base). 1322 * 1323 * Input parameters: 1324 * bus - ohci bus structure 1325 * ept - endpoint to remove 1326 * 1327 * Return value: 1328 * nothing 1329 ********************************************************************* */ 1330 1331static void ohci_ept_delete(usbbus_t *bus,usb_ept_t *uept) 1332{ 1333 ohci_endpoint_t *queue; 1334 ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc; 1335 ohci_endpoint_t *ept = (ohci_endpoint_t *) uept; 1336 ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept); 1337 uint32_t framenum; 1338 uint32_t tdphys; 1339 usbreq_t *ur; 1340 ohci_td_t *td; 1341 ohci_transfer_t *transfer; 1342 1343 if (ept->ep_flags & UP_TYPE_CONTROL) { 1344 queue = softc->ohci_ctl_list; 1345 } 1346 else if (ept->ep_flags & UP_TYPE_BULK) { 1347 queue = softc->ohci_bulk_list; 1348 } 1349 else if (ept->ep_flags & UP_TYPE_INTR) { 1350 queue = softc->ohci_inttable[0]; 1351 } 1352 else { 1353 printf("Invalid endpoint\n"); 1354 return; 1355 } 1356 1357 1358 /* 1359 * Set the SKIP bit on the endpoint and 1360 * wait for two SOFs to guarantee that we're 1361 * not processing this ED anymore. 1362 */ 1363 1364 ((volatile uint32_t) ed->ed_control) |= BSWAP32(M_OHCI_ED_SKIP); 1365 1366 framenum = OHCI_READCSR(softc,R_OHCI_FMNUMBER) & 0xFFFF; 1367 while ((OHCI_READCSR(softc,R_OHCI_FMNUMBER) & 0xFFFF) == framenum) ; /* NULL LOOP */ 1368 1369 framenum = OHCI_READCSR(softc,R_OHCI_FMNUMBER) & 0xFFFF; 1370 while ((OHCI_READCSR(softc,R_OHCI_FMNUMBER) & 0xFFFF) == framenum) ; /* NULL LOOP */ 1371 1372 /* 1373 * Remove endpoint from queue 1374 */ 1375 1376 _ohci_deqept(softc,queue,ept); 1377 1378 /* 1379 * Free/complete the TDs on the queue 1380 */ 1381 1382 tdphys = BSWAP32(ed->ed_headp) & M_OHCI_ED_PTRMASK; 1383 1384 while (tdphys != BSWAP32(ed->ed_tailp)) { 1385 td = (ohci_td_t *) OHCI_PTOV(tdphys); 1386 tdphys = BSWAP32(td->td_next_td); 1387 transfer = ohci_transfer_from_td(softc,td); 1388 1389 ur = transfer->t_ref; 1390 if (ur) { 1391 ur->ur_status = K_OHCI_CC_CANCELLED; 1392 ur->ur_tdcount--; 1393 if (ur->ur_tdcount == 0) { 1394 if (ohcidebug > 0) printf("Completing request due to closed pipe: %p\n",ur); 1395 usb_complete_request(ur,K_OHCI_CC_CANCELLED); 1396 } 1397 } 1398 1399 _ohci_freexfer(softc,transfer); 1400 } 1401 1402 /* 1403 * tdphys now points at the tail TD. Just free it. 1404 */ 1405 1406 td = (ohci_td_t *) OHCI_PTOV(tdphys); 1407 _ohci_freexfer(softc,ohci_transfer_from_td(softc,td)); 1408 1409 /* 1410 * Return endpoint to free pool 1411 */ 1412 1413 _ohci_freeept(softc,ept); 1414} 1415 1416 1417 1418/* ********************************************************************* 1419 * ohci_xfer(bus,ept,ur) 1420 * 1421 * Queue a transfer for the specified endpoint. Depending on 1422 * the transfer type, the transfer may go on one of many queues. 1423 * When the transfer completes, a callback will be called. 1424 * 1425 * Input parameters: 1426 * bus - bus structure 1427 * ept - endpoint descriptor 1428 * ur - request (includes pointer to user buffer) 1429 * 1430 * Return value: 1431 * 0 if ok 1432 * else error 1433 ********************************************************************* */ 1434 1435static int ohci_xfer(usbbus_t *bus,usb_ept_t *uept,usbreq_t *ur) 1436{ 1437 ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc; 1438 ohci_endpoint_t *ept = (ohci_endpoint_t *) uept; 1439 ohci_ed_t *ed = ohci_ed_from_endpoint(softc,ept); 1440 ohci_transfer_t *newtailtransfer = 0; 1441 ohci_td_t *newtailtd = NULL; 1442 ohci_transfer_t *curtransfer; 1443 ohci_td_t *curtd; 1444 uint8_t *ptr; 1445 int len; 1446 int amtcopy; 1447 int pktlen; 1448 uint32_t tdcontrol = 0; 1449 1450 /* 1451 * If the destination USB address matches 1452 * the address of the root hub, shunt the request 1453 * over to our root hub emulation. 1454 */ 1455 1456 if (ur->ur_dev->ud_address == softc->ohci_rh_addr) { 1457 return ohci_roothub_xfer(bus,uept,ur); 1458 } 1459 1460 /* 1461 * Set up the TD flags based on the 1462 * request type. 1463 */ 1464 1465// pktlen = ept->ep_mps; 1466 pktlen = OHCI_TD_MAX_DATA - 16; 1467 1468 if (ur->ur_flags & UR_FLAG_SETUP) { 1469 tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_SETUP) | 1470 V_OHCI_TD_DT(K_OHCI_TD_DT_DATA0) | 1471 V_OHCI_TD_CC(K_OHCI_CC_NOTACCESSED) | 1472 V_OHCI_TD_DI(1); 1473 } 1474 else if (ur->ur_flags & UR_FLAG_IN) { 1475 tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_IN) | 1476 V_OHCI_TD_DT(K_OHCI_TD_DT_TCARRY) | 1477 V_OHCI_TD_CC(K_OHCI_CC_NOTACCESSED) | 1478 V_OHCI_TD_DI(1); 1479 } 1480 else if (ur->ur_flags & UR_FLAG_OUT) { 1481 tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_OUT) | 1482 V_OHCI_TD_DT(K_OHCI_TD_DT_TCARRY) | 1483 V_OHCI_TD_CC(K_OHCI_CC_NOTACCESSED) | 1484 V_OHCI_TD_DI(1); 1485 } 1486 else if (ur->ur_flags & UR_FLAG_STATUS_OUT) { 1487 tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_OUT) | 1488 V_OHCI_TD_DT(K_OHCI_TD_DT_DATA1) | 1489 V_OHCI_TD_CC(K_OHCI_CC_NOTACCESSED) | 1490 V_OHCI_TD_DI(1); 1491 } 1492 else if (ur->ur_flags & UR_FLAG_STATUS_IN) { 1493 tdcontrol = V_OHCI_TD_PID(K_OHCI_TD_IN) | 1494 V_OHCI_TD_DT(K_OHCI_TD_DT_DATA1) | 1495 V_OHCI_TD_CC(K_OHCI_CC_NOTACCESSED) | 1496 V_OHCI_TD_DI(1); 1497 } 1498 else { 1499 printf("Shouldn't happen!\n"); 1500 } 1501 1502 if (ur->ur_flags & UR_FLAG_SHORTOK) { 1503 tdcontrol |= M_OHCI_TD_SHORTOK; 1504 } 1505 1506 1507 ptr = ur->ur_buffer; 1508 len = ur->ur_length; 1509 ur->ur_tdcount = 0; 1510 1511 if (ohcidebug > 1) { 1512 printf(">> Queueing xfer addr %d pipe %d ED %08X ptr %016llX length %d\n", 1513 ur->ur_dev->ud_address, 1514 ur->ur_pipe->up_num, 1515 ept->ep_phys, 1516 (uint64_t) (uintptr_t) ptr, 1517 len); 1518// ohci_dumped(ed); 1519 } 1520 1521 curtd = OHCI_PTOV(BSWAP32(ed->ed_tailp)); 1522 curtransfer = ohci_transfer_from_td(softc,curtd); 1523 1524 if (len == 0) { 1525 newtailtransfer = _ohci_allocxfer(softc); 1526 newtailtd = ohci_td_from_transfer(softc,newtailtransfer); 1527 curtd->td_cbp = 0; 1528 curtd->td_be = 0; 1529 curtd->td_next_td = BSWAP32(OHCI_VTOP(newtailtd)); 1530 curtd->td_control = BSWAP32(tdcontrol); 1531 curtransfer->t_next = newtailtransfer; 1532 curtransfer->t_ref = ur; 1533 curtransfer->t_length = 0; 1534 if (ohcidebug > 1) { printf("QueueTD: "); ohci_dumptd(curtd); } 1535 ur->ur_tdcount++; 1536 } 1537 else { 1538 /* Noncoherent DMA: need to flush user buffer to real memory first */ 1539 OHCI_FLUSH_RANGE(ptr,len); 1540 while (len > 0) { 1541 amtcopy = len; 1542 if (amtcopy > pktlen) amtcopy = pktlen; 1543 newtailtransfer = _ohci_allocxfer(softc); 1544 newtailtd = ohci_td_from_transfer(softc,newtailtransfer); 1545 curtd->td_cbp = BSWAP32(OHCI_VTOP(ptr)); 1546 curtd->td_be = BSWAP32(OHCI_VTOP(ptr+amtcopy)-1); 1547 curtd->td_next_td = BSWAP32(OHCI_VTOP(newtailtd)); 1548 curtd->td_control = BSWAP32(tdcontrol); 1549 curtransfer->t_next = newtailtransfer; 1550 curtransfer->t_ref = ur; 1551 curtransfer->t_length = amtcopy; 1552 if (ohcidebug > 1) { printf("QueueTD: "); ohci_dumptd(curtd); } 1553 curtd = newtailtd; 1554 curtransfer = ohci_transfer_from_td(softc,curtd); 1555 ptr += amtcopy; 1556 len -= amtcopy; 1557 ur->ur_tdcount++; 1558 } 1559 } 1560 1561 curtd = OHCI_PTOV(BSWAP32(ed->ed_headp & M_OHCI_ED_PTRMASK)); 1562 ed->ed_tailp = BSWAP32(OHCI_VTOP(newtailtd)); 1563 1564 /* 1565 * Prod the controller depending on what type of list we put 1566 * a TD on. 1567 */ 1568 1569 if (ept->ep_flags & UP_TYPE_BULK) { 1570 OHCI_WRITECSR(softc,R_OHCI_CMDSTATUS,M_OHCI_CMDSTATUS_BLF); 1571 } 1572 else { 1573 OHCI_WRITECSR(softc,R_OHCI_CMDSTATUS,M_OHCI_CMDSTATUS_CLF); 1574 } 1575 1576 return 0; 1577} 1578 1579/* ********************************************************************* 1580 * Driver structure 1581 ********************************************************************* */ 1582 1583usb_hcdrv_t ohci_driver = { 1584 ohci_create, 1585 ohci_delete, 1586 ohci_start, 1587 ohci_stop, 1588 ohci_intr, 1589 ohci_ept_create, 1590 ohci_ept_delete, 1591 ohci_ept_setmps, 1592 ohci_ept_setaddr, 1593 ohci_ept_cleartoggle, 1594 ohci_xfer 1595}; 1596 1597/* ********************************************************************* 1598 * Root Hub 1599 * 1600 * Data structures and functions 1601 ********************************************************************* */ 1602 1603/* 1604 * Data structures and routines to emulate the root hub. 1605 */ 1606static usb_device_descr_t ohci_root_devdsc = { 1607 sizeof(usb_device_descr_t), /* bLength */ 1608 USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */ 1609 USBWORD(0x0100), /* bcdUSB */ 1610 USB_DEVICE_CLASS_HUB, /* bDeviceClass */ 1611 0, /* bDeviceSubClass */ 1612 0, /* bDeviceProtocol */ 1613 64, /* bMaxPacketSize0 */ 1614 USBWORD(0), /* idVendor */ 1615 USBWORD(0), /* idProduct */ 1616 USBWORD(0x0100), /* bcdDevice */ 1617 1, /* iManufacturer */ 1618 2, /* iProduct */ 1619 0, /* iSerialNumber */ 1620 1 /* bNumConfigurations */ 1621}; 1622 1623static usb_config_descr_t ohci_root_cfgdsc = { 1624 sizeof(usb_config_descr_t), /* bLength */ 1625 USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */ 1626 USBWORD( 1627 sizeof(usb_config_descr_t) + 1628 sizeof(usb_interface_descr_t) + 1629 sizeof(usb_endpoint_descr_t)), /* wTotalLength */ 1630 1, /* bNumInterfaces */ 1631 1, /* bConfigurationValue */ 1632 0, /* iConfiguration */ 1633 USB_CONFIG_SELF_POWERED, /* bmAttributes */ 1634 0 /* MaxPower */ 1635}; 1636 1637static usb_interface_descr_t ohci_root_ifdsc = { 1638 sizeof(usb_interface_descr_t), /* bLength */ 1639 USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ 1640 0, /* bInterfaceNumber */ 1641 0, /* bAlternateSetting */ 1642 1, /* bNumEndpoints */ 1643 USB_INTERFACE_CLASS_HUB, /* bInterfaceClass */ 1644 0, /* bInterfaceSubClass */ 1645 0, /* bInterfaceProtocol */ 1646 0 /* iInterface */ 1647}; 1648 1649static usb_endpoint_descr_t ohci_root_epdsc = { 1650 sizeof(usb_endpoint_descr_t), /* bLength */ 1651 USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ 1652 (USB_ENDPOINT_DIRECTION_IN | 1), /* bEndpointAddress */ 1653 USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ 1654 USBWORD(8), /* wMaxPacketSize */ 1655 255 /* bInterval */ 1656}; 1657 1658static usb_hub_descr_t ohci_root_hubdsc = { 1659 USB_HUB_DESCR_SIZE, /* bLength */ 1660 USB_HUB_DESCRIPTOR_TYPE, /* bDescriptorType */ 1661 0, /* bNumberOfPorts */ 1662 USBWORD(0), /* wHubCharacteristics */ 1663 0, /* bPowreOnToPowerGood */ 1664 0, /* bHubControl Current */ 1665 {0} /* bRemoveAndPowerMask */ 1666}; 1667 1668/* ********************************************************************* 1669 * ohci_roothb_strdscr(ptr,str) 1670 * 1671 * Construct a string descriptor for root hub requests 1672 * 1673 * Input parameters: 1674 * ptr - pointer to where to put descriptor 1675 * str - regular string to put into descriptor 1676 * 1677 * Return value: 1678 * number of bytes written to descriptor 1679 ********************************************************************* */ 1680 1681static int ohci_roothub_strdscr(uint8_t *ptr,char *str) 1682{ 1683 uint8_t *p = ptr; 1684 1685 *p++ = strlen(str)*2 + 2; /* Unicode strings */ 1686 *p++ = USB_STRING_DESCRIPTOR_TYPE; 1687 while (*str) { 1688 *p++ = *str++; 1689 *p++ = 0; 1690 } 1691 return (p - ptr); 1692} 1693 1694/* ********************************************************************* 1695 * ohci_roothub_req(softc,req) 1696 * 1697 * Handle a descriptor request on the control pipe for the 1698 * root hub. We pretend to be a real root hub here and 1699 * return all the standard descriptors. 1700 * 1701 * Input parameters: 1702 * softc - our OHCI controller 1703 * req - a usb request (completed immediately) 1704 * 1705 * Return value: 1706 * 0 if ok 1707 * else error code 1708 ********************************************************************* */ 1709 1710static int ohci_roothub_req(ohci_softc_t *softc,usb_device_request_t *req) 1711{ 1712 uint8_t *ptr; 1713 uint16_t wLength; 1714 uint16_t wValue; 1715 uint16_t wIndex; 1716 usb_port_status_t ups; 1717 usb_hub_descr_t hdsc; 1718 uint32_t status; 1719 uint32_t statport; 1720 uint32_t tmpval; 1721 int res = 0; 1722 1723 ptr = softc->ohci_rh_buf; 1724 1725 wLength = GETUSBFIELD(req,wLength); 1726 wValue = GETUSBFIELD(req,wValue); 1727 wIndex = GETUSBFIELD(req,wIndex); 1728 1729 switch (REQSW(req->bRequest,req->bmRequestType)) { 1730 1731 case REQCODE(USB_REQUEST_GET_STATUS,USBREQ_DIR_IN,USBREQ_TYPE_STD,USBREQ_REC_DEVICE): 1732 *ptr++ = (USB_GETSTATUS_SELF_POWERED & 0xFF); 1733 *ptr++ = (USB_GETSTATUS_SELF_POWERED >> 8); 1734 break; 1735 1736 case REQCODE(USB_REQUEST_GET_STATUS,USBREQ_DIR_IN,USBREQ_TYPE_STD,USBREQ_REC_ENDPOINT): 1737 case REQCODE(USB_REQUEST_GET_STATUS,USBREQ_DIR_IN,USBREQ_TYPE_STD,USBREQ_REC_INTERFACE): 1738 *ptr++ = 0; 1739 *ptr++ = 0; 1740 break; 1741 1742 case REQCODE(USB_REQUEST_GET_STATUS,USBREQ_DIR_IN,USBREQ_TYPE_CLASS,USBREQ_REC_OTHER): 1743 status = OHCI_READCSR(softc,(R_OHCI_RHPORTSTATUS(wIndex))); 1744 if (ohcidebug > 0) { printf("RHGetStatus: "); ohci_dumpportstat(wIndex,status);} 1745 PUTUSBFIELD((&ups),wPortStatus,(status & 0xFFFF)); 1746 PUTUSBFIELD((&ups),wPortChange,(status >> 16)); 1747 memcpy(ptr,&ups,sizeof(ups)); 1748 ptr += sizeof(ups); 1749 break; 1750 1751 case REQCODE(USB_REQUEST_GET_STATUS,USBREQ_DIR_IN,USBREQ_TYPE_CLASS,USBREQ_REC_DEVICE): 1752 *ptr++ = 0; 1753 *ptr++ = 0; 1754 *ptr++ = 0; 1755 *ptr++ = 0; 1756 break; 1757 1758 case REQCODE(USB_REQUEST_CLEAR_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_DEVICE): 1759 case REQCODE(USB_REQUEST_CLEAR_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_INTERFACE): 1760 case REQCODE(USB_REQUEST_CLEAR_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_ENDPOINT): 1761 /* do nothing, not supported */ 1762 break; 1763 1764 case REQCODE(USB_REQUEST_CLEAR_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_CLASS,USBREQ_REC_OTHER): 1765 statport = R_OHCI_RHPORTSTATUS(wIndex); 1766 if (ohcidebug> 0) { 1767 printf("RHClearFeature(%d): ",wValue); ohci_dumpportstat(wIndex,OHCI_READCSR(softc,statport)); 1768 } 1769 switch (wValue) { 1770 case USB_PORT_FEATURE_CONNECTION: 1771 break; 1772 case USB_PORT_FEATURE_ENABLE: 1773 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_CCS); 1774 break; 1775 case USB_PORT_FEATURE_SUSPEND: 1776 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_POCI); 1777 break; 1778 case USB_PORT_FEATURE_OVER_CURRENT: 1779 break; 1780 case USB_PORT_FEATURE_RESET: 1781 break; 1782 case USB_PORT_FEATURE_POWER: 1783 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_LSDA); 1784 break; 1785 case USB_PORT_FEATURE_LOW_SPEED: 1786 break; 1787 case USB_PORT_FEATURE_C_PORT_CONNECTION: 1788 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_CSC); 1789 break; 1790 case USB_PORT_FEATURE_C_PORT_ENABLE: 1791 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PESC); 1792 break; 1793 case USB_PORT_FEATURE_C_PORT_SUSPEND: 1794 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PSSC); 1795 break; 1796 case USB_PORT_FEATURE_C_PORT_OVER_CURRENT: 1797 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_OCIC); 1798 break; 1799 case USB_PORT_FEATURE_C_PORT_RESET: 1800 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PRSC); 1801 break; 1802 1803 } 1804 1805 /* 1806 * If we've cleared all of the conditions that 1807 * want our attention on the port status, 1808 * then we can accept port status interrupts again. 1809 */ 1810 1811 if ((wValue >= USB_PORT_FEATURE_C_PORT_CONNECTION) && 1812 (wValue <= USB_PORT_FEATURE_C_PORT_RESET)) { 1813 status = OHCI_READCSR(softc,statport); 1814 if ((status & M_OHCI_RHPORTSTAT_ALLC) == 0) { 1815 softc->ohci_intdisable &= ~M_OHCI_INT_RHSC; 1816 } 1817 } 1818 break; 1819 1820 case REQCODE(USB_REQUEST_SET_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_DEVICE): 1821 case REQCODE(USB_REQUEST_SET_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_INTERFACE): 1822 case REQCODE(USB_REQUEST_SET_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_ENDPOINT): 1823 res = -1; 1824 break; 1825 1826 case REQCODE(USB_REQUEST_SET_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_CLASS,USBREQ_REC_DEVICE): 1827 /* nothing */ 1828 break; 1829 1830 case REQCODE(USB_REQUEST_SET_FEATURE,USBREQ_DIR_OUT,USBREQ_TYPE_CLASS,USBREQ_REC_OTHER): 1831 statport = R_OHCI_RHPORTSTATUS(wIndex); 1832 switch (wValue) { 1833 case USB_PORT_FEATURE_CONNECTION: 1834 break; 1835 case USB_PORT_FEATURE_ENABLE: 1836 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PES); 1837 break; 1838 case USB_PORT_FEATURE_SUSPEND: 1839 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PSS); 1840 break; 1841 case USB_PORT_FEATURE_OVER_CURRENT: 1842 break; 1843 case USB_PORT_FEATURE_RESET: 1844 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PRS); 1845 for (;;) { 1846 usb_delay_ms(softc->ohci_bus,100); 1847 if (!(OHCI_READCSR(softc,statport) & M_OHCI_RHPORTSTAT_PRS)) break; 1848 } 1849 break; 1850 case USB_PORT_FEATURE_POWER: 1851 OHCI_WRITECSR(softc,statport,M_OHCI_RHPORTSTAT_PPS); 1852 break; 1853 case USB_PORT_FEATURE_LOW_SPEED: 1854 break; 1855 case USB_PORT_FEATURE_C_PORT_CONNECTION: 1856 break; 1857 case USB_PORT_FEATURE_C_PORT_ENABLE: 1858 break; 1859 case USB_PORT_FEATURE_C_PORT_SUSPEND: 1860 break; 1861 case USB_PORT_FEATURE_C_PORT_OVER_CURRENT: 1862 break; 1863 case USB_PORT_FEATURE_C_PORT_RESET: 1864 break; 1865 1866 } 1867 1868 break; 1869 1870 case REQCODE(USB_REQUEST_SET_ADDRESS,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_DEVICE): 1871 softc->ohci_rh_newaddr = wValue; 1872 break; 1873 1874 case REQCODE(USB_REQUEST_GET_DESCRIPTOR,USBREQ_DIR_IN,USBREQ_TYPE_STD,USBREQ_REC_DEVICE): 1875 switch (wValue >> 8) { 1876 case USB_DEVICE_DESCRIPTOR_TYPE: 1877 memcpy(ptr,&ohci_root_devdsc,sizeof(ohci_root_devdsc)); 1878 ptr += sizeof(ohci_root_devdsc); 1879 break; 1880 case USB_CONFIGURATION_DESCRIPTOR_TYPE: 1881 memcpy(ptr,&ohci_root_cfgdsc,sizeof(ohci_root_cfgdsc)); 1882 ptr += sizeof(ohci_root_cfgdsc); 1883 memcpy(ptr,&ohci_root_ifdsc,sizeof(ohci_root_ifdsc)); 1884 ptr += sizeof(ohci_root_ifdsc); 1885 memcpy(ptr,&ohci_root_epdsc,sizeof(ohci_root_epdsc)); 1886 ptr += sizeof(ohci_root_epdsc); 1887 break; 1888 case USB_STRING_DESCRIPTOR_TYPE: 1889 switch (wValue & 0xFF) { 1890 case 1: 1891 ptr += ohci_roothub_strdscr(ptr,"Generic"); 1892 break; 1893 case 2: 1894 ptr += ohci_roothub_strdscr(ptr,"Root Hub"); 1895 break; 1896 default: 1897 *ptr++ = 0; 1898 break; 1899 } 1900 break; 1901 default: 1902 res = -1; 1903 break; 1904 } 1905 break; 1906 1907 case REQCODE(USB_REQUEST_GET_DESCRIPTOR,USBREQ_DIR_IN,USBREQ_TYPE_CLASS,USBREQ_REC_DEVICE): 1908 memcpy(&hdsc,&ohci_root_hubdsc,sizeof(hdsc)); 1909 hdsc.bNumberOfPorts = softc->ohci_ndp; 1910 status = OHCI_READCSR(softc,R_OHCI_RHDSCRA); 1911 tmpval = 0; 1912 if (status & M_OHCI_RHDSCRA_NPS) tmpval |= USB_HUBCHAR_PWR_NONE; 1913 if (status & M_OHCI_RHDSCRA_PSM) tmpval |= USB_HUBCHAR_PWR_GANGED; 1914 else tmpval |= USB_HUBCHAR_PWR_IND; 1915 PUTUSBFIELD((&hdsc),wHubCharacteristics,tmpval); 1916 tmpval = G_OHCI_RHDSCRA_POTPGT(status); 1917 hdsc.bPowerOnToPowerGood = tmpval; 1918 hdsc.bDescriptorLength = USB_HUB_DESCR_SIZE + 1; 1919 status = OHCI_READCSR(softc,R_OHCI_RHDSCRB); 1920 hdsc.bRemoveAndPowerMask[0] = (uint8_t) status; 1921 memcpy(ptr,&hdsc,sizeof(hdsc)); 1922 ptr += sizeof(hdsc); 1923 break; 1924 1925 case REQCODE(USB_REQUEST_SET_DESCRIPTOR,USBREQ_DIR_OUT,USBREQ_TYPE_CLASS,USBREQ_REC_DEVICE): 1926 /* nothing */ 1927 break; 1928 1929 case REQCODE(USB_REQUEST_GET_CONFIGURATION,USBREQ_DIR_IN,USBREQ_TYPE_STD,USBREQ_REC_DEVICE): 1930 *ptr++ = softc->ohci_rh_conf; 1931 break; 1932 1933 case REQCODE(USB_REQUEST_SET_CONFIGURATION,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_DEVICE): 1934 softc->ohci_rh_conf = wValue; 1935 break; 1936 1937 case REQCODE(USB_REQUEST_GET_INTERFACE,USBREQ_DIR_IN,USBREQ_TYPE_STD,USBREQ_REC_INTERFACE): 1938 *ptr++ = 0; 1939 break; 1940 1941 case REQCODE(USB_REQUEST_SET_INTERFACE,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_INTERFACE): 1942 /* nothing */ 1943 break; 1944 1945 case REQCODE(USB_REQUEST_SYNC_FRAME,USBREQ_DIR_OUT,USBREQ_TYPE_STD,USBREQ_REC_ENDPOINT): 1946 /* nothing */ 1947 break; 1948 } 1949 1950 softc->ohci_rh_ptr = softc->ohci_rh_buf; 1951 softc->ohci_rh_len = ptr - softc->ohci_rh_buf; 1952 1953 return res; 1954} 1955 1956/* ********************************************************************* 1957 * ohci_roothub_statchg(softc) 1958 * 1959 * This routine is called from the interrupt service routine 1960 * (well, polling routine) for the ohci controller. If the 1961 * controller notices a root hub status change, it dequeues an 1962 * interrupt transfer from the root hub's queue and completes 1963 * it here. 1964 * 1965 * Input parameters: 1966 * softc - our OHCI controller 1967 * 1968 * Return value: 1969 * nothing 1970 ********************************************************************* */ 1971 1972static void ohci_roothub_statchg(ohci_softc_t *softc) 1973{ 1974 usbreq_t *ur; 1975 uint32_t status; 1976 uint8_t portstat = 0; 1977 int idx; 1978 1979 /* Note: this only works up to 8 ports */ 1980 for (idx = 1; idx <= softc->ohci_ndp; idx++) { 1981 status = OHCI_READCSR(softc,R_OHCI_RHPORTSTATUS(idx)); 1982 if (status & M_OHCI_RHPORTSTAT_ALLC) { 1983 portstat = (1<<idx); 1984 } 1985 } 1986 1987 if (portstat != 0) { 1988 softc->ohci_intdisable |= M_OHCI_INT_RHSC; 1989 } 1990 1991 ur = (usbreq_t *) q_deqnext(&(softc->ohci_rh_intrq)); 1992 if (!ur) return; /* no requests pending, ignore it */ 1993 1994 memset(ur->ur_buffer,0,ur->ur_length); 1995 ur->ur_buffer[0] = portstat; 1996 ur->ur_xferred = ur->ur_length; 1997 1998 usb_complete_request(ur,0); 1999} 2000 2001/* ********************************************************************* 2002 * ohci_roothub_xfer(softc,req) 2003 * 2004 * Handle a root hub xfer - ohci_xfer transfers control here 2005 * if we detect the address of the root hub - no actual transfers 2006 * go out on the wire, we just handle the requests directly to 2007 * make it look like a hub is attached. 2008 * 2009 * This seems to be common practice in the USB world, so we do 2010 * it here too. 2011 * 2012 * Input parameters: 2013 * softc - our OHCI controller structure 2014 * req - usb request destined for host controller 2015 * 2016 * Return value: 2017 * 0 if ok 2018 * else error 2019 ********************************************************************* */ 2020 2021static int ohci_roothub_xfer(usbbus_t *bus,usb_ept_t *uept,usbreq_t *ur) 2022{ 2023 ohci_softc_t *softc = (ohci_softc_t *) bus->ub_hwsoftc; 2024 ohci_endpoint_t *ept = (ohci_endpoint_t *) uept; 2025 int res; 2026 2027 switch (ept->ep_num) { 2028 2029 /* 2030 * CONTROL ENDPOINT 2031 */ 2032 case 0: 2033 2034 /* 2035 * Three types of transfers: OUT (SETUP), IN (data), or STATUS. 2036 * figure out which is which. 2037 */ 2038 2039 if (ur->ur_flags & UR_FLAG_SETUP) { 2040 /* 2041 * SETUP packet - this is an OUT request to the control 2042 * pipe. We emulate the hub request here. 2043 */ 2044 usb_device_request_t *req; 2045 2046 req = (usb_device_request_t *) ur->ur_buffer; 2047 2048 res = ohci_roothub_req(softc,req); 2049 if (res != 0) printf("Root hub request returned an error\n"); 2050 2051 ur->ur_xferred = ur->ur_length; 2052 ur->ur_status = 0; 2053 usb_complete_request(ur,0); 2054 } 2055 2056 else if (ur->ur_flags & UR_FLAG_STATUS_IN) { 2057 /* 2058 * STATUS IN : it's sort of like a dummy IN request 2059 * to acknowledge a SETUP packet that otherwise has no 2060 * status. Just complete the usbreq. 2061 */ 2062 2063 if (softc->ohci_rh_newaddr != -1) { 2064 softc->ohci_rh_addr = softc->ohci_rh_newaddr; 2065 softc->ohci_rh_newaddr = -1; 2066 } 2067 2068 ur->ur_status = 0; 2069 ur->ur_xferred = 0; 2070 usb_complete_request(ur,0); 2071 } 2072 2073 else if (ur->ur_flags & UR_FLAG_STATUS_OUT) { 2074 /* 2075 * STATUS OUT : it's sort of like a dummy OUT request 2076 */ 2077 ur->ur_status = 0; 2078 ur->ur_xferred = 0; 2079 usb_complete_request(ur,0); 2080 } 2081 2082 else if (ur->ur_flags & UR_FLAG_IN) { 2083 /* 2084 * IN : return data from the root hub 2085 */ 2086 int amtcopy; 2087 2088 amtcopy = softc->ohci_rh_len; 2089 if (amtcopy > ur->ur_length) amtcopy = ur->ur_length; 2090 2091 memcpy(ur->ur_buffer,softc->ohci_rh_ptr,amtcopy); 2092 2093 softc->ohci_rh_ptr += amtcopy; 2094 softc->ohci_rh_len -= amtcopy; 2095 2096 ur->ur_status = 0; 2097 ur->ur_xferred = amtcopy; 2098 usb_complete_request(ur,0); 2099 } 2100 2101 else { 2102 printf("Unknown root hub transfer type\n"); 2103 return -1; 2104 } 2105 break; 2106 2107 /* 2108 * INTERRUPT ENDPOINT 2109 */ 2110 2111 case 1: /* interrupt pipe */ 2112 if (ur->ur_flags & UR_FLAG_IN) { 2113 q_enqueue(&(softc->ohci_rh_intrq),(queue_t *) ur); 2114 } 2115 break; 2116 2117 } 2118 2119 2120 return 0; 2121} 2122