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