| Commit | Line | Data |
|---|---|---|
| 12bd3c8b SW |
1 | #include <sys/cdefs.h> |
| 2 | __FBSDID("$FreeBSD$"); | |
| 3 | ||
| 4 | /*- | |
| 5 | * Copyright (c) 2009 Hans Petter Selasky. All rights reserved. | |
| 6 | * | |
| 7 | * Redistribution and use in source and binary forms, with or without | |
| 8 | * modification, are permitted provided that the following conditions | |
| 9 | * are met: | |
| 10 | * 1. Redistributions of source code must retain the above copyright | |
| 11 | * notice, this list of conditions and the following disclaimer. | |
| 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 13 | * notice, this list of conditions and the following disclaimer in the | |
| 14 | * documentation and/or other materials provided with the distribution. | |
| 15 | * | |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
| 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
| 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 26 | * SUCH DAMAGE. | |
| 27 | */ | |
| 28 | ||
| 29 | /* | |
| 30 | * This file contains the driver for the AVR32 series USB Device | |
| 31 | * Controller | |
| 32 | */ | |
| 33 | ||
| 34 | /* | |
| 35 | * NOTE: When the chip detects BUS-reset it will also reset the | |
| 36 | * endpoints, Function-address and more. | |
| 37 | */ | |
| 38 | ||
| 39 | #include <sys/stdint.h> | |
| 40 | #include <sys/stddef.h> | |
| 41 | #include <sys/param.h> | |
| 42 | #include <sys/queue.h> | |
| 43 | #include <sys/types.h> | |
| 44 | #include <sys/systm.h> | |
| 45 | #include <sys/kernel.h> | |
| 46 | #include <sys/bus.h> | |
| 47 | #include <sys/module.h> | |
| 48 | #include <sys/lock.h> | |
| 49 | #include <sys/mutex.h> | |
| 50 | #include <sys/condvar.h> | |
| 51 | #include <sys/sysctl.h> | |
| 52 | #include <sys/sx.h> | |
| 53 | #include <sys/unistd.h> | |
| 54 | #include <sys/callout.h> | |
| 55 | #include <sys/malloc.h> | |
| 56 | #include <sys/priv.h> | |
| 57 | ||
| 58 | #include <dev/usb/usb.h> | |
| 59 | #include <dev/usb/usbdi.h> | |
| 60 | ||
| 61 | #define USB_DEBUG_VAR avr32dci_debug | |
| 62 | ||
| 63 | #include <dev/usb/usb_core.h> | |
| 64 | #include <dev/usb/usb_debug.h> | |
| 65 | #include <dev/usb/usb_busdma.h> | |
| 66 | #include <dev/usb/usb_process.h> | |
| 67 | #include <dev/usb/usb_transfer.h> | |
| 68 | #include <dev/usb/usb_device.h> | |
| 69 | #include <dev/usb/usb_hub.h> | |
| 70 | #include <dev/usb/usb_util.h> | |
| 71 | ||
| 72 | #include <dev/usb/usb_controller.h> | |
| 73 | #include <dev/usb/usb_bus.h> | |
| 74 | #include <dev/usb/controller/avr32dci.h> | |
| 75 | ||
| 76 | #define AVR32_BUS2SC(bus) \ | |
| 77 | ((struct avr32dci_softc *)(((uint8_t *)(bus)) - \ | |
| 78 | ((uint8_t *)&(((struct avr32dci_softc *)0)->sc_bus)))) | |
| 79 | ||
| 80 | #define AVR32_PC2SC(pc) \ | |
| 81 | AVR32_BUS2SC(USB_DMATAG_TO_XROOT((pc)->tag_parent)->bus) | |
| 82 | ||
| 83 | #ifdef USB_DEBUG | |
| 84 | static int avr32dci_debug = 0; | |
| 85 | ||
| 86 | static SYSCTL_NODE(_hw_usb, OID_AUTO, avr32dci, CTLFLAG_RW, 0, "USB AVR32 DCI"); | |
| 87 | SYSCTL_INT(_hw_usb_avr32dci, OID_AUTO, debug, CTLFLAG_RW, | |
| 88 | &avr32dci_debug, 0, "AVR32 DCI debug level"); | |
| 89 | #endif | |
| 90 | ||
| 91 | #define AVR32_INTR_ENDPT 1 | |
| 92 | ||
| 93 | /* prototypes */ | |
| 94 | ||
| 95 | struct usb_bus_methods avr32dci_bus_methods; | |
| 96 | struct usb_pipe_methods avr32dci_device_non_isoc_methods; | |
| 97 | struct usb_pipe_methods avr32dci_device_isoc_fs_methods; | |
| 98 | ||
| 99 | static avr32dci_cmd_t avr32dci_setup_rx; | |
| 100 | static avr32dci_cmd_t avr32dci_data_rx; | |
| 101 | static avr32dci_cmd_t avr32dci_data_tx; | |
| 102 | static avr32dci_cmd_t avr32dci_data_tx_sync; | |
| 103 | static void avr32dci_device_done(struct usb_xfer *, usb_error_t); | |
| 104 | static void avr32dci_do_poll(struct usb_bus *); | |
| 105 | static void avr32dci_standard_done(struct usb_xfer *); | |
| 106 | static void avr32dci_root_intr(struct avr32dci_softc *sc); | |
| 107 | ||
| 108 | /* | |
| 109 | * Here is a list of what the chip supports: | |
| 110 | */ | |
| 111 | static const struct usb_hw_ep_profile | |
| 112 | avr32dci_ep_profile[4] = { | |
| 113 | ||
| 114 | [0] = { | |
| 115 | .max_in_frame_size = 64, | |
| 116 | .max_out_frame_size = 64, | |
| 117 | .is_simplex = 1, | |
| 118 | .support_control = 1, | |
| 119 | }, | |
| 120 | ||
| 121 | [1] = { | |
| 122 | .max_in_frame_size = 512, | |
| 123 | .max_out_frame_size = 512, | |
| 124 | .is_simplex = 1, | |
| 125 | .support_bulk = 1, | |
| 126 | .support_interrupt = 1, | |
| 127 | .support_isochronous = 1, | |
| 128 | .support_in = 1, | |
| 129 | .support_out = 1, | |
| 130 | }, | |
| 131 | ||
| 132 | [2] = { | |
| 133 | .max_in_frame_size = 64, | |
| 134 | .max_out_frame_size = 64, | |
| 135 | .is_simplex = 1, | |
| 136 | .support_bulk = 1, | |
| 137 | .support_interrupt = 1, | |
| 138 | .support_in = 1, | |
| 139 | .support_out = 1, | |
| 140 | }, | |
| 141 | ||
| 142 | [3] = { | |
| 143 | .max_in_frame_size = 1024, | |
| 144 | .max_out_frame_size = 1024, | |
| 145 | .is_simplex = 1, | |
| 146 | .support_bulk = 1, | |
| 147 | .support_interrupt = 1, | |
| 148 | .support_isochronous = 1, | |
| 149 | .support_in = 1, | |
| 150 | .support_out = 1, | |
| 151 | }, | |
| 152 | }; | |
| 153 | ||
| 154 | static void | |
| 155 | avr32dci_get_hw_ep_profile(struct usb_device *udev, | |
| 156 | const struct usb_hw_ep_profile **ppf, uint8_t ep_addr) | |
| 157 | { | |
| 158 | if (ep_addr == 0) | |
| 159 | *ppf = avr32dci_ep_profile; | |
| 160 | else if (ep_addr < 3) | |
| 161 | *ppf = avr32dci_ep_profile + 1; | |
| 162 | else if (ep_addr < 5) | |
| 163 | *ppf = avr32dci_ep_profile + 2; | |
| 164 | else if (ep_addr < 7) | |
| 165 | *ppf = avr32dci_ep_profile + 3; | |
| 166 | else | |
| 167 | *ppf = NULL; | |
| 168 | } | |
| 169 | ||
| 170 | static void | |
| 171 | avr32dci_mod_ctrl(struct avr32dci_softc *sc, uint32_t set, uint32_t clear) | |
| 172 | { | |
| 173 | uint32_t temp; | |
| 174 | ||
| 175 | temp = AVR32_READ_4(sc, AVR32_CTRL); | |
| 176 | temp |= set; | |
| 177 | temp &= ~clear; | |
| 178 | AVR32_WRITE_4(sc, AVR32_CTRL, temp); | |
| 179 | } | |
| 180 | ||
| 181 | static void | |
| 182 | avr32dci_mod_ien(struct avr32dci_softc *sc, uint32_t set, uint32_t clear) | |
| 183 | { | |
| 184 | uint32_t temp; | |
| 185 | ||
| 186 | temp = AVR32_READ_4(sc, AVR32_IEN); | |
| 187 | temp |= set; | |
| 188 | temp &= ~clear; | |
| 189 | AVR32_WRITE_4(sc, AVR32_IEN, temp); | |
| 190 | } | |
| 191 | ||
| 192 | static void | |
| 193 | avr32dci_clocks_on(struct avr32dci_softc *sc) | |
| 194 | { | |
| 195 | if (sc->sc_flags.clocks_off && | |
| 196 | sc->sc_flags.port_powered) { | |
| 197 | ||
| 198 | DPRINTFN(5, "\n"); | |
| 199 | ||
| 200 | /* turn on clocks */ | |
| 201 | (sc->sc_clocks_on) (&sc->sc_bus); | |
| 202 | ||
| 203 | avr32dci_mod_ctrl(sc, AVR32_CTRL_DEV_EN_USBA, 0); | |
| 204 | ||
| 205 | sc->sc_flags.clocks_off = 0; | |
| 206 | } | |
| 207 | } | |
| 208 | ||
| 209 | static void | |
| 210 | avr32dci_clocks_off(struct avr32dci_softc *sc) | |
| 211 | { | |
| 212 | if (!sc->sc_flags.clocks_off) { | |
| 213 | ||
| 214 | DPRINTFN(5, "\n"); | |
| 215 | ||
| 216 | avr32dci_mod_ctrl(sc, 0, AVR32_CTRL_DEV_EN_USBA); | |
| 217 | ||
| 218 | /* turn clocks off */ | |
| 219 | (sc->sc_clocks_off) (&sc->sc_bus); | |
| 220 | ||
| 221 | sc->sc_flags.clocks_off = 1; | |
| 222 | } | |
| 223 | } | |
| 224 | ||
| 225 | static void | |
| 226 | avr32dci_pull_up(struct avr32dci_softc *sc) | |
| 227 | { | |
| 228 | /* pullup D+, if possible */ | |
| 229 | ||
| 230 | if (!sc->sc_flags.d_pulled_up && | |
| 231 | sc->sc_flags.port_powered) { | |
| 232 | sc->sc_flags.d_pulled_up = 1; | |
| 233 | avr32dci_mod_ctrl(sc, 0, AVR32_CTRL_DEV_DETACH); | |
| 234 | } | |
| 235 | } | |
| 236 | ||
| 237 | static void | |
| 238 | avr32dci_pull_down(struct avr32dci_softc *sc) | |
| 239 | { | |
| 240 | /* pulldown D+, if possible */ | |
| 241 | ||
| 242 | if (sc->sc_flags.d_pulled_up) { | |
| 243 | sc->sc_flags.d_pulled_up = 0; | |
| 244 | avr32dci_mod_ctrl(sc, AVR32_CTRL_DEV_DETACH, 0); | |
| 245 | } | |
| 246 | } | |
| 247 | ||
| 248 | static void | |
| 249 | avr32dci_wakeup_peer(struct avr32dci_softc *sc) | |
| 250 | { | |
| 251 | if (!sc->sc_flags.status_suspend) { | |
| 252 | return; | |
| 253 | } | |
| 254 | avr32dci_mod_ctrl(sc, AVR32_CTRL_DEV_REWAKEUP, 0); | |
| 255 | ||
| 256 | /* wait 8 milliseconds */ | |
| 257 | /* Wait for reset to complete. */ | |
| 258 | usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 125); | |
| 259 | ||
| 260 | /* hardware should have cleared RMWKUP bit */ | |
| 261 | } | |
| 262 | ||
| 263 | static void | |
| 264 | avr32dci_set_address(struct avr32dci_softc *sc, uint8_t addr) | |
| 265 | { | |
| 266 | DPRINTFN(5, "addr=%d\n", addr); | |
| 267 | ||
| 268 | avr32dci_mod_ctrl(sc, AVR32_CTRL_DEV_FADDR_EN | addr, 0); | |
| 269 | } | |
| 270 | ||
| 271 | static uint8_t | |
| 272 | avr32dci_setup_rx(struct avr32dci_td *td) | |
| 273 | { | |
| 274 | struct avr32dci_softc *sc; | |
| 275 | struct usb_device_request req; | |
| 276 | uint16_t count; | |
| 277 | uint32_t temp; | |
| 278 | ||
| 279 | /* get pointer to softc */ | |
| 280 | sc = AVR32_PC2SC(td->pc); | |
| 281 | ||
| 282 | /* check endpoint status */ | |
| 283 | temp = AVR32_READ_4(sc, AVR32_EPTSTA(td->ep_no)); | |
| 284 | ||
| 285 | DPRINTFN(5, "EPTSTA(%u)=0x%08x\n", td->ep_no, temp); | |
| 286 | ||
| 287 | if (!(temp & AVR32_EPTSTA_RX_SETUP)) { | |
| 288 | goto not_complete; | |
| 289 | } | |
| 290 | /* clear did stall */ | |
| 291 | td->did_stall = 0; | |
| 292 | /* get the packet byte count */ | |
| 293 | count = AVR32_EPTSTA_BYTE_COUNT(temp); | |
| 294 | ||
| 295 | /* verify data length */ | |
| 296 | if (count != td->remainder) { | |
| 297 | DPRINTFN(0, "Invalid SETUP packet " | |
| 298 | "length, %d bytes\n", count); | |
| 299 | goto not_complete; | |
| 300 | } | |
| 301 | if (count != sizeof(req)) { | |
| 302 | DPRINTFN(0, "Unsupported SETUP packet " | |
| 303 | "length, %d bytes\n", count); | |
| 304 | goto not_complete; | |
| 305 | } | |
| 306 | /* receive data */ | |
| 307 | memcpy(&req, sc->physdata, sizeof(req)); | |
| 308 | ||
| 309 | /* copy data into real buffer */ | |
| 310 | usbd_copy_in(td->pc, 0, &req, sizeof(req)); | |
| 311 | ||
| 312 | td->offset = sizeof(req); | |
| 313 | td->remainder = 0; | |
| 314 | ||
| 315 | /* sneak peek the set address */ | |
| 316 | if ((req.bmRequestType == UT_WRITE_DEVICE) && | |
| 317 | (req.bRequest == UR_SET_ADDRESS)) { | |
| 318 | sc->sc_dv_addr = req.wValue[0] & 0x7F; | |
| 319 | /* must write address before ZLP */ | |
| 320 | avr32dci_mod_ctrl(sc, 0, AVR32_CTRL_DEV_FADDR_EN | | |
| 321 | AVR32_CTRL_DEV_ADDR); | |
| 322 | avr32dci_mod_ctrl(sc, sc->sc_dv_addr, 0); | |
| 323 | } else { | |
| 324 | sc->sc_dv_addr = 0xFF; | |
| 325 | } | |
| 326 | ||
| 327 | /* clear SETUP packet interrupt */ | |
| 328 | AVR32_WRITE_4(sc, AVR32_EPTCLRSTA(td->ep_no), AVR32_EPTSTA_RX_SETUP); | |
| 329 | return (0); /* complete */ | |
| 330 | ||
| 331 | not_complete: | |
| 332 | if (temp & AVR32_EPTSTA_RX_SETUP) { | |
| 333 | /* clear SETUP packet interrupt */ | |
| 334 | AVR32_WRITE_4(sc, AVR32_EPTCLRSTA(td->ep_no), AVR32_EPTSTA_RX_SETUP); | |
| 335 | } | |
| 336 | /* abort any ongoing transfer */ | |
| 337 | if (!td->did_stall) { | |
| 338 | DPRINTFN(5, "stalling\n"); | |
| 339 | AVR32_WRITE_4(sc, AVR32_EPTSETSTA(td->ep_no), | |
| 340 | AVR32_EPTSTA_FRCESTALL); | |
| 341 | td->did_stall = 1; | |
| 342 | } | |
| 343 | return (1); /* not complete */ | |
| 344 | } | |
| 345 | ||
| 346 | static uint8_t | |
| 347 | avr32dci_data_rx(struct avr32dci_td *td) | |
| 348 | { | |
| 349 | struct avr32dci_softc *sc; | |
| 350 | struct usb_page_search buf_res; | |
| 351 | uint16_t count; | |
| 352 | uint32_t temp; | |
| 353 | uint8_t to; | |
| 354 | uint8_t got_short; | |
| 355 | ||
| 356 | to = 4; /* don't loop forever! */ | |
| 357 | got_short = 0; | |
| 358 | ||
| 359 | /* get pointer to softc */ | |
| 360 | sc = AVR32_PC2SC(td->pc); | |
| 361 | ||
| 362 | repeat: | |
| 363 | /* check if any of the FIFO banks have data */ | |
| 364 | /* check endpoint status */ | |
| 365 | temp = AVR32_READ_4(sc, AVR32_EPTSTA(td->ep_no)); | |
| 366 | ||
| 367 | DPRINTFN(5, "EPTSTA(%u)=0x%08x\n", td->ep_no, temp); | |
| 368 | ||
| 369 | if (temp & AVR32_EPTSTA_RX_SETUP) { | |
| 370 | if (td->remainder == 0) { | |
| 371 | /* | |
| 372 | * We are actually complete and have | |
| 373 | * received the next SETUP | |
| 374 | */ | |
| 375 | DPRINTFN(5, "faking complete\n"); | |
| 376 | return (0); /* complete */ | |
| 377 | } | |
| 378 | /* | |
| 379 | * USB Host Aborted the transfer. | |
| 380 | */ | |
| 381 | td->error = 1; | |
| 382 | return (0); /* complete */ | |
| 383 | } | |
| 384 | /* check status */ | |
| 385 | if (!(temp & AVR32_EPTSTA_RX_BK_RDY)) { | |
| 386 | /* no data */ | |
| 387 | goto not_complete; | |
| 388 | } | |
| 389 | /* get the packet byte count */ | |
| 390 | count = AVR32_EPTSTA_BYTE_COUNT(temp); | |
| 391 | ||
| 392 | /* verify the packet byte count */ | |
| 393 | if (count != td->max_packet_size) { | |
| 394 | if (count < td->max_packet_size) { | |
| 395 | /* we have a short packet */ | |
| 396 | td->short_pkt = 1; | |
| 397 | got_short = 1; | |
| 398 | } else { | |
| 399 | /* invalid USB packet */ | |
| 400 | td->error = 1; | |
| 401 | return (0); /* we are complete */ | |
| 402 | } | |
| 403 | } | |
| 404 | /* verify the packet byte count */ | |
| 405 | if (count > td->remainder) { | |
| 406 | /* invalid USB packet */ | |
| 407 | td->error = 1; | |
| 408 | return (0); /* we are complete */ | |
| 409 | } | |
| 410 | while (count > 0) { | |
| 411 | usbd_get_page(td->pc, td->offset, &buf_res); | |
| 412 | ||
| 413 | /* get correct length */ | |
| 414 | if (buf_res.length > count) { | |
| 415 | buf_res.length = count; | |
| 416 | } | |
| 417 | /* receive data */ | |
| 418 | memcpy(buf_res.buffer, sc->physdata + | |
| 419 | (AVR32_EPTSTA_CURRENT_BANK(temp) << td->bank_shift) + | |
| 420 | (td->ep_no << 16) + (td->offset % td->max_packet_size), buf_res.length); | |
| 421 | /* update counters */ | |
| 422 | count -= buf_res.length; | |
| 423 | td->offset += buf_res.length; | |
| 424 | td->remainder -= buf_res.length; | |
| 425 | } | |
| 426 | ||
| 427 | /* clear OUT packet interrupt */ | |
| 428 | AVR32_WRITE_4(sc, AVR32_EPTCLRSTA(td->ep_no), AVR32_EPTSTA_RX_BK_RDY); | |
| 429 | ||
| 430 | /* check if we are complete */ | |
| 431 | if ((td->remainder == 0) || got_short) { | |
| 432 | if (td->short_pkt) { | |
| 433 | /* we are complete */ | |
| 434 | return (0); | |
| 435 | } | |
| 436 | /* else need to receive a zero length packet */ | |
| 437 | } | |
| 438 | if (--to) { | |
| 439 | goto repeat; | |
| 440 | } | |
| 441 | not_complete: | |
| 442 | return (1); /* not complete */ | |
| 443 | } | |
| 444 | ||
| 445 | static uint8_t | |
| 446 | avr32dci_data_tx(struct avr32dci_td *td) | |
| 447 | { | |
| 448 | struct avr32dci_softc *sc; | |
| 449 | struct usb_page_search buf_res; | |
| 450 | uint16_t count; | |
| 451 | uint8_t to; | |
| 452 | uint32_t temp; | |
| 453 | ||
| 454 | to = 4; /* don't loop forever! */ | |
| 455 | ||
| 456 | /* get pointer to softc */ | |
| 457 | sc = AVR32_PC2SC(td->pc); | |
| 458 | ||
| 459 | repeat: | |
| 460 | ||
| 461 | /* check endpoint status */ | |
| 462 | temp = AVR32_READ_4(sc, AVR32_EPTSTA(td->ep_no)); | |
| 463 | ||
| 464 | DPRINTFN(5, "EPTSTA(%u)=0x%08x\n", td->ep_no, temp); | |
| 465 | ||
| 466 | if (temp & AVR32_EPTSTA_RX_SETUP) { | |
| 467 | /* | |
| 468 | * The current transfer was aborted | |
| 469 | * by the USB Host | |
| 470 | */ | |
| 471 | td->error = 1; | |
| 472 | return (0); /* complete */ | |
| 473 | } | |
| 474 | if (temp & AVR32_EPTSTA_TX_PK_RDY) { | |
| 475 | /* cannot write any data - all banks are busy */ | |
| 476 | goto not_complete; | |
| 477 | } | |
| 478 | count = td->max_packet_size; | |
| 479 | if (td->remainder < count) { | |
| 480 | /* we have a short packet */ | |
| 481 | td->short_pkt = 1; | |
| 482 | count = td->remainder; | |
| 483 | } | |
| 484 | while (count > 0) { | |
| 485 | ||
| 486 | usbd_get_page(td->pc, td->offset, &buf_res); | |
| 487 | ||
| 488 | /* get correct length */ | |
| 489 | if (buf_res.length > count) { | |
| 490 | buf_res.length = count; | |
| 491 | } | |
| 492 | /* transmit data */ | |
| 493 | memcpy(sc->physdata + | |
| 494 | (AVR32_EPTSTA_CURRENT_BANK(temp) << td->bank_shift) + | |
| 495 | (td->ep_no << 16) + (td->offset % td->max_packet_size), | |
| 496 | buf_res.buffer, buf_res.length); | |
| 497 | /* update counters */ | |
| 498 | count -= buf_res.length; | |
| 499 | td->offset += buf_res.length; | |
| 500 | td->remainder -= buf_res.length; | |
| 501 | } | |
| 502 | ||
| 503 | /* allocate FIFO bank */ | |
| 504 | AVR32_WRITE_4(sc, AVR32_EPTCTL(td->ep_no), AVR32_EPTCTL_TX_PK_RDY); | |
| 505 | ||
| 506 | /* check remainder */ | |
| 507 | if (td->remainder == 0) { | |
| 508 | if (td->short_pkt) { | |
| 509 | return (0); /* complete */ | |
| 510 | } | |
| 511 | /* else we need to transmit a short packet */ | |
| 512 | } | |
| 513 | if (--to) { | |
| 514 | goto repeat; | |
| 515 | } | |
| 516 | not_complete: | |
| 517 | return (1); /* not complete */ | |
| 518 | } | |
| 519 | ||
| 520 | static uint8_t | |
| 521 | avr32dci_data_tx_sync(struct avr32dci_td *td) | |
| 522 | { | |
| 523 | struct avr32dci_softc *sc; | |
| 524 | uint32_t temp; | |
| 525 | ||
| 526 | /* get pointer to softc */ | |
| 527 | sc = AVR32_PC2SC(td->pc); | |
| 528 | ||
| 529 | /* check endpoint status */ | |
| 530 | temp = AVR32_READ_4(sc, AVR32_EPTSTA(td->ep_no)); | |
| 531 | ||
| 532 | DPRINTFN(5, "EPTSTA(%u)=0x%08x\n", td->ep_no, temp); | |
| 533 | ||
| 534 | if (temp & AVR32_EPTSTA_RX_SETUP) { | |
| 535 | DPRINTFN(5, "faking complete\n"); | |
| 536 | /* Race condition */ | |
| 537 | return (0); /* complete */ | |
| 538 | } | |
| 539 | /* | |
| 540 | * The control endpoint has only got one bank, so if that bank | |
| 541 | * is free the packet has been transferred! | |
| 542 | */ | |
| 543 | if (AVR32_EPTSTA_BUSY_BANK_STA(temp) != 0) { | |
| 544 | /* cannot write any data - a bank is busy */ | |
| 545 | goto not_complete; | |
| 546 | } | |
| 547 | if (sc->sc_dv_addr != 0xFF) { | |
| 548 | /* set new address */ | |
| 549 | avr32dci_set_address(sc, sc->sc_dv_addr); | |
| 550 | } | |
| 551 | return (0); /* complete */ | |
| 552 | ||
| 553 | not_complete: | |
| 554 | return (1); /* not complete */ | |
| 555 | } | |
| 556 | ||
| 557 | static uint8_t | |
| 558 | avr32dci_xfer_do_fifo(struct usb_xfer *xfer) | |
| 559 | { | |
| 560 | struct avr32dci_td *td; | |
| 561 | ||
| 562 | DPRINTFN(9, "\n"); | |
| 563 | ||
| 564 | td = xfer->td_transfer_cache; | |
| 565 | while (1) { | |
| 566 | if ((td->func) (td)) { | |
| 567 | /* operation in progress */ | |
| 568 | break; | |
| 569 | } | |
| 570 | if (((void *)td) == xfer->td_transfer_last) { | |
| 571 | goto done; | |
| 572 | } | |
| 573 | if (td->error) { | |
| 574 | goto done; | |
| 575 | } else if (td->remainder > 0) { | |
| 576 | /* | |
| 577 | * We had a short transfer. If there is no alternate | |
| 578 | * next, stop processing ! | |
| 579 | */ | |
| 580 | if (!td->alt_next) { | |
| 581 | goto done; | |
| 582 | } | |
| 583 | } | |
| 584 | /* | |
| 585 | * Fetch the next transfer descriptor and transfer | |
| 586 | * some flags to the next transfer descriptor | |
| 587 | */ | |
| 588 | td = td->obj_next; | |
| 589 | xfer->td_transfer_cache = td; | |
| 590 | } | |
| 591 | return (1); /* not complete */ | |
| 592 | ||
| 593 | done: | |
| 594 | /* compute all actual lengths */ | |
| 595 | ||
| 596 | avr32dci_standard_done(xfer); | |
| 597 | return (0); /* complete */ | |
| 598 | } | |
| 599 | ||
| 600 | static void | |
| 601 | avr32dci_interrupt_poll(struct avr32dci_softc *sc) | |
| 602 | { | |
| 603 | struct usb_xfer *xfer; | |
| 604 | ||
| 605 | repeat: | |
| 606 | TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { | |
| 607 | if (!avr32dci_xfer_do_fifo(xfer)) { | |
| 608 | /* queue has been modified */ | |
| 609 | goto repeat; | |
| 610 | } | |
| 611 | } | |
| 612 | } | |
| 613 | ||
| 614 | void | |
| 615 | avr32dci_vbus_interrupt(struct avr32dci_softc *sc, uint8_t is_on) | |
| 616 | { | |
| 617 | DPRINTFN(5, "vbus = %u\n", is_on); | |
| 618 | ||
| 619 | if (is_on) { | |
| 620 | if (!sc->sc_flags.status_vbus) { | |
| 621 | sc->sc_flags.status_vbus = 1; | |
| 622 | ||
| 623 | /* complete root HUB interrupt endpoint */ | |
| 624 | ||
| 625 | avr32dci_root_intr(sc); | |
| 626 | } | |
| 627 | } else { | |
| 628 | if (sc->sc_flags.status_vbus) { | |
| 629 | sc->sc_flags.status_vbus = 0; | |
| 630 | sc->sc_flags.status_bus_reset = 0; | |
| 631 | sc->sc_flags.status_suspend = 0; | |
| 632 | sc->sc_flags.change_suspend = 0; | |
| 633 | sc->sc_flags.change_connect = 1; | |
| 634 | ||
| 635 | /* complete root HUB interrupt endpoint */ | |
| 636 | ||
| 637 | avr32dci_root_intr(sc); | |
| 638 | } | |
| 639 | } | |
| 640 | } | |
| 641 | ||
| 642 | void | |
| 643 | avr32dci_interrupt(struct avr32dci_softc *sc) | |
| 644 | { | |
| 645 | uint32_t status; | |
| 646 | ||
| 647 | USB_BUS_LOCK(&sc->sc_bus); | |
| 648 | ||
| 649 | /* read interrupt status */ | |
| 650 | status = AVR32_READ_4(sc, AVR32_INTSTA); | |
| 651 | ||
| 652 | /* clear all set interrupts */ | |
| 653 | AVR32_WRITE_4(sc, AVR32_CLRINT, status); | |
| 654 | ||
| 655 | DPRINTFN(14, "INTSTA=0x%08x\n", status); | |
| 656 | ||
| 657 | /* check for any bus state change interrupts */ | |
| 658 | if (status & AVR32_INT_ENDRESET) { | |
| 659 | ||
| 660 | DPRINTFN(5, "end of reset\n"); | |
| 661 | ||
| 662 | /* set correct state */ | |
| 663 | sc->sc_flags.status_bus_reset = 1; | |
| 664 | sc->sc_flags.status_suspend = 0; | |
| 665 | sc->sc_flags.change_suspend = 0; | |
| 666 | sc->sc_flags.change_connect = 1; | |
| 667 | ||
| 668 | /* disable resume interrupt */ | |
| 669 | avr32dci_mod_ien(sc, AVR32_INT_DET_SUSPD | | |
| 670 | AVR32_INT_ENDRESET, AVR32_INT_WAKE_UP); | |
| 671 | ||
| 672 | /* complete root HUB interrupt endpoint */ | |
| 673 | avr32dci_root_intr(sc); | |
| 674 | } | |
| 675 | /* | |
| 676 | * If resume and suspend is set at the same time we interpret | |
| 677 | * that like RESUME. Resume is set when there is at least 3 | |
| 678 | * milliseconds of inactivity on the USB BUS. | |
| 679 | */ | |
| 680 | if (status & AVR32_INT_WAKE_UP) { | |
| 681 | ||
| 682 | DPRINTFN(5, "resume interrupt\n"); | |
| 683 | ||
| 684 | if (sc->sc_flags.status_suspend) { | |
| 685 | /* update status bits */ | |
| 686 | sc->sc_flags.status_suspend = 0; | |
| 687 | sc->sc_flags.change_suspend = 1; | |
| 688 | ||
| 689 | /* disable resume interrupt */ | |
| 690 | avr32dci_mod_ien(sc, AVR32_INT_DET_SUSPD | | |
| 691 | AVR32_INT_ENDRESET, AVR32_INT_WAKE_UP); | |
| 692 | ||
| 693 | /* complete root HUB interrupt endpoint */ | |
| 694 | avr32dci_root_intr(sc); | |
| 695 | } | |
| 696 | } else if (status & AVR32_INT_DET_SUSPD) { | |
| 697 | ||
| 698 | DPRINTFN(5, "suspend interrupt\n"); | |
| 699 | ||
| 700 | if (!sc->sc_flags.status_suspend) { | |
| 701 | /* update status bits */ | |
| 702 | sc->sc_flags.status_suspend = 1; | |
| 703 | sc->sc_flags.change_suspend = 1; | |
| 704 | ||
| 705 | /* disable suspend interrupt */ | |
| 706 | avr32dci_mod_ien(sc, AVR32_INT_WAKE_UP | | |
| 707 | AVR32_INT_ENDRESET, AVR32_INT_DET_SUSPD); | |
| 708 | ||
| 709 | /* complete root HUB interrupt endpoint */ | |
| 710 | avr32dci_root_intr(sc); | |
| 711 | } | |
| 712 | } | |
| 713 | /* check for any endpoint interrupts */ | |
| 714 | if (status & -AVR32_INT_EPT_INT(0)) { | |
| 715 | ||
| 716 | DPRINTFN(5, "real endpoint interrupt\n"); | |
| 717 | ||
| 718 | avr32dci_interrupt_poll(sc); | |
| 719 | } | |
| 720 | USB_BUS_UNLOCK(&sc->sc_bus); | |
| 721 | } | |
| 722 | ||
| 723 | static void | |
| 724 | avr32dci_setup_standard_chain_sub(struct avr32dci_std_temp *temp) | |
| 725 | { | |
| 726 | struct avr32dci_td *td; | |
| 727 | ||
| 728 | /* get current Transfer Descriptor */ | |
| 729 | td = temp->td_next; | |
| 730 | temp->td = td; | |
| 731 | ||
| 732 | /* prepare for next TD */ | |
| 733 | temp->td_next = td->obj_next; | |
| 734 | ||
| 735 | /* fill out the Transfer Descriptor */ | |
| 736 | td->func = temp->func; | |
| 737 | td->pc = temp->pc; | |
| 738 | td->offset = temp->offset; | |
| 739 | td->remainder = temp->len; | |
| 740 | td->error = 0; | |
| 741 | td->did_stall = temp->did_stall; | |
| 742 | td->short_pkt = temp->short_pkt; | |
| 743 | td->alt_next = temp->setup_alt_next; | |
| 744 | } | |
| 745 | ||
| 746 | static void | |
| 747 | avr32dci_setup_standard_chain(struct usb_xfer *xfer) | |
| 748 | { | |
| 749 | struct avr32dci_std_temp temp; | |
| 750 | struct avr32dci_softc *sc; | |
| 751 | struct avr32dci_td *td; | |
| 752 | uint32_t x; | |
| 753 | uint8_t ep_no; | |
| 754 | uint8_t need_sync; | |
| 755 | ||
| 756 | DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n", | |
| 757 | xfer->address, UE_GET_ADDR(xfer->endpointno), | |
| 758 | xfer->sumlen, usbd_get_speed(xfer->xroot->udev)); | |
| 759 | ||
| 760 | temp.max_frame_size = xfer->max_frame_size; | |
| 761 | ||
| 762 | td = xfer->td_start[0]; | |
| 763 | xfer->td_transfer_first = td; | |
| 764 | xfer->td_transfer_cache = td; | |
| 765 | ||
| 766 | /* setup temp */ | |
| 767 | ||
| 768 | temp.pc = NULL; | |
| 769 | temp.td = NULL; | |
| 770 | temp.td_next = xfer->td_start[0]; | |
| 771 | temp.offset = 0; | |
| 772 | temp.setup_alt_next = xfer->flags_int.short_frames_ok; | |
| 773 | temp.did_stall = !xfer->flags_int.control_stall; | |
| 774 | ||
| 775 | sc = AVR32_BUS2SC(xfer->xroot->bus); | |
| 776 | ep_no = (xfer->endpointno & UE_ADDR); | |
| 777 | ||
| 778 | /* check if we should prepend a setup message */ | |
| 779 | ||
| 780 | if (xfer->flags_int.control_xfr) { | |
| 781 | if (xfer->flags_int.control_hdr) { | |
| 782 | ||
| 783 | temp.func = &avr32dci_setup_rx; | |
| 784 | temp.len = xfer->frlengths[0]; | |
| 785 | temp.pc = xfer->frbuffers + 0; | |
| 786 | temp.short_pkt = temp.len ? 1 : 0; | |
| 787 | /* check for last frame */ | |
| 788 | if (xfer->nframes == 1) { | |
| 789 | /* no STATUS stage yet, SETUP is last */ | |
| 790 | if (xfer->flags_int.control_act) | |
| 791 | temp.setup_alt_next = 0; | |
| 792 | } | |
| 793 | avr32dci_setup_standard_chain_sub(&temp); | |
| 794 | } | |
| 795 | x = 1; | |
| 796 | } else { | |
| 797 | x = 0; | |
| 798 | } | |
| 799 | ||
| 800 | if (x != xfer->nframes) { | |
| 801 | if (xfer->endpointno & UE_DIR_IN) { | |
| 802 | temp.func = &avr32dci_data_tx; | |
| 803 | need_sync = 1; | |
| 804 | } else { | |
| 805 | temp.func = &avr32dci_data_rx; | |
| 806 | need_sync = 0; | |
| 807 | } | |
| 808 | ||
| 809 | /* setup "pc" pointer */ | |
| 810 | temp.pc = xfer->frbuffers + x; | |
| 811 | } else { | |
| 812 | need_sync = 0; | |
| 813 | } | |
| 814 | while (x != xfer->nframes) { | |
| 815 | ||
| 816 | /* DATA0 / DATA1 message */ | |
| 817 | ||
| 818 | temp.len = xfer->frlengths[x]; | |
| 819 | ||
| 820 | x++; | |
| 821 | ||
| 822 | if (x == xfer->nframes) { | |
| 823 | if (xfer->flags_int.control_xfr) { | |
| 824 | if (xfer->flags_int.control_act) { | |
| 825 | temp.setup_alt_next = 0; | |
| 826 | } | |
| 827 | } else { | |
| 828 | temp.setup_alt_next = 0; | |
| 829 | } | |
| 830 | } | |
| 831 | if (temp.len == 0) { | |
| 832 | ||
| 833 | /* make sure that we send an USB packet */ | |
| 834 | ||
| 835 | temp.short_pkt = 0; | |
| 836 | ||
| 837 | } else { | |
| 838 | ||
| 839 | /* regular data transfer */ | |
| 840 | ||
| 841 | temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1; | |
| 842 | } | |
| 843 | ||
| 844 | avr32dci_setup_standard_chain_sub(&temp); | |
| 845 | ||
| 846 | if (xfer->flags_int.isochronous_xfr) { | |
| 847 | temp.offset += temp.len; | |
| 848 | } else { | |
| 849 | /* get next Page Cache pointer */ | |
| 850 | temp.pc = xfer->frbuffers + x; | |
| 851 | } | |
| 852 | } | |
| 853 | ||
| 854 | if (xfer->flags_int.control_xfr) { | |
| 855 | ||
| 856 | /* always setup a valid "pc" pointer for status and sync */ | |
| 857 | temp.pc = xfer->frbuffers + 0; | |
| 858 | temp.len = 0; | |
| 859 | temp.short_pkt = 0; | |
| 860 | temp.setup_alt_next = 0; | |
| 861 | ||
| 862 | /* check if we need to sync */ | |
| 863 | if (need_sync) { | |
| 864 | /* we need a SYNC point after TX */ | |
| 865 | temp.func = &avr32dci_data_tx_sync; | |
| 866 | avr32dci_setup_standard_chain_sub(&temp); | |
| 867 | } | |
| 868 | /* check if we should append a status stage */ | |
| 869 | if (!xfer->flags_int.control_act) { | |
| 870 | ||
| 871 | /* | |
| 872 | * Send a DATA1 message and invert the current | |
| 873 | * endpoint direction. | |
| 874 | */ | |
| 875 | if (xfer->endpointno & UE_DIR_IN) { | |
| 876 | temp.func = &avr32dci_data_rx; | |
| 877 | need_sync = 0; | |
| 878 | } else { | |
| 879 | temp.func = &avr32dci_data_tx; | |
| 880 | need_sync = 1; | |
| 881 | } | |
| 882 | ||
| 883 | avr32dci_setup_standard_chain_sub(&temp); | |
| 884 | if (need_sync) { | |
| 885 | /* we need a SYNC point after TX */ | |
| 886 | temp.func = &avr32dci_data_tx_sync; | |
| 887 | avr32dci_setup_standard_chain_sub(&temp); | |
| 888 | } | |
| 889 | } | |
| 890 | } | |
| 891 | /* must have at least one frame! */ | |
| 892 | td = temp.td; | |
| 893 | xfer->td_transfer_last = td; | |
| 894 | } | |
| 895 | ||
| 896 | static void | |
| 897 | avr32dci_timeout(void *arg) | |
| 898 | { | |
| 899 | struct usb_xfer *xfer = arg; | |
| 900 | ||
| 901 | DPRINTF("xfer=%p\n", xfer); | |
| 902 | ||
| 903 | USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED); | |
| 904 | ||
| 905 | /* transfer is transferred */ | |
| 906 | avr32dci_device_done(xfer, USB_ERR_TIMEOUT); | |
| 907 | } | |
| 908 | ||
| 909 | static void | |
| 910 | avr32dci_start_standard_chain(struct usb_xfer *xfer) | |
| 911 | { | |
| 912 | DPRINTFN(9, "\n"); | |
| 913 | ||
| 914 | /* poll one time - will turn on interrupts */ | |
| 915 | if (avr32dci_xfer_do_fifo(xfer)) { | |
| 916 | uint8_t ep_no = xfer->endpointno & UE_ADDR; | |
| 917 | struct avr32dci_softc *sc = AVR32_BUS2SC(xfer->xroot->bus); | |
| 918 | ||
| 919 | avr32dci_mod_ien(sc, AVR32_INT_EPT_INT(ep_no), 0); | |
| 920 | ||
| 921 | /* put transfer on interrupt queue */ | |
| 922 | usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer); | |
| 923 | ||
| 924 | /* start timeout, if any */ | |
| 925 | if (xfer->timeout != 0) { | |
| 926 | usbd_transfer_timeout_ms(xfer, | |
| 927 | &avr32dci_timeout, xfer->timeout); | |
| 928 | } | |
| 929 | } | |
| 930 | } | |
| 931 | ||
| 932 | static void | |
| 933 | avr32dci_root_intr(struct avr32dci_softc *sc) | |
| 934 | { | |
| 935 | DPRINTFN(9, "\n"); | |
| 936 | ||
| 937 | USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); | |
| 938 | ||
| 939 | /* set port bit */ | |
| 940 | sc->sc_hub_idata[0] = 0x02; /* we only have one port */ | |
| 941 | ||
| 942 | uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata, | |
| 943 | sizeof(sc->sc_hub_idata)); | |
| 944 | } | |
| 945 | ||
| 946 | static usb_error_t | |
| 947 | avr32dci_standard_done_sub(struct usb_xfer *xfer) | |
| 948 | { | |
| 949 | struct avr32dci_td *td; | |
| 950 | uint32_t len; | |
| 951 | uint8_t error; | |
| 952 | ||
| 953 | DPRINTFN(9, "\n"); | |
| 954 | ||
| 955 | td = xfer->td_transfer_cache; | |
| 956 | ||
| 957 | do { | |
| 958 | len = td->remainder; | |
| 959 | ||
| 960 | if (xfer->aframes != xfer->nframes) { | |
| 961 | /* | |
| 962 | * Verify the length and subtract | |
| 963 | * the remainder from "frlengths[]": | |
| 964 | */ | |
| 965 | if (len > xfer->frlengths[xfer->aframes]) { | |
| 966 | td->error = 1; | |
| 967 | } else { | |
| 968 | xfer->frlengths[xfer->aframes] -= len; | |
| 969 | } | |
| 970 | } | |
| 971 | /* Check for transfer error */ | |
| 972 | if (td->error) { | |
| 973 | /* the transfer is finished */ | |
| 974 | error = 1; | |
| 975 | td = NULL; | |
| 976 | break; | |
| 977 | } | |
| 978 | /* Check for short transfer */ | |
| 979 | if (len > 0) { | |
| 980 | if (xfer->flags_int.short_frames_ok) { | |
| 981 | /* follow alt next */ | |
| 982 | if (td->alt_next) { | |
| 983 | td = td->obj_next; | |
| 984 | } else { | |
| 985 | td = NULL; | |
| 986 | } | |
| 987 | } else { | |
| 988 | /* the transfer is finished */ | |
| 989 | td = NULL; | |
| 990 | } | |
| 991 | error = 0; | |
| 992 | break; | |
| 993 | } | |
| 994 | td = td->obj_next; | |
| 995 | ||
| 996 | /* this USB frame is complete */ | |
| 997 | error = 0; | |
| 998 | break; | |
| 999 | ||
| 1000 | } while (0); | |
| 1001 | ||
| 1002 | /* update transfer cache */ | |
| 1003 | ||
| 1004 | xfer->td_transfer_cache = td; | |
| 1005 | ||
| 1006 | return (error ? | |
| 1007 | USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION); | |
| 1008 | } | |
| 1009 | ||
| 1010 | static void | |
| 1011 | avr32dci_standard_done(struct usb_xfer *xfer) | |
| 1012 | { | |
| 1013 | usb_error_t err = 0; | |
| 1014 | ||
| 1015 | DPRINTFN(13, "xfer=%p pipe=%p transfer done\n", | |
| 1016 | xfer, xfer->endpoint); | |
| 1017 | ||
| 1018 | /* reset scanner */ | |
| 1019 | ||
| 1020 | xfer->td_transfer_cache = xfer->td_transfer_first; | |
| 1021 | ||
| 1022 | if (xfer->flags_int.control_xfr) { | |
| 1023 | ||
| 1024 | if (xfer->flags_int.control_hdr) { | |
| 1025 | ||
| 1026 | err = avr32dci_standard_done_sub(xfer); | |
| 1027 | } | |
| 1028 | xfer->aframes = 1; | |
| 1029 | ||
| 1030 | if (xfer->td_transfer_cache == NULL) { | |
| 1031 | goto done; | |
| 1032 | } | |
| 1033 | } | |
| 1034 | while (xfer->aframes != xfer->nframes) { | |
| 1035 | ||
| 1036 | err = avr32dci_standard_done_sub(xfer); | |
| 1037 | xfer->aframes++; | |
| 1038 | ||
| 1039 | if (xfer->td_transfer_cache == NULL) { | |
| 1040 | goto done; | |
| 1041 | } | |
| 1042 | } | |
| 1043 | ||
| 1044 | if (xfer->flags_int.control_xfr && | |
| 1045 | !xfer->flags_int.control_act) { | |
| 1046 | ||
| 1047 | err = avr32dci_standard_done_sub(xfer); | |
| 1048 | } | |
| 1049 | done: | |
| 1050 | avr32dci_device_done(xfer, err); | |
| 1051 | } | |
| 1052 | ||
| 1053 | /*------------------------------------------------------------------------* | |
| 1054 | * avr32dci_device_done | |
| 1055 | * | |
| 1056 | * NOTE: this function can be called more than one time on the | |
| 1057 | * same USB transfer! | |
| 1058 | *------------------------------------------------------------------------*/ | |
| 1059 | static void | |
| 1060 | avr32dci_device_done(struct usb_xfer *xfer, usb_error_t error) | |
| 1061 | { | |
| 1062 | struct avr32dci_softc *sc = AVR32_BUS2SC(xfer->xroot->bus); | |
| 1063 | uint8_t ep_no; | |
| 1064 | ||
| 1065 | USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); | |
| 1066 | ||
| 1067 | DPRINTFN(9, "xfer=%p, pipe=%p, error=%d\n", | |
| 1068 | xfer, xfer->endpoint, error); | |
| 1069 | ||
| 1070 | if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) { | |
| 1071 | ep_no = (xfer->endpointno & UE_ADDR); | |
| 1072 | ||
| 1073 | /* disable endpoint interrupt */ | |
| 1074 | avr32dci_mod_ien(sc, 0, AVR32_INT_EPT_INT(ep_no)); | |
| 1075 | ||
| 1076 | DPRINTFN(15, "disabled interrupts!\n"); | |
| 1077 | } | |
| 1078 | /* dequeue transfer and start next transfer */ | |
| 1079 | usbd_transfer_done(xfer, error); | |
| 1080 | } | |
| 1081 | ||
| 1082 | static void | |
| 1083 | avr32dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer, | |
| 1084 | struct usb_endpoint *pipe, uint8_t *did_stall) | |
| 1085 | { | |
| 1086 | struct avr32dci_softc *sc; | |
| 1087 | uint8_t ep_no; | |
| 1088 | ||
| 1089 | USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED); | |
| 1090 | ||
| 1091 | DPRINTFN(5, "pipe=%p\n", pipe); | |
| 1092 | ||
| 1093 | if (xfer) { | |
| 1094 | /* cancel any ongoing transfers */ | |
| 1095 | avr32dci_device_done(xfer, USB_ERR_STALLED); | |
| 1096 | } | |
| 1097 | sc = AVR32_BUS2SC(udev->bus); | |
| 1098 | /* get endpoint number */ | |
| 1099 | ep_no = (pipe->edesc->bEndpointAddress & UE_ADDR); | |
| 1100 | /* set stall */ | |
| 1101 | AVR32_WRITE_4(sc, AVR32_EPTSETSTA(ep_no), AVR32_EPTSTA_FRCESTALL); | |
| 1102 | } | |
| 1103 | ||
| 1104 | static void | |
| 1105 | avr32dci_clear_stall_sub(struct avr32dci_softc *sc, uint8_t ep_no, | |
| 1106 | uint8_t ep_type, uint8_t ep_dir) | |
| 1107 | { | |
| 1108 | const struct usb_hw_ep_profile *pf; | |
| 1109 | uint32_t temp; | |
| 1110 | uint32_t epsize; | |
| 1111 | uint8_t n; | |
| 1112 | ||
| 1113 | if (ep_type == UE_CONTROL) { | |
| 1114 | /* clearing stall is not needed */ | |
| 1115 | return; | |
| 1116 | } | |
| 1117 | /* set endpoint reset */ | |
| 1118 | AVR32_WRITE_4(sc, AVR32_EPTRST, AVR32_EPTRST_MASK(ep_no)); | |
| 1119 | ||
| 1120 | /* set stall */ | |
| 1121 | AVR32_WRITE_4(sc, AVR32_EPTSETSTA(ep_no), AVR32_EPTSTA_FRCESTALL); | |
| 1122 | ||
| 1123 | /* reset data toggle */ | |
| 1124 | AVR32_WRITE_4(sc, AVR32_EPTCLRSTA(ep_no), AVR32_EPTSTA_TOGGLESQ); | |
| 1125 | ||
| 1126 | /* clear stall */ | |
| 1127 | AVR32_WRITE_4(sc, AVR32_EPTCLRSTA(ep_no), AVR32_EPTSTA_FRCESTALL); | |
| 1128 | ||
| 1129 | if (ep_type == UE_BULK) { | |
| 1130 | temp = AVR32_EPTCFG_TYPE_BULK; | |
| 1131 | } else if (ep_type == UE_INTERRUPT) { | |
| 1132 | temp = AVR32_EPTCFG_TYPE_INTR; | |
| 1133 | } else { | |
| 1134 | temp = AVR32_EPTCFG_TYPE_ISOC | | |
| 1135 | AVR32_EPTCFG_NB_TRANS(1); | |
| 1136 | } | |
| 1137 | if (ep_dir & UE_DIR_IN) { | |
| 1138 | temp |= AVR32_EPTCFG_EPDIR_IN; | |
| 1139 | } | |
| 1140 | avr32dci_get_hw_ep_profile(NULL, &pf, ep_no); | |
| 1141 | ||
| 1142 | /* compute endpoint size (use maximum) */ | |
| 1143 | epsize = pf->max_in_frame_size | pf->max_out_frame_size; | |
| 1144 | n = 0; | |
| 1145 | while ((epsize /= 2)) | |
| 1146 | n++; | |
| 1147 | temp |= AVR32_EPTCFG_EPSIZE(n); | |
| 1148 | ||
| 1149 | /* use the maximum number of banks supported */ | |
| 1150 | if (ep_no < 1) | |
| 1151 | temp |= AVR32_EPTCFG_NBANK(1); | |
| 1152 | else if (ep_no < 3) | |
| 1153 | temp |= AVR32_EPTCFG_NBANK(2); | |
| 1154 | else | |
| 1155 | temp |= AVR32_EPTCFG_NBANK(3); | |
| 1156 | ||
| 1157 | AVR32_WRITE_4(sc, AVR32_EPTCFG(ep_no), temp); | |
| 1158 | ||
| 1159 | temp = AVR32_READ_4(sc, AVR32_EPTCFG(ep_no)); | |
| 1160 | ||
| 1161 | if (!(temp & AVR32_EPTCFG_EPT_MAPD)) { | |
| 1162 | device_printf(sc->sc_bus.bdev, "Chip rejected configuration\n"); | |
| 1163 | } else { | |
| 1164 | AVR32_WRITE_4(sc, AVR32_EPTCTLENB(ep_no), | |
| 1165 | AVR32_EPTCTL_EPT_ENABL); | |
| 1166 | } | |
| 1167 | } | |
| 1168 | ||
| 1169 | static void | |
| 1170 | avr32dci_clear_stall(struct usb_device *udev, struct usb_endpoint *pipe) | |
| 1171 | { | |
| 1172 | struct avr32dci_softc *sc; | |
| 1173 | struct usb_endpoint_descriptor *ed; | |
| 1174 | ||
| 1175 | DPRINTFN(5, "pipe=%p\n", pipe); | |
| 1176 | ||
| 1177 | USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED); | |
| 1178 | ||
| 1179 | /* check mode */ | |
| 1180 | if (udev->flags.usb_mode != USB_MODE_DEVICE) { | |
| 1181 | /* not supported */ | |
| 1182 | return; | |
| 1183 | } | |
| 1184 | /* get softc */ | |
| 1185 | sc = AVR32_BUS2SC(udev->bus); | |
| 1186 | ||
| 1187 | /* get endpoint descriptor */ | |
| 1188 | ed = pipe->edesc; | |
| 1189 | ||
| 1190 | /* reset endpoint */ | |
| 1191 | avr32dci_clear_stall_sub(sc, | |
| 1192 | (ed->bEndpointAddress & UE_ADDR), | |
| 1193 | (ed->bmAttributes & UE_XFERTYPE), | |
| 1194 | (ed->bEndpointAddress & (UE_DIR_IN | UE_DIR_OUT))); | |
| 1195 | } | |
| 1196 | ||
| 1197 | usb_error_t | |
| 1198 | avr32dci_init(struct avr32dci_softc *sc) | |
| 1199 | { | |
| 1200 | uint8_t n; | |
| 1201 | ||
| 1202 | DPRINTF("start\n"); | |
| 1203 | ||
| 1204 | /* set up the bus structure */ | |
| 1205 | sc->sc_bus.usbrev = USB_REV_1_1; | |
| 1206 | sc->sc_bus.methods = &avr32dci_bus_methods; | |
| 1207 | ||
| 1208 | USB_BUS_LOCK(&sc->sc_bus); | |
| 1209 | ||
| 1210 | /* make sure USB is enabled */ | |
| 1211 | avr32dci_mod_ctrl(sc, AVR32_CTRL_DEV_EN_USBA, 0); | |
| 1212 | ||
| 1213 | /* turn on clocks */ | |
| 1214 | (sc->sc_clocks_on) (&sc->sc_bus); | |
| 1215 | ||
| 1216 | /* make sure device is re-enumerated */ | |
| 1217 | avr32dci_mod_ctrl(sc, AVR32_CTRL_DEV_DETACH, 0); | |
| 1218 | ||
| 1219 | /* wait a little for things to stabilise */ | |
| 1220 | usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 20); | |
| 1221 | ||
| 1222 | /* disable interrupts */ | |
| 1223 | avr32dci_mod_ien(sc, 0, 0xFFFFFFFF); | |
| 1224 | ||
| 1225 | /* enable interrupts */ | |
| 1226 | avr32dci_mod_ien(sc, AVR32_INT_DET_SUSPD | | |
| 1227 | AVR32_INT_ENDRESET, 0); | |
| 1228 | ||
| 1229 | /* reset all endpoints */ | |
| 1230 | AVR32_WRITE_4(sc, AVR32_EPTRST, (1 << AVR32_EP_MAX) - 1); | |
| 1231 | ||
| 1232 | /* disable all endpoints */ | |
| 1233 | for (n = 0; n != AVR32_EP_MAX; n++) { | |
| 1234 | /* disable endpoint */ | |
| 1235 | AVR32_WRITE_4(sc, AVR32_EPTCTLDIS(n), AVR32_EPTCTL_EPT_ENABL); | |
| 1236 | } | |
| 1237 | ||
| 1238 | /* turn off clocks */ | |
| 1239 | ||
| 1240 | avr32dci_clocks_off(sc); | |
| 1241 | ||
| 1242 | USB_BUS_UNLOCK(&sc->sc_bus); | |
| 1243 | ||
| 1244 | /* catch any lost interrupts */ | |
| 1245 | ||
| 1246 | avr32dci_do_poll(&sc->sc_bus); | |
| 1247 | ||
| 1248 | return (0); /* success */ | |
| 1249 | } | |
| 1250 | ||
| 1251 | void | |
| 1252 | avr32dci_uninit(struct avr32dci_softc *sc) | |
| 1253 | { | |
| 1254 | uint8_t n; | |
| 1255 | ||
| 1256 | USB_BUS_LOCK(&sc->sc_bus); | |
| 1257 | ||
| 1258 | /* turn on clocks */ | |
| 1259 | (sc->sc_clocks_on) (&sc->sc_bus); | |
| 1260 | ||
| 1261 | /* disable interrupts */ | |
| 1262 | avr32dci_mod_ien(sc, 0, 0xFFFFFFFF); | |
| 1263 | ||
| 1264 | /* reset all endpoints */ | |
| 1265 | AVR32_WRITE_4(sc, AVR32_EPTRST, (1 << AVR32_EP_MAX) - 1); | |
| 1266 | ||
| 1267 | /* disable all endpoints */ | |
| 1268 | for (n = 0; n != AVR32_EP_MAX; n++) { | |
| 1269 | /* disable endpoint */ | |
| 1270 | AVR32_WRITE_4(sc, AVR32_EPTCTLDIS(n), AVR32_EPTCTL_EPT_ENABL); | |
| 1271 | } | |
| 1272 | ||
| 1273 | sc->sc_flags.port_powered = 0; | |
| 1274 | sc->sc_flags.status_vbus = 0; | |
| 1275 | sc->sc_flags.status_bus_reset = 0; | |
| 1276 | sc->sc_flags.status_suspend = 0; | |
| 1277 | sc->sc_flags.change_suspend = 0; | |
| 1278 | sc->sc_flags.change_connect = 1; | |
| 1279 | ||
| 1280 | avr32dci_pull_down(sc); | |
| 1281 | avr32dci_clocks_off(sc); | |
| 1282 | ||
| 1283 | USB_BUS_UNLOCK(&sc->sc_bus); | |
| 1284 | } | |
| 1285 | ||
| 1286 | static void | |
| 1287 | avr32dci_suspend(struct avr32dci_softc *sc) | |
| 1288 | { | |
| 1289 | /* TODO */ | |
| 1290 | } | |
| 1291 | ||
| 1292 | static void | |
| 1293 | avr32dci_resume(struct avr32dci_softc *sc) | |
| 1294 | { | |
| 1295 | /* TODO */ | |
| 1296 | } | |
| 1297 | ||
| 1298 | static void | |
| 1299 | avr32dci_do_poll(struct usb_bus *bus) | |
| 1300 | { | |
| 1301 | struct avr32dci_softc *sc = AVR32_BUS2SC(bus); | |
| 1302 | ||
| 1303 | USB_BUS_LOCK(&sc->sc_bus); | |
| 1304 | avr32dci_interrupt_poll(sc); | |
| 1305 | USB_BUS_UNLOCK(&sc->sc_bus); | |
| 1306 | } | |
| 1307 | ||
| 1308 | /*------------------------------------------------------------------------* | |
| 1309 | * at91dci bulk support | |
| 1310 | * at91dci control support | |
| 1311 | * at91dci interrupt support | |
| 1312 | *------------------------------------------------------------------------*/ | |
| 1313 | static void | |
| 1314 | avr32dci_device_non_isoc_open(struct usb_xfer *xfer) | |
| 1315 | { | |
| 1316 | return; | |
| 1317 | } | |
| 1318 | ||
| 1319 | static void | |
| 1320 | avr32dci_device_non_isoc_close(struct usb_xfer *xfer) | |
| 1321 | { | |
| 1322 | avr32dci_device_done(xfer, USB_ERR_CANCELLED); | |
| 1323 | } | |
| 1324 | ||
| 1325 | static void | |
| 1326 | avr32dci_device_non_isoc_enter(struct usb_xfer *xfer) | |
| 1327 | { | |
| 1328 | return; | |
| 1329 | } | |
| 1330 | ||
| 1331 | static void | |
| 1332 | avr32dci_device_non_isoc_start(struct usb_xfer *xfer) | |
| 1333 | { | |
| 1334 | /* setup TDs */ | |
| 1335 | avr32dci_setup_standard_chain(xfer); | |
| 1336 | avr32dci_start_standard_chain(xfer); | |
| 1337 | } | |
| 1338 | ||
| 1339 | struct usb_pipe_methods avr32dci_device_non_isoc_methods = | |
| 1340 | { | |
| 1341 | .open = avr32dci_device_non_isoc_open, | |
| 1342 | .close = avr32dci_device_non_isoc_close, | |
| 1343 | .enter = avr32dci_device_non_isoc_enter, | |
| 1344 | .start = avr32dci_device_non_isoc_start, | |
| 1345 | }; | |
| 1346 | ||
| 1347 | /*------------------------------------------------------------------------* | |
| 1348 | * at91dci full speed isochronous support | |
| 1349 | *------------------------------------------------------------------------*/ | |
| 1350 | static void | |
| 1351 | avr32dci_device_isoc_fs_open(struct usb_xfer *xfer) | |
| 1352 | { | |
| 1353 | return; | |
| 1354 | } | |
| 1355 | ||
| 1356 | static void | |
| 1357 | avr32dci_device_isoc_fs_close(struct usb_xfer *xfer) | |
| 1358 | { | |
| 1359 | avr32dci_device_done(xfer, USB_ERR_CANCELLED); | |
| 1360 | } | |
| 1361 | ||
| 1362 | static void | |
| 1363 | avr32dci_device_isoc_fs_enter(struct usb_xfer *xfer) | |
| 1364 | { | |
| 1365 | struct avr32dci_softc *sc = AVR32_BUS2SC(xfer->xroot->bus); | |
| 1366 | uint32_t temp; | |
| 1367 | uint32_t nframes; | |
| 1368 | uint8_t ep_no; | |
| 1369 | ||
| 1370 | DPRINTFN(6, "xfer=%p next=%d nframes=%d\n", | |
| 1371 | xfer, xfer->endpoint->isoc_next, xfer->nframes); | |
| 1372 | ||
| 1373 | /* get the current frame index */ | |
| 1374 | ep_no = xfer->endpointno & UE_ADDR; | |
| 1375 | nframes = (AVR32_READ_4(sc, AVR32_FNUM) / 8); | |
| 1376 | ||
| 1377 | nframes &= AVR32_FRAME_MASK; | |
| 1378 | ||
| 1379 | /* | |
| 1380 | * check if the frame index is within the window where the frames | |
| 1381 | * will be inserted | |
| 1382 | */ | |
| 1383 | temp = (nframes - xfer->endpoint->isoc_next) & AVR32_FRAME_MASK; | |
| 1384 | ||
| 1385 | if ((xfer->endpoint->is_synced == 0) || | |
| 1386 | (temp < xfer->nframes)) { | |
| 1387 | /* | |
| 1388 | * If there is data underflow or the pipe queue is | |
| 1389 | * empty we schedule the transfer a few frames ahead | |
| 1390 | * of the current frame position. Else two isochronous | |
| 1391 | * transfers might overlap. | |
| 1392 | */ | |
| 1393 | xfer->endpoint->isoc_next = (nframes + 3) & AVR32_FRAME_MASK; | |
| 1394 | xfer->endpoint->is_synced = 1; | |
| 1395 | DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); | |
| 1396 | } | |
| 1397 | /* | |
| 1398 | * compute how many milliseconds the insertion is ahead of the | |
| 1399 | * current frame position: | |
| 1400 | */ | |
| 1401 | temp = (xfer->endpoint->isoc_next - nframes) & AVR32_FRAME_MASK; | |
| 1402 | ||
| 1403 | /* | |
| 1404 | * pre-compute when the isochronous transfer will be finished: | |
| 1405 | */ | |
| 1406 | xfer->isoc_time_complete = | |
| 1407 | usb_isoc_time_expand(&sc->sc_bus, nframes) + temp + | |
| 1408 | xfer->nframes; | |
| 1409 | ||
| 1410 | /* compute frame number for next insertion */ | |
| 1411 | xfer->endpoint->isoc_next += xfer->nframes; | |
| 1412 | ||
| 1413 | /* setup TDs */ | |
| 1414 | avr32dci_setup_standard_chain(xfer); | |
| 1415 | } | |
| 1416 | ||
| 1417 | static void | |
| 1418 | avr32dci_device_isoc_fs_start(struct usb_xfer *xfer) | |
| 1419 | { | |
| 1420 | /* start TD chain */ | |
| 1421 | avr32dci_start_standard_chain(xfer); | |
| 1422 | } | |
| 1423 | ||
| 1424 | struct usb_pipe_methods avr32dci_device_isoc_fs_methods = | |
| 1425 | { | |
| 1426 | .open = avr32dci_device_isoc_fs_open, | |
| 1427 | .close = avr32dci_device_isoc_fs_close, | |
| 1428 | .enter = avr32dci_device_isoc_fs_enter, | |
| 1429 | .start = avr32dci_device_isoc_fs_start, | |
| 1430 | }; | |
| 1431 | ||
| 1432 | /*------------------------------------------------------------------------* | |
| 1433 | * at91dci root control support | |
| 1434 | *------------------------------------------------------------------------* | |
| 1435 | * Simulate a hardware HUB by handling all the necessary requests. | |
| 1436 | *------------------------------------------------------------------------*/ | |
| 1437 | ||
| 1438 | static const struct usb_device_descriptor avr32dci_devd = { | |
| 1439 | .bLength = sizeof(struct usb_device_descriptor), | |
| 1440 | .bDescriptorType = UDESC_DEVICE, | |
| 1441 | .bcdUSB = {0x00, 0x02}, | |
| 1442 | .bDeviceClass = UDCLASS_HUB, | |
| 1443 | .bDeviceSubClass = UDSUBCLASS_HUB, | |
| 1444 | .bDeviceProtocol = UDPROTO_HSHUBSTT, | |
| 1445 | .bMaxPacketSize = 64, | |
| 1446 | .bcdDevice = {0x00, 0x01}, | |
| 1447 | .iManufacturer = 1, | |
| 1448 | .iProduct = 2, | |
| 1449 | .bNumConfigurations = 1, | |
| 1450 | }; | |
| 1451 | ||
| 1452 | static const struct usb_device_qualifier avr32dci_odevd = { | |
| 1453 | .bLength = sizeof(struct usb_device_qualifier), | |
| 1454 | .bDescriptorType = UDESC_DEVICE_QUALIFIER, | |
| 1455 | .bcdUSB = {0x00, 0x02}, | |
| 1456 | .bDeviceClass = UDCLASS_HUB, | |
| 1457 | .bDeviceSubClass = UDSUBCLASS_HUB, | |
| 1458 | .bDeviceProtocol = UDPROTO_FSHUB, | |
| 1459 | .bMaxPacketSize0 = 0, | |
| 1460 | .bNumConfigurations = 0, | |
| 1461 | }; | |
| 1462 | ||
| 1463 | static const struct avr32dci_config_desc avr32dci_confd = { | |
| 1464 | .confd = { | |
| 1465 | .bLength = sizeof(struct usb_config_descriptor), | |
| 1466 | .bDescriptorType = UDESC_CONFIG, | |
| 1467 | .wTotalLength[0] = sizeof(avr32dci_confd), | |
| 1468 | .bNumInterface = 1, | |
| 1469 | .bConfigurationValue = 1, | |
| 1470 | .iConfiguration = 0, | |
| 1471 | .bmAttributes = UC_SELF_POWERED, | |
| 1472 | .bMaxPower = 0, | |
| 1473 | }, | |
| 1474 | .ifcd = { | |
| 1475 | .bLength = sizeof(struct usb_interface_descriptor), | |
| 1476 | .bDescriptorType = UDESC_INTERFACE, | |
| 1477 | .bNumEndpoints = 1, | |
| 1478 | .bInterfaceClass = UICLASS_HUB, | |
| 1479 | .bInterfaceSubClass = UISUBCLASS_HUB, | |
| 1480 | .bInterfaceProtocol = 0, | |
| 1481 | }, | |
| 1482 | .endpd = { | |
| 1483 | .bLength = sizeof(struct usb_endpoint_descriptor), | |
| 1484 | .bDescriptorType = UDESC_ENDPOINT, | |
| 1485 | .bEndpointAddress = (UE_DIR_IN | AVR32_INTR_ENDPT), | |
| 1486 | .bmAttributes = UE_INTERRUPT, | |
| 1487 | .wMaxPacketSize[0] = 8, | |
| 1488 | .bInterval = 255, | |
| 1489 | }, | |
| 1490 | }; | |
| 1491 | ||
| 1492 | static const struct usb_hub_descriptor_min avr32dci_hubd = { | |
| 1493 | .bDescLength = sizeof(avr32dci_hubd), | |
| 1494 | .bDescriptorType = UDESC_HUB, | |
| 1495 | .bNbrPorts = 1, | |
| 1496 | .wHubCharacteristics[0] = | |
| 1497 | (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) & 0xFF, | |
| 1498 | .wHubCharacteristics[1] = | |
| 1499 | (UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) >> 8, | |
| 1500 | .bPwrOn2PwrGood = 50, | |
| 1501 | .bHubContrCurrent = 0, | |
| 1502 | .DeviceRemovable = {0}, /* port is removable */ | |
| 1503 | }; | |
| 1504 | ||
| 1505 | #define STRING_LANG \ | |
| 1506 | 0x09, 0x04, /* American English */ | |
| 1507 | ||
| 1508 | #define STRING_VENDOR \ | |
| 1509 | 'A', 0, 'V', 0, 'R', 0, '3', 0, '2', 0 | |
| 1510 | ||
| 1511 | #define STRING_PRODUCT \ | |
| 1512 | 'D', 0, 'C', 0, 'I', 0, ' ', 0, 'R', 0, \ | |
| 1513 | 'o', 0, 'o', 0, 't', 0, ' ', 0, 'H', 0, \ | |
| 1514 | 'U', 0, 'B', 0, | |
| 1515 | ||
| 1516 | USB_MAKE_STRING_DESC(STRING_LANG, avr32dci_langtab); | |
| 1517 | USB_MAKE_STRING_DESC(STRING_VENDOR, avr32dci_vendor); | |
| 1518 | USB_MAKE_STRING_DESC(STRING_PRODUCT, avr32dci_product); | |
| 1519 | ||
| 1520 | static usb_error_t | |
| 1521 | avr32dci_roothub_exec(struct usb_device *udev, | |
| 1522 | struct usb_device_request *req, const void **pptr, uint16_t *plength) | |
| 1523 | { | |
| 1524 | struct avr32dci_softc *sc = AVR32_BUS2SC(udev->bus); | |
| 1525 | const void *ptr; | |
| 1526 | uint16_t len; | |
| 1527 | uint16_t value; | |
| 1528 | uint16_t index; | |
| 1529 | uint32_t temp; | |
| 1530 | usb_error_t err; | |
| 1531 | ||
| 1532 | USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED); | |
| 1533 | ||
| 1534 | /* buffer reset */ | |
| 1535 | ptr = (const void *)&sc->sc_hub_temp; | |
| 1536 | len = 0; | |
| 1537 | err = 0; | |
| 1538 | ||
| 1539 | value = UGETW(req->wValue); | |
| 1540 | index = UGETW(req->wIndex); | |
| 1541 | ||
| 1542 | /* demultiplex the control request */ | |
| 1543 | ||
| 1544 | switch (req->bmRequestType) { | |
| 1545 | case UT_READ_DEVICE: | |
| 1546 | switch (req->bRequest) { | |
| 1547 | case UR_GET_DESCRIPTOR: | |
| 1548 | goto tr_handle_get_descriptor; | |
| 1549 | case UR_GET_CONFIG: | |
| 1550 | goto tr_handle_get_config; | |
| 1551 | case UR_GET_STATUS: | |
| 1552 | goto tr_handle_get_status; | |
| 1553 | default: | |
| 1554 | goto tr_stalled; | |
| 1555 | } | |
| 1556 | break; | |
| 1557 | ||
| 1558 | case UT_WRITE_DEVICE: | |
| 1559 | switch (req->bRequest) { | |
| 1560 | case UR_SET_ADDRESS: | |
| 1561 | goto tr_handle_set_address; | |
| 1562 | case UR_SET_CONFIG: | |
| 1563 | goto tr_handle_set_config; | |
| 1564 | case UR_CLEAR_FEATURE: | |
| 1565 | goto tr_valid; /* nop */ | |
| 1566 | case UR_SET_DESCRIPTOR: | |
| 1567 | goto tr_valid; /* nop */ | |
| 1568 | case UR_SET_FEATURE: | |
| 1569 | default: | |
| 1570 | goto tr_stalled; | |
| 1571 | } | |
| 1572 | break; | |
| 1573 | ||
| 1574 | case UT_WRITE_ENDPOINT: | |
| 1575 | switch (req->bRequest) { | |
| 1576 | case UR_CLEAR_FEATURE: | |
| 1577 | switch (UGETW(req->wValue)) { | |
| 1578 | case UF_ENDPOINT_HALT: | |
| 1579 | goto tr_handle_clear_halt; | |
| 1580 | case UF_DEVICE_REMOTE_WAKEUP: | |
| 1581 | goto tr_handle_clear_wakeup; | |
| 1582 | default: | |
| 1583 | goto tr_stalled; | |
| 1584 | } | |
| 1585 | break; | |
| 1586 | case UR_SET_FEATURE: | |
| 1587 | switch (UGETW(req->wValue)) { | |
| 1588 | case UF_ENDPOINT_HALT: | |
| 1589 | goto tr_handle_set_halt; | |
| 1590 | case UF_DEVICE_REMOTE_WAKEUP: | |
| 1591 | goto tr_handle_set_wakeup; | |
| 1592 | default: | |
| 1593 | goto tr_stalled; | |
| 1594 | } | |
| 1595 | break; | |
| 1596 | case UR_SYNCH_FRAME: | |
| 1597 | goto tr_valid; /* nop */ | |
| 1598 | default: | |
| 1599 | goto tr_stalled; | |
| 1600 | } | |
| 1601 | break; | |
| 1602 | ||
| 1603 | case UT_READ_ENDPOINT: | |
| 1604 | switch (req->bRequest) { | |
| 1605 | case UR_GET_STATUS: | |
| 1606 | goto tr_handle_get_ep_status; | |
| 1607 | default: | |
| 1608 | goto tr_stalled; | |
| 1609 | } | |
| 1610 | break; | |
| 1611 | ||
| 1612 | case UT_WRITE_INTERFACE: | |
| 1613 | switch (req->bRequest) { | |
| 1614 | case UR_SET_INTERFACE: | |
| 1615 | goto tr_handle_set_interface; | |
| 1616 | case UR_CLEAR_FEATURE: | |
| 1617 | goto tr_valid; /* nop */ | |
| 1618 | case UR_SET_FEATURE: | |
| 1619 | default: | |
| 1620 | goto tr_stalled; | |
| 1621 | } | |
| 1622 | break; | |
| 1623 | ||
| 1624 | case UT_READ_INTERFACE: | |
| 1625 | switch (req->bRequest) { | |
| 1626 | case UR_GET_INTERFACE: | |
| 1627 | goto tr_handle_get_interface; | |
| 1628 | case UR_GET_STATUS: | |
| 1629 | goto tr_handle_get_iface_status; | |
| 1630 | default: | |
| 1631 | goto tr_stalled; | |
| 1632 | } | |
| 1633 | break; | |
| 1634 | ||
| 1635 | case UT_WRITE_CLASS_INTERFACE: | |
| 1636 | case UT_WRITE_VENDOR_INTERFACE: | |
| 1637 | /* XXX forward */ | |
| 1638 | break; | |
| 1639 | ||
| 1640 | case UT_READ_CLASS_INTERFACE: | |
| 1641 | case UT_READ_VENDOR_INTERFACE: | |
| 1642 | /* XXX forward */ | |
| 1643 | break; | |
| 1644 | ||
| 1645 | case UT_WRITE_CLASS_DEVICE: | |
| 1646 | switch (req->bRequest) { | |
| 1647 | case UR_CLEAR_FEATURE: | |
| 1648 | goto tr_valid; | |
| 1649 | case UR_SET_DESCRIPTOR: | |
| 1650 | case UR_SET_FEATURE: | |
| 1651 | break; | |
| 1652 | default: | |
| 1653 | goto tr_stalled; | |
| 1654 | } | |
| 1655 | break; | |
| 1656 | ||
| 1657 | case UT_WRITE_CLASS_OTHER: | |
| 1658 | switch (req->bRequest) { | |
| 1659 | case UR_CLEAR_FEATURE: | |
| 1660 | goto tr_handle_clear_port_feature; | |
| 1661 | case UR_SET_FEATURE: | |
| 1662 | goto tr_handle_set_port_feature; | |
| 1663 | case UR_CLEAR_TT_BUFFER: | |
| 1664 | case UR_RESET_TT: | |
| 1665 | case UR_STOP_TT: | |
| 1666 | goto tr_valid; | |
| 1667 | ||
| 1668 | default: | |
| 1669 | goto tr_stalled; | |
| 1670 | } | |
| 1671 | break; | |
| 1672 | ||
| 1673 | case UT_READ_CLASS_OTHER: | |
| 1674 | switch (req->bRequest) { | |
| 1675 | case UR_GET_TT_STATE: | |
| 1676 | goto tr_handle_get_tt_state; | |
| 1677 | case UR_GET_STATUS: | |
| 1678 | goto tr_handle_get_port_status; | |
| 1679 | default: | |
| 1680 | goto tr_stalled; | |
| 1681 | } | |
| 1682 | break; | |
| 1683 | ||
| 1684 | case UT_READ_CLASS_DEVICE: | |
| 1685 | switch (req->bRequest) { | |
| 1686 | case UR_GET_DESCRIPTOR: | |
| 1687 | goto tr_handle_get_class_descriptor; | |
| 1688 | case UR_GET_STATUS: | |
| 1689 | goto tr_handle_get_class_status; | |
| 1690 | ||
| 1691 | default: | |
| 1692 | goto tr_stalled; | |
| 1693 | } | |
| 1694 | break; | |
| 1695 | default: | |
| 1696 | goto tr_stalled; | |
| 1697 | } | |
| 1698 | goto tr_valid; | |
| 1699 | ||
| 1700 | tr_handle_get_descriptor: | |
| 1701 | switch (value >> 8) { | |
| 1702 | case UDESC_DEVICE: | |
| 1703 | if (value & 0xff) { | |
| 1704 | goto tr_stalled; | |
| 1705 | } | |
| 1706 | len = sizeof(avr32dci_devd); | |
| 1707 | ptr = (const void *)&avr32dci_devd; | |
| 1708 | goto tr_valid; | |
| 1709 | case UDESC_CONFIG: | |
| 1710 | if (value & 0xff) { | |
| 1711 | goto tr_stalled; | |
| 1712 | } | |
| 1713 | len = sizeof(avr32dci_confd); | |
| 1714 | ptr = (const void *)&avr32dci_confd; | |
| 1715 | goto tr_valid; | |
| 1716 | case UDESC_STRING: | |
| 1717 | switch (value & 0xff) { | |
| 1718 | case 0: /* Language table */ | |
| 1719 | len = sizeof(avr32dci_langtab); | |
| 1720 | ptr = (const void *)&avr32dci_langtab; | |
| 1721 | goto tr_valid; | |
| 1722 | ||
| 1723 | case 1: /* Vendor */ | |
| 1724 | len = sizeof(avr32dci_vendor); | |
| 1725 | ptr = (const void *)&avr32dci_vendor; | |
| 1726 | goto tr_valid; | |
| 1727 | ||
| 1728 | case 2: /* Product */ | |
| 1729 | len = sizeof(avr32dci_product); | |
| 1730 | ptr = (const void *)&avr32dci_product; | |
| 1731 | goto tr_valid; | |
| 1732 | default: | |
| 1733 | break; | |
| 1734 | } | |
| 1735 | break; | |
| 1736 | default: | |
| 1737 | goto tr_stalled; | |
| 1738 | } | |
| 1739 | goto tr_stalled; | |
| 1740 | ||
| 1741 | tr_handle_get_config: | |
| 1742 | len = 1; | |
| 1743 | sc->sc_hub_temp.wValue[0] = sc->sc_conf; | |
| 1744 | goto tr_valid; | |
| 1745 | ||
| 1746 | tr_handle_get_status: | |
| 1747 | len = 2; | |
| 1748 | USETW(sc->sc_hub_temp.wValue, UDS_SELF_POWERED); | |
| 1749 | goto tr_valid; | |
| 1750 | ||
| 1751 | tr_handle_set_address: | |
| 1752 | if (value & 0xFF00) { | |
| 1753 | goto tr_stalled; | |
| 1754 | } | |
| 1755 | sc->sc_rt_addr = value; | |
| 1756 | goto tr_valid; | |
| 1757 | ||
| 1758 | tr_handle_set_config: | |
| 1759 | if (value >= 2) { | |
| 1760 | goto tr_stalled; | |
| 1761 | } | |
| 1762 | sc->sc_conf = value; | |
| 1763 | goto tr_valid; | |
| 1764 | ||
| 1765 | tr_handle_get_interface: | |
| 1766 | len = 1; | |
| 1767 | sc->sc_hub_temp.wValue[0] = 0; | |
| 1768 | goto tr_valid; | |
| 1769 | ||
| 1770 | tr_handle_get_tt_state: | |
| 1771 | tr_handle_get_class_status: | |
| 1772 | tr_handle_get_iface_status: | |
| 1773 | tr_handle_get_ep_status: | |
| 1774 | len = 2; | |
| 1775 | USETW(sc->sc_hub_temp.wValue, 0); | |
| 1776 | goto tr_valid; | |
| 1777 | ||
| 1778 | tr_handle_set_halt: | |
| 1779 | tr_handle_set_interface: | |
| 1780 | tr_handle_set_wakeup: | |
| 1781 | tr_handle_clear_wakeup: | |
| 1782 | tr_handle_clear_halt: | |
| 1783 | goto tr_valid; | |
| 1784 | ||
| 1785 | tr_handle_clear_port_feature: | |
| 1786 | if (index != 1) { | |
| 1787 | goto tr_stalled; | |
| 1788 | } | |
| 1789 | DPRINTFN(9, "UR_CLEAR_PORT_FEATURE on port %d\n", index); | |
| 1790 | ||
| 1791 | switch (value) { | |
| 1792 | case UHF_PORT_SUSPEND: | |
| 1793 | avr32dci_wakeup_peer(sc); | |
| 1794 | break; | |
| 1795 | ||
| 1796 | case UHF_PORT_ENABLE: | |
| 1797 | sc->sc_flags.port_enabled = 0; | |
| 1798 | break; | |
| 1799 | ||
| 1800 | case UHF_PORT_TEST: | |
| 1801 | case UHF_PORT_INDICATOR: | |
| 1802 | case UHF_C_PORT_ENABLE: | |
| 1803 | case UHF_C_PORT_OVER_CURRENT: | |
| 1804 | case UHF_C_PORT_RESET: | |
| 1805 | /* nops */ | |
| 1806 | break; | |
| 1807 | case UHF_PORT_POWER: | |
| 1808 | sc->sc_flags.port_powered = 0; | |
| 1809 | avr32dci_pull_down(sc); | |
| 1810 | avr32dci_clocks_off(sc); | |
| 1811 | break; | |
| 1812 | case UHF_C_PORT_CONNECTION: | |
| 1813 | /* clear connect change flag */ | |
| 1814 | sc->sc_flags.change_connect = 0; | |
| 1815 | ||
| 1816 | if (!sc->sc_flags.status_bus_reset) { | |
| 1817 | /* we are not connected */ | |
| 1818 | break; | |
| 1819 | } | |
| 1820 | /* configure the control endpoint */ | |
| 1821 | /* set endpoint reset */ | |
| 1822 | AVR32_WRITE_4(sc, AVR32_EPTRST, AVR32_EPTRST_MASK(0)); | |
| 1823 | ||
| 1824 | /* set stall */ | |
| 1825 | AVR32_WRITE_4(sc, AVR32_EPTSETSTA(0), AVR32_EPTSTA_FRCESTALL); | |
| 1826 | ||
| 1827 | /* reset data toggle */ | |
| 1828 | AVR32_WRITE_4(sc, AVR32_EPTCLRSTA(0), AVR32_EPTSTA_TOGGLESQ); | |
| 1829 | ||
| 1830 | /* clear stall */ | |
| 1831 | AVR32_WRITE_4(sc, AVR32_EPTCLRSTA(0), AVR32_EPTSTA_FRCESTALL); | |
| 1832 | ||
| 1833 | /* configure */ | |
| 1834 | AVR32_WRITE_4(sc, AVR32_EPTCFG(0), AVR32_EPTCFG_TYPE_CTRL | | |
| 1835 | AVR32_EPTCFG_NBANK(1) | AVR32_EPTCFG_EPSIZE(6)); | |
| 1836 | ||
| 1837 | temp = AVR32_READ_4(sc, AVR32_EPTCFG(0)); | |
| 1838 | ||
| 1839 | if (!(temp & AVR32_EPTCFG_EPT_MAPD)) { | |
| 1840 | device_printf(sc->sc_bus.bdev, | |
| 1841 | "Chip rejected configuration\n"); | |
| 1842 | } else { | |
| 1843 | AVR32_WRITE_4(sc, AVR32_EPTCTLENB(0), | |
| 1844 | AVR32_EPTCTL_EPT_ENABL); | |
| 1845 | } | |
| 1846 | break; | |
| 1847 | case UHF_C_PORT_SUSPEND: | |
| 1848 | sc->sc_flags.change_suspend = 0; | |
| 1849 | break; | |
| 1850 | default: | |
| 1851 | err = USB_ERR_IOERROR; | |
| 1852 | goto done; | |
| 1853 | } | |
| 1854 | goto tr_valid; | |
| 1855 | ||
| 1856 | tr_handle_set_port_feature: | |
| 1857 | if (index != 1) { | |
| 1858 | goto tr_stalled; | |
| 1859 | } | |
| 1860 | DPRINTFN(9, "UR_SET_PORT_FEATURE\n"); | |
| 1861 | ||
| 1862 | switch (value) { | |
| 1863 | case UHF_PORT_ENABLE: | |
| 1864 | sc->sc_flags.port_enabled = 1; | |
| 1865 | break; | |
| 1866 | case UHF_PORT_SUSPEND: | |
| 1867 | case UHF_PORT_RESET: | |
| 1868 | case UHF_PORT_TEST: | |
| 1869 | case UHF_PORT_INDICATOR: | |
| 1870 | /* nops */ | |
| 1871 | break; | |
| 1872 | case UHF_PORT_POWER: | |
| 1873 | sc->sc_flags.port_powered = 1; | |
| 1874 | break; | |
| 1875 | default: | |
| 1876 | err = USB_ERR_IOERROR; | |
| 1877 | goto done; | |
| 1878 | } | |
| 1879 | goto tr_valid; | |
| 1880 | ||
| 1881 | tr_handle_get_port_status: | |
| 1882 | ||
| 1883 | DPRINTFN(9, "UR_GET_PORT_STATUS\n"); | |
| 1884 | ||
| 1885 | if (index != 1) { | |
| 1886 | goto tr_stalled; | |
| 1887 | } | |
| 1888 | if (sc->sc_flags.status_vbus) { | |
| 1889 | avr32dci_clocks_on(sc); | |
| 1890 | avr32dci_pull_up(sc); | |
| 1891 | } else { | |
| 1892 | avr32dci_pull_down(sc); | |
| 1893 | avr32dci_clocks_off(sc); | |
| 1894 | } | |
| 1895 | ||
| 1896 | /* Select Device Side Mode */ | |
| 1897 | ||
| 1898 | value = UPS_PORT_MODE_DEVICE; | |
| 1899 | ||
| 1900 | /* Check for High Speed */ | |
| 1901 | if (AVR32_READ_4(sc, AVR32_INTSTA) & AVR32_INT_SPEED) | |
| 1902 | value |= UPS_HIGH_SPEED; | |
| 1903 | ||
| 1904 | if (sc->sc_flags.port_powered) { | |
| 1905 | value |= UPS_PORT_POWER; | |
| 1906 | } | |
| 1907 | if (sc->sc_flags.port_enabled) { | |
| 1908 | value |= UPS_PORT_ENABLED; | |
| 1909 | } | |
| 1910 | if (sc->sc_flags.status_vbus && | |
| 1911 | sc->sc_flags.status_bus_reset) { | |
| 1912 | value |= UPS_CURRENT_CONNECT_STATUS; | |
| 1913 | } | |
| 1914 | if (sc->sc_flags.status_suspend) { | |
| 1915 | value |= UPS_SUSPEND; | |
| 1916 | } | |
| 1917 | USETW(sc->sc_hub_temp.ps.wPortStatus, value); | |
| 1918 | ||
| 1919 | value = 0; | |
| 1920 | ||
| 1921 | if (sc->sc_flags.change_connect) { | |
| 1922 | value |= UPS_C_CONNECT_STATUS; | |
| 1923 | } | |
| 1924 | if (sc->sc_flags.change_suspend) { | |
| 1925 | value |= UPS_C_SUSPEND; | |
| 1926 | } | |
| 1927 | USETW(sc->sc_hub_temp.ps.wPortChange, value); | |
| 1928 | len = sizeof(sc->sc_hub_temp.ps); | |
| 1929 | goto tr_valid; | |
| 1930 | ||
| 1931 | tr_handle_get_class_descriptor: | |
| 1932 | if (value & 0xFF) { | |
| 1933 | goto tr_stalled; | |
| 1934 | } | |
| 1935 | ptr = (const void *)&avr32dci_hubd; | |
| 1936 | len = sizeof(avr32dci_hubd); | |
| 1937 | goto tr_valid; | |
| 1938 | ||
| 1939 | tr_stalled: | |
| 1940 | err = USB_ERR_STALLED; | |
| 1941 | tr_valid: | |
| 1942 | done: | |
| 1943 | *plength = len; | |
| 1944 | *pptr = ptr; | |
| 1945 | return (err); | |
| 1946 | } | |
| 1947 | ||
| 1948 | static void | |
| 1949 | avr32dci_xfer_setup(struct usb_setup_params *parm) | |
| 1950 | { | |
| 1951 | const struct usb_hw_ep_profile *pf; | |
| 1952 | struct avr32dci_softc *sc; | |
| 1953 | struct usb_xfer *xfer; | |
| 1954 | void *last_obj; | |
| 1955 | uint32_t ntd; | |
| 1956 | uint32_t n; | |
| 1957 | uint8_t ep_no; | |
| 1958 | ||
| 1959 | sc = AVR32_BUS2SC(parm->udev->bus); | |
| 1960 | xfer = parm->curr_xfer; | |
| 1961 | ||
| 1962 | /* | |
| 1963 | * NOTE: This driver does not use any of the parameters that | |
| 1964 | * are computed from the following values. Just set some | |
| 1965 | * reasonable dummies: | |
| 1966 | */ | |
| 1967 | parm->hc_max_packet_size = 0x400; | |
| 1968 | parm->hc_max_packet_count = 1; | |
| 1969 | parm->hc_max_frame_size = 0x400; | |
| 1970 | ||
| 1971 | usbd_transfer_setup_sub(parm); | |
| 1972 | ||
| 1973 | /* | |
| 1974 | * compute maximum number of TDs | |
| 1975 | */ | |
| 1976 | if ((xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE) == UE_CONTROL) { | |
| 1977 | ||
| 1978 | ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC 1 */ | |
| 1979 | + 1 /* SYNC 2 */ ; | |
| 1980 | } else { | |
| 1981 | ||
| 1982 | ntd = xfer->nframes + 1 /* SYNC */ ; | |
| 1983 | } | |
| 1984 | ||
| 1985 | /* | |
| 1986 | * check if "usbd_transfer_setup_sub" set an error | |
| 1987 | */ | |
| 1988 | if (parm->err) | |
| 1989 | return; | |
| 1990 | ||
| 1991 | /* | |
| 1992 | * allocate transfer descriptors | |
| 1993 | */ | |
| 1994 | last_obj = NULL; | |
| 1995 | ||
| 1996 | /* | |
| 1997 | * get profile stuff | |
| 1998 | */ | |
| 1999 | ep_no = xfer->endpointno & UE_ADDR; | |
| 2000 | avr32dci_get_hw_ep_profile(parm->udev, &pf, ep_no); | |
| 2001 | ||
| 2002 | if (pf == NULL) { | |
| 2003 | /* should not happen */ | |
| 2004 | parm->err = USB_ERR_INVAL; | |
| 2005 | return; | |
| 2006 | } | |
| 2007 | /* align data */ | |
| 2008 | parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); | |
| 2009 | ||
| 2010 | for (n = 0; n != ntd; n++) { | |
| 2011 | ||
| 2012 | struct avr32dci_td *td; | |
| 2013 | ||
| 2014 | if (parm->buf) { | |
| 2015 | uint32_t temp; | |
| 2016 | ||
| 2017 | td = USB_ADD_BYTES(parm->buf, parm->size[0]); | |
| 2018 | ||
| 2019 | /* init TD */ | |
| 2020 | td->max_packet_size = xfer->max_packet_size; | |
| 2021 | td->ep_no = ep_no; | |
| 2022 | temp = pf->max_in_frame_size | pf->max_out_frame_size; | |
| 2023 | td->bank_shift = 0; | |
| 2024 | while ((temp /= 2)) | |
| 2025 | td->bank_shift++; | |
| 2026 | if (pf->support_multi_buffer) { | |
| 2027 | td->support_multi_buffer = 1; | |
| 2028 | } | |
| 2029 | td->obj_next = last_obj; | |
| 2030 | ||
| 2031 | last_obj = td; | |
| 2032 | } | |
| 2033 | parm->size[0] += sizeof(*td); | |
| 2034 | } | |
| 2035 | ||
| 2036 | xfer->td_start[0] = last_obj; | |
| 2037 | } | |
| 2038 | ||
| 2039 | static void | |
| 2040 | avr32dci_xfer_unsetup(struct usb_xfer *xfer) | |
| 2041 | { | |
| 2042 | return; | |
| 2043 | } | |
| 2044 | ||
| 2045 | static void | |
| 2046 | avr32dci_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc, | |
| 2047 | struct usb_endpoint *pipe) | |
| 2048 | { | |
| 2049 | struct avr32dci_softc *sc = AVR32_BUS2SC(udev->bus); | |
| 2050 | ||
| 2051 | DPRINTFN(2, "pipe=%p, addr=%d, endpt=%d, mode=%d (%d,%d)\n", | |
| 2052 | pipe, udev->address, | |
| 2053 | edesc->bEndpointAddress, udev->flags.usb_mode, | |
| 2054 | sc->sc_rt_addr, udev->device_index); | |
| 2055 | ||
| 2056 | if (udev->device_index != sc->sc_rt_addr) { | |
| 2057 | ||
| 2058 | if (udev->flags.usb_mode != USB_MODE_DEVICE) { | |
| 2059 | /* not supported */ | |
| 2060 | return; | |
| 2061 | } | |
| 2062 | if ((udev->speed != USB_SPEED_FULL) && | |
| 2063 | (udev->speed != USB_SPEED_HIGH)) { | |
| 2064 | /* not supported */ | |
| 2065 | return; | |
| 2066 | } | |
| 2067 | if ((edesc->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS) | |
| 2068 | pipe->methods = &avr32dci_device_isoc_fs_methods; | |
| 2069 | else | |
| 2070 | pipe->methods = &avr32dci_device_non_isoc_methods; | |
| 2071 | } | |
| 2072 | } | |
| 2073 | ||
| 2074 | static void | |
| 2075 | avr32dci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) | |
| 2076 | { | |
| 2077 | struct avr32dci_softc *sc = AVR32_BUS2SC(bus); | |
| 2078 | ||
| 2079 | switch (state) { | |
| 2080 | case USB_HW_POWER_SUSPEND: | |
| 2081 | avr32dci_suspend(sc); | |
| 2082 | break; | |
| 2083 | case USB_HW_POWER_SHUTDOWN: | |
| 2084 | avr32dci_uninit(sc); | |
| 2085 | break; | |
| 2086 | case USB_HW_POWER_RESUME: | |
| 2087 | avr32dci_resume(sc); | |
| 2088 | break; | |
| 2089 | default: | |
| 2090 | break; | |
| 2091 | } | |
| 2092 | } | |
| 2093 | ||
| 2094 | struct usb_bus_methods avr32dci_bus_methods = | |
| 2095 | { | |
| 2096 | .endpoint_init = &avr32dci_ep_init, | |
| 2097 | .xfer_setup = &avr32dci_xfer_setup, | |
| 2098 | .xfer_unsetup = &avr32dci_xfer_unsetup, | |
| 2099 | .get_hw_ep_profile = &avr32dci_get_hw_ep_profile, | |
| 2100 | .set_stall = &avr32dci_set_stall, | |
| 2101 | .clear_stall = &avr32dci_clear_stall, | |
| 2102 | .roothub_exec = &avr32dci_roothub_exec, | |
| 2103 | .xfer_poll = &avr32dci_do_poll, | |
| 2104 | .set_hw_power_sleep = &avr32dci_set_hw_power_sleep, | |
| 2105 | }; |