1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2008 Hans Petter Selasky <hselasky@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 * This file contains the driver for the USS820 series USB Device 31 * Controller 32 * 33 * NOTE: The datasheet does not document everything. 34 */ 35 36 #ifdef USB_GLOBAL_INCLUDE_FILE 37 #include USB_GLOBAL_INCLUDE_FILE 38 #else 39 #include <sys/stdint.h> 40 #include <sys/stddef.h> 41 #include <sys/param.h> 42 #include <sys/queue.h> 43 #include <sys/types.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/bus.h> 47 #include <sys/module.h> 48 #include <sys/lock.h> 49 #include <sys/mutex.h> 50 #include <sys/condvar.h> 51 #include <sys/sysctl.h> 52 #include <sys/sx.h> 53 #include <sys/unistd.h> 54 #include <sys/callout.h> 55 #include <sys/malloc.h> 56 #include <sys/priv.h> 57 58 #include <dev/usb/usb.h> 59 #include <dev/usb/usbdi.h> 60 61 #define USB_DEBUG_VAR uss820dcidebug 62 63 #include <dev/usb/usb_core.h> 64 #include <dev/usb/usb_debug.h> 65 #include <dev/usb/usb_busdma.h> 66 #include <dev/usb/usb_process.h> 67 #include <dev/usb/usb_transfer.h> 68 #include <dev/usb/usb_device.h> 69 #include <dev/usb/usb_hub.h> 70 #include <dev/usb/usb_util.h> 71 72 #include <dev/usb/usb_controller.h> 73 #include <dev/usb/usb_bus.h> 74 #endif /* USB_GLOBAL_INCLUDE_FILE */ 75 76 #include <dev/usb/controller/uss820dci.h> 77 78 #define USS820_DCI_BUS2SC(bus) \ 79 __containerof(bus, struct uss820dci_softc, sc_bus) 80 81 #define USS820_DCI_PC2SC(pc) \ 82 USS820_DCI_BUS2SC(USB_DMATAG_TO_XROOT((pc)->tag_parent)->bus) 83 84 #define USS820_DCI_THREAD_IRQ \ 85 (USS820_SSR_SUSPEND | USS820_SSR_RESUME | USS820_SSR_RESET) 86 87 #ifdef USB_DEBUG 88 static int uss820dcidebug = 0; 89 90 static SYSCTL_NODE(_hw_usb, OID_AUTO, uss820dci, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 91 "USB uss820dci"); 92 SYSCTL_INT(_hw_usb_uss820dci, OID_AUTO, debug, CTLFLAG_RWTUN, 93 &uss820dcidebug, 0, "uss820dci debug level"); 94 #endif 95 96 #define USS820_DCI_INTR_ENDPT 1 97 98 /* prototypes */ 99 100 static const struct usb_bus_methods uss820dci_bus_methods; 101 static const struct usb_pipe_methods uss820dci_device_bulk_methods; 102 static const struct usb_pipe_methods uss820dci_device_ctrl_methods; 103 static const struct usb_pipe_methods uss820dci_device_intr_methods; 104 static const struct usb_pipe_methods uss820dci_device_isoc_fs_methods; 105 106 static uss820dci_cmd_t uss820dci_setup_rx; 107 static uss820dci_cmd_t uss820dci_data_rx; 108 static uss820dci_cmd_t uss820dci_data_tx; 109 static uss820dci_cmd_t uss820dci_data_tx_sync; 110 static void uss820dci_device_done(struct usb_xfer *, usb_error_t); 111 static void uss820dci_do_poll(struct usb_bus *); 112 static void uss820dci_standard_done(struct usb_xfer *); 113 static void uss820dci_intr_set(struct usb_xfer *, uint8_t); 114 static void uss820dci_update_shared_1(struct uss820dci_softc *, uint8_t, 115 uint8_t, uint8_t); 116 static void uss820dci_root_intr(struct uss820dci_softc *); 117 118 /* 119 * Here is a list of what the USS820D chip can support. The main 120 * limitation is that the sum of the buffer sizes must be less than 121 * 1120 bytes. 122 */ 123 static const struct usb_hw_ep_profile 124 uss820dci_ep_profile[] = { 125 [0] = { 126 .max_in_frame_size = 32, 127 .max_out_frame_size = 32, 128 .is_simplex = 0, 129 .support_control = 1, 130 }, 131 [1] = { 132 .max_in_frame_size = 64, 133 .max_out_frame_size = 64, 134 .is_simplex = 0, 135 .support_multi_buffer = 1, 136 .support_bulk = 1, 137 .support_interrupt = 1, 138 .support_in = 1, 139 .support_out = 1, 140 }, 141 [2] = { 142 .max_in_frame_size = 8, 143 .max_out_frame_size = 8, 144 .is_simplex = 0, 145 .support_multi_buffer = 1, 146 .support_bulk = 1, 147 .support_interrupt = 1, 148 .support_in = 1, 149 .support_out = 1, 150 }, 151 [3] = { 152 .max_in_frame_size = 256, 153 .max_out_frame_size = 256, 154 .is_simplex = 0, 155 .support_multi_buffer = 1, 156 .support_isochronous = 1, 157 .support_in = 1, 158 .support_out = 1, 159 }, 160 }; 161 162 static void 163 uss820dci_update_shared_1(struct uss820dci_softc *sc, uint8_t reg, 164 uint8_t keep_mask, uint8_t set_mask) 165 { 166 uint8_t temp; 167 168 USS820_WRITE_1(sc, USS820_PEND, 1); 169 temp = USS820_READ_1(sc, reg); 170 temp &= (keep_mask); 171 temp |= (set_mask); 172 USS820_WRITE_1(sc, reg, temp); 173 USS820_WRITE_1(sc, USS820_PEND, 0); 174 } 175 176 static void 177 uss820dci_get_hw_ep_profile(struct usb_device *udev, 178 const struct usb_hw_ep_profile **ppf, uint8_t ep_addr) 179 { 180 if (ep_addr == 0) { 181 *ppf = uss820dci_ep_profile + 0; 182 } else if (ep_addr < 5) { 183 *ppf = uss820dci_ep_profile + 1; 184 } else if (ep_addr < 7) { 185 *ppf = uss820dci_ep_profile + 2; 186 } else if (ep_addr == 7) { 187 *ppf = uss820dci_ep_profile + 3; 188 } else { 189 *ppf = NULL; 190 } 191 } 192 193 static void 194 uss820dci_pull_up(struct uss820dci_softc *sc) 195 { 196 uint8_t temp; 197 198 /* pullup D+, if possible */ 199 200 if (!sc->sc_flags.d_pulled_up && 201 sc->sc_flags.port_powered) { 202 sc->sc_flags.d_pulled_up = 1; 203 204 DPRINTF("\n"); 205 206 temp = USS820_READ_1(sc, USS820_MCSR); 207 temp |= USS820_MCSR_DPEN; 208 USS820_WRITE_1(sc, USS820_MCSR, temp); 209 } 210 } 211 212 static void 213 uss820dci_pull_down(struct uss820dci_softc *sc) 214 { 215 uint8_t temp; 216 217 /* pulldown D+, if possible */ 218 219 if (sc->sc_flags.d_pulled_up) { 220 sc->sc_flags.d_pulled_up = 0; 221 222 DPRINTF("\n"); 223 224 temp = USS820_READ_1(sc, USS820_MCSR); 225 temp &= ~USS820_MCSR_DPEN; 226 USS820_WRITE_1(sc, USS820_MCSR, temp); 227 } 228 } 229 230 static void 231 uss820dci_wakeup_peer(struct uss820dci_softc *sc) 232 { 233 if (!(sc->sc_flags.status_suspend)) { 234 return; 235 } 236 DPRINTFN(0, "not supported\n"); 237 } 238 239 static void 240 uss820dci_set_address(struct uss820dci_softc *sc, uint8_t addr) 241 { 242 DPRINTFN(5, "addr=%d\n", addr); 243 244 USS820_WRITE_1(sc, USS820_FADDR, addr); 245 } 246 247 static uint8_t 248 uss820dci_setup_rx(struct uss820dci_softc *sc, struct uss820dci_td *td) 249 { 250 struct usb_device_request req; 251 uint16_t count; 252 uint8_t rx_stat; 253 uint8_t temp; 254 255 /* select the correct endpoint */ 256 USS820_WRITE_1(sc, USS820_EPINDEX, td->ep_index); 257 258 /* read out FIFO status */ 259 rx_stat = USS820_READ_1(sc, USS820_RXSTAT); 260 261 DPRINTFN(5, "rx_stat=0x%02x rem=%u\n", rx_stat, td->remainder); 262 263 if (!(rx_stat & USS820_RXSTAT_RXSETUP)) { 264 goto not_complete; 265 } 266 /* clear did stall */ 267 td->did_stall = 0; 268 269 /* clear stall and all I/O */ 270 uss820dci_update_shared_1(sc, USS820_EPCON, 271 0xFF ^ (USS820_EPCON_TXSTL | 272 USS820_EPCON_RXSTL | 273 USS820_EPCON_RXIE | 274 USS820_EPCON_TXOE), 0); 275 276 /* clear end overwrite flag */ 277 uss820dci_update_shared_1(sc, USS820_RXSTAT, 278 0xFF ^ USS820_RXSTAT_EDOVW, 0); 279 280 /* get the packet byte count */ 281 count = USS820_READ_1(sc, USS820_RXCNTL); 282 count |= (USS820_READ_1(sc, USS820_RXCNTH) << 8); 283 count &= 0x3FF; 284 285 /* verify data length */ 286 if (count != td->remainder) { 287 DPRINTFN(0, "Invalid SETUP packet " 288 "length, %d bytes\n", count); 289 goto setup_not_complete; 290 } 291 if (count != sizeof(req)) { 292 DPRINTFN(0, "Unsupported SETUP packet " 293 "length, %d bytes\n", count); 294 goto setup_not_complete; 295 } 296 /* receive data */ 297 bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl, 298 USS820_RXDAT * USS820_REG_STRIDE, (void *)&req, sizeof(req)); 299 300 /* read out FIFO status */ 301 rx_stat = USS820_READ_1(sc, USS820_RXSTAT); 302 303 if (rx_stat & (USS820_RXSTAT_EDOVW | 304 USS820_RXSTAT_STOVW)) { 305 DPRINTF("new SETUP packet received\n"); 306 return (1); /* not complete */ 307 } 308 /* clear receive setup bit */ 309 uss820dci_update_shared_1(sc, USS820_RXSTAT, 310 0xFF ^ (USS820_RXSTAT_RXSETUP | 311 USS820_RXSTAT_EDOVW | 312 USS820_RXSTAT_STOVW), 0); 313 314 /* set RXFFRC bit */ 315 temp = USS820_READ_1(sc, USS820_RXCON); 316 temp |= USS820_RXCON_RXFFRC; 317 USS820_WRITE_1(sc, USS820_RXCON, temp); 318 319 /* copy data into real buffer */ 320 usbd_copy_in(td->pc, 0, &req, sizeof(req)); 321 322 td->offset = sizeof(req); 323 td->remainder = 0; 324 325 /* sneak peek the set address */ 326 if ((req.bmRequestType == UT_WRITE_DEVICE) && 327 (req.bRequest == UR_SET_ADDRESS)) { 328 sc->sc_dv_addr = req.wValue[0] & 0x7F; 329 } else { 330 sc->sc_dv_addr = 0xFF; 331 } 332 333 /* reset TX FIFO */ 334 temp = USS820_READ_1(sc, USS820_TXCON); 335 temp |= USS820_TXCON_TXCLR; 336 USS820_WRITE_1(sc, USS820_TXCON, temp); 337 temp &= ~USS820_TXCON_TXCLR; 338 USS820_WRITE_1(sc, USS820_TXCON, temp); 339 340 return (0); /* complete */ 341 342 setup_not_complete: 343 344 /* set RXFFRC bit */ 345 temp = USS820_READ_1(sc, USS820_RXCON); 346 temp |= USS820_RXCON_RXFFRC; 347 USS820_WRITE_1(sc, USS820_RXCON, temp); 348 349 /* FALLTHROUGH */ 350 351 not_complete: 352 /* abort any ongoing transfer */ 353 if (!td->did_stall) { 354 DPRINTFN(5, "stalling\n"); 355 /* set stall */ 356 uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF, 357 (USS820_EPCON_TXSTL | USS820_EPCON_RXSTL)); 358 359 td->did_stall = 1; 360 } 361 362 /* clear end overwrite flag, if any */ 363 if (rx_stat & USS820_RXSTAT_RXSETUP) { 364 uss820dci_update_shared_1(sc, USS820_RXSTAT, 365 0xFF ^ (USS820_RXSTAT_EDOVW | 366 USS820_RXSTAT_STOVW | 367 USS820_RXSTAT_RXSETUP), 0); 368 } 369 return (1); /* not complete */ 370 } 371 372 static uint8_t 373 uss820dci_data_rx(struct uss820dci_softc *sc, struct uss820dci_td *td) 374 { 375 struct usb_page_search buf_res; 376 uint16_t count; 377 uint8_t rx_flag; 378 uint8_t rx_stat; 379 uint8_t rx_cntl; 380 uint8_t to; 381 uint8_t got_short; 382 383 to = 2; /* don't loop forever! */ 384 got_short = 0; 385 386 /* select the correct endpoint */ 387 USS820_WRITE_1(sc, USS820_EPINDEX, td->ep_index); 388 389 /* check if any of the FIFO banks have data */ 390 repeat: 391 /* read out FIFO flag */ 392 rx_flag = USS820_READ_1(sc, USS820_RXFLG); 393 /* read out FIFO status */ 394 rx_stat = USS820_READ_1(sc, USS820_RXSTAT); 395 396 DPRINTFN(5, "rx_stat=0x%02x rx_flag=0x%02x rem=%u\n", 397 rx_stat, rx_flag, td->remainder); 398 399 if (rx_stat & (USS820_RXSTAT_RXSETUP | 400 USS820_RXSTAT_RXSOVW | 401 USS820_RXSTAT_EDOVW)) { 402 if (td->remainder == 0 && td->ep_index == 0) { 403 /* 404 * We are actually complete and have 405 * received the next SETUP 406 */ 407 DPRINTFN(5, "faking complete\n"); 408 return (0); /* complete */ 409 } 410 /* 411 * USB Host Aborted the transfer. 412 */ 413 td->error = 1; 414 return (0); /* complete */ 415 } 416 /* check for errors */ 417 if (rx_flag & (USS820_RXFLG_RXOVF | 418 USS820_RXFLG_RXURF)) { 419 DPRINTFN(5, "overflow or underflow\n"); 420 /* should not happen */ 421 td->error = 1; 422 return (0); /* complete */ 423 } 424 /* check status */ 425 if (!(rx_flag & (USS820_RXFLG_RXFIF0 | 426 USS820_RXFLG_RXFIF1))) { 427 /* read out EPCON register */ 428 /* enable RX input */ 429 if (!td->did_enable) { 430 uss820dci_update_shared_1(USS820_DCI_PC2SC(td->pc), 431 USS820_EPCON, 0xFF, USS820_EPCON_RXIE); 432 td->did_enable = 1; 433 } 434 return (1); /* not complete */ 435 } 436 /* get the packet byte count */ 437 count = USS820_READ_1(sc, USS820_RXCNTL); 438 count |= (USS820_READ_1(sc, USS820_RXCNTH) << 8); 439 count &= 0x3FF; 440 441 DPRINTFN(5, "count=0x%04x\n", count); 442 443 /* verify the packet byte count */ 444 if (count != td->max_packet_size) { 445 if (count < td->max_packet_size) { 446 /* we have a short packet */ 447 td->short_pkt = 1; 448 got_short = 1; 449 } else { 450 /* invalid USB packet */ 451 td->error = 1; 452 return (0); /* we are complete */ 453 } 454 } 455 /* verify the packet byte count */ 456 if (count > td->remainder) { 457 /* invalid USB packet */ 458 td->error = 1; 459 return (0); /* we are complete */ 460 } 461 while (count > 0) { 462 usbd_get_page(td->pc, td->offset, &buf_res); 463 464 /* get correct length */ 465 if (buf_res.length > count) { 466 buf_res.length = count; 467 } 468 /* receive data */ 469 bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl, 470 USS820_RXDAT * USS820_REG_STRIDE, buf_res.buffer, buf_res.length); 471 472 /* update counters */ 473 count -= buf_res.length; 474 td->offset += buf_res.length; 475 td->remainder -= buf_res.length; 476 } 477 478 /* set RXFFRC bit */ 479 rx_cntl = USS820_READ_1(sc, USS820_RXCON); 480 rx_cntl |= USS820_RXCON_RXFFRC; 481 USS820_WRITE_1(sc, USS820_RXCON, rx_cntl); 482 483 /* check if we are complete */ 484 if ((td->remainder == 0) || got_short) { 485 if (td->short_pkt) { 486 /* we are complete */ 487 return (0); 488 } 489 /* else need to receive a zero length packet */ 490 } 491 if (--to) { 492 goto repeat; 493 } 494 return (1); /* not complete */ 495 } 496 497 static uint8_t 498 uss820dci_data_tx(struct uss820dci_softc *sc, struct uss820dci_td *td) 499 { 500 struct usb_page_search buf_res; 501 uint16_t count; 502 uint16_t count_copy; 503 uint8_t rx_stat; 504 uint8_t tx_flag; 505 uint8_t to; 506 507 /* select the correct endpoint */ 508 USS820_WRITE_1(sc, USS820_EPINDEX, td->ep_index); 509 510 to = 2; /* don't loop forever! */ 511 512 repeat: 513 /* read out TX FIFO flags */ 514 tx_flag = USS820_READ_1(sc, USS820_TXFLG); 515 516 DPRINTFN(5, "tx_flag=0x%02x rem=%u\n", tx_flag, td->remainder); 517 518 if (td->ep_index == 0) { 519 /* read out RX FIFO status last */ 520 rx_stat = USS820_READ_1(sc, USS820_RXSTAT); 521 522 DPRINTFN(5, "rx_stat=0x%02x\n", rx_stat); 523 524 if (rx_stat & (USS820_RXSTAT_RXSETUP | 525 USS820_RXSTAT_RXSOVW | 526 USS820_RXSTAT_EDOVW)) { 527 /* 528 * The current transfer was aborted by the USB 529 * Host: 530 */ 531 td->error = 1; 532 return (0); /* complete */ 533 } 534 } 535 if (tx_flag & (USS820_TXFLG_TXOVF | 536 USS820_TXFLG_TXURF)) { 537 td->error = 1; 538 return (0); /* complete */ 539 } 540 if (tx_flag & USS820_TXFLG_TXFIF0) { 541 if (tx_flag & USS820_TXFLG_TXFIF1) { 542 return (1); /* not complete */ 543 } 544 } 545 if ((!td->support_multi_buffer) && 546 (tx_flag & (USS820_TXFLG_TXFIF0 | 547 USS820_TXFLG_TXFIF1))) { 548 return (1); /* not complete */ 549 } 550 count = td->max_packet_size; 551 if (td->remainder < count) { 552 /* we have a short packet */ 553 td->short_pkt = 1; 554 count = td->remainder; 555 } 556 count_copy = count; 557 while (count > 0) { 558 usbd_get_page(td->pc, td->offset, &buf_res); 559 560 /* get correct length */ 561 if (buf_res.length > count) { 562 buf_res.length = count; 563 } 564 /* transmit data */ 565 bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl, 566 USS820_TXDAT * USS820_REG_STRIDE, buf_res.buffer, buf_res.length); 567 568 /* update counters */ 569 count -= buf_res.length; 570 td->offset += buf_res.length; 571 td->remainder -= buf_res.length; 572 } 573 574 /* post-write high packet byte count first */ 575 USS820_WRITE_1(sc, USS820_TXCNTH, count_copy >> 8); 576 577 /* post-write low packet byte count last */ 578 USS820_WRITE_1(sc, USS820_TXCNTL, count_copy); 579 580 /* 581 * Enable TX output, which must happen after that we have written 582 * data into the FIFO. This is undocumented. 583 */ 584 if (!td->did_enable) { 585 uss820dci_update_shared_1(USS820_DCI_PC2SC(td->pc), 586 USS820_EPCON, 0xFF, USS820_EPCON_TXOE); 587 td->did_enable = 1; 588 } 589 /* check remainder */ 590 if (td->remainder == 0) { 591 if (td->short_pkt) { 592 return (0); /* complete */ 593 } 594 /* else we need to transmit a short packet */ 595 } 596 if (--to) { 597 goto repeat; 598 } 599 return (1); /* not complete */ 600 } 601 602 static uint8_t 603 uss820dci_data_tx_sync(struct uss820dci_softc *sc, struct uss820dci_td *td) 604 { 605 uint8_t rx_stat; 606 uint8_t tx_flag; 607 608 /* select the correct endpoint */ 609 USS820_WRITE_1(sc, USS820_EPINDEX, td->ep_index); 610 611 /* read out TX FIFO flag */ 612 tx_flag = USS820_READ_1(sc, USS820_TXFLG); 613 614 if (td->ep_index == 0) { 615 /* read out RX FIFO status last */ 616 rx_stat = USS820_READ_1(sc, USS820_RXSTAT); 617 618 DPRINTFN(5, "rx_stat=0x%02x rem=%u\n", rx_stat, td->remainder); 619 620 if (rx_stat & (USS820_RXSTAT_RXSETUP | 621 USS820_RXSTAT_RXSOVW | 622 USS820_RXSTAT_EDOVW)) { 623 DPRINTFN(5, "faking complete\n"); 624 /* Race condition */ 625 return (0); /* complete */ 626 } 627 } 628 DPRINTFN(5, "tx_flag=0x%02x rem=%u\n", tx_flag, td->remainder); 629 630 if (tx_flag & (USS820_TXFLG_TXOVF | 631 USS820_TXFLG_TXURF)) { 632 td->error = 1; 633 return (0); /* complete */ 634 } 635 if (tx_flag & (USS820_TXFLG_TXFIF0 | 636 USS820_TXFLG_TXFIF1)) { 637 return (1); /* not complete */ 638 } 639 if (td->ep_index == 0 && sc->sc_dv_addr != 0xFF) { 640 /* write function address */ 641 uss820dci_set_address(sc, sc->sc_dv_addr); 642 } 643 return (0); /* complete */ 644 } 645 646 static void 647 uss820dci_xfer_do_fifo(struct usb_xfer *xfer) 648 { 649 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus); 650 struct uss820dci_td *td; 651 652 DPRINTFN(9, "\n"); 653 654 td = xfer->td_transfer_cache; 655 if (td == NULL) 656 return; 657 658 while (1) { 659 if ((td->func) (sc, td)) { 660 /* operation in progress */ 661 break; 662 } 663 if (((void *)td) == xfer->td_transfer_last) { 664 goto done; 665 } 666 if (td->error) { 667 goto done; 668 } else if (td->remainder > 0) { 669 /* 670 * We had a short transfer. If there is no alternate 671 * next, stop processing ! 672 */ 673 if (!td->alt_next) { 674 goto done; 675 } 676 } 677 /* 678 * Fetch the next transfer descriptor. 679 */ 680 td = td->obj_next; 681 xfer->td_transfer_cache = td; 682 } 683 return; 684 685 done: 686 /* compute all actual lengths */ 687 xfer->td_transfer_cache = NULL; 688 sc->sc_xfer_complete = 1; 689 } 690 691 static uint8_t 692 uss820dci_xfer_do_complete(struct usb_xfer *xfer) 693 { 694 struct uss820dci_td *td; 695 696 DPRINTFN(9, "\n"); 697 698 td = xfer->td_transfer_cache; 699 if (td == NULL) { 700 /* compute all actual lengths */ 701 uss820dci_standard_done(xfer); 702 return(1); 703 } 704 return (0); 705 } 706 707 static void 708 uss820dci_interrupt_poll_locked(struct uss820dci_softc *sc) 709 { 710 struct usb_xfer *xfer; 711 712 TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) 713 uss820dci_xfer_do_fifo(xfer); 714 } 715 716 static void 717 uss820dci_interrupt_complete_locked(struct uss820dci_softc *sc) 718 { 719 struct usb_xfer *xfer; 720 repeat: 721 TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { 722 if (uss820dci_xfer_do_complete(xfer)) 723 goto repeat; 724 } 725 } 726 727 static void 728 uss820dci_wait_suspend(struct uss820dci_softc *sc, uint8_t on) 729 { 730 uint8_t scr; 731 uint8_t scratch; 732 733 scr = USS820_READ_1(sc, USS820_SCR); 734 scratch = USS820_READ_1(sc, USS820_SCRATCH); 735 736 if (on) { 737 scr |= USS820_SCR_IE_SUSP; 738 scratch &= ~USS820_SCRATCH_IE_RESUME; 739 } else { 740 scr &= ~USS820_SCR_IE_SUSP; 741 scratch |= USS820_SCRATCH_IE_RESUME; 742 } 743 744 USS820_WRITE_1(sc, USS820_SCR, scr); 745 USS820_WRITE_1(sc, USS820_SCRATCH, scratch); 746 } 747 748 int 749 uss820dci_filter_interrupt(void *arg) 750 { 751 struct uss820dci_softc *sc = arg; 752 int retval = FILTER_HANDLED; 753 uint8_t ssr; 754 755 USB_BUS_SPIN_LOCK(&sc->sc_bus); 756 757 ssr = USS820_READ_1(sc, USS820_SSR); 758 uss820dci_update_shared_1(sc, USS820_SSR, USS820_DCI_THREAD_IRQ, 0); 759 760 if (ssr & USS820_DCI_THREAD_IRQ) 761 retval = FILTER_SCHEDULE_THREAD; 762 763 /* poll FIFOs, if any */ 764 uss820dci_interrupt_poll_locked(sc); 765 766 if (sc->sc_xfer_complete != 0) 767 retval = FILTER_SCHEDULE_THREAD; 768 769 USB_BUS_SPIN_UNLOCK(&sc->sc_bus); 770 771 return (retval); 772 } 773 774 void 775 uss820dci_interrupt(void *arg) 776 { 777 struct uss820dci_softc *sc = arg; 778 uint8_t ssr; 779 uint8_t event; 780 781 USB_BUS_LOCK(&sc->sc_bus); 782 USB_BUS_SPIN_LOCK(&sc->sc_bus); 783 784 ssr = USS820_READ_1(sc, USS820_SSR); 785 786 /* acknowledge all interrupts */ 787 788 uss820dci_update_shared_1(sc, USS820_SSR, ~USS820_DCI_THREAD_IRQ, 0); 789 790 /* check for any bus state change interrupts */ 791 792 if (ssr & USS820_DCI_THREAD_IRQ) { 793 event = 0; 794 795 if (ssr & USS820_SSR_RESET) { 796 sc->sc_flags.status_bus_reset = 1; 797 sc->sc_flags.status_suspend = 0; 798 sc->sc_flags.change_suspend = 0; 799 sc->sc_flags.change_connect = 1; 800 801 /* disable resume interrupt */ 802 uss820dci_wait_suspend(sc, 1); 803 804 event = 1; 805 } 806 /* 807 * If "RESUME" and "SUSPEND" is set at the same time 808 * we interpret that like "RESUME". Resume is set when 809 * there is at least 3 milliseconds of inactivity on 810 * the USB BUS. 811 */ 812 if (ssr & USS820_SSR_RESUME) { 813 if (sc->sc_flags.status_suspend) { 814 sc->sc_flags.status_suspend = 0; 815 sc->sc_flags.change_suspend = 1; 816 /* disable resume interrupt */ 817 uss820dci_wait_suspend(sc, 1); 818 event = 1; 819 } 820 } else if (ssr & USS820_SSR_SUSPEND) { 821 if (!sc->sc_flags.status_suspend) { 822 sc->sc_flags.status_suspend = 1; 823 sc->sc_flags.change_suspend = 1; 824 /* enable resume interrupt */ 825 uss820dci_wait_suspend(sc, 0); 826 event = 1; 827 } 828 } 829 if (event) { 830 DPRINTF("real bus interrupt 0x%02x\n", ssr); 831 832 /* complete root HUB interrupt endpoint */ 833 uss820dci_root_intr(sc); 834 } 835 } 836 /* acknowledge all SBI interrupts */ 837 uss820dci_update_shared_1(sc, USS820_SBI, 0, 0); 838 839 /* acknowledge all SBI1 interrupts */ 840 uss820dci_update_shared_1(sc, USS820_SBI1, 0, 0); 841 842 if (sc->sc_xfer_complete != 0) { 843 sc->sc_xfer_complete = 0; 844 845 /* complete FIFOs, if any */ 846 uss820dci_interrupt_complete_locked(sc); 847 } 848 USB_BUS_SPIN_UNLOCK(&sc->sc_bus); 849 USB_BUS_UNLOCK(&sc->sc_bus); 850 } 851 852 static void 853 uss820dci_setup_standard_chain_sub(struct uss820_std_temp *temp) 854 { 855 struct uss820dci_td *td; 856 857 /* get current Transfer Descriptor */ 858 td = temp->td_next; 859 temp->td = td; 860 861 /* prepare for next TD */ 862 temp->td_next = td->obj_next; 863 864 /* fill out the Transfer Descriptor */ 865 td->func = temp->func; 866 td->pc = temp->pc; 867 td->offset = temp->offset; 868 td->remainder = temp->len; 869 td->error = 0; 870 td->did_enable = 0; 871 td->did_stall = temp->did_stall; 872 td->short_pkt = temp->short_pkt; 873 td->alt_next = temp->setup_alt_next; 874 } 875 876 static void 877 uss820dci_setup_standard_chain(struct usb_xfer *xfer) 878 { 879 struct uss820_std_temp temp; 880 struct uss820dci_td *td; 881 uint32_t x; 882 883 DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n", 884 xfer->address, UE_GET_ADDR(xfer->endpointno), 885 xfer->sumlen, usbd_get_speed(xfer->xroot->udev)); 886 887 temp.max_frame_size = xfer->max_frame_size; 888 889 td = xfer->td_start[0]; 890 xfer->td_transfer_first = td; 891 xfer->td_transfer_cache = td; 892 893 /* setup temp */ 894 895 temp.pc = NULL; 896 temp.td = NULL; 897 temp.td_next = xfer->td_start[0]; 898 temp.offset = 0; 899 temp.setup_alt_next = xfer->flags_int.short_frames_ok || 900 xfer->flags_int.isochronous_xfr; 901 temp.did_stall = !xfer->flags_int.control_stall; 902 903 /* check if we should prepend a setup message */ 904 905 if (xfer->flags_int.control_xfr) { 906 if (xfer->flags_int.control_hdr) { 907 temp.func = &uss820dci_setup_rx; 908 temp.len = xfer->frlengths[0]; 909 temp.pc = xfer->frbuffers + 0; 910 temp.short_pkt = temp.len ? 1 : 0; 911 /* check for last frame */ 912 if (xfer->nframes == 1) { 913 /* no STATUS stage yet, SETUP is last */ 914 if (xfer->flags_int.control_act) 915 temp.setup_alt_next = 0; 916 } 917 918 uss820dci_setup_standard_chain_sub(&temp); 919 } 920 x = 1; 921 } else { 922 x = 0; 923 } 924 925 if (x != xfer->nframes) { 926 if (xfer->endpointno & UE_DIR_IN) { 927 temp.func = &uss820dci_data_tx; 928 } else { 929 temp.func = &uss820dci_data_rx; 930 } 931 932 /* setup "pc" pointer */ 933 temp.pc = xfer->frbuffers + x; 934 } 935 while (x != xfer->nframes) { 936 /* DATA0 / DATA1 message */ 937 938 temp.len = xfer->frlengths[x]; 939 940 x++; 941 942 if (x == xfer->nframes) { 943 if (xfer->flags_int.control_xfr) { 944 if (xfer->flags_int.control_act) { 945 temp.setup_alt_next = 0; 946 } 947 } else { 948 temp.setup_alt_next = 0; 949 } 950 } 951 if (temp.len == 0) { 952 /* make sure that we send an USB packet */ 953 954 temp.short_pkt = 0; 955 956 } else { 957 /* regular data transfer */ 958 959 temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1; 960 } 961 962 uss820dci_setup_standard_chain_sub(&temp); 963 964 if (xfer->flags_int.isochronous_xfr) { 965 temp.offset += temp.len; 966 } else { 967 /* get next Page Cache pointer */ 968 temp.pc = xfer->frbuffers + x; 969 } 970 } 971 972 /* check for control transfer */ 973 if (xfer->flags_int.control_xfr) { 974 uint8_t need_sync; 975 976 /* always setup a valid "pc" pointer for status and sync */ 977 temp.pc = xfer->frbuffers + 0; 978 temp.len = 0; 979 temp.short_pkt = 0; 980 temp.setup_alt_next = 0; 981 982 /* check if we should append a status stage */ 983 if (!xfer->flags_int.control_act) { 984 /* 985 * Send a DATA1 message and invert the current 986 * endpoint direction. 987 */ 988 if (xfer->endpointno & UE_DIR_IN) { 989 temp.func = &uss820dci_data_rx; 990 need_sync = 0; 991 } else { 992 temp.func = &uss820dci_data_tx; 993 need_sync = 1; 994 } 995 temp.len = 0; 996 temp.short_pkt = 0; 997 998 uss820dci_setup_standard_chain_sub(&temp); 999 if (need_sync) { 1000 /* we need a SYNC point after TX */ 1001 temp.func = &uss820dci_data_tx_sync; 1002 uss820dci_setup_standard_chain_sub(&temp); 1003 } 1004 } 1005 } 1006 /* must have at least one frame! */ 1007 td = temp.td; 1008 xfer->td_transfer_last = td; 1009 } 1010 1011 static void 1012 uss820dci_timeout(void *arg) 1013 { 1014 struct usb_xfer *xfer = arg; 1015 1016 DPRINTF("xfer=%p\n", xfer); 1017 1018 USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED); 1019 1020 /* transfer is transferred */ 1021 uss820dci_device_done(xfer, USB_ERR_TIMEOUT); 1022 } 1023 1024 static void 1025 uss820dci_intr_set(struct usb_xfer *xfer, uint8_t set) 1026 { 1027 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus); 1028 uint8_t ep_no = (xfer->endpointno & UE_ADDR); 1029 uint8_t ep_reg; 1030 uint8_t temp; 1031 1032 DPRINTFN(15, "endpoint 0x%02x\n", xfer->endpointno); 1033 1034 if (ep_no > 3) { 1035 ep_reg = USS820_SBIE1; 1036 } else { 1037 ep_reg = USS820_SBIE; 1038 } 1039 1040 ep_no &= 3; 1041 ep_no = 1 << (2 * ep_no); 1042 1043 if (xfer->flags_int.control_xfr) { 1044 if (xfer->flags_int.control_hdr) { 1045 ep_no <<= 1; /* RX interrupt only */ 1046 } else { 1047 ep_no |= (ep_no << 1); /* RX and TX interrupt */ 1048 } 1049 } else { 1050 if (!(xfer->endpointno & UE_DIR_IN)) { 1051 ep_no <<= 1; 1052 } 1053 } 1054 temp = USS820_READ_1(sc, ep_reg); 1055 if (set) { 1056 temp |= ep_no; 1057 } else { 1058 temp &= ~ep_no; 1059 } 1060 USS820_WRITE_1(sc, ep_reg, temp); 1061 } 1062 1063 static void 1064 uss820dci_start_standard_chain(struct usb_xfer *xfer) 1065 { 1066 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus); 1067 1068 DPRINTFN(9, "\n"); 1069 1070 USB_BUS_SPIN_LOCK(&sc->sc_bus); 1071 1072 /* poll one time */ 1073 uss820dci_xfer_do_fifo(xfer); 1074 1075 if (uss820dci_xfer_do_complete(xfer) == 0) { 1076 /* 1077 * Only enable the endpoint interrupt when we are 1078 * actually waiting for data, hence we are dealing 1079 * with level triggered interrupts ! 1080 */ 1081 uss820dci_intr_set(xfer, 1); 1082 1083 /* put transfer on interrupt queue */ 1084 usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer); 1085 1086 /* start timeout, if any */ 1087 if (xfer->timeout != 0) { 1088 usbd_transfer_timeout_ms(xfer, 1089 &uss820dci_timeout, xfer->timeout); 1090 } 1091 } 1092 USB_BUS_SPIN_UNLOCK(&sc->sc_bus); 1093 } 1094 1095 static void 1096 uss820dci_root_intr(struct uss820dci_softc *sc) 1097 { 1098 DPRINTFN(9, "\n"); 1099 1100 USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); 1101 1102 /* set port bit */ 1103 sc->sc_hub_idata[0] = 0x02; /* we only have one port */ 1104 1105 uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata, 1106 sizeof(sc->sc_hub_idata)); 1107 } 1108 1109 static usb_error_t 1110 uss820dci_standard_done_sub(struct usb_xfer *xfer) 1111 { 1112 struct uss820dci_td *td; 1113 uint32_t len; 1114 uint8_t error; 1115 1116 DPRINTFN(9, "\n"); 1117 1118 td = xfer->td_transfer_cache; 1119 1120 do { 1121 len = td->remainder; 1122 1123 if (xfer->aframes != xfer->nframes) { 1124 /* 1125 * Verify the length and subtract 1126 * the remainder from "frlengths[]": 1127 */ 1128 if (len > xfer->frlengths[xfer->aframes]) { 1129 td->error = 1; 1130 } else { 1131 xfer->frlengths[xfer->aframes] -= len; 1132 } 1133 } 1134 /* Check for transfer error */ 1135 if (td->error) { 1136 /* the transfer is finished */ 1137 error = 1; 1138 td = NULL; 1139 break; 1140 } 1141 /* Check for short transfer */ 1142 if (len > 0) { 1143 if (xfer->flags_int.short_frames_ok || 1144 xfer->flags_int.isochronous_xfr) { 1145 /* follow alt next */ 1146 if (td->alt_next) { 1147 td = td->obj_next; 1148 } else { 1149 td = NULL; 1150 } 1151 } else { 1152 /* the transfer is finished */ 1153 td = NULL; 1154 } 1155 error = 0; 1156 break; 1157 } 1158 td = td->obj_next; 1159 1160 /* this USB frame is complete */ 1161 error = 0; 1162 break; 1163 1164 } while (0); 1165 1166 /* update transfer cache */ 1167 1168 xfer->td_transfer_cache = td; 1169 1170 return (error ? 1171 USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION); 1172 } 1173 1174 static void 1175 uss820dci_standard_done(struct usb_xfer *xfer) 1176 { 1177 usb_error_t err = 0; 1178 1179 DPRINTFN(13, "xfer=%p endpoint=%p transfer done\n", 1180 xfer, xfer->endpoint); 1181 1182 /* reset scanner */ 1183 1184 xfer->td_transfer_cache = xfer->td_transfer_first; 1185 1186 if (xfer->flags_int.control_xfr) { 1187 if (xfer->flags_int.control_hdr) { 1188 err = uss820dci_standard_done_sub(xfer); 1189 } 1190 xfer->aframes = 1; 1191 1192 if (xfer->td_transfer_cache == NULL) { 1193 goto done; 1194 } 1195 } 1196 while (xfer->aframes != xfer->nframes) { 1197 err = uss820dci_standard_done_sub(xfer); 1198 xfer->aframes++; 1199 1200 if (xfer->td_transfer_cache == NULL) { 1201 goto done; 1202 } 1203 } 1204 1205 if (xfer->flags_int.control_xfr && 1206 !xfer->flags_int.control_act) { 1207 err = uss820dci_standard_done_sub(xfer); 1208 } 1209 done: 1210 uss820dci_device_done(xfer, err); 1211 } 1212 1213 /*------------------------------------------------------------------------* 1214 * uss820dci_device_done 1215 * 1216 * NOTE: this function can be called more than one time on the 1217 * same USB transfer! 1218 *------------------------------------------------------------------------*/ 1219 static void 1220 uss820dci_device_done(struct usb_xfer *xfer, usb_error_t error) 1221 { 1222 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus); 1223 1224 USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED); 1225 1226 DPRINTFN(2, "xfer=%p, endpoint=%p, error=%d\n", 1227 xfer, xfer->endpoint, error); 1228 1229 USB_BUS_SPIN_LOCK(&sc->sc_bus); 1230 1231 if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) { 1232 uss820dci_intr_set(xfer, 0); 1233 } 1234 /* dequeue transfer and start next transfer */ 1235 usbd_transfer_done(xfer, error); 1236 1237 USB_BUS_SPIN_UNLOCK(&sc->sc_bus); 1238 } 1239 1240 static void 1241 uss820dci_xfer_stall(struct usb_xfer *xfer) 1242 { 1243 uss820dci_device_done(xfer, USB_ERR_STALLED); 1244 } 1245 1246 static void 1247 uss820dci_set_stall(struct usb_device *udev, 1248 struct usb_endpoint *ep, uint8_t *did_stall) 1249 { 1250 struct uss820dci_softc *sc; 1251 uint8_t ep_no; 1252 uint8_t ep_type; 1253 uint8_t ep_dir; 1254 uint8_t temp; 1255 1256 USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED); 1257 1258 DPRINTFN(5, "endpoint=%p\n", ep); 1259 1260 /* set FORCESTALL */ 1261 sc = USS820_DCI_BUS2SC(udev->bus); 1262 ep_no = (ep->edesc->bEndpointAddress & UE_ADDR); 1263 ep_dir = (ep->edesc->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT)); 1264 ep_type = (ep->edesc->bmAttributes & UE_XFERTYPE); 1265 1266 if (ep_type == UE_CONTROL) { 1267 /* should not happen */ 1268 return; 1269 } 1270 USB_BUS_SPIN_LOCK(&sc->sc_bus); 1271 USS820_WRITE_1(sc, USS820_EPINDEX, ep_no); 1272 1273 if (ep_dir == UE_DIR_IN) { 1274 temp = USS820_EPCON_TXSTL; 1275 } else { 1276 temp = USS820_EPCON_RXSTL; 1277 } 1278 uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF, temp); 1279 USB_BUS_SPIN_UNLOCK(&sc->sc_bus); 1280 } 1281 1282 static void 1283 uss820dci_clear_stall_sub(struct uss820dci_softc *sc, 1284 uint8_t ep_no, uint8_t ep_type, uint8_t ep_dir) 1285 { 1286 uint8_t temp; 1287 1288 if (ep_type == UE_CONTROL) { 1289 /* clearing stall is not needed */ 1290 return; 1291 } 1292 USB_BUS_SPIN_LOCK(&sc->sc_bus); 1293 1294 /* select endpoint index */ 1295 USS820_WRITE_1(sc, USS820_EPINDEX, ep_no); 1296 1297 /* clear stall and disable I/O transfers */ 1298 if (ep_dir == UE_DIR_IN) { 1299 temp = 0xFF ^ (USS820_EPCON_TXOE | 1300 USS820_EPCON_TXSTL); 1301 } else { 1302 temp = 0xFF ^ (USS820_EPCON_RXIE | 1303 USS820_EPCON_RXSTL); 1304 } 1305 uss820dci_update_shared_1(sc, USS820_EPCON, temp, 0); 1306 1307 if (ep_dir == UE_DIR_IN) { 1308 /* reset data toggle */ 1309 USS820_WRITE_1(sc, USS820_TXSTAT, 1310 USS820_TXSTAT_TXSOVW); 1311 1312 /* reset FIFO */ 1313 temp = USS820_READ_1(sc, USS820_TXCON); 1314 temp |= USS820_TXCON_TXCLR; 1315 USS820_WRITE_1(sc, USS820_TXCON, temp); 1316 temp &= ~USS820_TXCON_TXCLR; 1317 USS820_WRITE_1(sc, USS820_TXCON, temp); 1318 } else { 1319 /* reset data toggle */ 1320 uss820dci_update_shared_1(sc, USS820_RXSTAT, 1321 0, USS820_RXSTAT_RXSOVW); 1322 1323 /* reset FIFO */ 1324 temp = USS820_READ_1(sc, USS820_RXCON); 1325 temp |= USS820_RXCON_RXCLR; 1326 temp &= ~USS820_RXCON_RXFFRC; 1327 USS820_WRITE_1(sc, USS820_RXCON, temp); 1328 temp &= ~USS820_RXCON_RXCLR; 1329 USS820_WRITE_1(sc, USS820_RXCON, temp); 1330 } 1331 USB_BUS_SPIN_UNLOCK(&sc->sc_bus); 1332 } 1333 1334 static void 1335 uss820dci_clear_stall(struct usb_device *udev, struct usb_endpoint *ep) 1336 { 1337 struct uss820dci_softc *sc; 1338 struct usb_endpoint_descriptor *ed; 1339 1340 USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED); 1341 1342 DPRINTFN(5, "endpoint=%p\n", ep); 1343 1344 /* check mode */ 1345 if (udev->flags.usb_mode != USB_MODE_DEVICE) { 1346 /* not supported */ 1347 return; 1348 } 1349 /* get softc */ 1350 sc = USS820_DCI_BUS2SC(udev->bus); 1351 1352 /* get endpoint descriptor */ 1353 ed = ep->edesc; 1354 1355 /* reset endpoint */ 1356 uss820dci_clear_stall_sub(sc, 1357 (ed->bEndpointAddress & UE_ADDR), 1358 (ed->bmAttributes & UE_XFERTYPE), 1359 (ed->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT))); 1360 } 1361 1362 usb_error_t 1363 uss820dci_init(struct uss820dci_softc *sc) 1364 { 1365 const struct usb_hw_ep_profile *pf; 1366 uint8_t n; 1367 uint8_t temp; 1368 1369 DPRINTF("start\n"); 1370 1371 /* set up the bus structure */ 1372 sc->sc_bus.usbrev = USB_REV_1_1; 1373 sc->sc_bus.methods = &uss820dci_bus_methods; 1374 1375 USB_BUS_LOCK(&sc->sc_bus); 1376 1377 /* we always have VBUS */ 1378 sc->sc_flags.status_vbus = 1; 1379 1380 /* reset the chip */ 1381 USS820_WRITE_1(sc, USS820_SCR, USS820_SCR_SRESET); 1382 DELAY(100); 1383 USS820_WRITE_1(sc, USS820_SCR, 0); 1384 1385 /* wait for reset to complete */ 1386 for (n = 0;; n++) { 1387 temp = USS820_READ_1(sc, USS820_MCSR); 1388 1389 if (temp & USS820_MCSR_INIT) { 1390 break; 1391 } 1392 if (n == 100) { 1393 USB_BUS_UNLOCK(&sc->sc_bus); 1394 return (USB_ERR_INVAL); 1395 } 1396 /* wait a little for things to stabilise */ 1397 DELAY(100); 1398 } 1399 1400 /* do a pulldown */ 1401 uss820dci_pull_down(sc); 1402 1403 /* wait 10ms for pulldown to stabilise */ 1404 usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 100); 1405 1406 /* check hardware revision */ 1407 temp = USS820_READ_1(sc, USS820_REV); 1408 1409 if (temp < 0x13) { 1410 USB_BUS_UNLOCK(&sc->sc_bus); 1411 return (USB_ERR_INVAL); 1412 } 1413 /* enable interrupts */ 1414 USS820_WRITE_1(sc, USS820_SCR, 1415 USS820_SCR_T_IRQ | 1416 USS820_SCR_IE_RESET | 1417 /* USS820_SCR_RWUPE | */ 1418 USS820_SCR_IE_SUSP | 1419 USS820_SCR_IRQPOL); 1420 1421 /* enable interrupts */ 1422 USS820_WRITE_1(sc, USS820_SCRATCH, 1423 USS820_SCRATCH_IE_RESUME); 1424 1425 /* enable features */ 1426 USS820_WRITE_1(sc, USS820_MCSR, 1427 USS820_MCSR_BDFEAT | 1428 USS820_MCSR_FEAT); 1429 1430 sc->sc_flags.mcsr_feat = 1; 1431 1432 /* disable interrupts */ 1433 USS820_WRITE_1(sc, USS820_SBIE, 0); 1434 1435 /* disable interrupts */ 1436 USS820_WRITE_1(sc, USS820_SBIE1, 0); 1437 1438 /* disable all endpoints */ 1439 for (n = 0; n != USS820_EP_MAX; n++) { 1440 /* select endpoint */ 1441 USS820_WRITE_1(sc, USS820_EPINDEX, n); 1442 1443 /* disable endpoint */ 1444 uss820dci_update_shared_1(sc, USS820_EPCON, 0, 0); 1445 } 1446 1447 /* 1448 * Initialise default values for some registers that cannot be 1449 * changed during operation! 1450 */ 1451 for (n = 0; n != USS820_EP_MAX; n++) { 1452 uss820dci_get_hw_ep_profile(NULL, &pf, n); 1453 1454 /* the maximum frame sizes should be the same */ 1455 if (pf->max_in_frame_size != pf->max_out_frame_size) { 1456 DPRINTF("Max frame size mismatch %u != %u\n", 1457 pf->max_in_frame_size, pf->max_out_frame_size); 1458 } 1459 if (pf->support_isochronous) { 1460 if (pf->max_in_frame_size <= 64) { 1461 temp = (USS820_TXCON_FFSZ_16_64 | 1462 USS820_TXCON_TXISO | 1463 USS820_TXCON_ATM); 1464 } else if (pf->max_in_frame_size <= 256) { 1465 temp = (USS820_TXCON_FFSZ_64_256 | 1466 USS820_TXCON_TXISO | 1467 USS820_TXCON_ATM); 1468 } else if (pf->max_in_frame_size <= 512) { 1469 temp = (USS820_TXCON_FFSZ_8_512 | 1470 USS820_TXCON_TXISO | 1471 USS820_TXCON_ATM); 1472 } else { /* 1024 bytes */ 1473 temp = (USS820_TXCON_FFSZ_32_1024 | 1474 USS820_TXCON_TXISO | 1475 USS820_TXCON_ATM); 1476 } 1477 } else { 1478 if ((pf->max_in_frame_size <= 8) && 1479 (sc->sc_flags.mcsr_feat)) { 1480 temp = (USS820_TXCON_FFSZ_8_512 | 1481 USS820_TXCON_ATM); 1482 } else if (pf->max_in_frame_size <= 16) { 1483 temp = (USS820_TXCON_FFSZ_16_64 | 1484 USS820_TXCON_ATM); 1485 } else if ((pf->max_in_frame_size <= 32) && 1486 (sc->sc_flags.mcsr_feat)) { 1487 temp = (USS820_TXCON_FFSZ_32_1024 | 1488 USS820_TXCON_ATM); 1489 } else { /* 64 bytes */ 1490 temp = (USS820_TXCON_FFSZ_64_256 | 1491 USS820_TXCON_ATM); 1492 } 1493 } 1494 1495 /* need to configure the chip early */ 1496 1497 USS820_WRITE_1(sc, USS820_EPINDEX, n); 1498 USS820_WRITE_1(sc, USS820_TXCON, temp); 1499 USS820_WRITE_1(sc, USS820_RXCON, temp); 1500 1501 if (pf->support_control) { 1502 temp = USS820_EPCON_CTLEP | 1503 USS820_EPCON_RXSPM | 1504 USS820_EPCON_RXIE | 1505 USS820_EPCON_RXEPEN | 1506 USS820_EPCON_TXOE | 1507 USS820_EPCON_TXEPEN; 1508 } else { 1509 temp = USS820_EPCON_RXEPEN | USS820_EPCON_TXEPEN; 1510 } 1511 1512 uss820dci_update_shared_1(sc, USS820_EPCON, 0, temp); 1513 } 1514 1515 USB_BUS_UNLOCK(&sc->sc_bus); 1516 1517 /* catch any lost interrupts */ 1518 1519 uss820dci_do_poll(&sc->sc_bus); 1520 1521 return (0); /* success */ 1522 } 1523 1524 void 1525 uss820dci_uninit(struct uss820dci_softc *sc) 1526 { 1527 uint8_t temp; 1528 1529 USB_BUS_LOCK(&sc->sc_bus); 1530 1531 /* disable all interrupts */ 1532 temp = USS820_READ_1(sc, USS820_SCR); 1533 temp &= ~USS820_SCR_T_IRQ; 1534 USS820_WRITE_1(sc, USS820_SCR, temp); 1535 1536 sc->sc_flags.port_powered = 0; 1537 sc->sc_flags.status_vbus = 0; 1538 sc->sc_flags.status_bus_reset = 0; 1539 sc->sc_flags.status_suspend = 0; 1540 sc->sc_flags.change_suspend = 0; 1541 sc->sc_flags.change_connect = 1; 1542 1543 uss820dci_pull_down(sc); 1544 USB_BUS_UNLOCK(&sc->sc_bus); 1545 } 1546 1547 static void 1548 uss820dci_suspend(struct uss820dci_softc *sc) 1549 { 1550 /* TODO */ 1551 } 1552 1553 static void 1554 uss820dci_resume(struct uss820dci_softc *sc) 1555 { 1556 /* TODO */ 1557 } 1558 1559 static void 1560 uss820dci_do_poll(struct usb_bus *bus) 1561 { 1562 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(bus); 1563 1564 USB_BUS_LOCK(&sc->sc_bus); 1565 USB_BUS_SPIN_LOCK(&sc->sc_bus); 1566 uss820dci_interrupt_poll_locked(sc); 1567 uss820dci_interrupt_complete_locked(sc); 1568 USB_BUS_SPIN_UNLOCK(&sc->sc_bus); 1569 USB_BUS_UNLOCK(&sc->sc_bus); 1570 } 1571 1572 /*------------------------------------------------------------------------* 1573 * uss820dci bulk support 1574 *------------------------------------------------------------------------*/ 1575 static void 1576 uss820dci_device_bulk_open(struct usb_xfer *xfer) 1577 { 1578 return; 1579 } 1580 1581 static void 1582 uss820dci_device_bulk_close(struct usb_xfer *xfer) 1583 { 1584 uss820dci_device_done(xfer, USB_ERR_CANCELLED); 1585 } 1586 1587 static void 1588 uss820dci_device_bulk_enter(struct usb_xfer *xfer) 1589 { 1590 return; 1591 } 1592 1593 static void 1594 uss820dci_device_bulk_start(struct usb_xfer *xfer) 1595 { 1596 /* setup TDs */ 1597 uss820dci_setup_standard_chain(xfer); 1598 uss820dci_start_standard_chain(xfer); 1599 } 1600 1601 static const struct usb_pipe_methods uss820dci_device_bulk_methods = 1602 { 1603 .open = uss820dci_device_bulk_open, 1604 .close = uss820dci_device_bulk_close, 1605 .enter = uss820dci_device_bulk_enter, 1606 .start = uss820dci_device_bulk_start, 1607 }; 1608 1609 /*------------------------------------------------------------------------* 1610 * uss820dci control support 1611 *------------------------------------------------------------------------*/ 1612 static void 1613 uss820dci_device_ctrl_open(struct usb_xfer *xfer) 1614 { 1615 return; 1616 } 1617 1618 static void 1619 uss820dci_device_ctrl_close(struct usb_xfer *xfer) 1620 { 1621 uss820dci_device_done(xfer, USB_ERR_CANCELLED); 1622 } 1623 1624 static void 1625 uss820dci_device_ctrl_enter(struct usb_xfer *xfer) 1626 { 1627 return; 1628 } 1629 1630 static void 1631 uss820dci_device_ctrl_start(struct usb_xfer *xfer) 1632 { 1633 /* setup TDs */ 1634 uss820dci_setup_standard_chain(xfer); 1635 uss820dci_start_standard_chain(xfer); 1636 } 1637 1638 static const struct usb_pipe_methods uss820dci_device_ctrl_methods = 1639 { 1640 .open = uss820dci_device_ctrl_open, 1641 .close = uss820dci_device_ctrl_close, 1642 .enter = uss820dci_device_ctrl_enter, 1643 .start = uss820dci_device_ctrl_start, 1644 }; 1645 1646 /*------------------------------------------------------------------------* 1647 * uss820dci interrupt support 1648 *------------------------------------------------------------------------*/ 1649 static void 1650 uss820dci_device_intr_open(struct usb_xfer *xfer) 1651 { 1652 return; 1653 } 1654 1655 static void 1656 uss820dci_device_intr_close(struct usb_xfer *xfer) 1657 { 1658 uss820dci_device_done(xfer, USB_ERR_CANCELLED); 1659 } 1660 1661 static void 1662 uss820dci_device_intr_enter(struct usb_xfer *xfer) 1663 { 1664 return; 1665 } 1666 1667 static void 1668 uss820dci_device_intr_start(struct usb_xfer *xfer) 1669 { 1670 /* setup TDs */ 1671 uss820dci_setup_standard_chain(xfer); 1672 uss820dci_start_standard_chain(xfer); 1673 } 1674 1675 static const struct usb_pipe_methods uss820dci_device_intr_methods = 1676 { 1677 .open = uss820dci_device_intr_open, 1678 .close = uss820dci_device_intr_close, 1679 .enter = uss820dci_device_intr_enter, 1680 .start = uss820dci_device_intr_start, 1681 }; 1682 1683 /*------------------------------------------------------------------------* 1684 * uss820dci full speed isochronous support 1685 *------------------------------------------------------------------------*/ 1686 static void 1687 uss820dci_device_isoc_fs_open(struct usb_xfer *xfer) 1688 { 1689 return; 1690 } 1691 1692 static void 1693 uss820dci_device_isoc_fs_close(struct usb_xfer *xfer) 1694 { 1695 uss820dci_device_done(xfer, USB_ERR_CANCELLED); 1696 } 1697 1698 static void 1699 uss820dci_device_isoc_fs_enter(struct usb_xfer *xfer) 1700 { 1701 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus); 1702 uint32_t nframes; 1703 1704 DPRINTFN(6, "xfer=%p next=%d nframes=%d\n", 1705 xfer, xfer->endpoint->isoc_next, xfer->nframes); 1706 1707 /* get the current frame index - we don't need the high bits */ 1708 1709 nframes = USS820_READ_1(sc, USS820_SOFL); 1710 1711 if (usbd_xfer_get_isochronous_start_frame( 1712 xfer, nframes, 0, 1, USS820_SOFL_MASK, NULL)) 1713 DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); 1714 1715 /* setup TDs */ 1716 uss820dci_setup_standard_chain(xfer); 1717 } 1718 1719 static void 1720 uss820dci_device_isoc_fs_start(struct usb_xfer *xfer) 1721 { 1722 /* start TD chain */ 1723 uss820dci_start_standard_chain(xfer); 1724 } 1725 1726 static const struct usb_pipe_methods uss820dci_device_isoc_fs_methods = 1727 { 1728 .open = uss820dci_device_isoc_fs_open, 1729 .close = uss820dci_device_isoc_fs_close, 1730 .enter = uss820dci_device_isoc_fs_enter, 1731 .start = uss820dci_device_isoc_fs_start, 1732 }; 1733 1734 /*------------------------------------------------------------------------* 1735 * uss820dci root control support 1736 *------------------------------------------------------------------------* 1737 * Simulate a hardware HUB by handling all the necessary requests. 1738 *------------------------------------------------------------------------*/ 1739 1740 static const struct usb_device_descriptor uss820dci_devd = { 1741 .bLength = sizeof(struct usb_device_descriptor), 1742 .bDescriptorType = UDESC_DEVICE, 1743 .bcdUSB = {0x00, 0x02}, 1744 .bDeviceClass = UDCLASS_HUB, 1745 .bDeviceSubClass = UDSUBCLASS_HUB, 1746 .bDeviceProtocol = UDPROTO_FSHUB, 1747 .bMaxPacketSize = 64, 1748 .bcdDevice = {0x00, 0x01}, 1749 .iManufacturer = 1, 1750 .iProduct = 2, 1751 .bNumConfigurations = 1, 1752 }; 1753 1754 static const struct usb_device_qualifier uss820dci_odevd = { 1755 .bLength = sizeof(struct usb_device_qualifier), 1756 .bDescriptorType = UDESC_DEVICE_QUALIFIER, 1757 .bcdUSB = {0x00, 0x02}, 1758 .bDeviceClass = UDCLASS_HUB, 1759 .bDeviceSubClass = UDSUBCLASS_HUB, 1760 .bDeviceProtocol = UDPROTO_FSHUB, 1761 .bMaxPacketSize0 = 0, 1762 .bNumConfigurations = 0, 1763 }; 1764 1765 static const struct uss820dci_config_desc uss820dci_confd = { 1766 .confd = { 1767 .bLength = sizeof(struct usb_config_descriptor), 1768 .bDescriptorType = UDESC_CONFIG, 1769 .wTotalLength[0] = sizeof(uss820dci_confd), 1770 .bNumInterface = 1, 1771 .bConfigurationValue = 1, 1772 .iConfiguration = 0, 1773 .bmAttributes = UC_SELF_POWERED, 1774 .bMaxPower = 0, 1775 }, 1776 .ifcd = { 1777 .bLength = sizeof(struct usb_interface_descriptor), 1778 .bDescriptorType = UDESC_INTERFACE, 1779 .bNumEndpoints = 1, 1780 .bInterfaceClass = UICLASS_HUB, 1781 .bInterfaceSubClass = UISUBCLASS_HUB, 1782 .bInterfaceProtocol = 0, 1783 }, 1784 1785 .endpd = { 1786 .bLength = sizeof(struct usb_endpoint_descriptor), 1787 .bDescriptorType = UDESC_ENDPOINT, 1788 .bEndpointAddress = (UE_DIR_IN | USS820_DCI_INTR_ENDPT), 1789 .bmAttributes = UE_INTERRUPT, 1790 .wMaxPacketSize[0] = 8, 1791 .bInterval = 255, 1792 }, 1793 }; 1794 #define HSETW(ptr, val) ptr = { (uint8_t)(val), (uint8_t)((val) >> 8) } 1795 1796 static const struct usb_hub_descriptor_min uss820dci_hubd = { 1797 .bDescLength = sizeof(uss820dci_hubd), 1798 .bDescriptorType = UDESC_HUB, 1799 .bNbrPorts = 1, 1800 HSETW(.wHubCharacteristics, (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL)), 1801 .bPwrOn2PwrGood = 50, 1802 .bHubContrCurrent = 0, 1803 .DeviceRemovable = {0}, /* port is removable */ 1804 }; 1805 1806 #define STRING_VENDOR \ 1807 "A\0G\0E\0R\0E" 1808 1809 #define STRING_PRODUCT \ 1810 "D\0C\0I\0 \0R\0o\0o\0t\0 \0H\0U\0B" 1811 1812 USB_MAKE_STRING_DESC(STRING_VENDOR, uss820dci_vendor); 1813 USB_MAKE_STRING_DESC(STRING_PRODUCT, uss820dci_product); 1814 1815 static usb_error_t 1816 uss820dci_roothub_exec(struct usb_device *udev, 1817 struct usb_device_request *req, const void **pptr, uint16_t *plength) 1818 { 1819 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(udev->bus); 1820 const void *ptr; 1821 uint16_t len; 1822 uint16_t value; 1823 uint16_t index; 1824 usb_error_t err; 1825 1826 USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); 1827 1828 /* buffer reset */ 1829 ptr = (const void *)&sc->sc_hub_temp; 1830 len = 0; 1831 err = 0; 1832 1833 value = UGETW(req->wValue); 1834 index = UGETW(req->wIndex); 1835 1836 /* demultiplex the control request */ 1837 1838 switch (req->bmRequestType) { 1839 case UT_READ_DEVICE: 1840 switch (req->bRequest) { 1841 case UR_GET_DESCRIPTOR: 1842 goto tr_handle_get_descriptor; 1843 case UR_GET_CONFIG: 1844 goto tr_handle_get_config; 1845 case UR_GET_STATUS: 1846 goto tr_handle_get_status; 1847 default: 1848 goto tr_stalled; 1849 } 1850 break; 1851 1852 case UT_WRITE_DEVICE: 1853 switch (req->bRequest) { 1854 case UR_SET_ADDRESS: 1855 goto tr_handle_set_address; 1856 case UR_SET_CONFIG: 1857 goto tr_handle_set_config; 1858 case UR_CLEAR_FEATURE: 1859 goto tr_valid; /* nop */ 1860 case UR_SET_DESCRIPTOR: 1861 goto tr_valid; /* nop */ 1862 case UR_SET_FEATURE: 1863 default: 1864 goto tr_stalled; 1865 } 1866 break; 1867 1868 case UT_WRITE_ENDPOINT: 1869 switch (req->bRequest) { 1870 case UR_CLEAR_FEATURE: 1871 switch (UGETW(req->wValue)) { 1872 case UF_ENDPOINT_HALT: 1873 goto tr_handle_clear_halt; 1874 case UF_DEVICE_REMOTE_WAKEUP: 1875 goto tr_handle_clear_wakeup; 1876 default: 1877 goto tr_stalled; 1878 } 1879 break; 1880 case UR_SET_FEATURE: 1881 switch (UGETW(req->wValue)) { 1882 case UF_ENDPOINT_HALT: 1883 goto tr_handle_set_halt; 1884 case UF_DEVICE_REMOTE_WAKEUP: 1885 goto tr_handle_set_wakeup; 1886 default: 1887 goto tr_stalled; 1888 } 1889 break; 1890 case UR_SYNCH_FRAME: 1891 goto tr_valid; /* nop */ 1892 default: 1893 goto tr_stalled; 1894 } 1895 break; 1896 1897 case UT_READ_ENDPOINT: 1898 switch (req->bRequest) { 1899 case UR_GET_STATUS: 1900 goto tr_handle_get_ep_status; 1901 default: 1902 goto tr_stalled; 1903 } 1904 break; 1905 1906 case UT_WRITE_INTERFACE: 1907 switch (req->bRequest) { 1908 case UR_SET_INTERFACE: 1909 goto tr_handle_set_interface; 1910 case UR_CLEAR_FEATURE: 1911 goto tr_valid; /* nop */ 1912 case UR_SET_FEATURE: 1913 default: 1914 goto tr_stalled; 1915 } 1916 break; 1917 1918 case UT_READ_INTERFACE: 1919 switch (req->bRequest) { 1920 case UR_GET_INTERFACE: 1921 goto tr_handle_get_interface; 1922 case UR_GET_STATUS: 1923 goto tr_handle_get_iface_status; 1924 default: 1925 goto tr_stalled; 1926 } 1927 break; 1928 1929 case UT_WRITE_CLASS_INTERFACE: 1930 case UT_WRITE_VENDOR_INTERFACE: 1931 /* XXX forward */ 1932 break; 1933 1934 case UT_READ_CLASS_INTERFACE: 1935 case UT_READ_VENDOR_INTERFACE: 1936 /* XXX forward */ 1937 break; 1938 1939 case UT_WRITE_CLASS_DEVICE: 1940 switch (req->bRequest) { 1941 case UR_CLEAR_FEATURE: 1942 goto tr_valid; 1943 case UR_SET_DESCRIPTOR: 1944 case UR_SET_FEATURE: 1945 break; 1946 default: 1947 goto tr_stalled; 1948 } 1949 break; 1950 1951 case UT_WRITE_CLASS_OTHER: 1952 switch (req->bRequest) { 1953 case UR_CLEAR_FEATURE: 1954 goto tr_handle_clear_port_feature; 1955 case UR_SET_FEATURE: 1956 goto tr_handle_set_port_feature; 1957 case UR_CLEAR_TT_BUFFER: 1958 case UR_RESET_TT: 1959 case UR_STOP_TT: 1960 goto tr_valid; 1961 1962 default: 1963 goto tr_stalled; 1964 } 1965 break; 1966 1967 case UT_READ_CLASS_OTHER: 1968 switch (req->bRequest) { 1969 case UR_GET_TT_STATE: 1970 goto tr_handle_get_tt_state; 1971 case UR_GET_STATUS: 1972 goto tr_handle_get_port_status; 1973 default: 1974 goto tr_stalled; 1975 } 1976 break; 1977 1978 case UT_READ_CLASS_DEVICE: 1979 switch (req->bRequest) { 1980 case UR_GET_DESCRIPTOR: 1981 goto tr_handle_get_class_descriptor; 1982 case UR_GET_STATUS: 1983 goto tr_handle_get_class_status; 1984 1985 default: 1986 goto tr_stalled; 1987 } 1988 break; 1989 default: 1990 goto tr_stalled; 1991 } 1992 goto tr_valid; 1993 1994 tr_handle_get_descriptor: 1995 switch (value >> 8) { 1996 case UDESC_DEVICE: 1997 if (value & 0xff) { 1998 goto tr_stalled; 1999 } 2000 len = sizeof(uss820dci_devd); 2001 ptr = (const void *)&uss820dci_devd; 2002 goto tr_valid; 2003 case UDESC_DEVICE_QUALIFIER: 2004 if (value & 0xff) { 2005 goto tr_stalled; 2006 } 2007 len = sizeof(uss820dci_odevd); 2008 ptr = (const void *)&uss820dci_odevd; 2009 goto tr_valid; 2010 case UDESC_CONFIG: 2011 if (value & 0xff) { 2012 goto tr_stalled; 2013 } 2014 len = sizeof(uss820dci_confd); 2015 ptr = (const void *)&uss820dci_confd; 2016 goto tr_valid; 2017 case UDESC_STRING: 2018 switch (value & 0xff) { 2019 case 0: /* Language table */ 2020 len = sizeof(usb_string_lang_en); 2021 ptr = (const void *)&usb_string_lang_en; 2022 goto tr_valid; 2023 2024 case 1: /* Vendor */ 2025 len = sizeof(uss820dci_vendor); 2026 ptr = (const void *)&uss820dci_vendor; 2027 goto tr_valid; 2028 2029 case 2: /* Product */ 2030 len = sizeof(uss820dci_product); 2031 ptr = (const void *)&uss820dci_product; 2032 goto tr_valid; 2033 default: 2034 break; 2035 } 2036 break; 2037 default: 2038 goto tr_stalled; 2039 } 2040 goto tr_stalled; 2041 2042 tr_handle_get_config: 2043 len = 1; 2044 sc->sc_hub_temp.wValue[0] = sc->sc_conf; 2045 goto tr_valid; 2046 2047 tr_handle_get_status: 2048 len = 2; 2049 USETW(sc->sc_hub_temp.wValue, UDS_SELF_POWERED); 2050 goto tr_valid; 2051 2052 tr_handle_set_address: 2053 if (value & 0xFF00) { 2054 goto tr_stalled; 2055 } 2056 sc->sc_rt_addr = value; 2057 goto tr_valid; 2058 2059 tr_handle_set_config: 2060 if (value >= 2) { 2061 goto tr_stalled; 2062 } 2063 sc->sc_conf = value; 2064 goto tr_valid; 2065 2066 tr_handle_get_interface: 2067 len = 1; 2068 sc->sc_hub_temp.wValue[0] = 0; 2069 goto tr_valid; 2070 2071 tr_handle_get_tt_state: 2072 tr_handle_get_class_status: 2073 tr_handle_get_iface_status: 2074 tr_handle_get_ep_status: 2075 len = 2; 2076 USETW(sc->sc_hub_temp.wValue, 0); 2077 goto tr_valid; 2078 2079 tr_handle_set_halt: 2080 tr_handle_set_interface: 2081 tr_handle_set_wakeup: 2082 tr_handle_clear_wakeup: 2083 tr_handle_clear_halt: 2084 goto tr_valid; 2085 2086 tr_handle_clear_port_feature: 2087 if (index != 1) { 2088 goto tr_stalled; 2089 } 2090 DPRINTFN(9, "UR_CLEAR_PORT_FEATURE on port %d\n", index); 2091 2092 switch (value) { 2093 case UHF_PORT_SUSPEND: 2094 uss820dci_wakeup_peer(sc); 2095 break; 2096 2097 case UHF_PORT_ENABLE: 2098 sc->sc_flags.port_enabled = 0; 2099 break; 2100 2101 case UHF_PORT_TEST: 2102 case UHF_PORT_INDICATOR: 2103 case UHF_C_PORT_ENABLE: 2104 case UHF_C_PORT_OVER_CURRENT: 2105 case UHF_C_PORT_RESET: 2106 /* nops */ 2107 break; 2108 case UHF_PORT_POWER: 2109 sc->sc_flags.port_powered = 0; 2110 uss820dci_pull_down(sc); 2111 break; 2112 case UHF_C_PORT_CONNECTION: 2113 sc->sc_flags.change_connect = 0; 2114 break; 2115 case UHF_C_PORT_SUSPEND: 2116 sc->sc_flags.change_suspend = 0; 2117 break; 2118 default: 2119 err = USB_ERR_IOERROR; 2120 goto done; 2121 } 2122 goto tr_valid; 2123 2124 tr_handle_set_port_feature: 2125 if (index != 1) { 2126 goto tr_stalled; 2127 } 2128 DPRINTFN(9, "UR_SET_PORT_FEATURE\n"); 2129 2130 switch (value) { 2131 case UHF_PORT_ENABLE: 2132 sc->sc_flags.port_enabled = 1; 2133 break; 2134 case UHF_PORT_SUSPEND: 2135 case UHF_PORT_RESET: 2136 case UHF_PORT_TEST: 2137 case UHF_PORT_INDICATOR: 2138 /* nops */ 2139 break; 2140 case UHF_PORT_POWER: 2141 sc->sc_flags.port_powered = 1; 2142 break; 2143 default: 2144 err = USB_ERR_IOERROR; 2145 goto done; 2146 } 2147 goto tr_valid; 2148 2149 tr_handle_get_port_status: 2150 2151 DPRINTFN(9, "UR_GET_PORT_STATUS\n"); 2152 2153 if (index != 1) { 2154 goto tr_stalled; 2155 } 2156 if (sc->sc_flags.status_vbus) { 2157 uss820dci_pull_up(sc); 2158 } else { 2159 uss820dci_pull_down(sc); 2160 } 2161 2162 /* Select FULL-speed and Device Side Mode */ 2163 2164 value = UPS_PORT_MODE_DEVICE; 2165 2166 if (sc->sc_flags.port_powered) { 2167 value |= UPS_PORT_POWER; 2168 } 2169 if (sc->sc_flags.port_enabled) { 2170 value |= UPS_PORT_ENABLED; 2171 } 2172 if (sc->sc_flags.status_vbus && 2173 sc->sc_flags.status_bus_reset) { 2174 value |= UPS_CURRENT_CONNECT_STATUS; 2175 } 2176 if (sc->sc_flags.status_suspend) { 2177 value |= UPS_SUSPEND; 2178 } 2179 USETW(sc->sc_hub_temp.ps.wPortStatus, value); 2180 2181 value = 0; 2182 2183 if (sc->sc_flags.change_connect) { 2184 value |= UPS_C_CONNECT_STATUS; 2185 } 2186 if (sc->sc_flags.change_suspend) { 2187 value |= UPS_C_SUSPEND; 2188 } 2189 USETW(sc->sc_hub_temp.ps.wPortChange, value); 2190 len = sizeof(sc->sc_hub_temp.ps); 2191 goto tr_valid; 2192 2193 tr_handle_get_class_descriptor: 2194 if (value & 0xFF) { 2195 goto tr_stalled; 2196 } 2197 ptr = (const void *)&uss820dci_hubd; 2198 len = sizeof(uss820dci_hubd); 2199 goto tr_valid; 2200 2201 tr_stalled: 2202 err = USB_ERR_STALLED; 2203 tr_valid: 2204 done: 2205 *plength = len; 2206 *pptr = ptr; 2207 return (err); 2208 } 2209 2210 static void 2211 uss820dci_xfer_setup(struct usb_setup_params *parm) 2212 { 2213 const struct usb_hw_ep_profile *pf; 2214 struct usb_xfer *xfer; 2215 void *last_obj; 2216 uint32_t ntd; 2217 uint32_t n; 2218 uint8_t ep_no; 2219 2220 xfer = parm->curr_xfer; 2221 2222 /* 2223 * NOTE: This driver does not use any of the parameters that 2224 * are computed from the following values. Just set some 2225 * reasonable dummies: 2226 */ 2227 parm->hc_max_packet_size = 0x500; 2228 parm->hc_max_packet_count = 1; 2229 parm->hc_max_frame_size = 0x500; 2230 2231 usbd_transfer_setup_sub(parm); 2232 2233 /* 2234 * compute maximum number of TDs 2235 */ 2236 if (parm->methods == &uss820dci_device_ctrl_methods) { 2237 ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC */ ; 2238 2239 } else if (parm->methods == &uss820dci_device_bulk_methods) { 2240 ntd = xfer->nframes + 1 /* SYNC */ ; 2241 2242 } else if (parm->methods == &uss820dci_device_intr_methods) { 2243 ntd = xfer->nframes + 1 /* SYNC */ ; 2244 2245 } else if (parm->methods == &uss820dci_device_isoc_fs_methods) { 2246 ntd = xfer->nframes + 1 /* SYNC */ ; 2247 2248 } else { 2249 ntd = 0; 2250 } 2251 2252 /* 2253 * check if "usbd_transfer_setup_sub" set an error 2254 */ 2255 if (parm->err) { 2256 return; 2257 } 2258 /* 2259 * allocate transfer descriptors 2260 */ 2261 last_obj = NULL; 2262 2263 /* 2264 * get profile stuff 2265 */ 2266 if (ntd) { 2267 ep_no = xfer->endpointno & UE_ADDR; 2268 uss820dci_get_hw_ep_profile(parm->udev, &pf, ep_no); 2269 2270 if (pf == NULL) { 2271 /* should not happen */ 2272 parm->err = USB_ERR_INVAL; 2273 return; 2274 } 2275 } else { 2276 ep_no = 0; 2277 pf = NULL; 2278 } 2279 2280 /* align data */ 2281 parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); 2282 2283 for (n = 0; n != ntd; n++) { 2284 struct uss820dci_td *td; 2285 2286 if (parm->buf) { 2287 td = USB_ADD_BYTES(parm->buf, parm->size[0]); 2288 2289 /* init TD */ 2290 td->max_packet_size = xfer->max_packet_size; 2291 td->ep_index = ep_no; 2292 if (pf->support_multi_buffer && 2293 (parm->methods != &uss820dci_device_ctrl_methods)) { 2294 td->support_multi_buffer = 1; 2295 } 2296 td->obj_next = last_obj; 2297 2298 last_obj = td; 2299 } 2300 parm->size[0] += sizeof(*td); 2301 } 2302 2303 xfer->td_start[0] = last_obj; 2304 } 2305 2306 static void 2307 uss820dci_xfer_unsetup(struct usb_xfer *xfer) 2308 { 2309 return; 2310 } 2311 2312 static void 2313 uss820dci_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc, 2314 struct usb_endpoint *ep) 2315 { 2316 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(udev->bus); 2317 2318 DPRINTFN(2, "endpoint=%p, addr=%d, endpt=%d, mode=%d (%d)\n", 2319 ep, udev->address, 2320 edesc->bEndpointAddress, udev->flags.usb_mode, 2321 sc->sc_rt_addr); 2322 2323 if (udev->device_index != sc->sc_rt_addr) { 2324 if (udev->speed != USB_SPEED_FULL) { 2325 /* not supported */ 2326 return; 2327 } 2328 switch (edesc->bmAttributes & UE_XFERTYPE) { 2329 case UE_CONTROL: 2330 ep->methods = &uss820dci_device_ctrl_methods; 2331 break; 2332 case UE_INTERRUPT: 2333 ep->methods = &uss820dci_device_intr_methods; 2334 break; 2335 case UE_ISOCHRONOUS: 2336 ep->methods = &uss820dci_device_isoc_fs_methods; 2337 break; 2338 case UE_BULK: 2339 ep->methods = &uss820dci_device_bulk_methods; 2340 break; 2341 default: 2342 /* do nothing */ 2343 break; 2344 } 2345 } 2346 } 2347 2348 static void 2349 uss820dci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) 2350 { 2351 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(bus); 2352 2353 switch (state) { 2354 case USB_HW_POWER_SUSPEND: 2355 uss820dci_suspend(sc); 2356 break; 2357 case USB_HW_POWER_SHUTDOWN: 2358 uss820dci_uninit(sc); 2359 break; 2360 case USB_HW_POWER_RESUME: 2361 uss820dci_resume(sc); 2362 break; 2363 default: 2364 break; 2365 } 2366 } 2367 2368 static const struct usb_bus_methods uss820dci_bus_methods = 2369 { 2370 .endpoint_init = &uss820dci_ep_init, 2371 .xfer_setup = &uss820dci_xfer_setup, 2372 .xfer_unsetup = &uss820dci_xfer_unsetup, 2373 .get_hw_ep_profile = &uss820dci_get_hw_ep_profile, 2374 .xfer_stall = &uss820dci_xfer_stall, 2375 .set_stall = &uss820dci_set_stall, 2376 .clear_stall = &uss820dci_clear_stall, 2377 .roothub_exec = &uss820dci_roothub_exec, 2378 .xfer_poll = &uss820dci_do_poll, 2379 .set_hw_power_sleep = uss820dci_set_hw_power_sleep, 2380 }; 2381