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