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