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