Changeset 159100a in mainline
- Timestamp:
- 2011-07-13T22:19:26Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- ef9460b
- Parents:
- 3e5c48c9 (diff), 5d36062 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
HelenOS.config
r3e5c48c9 r159100a 573 573 ! CONFIG_RUN_VIRTUAL_USB_HC (n/y) 574 574 575 % Polling UHCI & OHCI (no interrupts) 576 ! [PLATFORM=ia32|PLATFORM=amd64] CONFIG_USBHC_NO_INTERRUPTS (n/y) 577 575 % OHCI root hub port power switching 576 @ "no" All root hub ports are always powered. 577 @ "ganged" Root hub ports are all powered or all off. 578 @ "per_port" Powered status of every root hub port is independent. 579 ![PLATFORM=ia32|PLATFORM=amd64] OHCI_POWER_SWITCH (choice) -
defaults/amd64/Makefile.config
r3e5c48c9 r159100a 65 65 CONFIG_MOUNT_DATA = n 66 66 67 # OHCI root hub power switch, ganged is enough 68 OHCI_POWER_SWITCH = ganged -
defaults/ia32/Makefile.config
r3e5c48c9 r159100a 71 71 CONFIG_MOUNT_DATA = n 72 72 73 # OHCI root hub power switch, ganged is enough 74 OHCI_POWER_SWITCH = ganged -
uspace/drv/bus/usb/ohci/hc.c
r3e5c48c9 r159100a 46 46 #define OHCI_USED_INTERRUPTS \ 47 47 (I_SO | I_WDH | I_UE | I_RHSC) 48 static int interrupt_emulator(hc_t *instance); 48 49 static const irq_cmd_t ohci_irq_commands[] = 50 { 51 { .cmd = CMD_MEM_READ_32, .dstarg = 1, .addr = NULL /*filled later*/ }, 52 { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = OHCI_USED_INTERRUPTS }, 53 { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 }, 54 { .cmd = CMD_MEM_WRITE_A_32, .srcarg = 1, .addr = NULL /*filled later*/ }, 55 { .cmd = CMD_ACCEPT }, 56 }; 57 49 58 static void hc_gain_control(hc_t *instance); 59 static void hc_start(hc_t *instance); 50 60 static int hc_init_transfer_lists(hc_t *instance); 51 61 static int hc_init_memory(hc_t *instance); 62 static int interrupt_emulator(hc_t *instance); 63 64 /*----------------------------------------------------------------------------*/ 65 /** Get number of commands used in IRQ code. 66 * @return Number of commands. 67 */ 68 size_t hc_irq_cmd_count(void) 69 { 70 return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t); 71 } 72 /*----------------------------------------------------------------------------*/ 73 /** Generate IRQ code commands. 74 * @param[out] cmds Place to store the commands. 75 * @param[in] cmd_size Size of the place (bytes). 76 * @param[in] regs Physical address of device's registers. 77 * @param[in] reg_size Size of the register area (bytes). 78 * 79 * @return Error code. 80 */ 81 int hc_get_irq_commands( 82 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size) 83 { 84 if (cmd_size < sizeof(ohci_irq_commands) 85 || reg_size < sizeof(ohci_regs_t)) 86 return EOVERFLOW; 87 88 /* Create register mapping to use in IRQ handler. 89 * This mapping should be present in kernel only. 90 * Remove it from here when kernel knows how to create mappings 91 * and accepts physical addresses in IRQ code. 92 * TODO: remove */ 93 ohci_regs_t *registers; 94 const int ret = pio_enable((void*)regs, reg_size, (void**)®isters); 95 if (ret != EOK) 96 return ret; 97 98 /* Some bogus access to force create mapping. DO NOT remove, 99 * unless whole virtual addresses in irq is replaced 100 * NOTE: Compiler won't remove this as ohci_regs_t members 101 * are declared volatile. 102 * 103 * Introducing CMD_MEM set of IRQ code commands broke 104 * assumption that IRQ code does not cause page faults. 105 * If this happens during idling (THREAD == NULL) 106 * it causes kernel panic. 107 */ 108 registers->revision; 109 110 memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands)); 111 112 void *address = (void*)®isters->interrupt_status; 113 cmds[0].addr = address; 114 cmds[3].addr = address; 115 return EOK; 116 } 52 117 /*----------------------------------------------------------------------------*/ 53 118 /** Announce OHCI root hub to the DDF … … 83 148 int ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL, 84 149 USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0); 85 CHECK_RET_RELEASE(ret, "Failed(%d) to add OHCI rh endpoint 0.\n", ret); 150 CHECK_RET_RELEASE(ret, 151 "Failed to add OHCI root hub endpoint 0: %s.\n", str_error(ret)); 86 152 87 153 char *match_str = NULL; 88 /* DDF needs heap allocated string */154 /* DDF needs heap allocated string. */ 89 155 ret = asprintf(&match_str, "usb&class=hub"); 90 156 ret = ret > 0 ? 0 : ret; 91 CHECK_RET_RELEASE(ret, "Failed(%d) to create match-id string.\n", ret); 157 CHECK_RET_RELEASE(ret, 158 "Failed to create match-id string: %s.\n", str_error(ret)); 92 159 93 160 ret = ddf_fun_add_match_id(hub_fun, match_str, 100); 94 CHECK_RET_RELEASE(ret, "Failed(%d) add root hub match-id.\n", ret); 161 CHECK_RET_RELEASE(ret, 162 "Failed to add root hub match-id: %s.\n", str_error(ret)); 95 163 96 164 ret = ddf_fun_bind(hub_fun); 97 CHECK_RET_RELEASE(ret, "Failed(%d) to bind root hub function.\n", ret); 165 CHECK_RET_RELEASE(ret, 166 "Failed to bind root hub function: %s.\n", str_error(ret)); 98 167 99 168 return EOK; … … 112 181 { 113 182 assert(instance); 114 int ret = EOK; 183 115 184 #define CHECK_RET_RETURN(ret, message...) \ 116 185 if (ret != EOK) { \ … … 119 188 } else (void)0 120 189 121 ret = pio_enable((void*)regs, reg_size, (void**)&instance->registers); 190 int ret = 191 pio_enable((void*)regs, reg_size, (void**)&instance->registers); 122 192 CHECK_RET_RETURN(ret, 123 "Failed(%d) to gain access to device registers: %s.\n", 124 ret, str_error(ret)); 193 "Failed to gain access to device registers: %s.\n", str_error(ret)); 125 194 126 195 list_initialize(&instance->pending_batches); 127 196 usb_device_keeper_init(&instance->manager); 197 128 198 ret = usb_endpoint_manager_init(&instance->ep_manager, 129 199 BANDWIDTH_AVAILABLE_USB11); … … 137 207 138 208 fibril_mutex_initialize(&instance->guard); 209 139 210 hc_gain_control(instance); 140 141 rh_init(&instance->rh, instance->registers);142 211 143 212 if (!interrupts) { … … 147 216 } 148 217 149 return EOK; 150 } 151 /*----------------------------------------------------------------------------*/ 152 /** Create end register endpoint structures 218 rh_init(&instance->rh, instance->registers); 219 hc_start(instance); 220 221 return EOK; 222 } 223 /*----------------------------------------------------------------------------*/ 224 /** Create and register endpoint structures. 153 225 * 154 226 * @param[in] instance OHCI driver structure. … … 168 240 size_t mps, size_t size, unsigned interval) 169 241 { 170 endpoint_t *ep = malloc(sizeof(endpoint_t)); 242 endpoint_t *ep = 243 endpoint_get(address, endpoint, direction, type, speed, mps); 171 244 if (ep == NULL) 172 245 return ENOMEM; 173 int ret =174 endpoint_init(ep, address, endpoint, direction, type, speed, mps);175 if (ret != EOK) {176 free(ep);177 return ret;178 }179 246 180 247 hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep); … … 184 251 } 185 252 186 ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size); 253 int ret = 254 usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size); 187 255 if (ret != EOK) { 188 256 hcd_endpoint_clear(ep); … … 212 280 &instance->lists[ep->transfer_type], hcd_ep); 213 281 instance->registers->control |= C_PLE | C_IE; 214 break;215 default:216 282 break; 217 283 } … … 312 378 /* Check for root hub communication */ 313 379 if (batch->ep->address == instance->rh.address) { 314 return rh_request(&instance->rh, batch); 380 rh_request(&instance->rh, batch); 381 return EOK; 315 382 } 316 383 … … 374 441 375 442 if (status & I_UE) { 376 hc_start _hw(instance);443 hc_start(instance); 377 444 } 378 445 … … 399 466 /** Turn off any (BIOS)driver that might be in control of the device. 400 467 * 468 * This function implements routines described in chapter 5.1.1.3 of the OHCI 469 * specification (page 40, pdf page 54). 470 * 401 471 * @param[in] instance OHCI hc driver structure. 402 472 */ … … 404 474 { 405 475 assert(instance); 476 406 477 usb_log_debug("Requesting OHCI control.\n"); 407 /* Turn off legacy emulation */ 408 volatile uint32_t *ohci_emulation_reg = 409 (uint32_t*)((char*)instance->registers + 0x100); 410 usb_log_debug("OHCI legacy register %p: %x.\n", 411 ohci_emulation_reg, *ohci_emulation_reg); 412 /* Do not change A20 state */ 413 *ohci_emulation_reg &= 0x100; 414 usb_log_debug("OHCI legacy register %p: %x.\n", 415 ohci_emulation_reg, *ohci_emulation_reg); 478 if (instance->registers->revision & R_LEGACY_FLAG) { 479 /* Turn off legacy emulation, it should be enough to zero 480 * the lowest bit, but it caused problems. Thus clear all 481 * except GateA20 (causes restart on some hw). 482 * See page 145 of the specs for details. 483 */ 484 volatile uint32_t *ohci_emulation_reg = 485 (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET); 486 usb_log_debug("OHCI legacy register %p: %x.\n", 487 ohci_emulation_reg, *ohci_emulation_reg); 488 /* Zero everything but A20State */ 489 *ohci_emulation_reg &= 0x100; 490 usb_log_debug( 491 "OHCI legacy register (should be 0 or 0x100) %p: %x.\n", 492 ohci_emulation_reg, *ohci_emulation_reg); 493 } 416 494 417 495 /* Interrupt routing enabled => smm driver is active */ … … 419 497 usb_log_debug("SMM driver: request ownership change.\n"); 420 498 instance->registers->command_status |= CS_OCR; 499 /* Hope that SMM actually knows its stuff or we can hang here */ 421 500 while (instance->registers->control & C_IR) { 422 501 async_usleep(1000); 423 502 } 424 503 usb_log_info("SMM driver: Ownership taken.\n"); 425 instance->registers->control &= (C_HCFS_RESET << C_HCFS_SHIFT);504 C_HCFS_SET(instance->registers->control, C_HCFS_RESET); 426 505 async_usleep(50000); 427 506 return; 428 507 } 429 508 430 const unsigned hc_status = 431 (instance->registers->control >> C_HCFS_SHIFT) & C_HCFS_MASK; 509 const unsigned hc_status = C_HCFS_GET(instance->registers->control); 432 510 /* Interrupt routing disabled && status != USB_RESET => BIOS active */ 433 511 if (hc_status != C_HCFS_RESET) { … … 437 515 return; 438 516 } 439 /* HC is suspended assert resume for 20ms */440 instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);517 /* HC is suspended assert resume for 20ms, */ 518 C_HCFS_SET(instance->registers->control, C_HCFS_RESUME); 441 519 async_usleep(20000); 442 520 usb_log_info("BIOS driver: HC resumed.\n"); … … 454 532 * @param[in] instance OHCI hc driver structure. 455 533 */ 456 void hc_start _hw(hc_t *instance)534 void hc_start(hc_t *instance) 457 535 { 458 536 /* OHCI guide page 42 */ … … 516 594 instance->registers->periodic_start, frame_length); 517 595 518 instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);596 C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL); 519 597 usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n", 520 598 instance->registers->control); … … 534 612 int ret = endpoint_list_init(&instance->lists[type], name); \ 535 613 if (ret != EOK) { \ 536 usb_log_error("Failed (%d) to setup %s endpoint list.\n", \537 ret, name); \614 usb_log_error("Failed to setup %s endpoint list: %s.\n", \ 615 name, str_error(ret)); \ 538 616 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\ 539 617 endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \ … … 587 665 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa); 588 666 589 /* Init interrupt code */ 590 instance->interrupt_code.cmds = instance->interrupt_commands; 591 instance->interrupt_code.cmdcount = OHCI_NEEDED_IRQ_COMMANDS; 592 { 593 /* Read status register */ 594 instance->interrupt_commands[0].cmd = CMD_MEM_READ_32; 595 instance->interrupt_commands[0].dstarg = 1; 596 instance->interrupt_commands[0].addr = 597 (void*)&instance->registers->interrupt_status; 598 599 /* Test whether we are the interrupt cause */ 600 instance->interrupt_commands[1].cmd = CMD_BTEST; 601 instance->interrupt_commands[1].value = 602 OHCI_USED_INTERRUPTS; 603 instance->interrupt_commands[1].srcarg = 1; 604 instance->interrupt_commands[1].dstarg = 2; 605 606 /* Predicate cleaning and accepting */ 607 instance->interrupt_commands[2].cmd = CMD_PREDICATE; 608 instance->interrupt_commands[2].value = 2; 609 instance->interrupt_commands[2].srcarg = 2; 610 611 /* Write-clean status register */ 612 instance->interrupt_commands[3].cmd = CMD_MEM_WRITE_A_32; 613 instance->interrupt_commands[3].srcarg = 1; 614 instance->interrupt_commands[3].addr = 615 (void*)&instance->registers->interrupt_status; 616 617 /* Accept interrupt */ 618 instance->interrupt_commands[4].cmd = CMD_ACCEPT; 619 } 620 621 return EOK; 622 } 667 return EOK; 668 } 669 623 670 /** 624 671 * @} -
uspace/drv/bus/usb/ohci/hc.h
r3e5c48c9 r159100a 51 51 #include "hw_struct/hcca.h" 52 52 53 #define OHCI_NEEDED_IRQ_COMMANDS 5 54 55 /** Main OHCI drier structure */ 53 /** Main OHCI driver structure */ 56 54 typedef struct hc { 57 55 /** USB bus driver, devices and addresses */ … … 76 74 fibril_mutex_t guard; 77 75 78 /** Code to be executed in kernel interrupt handler */79 irq_code_t interrupt_code;80 81 /** Commands that form interrupt code */82 irq_cmd_t interrupt_commands[OHCI_NEEDED_IRQ_COMMANDS];83 84 76 /** USB hub emulation structure */ 85 77 rh_t rh; 86 78 } hc_t; 87 79 80 size_t hc_irq_cmd_count(void); 81 int hc_get_irq_commands( 82 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size); 83 int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts); 88 84 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun); 89 int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);90 void hc_start_hw(hc_t *instance);91 85 92 86 /** Safely dispose host controller internal structures -
uspace/drv/bus/usb/ohci/ohci.c
r3e5c48c9 r159100a 58 58 { 59 59 assert(dev); 60 assert(dev->driver_data);61 60 return dev->driver_data; 62 61 } 63 64 62 /** IRQ handling callback, identifies device 65 63 * … … 70 68 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) 71 69 { 72 hc_t *hc = &dev_to_ohci(dev)->hc; 73 assert(hc); 70 assert(dev); 71 72 ohci_t *ohci = dev_to_ohci(dev); 73 if (!ohci) { 74 usb_log_warning("Interrupt on device that is not ready.\n"); 75 return; 76 } 74 77 const uint16_t status = IPC_GET_ARG1(*call); 75 hc_interrupt( hc, status);78 hc_interrupt(&ohci->hc, status); 76 79 } 77 80 /*----------------------------------------------------------------------------*/ … … 166 169 } \ 167 170 free(instance); \ 171 device->driver_data = NULL; \ 168 172 usb_log_error(message); \ 169 173 return ret; \ … … 173 177 instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc"); 174 178 int ret = instance->hc_fun ? EOK : ENOMEM; 175 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI HC function.\n"); 179 CHECK_RET_DEST_FREE_RETURN(ret, 180 "Failed to create OHCI HC function: %s.\n", str_error(ret)); 176 181 instance->hc_fun->ops = &hc_ops; 177 182 instance->hc_fun->driver_data = &instance->hc; … … 179 184 instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh"); 180 185 ret = instance->rh_fun ? EOK : ENOMEM; 181 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI RH function.\n"); 186 CHECK_RET_DEST_FREE_RETURN(ret, 187 "Failed to create OHCI RH function: %s.\n", str_error(ret)); 182 188 instance->rh_fun->ops = &rh_ops; 183 189 … … 193 199 (void *) reg_base, reg_size, irq); 194 200 201 const size_t cmd_count = hc_irq_cmd_count(); 202 irq_cmd_t irq_cmds[cmd_count]; 203 ret = 204 hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size); 205 CHECK_RET_DEST_FREE_RETURN(ret, 206 "Failed to generate IRQ commands: %s.\n", str_error(ret)); 207 208 irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds }; 209 210 /* Register handler to avoid interrupt lockup */ 211 ret = register_interrupt_handler(device, irq, irq_handler, &irq_code); 212 CHECK_RET_DEST_FREE_RETURN(ret, 213 "Failed to register interrupt handler: %s.\n", str_error(ret)); 214 215 /* Try to enable interrupts */ 195 216 bool interrupts = false; 196 #ifdef CONFIG_USBHC_NO_INTERRUPTS197 usb_log_warning("Interrupts disabled in OS config, "198 "falling back to polling.\n");199 #else200 217 ret = pci_enable_interrupts(device); 201 218 if (ret != EOK) { 202 usb_log_warning("Failed to enable interrupts: %s. \n",203 str_error(ret));204 usb_log_info("HW interrupts not available, "205 "falling back to polling.\n");219 usb_log_warning("Failed to enable interrupts: %s." 220 " Falling back to polling\n", str_error(ret)); 221 /* We don't need that handler */ 222 unregister_interrupt_handler(device, irq); 206 223 } else { 207 224 usb_log_debug("Hw interrupts enabled.\n"); 208 225 interrupts = true; 209 226 } 210 #endif211 227 212 228 ret = hc_init(&instance->hc, reg_base, reg_size, interrupts); 213 CHECK_RET_DEST_FREE_RETURN(ret, "Failed(%d) to init ohci_hcd.\n", ret); 229 CHECK_RET_DEST_FREE_RETURN(ret, 230 "Failed to init ohci_hcd: %s.\n", str_error(ret)); 231 232 device->driver_data = instance; 214 233 215 234 #define CHECK_RET_FINI_RETURN(ret, message...) \ 216 235 if (ret != EOK) { \ 236 unregister_interrupt_handler(device, irq); \ 217 237 hc_fini(&instance->hc); \ 218 238 CHECK_RET_DEST_FREE_RETURN(ret, message); \ 219 239 } else (void)0 220 240 221 /* It does no harm if we register this on polling */222 ret = register_interrupt_handler(device, irq, irq_handler,223 &instance->hc.interrupt_code);224 CHECK_RET_FINI_RETURN(ret,225 "Failed(%d) to register interrupt handler.\n", ret);226 241 227 242 ret = ddf_fun_bind(instance->hc_fun); 228 243 CHECK_RET_FINI_RETURN(ret, 229 "Failed(%d) to bind OHCI device function: %s.\n", 230 ret, str_error(ret)); 244 "Failed to bind OHCI device function: %s.\n", str_error(ret)); 231 245 232 246 ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME); … … 234 248 "Failed to add OHCI to HC class: %s.\n", str_error(ret)); 235 249 236 device->driver_data = instance;237 238 hc_start_hw(&instance->hc);239 250 hc_register_hub(&instance->hc, instance->rh_fun); 240 251 return EOK; -
uspace/drv/bus/usb/ohci/ohci_regs.h
r3e5c48c9 r159100a 34 34 #ifndef DRV_OHCI_OHCI_REGS_H 35 35 #define DRV_OHCI_OHCI_REGS_H 36 #include <stdint.h> 36 #include <sys/types.h> 37 38 #define LEGACY_REGS_OFFSET 0x100 37 39 38 40 /** OHCI memory mapped registers structure */ 39 41 typedef struct ohci_regs { 40 const volatile uint32_t revision; 41 volatile uint32_t control; 42 #define C_CSBR_MASK (0x3) /* Control-bulk service ratio */ 43 #define C_CSBR_1_1 (0x0) 44 #define C_CSBR_1_2 (0x1) 45 #define C_CSBR_1_3 (0x2) 46 #define C_CSBR_1_4 (0x3) 47 #define C_CSBR_SHIFT (0) 42 const ioport32_t revision; 43 #define R_REVISION_MASK (0x3f) 44 #define R_REVISION_SHIFT (0) 45 #define R_LEGACY_FLAG (0x80) 46 47 ioport32_t control; 48 #define C_CBSR_MASK (0x3) /* Control-bulk service ratio */ 49 #define C_CBSR_1_1 (0x0) 50 #define C_CBSR_1_2 (0x1) 51 #define C_CBSR_1_3 (0x2) 52 #define C_CBSR_1_4 (0x3) 53 #define C_CBSR_SHIFT (0) 48 54 49 55 #define C_PLE (1 << 2) /* Periodic list enable */ … … 59 65 #define C_HCFS_SHIFT (6) 60 66 67 #define C_HCFS_GET(reg) \ 68 ((reg >> C_HCFS_SHIFT) & C_HCFS_MASK) 69 #define C_HCFS_SET(reg, hcfs_state) \ 70 do { \ 71 reg = (reg & ~(C_HCFS_MASK << C_HCFS_SHIFT)) \ 72 | ((hcfs_state & C_HCFS_MASK) << C_HCFS_SHIFT); \ 73 } while (0) 74 75 61 76 #define C_IR (1 << 8) /* Interrupt routing, make sure it's 0 */ 62 77 #define C_RWC (1 << 9) /* Remote wakeup connected, host specific */ 63 78 #define C_RWE (1 << 10) /* Remote wakeup enable */ 64 79 65 volatile uint32_t command_status;80 ioport32_t command_status; 66 81 #define CS_HCR (1 << 0) /* Host controller reset */ 67 82 #define CS_CLF (1 << 1) /* Control list filled */ … … 75 90 * writing causes enable/disable, 76 91 * status is write-clean (writing 1 clears the bit*/ 77 volatile uint32_t interrupt_status;78 volatile uint32_t interrupt_enable;79 volatile uint32_t interrupt_disable;92 ioport32_t interrupt_status; 93 ioport32_t interrupt_enable; 94 ioport32_t interrupt_disable; 80 95 #define I_SO (1 << 0) /* Scheduling overrun */ 81 96 #define I_WDH (1 << 1) /* Done head write-back */ … … 89 104 90 105 /** HCCA pointer (see hw_struct hcca.h) */ 91 volatile uint32_t hcca;106 ioport32_t hcca; 92 107 #define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */ 93 108 94 109 /** Currently executed periodic endpoint */ 95 const volatile uint32_t periodic_current;110 const ioport32_t periodic_current; 96 111 97 112 /** The first control endpoint */ 98 volatile uint32_t control_head;113 ioport32_t control_head; 99 114 100 115 /** Currently executed control endpoint */ 101 volatile uint32_t control_current;116 ioport32_t control_current; 102 117 103 118 /** The first bulk endpoint */ 104 volatile uint32_t bulk_head;119 ioport32_t bulk_head; 105 120 106 121 /** Currently executed bulk endpoint */ 107 volatile uint32_t bulk_current;122 ioport32_t bulk_current; 108 123 109 124 /** Done TD list, this value is periodically written to HCCA */ 110 const volatile uint32_t done_head;125 const ioport32_t done_head; 111 126 112 127 /** Frame time and max packet size for all transfers */ 113 volatile uint32_t fm_interval;128 ioport32_t fm_interval; 114 129 #define FMI_FI_MASK (0x3fff) /* Frame interval in bit times (should be 11999)*/ 115 130 #define FMI_FI_SHIFT (0) … … 119 134 120 135 /** Bit times remaining in current frame */ 121 const volatile uint32_t fm_remaining;136 const ioport32_t fm_remaining; 122 137 #define FMR_FR_MASK FMI_FI_MASK 123 138 #define FMR_FR_SHIFT FMI_FI_SHIFT … … 125 140 126 141 /** Frame number */ 127 const volatile uint32_t fm_number;142 const ioport32_t fm_number; 128 143 #define FMN_NUMBER_MASK (0xffff) 129 144 130 145 /** Remaining bit time in frame to start periodic transfers */ 131 volatile uint32_t periodic_start;146 ioport32_t periodic_start; 132 147 #define PS_PS_MASK (0x3fff) /* bit time when periodic get priority (0x3e67) */ 133 148 134 149 /** Threshold for starting LS transaction */ 135 volatile uint32_t ls_threshold;150 ioport32_t ls_threshold; 136 151 #define LST_LST_MASK (0x7fff) 137 152 138 153 /** The first root hub control register */ 139 volatile uint32_t rh_desc_a;154 ioport32_t rh_desc_a; 140 155 #define RHDA_NDS_MASK (0xff) /* Number of downstream ports, max 15 */ 141 156 #define RHDA_NDS_SHIFT (0) … … 144 159 #define RHDA_DT_FLAG (1 << 10) /* 1-Compound device, must be 0 */ 145 160 #define RHDA_OCPM_FLAG (1 << 11) /* Over-current mode: 0-global, 1-per port */ 146 #define RHDA_NOCP 161 #define RHDA_NOCP_FLAG (1 << 12) /* OC control: 0-use OCPM, 1-OC off */ 147 162 #define RHDA_POTPGT_MASK (0xff) /* Power on to power good time */ 148 163 #define RHDA_POTPGT_SHIFT (24) 149 164 150 165 /** The other root hub control register */ 151 volatile uint32_t rh_desc_b;166 ioport32_t rh_desc_b; 152 167 #define RHDB_DR_MASK (0xffff) /* Device removable mask */ 153 168 #define RHDB_DR_SHIFT (0) … … 161 176 162 177 /** Root hub status register */ 163 volatile uint32_t rh_status;178 ioport32_t rh_status; 164 179 #define RHS_LPS_FLAG (1 << 0)/* read: 0, 165 180 * write: 0-no effect, … … 167 182 * specified in PPCM(RHDB), or all ports, 168 183 * if power is set globally */ 169 #define RHS_CLEAR_ PORT_POWER RHS_LPS_FLAG /* synonym for the above */184 #define RHS_CLEAR_GLOBAL_POWER RHS_LPS_FLAG /* synonym for the above */ 170 185 #define RHS_OCI_FLAG (1 << 1)/* Over-current indicator, if per-port: 0 */ 171 186 #define RHS_DRWE_FLAG (1 << 15)/* read: 0-connect status change does not wake HC … … 178 193 * specified in PPCM(RHDB), or all ports, 179 194 * if power is set globally */ 180 #define RHS_SET_ PORT_POWER RHS_LPSC_FLAG /* synonym for the above */195 #define RHS_SET_GLOBAL_POWER RHS_LPSC_FLAG /* synonym for the above */ 181 196 #define RHS_OCIC_FLAG (1 << 17)/* Over-current indicator change */ 182 197 #define RHS_CLEAR_DRWE (1 << 31) 183 198 184 199 /** Root hub per port status */ 185 volatile uint32_t rh_port_status[];200 ioport32_t rh_port_status[]; 186 201 #define RHPS_CCS_FLAG (1 << 0) /* r: current connect status, 187 202 * w: 1-clear port enable, 0-nothing */ -
uspace/drv/bus/usb/ohci/root_hub.c
r3e5c48c9 r159100a 40 40 #include "root_hub.h" 41 41 #include <usb/classes/classes.h> 42 #include <usb/classes/hub.h> 42 43 #include <usb/dev/driver.h> 43 44 #include "ohci_regs.h" … … 56 57 .device_subclass = 0, 57 58 .device_version = 0, 58 .length = sizeof 59 .max_packet_size = 8,60 .vendor_id = 0x16db, 59 .length = sizeof(usb_standard_device_descriptor_t), 60 .max_packet_size = 64, 61 .vendor_id = 0x16db, /* HelenOS does not have USB vendor ID assigned.*/ 61 62 .product_id = 0x0001, 62 63 .str_serial_number = 0, … … 73 74 .descriptor_type = USB_DESCTYPE_CONFIGURATION, 74 75 .interface_count = 1, 75 .length = sizeof 76 .max_power = 100,76 .length = sizeof(usb_standard_configuration_descriptor_t), 77 .max_power = 0, /* root hubs don't need no power */ 77 78 .str_configuration = 0, 78 79 }; … … 89 90 .interface_protocol = 0, 90 91 .interface_subclass = 0, 91 .length = sizeof 92 .length = sizeof(usb_standard_interface_descriptor_t), 92 93 .str_interface = 0, 93 94 }; … … 100 101 .descriptor_type = USB_DESCTYPE_ENDPOINT, 101 102 .endpoint_address = 1 + (1 << 7), 102 .length = sizeof 103 .max_packet_size = 8,103 .length = sizeof(usb_standard_endpoint_descriptor_t), 104 .max_packet_size = 2, 104 105 .poll_interval = 255, 105 106 }; 106 107 107 /** 108 * bitmask of hub features that are valid to be cleared 109 */ 110 static const uint32_t hub_clear_feature_valid_mask = 111 RHS_OCIC_FLAG | 112 RHS_CLEAR_PORT_POWER; 113 114 /** 115 * bitmask of hub features that are cleared by writing 1 (and not 0) 116 */ 117 static const uint32_t hub_clear_feature_by_writing_one_mask = 118 RHS_CLEAR_PORT_POWER; 119 120 /** 121 * bitmask of hub features that are valid to be set 122 */ 123 static const uint32_t hub_set_feature_valid_mask = 124 RHS_LPSC_FLAG | 125 RHS_OCIC_FLAG; 126 127 /** 128 * bitmask of hub features that are set by writing 1 and cleared by writing 0 129 */ 130 static const uint32_t hub_set_feature_direct_mask = 131 RHS_SET_PORT_POWER; 132 133 /** 134 * bitmask of port features that are valid to be set 135 */ 136 static const uint32_t port_set_feature_valid_mask = 137 RHPS_SET_PORT_ENABLE | 138 RHPS_SET_PORT_SUSPEND | 139 RHPS_SET_PORT_RESET | 140 RHPS_SET_PORT_POWER; 141 142 /** 143 * bitmask of port features that can be cleared 144 */ 145 static const uint32_t port_clear_feature_valid_mask = 146 RHPS_CCS_FLAG | 147 RHPS_SET_PORT_SUSPEND | 148 RHPS_POCI_FLAG | 149 RHPS_SET_PORT_POWER | 150 RHPS_CSC_FLAG | 151 RHPS_PESC_FLAG | 152 RHPS_PSSC_FLAG | 153 RHPS_OCIC_FLAG | 154 RHPS_PRSC_FLAG; 155 156 //note that USB_HUB_FEATURE_PORT_POWER bit is translated into 157 //USB_HUB_FEATURE_PORT_LOW_SPEED for port set feature request 158 159 /** 160 * bitmask with port status changes 161 */ 162 static const uint32_t port_status_change_mask = RHPS_CHANGE_WC_MASK; 163 164 static int create_serialized_hub_descriptor(rh_t *instance); 165 166 static int rh_init_descriptors(rh_t *instance); 167 168 static int process_get_port_status_request(rh_t *instance, uint16_t port, 169 usb_transfer_batch_t * request); 170 171 static int process_get_hub_status_request(rh_t *instance, 172 usb_transfer_batch_t * request); 173 174 static int process_get_status_request(rh_t *instance, 175 usb_transfer_batch_t * request); 176 177 static void create_interrupt_mask_in_instance(rh_t *instance); 178 179 static int process_get_descriptor_request(rh_t *instance, 180 usb_transfer_batch_t *request); 181 182 static int process_get_configuration_request(rh_t *instance, 183 usb_transfer_batch_t *request); 184 185 static int process_hub_feature_set_request(rh_t *instance, uint16_t feature); 186 187 static int process_hub_feature_clear_request(rh_t *instance, 188 uint16_t feature); 189 190 static int process_port_feature_set_request(rh_t *instance, 191 uint16_t feature, uint16_t port); 192 193 static int process_port_feature_clear_request(rh_t *instance, 194 uint16_t feature, uint16_t port); 195 196 static int process_address_set_request(rh_t *instance, 197 uint16_t address); 198 199 static int process_request_with_output(rh_t *instance, 200 usb_transfer_batch_t *request); 201 202 static int process_request_with_input(rh_t *instance, 203 usb_transfer_batch_t *request); 204 205 static int process_request_without_data(rh_t *instance, 206 usb_transfer_batch_t *request); 207 208 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request); 209 210 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request); 211 212 static bool is_zeros(void * buffer, size_t size); 213 214 /** Root hub initialization 215 * @return Error code. 216 */ 217 int rh_init(rh_t *instance, ohci_regs_t *regs) { 218 assert(instance); 108 static void create_serialized_hub_descriptor(rh_t *instance); 109 static void rh_init_descriptors(rh_t *instance); 110 static uint16_t create_interrupt_mask(rh_t *instance); 111 static int get_status(rh_t *instance, usb_transfer_batch_t *request); 112 static int get_descriptor(rh_t *instance, usb_transfer_batch_t *request); 113 static int set_feature(rh_t *instance, usb_transfer_batch_t *request); 114 static int clear_feature(rh_t *instance, usb_transfer_batch_t *request); 115 static int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port); 116 static int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port); 117 static int control_request(rh_t *instance, usb_transfer_batch_t *request); 118 static inline void interrupt_request( 119 usb_transfer_batch_t *request, uint16_t mask, size_t size) 120 { 121 assert(request); 122 123 memcpy(request->data_buffer, &mask, size); 124 request->transfered_size = size; 125 usb_transfer_batch_finish_error(request, EOK); 126 } 127 128 #define TRANSFER_OK(bytes) \ 129 do { \ 130 request->transfered_size = bytes; \ 131 return EOK; \ 132 } while (0) 133 134 /** Root Hub driver structure initialization. 135 * 136 * Reads info registers and prepares descriptors. Sets power mode. 137 */ 138 void rh_init(rh_t *instance, ohci_regs_t *regs) 139 { 140 assert(instance); 141 assert(regs); 142 219 143 instance->registers = regs; 220 144 instance->port_count = 221 145 (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK; 222 int opResult = rh_init_descriptors(instance); 223 if (opResult != EOK) { 224 return opResult; 225 } 226 // set port power mode to no-power-switching 146 if (instance->port_count > 15) { 147 usb_log_warning("OHCI specification does not allow more than 15" 148 " ports. Max 15 ports will be used"); 149 instance->port_count = 15; 150 } 151 152 /* Don't forget the hub status bit and round up */ 153 instance->interrupt_mask_size = 1 + (instance->port_count / 8); 154 instance->unfinished_interrupt_transfer = NULL; 155 156 #ifdef OHCI_POWER_SWITCH_no 157 /* Set port power mode to no power-switching. (always on) */ 227 158 instance->registers->rh_desc_a |= RHDA_NPS_FLAG; 228 instance->unfinished_interrupt_transfer = NULL; 229 instance->interrupt_mask_size = (instance->port_count + 8) / 8; 230 instance->interrupt_buffer = malloc(instance->interrupt_mask_size); 231 if (!instance->interrupt_buffer) 232 return ENOMEM; 159 /* Set to no over-current reporting */ 160 instance->registers->rh_desc_a |= RHDA_NOCP_FLAG; 161 #elif defined OHCI_POWER_SWITCH_ganged 162 /* Set port power mode to no ganged power-switching. */ 163 instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG; 164 instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG; 165 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 166 /* Set to global over-current */ 167 instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG; 168 instance->registers->rh_desc_a &= ~RHDA_OCPM_FLAG; 169 #else 170 /* Set port power mode to no per port power-switching. */ 171 instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG; 172 instance->registers->rh_desc_a |= RHDA_PSM_FLAG; 173 174 /* Control all ports by global switch and turn them off */ 175 instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT); 176 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 177 /* Return control to per port state */ 178 instance->registers->rh_desc_b |= 179 ((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT; 180 /* Set per port over-current */ 181 instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG; 182 instance->registers->rh_desc_a |= RHDA_OCPM_FLAG; 183 #endif 184 185 rh_init_descriptors(instance); 233 186 234 187 usb_log_info("Root hub (%zu ports) initialized.\n", 235 188 instance->port_count); 236 237 return EOK; 238 } 239 /*----------------------------------------------------------------------------*/ 240 241 /** 242 * process root hub request 243 * 244 * @param instance root hub instance 245 * @param request structure containing both request and response information 246 * @return error code 247 */ 248 int rh_request(rh_t *instance, usb_transfer_batch_t *request) { 189 } 190 /*----------------------------------------------------------------------------*/ 191 /** 192 * Process root hub request. 193 * 194 * @param instance Root hub instance 195 * @param request Structure containing both request and response information 196 * @return Error code 197 */ 198 void rh_request(rh_t *instance, usb_transfer_batch_t *request) 199 { 249 200 assert(instance); 250 201 assert(request); 251 int opResult; 252 if (request->ep->transfer_type == USB_TRANSFER_CONTROL) { 202 203 switch (request->ep->transfer_type) 204 { 205 case USB_TRANSFER_CONTROL: 253 206 usb_log_debug("Root hub got CONTROL packet\n"); 254 opResult = process_ctrl_request(instance, request); 255 usb_transfer_batch_finish_error(request, opResult); 256 } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) { 207 const int ret = control_request(instance, request); 208 usb_transfer_batch_finish_error(request, ret); 209 break; 210 case USB_TRANSFER_INTERRUPT: 257 211 usb_log_debug("Root hub got INTERRUPT packet\n"); 258 create_interrupt_mask_in_instance(instance); 259 if (is_zeros(instance->interrupt_buffer, 260 instance->interrupt_mask_size)) { 212 const uint16_t mask = create_interrupt_mask(instance); 213 if (mask == 0) { 261 214 usb_log_debug("No changes..\n"); 215 assert(instance->unfinished_interrupt_transfer == NULL); 262 216 instance->unfinished_interrupt_transfer = request; 263 //will be finished later 264 } else { 265 usb_log_debug("Processing changes..\n"); 266 process_interrupt_mask_in_instance(instance, request); 217 break; 267 218 } 268 opResult = EOK; 269 } else { 270 271 opResult = EINVAL; 272 usb_transfer_batch_finish_error(request, opResult); 273 } 274 return EOK; 275 } 276 277 /*----------------------------------------------------------------------------*/ 278 279 /** 280 * process interrupt on a hub 219 usb_log_debug("Processing changes...\n"); 220 interrupt_request(request, mask, instance->interrupt_mask_size); 221 break; 222 223 default: 224 usb_log_error("Root hub got unsupported request.\n"); 225 usb_transfer_batch_finish_error(request, EINVAL); 226 } 227 } 228 /*----------------------------------------------------------------------------*/ 229 /** 230 * Process interrupt on a hub device. 281 231 * 282 232 * If there is no pending interrupt transfer, nothing happens. 283 233 * @param instance 284 234 */ 285 void rh_interrupt(rh_t *instance) { 286 if (!instance->unfinished_interrupt_transfer) { 235 void rh_interrupt(rh_t *instance) 236 { 237 assert(instance); 238 239 if (!instance->unfinished_interrupt_transfer) 287 240 return; 288 } 241 289 242 usb_log_debug("Finalizing interrupt transfer\n"); 290 create_interrupt_mask_in_instance(instance); 291 process_interrupt_mask_in_instance(instance, 292 instance->unfinished_interrupt_transfer); 293 } 294 /*----------------------------------------------------------------------------*/ 295 296 /** 297 * Create hub descriptor used in hub-driver <-> hub communication 298 * 299 * This means creating byt array from data in root hub registers. For more 300 * info see usb hub specification. 301 * 243 const uint16_t mask = create_interrupt_mask(instance); 244 interrupt_request(instance->unfinished_interrupt_transfer, 245 mask, instance->interrupt_mask_size); 246 247 instance->unfinished_interrupt_transfer = NULL; 248 } 249 /*----------------------------------------------------------------------------*/ 250 /** 251 * Create hub descriptor. 252 * 253 * For descriptor format see USB hub specification (chapter 11.15.2.1, pg. 263) 254 * 255 * @param instance Root hub instance 256 * @return Error code 257 */ 258 void create_serialized_hub_descriptor(rh_t *instance) 259 { 260 assert(instance); 261 262 /* 7 bytes + 2 port bit fields (port count + global bit) */ 263 const size_t size = 7 + (instance->interrupt_mask_size * 2); 264 assert(size <= HUB_DESCRIPTOR_MAX_SIZE); 265 instance->hub_descriptor_size = size; 266 267 const uint32_t hub_desc = instance->registers->rh_desc_a; 268 const uint32_t port_desc = instance->registers->rh_desc_b; 269 270 /* bDescLength */ 271 instance->descriptors.hub[0] = size; 272 /* bDescriptorType */ 273 instance->descriptors.hub[1] = USB_DESCTYPE_HUB; 274 /* bNmbrPorts */ 275 instance->descriptors.hub[2] = instance->port_count; 276 /* wHubCharacteristics */ 277 instance->descriptors.hub[3] = 0 | 278 /* The lowest 2 bits indicate power switching mode */ 279 (((hub_desc & RHDA_PSM_FLAG) ? 1 : 0) << 0) | 280 (((hub_desc & RHDA_NPS_FLAG) ? 1 : 0) << 1) | 281 /* Bit 3 indicates device type (compound device) */ 282 (((hub_desc & RHDA_DT_FLAG) ? 1 : 0) << 2) | 283 /* Bits 4,5 indicate over-current protection mode */ 284 (((hub_desc & RHDA_OCPM_FLAG) ? 1 : 0) << 3) | 285 (((hub_desc & RHDA_NOCP_FLAG) ? 1 : 0) << 4); 286 287 /* Reserved */ 288 instance->descriptors.hub[4] = 0; 289 /* bPwrOn2PwrGood */ 290 instance->descriptors.hub[5] = 291 (hub_desc >> RHDA_POTPGT_SHIFT) & RHDA_POTPGT_MASK; 292 /* bHubContrCurrent, root hubs don't need no power. */ 293 instance->descriptors.hub[6] = 0; 294 295 /* Device Removable and some legacy 1.0 stuff*/ 296 instance->descriptors.hub[7] = 297 (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK & 0xff; 298 instance->descriptors.hub[8] = 0xff; 299 if (instance->interrupt_mask_size == 2) { 300 instance->descriptors.hub[8] = 301 (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK >> 8; 302 instance->descriptors.hub[9] = 0xff; 303 instance->descriptors.hub[10] = 0xff; 304 } 305 } 306 /*----------------------------------------------------------------------------*/ 307 /** Initialize hub descriptors. 308 * 309 * A full configuration descriptor is assembled. The configuration and endpoint 310 * descriptors have local modifications. 311 * @param instance Root hub instance 312 * @return Error code 313 */ 314 void rh_init_descriptors(rh_t *instance) 315 { 316 assert(instance); 317 318 instance->descriptors.configuration = ohci_rh_conf_descriptor; 319 instance->descriptors.interface = ohci_rh_iface_descriptor; 320 instance->descriptors.endpoint = ohci_rh_ep_descriptor; 321 create_serialized_hub_descriptor(instance); 322 323 instance->descriptors.endpoint.max_packet_size = 324 instance->interrupt_mask_size; 325 326 instance->descriptors.configuration.total_length = 327 sizeof(usb_standard_configuration_descriptor_t) + 328 sizeof(usb_standard_endpoint_descriptor_t) + 329 sizeof(usb_standard_interface_descriptor_t) + 330 instance->hub_descriptor_size; 331 } 332 /*----------------------------------------------------------------------------*/ 333 /** 334 * Create bitmap of changes to answer status interrupt. 335 * 336 * Result contains bitmap where bit 0 indicates change on hub and 337 * bit i indicates change on i`th port (i>0). For more info see 338 * Hub and Port status bitmap specification in USB specification 339 * (chapter 11.13.4). 302 340 * @param instance root hub instance 303 * @return error code 304 */ 305 static int create_serialized_hub_descriptor(rh_t *instance) { 306 size_t size = 7 + 307 ((instance->port_count + 7) / 8) * 2; 308 size_t var_size = (instance->port_count + 7) / 8; 309 uint8_t * result = (uint8_t*) malloc(size); 310 if (!result) return ENOMEM; 311 312 bzero(result, size); 313 //size 314 result[0] = size; 315 //descriptor type 316 result[1] = USB_DESCTYPE_HUB; 317 result[2] = instance->port_count; 318 uint32_t hub_desc_reg = instance->registers->rh_desc_a; 319 result[3] = 320 ((hub_desc_reg >> 8) % 2) + 321 (((hub_desc_reg >> 9) % 2) << 1) + 322 (((hub_desc_reg >> 10) % 2) << 2) + 323 (((hub_desc_reg >> 11) % 2) << 3) + 324 (((hub_desc_reg >> 12) % 2) << 4); 325 result[4] = 0; 326 result[5] = /*descriptor->pwr_on_2_good_time*/ 50; 327 result[6] = 50; 328 329 size_t port; 330 for (port = 1; port <= instance->port_count; ++port) { 331 uint8_t is_non_removable = 332 instance->registers->rh_desc_b >> port % 2; 333 result[7 + port / 8] += 334 is_non_removable << (port % 8); 335 } 336 size_t i; 337 for (i = 0; i < var_size; ++i) { 338 result[7 + var_size + i] = 255; 339 } 340 instance->hub_descriptor = result; 341 instance->descriptor_size = size; 342 343 return EOK; 344 } 345 /*----------------------------------------------------------------------------*/ 346 347 /** initialize hub descriptors 348 * 349 * Initialized are device and full configuration descriptor. These need to 350 * be initialized only once per hub. 351 * @instance root hub instance 352 * @return error code 353 */ 354 static int rh_init_descriptors(rh_t *instance) { 355 memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor, 356 sizeof (ohci_rh_device_descriptor) 357 ); 358 usb_standard_configuration_descriptor_t descriptor; 359 memcpy(&descriptor, &ohci_rh_conf_descriptor, 360 sizeof (ohci_rh_conf_descriptor)); 361 362 int opResult = create_serialized_hub_descriptor(instance); 363 if (opResult != EOK) { 364 return opResult; 365 } 366 descriptor.total_length = 367 sizeof (usb_standard_configuration_descriptor_t) + 368 sizeof (usb_standard_endpoint_descriptor_t) + 369 sizeof (usb_standard_interface_descriptor_t) + 370 instance->descriptor_size; 371 372 uint8_t * full_config_descriptor = 373 (uint8_t*) malloc(descriptor.total_length); 374 if (!full_config_descriptor) { 375 return ENOMEM; 376 } 377 memcpy(full_config_descriptor, &descriptor, sizeof (descriptor)); 378 memcpy(full_config_descriptor + sizeof (descriptor), 379 &ohci_rh_iface_descriptor, sizeof (ohci_rh_iface_descriptor)); 380 memcpy(full_config_descriptor + sizeof (descriptor) + 381 sizeof (ohci_rh_iface_descriptor), 382 &ohci_rh_ep_descriptor, sizeof (ohci_rh_ep_descriptor)); 383 memcpy(full_config_descriptor + sizeof (descriptor) + 384 sizeof (ohci_rh_iface_descriptor) + 385 sizeof (ohci_rh_ep_descriptor), 386 instance->hub_descriptor, instance->descriptor_size); 387 388 instance->descriptors.configuration = full_config_descriptor; 389 instance->descriptors.configuration_size = descriptor.total_length; 390 391 return EOK; 392 } 393 /*----------------------------------------------------------------------------*/ 394 395 /** 396 * create answer to port status_request 397 * 398 * Copy content of corresponding port status register to answer buffer. The 399 * format of the port status register and port status data is the same ( 400 * see OHCI root hub and USB hub documentation). 401 * 402 * @param instance root hub instance 403 * @param port port number, counted from 1 404 * @param request structure containing both request and response information 405 * @return error code 406 */ 407 static int process_get_port_status_request(rh_t *instance, uint16_t port, 408 usb_transfer_batch_t * request) { 409 if (port < 1 || port > instance->port_count) 410 return EINVAL; 411 request->transfered_size = 4; 412 uint32_t data = instance->registers->rh_port_status[port - 1]; 413 memcpy(request->data_buffer, &data, 4); 414 return EOK; 415 } 416 /*----------------------------------------------------------------------------*/ 417 418 /** 419 * create answer to port status_request 420 * 421 * This copies flags in hub status register into the buffer. The format of the 422 * status register and status message is the same, according to USB hub 423 * specification and OHCI root hub specification. 424 * 425 * @param instance root hub instance 426 * @param request structure containing both request and response information 427 * @return error code 428 */ 429 static int process_get_hub_status_request(rh_t *instance, 430 usb_transfer_batch_t * request) { 431 request->transfered_size = 4; 432 //bits, 0,1,16,17 433 uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17); 434 uint32_t data = mask & instance->registers->rh_status; 435 memcpy(request->data_buffer, &data, 4); 436 437 return EOK; 438 } 439 /*----------------------------------------------------------------------------*/ 440 441 /** 442 * create answer to status request 341 * @return Mask of changes. 342 */ 343 uint16_t create_interrupt_mask(rh_t *instance) 344 { 345 assert(instance); 346 uint16_t mask = 0; 347 348 /* Only local power source change and over-current change can happen */ 349 if (instance->registers->rh_status & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) { 350 mask |= 1; 351 } 352 size_t port = 1; 353 for (; port <= instance->port_count; ++port) { 354 /* Write-clean bits are those that indicate change */ 355 if (RHPS_CHANGE_WC_MASK 356 & instance->registers->rh_port_status[port - 1]) { 357 358 mask |= (1 << port); 359 } 360 } 361 /* USB is little endian */ 362 return host2uint32_t_le(mask); 363 } 364 /*----------------------------------------------------------------------------*/ 365 /** 366 * Create answer to status request. 443 367 * 444 368 * This might be either hub status or port status request. If neither, … … 448 372 * @return error code 449 373 */ 450 static int process_get_status_request(rh_t *instance, 451 usb_transfer_batch_t * request) { 452 size_t buffer_size = request->buffer_size; 453 usb_device_request_setup_packet_t * request_packet = 454 (usb_device_request_setup_packet_t*) 455 request->setup_buffer; 456 457 usb_hub_bm_request_type_t request_type = request_packet->request_type; 458 if (buffer_size < 4) { 459 usb_log_warning("Requested more data than buffer size\n"); 460 return EINVAL; 461 } 462 463 if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) 464 return process_get_hub_status_request(instance, request); 465 if (request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) 466 return process_get_port_status_request(instance, 467 request_packet->index, 468 request); 374 int get_status(rh_t *instance, usb_transfer_batch_t *request) 375 { 376 assert(instance); 377 assert(request); 378 379 const usb_device_request_setup_packet_t *request_packet = 380 (usb_device_request_setup_packet_t*)request->setup_buffer; 381 382 if (request->buffer_size < 4) { 383 usb_log_error("Buffer too small for get status request.\n"); 384 return EOVERFLOW; 385 } 386 387 /* Hub status: just filter relevant info from rh_status reg */ 388 if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) { 389 const uint32_t data = instance->registers->rh_status & 390 (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG); 391 memcpy(request->data_buffer, &data, 4); 392 TRANSFER_OK(4); 393 } 394 395 /* Copy appropriate rh_port_status register, OHCI designers were 396 * kind enough to make those bit values match USB specification */ 397 if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) { 398 const unsigned port = request_packet->index; 399 if (port < 1 || port > instance->port_count) 400 return EINVAL; 401 402 const uint32_t data = 403 instance->registers->rh_port_status[port - 1]; 404 memcpy(request->data_buffer, &data, 4); 405 TRANSFER_OK(4); 406 } 469 407 470 408 return ENOTSUP; 471 409 } 472 410 /*----------------------------------------------------------------------------*/ 473 474 /** 475 * create answer to status interrupt consisting of change bitmap 476 * 477 * Result contains bitmap where bit 0 indicates change on hub and 478 * bit i indicates change on i`th port (i>0). For more info see 479 * Hub and Port status bitmap specification in USB specification 480 * (chapter 11.13.4). 481 * Uses instance`s interrupt buffer to store the interrupt information. 482 * @param instance root hub instance 483 */ 484 static void create_interrupt_mask_in_instance(rh_t * instance) { 485 uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer); 486 uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16)) 487 | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16)); 488 bzero(bitmap, instance->interrupt_mask_size); 489 if ((instance->registers->rh_status & mask) != 0) { 490 bitmap[0] = 1; 491 } 492 size_t port; 493 mask = port_status_change_mask; 494 for (port = 1; port <= instance->port_count; ++port) { 495 if ((mask & instance->registers->rh_port_status[port - 1]) != 0) { 496 497 bitmap[(port) / 8] += 1 << (port % 8); 498 } 499 } 500 } 501 /*----------------------------------------------------------------------------*/ 502 503 /** 504 * create answer to a descriptor request 411 /** 412 * Create answer to a descriptor request. 505 413 * 506 414 * This might be a request for standard (configuration, device, endpoint or 507 415 * interface) or device specific (hub) descriptor. 508 * @param instance root hub instance 509 * @param request structure containing both request and response information 510 * @return error code 511 */ 512 static int process_get_descriptor_request(rh_t *instance, 513 usb_transfer_batch_t *request) { 514 usb_device_request_setup_packet_t * setup_request = 515 (usb_device_request_setup_packet_t*) request->setup_buffer; 416 * @param instance Root hub instance 417 * @param request Structure containing both request and response information 418 * @return Error code 419 */ 420 int get_descriptor(rh_t *instance, usb_transfer_batch_t *request) 421 { 422 assert(instance); 423 assert(request); 424 425 const usb_device_request_setup_packet_t *setup_request = 426 (usb_device_request_setup_packet_t *) request->setup_buffer; 516 427 size_t size; 517 const void * result_descriptor = NULL;428 const void *descriptor = NULL; 518 429 const uint16_t setup_request_value = setup_request->value_high; 519 430 //(setup_request->value_low << 8); 520 switch (setup_request_value) { 521 case USB_DESCTYPE_HUB: 522 { 523 usb_log_debug2("USB_DESCTYPE_HUB\n"); 524 result_descriptor = instance->hub_descriptor; 525 size = instance->descriptor_size; 526 break; 527 } 528 case USB_DESCTYPE_DEVICE: 529 { 530 usb_log_debug2("USB_DESCTYPE_DEVICE\n"); 531 result_descriptor = &ohci_rh_device_descriptor; 532 size = sizeof (ohci_rh_device_descriptor); 533 break; 534 } 535 case USB_DESCTYPE_CONFIGURATION: 536 { 537 usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n"); 538 result_descriptor = instance->descriptors.configuration; 539 size = instance->descriptors.configuration_size; 540 break; 541 } 542 case USB_DESCTYPE_INTERFACE: 543 { 544 usb_log_debug2("USB_DESCTYPE_INTERFACE\n"); 545 result_descriptor = &ohci_rh_iface_descriptor; 546 size = sizeof (ohci_rh_iface_descriptor); 547 break; 548 } 549 case USB_DESCTYPE_ENDPOINT: 550 { 551 usb_log_debug2("USB_DESCTYPE_ENDPOINT\n"); 552 result_descriptor = &ohci_rh_ep_descriptor; 553 size = sizeof (ohci_rh_ep_descriptor); 554 break; 555 } 556 default: 557 { 558 usb_log_debug2("USB_DESCTYPE_EINVAL %d \n", 559 setup_request->value); 560 usb_log_debug2("\ttype %d\n\trequest %d\n\tvalue " 561 "%d\n\tindex %d\n\tlen %d\n ", 562 setup_request->request_type, 563 setup_request->request, 564 setup_request_value, 565 setup_request->index, 566 setup_request->length 567 ); 568 return EINVAL; 569 } 431 switch (setup_request_value) 432 { 433 case USB_DESCTYPE_HUB: 434 usb_log_debug2("USB_DESCTYPE_HUB\n"); 435 /* Hub descriptor was generated locally */ 436 descriptor = instance->descriptors.hub; 437 size = instance->hub_descriptor_size; 438 break; 439 440 case USB_DESCTYPE_DEVICE: 441 usb_log_debug2("USB_DESCTYPE_DEVICE\n"); 442 /* Device descriptor is shared (No one should ask for it)*/ 443 descriptor = &ohci_rh_device_descriptor; 444 size = sizeof(ohci_rh_device_descriptor); 445 break; 446 447 case USB_DESCTYPE_CONFIGURATION: 448 usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n"); 449 /* Start with configuration and add others depending on 450 * request size */ 451 descriptor = &instance->descriptors; 452 size = instance->descriptors.configuration.total_length; 453 break; 454 455 case USB_DESCTYPE_INTERFACE: 456 usb_log_debug2("USB_DESCTYPE_INTERFACE\n"); 457 /* Use local interface descriptor. There is one and it 458 * might be modified */ 459 descriptor = &instance->descriptors.interface; 460 size = sizeof(instance->descriptors.interface); 461 break; 462 463 case USB_DESCTYPE_ENDPOINT: 464 /* Use local endpoint descriptor. There is one 465 * it might have max_packet_size field modified*/ 466 usb_log_debug2("USB_DESCTYPE_ENDPOINT\n"); 467 descriptor = &instance->descriptors.endpoint; 468 size = sizeof(instance->descriptors.endpoint); 469 break; 470 471 default: 472 usb_log_debug2("USB_DESCTYPE_EINVAL %d \n" 473 "\ttype %d\n\trequest %d\n\tvalue " 474 "%d\n\tindex %d\n\tlen %d\n ", 475 setup_request->value, 476 setup_request->request_type, setup_request->request, 477 setup_request_value, setup_request->index, 478 setup_request->length); 479 return EINVAL; 570 480 } 571 481 if (request->buffer_size < size) { 572 482 size = request->buffer_size; 573 483 } 574 request->transfered_size = size; 575 memcpy(request->data_buffer, result_descriptor, size); 576 577 return EOK; 578 } 579 /*----------------------------------------------------------------------------*/ 580 581 /** 582 * answer to get configuration request 583 * 584 * Root hub works independently on the configuration. 585 * @param instance root hub instance 586 * @param request structure containing both request and response information 587 * @return error code 588 */ 589 static int process_get_configuration_request(rh_t *instance, 590 usb_transfer_batch_t *request) { 591 //set and get configuration requests do not have any meaning, only dummy 592 //values are returned 593 if (request->buffer_size != 1) 594 return EINVAL; 595 request->data_buffer[0] = 1; 596 request->transfered_size = 1; 597 598 return EOK; 599 } 600 /*----------------------------------------------------------------------------*/ 601 602 /** 603 * process feature-enabling request on hub 604 * 605 * @param instance root hub instance 606 * @param feature feature selector 607 * @return error code 608 */ 609 static int process_hub_feature_set_request(rh_t *instance, 610 uint16_t feature) { 611 if (!((1 << feature) & hub_set_feature_valid_mask)) 612 return EINVAL; 613 if (feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER) 614 feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16; 615 instance->registers->rh_status = 616 (instance->registers->rh_status | (1 << feature)) 617 & (~hub_clear_feature_by_writing_one_mask); 618 619 return EOK; 620 } 621 /*----------------------------------------------------------------------------*/ 622 623 /** 624 * process feature-disabling request on hub 625 * 626 * @param instance root hub instance 627 * @param feature feature selector 628 * @return error code 629 */ 630 static int process_hub_feature_clear_request(rh_t *instance, 631 uint16_t feature) { 632 if (!((1 << feature) & hub_clear_feature_valid_mask)) 633 return EINVAL; 634 //is the feature cleared directly? 635 if ((1 << feature) & hub_set_feature_direct_mask) { 636 instance->registers->rh_status = 637 (instance->registers->rh_status & (~(1 << feature))) 638 & (~hub_clear_feature_by_writing_one_mask); 639 } else {//the feature is cleared by writing '1' 640 641 instance->registers->rh_status = 642 (instance->registers->rh_status 643 & (~hub_clear_feature_by_writing_one_mask)) 644 | (1 << feature); 645 } 646 return EOK; 647 } 648 /*----------------------------------------------------------------------------*/ 649 484 485 memcpy(request->data_buffer, descriptor, size); 486 TRANSFER_OK(size); 487 } 488 /*----------------------------------------------------------------------------*/ 650 489 /** 651 490 * process feature-enabling request on hub … … 657 496 * @return error code 658 497 */ 659 static int process_port_feature_set_request(rh_t *instance, 660 uint16_t feature, uint16_t port){661 if (!((1 << feature) & port_set_feature_valid_mask))662 return EINVAL; 498 int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port) 499 { 500 assert(instance); 501 663 502 if (port < 1 || port > instance->port_count) 664 503 return EINVAL; 665 instance->registers->rh_port_status[port - 1] = 666 (instance->registers->rh_port_status[port - 1] | (1 << feature)) 667 & (~port_clear_feature_valid_mask); 668 return EOK; 669 } 670 /*----------------------------------------------------------------------------*/ 671 672 /** 673 * process feature-disabling request on hub 504 505 switch (feature) 506 { 507 case USB_HUB_FEATURE_PORT_POWER: //8 508 /* No power switching */ 509 if (instance->registers->rh_desc_a & RHDA_NPS_FLAG) 510 return EOK; 511 /* Ganged power switching */ 512 if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) { 513 instance->registers->rh_status = RHS_SET_GLOBAL_POWER; 514 return EOK; 515 } 516 case USB_HUB_FEATURE_PORT_ENABLE: //1 517 case USB_HUB_FEATURE_PORT_SUSPEND: //2 518 case USB_HUB_FEATURE_PORT_RESET: //4 519 /* Nice thing is that these shifts correspond to the position 520 * of control bits in register */ 521 instance->registers->rh_port_status[port - 1] = (1 << feature); 522 return EOK; 523 default: 524 return ENOTSUP; 525 } 526 } 527 /*----------------------------------------------------------------------------*/ 528 /** 529 * Process feature clear request. 674 530 * 675 531 * @param instance root hub instance … … 679 535 * @return error code 680 536 */ 681 static int process_port_feature_clear_request(rh_t *instance, 682 uint16_t feature, uint16_t port){683 if (!((1 << feature) & port_clear_feature_valid_mask))684 return EINVAL; 537 int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port) 538 { 539 assert(instance); 540 685 541 if (port < 1 || port > instance->port_count) 686 542 return EINVAL; 687 if (feature == USB_HUB_FEATURE_PORT_POWER) 688 feature = USB_HUB_FEATURE_PORT_LOW_SPEED; 689 if (feature == USB_HUB_FEATURE_PORT_SUSPEND) 690 feature = USB_HUB_FEATURE_PORT_OVER_CURRENT; 691 instance->registers->rh_port_status[port - 1] = 692 (instance->registers->rh_port_status[port - 1] 693 & (~port_clear_feature_valid_mask)) 694 | (1 << feature); 695 696 return EOK; 697 } 698 /*----------------------------------------------------------------------------*/ 699 700 /** 701 * register address to this device 702 * 703 * @param instance root hub instance 704 * @param address new address 705 * @return error code 706 */ 707 static int process_address_set_request(rh_t *instance, 708 uint16_t address) { 709 return ENOTSUP; 710 } 711 /*----------------------------------------------------------------------------*/ 712 713 /** 714 * process one of requests that requere output data 715 * 716 * Request can be one of USB_DEVREQ_GET_STATUS, USB_DEVREQ_GET_DESCRIPTOR or 717 * USB_DEVREQ_GET_CONFIGURATION. 718 * @param instance root hub instance 719 * @param request structure containing both request and response information 720 * @return error code 721 */ 722 static int process_request_with_output(rh_t *instance, 723 usb_transfer_batch_t *request) { 724 usb_device_request_setup_packet_t * setup_request = 725 (usb_device_request_setup_packet_t*) request->setup_buffer; 726 if (setup_request->request == USB_DEVREQ_GET_STATUS) { 727 usb_log_debug("USB_DEVREQ_GET_STATUS\n"); 728 return process_get_status_request(instance, request); 729 } 730 if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR) { 731 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n"); 732 return process_get_descriptor_request(instance, request); 733 } 734 if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION) { 735 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n"); 736 737 return process_get_configuration_request(instance, request); 738 } 739 return ENOTSUP; 740 } 741 /*----------------------------------------------------------------------------*/ 742 743 /** 744 * process one of requests that carry input data 745 * 746 * Request can be one of USB_DEVREQ_SET_DESCRIPTOR or 747 * USB_DEVREQ_SET_CONFIGURATION. 748 * @param instance root hub instance 749 * @param request structure containing both request and response information 750 * @return error code 751 */ 752 static int process_request_with_input(rh_t *instance, 753 usb_transfer_batch_t *request) { 754 usb_device_request_setup_packet_t * setup_request = 755 (usb_device_request_setup_packet_t*) request->setup_buffer; 756 request->transfered_size = 0; 757 if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR) { 543 544 /* Enabled features to clear: see page 269 of USB specs */ 545 switch (feature) 546 { 547 case USB_HUB_FEATURE_PORT_POWER: //8 548 /* No power switching */ 549 if (instance->registers->rh_desc_a & RHDA_NPS_FLAG) 550 return ENOTSUP; 551 /* Ganged power switching */ 552 if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) { 553 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 554 return EOK; 555 } 556 instance->registers->rh_port_status[port - 1] = 557 RHPS_CLEAR_PORT_POWER; 558 return EOK; 559 560 case USB_HUB_FEATURE_PORT_ENABLE: //1 561 instance->registers->rh_port_status[port - 1] = 562 RHPS_CLEAR_PORT_ENABLE; 563 return EOK; 564 565 case USB_HUB_FEATURE_PORT_SUSPEND: //2 566 instance->registers->rh_port_status[port - 1] = 567 RHPS_CLEAR_PORT_SUSPEND; 568 return EOK; 569 570 case USB_HUB_FEATURE_C_PORT_CONNECTION: //16 571 case USB_HUB_FEATURE_C_PORT_ENABLE: //17 572 case USB_HUB_FEATURE_C_PORT_SUSPEND: //18 573 case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: //19 574 case USB_HUB_FEATURE_C_PORT_RESET: //20 575 /* Nice thing is that these shifts correspond to the position 576 * of control bits in register */ 577 instance->registers->rh_port_status[port - 1] = (1 << feature); 578 return EOK; 579 580 default: 758 581 return ENOTSUP; 759 582 } 760 if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION) { 761 //set and get configuration requests do not have any meaning, 762 //only dummy values are returned 763 764 return EOK; 765 } 766 return ENOTSUP; 767 } 768 /*----------------------------------------------------------------------------*/ 769 583 } 584 /*----------------------------------------------------------------------------*/ 770 585 /** 771 586 * process one of requests that do not request nor carry additional data … … 777 592 * @return error code 778 593 */ 779 static int process_request_without_data(rh_t *instance, 780 usb_transfer_batch_t *request) { 781 usb_device_request_setup_packet_t * setup_request = 782 (usb_device_request_setup_packet_t*) request->setup_buffer; 783 request->transfered_size = 0; 784 if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE) { 785 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) { 786 usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n"); 787 return process_hub_feature_clear_request(instance, 788 setup_request->value); 789 } 790 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) { 791 usb_log_debug2("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 792 return process_port_feature_clear_request(instance, 793 setup_request->value, 794 setup_request->index); 795 } 796 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n", 594 int set_feature(rh_t *instance, usb_transfer_batch_t *request) 595 { 596 assert(instance); 597 assert(request); 598 599 const usb_device_request_setup_packet_t *setup_request = 600 (usb_device_request_setup_packet_t *) request->setup_buffer; 601 switch (setup_request->request_type) 602 { 603 case USB_HUB_REQ_TYPE_SET_PORT_FEATURE: 604 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 605 return set_feature_port(instance, 606 setup_request->value, setup_request->index); 607 608 case USB_HUB_REQ_TYPE_SET_HUB_FEATURE: 609 /* Chapter 11.16.2 specifies that hub can be recipient 610 * only for C_HUB_LOCAL_POWER and C_HUB_OVER_CURRENT 611 * features. It makes no sense to SET either. */ 612 usb_log_error("Invalid HUB set feature request.\n"); 613 return ENOTSUP; 614 default: 615 usb_log_error("Invalid set feature request type: %d\n", 797 616 setup_request->request_type); 798 617 return EINVAL; 799 618 } 800 if (setup_request->request == USB_DEVREQ_SET_FEATURE) { 801 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) { 802 usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n"); 803 return process_hub_feature_set_request(instance, 804 setup_request->value); 619 } 620 /*----------------------------------------------------------------------------*/ 621 /** 622 * process one of requests that do not request nor carry additional data 623 * 624 * Request can be one of USB_DEVREQ_CLEAR_FEATURE, USB_DEVREQ_SET_FEATURE or 625 * USB_DEVREQ_SET_ADDRESS. 626 * @param instance root hub instance 627 * @param request structure containing both request and response information 628 * @return error code 629 */ 630 int clear_feature(rh_t *instance, usb_transfer_batch_t *request) 631 { 632 assert(instance); 633 assert(request); 634 635 const usb_device_request_setup_packet_t *setup_request = 636 (usb_device_request_setup_packet_t *) request->setup_buffer; 637 request->transfered_size = 0; 638 switch (setup_request->request_type) 639 { 640 case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE: 641 usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n"); 642 return clear_feature_port(instance, 643 setup_request->value, setup_request->index); 644 645 case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE: 646 usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE\n"); 647 /* 648 * Chapter 11.16.2 specifies that only C_HUB_LOCAL_POWER and 649 * C_HUB_OVER_CURRENT are supported. C_HUB_OVER_CURRENT is represented 650 * by OHCI RHS_OCIC_FLAG. C_HUB_LOCAL_POWER is not supported 651 * as root hubs do not support local power status feature. 652 * (OHCI pg. 127) */ 653 if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) { 654 instance->registers->rh_status = RHS_OCIC_FLAG; 655 TRANSFER_OK(0); 805 656 } 806 if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) { 807 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 808 return process_port_feature_set_request(instance, 809 setup_request->value, 810 setup_request->index); 811 } 812 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n", 657 default: 658 usb_log_error("Invalid clear feature request type: %d\n", 813 659 setup_request->request_type); 814 660 return EINVAL; 815 661 } 816 if (setup_request->request == USB_DEVREQ_SET_ADDRESS) { 817 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n"); 818 return process_address_set_request(instance, 819 setup_request->value); 820 } 821 usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n", 822 setup_request->request_type); 823 824 return ENOTSUP; 825 } 826 /*----------------------------------------------------------------------------*/ 827 828 /** 829 * process hub control request 662 } 663 /*----------------------------------------------------------------------------*/ 664 /** 665 * Process hub control request. 830 666 * 831 667 * If needed, writes answer into the request structure. … … 844 680 * @return error code 845 681 */ 846 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) { 682 int control_request(rh_t *instance, usb_transfer_batch_t *request) 683 { 684 assert(instance); 685 assert(request); 686 847 687 if (!request->setup_buffer) { 848 usb_log_error(" root hub received empty transaction?");688 usb_log_error("Root hub received empty transaction!"); 849 689 return EINVAL; 850 690 } 851 int opResult; 852 if (sizeof 691 692 if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) { 853 693 usb_log_error("Setup packet too small\n"); 854 return EINVAL; 855 } 856 usb_log_debug("CTRL packet: %s.\n", 857 usb_debug_str_buffer( 858 (const uint8_t *) request->setup_buffer, 8, 8)); 859 usb_device_request_setup_packet_t * setup_request = 860 (usb_device_request_setup_packet_t*) 861 request->setup_buffer; 862 switch (setup_request->request) { 863 case USB_DEVREQ_GET_STATUS: 864 case USB_DEVREQ_GET_DESCRIPTOR: 865 case USB_DEVREQ_GET_CONFIGURATION: 866 usb_log_debug2("Processing request with output\n"); 867 opResult = process_request_with_output( 868 instance, request); 869 break; 870 case USB_DEVREQ_CLEAR_FEATURE: 871 case USB_DEVREQ_SET_FEATURE: 872 case USB_DEVREQ_SET_ADDRESS: 873 usb_log_debug2("Processing request without " 874 "additional data\n"); 875 opResult = process_request_without_data( 876 instance, request); 877 break; 878 case USB_DEVREQ_SET_DESCRIPTOR: 879 case USB_DEVREQ_SET_CONFIGURATION: 880 usb_log_debug2("Processing request with input\n"); 881 opResult = process_request_with_input( 882 instance, request); 883 884 break; 885 default: 886 usb_log_warning("Received unsupported request: %d.\n", 887 setup_request->request); 888 opResult = ENOTSUP; 889 } 890 return opResult; 891 } 892 /*----------------------------------------------------------------------------*/ 893 894 /** 895 * process hanging interrupt request 896 * 897 * If an interrupt transfer has been received and there was no change, 898 * the driver stores the transfer information and waits for change to occcur. 899 * This routine is called when that happens and it finalizes the interrupt 900 * transfer. 901 * 902 * @param instance hub instance 903 * @param request batch request to be processed 904 * 905 * @return 906 */ 907 static int process_interrupt_mask_in_instance(rh_t *instance, 908 usb_transfer_batch_t * request) { 909 memcpy(request->data_buffer, instance->interrupt_buffer, 910 instance->interrupt_mask_size); 911 request->transfered_size = instance->interrupt_mask_size; 912 instance->unfinished_interrupt_transfer = NULL; 913 usb_transfer_batch_finish_error(request, EOK); 914 915 return EOK; 916 } 917 918 /*----------------------------------------------------------------------------*/ 919 920 /** 921 * return whether the buffer is full of zeros 922 * 923 * Convenience function. 924 * @param buffer 925 * @param size 926 * @return 927 */ 928 static bool is_zeros(void *buffer, size_t size) { 929 if (!buffer) return true; 930 if (!size) return true; 931 size_t i; 932 for (i = 0; i < size; ++i) { 933 if (((char*) buffer)[i]) 934 return false; 935 } 936 return true; 694 return EOVERFLOW; 695 } 696 697 usb_log_debug2("CTRL packet: %s.\n", 698 usb_debug_str_buffer((uint8_t *) request->setup_buffer, 8, 8)); 699 const usb_device_request_setup_packet_t *setup_request = 700 (usb_device_request_setup_packet_t *) request->setup_buffer; 701 switch (setup_request->request) 702 { 703 case USB_DEVREQ_GET_STATUS: 704 usb_log_debug("USB_DEVREQ_GET_STATUS\n"); 705 return get_status(instance, request); 706 707 case USB_DEVREQ_GET_DESCRIPTOR: 708 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n"); 709 return get_descriptor(instance, request); 710 711 case USB_DEVREQ_GET_CONFIGURATION: 712 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n"); 713 if (request->buffer_size != 1) 714 return EINVAL; 715 request->data_buffer[0] = 1; 716 TRANSFER_OK(1); 717 718 case USB_DEVREQ_CLEAR_FEATURE: 719 usb_log_debug2("Processing request without " 720 "additional data\n"); 721 return clear_feature(instance, request); 722 case USB_DEVREQ_SET_FEATURE: 723 usb_log_debug2("Processing request without " 724 "additional data\n"); 725 return set_feature(instance, request); 726 727 case USB_DEVREQ_SET_ADDRESS: 728 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n"); 729 instance->address = setup_request->value; 730 TRANSFER_OK(0); 731 732 case USB_DEVREQ_SET_CONFIGURATION: 733 usb_log_debug("USB_DEVREQ_SET_CONFIGURATION\n"); 734 /* We don't need to do anything */ 735 TRANSFER_OK(0); 736 737 case USB_DEVREQ_SET_DESCRIPTOR: /* Not supported by OHCI RH */ 738 default: 739 usb_log_error("Received unsupported request: %d.\n", 740 setup_request->request); 741 return ENOTSUP; 742 } 937 743 } 938 744 -
uspace/drv/bus/usb/ohci/root_hub.h
r3e5c48c9 r159100a 41 41 #include "batch.h" 42 42 43 #define HUB_DESCRIPTOR_MAX_SIZE (7 + 2 + 2) 44 43 45 /** 44 46 * ohci root hub representation … … 51 53 /** hub port count */ 52 54 size_t port_count; 53 /** hubs descriptors */54 usb_device_descriptors_t descriptors;55 55 /** interrupt transfer waiting for an actual interrupt to occur */ 56 usb_transfer_batch_t * unfinished_interrupt_transfer; 57 /** pre-allocated interrupt mask 58 * 59 * This is allocated when initializing instance, so that memory 60 * allocation is not needed when processing request. Buffer is used for 61 * interrupt bitmask. 62 */ 63 uint8_t * interrupt_buffer; 56 usb_transfer_batch_t *unfinished_interrupt_transfer; 64 57 /** size of interrupt buffer */ 65 58 size_t interrupt_mask_size; 66 /** instance`s descriptor*/ 67 uint8_t * hub_descriptor; 59 /** Descriptors */ 60 struct { 61 usb_standard_configuration_descriptor_t configuration; 62 usb_standard_interface_descriptor_t interface; 63 usb_standard_endpoint_descriptor_t endpoint; 64 uint8_t hub[HUB_DESCRIPTOR_MAX_SIZE]; 65 } __attribute__ ((packed)) descriptors; 68 66 /** size of hub descriptor */ 69 size_t descriptor_size; 70 67 size_t hub_descriptor_size; 71 68 72 69 } rh_t; 73 70 74 intrh_init(rh_t *instance, ohci_regs_t *regs);71 void rh_init(rh_t *instance, ohci_regs_t *regs); 75 72 76 intrh_request(rh_t *instance, usb_transfer_batch_t *request);73 void rh_request(rh_t *instance, usb_transfer_batch_t *request); 77 74 78 75 void rh_interrupt(rh_t *instance); -
uspace/drv/bus/usb/uhci/hc.c
r3e5c48c9 r159100a 47 47 (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT) 48 48 49 static const irq_cmd_t uhci_irq_commands[] = 50 { 51 { .cmd = CMD_PIO_READ_16, .dstarg = 1, .addr = NULL/*filled later*/}, 52 { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, 53 .value = UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS }, 54 { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 }, 55 { .cmd = CMD_PIO_WRITE_A_16, .srcarg = 1, .addr = NULL/*filled later*/}, 56 { .cmd = CMD_ACCEPT }, 57 }; 49 58 50 59 static int hc_init_transfer_lists(hc_t *instance); … … 54 63 static int hc_interrupt_emulator(void *arg); 55 64 static int hc_debug_checker(void *arg); 65 66 /*----------------------------------------------------------------------------*/ 67 /** Get number of commands used in IRQ code. 68 * @return Number of commands. 69 */ 70 size_t hc_irq_cmd_count(void) 71 { 72 return sizeof(uhci_irq_commands) / sizeof(irq_cmd_t); 73 } 74 /*----------------------------------------------------------------------------*/ 75 /** Generate IRQ code commands. 76 * @param[out] cmds Place to store the commands. 77 * @param[in] cmd_size Size of the place (bytes). 78 * @param[in] regs Physical address of device's registers. 79 * @param[in] reg_size Size of the register area (bytes). 80 * 81 * @return Error code. 82 */ 83 int hc_get_irq_commands( 84 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size) 85 { 86 if (cmd_size < sizeof(uhci_irq_commands) 87 || reg_size < sizeof(uhci_regs_t)) 88 return EOVERFLOW; 89 90 uhci_regs_t *registers = (uhci_regs_t*)regs; 91 92 memcpy(cmds, uhci_irq_commands, sizeof(uhci_irq_commands)); 93 94 cmds[0].addr = (void*)®isters->usbsts; 95 cmds[3].addr = (void*)®isters->usbsts; 96 return EOK; 97 } 56 98 /*----------------------------------------------------------------------------*/ 57 99 /** Initialize UHCI hc driver structure … … 69 111 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts) 70 112 { 71 assert(reg_size >= sizeof( regs_t));113 assert(reg_size >= sizeof(uhci_regs_t)); 72 114 int ret; 73 115 … … 82 124 83 125 /* allow access to hc control registers */ 84 regs_t *io;126 uhci_regs_t *io; 85 127 ret = pio_enable(regs, reg_size, (void **)&io); 86 CHECK_RET_RETURN(ret, 87 "Failed(%d) to gain access to registers at %p: %s.\n", 88 ret, io, str_error(ret)); 128 CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p: %s.\n", 129 io, str_error(ret)); 89 130 instance->registers = io; 90 usb_log_debug( "Device registers at %p (%zuB) accessible.\n",91 io, reg_size);131 usb_log_debug( 132 "Device registers at %p (%zuB) accessible.\n", io, reg_size); 92 133 93 134 ret = hc_init_mem_structures(instance); 94 135 CHECK_RET_RETURN(ret, 95 "Failed (%d)to initialize UHCI memory structures: %s.\n",96 ret,str_error(ret));136 "Failed to initialize UHCI memory structures: %s.\n", 137 str_error(ret)); 97 138 98 139 hc_init_hw(instance); … … 116 157 { 117 158 assert(instance); 118 regs_t *registers = instance->registers;159 uhci_regs_t *registers = instance->registers; 119 160 120 161 /* Reset everything, who knows what touched it before us */ 121 162 pio_write_16(®isters->usbcmd, UHCI_CMD_GLOBAL_RESET); 122 async_usleep( 10000); /* 10ms according to USB spec*/163 async_usleep(50000); /* 50ms according to USB spec(root hub reset) */ 123 164 pio_write_16(®isters->usbcmd, 0); 124 165 125 /* Reset hc, all states and counters */166 /* Reset hc, all states and counters. Hope that hw is not broken */ 126 167 pio_write_16(®isters->usbcmd, UHCI_CMD_HCRESET); 127 168 do { async_usleep(10); } … … 141 182 } 142 183 143 const uint16_t status= pio_read_16(®isters->usbcmd);144 if ( status!= 0)145 usb_log_warning("Previous command value: %x.\n", status);184 const uint16_t cmd = pio_read_16(®isters->usbcmd); 185 if (cmd != 0) 186 usb_log_warning("Previous command value: %x.\n", cmd); 146 187 147 188 /* Start the hc with large(64B) packet FSBR */ … … 170 211 } else (void) 0 171 212 172 /* Init interrupt code */173 instance->interrupt_code.cmds = instance->interrupt_commands;174 {175 /* Read status register */176 instance->interrupt_commands[0].cmd = CMD_PIO_READ_16;177 instance->interrupt_commands[0].dstarg = 1;178 instance->interrupt_commands[0].addr =179 &instance->registers->usbsts;180 181 /* Test whether we are the interrupt cause */182 instance->interrupt_commands[1].cmd = CMD_BTEST;183 instance->interrupt_commands[1].value =184 UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS;185 instance->interrupt_commands[1].srcarg = 1;186 instance->interrupt_commands[1].dstarg = 2;187 188 /* Predicate cleaning and accepting */189 instance->interrupt_commands[2].cmd = CMD_PREDICATE;190 instance->interrupt_commands[2].value = 2;191 instance->interrupt_commands[2].srcarg = 2;192 193 /* Write clean status register */194 instance->interrupt_commands[3].cmd = CMD_PIO_WRITE_A_16;195 instance->interrupt_commands[3].srcarg = 1;196 instance->interrupt_commands[3].addr =197 &instance->registers->usbsts;198 199 /* Accept interrupt */200 instance->interrupt_commands[4].cmd = CMD_ACCEPT;201 202 instance->interrupt_code.cmdcount = UHCI_NEEDED_IRQ_COMMANDS;203 }204 205 213 /* Init transfer lists */ 206 214 int ret = hc_init_transfer_lists(instance); 207 CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n");215 CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n"); 208 216 usb_log_debug("Initialized transfer lists.\n"); 209 210 /* Init USB frame list page*/211 instance->frame_list = get_page();212 ret = instance->frame_list ? EOK : ENOMEM;213 CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");214 usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);215 216 /* Set all frames to point to the first queue head */217 const uint32_t queue = LINK_POINTER_QH(218 addr_to_phys(instance->transfers_interrupt.queue_head));219 220 unsigned i = 0;221 for(; i < UHCI_FRAME_LIST_COUNT; ++i) {222 instance->frame_list[i] = queue;223 }224 217 225 218 /* Init device keeper */ 226 219 usb_device_keeper_init(&instance->manager); 227 usb_log_debug("Initialized device manager.\n");220 usb_log_debug("Initialized device keeper.\n"); 228 221 229 222 ret = usb_endpoint_manager_init(&instance->ep_manager, … … 232 225 str_error(ret)); 233 226 227 /* Init USB frame list page*/ 228 instance->frame_list = get_page(); 229 if (!instance->frame_list) { 230 usb_log_error("Failed to get frame list page.\n"); 231 usb_endpoint_manager_destroy(&instance->ep_manager); 232 return ENOMEM; 233 } 234 usb_log_debug("Initialized frame list at %p.\n", instance->frame_list); 235 236 /* Set all frames to point to the first queue head */ 237 const uint32_t queue = LINK_POINTER_QH( 238 addr_to_phys(instance->transfers_interrupt.queue_head)); 239 unsigned i = 0; 240 for(; i < UHCI_FRAME_LIST_COUNT; ++i) { 241 instance->frame_list[i] = queue; 242 } 243 234 244 return EOK; 235 245 #undef CHECK_RET_RETURN … … 252 262 int ret = transfer_list_init(&instance->transfers_##type, name); \ 253 263 if (ret != EOK) { \ 254 usb_log_error("Failed (%d)to setup %s transfer list: %s.\n", \255 ret,name, str_error(ret)); \264 usb_log_error("Failed to setup %s transfer list: %s.\n", \ 265 name, str_error(ret)); \ 256 266 transfer_list_fini(&instance->transfers_bulk_full); \ 257 267 transfer_list_fini(&instance->transfers_control_full); \ -
uspace/drv/bus/usb/uhci/hc.h
r3e5c48c9 r159100a 84 84 /** SOF modification to match external timers */ 85 85 uint8_t sofmod; 86 } regs_t;86 } uhci_regs_t; 87 87 88 88 #define UHCI_FRAME_LIST_COUNT 1024 … … 100 100 101 101 /** Addresses of I/O registers */ 102 regs_t *registers;102 uhci_regs_t *registers; 103 103 104 104 /** Frame List contains 1024 link pointers */ … … 116 116 /** Pointer table to the above lists, helps during scheduling */ 117 117 transfer_list_t *transfers[2][4]; 118 119 /** Code to be executed in kernel interrupt handler */120 irq_code_t interrupt_code;121 122 /** Commands that form interrupt code */123 irq_cmd_t interrupt_commands[UHCI_NEEDED_IRQ_COMMANDS];124 125 118 /** Fibril periodically checking status register*/ 126 119 fid_t interrupt_emulator; 127 128 120 /** Indicator of hw interrupts availability */ 129 121 bool hw_interrupts; … … 132 124 unsigned hw_failures; 133 125 } hc_t; 134 126 size_t hc_irq_cmd_count(void); 127 int hc_get_irq_commands( 128 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size); 135 129 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts); 136 137 130 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch); 138 139 131 void hc_interrupt(hc_t *instance, uint16_t status); 140 132 -
uspace/drv/bus/usb/uhci/root_hub.c
r3e5c48c9 r159100a 55 55 int ret = asprintf(&match_str, "usb&uhci&root-hub"); 56 56 if (ret < 0) { 57 usb_log_error( 58 "Failed(%d) to create root hub match string: %s.\n", 59 ret, str_error(ret)); 57 usb_log_error("Failed to create root hub match string: %s.\n", 58 str_error(ret)); 60 59 return ret; 61 60 } … … 65 64 if (ret != EOK) { 66 65 free(match_str); 67 usb_log_error("Failed (%d)to add root hub match id: %s\n",68 ret,str_error(ret));66 usb_log_error("Failed to add root hub match id: %s\n", 67 str_error(ret)); 69 68 return ret; 70 69 } -
uspace/drv/bus/usb/uhci/uhci.c
r3e5c48c9 r159100a 64 64 { 65 65 assert(dev); 66 assert(dev->driver_data);67 66 return dev->driver_data; 68 67 } … … 78 77 assert(dev); 79 78 uhci_t *uhci = dev_to_uhci(dev); 80 hc_t *hc = &uhci->hc; 79 if (!uhci) { 80 usb_log_error("Interrupt on not yet initialized device.\n"); 81 return; 82 } 81 83 const uint16_t status = IPC_GET_ARG1(*call); 82 assert(hc); 83 hc_interrupt(hc, status); 84 hc_interrupt(&uhci->hc, status); 84 85 } 85 86 /*----------------------------------------------------------------------------*/ … … 192 193 } \ 193 194 free(instance); \ 195 device->driver_data = NULL; \ 194 196 usb_log_error(message); \ 195 197 return ret; \ … … 222 224 ret = pci_disable_legacy(device); 223 225 CHECK_RET_DEST_FREE_RETURN(ret, 224 "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret)); 226 "Failed to disable legacy USB: %s.\n", str_error(ret)); 227 228 const size_t cmd_count = hc_irq_cmd_count(); 229 irq_cmd_t irq_cmds[cmd_count]; 230 ret = 231 hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size); 232 CHECK_RET_DEST_FREE_RETURN(ret, 233 "Failed to generate IRQ commands: %s.\n", str_error(ret)); 234 235 irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds }; 236 237 /* Register handler to avoid interrupt lockup */ 238 ret = register_interrupt_handler(device, irq, irq_handler, &irq_code); 239 CHECK_RET_DEST_FREE_RETURN(ret, 240 "Failed to register interrupt handler: %s.\n", str_error(ret)); 225 241 226 242 bool interrupts = false; 227 #ifdef CONFIG_USBHC_NO_INTERRUPTS228 usb_log_warning("Interrupts disabled in OS config, " \229 "falling back to polling.\n");230 #else231 243 ret = pci_enable_interrupts(device); 232 244 if (ret != EOK) { 233 usb_log_warning("Failed to enable interrupts: %s.\n", 234 str_error(ret)); 235 usb_log_info("HW interrupts not available, " \ 236 "falling back to polling.\n"); 245 usb_log_warning("Failed to enable interrupts: %s." 246 " Falling back to polling.\n", str_error(ret)); 237 247 } else { 238 248 usb_log_debug("Hw interrupts enabled.\n"); 239 249 interrupts = true; 240 250 } 241 #endif242 243 251 244 252 ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts); 245 253 CHECK_RET_DEST_FREE_RETURN(ret, 246 "Failed(%d) to init uhci_hcd: %s.\n", ret, str_error(ret)); 254 "Failed to init uhci_hcd: %s.\n", str_error(ret)); 255 256 device->driver_data = instance; 247 257 248 258 #define CHECK_RET_FINI_RETURN(ret, message...) \ … … 253 263 } else (void)0 254 264 255 /* It does no harm if we register this on polling */256 ret = register_interrupt_handler(device, irq, irq_handler,257 &instance->hc.interrupt_code);258 CHECK_RET_FINI_RETURN(ret,259 "Failed(%d) to register interrupt handler: %s.\n",260 ret, str_error(ret));261 262 265 ret = ddf_fun_bind(instance->hc_fun); 263 CHECK_RET_FINI_RETURN(ret, 264 "Failed(%d) to bind UHCI device function: %s.\n", 265 ret, str_error(ret)); 266 CHECK_RET_FINI_RETURN(ret, "Failed to bind UHCI device function: %s.\n", 267 str_error(ret)); 266 268 267 269 ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME); … … 272 274 (uintptr_t)instance->hc.registers + 0x10, 4); 273 275 CHECK_RET_FINI_RETURN(ret, 274 "Failed (%d) to setup UHCI root hub: %s.\n", ret, str_error(ret));276 "Failed to setup UHCI root hub: %s.\n", str_error(ret)); 275 277 276 278 ret = ddf_fun_bind(instance->rh_fun); 277 279 CHECK_RET_FINI_RETURN(ret, 278 "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret)); 279 280 device->driver_data = instance; 280 "Failed to register UHCI root hub: %s.\n", str_error(ret)); 281 281 282 return EOK; 282 283 #undef CHECK_RET_FINI_RETURN -
uspace/drv/bus/usb/usbhub/usbhub.c
r3e5c48c9 r159100a 220 220 * @return error code 221 221 */ 222 static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) { 222 int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) 223 { 223 224 // get hub descriptor 224 usb_log_debug(" Creating serializeddescriptor\n");225 usb_log_debug("Retrieving descriptor\n"); 225 226 uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE]; 226 usb_hub_descriptor_t * descriptor;227 227 int opResult; 228 228 … … 234 234 235 235 if (opResult != EOK) { 236 usb_log_error("Failed when receiving hub descriptor, " 237 "%s\n", 238 str_error(opResult)); 239 free(serialized_descriptor); 236 usb_log_error("Failed to receive hub descriptor: %s.\n", 237 str_error(opResult)); 240 238 return opResult; 241 239 } 242 usb_log_debug2("Deserializing descriptor\n"); 243 descriptor = usb_create_deserialized_hub_desriptor( 244 serialized_descriptor); 245 if (descriptor == NULL) { 246 usb_log_warning("could not deserialize descriptor \n"); 247 return ENOMEM; 248 } 249 usb_log_debug("setting port count to %d\n", descriptor->ports_count); 250 hub_info->port_count = descriptor->ports_count; 251 bool is_power_switched = 252 ((descriptor->hub_characteristics & 1) == 0); 253 bool has_individual_port_powering = 254 ((descriptor->hub_characteristics & 1) != 0); 255 hub_info->ports = malloc( 256 sizeof (usb_hub_port_t) * (hub_info->port_count + 1)); 240 usb_log_debug2("Parsing descriptor\n"); 241 usb_hub_descriptor_t descriptor; 242 opResult = usb_deserialize_hub_desriptor( 243 serialized_descriptor, received_size, &descriptor); 244 if (opResult != EOK) { 245 usb_log_error("Could not parse descriptor: %s\n", 246 str_error(opResult)); 247 return opResult; 248 } 249 usb_log_debug("Setting port count to %d.\n", descriptor.ports_count); 250 hub_info->port_count = descriptor.ports_count; 251 252 hub_info->ports = 253 malloc(sizeof(usb_hub_port_t) * (hub_info->port_count + 1)); 257 254 if (!hub_info->ports) { 258 255 return ENOMEM; 259 256 } 257 260 258 size_t port; 261 259 for (port = 0; port < hub_info->port_count + 1; ++port) { 262 260 usb_hub_port_init(&hub_info->ports[port]); 263 261 } 262 263 const bool is_power_switched = 264 !(descriptor.hub_characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG); 264 265 if (is_power_switched) { 265 266 usb_log_debug("Hub power switched\n"); 266 267 if (!has_individual_port_powering) { 268 //this setting actually makes no difference 269 usb_log_debug("Hub has global powering\n"); 270 } 267 const bool per_port_power = descriptor.hub_characteristics 268 & HUB_CHAR_POWER_PER_PORT_FLAG; 271 269 272 270 for (port = 1; port <= hub_info->port_count; ++port) { 273 271 usb_log_debug("Powering port %zu.\n", port); 274 opResult = usb_hub_set_port_feature(hub_info->control_pipe, 272 opResult = usb_hub_set_port_feature( 273 hub_info->control_pipe, 275 274 port, USB_HUB_FEATURE_PORT_POWER); 276 275 if (opResult != EOK) { 277 276 usb_log_error("Cannot power on port %zu: %s.\n", 278 277 port, str_error(opResult)); 278 } else { 279 if (!per_port_power) { 280 usb_log_debug( 281 "Ganged power switching mode, " 282 "one port is enough.\n"); 283 break; 284 } 279 285 } 280 286 } … … 283 289 usb_log_debug("Power not switched, not going to be powered\n"); 284 290 } 285 usb_log_debug2("Freeing data\n");286 free(descriptor);287 291 return EOK; 288 292 } -
uspace/drv/bus/usb/usbhub/usbhub_private.h
r3e5c48c9 r159100a 171 171 void * serialized_descriptor); 172 172 173 usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor( 174 void * serialized_descriptor); 175 176 void usb_deserialize_hub_desriptor(void * serialized_descriptor, 177 usb_hub_descriptor_t * descriptor); 173 int usb_deserialize_hub_desriptor( 174 void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor); 178 175 179 176 -
uspace/drv/bus/usb/usbhub/utils.c
r3e5c48c9 r159100a 110 110 } 111 111 112 /*----------------------------------------------------------------------------*/ 112 113 /** 113 * create deserialized desriptor structure out of serialized descriptor114 * Deserialize descriptor into given pointer 114 115 * 115 * The serialized descriptor must be proper usb hub descriptor,116 * otherwise an eerror might occur.117 *118 * @param sdescriptor serialized descriptor119 * @return newly created deserialized descriptor pointer120 */121 usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(122 void *serialized_descriptor) {123 uint8_t * sdescriptor = serialized_descriptor;124 125 if (sdescriptor[1] != USB_DESCTYPE_HUB) {126 usb_log_warning("trying to deserialize wrong descriptor %x\n",127 sdescriptor[1]);128 return NULL;129 }130 131 usb_hub_descriptor_t * result = malloc(sizeof (usb_hub_descriptor_t));132 if (result)133 usb_deserialize_hub_desriptor(serialized_descriptor, result);134 return result;135 }136 137 /**138 * deserialize descriptor into given pointer139 *140 116 * @param serialized_descriptor 141 117 * @param descriptor 142 118 * @return 143 119 */ 144 void usb_deserialize_hub_desriptor( 145 void * serialized_descriptor, usb_hub_descriptor_t *descriptor) { 120 int usb_deserialize_hub_desriptor( 121 void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor) 122 { 146 123 uint8_t * sdescriptor = serialized_descriptor; 124 125 if (sdescriptor[1] != USB_DESCTYPE_HUB) { 126 usb_log_error("Trying to deserialize wrong descriptor %x\n", 127 sdescriptor[1]); 128 return EINVAL; 129 } 130 if (size < 7) { 131 usb_log_error("Serialized descriptor too small.\n"); 132 return EOVERFLOW; 133 } 134 147 135 descriptor->ports_count = sdescriptor[2]; 148 /// @fixme handling of endianness?? 149 descriptor->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3]; 136 descriptor->hub_characteristics = sdescriptor[3] + 256 * sdescriptor[4]; 150 137 descriptor->pwr_on_2_good_time = sdescriptor[5]; 151 138 descriptor->current_requirement = sdescriptor[6]; 152 size_t var_size = (descriptor->ports_count + 7) / 8;139 const size_t var_size = (descriptor->ports_count + 7) / 8; 153 140 //descriptor->devices_removable = (uint8_t*) malloc(var_size); 154 141 155 size_t i; 156 for (i = 0; i < var_size; ++i) { 142 if (size < (7 + var_size)) { 143 usb_log_error("Serialized descriptor too small.\n"); 144 return EOVERFLOW; 145 } 146 size_t i = 0; 147 for (; i < var_size; ++i) { 157 148 descriptor->devices_removable[i] = sdescriptor[7 + i]; 158 149 } 150 return EOK; 159 151 } 160 152 /*----------------------------------------------------------------------------*/ 161 153 /** 162 154 * @} -
uspace/drv/bus/usb/vhc/connhost.c
r3e5c48c9 r159100a 141 141 size_t max_packet_size, unsigned int interval) 142 142 { 143 VHC_DATA(vhc, fun); 144 145 endpoint_t *ep = malloc(sizeof(endpoint_t)); 143 /* TODO: Use usb_endpoint_manager_add_ep */ 144 VHC_DATA(vhc, fun); 145 146 endpoint_t *ep = endpoint_get( 147 address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1); 146 148 if (ep == NULL) { 147 149 return ENOMEM; 148 150 } 149 151 150 int rc = endpoint_init(ep, address, endpoint, direction, transfer_type, 151 USB_SPEED_FULL, 1); 152 if (rc != EOK) { 153 free(ep); 154 return rc; 155 } 156 157 rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1); 152 int rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1); 158 153 if (rc != EOK) { 159 154 endpoint_destroy(ep); -
uspace/lib/usb/include/usb/classes/hub.h
r3e5c48c9 r159100a 119 119 */ 120 120 uint16_t hub_characteristics; 121 #define HUB_CHAR_POWER_PER_PORT_FLAG (1 << 0) 122 #define HUB_CHAR_NO_POWER_SWITCH_FLAG (1 << 1) 121 123 122 124 /** -
uspace/lib/usbhost/include/usb/host/endpoint.h
r3e5c48c9 r159100a 61 61 } endpoint_t; 62 62 63 int endpoint_init(endpoint_t *instance, usb_address_t address,64 usb_ endpoint_t endpoint, usb_direction_t direction,65 usb_transfer_type_t type, usb_speed_t speed,size_t max_packet_size);63 endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint, 64 usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed, 65 size_t max_packet_size); 66 66 67 67 void endpoint_destroy(endpoint_t *instance); -
uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h
r3e5c48c9 r159100a 82 82 size_t data_size) 83 83 { 84 endpoint_t *ep = malloc(sizeof(endpoint_t)); 85 if (ep == NULL) 84 endpoint_t *ep = endpoint_get( 85 address, endpoint, direction, type, speed, max_packet_size); 86 if (!ep) 86 87 return ENOMEM; 87 88 88 int ret = endpoint_init(ep, address, endpoint, direction, type, speed, 89 max_packet_size); 90 if (ret != EOK) { 91 free(ep); 92 return ret; 93 } 94 95 ret = usb_endpoint_manager_register_ep(instance, ep, data_size); 89 const int ret = 90 usb_endpoint_manager_register_ep(instance, ep, data_size); 96 91 if (ret != EOK) { 97 92 endpoint_destroy(ep); 98 return ret;99 93 } 100 return EOK;94 return ret; 101 95 } 102 96 #endif -
uspace/lib/usbhost/src/batch.c
r3e5c48c9 r159100a 109 109 assert(instance); 110 110 assert(instance->ep); 111 assert(instance->next_step); 111 112 endpoint_release(instance->ep); 112 113 instance->next_step(instance); -
uspace/lib/usbhost/src/endpoint.c
r3e5c48c9 r159100a 39 39 #include <usb/host/endpoint.h> 40 40 41 int endpoint_init(endpoint_t *instance, usb_address_t address,42 usb_ endpoint_t endpoint, usb_direction_t direction,43 usb_transfer_type_t type, usb_speed_t speed,size_t max_packet_size)41 endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint, 42 usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed, 43 size_t max_packet_size) 44 44 { 45 assert(instance); 46 instance->address = address; 47 instance->endpoint = endpoint; 48 instance->direction = direction; 49 instance->transfer_type = type; 50 instance->speed = speed; 51 instance->max_packet_size = max_packet_size; 52 instance->toggle = 0; 53 instance->active = false; 54 fibril_mutex_initialize(&instance->guard); 55 fibril_condvar_initialize(&instance->avail); 56 endpoint_clear_hc_data(instance); 57 return EOK; 45 endpoint_t *instance = malloc(sizeof(endpoint_t)); 46 if (instance) { 47 instance->address = address; 48 instance->endpoint = endpoint; 49 instance->direction = direction; 50 instance->transfer_type = type; 51 instance->speed = speed; 52 instance->max_packet_size = max_packet_size; 53 instance->toggle = 0; 54 instance->active = false; 55 fibril_mutex_initialize(&instance->guard); 56 fibril_condvar_initialize(&instance->avail); 57 endpoint_clear_hc_data(instance); 58 } 59 return instance; 58 60 } 59 61 /*----------------------------------------------------------------------------*/
Note:
See TracChangeset
for help on using the changeset viewer.