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