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