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