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