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 temp.did_stall = !xfer->flags_int.control_stall; 880 881 sc = USS820_DCI_BUS2SC(xfer->xroot->bus); 882 ep_no = (xfer->endpointno & UE_ADDR); 883 884 /* check if we should prepend a setup message */ 885 886 if (xfer->flags_int.control_xfr) { 887 if (xfer->flags_int.control_hdr) { 888 889 temp.func = &uss820dci_setup_rx; 890 temp.len = xfer->frlengths[0]; 891 temp.pc = xfer->frbuffers + 0; 892 temp.short_pkt = temp.len ? 1 : 0; 893 /* check for last frame */ 894 if (xfer->nframes == 1) { 895 /* no STATUS stage yet, SETUP is last */ 896 if (xfer->flags_int.control_act) 897 temp.setup_alt_next = 0; 898 } 899 900 uss820dci_setup_standard_chain_sub(&temp); 901 } 902 x = 1; 903 } else { 904 x = 0; 905 } 906 907 if (x != xfer->nframes) { 908 if (xfer->endpointno & UE_DIR_IN) { 909 temp.func = &uss820dci_data_tx; 910 } else { 911 temp.func = &uss820dci_data_rx; 912 } 913 914 /* setup "pc" pointer */ 915 temp.pc = xfer->frbuffers + x; 916 } 917 while (x != xfer->nframes) { 918 919 /* DATA0 / DATA1 message */ 920 921 temp.len = xfer->frlengths[x]; 922 923 x++; 924 925 if (x == xfer->nframes) { 926 if (xfer->flags_int.control_xfr) { 927 if (xfer->flags_int.control_act) { 928 temp.setup_alt_next = 0; 929 } 930 } else { 931 temp.setup_alt_next = 0; 932 } 933 } 934 if (temp.len == 0) { 935 936 /* make sure that we send an USB packet */ 937 938 temp.short_pkt = 0; 939 940 } else { 941 942 /* regular data transfer */ 943 944 temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1; 945 } 946 947 uss820dci_setup_standard_chain_sub(&temp); 948 949 if (xfer->flags_int.isochronous_xfr) { 950 temp.offset += temp.len; 951 } else { 952 /* get next Page Cache pointer */ 953 temp.pc = xfer->frbuffers + x; 954 } 955 } 956 957 /* check for control transfer */ 958 if (xfer->flags_int.control_xfr) { 959 uint8_t need_sync; 960 961 /* always setup a valid "pc" pointer for status and sync */ 962 temp.pc = xfer->frbuffers + 0; 963 temp.len = 0; 964 temp.short_pkt = 0; 965 temp.setup_alt_next = 0; 966 967 /* check if we should append a status stage */ 968 if (!xfer->flags_int.control_act) { 969 970 /* 971 * Send a DATA1 message and invert the current 972 * endpoint direction. 973 */ 974 if (xfer->endpointno & UE_DIR_IN) { 975 temp.func = &uss820dci_data_rx; 976 need_sync = 0; 977 } else { 978 temp.func = &uss820dci_data_tx; 979 need_sync = 1; 980 } 981 temp.len = 0; 982 temp.short_pkt = 0; 983 984 uss820dci_setup_standard_chain_sub(&temp); 985 if (need_sync) { 986 /* we need a SYNC point after TX */ 987 temp.func = &uss820dci_data_tx_sync; 988 uss820dci_setup_standard_chain_sub(&temp); 989 } 990 } 991 } 992 /* must have at least one frame! */ 993 td = temp.td; 994 xfer->td_transfer_last = td; 995 } 996 997 static void 998 uss820dci_timeout(void *arg) 999 { 1000 struct usb_xfer *xfer = arg; 1001 1002 DPRINTF("xfer=%p\n", xfer); 1003 1004 USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED); 1005 1006 /* transfer is transferred */ 1007 uss820dci_device_done(xfer, USB_ERR_TIMEOUT); 1008 } 1009 1010 static void 1011 uss820dci_intr_set(struct usb_xfer *xfer, uint8_t set) 1012 { 1013 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus); 1014 uint8_t ep_no = (xfer->endpointno & UE_ADDR); 1015 uint8_t ep_reg; 1016 uint8_t temp; 1017 1018 DPRINTFN(15, "endpoint 0x%02x\n", xfer->endpointno); 1019 1020 if (ep_no > 3) { 1021 ep_reg = USS820_SBIE1; 1022 } else { 1023 ep_reg = USS820_SBIE; 1024 } 1025 1026 ep_no &= 3; 1027 ep_no = 1 << (2 * ep_no); 1028 1029 if (xfer->flags_int.control_xfr) { 1030 if (xfer->flags_int.control_hdr) { 1031 ep_no <<= 1; /* RX interrupt only */ 1032 } else { 1033 ep_no |= (ep_no << 1); /* RX and TX interrupt */ 1034 } 1035 } else { 1036 if (!(xfer->endpointno & UE_DIR_IN)) { 1037 ep_no <<= 1; 1038 } 1039 } 1040 temp = USS820_READ_1(sc, ep_reg); 1041 if (set) { 1042 temp |= ep_no; 1043 } else { 1044 temp &= ~ep_no; 1045 } 1046 USS820_WRITE_1(sc, ep_reg, temp); 1047 } 1048 1049 static void 1050 uss820dci_start_standard_chain(struct usb_xfer *xfer) 1051 { 1052 DPRINTFN(9, "\n"); 1053 1054 /* poll one time */ 1055 if (uss820dci_xfer_do_fifo(xfer)) { 1056 1057 /* 1058 * Only enable the endpoint interrupt when we are 1059 * actually waiting for data, hence we are dealing 1060 * with level triggered interrupts ! 1061 */ 1062 uss820dci_intr_set(xfer, 1); 1063 1064 /* put transfer on interrupt queue */ 1065 usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer); 1066 1067 /* start timeout, if any */ 1068 if (xfer->timeout != 0) { 1069 usbd_transfer_timeout_ms(xfer, 1070 &uss820dci_timeout, xfer->timeout); 1071 } 1072 } 1073 } 1074 1075 static void 1076 uss820dci_root_intr(struct uss820dci_softc *sc) 1077 { 1078 DPRINTFN(9, "\n"); 1079 1080 USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); 1081 1082 /* set port bit */ 1083 sc->sc_hub_idata[0] = 0x02; /* we only have one port */ 1084 1085 uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata, 1086 sizeof(sc->sc_hub_idata)); 1087 } 1088 1089 static usb_error_t 1090 uss820dci_standard_done_sub(struct usb_xfer *xfer) 1091 { 1092 struct uss820dci_td *td; 1093 uint32_t len; 1094 uint8_t error; 1095 1096 DPRINTFN(9, "\n"); 1097 1098 td = xfer->td_transfer_cache; 1099 1100 do { 1101 len = td->remainder; 1102 1103 if (xfer->aframes != xfer->nframes) { 1104 /* 1105 * Verify the length and subtract 1106 * the remainder from "frlengths[]": 1107 */ 1108 if (len > xfer->frlengths[xfer->aframes]) { 1109 td->error = 1; 1110 } else { 1111 xfer->frlengths[xfer->aframes] -= len; 1112 } 1113 } 1114 /* Check for transfer error */ 1115 if (td->error) { 1116 /* the transfer is finished */ 1117 error = 1; 1118 td = NULL; 1119 break; 1120 } 1121 /* Check for short transfer */ 1122 if (len > 0) { 1123 if (xfer->flags_int.short_frames_ok) { 1124 /* follow alt next */ 1125 if (td->alt_next) { 1126 td = td->obj_next; 1127 } else { 1128 td = NULL; 1129 } 1130 } else { 1131 /* the transfer is finished */ 1132 td = NULL; 1133 } 1134 error = 0; 1135 break; 1136 } 1137 td = td->obj_next; 1138 1139 /* this USB frame is complete */ 1140 error = 0; 1141 break; 1142 1143 } while (0); 1144 1145 /* update transfer cache */ 1146 1147 xfer->td_transfer_cache = td; 1148 1149 return (error ? 1150 USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION); 1151 } 1152 1153 static void 1154 uss820dci_standard_done(struct usb_xfer *xfer) 1155 { 1156 usb_error_t err = 0; 1157 1158 DPRINTFN(13, "xfer=%p endpoint=%p transfer done\n", 1159 xfer, xfer->endpoint); 1160 1161 /* reset scanner */ 1162 1163 xfer->td_transfer_cache = xfer->td_transfer_first; 1164 1165 if (xfer->flags_int.control_xfr) { 1166 1167 if (xfer->flags_int.control_hdr) { 1168 1169 err = uss820dci_standard_done_sub(xfer); 1170 } 1171 xfer->aframes = 1; 1172 1173 if (xfer->td_transfer_cache == NULL) { 1174 goto done; 1175 } 1176 } 1177 while (xfer->aframes != xfer->nframes) { 1178 1179 err = uss820dci_standard_done_sub(xfer); 1180 xfer->aframes++; 1181 1182 if (xfer->td_transfer_cache == NULL) { 1183 goto done; 1184 } 1185 } 1186 1187 if (xfer->flags_int.control_xfr && 1188 !xfer->flags_int.control_act) { 1189 1190 err = uss820dci_standard_done_sub(xfer); 1191 } 1192 done: 1193 uss820dci_device_done(xfer, err); 1194 } 1195 1196 /*------------------------------------------------------------------------* 1197 * uss820dci_device_done 1198 * 1199 * NOTE: this function can be called more than one time on the 1200 * same USB transfer! 1201 *------------------------------------------------------------------------*/ 1202 static void 1203 uss820dci_device_done(struct usb_xfer *xfer, usb_error_t error) 1204 { 1205 USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED); 1206 1207 DPRINTFN(2, "xfer=%p, endpoint=%p, error=%d\n", 1208 xfer, xfer->endpoint, error); 1209 1210 if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) { 1211 uss820dci_intr_set(xfer, 0); 1212 } 1213 /* dequeue transfer and start next transfer */ 1214 usbd_transfer_done(xfer, error); 1215 } 1216 1217 static void 1218 uss820dci_xfer_stall(struct usb_xfer *xfer) 1219 { 1220 uss820dci_device_done(xfer, USB_ERR_STALLED); 1221 } 1222 1223 static void 1224 uss820dci_set_stall(struct usb_device *udev, 1225 struct usb_endpoint *ep, uint8_t *did_stall) 1226 { 1227 struct uss820dci_softc *sc; 1228 uint8_t ep_no; 1229 uint8_t ep_type; 1230 uint8_t ep_dir; 1231 uint8_t temp; 1232 1233 USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED); 1234 1235 DPRINTFN(5, "endpoint=%p\n", ep); 1236 1237 /* set FORCESTALL */ 1238 sc = USS820_DCI_BUS2SC(udev->bus); 1239 ep_no = (ep->edesc->bEndpointAddress & UE_ADDR); 1240 ep_dir = (ep->edesc->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT)); 1241 ep_type = (ep->edesc->bmAttributes & UE_XFERTYPE); 1242 1243 if (ep_type == UE_CONTROL) { 1244 /* should not happen */ 1245 return; 1246 } 1247 USS820_WRITE_1(sc, USS820_EPINDEX, ep_no); 1248 1249 if (ep_dir == UE_DIR_IN) { 1250 temp = USS820_EPCON_TXSTL; 1251 } else { 1252 temp = USS820_EPCON_RXSTL; 1253 } 1254 uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF, temp); 1255 } 1256 1257 static void 1258 uss820dci_clear_stall_sub(struct uss820dci_softc *sc, 1259 uint8_t ep_no, uint8_t ep_type, uint8_t ep_dir) 1260 { 1261 uint8_t temp; 1262 1263 if (ep_type == UE_CONTROL) { 1264 /* clearing stall is not needed */ 1265 return; 1266 } 1267 /* select endpoint index */ 1268 USS820_WRITE_1(sc, USS820_EPINDEX, ep_no); 1269 1270 /* clear stall and disable I/O transfers */ 1271 if (ep_dir == UE_DIR_IN) { 1272 temp = 0xFF ^ (USS820_EPCON_TXOE | 1273 USS820_EPCON_TXSTL); 1274 } else { 1275 temp = 0xFF ^ (USS820_EPCON_RXIE | 1276 USS820_EPCON_RXSTL); 1277 } 1278 uss820dci_update_shared_1(sc, USS820_EPCON, temp, 0); 1279 1280 if (ep_dir == UE_DIR_IN) { 1281 /* reset data toggle */ 1282 USS820_WRITE_1(sc, USS820_TXSTAT, 1283 USS820_TXSTAT_TXSOVW); 1284 1285 /* reset FIFO */ 1286 temp = USS820_READ_1(sc, USS820_TXCON); 1287 temp |= USS820_TXCON_TXCLR; 1288 USS820_WRITE_1(sc, USS820_TXCON, temp); 1289 temp &= ~USS820_TXCON_TXCLR; 1290 USS820_WRITE_1(sc, USS820_TXCON, temp); 1291 } else { 1292 1293 /* reset data toggle */ 1294 uss820dci_update_shared_1(sc, USS820_RXSTAT, 1295 0, USS820_RXSTAT_RXSOVW); 1296 1297 /* reset FIFO */ 1298 temp = USS820_READ_1(sc, USS820_RXCON); 1299 temp |= USS820_RXCON_RXCLR; 1300 temp &= ~USS820_RXCON_RXFFRC; 1301 USS820_WRITE_1(sc, USS820_RXCON, temp); 1302 temp &= ~USS820_RXCON_RXCLR; 1303 USS820_WRITE_1(sc, USS820_RXCON, temp); 1304 } 1305 } 1306 1307 static void 1308 uss820dci_clear_stall(struct usb_device *udev, struct usb_endpoint *ep) 1309 { 1310 struct uss820dci_softc *sc; 1311 struct usb_endpoint_descriptor *ed; 1312 1313 USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED); 1314 1315 DPRINTFN(5, "endpoint=%p\n", ep); 1316 1317 /* check mode */ 1318 if (udev->flags.usb_mode != USB_MODE_DEVICE) { 1319 /* not supported */ 1320 return; 1321 } 1322 /* get softc */ 1323 sc = USS820_DCI_BUS2SC(udev->bus); 1324 1325 /* get endpoint descriptor */ 1326 ed = ep->edesc; 1327 1328 /* reset endpoint */ 1329 uss820dci_clear_stall_sub(sc, 1330 (ed->bEndpointAddress & UE_ADDR), 1331 (ed->bmAttributes & UE_XFERTYPE), 1332 (ed->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT))); 1333 } 1334 1335 usb_error_t 1336 uss820dci_init(struct uss820dci_softc *sc) 1337 { 1338 const struct usb_hw_ep_profile *pf; 1339 uint8_t n; 1340 uint8_t temp; 1341 1342 DPRINTF("start\n"); 1343 1344 /* set up the bus structure */ 1345 sc->sc_bus.usbrev = USB_REV_1_1; 1346 sc->sc_bus.methods = &uss820dci_bus_methods; 1347 1348 USB_BUS_LOCK(&sc->sc_bus); 1349 1350 /* we always have VBUS */ 1351 sc->sc_flags.status_vbus = 1; 1352 1353 /* reset the chip */ 1354 USS820_WRITE_1(sc, USS820_SCR, USS820_SCR_SRESET); 1355 DELAY(100); 1356 USS820_WRITE_1(sc, USS820_SCR, 0); 1357 1358 /* wait for reset to complete */ 1359 for (n = 0;; n++) { 1360 1361 temp = USS820_READ_1(sc, USS820_MCSR); 1362 1363 if (temp & USS820_MCSR_INIT) { 1364 break; 1365 } 1366 if (n == 100) { 1367 USB_BUS_UNLOCK(&sc->sc_bus); 1368 return (USB_ERR_INVAL); 1369 } 1370 /* wait a little for things to stabilise */ 1371 DELAY(100); 1372 } 1373 1374 /* do a pulldown */ 1375 uss820dci_pull_down(sc); 1376 1377 /* wait 10ms for pulldown to stabilise */ 1378 usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 100); 1379 1380 /* check hardware revision */ 1381 temp = USS820_READ_1(sc, USS820_REV); 1382 1383 if (temp < 0x13) { 1384 USB_BUS_UNLOCK(&sc->sc_bus); 1385 return (USB_ERR_INVAL); 1386 } 1387 /* enable interrupts */ 1388 USS820_WRITE_1(sc, USS820_SCR, 1389 USS820_SCR_T_IRQ | 1390 USS820_SCR_IE_RESET | 1391 /* USS820_SCR_RWUPE | */ 1392 USS820_SCR_IE_SUSP | 1393 USS820_SCR_IRQPOL); 1394 1395 /* enable interrupts */ 1396 USS820_WRITE_1(sc, USS820_SCRATCH, 1397 USS820_SCRATCH_IE_RESUME); 1398 1399 /* enable features */ 1400 USS820_WRITE_1(sc, USS820_MCSR, 1401 USS820_MCSR_BDFEAT | 1402 USS820_MCSR_FEAT); 1403 1404 sc->sc_flags.mcsr_feat = 1; 1405 1406 /* disable interrupts */ 1407 USS820_WRITE_1(sc, USS820_SBIE, 0); 1408 1409 /* disable interrupts */ 1410 USS820_WRITE_1(sc, USS820_SBIE1, 0); 1411 1412 /* disable all endpoints */ 1413 for (n = 0; n != USS820_EP_MAX; n++) { 1414 1415 /* select endpoint */ 1416 USS820_WRITE_1(sc, USS820_EPINDEX, n); 1417 1418 /* disable endpoint */ 1419 uss820dci_update_shared_1(sc, USS820_EPCON, 0, 0); 1420 } 1421 1422 /* 1423 * Initialise default values for some registers that cannot be 1424 * changed during operation! 1425 */ 1426 for (n = 0; n != USS820_EP_MAX; n++) { 1427 1428 uss820dci_get_hw_ep_profile(NULL, &pf, n); 1429 1430 /* the maximum frame sizes should be the same */ 1431 if (pf->max_in_frame_size != pf->max_out_frame_size) { 1432 DPRINTF("Max frame size mismatch %u != %u\n", 1433 pf->max_in_frame_size, pf->max_out_frame_size); 1434 } 1435 if (pf->support_isochronous) { 1436 if (pf->max_in_frame_size <= 64) { 1437 temp = (USS820_TXCON_FFSZ_16_64 | 1438 USS820_TXCON_TXISO | 1439 USS820_TXCON_ATM); 1440 } else if (pf->max_in_frame_size <= 256) { 1441 temp = (USS820_TXCON_FFSZ_64_256 | 1442 USS820_TXCON_TXISO | 1443 USS820_TXCON_ATM); 1444 } else if (pf->max_in_frame_size <= 512) { 1445 temp = (USS820_TXCON_FFSZ_8_512 | 1446 USS820_TXCON_TXISO | 1447 USS820_TXCON_ATM); 1448 } else { /* 1024 bytes */ 1449 temp = (USS820_TXCON_FFSZ_32_1024 | 1450 USS820_TXCON_TXISO | 1451 USS820_TXCON_ATM); 1452 } 1453 } else { 1454 if ((pf->max_in_frame_size <= 8) && 1455 (sc->sc_flags.mcsr_feat)) { 1456 temp = (USS820_TXCON_FFSZ_8_512 | 1457 USS820_TXCON_ATM); 1458 } else if (pf->max_in_frame_size <= 16) { 1459 temp = (USS820_TXCON_FFSZ_16_64 | 1460 USS820_TXCON_ATM); 1461 } else if ((pf->max_in_frame_size <= 32) && 1462 (sc->sc_flags.mcsr_feat)) { 1463 temp = (USS820_TXCON_FFSZ_32_1024 | 1464 USS820_TXCON_ATM); 1465 } else { /* 64 bytes */ 1466 temp = (USS820_TXCON_FFSZ_64_256 | 1467 USS820_TXCON_ATM); 1468 } 1469 } 1470 1471 /* need to configure the chip early */ 1472 1473 USS820_WRITE_1(sc, USS820_EPINDEX, n); 1474 USS820_WRITE_1(sc, USS820_TXCON, temp); 1475 USS820_WRITE_1(sc, USS820_RXCON, temp); 1476 1477 if (pf->support_control) { 1478 temp = USS820_EPCON_CTLEP | 1479 USS820_EPCON_RXSPM | 1480 USS820_EPCON_RXIE | 1481 USS820_EPCON_RXEPEN | 1482 USS820_EPCON_TXOE | 1483 USS820_EPCON_TXEPEN; 1484 } else { 1485 temp = USS820_EPCON_RXEPEN | USS820_EPCON_TXEPEN; 1486 } 1487 1488 uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF, temp); 1489 } 1490 1491 USB_BUS_UNLOCK(&sc->sc_bus); 1492 1493 /* catch any lost interrupts */ 1494 1495 uss820dci_do_poll(&sc->sc_bus); 1496 1497 return (0); /* success */ 1498 } 1499 1500 void 1501 uss820dci_uninit(struct uss820dci_softc *sc) 1502 { 1503 uint8_t temp; 1504 1505 USB_BUS_LOCK(&sc->sc_bus); 1506 1507 /* disable all interrupts */ 1508 temp = USS820_READ_1(sc, USS820_SCR); 1509 temp &= ~USS820_SCR_T_IRQ; 1510 USS820_WRITE_1(sc, USS820_SCR, temp); 1511 1512 sc->sc_flags.port_powered = 0; 1513 sc->sc_flags.status_vbus = 0; 1514 sc->sc_flags.status_bus_reset = 0; 1515 sc->sc_flags.status_suspend = 0; 1516 sc->sc_flags.change_suspend = 0; 1517 sc->sc_flags.change_connect = 1; 1518 1519 uss820dci_pull_down(sc); 1520 USB_BUS_UNLOCK(&sc->sc_bus); 1521 } 1522 1523 static void 1524 uss820dci_suspend(struct uss820dci_softc *sc) 1525 { 1526 /* TODO */ 1527 } 1528 1529 static void 1530 uss820dci_resume(struct uss820dci_softc *sc) 1531 { 1532 /* TODO */ 1533 } 1534 1535 static void 1536 uss820dci_do_poll(struct usb_bus *bus) 1537 { 1538 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(bus); 1539 1540 USB_BUS_LOCK(&sc->sc_bus); 1541 uss820dci_interrupt_poll(sc); 1542 USB_BUS_UNLOCK(&sc->sc_bus); 1543 } 1544 1545 /*------------------------------------------------------------------------* 1546 * at91dci bulk support 1547 *------------------------------------------------------------------------*/ 1548 static void 1549 uss820dci_device_bulk_open(struct usb_xfer *xfer) 1550 { 1551 return; 1552 } 1553 1554 static void 1555 uss820dci_device_bulk_close(struct usb_xfer *xfer) 1556 { 1557 uss820dci_device_done(xfer, USB_ERR_CANCELLED); 1558 } 1559 1560 static void 1561 uss820dci_device_bulk_enter(struct usb_xfer *xfer) 1562 { 1563 return; 1564 } 1565 1566 static void 1567 uss820dci_device_bulk_start(struct usb_xfer *xfer) 1568 { 1569 /* setup TDs */ 1570 uss820dci_setup_standard_chain(xfer); 1571 uss820dci_start_standard_chain(xfer); 1572 } 1573 1574 static const struct usb_pipe_methods uss820dci_device_bulk_methods = 1575 { 1576 .open = uss820dci_device_bulk_open, 1577 .close = uss820dci_device_bulk_close, 1578 .enter = uss820dci_device_bulk_enter, 1579 .start = uss820dci_device_bulk_start, 1580 }; 1581 1582 /*------------------------------------------------------------------------* 1583 * at91dci control support 1584 *------------------------------------------------------------------------*/ 1585 static void 1586 uss820dci_device_ctrl_open(struct usb_xfer *xfer) 1587 { 1588 return; 1589 } 1590 1591 static void 1592 uss820dci_device_ctrl_close(struct usb_xfer *xfer) 1593 { 1594 uss820dci_device_done(xfer, USB_ERR_CANCELLED); 1595 } 1596 1597 static void 1598 uss820dci_device_ctrl_enter(struct usb_xfer *xfer) 1599 { 1600 return; 1601 } 1602 1603 static void 1604 uss820dci_device_ctrl_start(struct usb_xfer *xfer) 1605 { 1606 /* setup TDs */ 1607 uss820dci_setup_standard_chain(xfer); 1608 uss820dci_start_standard_chain(xfer); 1609 } 1610 1611 static const struct usb_pipe_methods uss820dci_device_ctrl_methods = 1612 { 1613 .open = uss820dci_device_ctrl_open, 1614 .close = uss820dci_device_ctrl_close, 1615 .enter = uss820dci_device_ctrl_enter, 1616 .start = uss820dci_device_ctrl_start, 1617 }; 1618 1619 /*------------------------------------------------------------------------* 1620 * at91dci interrupt support 1621 *------------------------------------------------------------------------*/ 1622 static void 1623 uss820dci_device_intr_open(struct usb_xfer *xfer) 1624 { 1625 return; 1626 } 1627 1628 static void 1629 uss820dci_device_intr_close(struct usb_xfer *xfer) 1630 { 1631 uss820dci_device_done(xfer, USB_ERR_CANCELLED); 1632 } 1633 1634 static void 1635 uss820dci_device_intr_enter(struct usb_xfer *xfer) 1636 { 1637 return; 1638 } 1639 1640 static void 1641 uss820dci_device_intr_start(struct usb_xfer *xfer) 1642 { 1643 /* setup TDs */ 1644 uss820dci_setup_standard_chain(xfer); 1645 uss820dci_start_standard_chain(xfer); 1646 } 1647 1648 static const struct usb_pipe_methods uss820dci_device_intr_methods = 1649 { 1650 .open = uss820dci_device_intr_open, 1651 .close = uss820dci_device_intr_close, 1652 .enter = uss820dci_device_intr_enter, 1653 .start = uss820dci_device_intr_start, 1654 }; 1655 1656 /*------------------------------------------------------------------------* 1657 * at91dci full speed isochronous support 1658 *------------------------------------------------------------------------*/ 1659 static void 1660 uss820dci_device_isoc_fs_open(struct usb_xfer *xfer) 1661 { 1662 return; 1663 } 1664 1665 static void 1666 uss820dci_device_isoc_fs_close(struct usb_xfer *xfer) 1667 { 1668 uss820dci_device_done(xfer, USB_ERR_CANCELLED); 1669 } 1670 1671 static void 1672 uss820dci_device_isoc_fs_enter(struct usb_xfer *xfer) 1673 { 1674 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus); 1675 uint32_t temp; 1676 uint32_t nframes; 1677 1678 DPRINTFN(6, "xfer=%p next=%d nframes=%d\n", 1679 xfer, xfer->endpoint->isoc_next, xfer->nframes); 1680 1681 /* get the current frame index - we don't need the high bits */ 1682 1683 nframes = USS820_READ_1(sc, USS820_SOFL); 1684 1685 /* 1686 * check if the frame index is within the window where the 1687 * frames will be inserted 1688 */ 1689 temp = (nframes - xfer->endpoint->isoc_next) & USS820_SOFL_MASK; 1690 1691 if ((xfer->endpoint->is_synced == 0) || 1692 (temp < xfer->nframes)) { 1693 /* 1694 * If there is data underflow or the pipe queue is 1695 * empty we schedule the transfer a few frames ahead 1696 * of the current frame position. Else two isochronous 1697 * transfers might overlap. 1698 */ 1699 xfer->endpoint->isoc_next = (nframes + 3) & USS820_SOFL_MASK; 1700 xfer->endpoint->is_synced = 1; 1701 DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); 1702 } 1703 /* 1704 * compute how many milliseconds the insertion is ahead of the 1705 * current frame position: 1706 */ 1707 temp = (xfer->endpoint->isoc_next - nframes) & USS820_SOFL_MASK; 1708 1709 /* 1710 * pre-compute when the isochronous transfer will be finished: 1711 */ 1712 xfer->isoc_time_complete = 1713 usb_isoc_time_expand(&sc->sc_bus, nframes) + temp + 1714 xfer->nframes; 1715 1716 /* compute frame number for next insertion */ 1717 xfer->endpoint->isoc_next += xfer->nframes; 1718 1719 /* setup TDs */ 1720 uss820dci_setup_standard_chain(xfer); 1721 } 1722 1723 static void 1724 uss820dci_device_isoc_fs_start(struct usb_xfer *xfer) 1725 { 1726 /* start TD chain */ 1727 uss820dci_start_standard_chain(xfer); 1728 } 1729 1730 static const struct usb_pipe_methods uss820dci_device_isoc_fs_methods = 1731 { 1732 .open = uss820dci_device_isoc_fs_open, 1733 .close = uss820dci_device_isoc_fs_close, 1734 .enter = uss820dci_device_isoc_fs_enter, 1735 .start = uss820dci_device_isoc_fs_start, 1736 }; 1737 1738 /*------------------------------------------------------------------------* 1739 * at91dci root control support 1740 *------------------------------------------------------------------------* 1741 * Simulate a hardware HUB by handling all the necessary requests. 1742 *------------------------------------------------------------------------*/ 1743 1744 static const struct usb_device_descriptor uss820dci_devd = { 1745 .bLength = sizeof(struct usb_device_descriptor), 1746 .bDescriptorType = UDESC_DEVICE, 1747 .bcdUSB = {0x00, 0x02}, 1748 .bDeviceClass = UDCLASS_HUB, 1749 .bDeviceSubClass = UDSUBCLASS_HUB, 1750 .bDeviceProtocol = UDPROTO_FSHUB, 1751 .bMaxPacketSize = 64, 1752 .bcdDevice = {0x00, 0x01}, 1753 .iManufacturer = 1, 1754 .iProduct = 2, 1755 .bNumConfigurations = 1, 1756 }; 1757 1758 static const struct usb_device_qualifier uss820dci_odevd = { 1759 .bLength = sizeof(struct usb_device_qualifier), 1760 .bDescriptorType = UDESC_DEVICE_QUALIFIER, 1761 .bcdUSB = {0x00, 0x02}, 1762 .bDeviceClass = UDCLASS_HUB, 1763 .bDeviceSubClass = UDSUBCLASS_HUB, 1764 .bDeviceProtocol = UDPROTO_FSHUB, 1765 .bMaxPacketSize0 = 0, 1766 .bNumConfigurations = 0, 1767 }; 1768 1769 static const struct uss820dci_config_desc uss820dci_confd = { 1770 .confd = { 1771 .bLength = sizeof(struct usb_config_descriptor), 1772 .bDescriptorType = UDESC_CONFIG, 1773 .wTotalLength[0] = sizeof(uss820dci_confd), 1774 .bNumInterface = 1, 1775 .bConfigurationValue = 1, 1776 .iConfiguration = 0, 1777 .bmAttributes = UC_SELF_POWERED, 1778 .bMaxPower = 0, 1779 }, 1780 .ifcd = { 1781 .bLength = sizeof(struct usb_interface_descriptor), 1782 .bDescriptorType = UDESC_INTERFACE, 1783 .bNumEndpoints = 1, 1784 .bInterfaceClass = UICLASS_HUB, 1785 .bInterfaceSubClass = UISUBCLASS_HUB, 1786 .bInterfaceProtocol = 0, 1787 }, 1788 1789 .endpd = { 1790 .bLength = sizeof(struct usb_endpoint_descriptor), 1791 .bDescriptorType = UDESC_ENDPOINT, 1792 .bEndpointAddress = (UE_DIR_IN | USS820_DCI_INTR_ENDPT), 1793 .bmAttributes = UE_INTERRUPT, 1794 .wMaxPacketSize[0] = 8, 1795 .bInterval = 255, 1796 }, 1797 }; 1798 1799 #define HSETW(ptr, val) ptr = { (uint8_t)(val), (uint8_t)((val) >> 8) } 1800 1801 static const struct usb_hub_descriptor_min uss820dci_hubd = { 1802 .bDescLength = sizeof(uss820dci_hubd), 1803 .bDescriptorType = UDESC_HUB, 1804 .bNbrPorts = 1, 1805 HSETW(.wHubCharacteristics, (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL)), 1806 .bPwrOn2PwrGood = 50, 1807 .bHubContrCurrent = 0, 1808 .DeviceRemovable = {0}, /* port is removable */ 1809 }; 1810 1811 #define STRING_VENDOR \ 1812 "A\0G\0E\0R\0E" 1813 1814 #define STRING_PRODUCT \ 1815 "D\0C\0I\0 \0R\0o\0o\0t\0 \0H\0U\0B" 1816 1817 USB_MAKE_STRING_DESC(STRING_VENDOR, uss820dci_vendor); 1818 USB_MAKE_STRING_DESC(STRING_PRODUCT, uss820dci_product); 1819 1820 static usb_error_t 1821 uss820dci_roothub_exec(struct usb_device *udev, 1822 struct usb_device_request *req, const void **pptr, uint16_t *plength) 1823 { 1824 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(udev->bus); 1825 const void *ptr; 1826 uint16_t len; 1827 uint16_t value; 1828 uint16_t index; 1829 usb_error_t err; 1830 1831 USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); 1832 1833 /* buffer reset */ 1834 ptr = (const void *)&sc->sc_hub_temp; 1835 len = 0; 1836 err = 0; 1837 1838 value = UGETW(req->wValue); 1839 index = UGETW(req->wIndex); 1840 1841 /* demultiplex the control request */ 1842 1843 switch (req->bmRequestType) { 1844 case UT_READ_DEVICE: 1845 switch (req->bRequest) { 1846 case UR_GET_DESCRIPTOR: 1847 goto tr_handle_get_descriptor; 1848 case UR_GET_CONFIG: 1849 goto tr_handle_get_config; 1850 case UR_GET_STATUS: 1851 goto tr_handle_get_status; 1852 default: 1853 goto tr_stalled; 1854 } 1855 break; 1856 1857 case UT_WRITE_DEVICE: 1858 switch (req->bRequest) { 1859 case UR_SET_ADDRESS: 1860 goto tr_handle_set_address; 1861 case UR_SET_CONFIG: 1862 goto tr_handle_set_config; 1863 case UR_CLEAR_FEATURE: 1864 goto tr_valid; /* nop */ 1865 case UR_SET_DESCRIPTOR: 1866 goto tr_valid; /* nop */ 1867 case UR_SET_FEATURE: 1868 default: 1869 goto tr_stalled; 1870 } 1871 break; 1872 1873 case UT_WRITE_ENDPOINT: 1874 switch (req->bRequest) { 1875 case UR_CLEAR_FEATURE: 1876 switch (UGETW(req->wValue)) { 1877 case UF_ENDPOINT_HALT: 1878 goto tr_handle_clear_halt; 1879 case UF_DEVICE_REMOTE_WAKEUP: 1880 goto tr_handle_clear_wakeup; 1881 default: 1882 goto tr_stalled; 1883 } 1884 break; 1885 case UR_SET_FEATURE: 1886 switch (UGETW(req->wValue)) { 1887 case UF_ENDPOINT_HALT: 1888 goto tr_handle_set_halt; 1889 case UF_DEVICE_REMOTE_WAKEUP: 1890 goto tr_handle_set_wakeup; 1891 default: 1892 goto tr_stalled; 1893 } 1894 break; 1895 case UR_SYNCH_FRAME: 1896 goto tr_valid; /* nop */ 1897 default: 1898 goto tr_stalled; 1899 } 1900 break; 1901 1902 case UT_READ_ENDPOINT: 1903 switch (req->bRequest) { 1904 case UR_GET_STATUS: 1905 goto tr_handle_get_ep_status; 1906 default: 1907 goto tr_stalled; 1908 } 1909 break; 1910 1911 case UT_WRITE_INTERFACE: 1912 switch (req->bRequest) { 1913 case UR_SET_INTERFACE: 1914 goto tr_handle_set_interface; 1915 case UR_CLEAR_FEATURE: 1916 goto tr_valid; /* nop */ 1917 case UR_SET_FEATURE: 1918 default: 1919 goto tr_stalled; 1920 } 1921 break; 1922 1923 case UT_READ_INTERFACE: 1924 switch (req->bRequest) { 1925 case UR_GET_INTERFACE: 1926 goto tr_handle_get_interface; 1927 case UR_GET_STATUS: 1928 goto tr_handle_get_iface_status; 1929 default: 1930 goto tr_stalled; 1931 } 1932 break; 1933 1934 case UT_WRITE_CLASS_INTERFACE: 1935 case UT_WRITE_VENDOR_INTERFACE: 1936 /* XXX forward */ 1937 break; 1938 1939 case UT_READ_CLASS_INTERFACE: 1940 case UT_READ_VENDOR_INTERFACE: 1941 /* XXX forward */ 1942 break; 1943 1944 case UT_WRITE_CLASS_DEVICE: 1945 switch (req->bRequest) { 1946 case UR_CLEAR_FEATURE: 1947 goto tr_valid; 1948 case UR_SET_DESCRIPTOR: 1949 case UR_SET_FEATURE: 1950 break; 1951 default: 1952 goto tr_stalled; 1953 } 1954 break; 1955 1956 case UT_WRITE_CLASS_OTHER: 1957 switch (req->bRequest) { 1958 case UR_CLEAR_FEATURE: 1959 goto tr_handle_clear_port_feature; 1960 case UR_SET_FEATURE: 1961 goto tr_handle_set_port_feature; 1962 case UR_CLEAR_TT_BUFFER: 1963 case UR_RESET_TT: 1964 case UR_STOP_TT: 1965 goto tr_valid; 1966 1967 default: 1968 goto tr_stalled; 1969 } 1970 break; 1971 1972 case UT_READ_CLASS_OTHER: 1973 switch (req->bRequest) { 1974 case UR_GET_TT_STATE: 1975 goto tr_handle_get_tt_state; 1976 case UR_GET_STATUS: 1977 goto tr_handle_get_port_status; 1978 default: 1979 goto tr_stalled; 1980 } 1981 break; 1982 1983 case UT_READ_CLASS_DEVICE: 1984 switch (req->bRequest) { 1985 case UR_GET_DESCRIPTOR: 1986 goto tr_handle_get_class_descriptor; 1987 case UR_GET_STATUS: 1988 goto tr_handle_get_class_status; 1989 1990 default: 1991 goto tr_stalled; 1992 } 1993 break; 1994 default: 1995 goto tr_stalled; 1996 } 1997 goto tr_valid; 1998 1999 tr_handle_get_descriptor: 2000 switch (value >> 8) { 2001 case UDESC_DEVICE: 2002 if (value & 0xff) { 2003 goto tr_stalled; 2004 } 2005 len = sizeof(uss820dci_devd); 2006 ptr = (const void *)&uss820dci_devd; 2007 goto tr_valid; 2008 case UDESC_CONFIG: 2009 if (value & 0xff) { 2010 goto tr_stalled; 2011 } 2012 len = sizeof(uss820dci_confd); 2013 ptr = (const void *)&uss820dci_confd; 2014 goto tr_valid; 2015 case UDESC_STRING: 2016 switch (value & 0xff) { 2017 case 0: /* Language table */ 2018 len = sizeof(usb_string_lang_en); 2019 ptr = (const void *)&usb_string_lang_en; 2020 goto tr_valid; 2021 2022 case 1: /* Vendor */ 2023 len = sizeof(uss820dci_vendor); 2024 ptr = (const void *)&uss820dci_vendor; 2025 goto tr_valid; 2026 2027 case 2: /* Product */ 2028 len = sizeof(uss820dci_product); 2029 ptr = (const void *)&uss820dci_product; 2030 goto tr_valid; 2031 default: 2032 break; 2033 } 2034 break; 2035 default: 2036 goto tr_stalled; 2037 } 2038 goto tr_stalled; 2039 2040 tr_handle_get_config: 2041 len = 1; 2042 sc->sc_hub_temp.wValue[0] = sc->sc_conf; 2043 goto tr_valid; 2044 2045 tr_handle_get_status: 2046 len = 2; 2047 USETW(sc->sc_hub_temp.wValue, UDS_SELF_POWERED); 2048 goto tr_valid; 2049 2050 tr_handle_set_address: 2051 if (value & 0xFF00) { 2052 goto tr_stalled; 2053 } 2054 sc->sc_rt_addr = value; 2055 goto tr_valid; 2056 2057 tr_handle_set_config: 2058 if (value >= 2) { 2059 goto tr_stalled; 2060 } 2061 sc->sc_conf = value; 2062 goto tr_valid; 2063 2064 tr_handle_get_interface: 2065 len = 1; 2066 sc->sc_hub_temp.wValue[0] = 0; 2067 goto tr_valid; 2068 2069 tr_handle_get_tt_state: 2070 tr_handle_get_class_status: 2071 tr_handle_get_iface_status: 2072 tr_handle_get_ep_status: 2073 len = 2; 2074 USETW(sc->sc_hub_temp.wValue, 0); 2075 goto tr_valid; 2076 2077 tr_handle_set_halt: 2078 tr_handle_set_interface: 2079 tr_handle_set_wakeup: 2080 tr_handle_clear_wakeup: 2081 tr_handle_clear_halt: 2082 goto tr_valid; 2083 2084 tr_handle_clear_port_feature: 2085 if (index != 1) { 2086 goto tr_stalled; 2087 } 2088 DPRINTFN(9, "UR_CLEAR_PORT_FEATURE on port %d\n", index); 2089 2090 switch (value) { 2091 case UHF_PORT_SUSPEND: 2092 uss820dci_wakeup_peer(sc); 2093 break; 2094 2095 case UHF_PORT_ENABLE: 2096 sc->sc_flags.port_enabled = 0; 2097 break; 2098 2099 case UHF_PORT_TEST: 2100 case UHF_PORT_INDICATOR: 2101 case UHF_C_PORT_ENABLE: 2102 case UHF_C_PORT_OVER_CURRENT: 2103 case UHF_C_PORT_RESET: 2104 /* nops */ 2105 break; 2106 case UHF_PORT_POWER: 2107 sc->sc_flags.port_powered = 0; 2108 uss820dci_pull_down(sc); 2109 break; 2110 case UHF_C_PORT_CONNECTION: 2111 sc->sc_flags.change_connect = 0; 2112 break; 2113 case UHF_C_PORT_SUSPEND: 2114 sc->sc_flags.change_suspend = 0; 2115 break; 2116 default: 2117 err = USB_ERR_IOERROR; 2118 goto done; 2119 } 2120 goto tr_valid; 2121 2122 tr_handle_set_port_feature: 2123 if (index != 1) { 2124 goto tr_stalled; 2125 } 2126 DPRINTFN(9, "UR_SET_PORT_FEATURE\n"); 2127 2128 switch (value) { 2129 case UHF_PORT_ENABLE: 2130 sc->sc_flags.port_enabled = 1; 2131 break; 2132 case UHF_PORT_SUSPEND: 2133 case UHF_PORT_RESET: 2134 case UHF_PORT_TEST: 2135 case UHF_PORT_INDICATOR: 2136 /* nops */ 2137 break; 2138 case UHF_PORT_POWER: 2139 sc->sc_flags.port_powered = 1; 2140 break; 2141 default: 2142 err = USB_ERR_IOERROR; 2143 goto done; 2144 } 2145 goto tr_valid; 2146 2147 tr_handle_get_port_status: 2148 2149 DPRINTFN(9, "UR_GET_PORT_STATUS\n"); 2150 2151 if (index != 1) { 2152 goto tr_stalled; 2153 } 2154 if (sc->sc_flags.status_vbus) { 2155 uss820dci_pull_up(sc); 2156 } else { 2157 uss820dci_pull_down(sc); 2158 } 2159 2160 /* Select FULL-speed and Device Side Mode */ 2161 2162 value = UPS_PORT_MODE_DEVICE; 2163 2164 if (sc->sc_flags.port_powered) { 2165 value |= UPS_PORT_POWER; 2166 } 2167 if (sc->sc_flags.port_enabled) { 2168 value |= UPS_PORT_ENABLED; 2169 } 2170 if (sc->sc_flags.status_vbus && 2171 sc->sc_flags.status_bus_reset) { 2172 value |= UPS_CURRENT_CONNECT_STATUS; 2173 } 2174 if (sc->sc_flags.status_suspend) { 2175 value |= UPS_SUSPEND; 2176 } 2177 USETW(sc->sc_hub_temp.ps.wPortStatus, value); 2178 2179 value = 0; 2180 2181 if (sc->sc_flags.change_connect) { 2182 value |= UPS_C_CONNECT_STATUS; 2183 } 2184 if (sc->sc_flags.change_suspend) { 2185 value |= UPS_C_SUSPEND; 2186 } 2187 USETW(sc->sc_hub_temp.ps.wPortChange, value); 2188 len = sizeof(sc->sc_hub_temp.ps); 2189 goto tr_valid; 2190 2191 tr_handle_get_class_descriptor: 2192 if (value & 0xFF) { 2193 goto tr_stalled; 2194 } 2195 ptr = (const void *)&uss820dci_hubd; 2196 len = sizeof(uss820dci_hubd); 2197 goto tr_valid; 2198 2199 tr_stalled: 2200 err = USB_ERR_STALLED; 2201 tr_valid: 2202 done: 2203 *plength = len; 2204 *pptr = ptr; 2205 return (err); 2206 } 2207 2208 static void 2209 uss820dci_xfer_setup(struct usb_setup_params *parm) 2210 { 2211 const struct usb_hw_ep_profile *pf; 2212 struct uss820dci_softc *sc; 2213 struct usb_xfer *xfer; 2214 void *last_obj; 2215 uint32_t ntd; 2216 uint32_t n; 2217 uint8_t ep_no; 2218 2219 sc = USS820_DCI_BUS2SC(parm->udev->bus); 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 2238 ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC */ ; 2239 2240 } else if (parm->methods == &uss820dci_device_bulk_methods) { 2241 2242 ntd = xfer->nframes + 1 /* SYNC */ ; 2243 2244 } else if (parm->methods == &uss820dci_device_intr_methods) { 2245 2246 ntd = xfer->nframes + 1 /* SYNC */ ; 2247 2248 } else if (parm->methods == &uss820dci_device_isoc_fs_methods) { 2249 2250 ntd = xfer->nframes + 1 /* SYNC */ ; 2251 2252 } else { 2253 2254 ntd = 0; 2255 } 2256 2257 /* 2258 * check if "usbd_transfer_setup_sub" set an error 2259 */ 2260 if (parm->err) { 2261 return; 2262 } 2263 /* 2264 * allocate transfer descriptors 2265 */ 2266 last_obj = NULL; 2267 2268 /* 2269 * get profile stuff 2270 */ 2271 if (ntd) { 2272 2273 ep_no = xfer->endpointno & UE_ADDR; 2274 uss820dci_get_hw_ep_profile(parm->udev, &pf, ep_no); 2275 2276 if (pf == NULL) { 2277 /* should not happen */ 2278 parm->err = USB_ERR_INVAL; 2279 return; 2280 } 2281 } else { 2282 ep_no = 0; 2283 pf = NULL; 2284 } 2285 2286 /* align data */ 2287 parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); 2288 2289 for (n = 0; n != ntd; n++) { 2290 2291 struct uss820dci_td *td; 2292 2293 if (parm->buf) { 2294 2295 td = USB_ADD_BYTES(parm->buf, parm->size[0]); 2296 2297 /* init TD */ 2298 td->io_tag = sc->sc_io_tag; 2299 td->io_hdl = sc->sc_io_hdl; 2300 td->max_packet_size = xfer->max_packet_size; 2301 td->ep_index = ep_no; 2302 if (pf->support_multi_buffer && 2303 (parm->methods != &uss820dci_device_ctrl_methods)) { 2304 td->support_multi_buffer = 1; 2305 } 2306 td->obj_next = last_obj; 2307 2308 last_obj = td; 2309 } 2310 parm->size[0] += sizeof(*td); 2311 } 2312 2313 xfer->td_start[0] = last_obj; 2314 } 2315 2316 static void 2317 uss820dci_xfer_unsetup(struct usb_xfer *xfer) 2318 { 2319 return; 2320 } 2321 2322 static void 2323 uss820dci_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc, 2324 struct usb_endpoint *ep) 2325 { 2326 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(udev->bus); 2327 2328 DPRINTFN(2, "endpoint=%p, addr=%d, endpt=%d, mode=%d (%d)\n", 2329 ep, udev->address, 2330 edesc->bEndpointAddress, udev->flags.usb_mode, 2331 sc->sc_rt_addr); 2332 2333 if (udev->device_index != sc->sc_rt_addr) { 2334 2335 if (udev->speed != USB_SPEED_FULL) { 2336 /* not supported */ 2337 return; 2338 } 2339 switch (edesc->bmAttributes & UE_XFERTYPE) { 2340 case UE_CONTROL: 2341 ep->methods = &uss820dci_device_ctrl_methods; 2342 break; 2343 case UE_INTERRUPT: 2344 ep->methods = &uss820dci_device_intr_methods; 2345 break; 2346 case UE_ISOCHRONOUS: 2347 ep->methods = &uss820dci_device_isoc_fs_methods; 2348 break; 2349 case UE_BULK: 2350 ep->methods = &uss820dci_device_bulk_methods; 2351 break; 2352 default: 2353 /* do nothing */ 2354 break; 2355 } 2356 } 2357 } 2358 2359 static void 2360 uss820dci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) 2361 { 2362 struct uss820dci_softc *sc = USS820_DCI_BUS2SC(bus); 2363 2364 switch (state) { 2365 case USB_HW_POWER_SUSPEND: 2366 uss820dci_suspend(sc); 2367 break; 2368 case USB_HW_POWER_SHUTDOWN: 2369 uss820dci_uninit(sc); 2370 break; 2371 case USB_HW_POWER_RESUME: 2372 uss820dci_resume(sc); 2373 break; 2374 default: 2375 break; 2376 } 2377 } 2378 2379 static const struct usb_bus_methods uss820dci_bus_methods = 2380 { 2381 .endpoint_init = &uss820dci_ep_init, 2382 .xfer_setup = &uss820dci_xfer_setup, 2383 .xfer_unsetup = &uss820dci_xfer_unsetup, 2384 .get_hw_ep_profile = &uss820dci_get_hw_ep_profile, 2385 .xfer_stall = &uss820dci_xfer_stall, 2386 .set_stall = &uss820dci_set_stall, 2387 .clear_stall = &uss820dci_clear_stall, 2388 .roothub_exec = &uss820dci_roothub_exec, 2389 .xfer_poll = &uss820dci_do_poll, 2390 .set_hw_power_sleep = uss820dci_set_hw_power_sleep, 2391 }; 2392