Changeset 4069f5c in mainline
- Timestamp:
- 2011-07-17T09:52:42Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 64639256, ca1f1ec
- Parents:
- 27eddb52 (diff), 4118f5f (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:
-
- 3 added
- 47 edited
- 4 moved
Legend:
- Unmodified
- Added
- Removed
-
HelenOS.config
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 71 71 CONFIG_MOUNT_DATA = n 72 72 73 # OHCI root hub power switch, ganged is enough 74 OHCI_POWER_SWITCH = ganged -
uspace/app/bdsh/Makefile
r27eddb52 r4069f5c 54 54 cmds/mod_cmds.c \ 55 55 cmds/builtin_cmds.c \ 56 compl.c \ 56 57 errors.c \ 57 58 input.c \ -
uspace/app/bdsh/config.h
r27eddb52 r4069f5c 40 40 #endif 41 41 42 /* Work around for getenv() */43 #define PATH "/srv:/app"44 #define PATH_DELIM ":"45 46 42 /* Used in many places */ 47 43 #define SMALL_BUFLEN 256 -
uspace/app/bdsh/exec.c
r27eddb52 r4069f5c 52 52 static int try_access(const char *); 53 53 54 const char *search_dir[] = { "app", "srv", NULL }; 55 54 56 /* work-around for access() */ 55 57 static int try_access(const char *f) … … 69 71 static char *find_command(char *cmd) 70 72 { 71 char *path_tok; 72 char *path[PATH_MAX]; 73 int n = 0, i = 0; 74 size_t x = str_size(cmd) + 2; 73 size_t i; 75 74 76 75 found = (char *)malloc(PATH_MAX); … … 81 80 } 82 81 83 path_tok = str_dup(PATH);84 85 /* Extract the PATH env to a path[] array */86 path[n] = strtok(path_tok, PATH_DELIM);87 while (NULL != path[n]) {88 if ((str_size(path[n]) + x ) > PATH_MAX) {89 cli_error(CL_ENOTSUP,90 "Segment %d of path is too large, search ends at segment %d",91 n, n-1);92 break;93 }94 path[++n] = strtok(NULL, PATH_DELIM);95 }96 97 82 /* We now have n places to look for the command */ 98 for (i =0; path[i]; i++) {83 for (i = 0; search_dir[i] != NULL; i++) { 99 84 memset(found, 0, sizeof(found)); 100 snprintf(found, PATH_MAX, "%s/%s", path[i], cmd);85 snprintf(found, PATH_MAX, "%s/%s", search_dir[i], cmd); 101 86 if (-1 != try_access(found)) { 102 free(path_tok);103 87 return (char *) found; 104 88 } … … 106 90 107 91 /* We didn't find it, just give it back as-is. */ 108 free(path_tok);109 92 return (char *) cmd; 110 93 } -
uspace/app/bdsh/exec.h
r27eddb52 r4069f5c 33 33 #include "scli.h" 34 34 35 extern const char *search_dir[]; 36 35 37 extern unsigned int try_exec(char *, char **, iostate_t *); 36 38 -
uspace/app/bdsh/input.c
r27eddb52 r4069f5c 1 1 /* 2 2 * Copyright (c) 2008 Tim Post 3 * Copyright (c) 2011 Jiri Svoboda 3 4 * All rights reserved. 4 5 * … … 43 44 44 45 #include "config.h" 46 #include "compl.h" 45 47 #include "util.h" 46 48 #include "scli.h" … … 226 228 int rc; 227 229 228 console_flush(tinput->console); 229 console_set_style(tinput->console, STYLE_EMPHASIS); 230 printf("%s", usr->prompt); 231 console_flush(tinput->console); 232 console_set_style(tinput->console, STYLE_NORMAL); 230 tinput_set_prompt(tinput, usr->prompt); 233 231 234 232 rc = tinput_read(tinput, &str); … … 263 261 } 264 262 263 tinput_set_compl_ops(tinput, &compl_ops); 264 265 265 return 0; 266 266 } -
uspace/app/bdsh/scli.h
r27eddb52 r4069f5c 32 32 #include "config.h" 33 33 #include <stdint.h> 34 #include <stdio.h> 34 35 35 36 typedef struct { -
uspace/app/sbi/src/input.c
r27eddb52 r4069f5c 176 176 int input_get_line(input_t *input, char **line) 177 177 { 178 const char *prompt; 178 179 const char *sp; 179 180 char *dp; … … 212 213 /* Interactive mode */ 213 214 if (input->line_no == 0) 214 pr intf("sbi> ");215 prompt = "sbi> "; 215 216 else 216 pr intf("... ");217 prompt = "... "; 217 218 218 219 fflush(stdout); 219 if (os_input_line( &line_p) != EOK)220 if (os_input_line(prompt, &line_p) != EOK) 220 221 return EIO; 221 222 -
uspace/app/sbi/src/os/helenos.c
r27eddb52 r4069f5c 210 210 * @param ptr Place to store pointer to new string. 211 211 */ 212 int os_input_line(c har **ptr)212 int os_input_line(const char *prompt, char **ptr) 213 213 { 214 214 char *line; … … 219 219 if (tinput == NULL) 220 220 return EIO; 221 222 tinput_set_prompt(tinput, prompt); 221 223 } 222 224 -
uspace/app/sbi/src/os/os.h
r27eddb52 r4069f5c 38 38 char *os_chr_to_astr(wchar_t chr); 39 39 void os_input_disp_help(void); 40 int os_input_line(c har **ptr);40 int os_input_line(const char *prompt, char **ptr); 41 41 int os_exec(char * const cmd[]); 42 42 -
uspace/app/sbi/src/os/posix.c
r27eddb52 r4069f5c 193 193 * @param ptr Place to store pointer to new string. 194 194 */ 195 int os_input_line(char **ptr) 196 { 195 int os_input_line(const char *prompt, char **ptr) 196 { 197 printf("%s", prompt); 198 197 199 if (fgets(os_input_buffer, OS_INPUT_BUFFER_SIZE, stdin) == NULL) 198 200 os_input_buffer[0] = '\0'; -
uspace/drv/bus/isa/isa.c
r27eddb52 r4069f5c 352 352 str_error(rc)); 353 353 } 354 355 free(id); 354 356 } 355 357 -
uspace/drv/bus/pci/pciintel/pci.c
r27eddb52 r4069f5c 342 342 } 343 343 344 free(match_id_str); 345 344 346 /* TODO add more ids (with subsys ids, using class id etc.) */ 345 347 } -
uspace/drv/bus/usb/ohci/hc.c
r27eddb52 r4069f5c 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); 86 87 char *match_str = NULL; 88 /* DDF needs heap allocated string */ 89 ret = asprintf(&match_str, "usb&class=hub"); 90 ret = ret > 0 ? 0 : ret; 91 CHECK_RET_RELEASE(ret, "Failed(%d) to create match-id string.\n", ret); 92 93 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); 150 CHECK_RET_RELEASE(ret, 151 "Failed to add OHCI root hub endpoint 0: %s.\n", str_error(ret)); 152 153 ret = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100); 154 CHECK_RET_RELEASE(ret, 155 "Failed to add root hub match-id: %s.\n", str_error(ret)); 95 156 96 157 ret = ddf_fun_bind(hub_fun); 97 CHECK_RET_RELEASE(ret, "Failed(%d) to bind root hub function.\n", ret); 158 CHECK_RET_RELEASE(ret, 159 "Failed to bind root hub function: %s.\n", str_error(ret)); 98 160 99 161 return EOK; … … 112 174 { 113 175 assert(instance); 114 int ret = EOK; 176 115 177 #define CHECK_RET_RETURN(ret, message...) \ 116 178 if (ret != EOK) { \ … … 119 181 } else (void)0 120 182 121 ret = pio_enable((void*)regs, reg_size, (void**)&instance->registers); 183 int ret = 184 pio_enable((void*)regs, reg_size, (void**)&instance->registers); 122 185 CHECK_RET_RETURN(ret, 123 "Failed(%d) to gain access to device registers: %s.\n", 124 ret, str_error(ret)); 186 "Failed to gain access to device registers: %s.\n", str_error(ret)); 125 187 126 188 list_initialize(&instance->pending_batches); 127 189 usb_device_keeper_init(&instance->manager); 190 128 191 ret = usb_endpoint_manager_init(&instance->ep_manager, 129 192 BANDWIDTH_AVAILABLE_USB11); … … 137 200 138 201 fibril_mutex_initialize(&instance->guard); 202 139 203 hc_gain_control(instance); 140 141 rh_init(&instance->rh, instance->registers);142 204 143 205 if (!interrupts) { … … 147 209 } 148 210 149 return EOK; 150 } 151 /*----------------------------------------------------------------------------*/ 152 /** Create end register endpoint structures 211 rh_init(&instance->rh, instance->registers); 212 hc_start(instance); 213 214 return EOK; 215 } 216 /*----------------------------------------------------------------------------*/ 217 /** Create and register endpoint structures. 153 218 * 154 219 * @param[in] instance OHCI driver structure. … … 168 233 size_t mps, size_t size, unsigned interval) 169 234 { 170 endpoint_t *ep = malloc(sizeof(endpoint_t)); 235 endpoint_t *ep = 236 endpoint_get(address, endpoint, direction, type, speed, mps); 171 237 if (ep == NULL) 172 238 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 239 180 240 hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep); … … 184 244 } 185 245 186 ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size); 246 int ret = 247 usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size); 187 248 if (ret != EOK) { 188 249 hcd_endpoint_clear(ep); … … 212 273 &instance->lists[ep->transfer_type], hcd_ep); 213 274 instance->registers->control |= C_PLE | C_IE; 214 break;215 default:216 275 break; 217 276 } … … 312 371 /* Check for root hub communication */ 313 372 if (batch->ep->address == instance->rh.address) { 314 return rh_request(&instance->rh, batch); 373 rh_request(&instance->rh, batch); 374 return EOK; 315 375 } 316 376 … … 374 434 375 435 if (status & I_UE) { 376 hc_start _hw(instance);436 hc_start(instance); 377 437 } 378 438 … … 399 459 /** Turn off any (BIOS)driver that might be in control of the device. 400 460 * 461 * This function implements routines described in chapter 5.1.1.3 of the OHCI 462 * specification (page 40, pdf page 54). 463 * 401 464 * @param[in] instance OHCI hc driver structure. 402 465 */ … … 404 467 { 405 468 assert(instance); 469 406 470 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); 471 if (instance->registers->revision & R_LEGACY_FLAG) { 472 /* Turn off legacy emulation, it should be enough to zero 473 * the lowest bit, but it caused problems. Thus clear all 474 * except GateA20 (causes restart on some hw). 475 * See page 145 of the specs for details. 476 */ 477 volatile uint32_t *ohci_emulation_reg = 478 (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET); 479 usb_log_debug("OHCI legacy register %p: %x.\n", 480 ohci_emulation_reg, *ohci_emulation_reg); 481 /* Zero everything but A20State */ 482 *ohci_emulation_reg &= 0x100; 483 usb_log_debug( 484 "OHCI legacy register (should be 0 or 0x100) %p: %x.\n", 485 ohci_emulation_reg, *ohci_emulation_reg); 486 } 416 487 417 488 /* Interrupt routing enabled => smm driver is active */ … … 419 490 usb_log_debug("SMM driver: request ownership change.\n"); 420 491 instance->registers->command_status |= CS_OCR; 492 /* Hope that SMM actually knows its stuff or we can hang here */ 421 493 while (instance->registers->control & C_IR) { 422 494 async_usleep(1000); 423 495 } 424 496 usb_log_info("SMM driver: Ownership taken.\n"); 425 instance->registers->control &= (C_HCFS_RESET << C_HCFS_SHIFT);497 C_HCFS_SET(instance->registers->control, C_HCFS_RESET); 426 498 async_usleep(50000); 427 499 return; 428 500 } 429 501 430 const unsigned hc_status = 431 (instance->registers->control >> C_HCFS_SHIFT) & C_HCFS_MASK; 502 const unsigned hc_status = C_HCFS_GET(instance->registers->control); 432 503 /* Interrupt routing disabled && status != USB_RESET => BIOS active */ 433 504 if (hc_status != C_HCFS_RESET) { … … 437 508 return; 438 509 } 439 /* HC is suspended assert resume for 20ms */440 instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);510 /* HC is suspended assert resume for 20ms, */ 511 C_HCFS_SET(instance->registers->control, C_HCFS_RESUME); 441 512 async_usleep(20000); 442 513 usb_log_info("BIOS driver: HC resumed.\n"); … … 454 525 * @param[in] instance OHCI hc driver structure. 455 526 */ 456 void hc_start _hw(hc_t *instance)527 void hc_start(hc_t *instance) 457 528 { 458 529 /* OHCI guide page 42 */ … … 516 587 instance->registers->periodic_start, frame_length); 517 588 518 instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);589 C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL); 519 590 usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n", 520 591 instance->registers->control); … … 534 605 int ret = endpoint_list_init(&instance->lists[type], name); \ 535 606 if (ret != EOK) { \ 536 usb_log_error("Failed (%d) to setup %s endpoint list.\n", \537 ret, name); \607 usb_log_error("Failed to setup %s endpoint list: %s.\n", \ 608 name, str_error(ret)); \ 538 609 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\ 539 610 endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \ … … 587 658 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa); 588 659 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 } 660 return EOK; 661 } 662 623 663 /** 624 664 * @} -
uspace/drv/bus/usb/ohci/hc.h
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 50 50 int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size) 51 51 { 52 int ret; 53 52 54 assert(fun); 53 55 54 char *match_str = NULL; 55 int ret = asprintf(&match_str, "usb&uhci&root-hub"); 56 if (ret < 0) { 57 usb_log_error( 58 "Failed(%d) to create root hub match string: %s.\n", 59 ret, str_error(ret)); 60 return ret; 61 } 62 assert(match_str); 63 64 ret = ddf_fun_add_match_id(fun, match_str, 100); 56 ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100); 65 57 if (ret != EOK) { 66 free(match_str); 67 usb_log_error("Failed(%d) to add root hub match id: %s\n", 68 ret, str_error(ret)); 58 usb_log_error("Failed to add root hub match id: %s\n", 59 str_error(ret)); 69 60 return ret; 70 61 } -
uspace/drv/bus/usb/uhci/uhci.c
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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/usbmast/Makefile
r27eddb52 r4069f5c 44 44 45 45 SOURCES = \ 46 cmds.c \ 46 bo_trans.c \ 47 cmdw.c \ 47 48 main.c \ 48 mast.c \49 49 scsi_ms.c 50 50 -
uspace/drv/bus/usb/usbmast/bo_trans.c
r27eddb52 r4069f5c 32 32 /** 33 33 * @file 34 * Generic functions for USB mass storage (implementation). 35 */ 36 #include "mast.h" 37 #include "cmds.h" 34 * USB mass storage bulk-only transport. 35 */ 38 36 #include <bool.h> 39 37 #include <errno.h> … … 41 39 #include <usb/debug.h> 42 40 #include <usb/dev/request.h> 41 42 #include "bo_trans.h" 43 #include "cmdw.h" 44 #include "usbmast.h" 43 45 44 46 bool usb_mast_verbose = false; … … 53 55 /** Send command via bulk-only transport. 54 56 * 57 * @param mfun Mass storage function 55 58 * @param tag Command block wrapper tag (automatically compared 56 59 * with answer) 57 * @param lun LUN58 60 * @param cmd Command block 59 61 * @param cmd_size Command block size in bytes … … 65 67 * @return Error code 66 68 */ 67 static int usb_massstor_cmd(usb _device_t *dev, uint32_t tag, uint8_t lun,68 const void *cmd, size_t cmd_size, usb_direction_t ddir, void *dbuf,69 size_t dbuf_size, size_t*xferred_size)69 static int usb_massstor_cmd(usbmast_fun_t *mfun, uint32_t tag, const void *cmd, 70 size_t cmd_size, usb_direction_t ddir, void *dbuf, size_t dbuf_size, 71 size_t *xferred_size) 70 72 { 71 73 int rc; 72 74 size_t act_size; 73 usb_pipe_t *bulk_in_pipe = dev->pipes[BULK_IN_EP].pipe;74 usb_pipe_t *bulk_out_pipe = dev->pipes[BULK_OUT_EP].pipe;75 usb_pipe_t *bulk_in_pipe = mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe; 76 usb_pipe_t *bulk_out_pipe = mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe; 75 77 76 78 /* Prepare CBW - command block wrapper */ 77 79 usb_massstor_cbw_t cbw; 78 usb_massstor_cbw_prepare(&cbw, tag, dbuf_size, ddir, lun, cmd_size,79 cmd );80 usb_massstor_cbw_prepare(&cbw, tag, dbuf_size, ddir, mfun->lun, 81 cmd_size, cmd); 80 82 81 83 /* Send the CBW. */ … … 164 166 /** Perform data-in command. 165 167 * 168 * @param mfun Mass storage function 166 169 * @param tag Command block wrapper tag (automatically compared with 167 170 * answer) 168 * @param lun LUN169 171 * @param cmd CDB (Command Descriptor) 170 172 * @param cmd_size CDB length in bytes … … 175 177 * @return Error code 176 178 */ 177 int usb_massstor_data_in(usb _device_t *dev, uint32_t tag, uint8_t lun,178 const void *cmd,size_t cmd_size, void *dbuf, size_t dbuf_size, size_t *proc_size)179 { 180 return usb_massstor_cmd( dev, tag, lun, cmd, cmd_size, USB_DIRECTION_IN,179 int usb_massstor_data_in(usbmast_fun_t *mfun, uint32_t tag, const void *cmd, 180 size_t cmd_size, void *dbuf, size_t dbuf_size, size_t *proc_size) 181 { 182 return usb_massstor_cmd(mfun, tag, cmd, cmd_size, USB_DIRECTION_IN, 181 183 dbuf, dbuf_size, proc_size); 182 184 } … … 184 186 /** Perform data-out command. 185 187 * 188 * @param mfun Mass storage function 186 189 * @param tag Command block wrapper tag (automatically compared with 187 190 * answer) 188 * @param lun LUN189 191 * @param cmd CDB (Command Descriptor) 190 192 * @param cmd_size CDB length in bytes … … 195 197 * @return Error code 196 198 */ 197 int usb_massstor_data_out(usb_device_t *dev, uint32_t tag, uint8_t lun, 198 const void *cmd, size_t cmd_size, const void *data, size_t data_size, 199 size_t *proc_size) 200 { 201 return usb_massstor_cmd(dev, tag, lun, cmd, cmd_size, USB_DIRECTION_OUT, 199 int usb_massstor_data_out(usbmast_fun_t *mfun, uint32_t tag, const void *cmd, 200 size_t cmd_size, const void *data, size_t data_size, size_t *proc_size) 201 { 202 return usb_massstor_cmd(mfun, tag, cmd, cmd_size, USB_DIRECTION_OUT, 202 203 (void *) data, data_size, proc_size); 203 204 } … … 205 206 /** Perform bulk-only mass storage reset. 206 207 * 207 * @param dev Device to be reseted.208 * @return Error code.209 */ 210 int usb_massstor_reset(usb _device_t *dev)211 { 212 return usb_control_request_set(& dev->ctrl_pipe,208 * @param mfun Mass storage function 209 * @return Error code 210 */ 211 int usb_massstor_reset(usbmast_dev_t *mdev) 212 { 213 return usb_control_request_set(&mdev->usb_dev->ctrl_pipe, 213 214 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 214 0xFF, 0, dev->interface_no, NULL, 0);215 0xFF, 0, mdev->usb_dev->interface_no, NULL, 0); 215 216 } 216 217 … … 220 221 * would reappear on next transaction somehow. 221 222 * 222 * @param dev Device to be reseted.223 */ 224 void usb_massstor_reset_recovery(usb _device_t *dev)223 * @param mfun Mass storage function 224 */ 225 void usb_massstor_reset_recovery(usbmast_dev_t *mdev) 225 226 { 226 227 /* We would ignore errors here because if this fails 227 228 * we are doomed anyway and any following transaction would fail. 228 229 */ 229 usb_massstor_reset(dev); 230 usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[BULK_IN_EP].pipe); 231 usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[BULK_OUT_EP].pipe); 230 usb_massstor_reset(mdev); 231 usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe, 232 mdev->usb_dev->pipes[BULK_IN_EP].pipe); 233 usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe, 234 mdev->usb_dev->pipes[BULK_OUT_EP].pipe); 232 235 } 233 236 … … 240 243 * You shall rather use usb_masstor_get_lun_count. 241 244 * 242 * @param dev Mass storage device.243 * @return Error code of maximum LUN (index, not count).244 */ 245 int usb_massstor_get_max_lun(usb _device_t *dev)245 * @param mfun Mass storage function 246 * @return Error code of maximum LUN (index, not count) 247 */ 248 int usb_massstor_get_max_lun(usbmast_dev_t *mdev) 246 249 { 247 250 uint8_t max_lun; 248 251 size_t data_recv_len; 249 int rc = usb_control_request_get(& dev->ctrl_pipe,252 int rc = usb_control_request_get(&mdev->usb_dev->ctrl_pipe, 250 253 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 251 0xFE, 0, dev->interface_no, &max_lun, 1, &data_recv_len);254 0xFE, 0, mdev->usb_dev->interface_no, &max_lun, 1, &data_recv_len); 252 255 if (rc != EOK) { 253 256 return rc; … … 264 267 * (typically that shall not be a problem). 265 268 * 266 * @param dev Mass storage device.267 * @return Number of LUNs.268 */ 269 size_t usb_masstor_get_lun_count(usb _device_t *dev)270 { 271 int max_lun = usb_massstor_get_max_lun( dev);269 * @param mfun Mass storage function 270 * @return Number of LUNs 271 */ 272 size_t usb_masstor_get_lun_count(usbmast_dev_t *mdev) 273 { 274 int max_lun = usb_massstor_get_max_lun(mdev); 272 275 if (max_lun < 0) { 273 276 max_lun = 1; -
uspace/drv/bus/usb/usbmast/bo_trans.h
r27eddb52 r4069f5c 31 31 */ 32 32 /** @file 33 * Generic functions for USB mass storage.33 * USB mass storage bulk-only transport. 34 34 */ 35 35 36 #ifndef USB_USBMAST_MAST_H_37 #define USB_USBMAST_MAST_H_36 #ifndef BO_TRANS_H_ 37 #define BO_TRANS_H_ 38 38 39 39 #include <scsi/spc.h> … … 42 42 #include <usb/dev/pipes.h> 43 43 #include <usb/dev/driver.h> 44 #include "usbmast.h" 44 45 45 46 #define BULK_IN_EP 0 46 47 #define BULK_OUT_EP 1 47 48 48 extern int usb_massstor_data_in(usb _device_t *, uint32_t, uint8_t, const void *,49 extern int usb_massstor_data_in(usbmast_fun_t *, uint32_t, const void *, 49 50 size_t, void *, size_t, size_t *); 50 extern int usb_massstor_data_out(usb _device_t *, uint32_t, uint8_t, const void *,51 extern int usb_massstor_data_out(usbmast_fun_t *, uint32_t, const void *, 51 52 size_t, const void *, size_t, size_t *); 52 extern int usb_massstor_reset(usb _device_t *);53 extern void usb_massstor_reset_recovery(usb _device_t *);54 extern int usb_massstor_get_max_lun(usb _device_t *);55 extern size_t usb_masstor_get_lun_count(usb _device_t *);53 extern int usb_massstor_reset(usbmast_dev_t *); 54 extern void usb_massstor_reset_recovery(usbmast_dev_t *); 55 extern int usb_massstor_get_max_lun(usbmast_dev_t *); 56 extern size_t usb_masstor_get_lun_count(usbmast_dev_t *); 56 57 57 58 #endif -
uspace/drv/bus/usb/usbmast/cmdw.c
r27eddb52 r4069f5c 38 38 #include <sys/types.h> 39 39 #include <usb/usb.h> 40 #include "cmd s.h"40 #include "cmdw.h" 41 41 42 42 void usb_massstor_cbw_prepare(usb_massstor_cbw_t *cbw, -
uspace/drv/bus/usb/usbmast/cmdw.h
r27eddb52 r4069f5c 34 34 */ 35 35 36 #ifndef USB_USBMAST_CMDS_H_37 #define USB_USBMAST_CMDS_H_36 #ifndef CMDW_H_ 37 #define CMDW_H_ 38 38 39 39 #include <sys/types.h> -
uspace/drv/bus/usb/usbmast/main.c
r27eddb52 r4069f5c 45 45 #include <errno.h> 46 46 #include <str_error.h> 47 #include "cmd s.h"48 #include " mast.h"47 #include "cmdw.h" 48 #include "bo_trans.h" 49 49 #include "scsi_ms.h" 50 #include "usbmast.h" 50 51 51 52 #define NAME "usbmast" … … 77 78 }; 78 79 79 /** Mass storage function. 80 * 81 * Serves as soft state for function/LUN. 82 */ 83 typedef struct { 84 /** DDF function */ 85 ddf_fun_t *ddf_fun; 86 /** Total number of blocks. */ 87 uint64_t nblocks; 88 /** Block size in bytes. */ 89 size_t block_size; 90 /** USB device function belongs to */ 91 usb_device_t *usb_dev; 92 } usbmast_fun_t; 93 80 static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun); 94 81 static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall, 95 82 void *arg); … … 103 90 { 104 91 int rc; 105 const char *fun_name = "a"; 106 ddf_fun_t *fun = NULL; 107 usbmast_fun_t *msfun = NULL; 92 usbmast_dev_t *mdev = NULL; 93 unsigned i; 108 94 109 95 /* Allocate softstate */ 110 m sfun = calloc(1, sizeof(usbmast_fun_t));111 if (m sfun== NULL) {96 mdev = calloc(1, sizeof(usbmast_dev_t)); 97 if (mdev == NULL) { 112 98 usb_log_error("Failed allocating softstate.\n"); 113 99 rc = ENOMEM; … … 115 101 } 116 102 117 fun = ddf_fun_create(dev->ddf_dev, fun_exposed, fun_name); 118 if (fun == NULL) { 119 usb_log_error("Failed to create DDF function %s.\n", fun_name); 120 rc = ENOMEM; 121 goto error; 122 } 123 124 /* Set up a connection handler. */ 125 fun->conn_handler = usbmast_bd_connection; 126 fun->driver_data = msfun; 103 mdev->ddf_dev = dev->ddf_dev; 104 mdev->usb_dev = dev; 127 105 128 106 usb_log_info("Initializing mass storage `%s'.\n", … … 136 114 137 115 usb_log_debug("Get LUN count...\n"); 138 size_t lun_count = usb_masstor_get_lun_count(dev); 139 140 /* XXX Handle more than one LUN properly. */ 141 if (lun_count > 1) { 142 usb_log_warning ("Mass storage has %zu LUNs. Ignoring all " 143 "but first.\n", lun_count); 144 } 116 mdev->luns = usb_masstor_get_lun_count(mdev); 117 118 for (i = 0; i < mdev->luns; i++) { 119 rc = usbmast_fun_create(mdev, i); 120 if (rc != EOK) 121 goto error; 122 } 123 124 return EOK; 125 error: 126 /* XXX Destroy functions */ 127 if (mdev != NULL) 128 free(mdev); 129 return rc; 130 } 131 132 /** Create mass storage function. 133 * 134 * Called once for each LUN. 135 * 136 * @param mdev Mass storage device 137 * @param lun LUN 138 * @return EOK on success or negative error code. 139 */ 140 static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun) 141 { 142 int rc; 143 char *fun_name = NULL; 144 ddf_fun_t *fun = NULL; 145 usbmast_fun_t *mfun = NULL; 146 147 /* Allocate softstate */ 148 mfun = calloc(1, sizeof(usbmast_fun_t)); 149 if (mfun == NULL) { 150 usb_log_error("Failed allocating softstate.\n"); 151 rc = ENOMEM; 152 goto error; 153 } 154 155 mfun->mdev = mdev; 156 mfun->lun = lun; 157 158 if (asprintf(&fun_name, "l%u", lun) < 0) { 159 usb_log_error("Out of memory.\n"); 160 rc = ENOMEM; 161 goto error; 162 } 163 164 fun = ddf_fun_create(mdev->ddf_dev, fun_exposed, fun_name); 165 if (fun == NULL) { 166 usb_log_error("Failed to create DDF function %s.\n", fun_name); 167 rc = ENOMEM; 168 goto error; 169 } 170 171 free(fun_name); 172 fun_name = NULL; 173 174 /* Set up a connection handler. */ 175 fun->conn_handler = usbmast_bd_connection; 176 fun->driver_data = mfun; 145 177 146 178 usb_log_debug("Inquire...\n"); 147 179 usbmast_inquiry_data_t inquiry; 148 rc = usbmast_inquiry( dev, &inquiry);180 rc = usbmast_inquiry(mfun, &inquiry); 149 181 if (rc != EOK) { 150 182 usb_log_warning("Failed to inquire device `%s': %s.\n", 151 dev->ddf_dev->name, str_error(rc));183 mdev->ddf_dev->name, str_error(rc)); 152 184 rc = EIO; 153 185 goto error; 154 186 } 155 187 156 usb_log_info("Mass storage `%s': " \ 157 "%s by %s rev. %s is %s (%s), %zu LUN(s).\n", 158 dev->ddf_dev->name, 188 usb_log_info("Mass storage `%s' LUN %u: " \ 189 "%s by %s rev. %s is %s (%s).\n", 190 mdev->ddf_dev->name, 191 lun, 159 192 inquiry.product, 160 193 inquiry.vendor, 161 194 inquiry.revision, 162 195 usbmast_scsi_dev_type_str(inquiry.device_type), 163 inquiry.removable ? "removable" : "non-removable", 164 lun_count); 196 inquiry.removable ? "removable" : "non-removable"); 165 197 166 198 uint32_t nblocks, block_size; 167 199 168 rc = usbmast_read_capacity( dev, &nblocks, &block_size);200 rc = usbmast_read_capacity(mfun, &nblocks, &block_size); 169 201 if (rc != EOK) { 170 202 usb_log_warning("Failed to read capacity, device `%s': %s.\n", 171 dev->ddf_dev->name, str_error(rc));203 mdev->ddf_dev->name, str_error(rc)); 172 204 rc = EIO; 173 205 goto error; … … 177 209 "block_size=%" PRIu32 "\n", nblocks, block_size); 178 210 179 msfun->nblocks = nblocks; 180 msfun->block_size = block_size; 181 msfun->usb_dev = dev; 211 mfun->nblocks = nblocks; 212 mfun->block_size = block_size; 182 213 183 214 rc = ddf_fun_bind(fun); … … 194 225 if (fun != NULL) 195 226 ddf_fun_destroy(fun); 196 if (msfun != NULL) 197 free(msfun); 227 if (fun_name != NULL) 228 free(fun_name); 229 if (mfun != NULL) 230 free(mfun); 198 231 return rc; 199 232 } … … 203 236 void *arg) 204 237 { 205 usbmast_fun_t *m sfun;238 usbmast_fun_t *mfun; 206 239 void *comm_buf = NULL; 207 240 size_t comm_size; … … 229 262 (void) async_share_out_finalize(callid, comm_buf); 230 263 231 m sfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;264 mfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data; 232 265 233 266 while (true) { … … 243 276 switch (method) { 244 277 case BD_GET_BLOCK_SIZE: 245 async_answer_1(callid, EOK, m sfun->block_size);278 async_answer_1(callid, EOK, mfun->block_size); 246 279 break; 247 280 case BD_GET_NUM_BLOCKS: 248 async_answer_2(callid, EOK, LOWER32(m sfun->nblocks),249 UPPER32(m sfun->nblocks));281 async_answer_2(callid, EOK, LOWER32(mfun->nblocks), 282 UPPER32(mfun->nblocks)); 250 283 break; 251 284 case BD_READ_BLOCKS: 252 285 ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 253 286 cnt = IPC_GET_ARG3(call); 254 retval = usbmast_read(msfun->usb_dev, ba, cnt, 255 msfun->block_size, comm_buf); 287 retval = usbmast_read(mfun, ba, cnt, comm_buf); 256 288 async_answer_0(callid, retval); 257 289 break; … … 259 291 ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 260 292 cnt = IPC_GET_ARG3(call); 261 retval = usbmast_write(msfun->usb_dev, ba, cnt, 262 msfun->block_size, comm_buf); 293 retval = usbmast_write(mfun, ba, cnt, comm_buf); 263 294 async_answer_0(callid, retval); 264 295 break; -
uspace/drv/bus/usb/usbmast/scsi_ms.c
r27eddb52 r4069f5c 46 46 #include <scsi/sbc.h> 47 47 #include <scsi/spc.h> 48 #include "cmd s.h"49 #include " mast.h"48 #include "cmdw.h" 49 #include "bo_trans.h" 50 50 #include "scsi_ms.h" 51 #include "usbmast.h" 51 52 52 53 /** Get string representation for SCSI peripheral device type. … … 62 63 /** Perform SCSI Inquiry command on USB mass storage device. 63 64 * 64 * @param dev USB device.65 * @param inquiry_result Where to store parsed inquiry result .66 * @return Error code .67 */ 68 int usbmast_inquiry(usb _device_t *dev, usbmast_inquiry_data_t *inq_res)65 * @param mfun Mass storage function 66 * @param inquiry_result Where to store parsed inquiry result 67 * @return Error code 68 */ 69 int usbmast_inquiry(usbmast_fun_t *mfun, usbmast_inquiry_data_t *inq_res) 69 70 { 70 71 scsi_std_inquiry_data_t inq_data; … … 77 78 cdb.alloc_len = host2uint16_t_be(sizeof(inq_data)); 78 79 79 rc = usb_massstor_data_in( dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,80 rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb, 80 81 sizeof(cdb), &inq_data, sizeof(inq_data), &response_len); 81 82 82 83 if (rc != EOK) { 83 84 usb_log_error("Inquiry failed, device %s: %s.\n", 84 dev->ddf_dev->name, str_error(rc));85 mfun->mdev->ddf_dev->name, str_error(rc)); 85 86 return rc; 86 87 } … … 118 119 /** Perform SCSI Request Sense command on USB mass storage device. 119 120 * 120 * @param dev USB device121 * @param mfun Mass storage function 121 122 * @param buf Destination buffer 122 123 * @param size Size of @a buf … … 124 125 * @return Error code. 125 126 */ 126 int usbmast_request_sense(usb _device_t *dev, void *buf, size_t size)127 int usbmast_request_sense(usbmast_fun_t *mfun, void *buf, size_t size) 127 128 { 128 129 scsi_cdb_request_sense_t cdb; … … 134 135 cdb.alloc_len = min(size, SCSI_SENSE_DATA_MAX_SIZE); 135 136 136 rc = usb_massstor_data_in( dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,137 rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb, 137 138 sizeof(cdb), buf, size, &data_len); 138 139 139 140 if (rc != EOK) { 140 141 usb_log_error("Request Sense failed, device %s: %s.\n", 141 dev->ddf_dev->name, str_error(rc));142 mfun->mdev->ddf_dev->name, str_error(rc)); 142 143 return rc; 143 144 } … … 154 155 /** Perform SCSI Read Capacity command on USB mass storage device. 155 156 * 156 * @param dev USB device.157 * @param nblocks Output, number of blocks .158 * @param block_size Output, block size in bytes .157 * @param mfun Mass storage function 158 * @param nblocks Output, number of blocks 159 * @param block_size Output, block size in bytes 159 160 * 160 161 * @return Error code. 161 162 */ 162 int usbmast_read_capacity(usb _device_t *dev, uint32_t *nblocks,163 int usbmast_read_capacity(usbmast_fun_t *mfun, uint32_t *nblocks, 163 164 uint32_t *block_size) 164 165 { … … 171 172 cdb.op_code = SCSI_CMD_READ_CAPACITY_10; 172 173 173 rc = usb_massstor_data_in( dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,174 rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb, 174 175 sizeof(cdb), &data, sizeof(data), &data_len); 175 176 176 177 if (rc != EOK) { 177 178 usb_log_error("Read Capacity (10) failed, device %s: %s.\n", 178 dev->ddf_dev->name, str_error(rc));179 mfun->mdev->ddf_dev->name, str_error(rc)); 179 180 return rc; 180 181 } … … 194 195 /** Perform SCSI Read command on USB mass storage device. 195 196 * 196 * @param dev USB device. 197 * @param ba Address of first block. 198 * @param nblocks Number of blocks to read. 199 * @param bsize Block size. 200 * 201 * @return Error code. 202 */ 203 int usbmast_read(usb_device_t *dev, uint64_t ba, size_t nblocks, size_t bsize, 204 void *buf) 197 * @param mfun Mass storage function 198 * @param ba Address of first block 199 * @param nblocks Number of blocks to read 200 * 201 * @return Error code 202 */ 203 int usbmast_read(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks, void *buf) 205 204 { 206 205 scsi_cdb_read_12_t cdb; … … 213 212 return ELIMIT; 214 213 215 if ((uint64_t)nblocks * bsize > UINT32_MAX)214 if ((uint64_t)nblocks * mfun->block_size > UINT32_MAX) 216 215 return ELIMIT; 217 216 … … 221 220 cdb.xfer_len = host2uint32_t_be(nblocks); 222 221 223 rc = usb_massstor_data_in( dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,224 sizeof(cdb), buf, nblocks * bsize, &data_len);222 rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb, 223 sizeof(cdb), buf, nblocks * mfun->block_size, &data_len); 225 224 226 225 if (rc != EOK) { 227 226 usb_log_error("Read (12) failed, device %s: %s.\n", 228 dev->ddf_dev->name, str_error(rc));229 return rc; 230 } 231 232 if (data_len < nblocks * bsize) {227 mfun->mdev->ddf_dev->name, str_error(rc)); 228 return rc; 229 } 230 231 if (data_len < nblocks * mfun->block_size) { 233 232 usb_log_error("SCSI Read response too short (%zu).\n", 234 233 data_len); … … 241 240 /** Perform SCSI Write command on USB mass storage device. 242 241 * 243 * @param dev USB device242 * @param mfun Mass storage function 244 243 * @param ba Address of first block 245 244 * @param nblocks Number of blocks to read 246 * @param bsize Block size247 245 * @param data Data to write 248 246 * 249 247 * @return Error code 250 248 */ 251 int usbmast_write(usb _device_t *dev, uint64_t ba, size_t nblocks, size_t bsize,249 int usbmast_write(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks, 252 250 const void *data) 253 251 { … … 256 254 int rc; 257 255 258 /* XXX Need softstate to store block size. */259 260 256 if (ba > UINT32_MAX) 261 257 return ELIMIT; 262 258 263 if ((uint64_t)nblocks * bsize > UINT32_MAX)259 if ((uint64_t)nblocks * mfun->block_size > UINT32_MAX) 264 260 return ELIMIT; 265 261 … … 269 265 cdb.xfer_len = host2uint32_t_be(nblocks); 270 266 271 rc = usb_massstor_data_out( dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,272 sizeof(cdb), data, nblocks * bsize, &sent_len);267 rc = usb_massstor_data_out(mfun, 0xDEADBEEF, (uint8_t *) &cdb, 268 sizeof(cdb), data, nblocks * mfun->block_size, &sent_len); 273 269 274 270 if (rc != EOK) { 275 271 usb_log_error("Write (12) failed, device %s: %s.\n", 276 dev->ddf_dev->name, str_error(rc));277 return rc; 278 } 279 280 if (sent_len < nblocks * bsize) {272 mfun->mdev->ddf_dev->name, str_error(rc)); 273 return rc; 274 } 275 276 if (sent_len < nblocks * mfun->block_size) { 281 277 usb_log_error("SCSI Write not all bytes transferred (%zu).\n", 282 278 sent_len); -
uspace/drv/bus/usb/usbmast/scsi_ms.h
r27eddb52 r4069f5c 59 59 } usbmast_inquiry_data_t; 60 60 61 extern int usbmast_inquiry(usb_device_t *, usbmast_inquiry_data_t *); 62 extern int usbmast_request_sense(usb_device_t *, void *, size_t); 63 extern int usbmast_read_capacity(usb_device_t *, uint32_t *, uint32_t *); 64 extern int usbmast_read(usb_device_t *, uint64_t, size_t, size_t, void *); 65 extern int usbmast_write(usb_device_t *, uint64_t, size_t, size_t, 66 const void *); 61 extern int usbmast_inquiry(usbmast_fun_t *, usbmast_inquiry_data_t *); 62 extern int usbmast_request_sense(usbmast_fun_t *, void *, size_t); 63 extern int usbmast_read_capacity(usbmast_fun_t *, uint32_t *, uint32_t *); 64 extern int usbmast_read(usbmast_fun_t *, uint64_t, size_t, void *); 65 extern int usbmast_write(usbmast_fun_t *, uint64_t, size_t, const void *); 67 66 extern const char *usbmast_scsi_dev_type_str(unsigned); 68 67 -
uspace/drv/bus/usb/vhc/connhost.c
r27eddb52 r4069f5c 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/drv/infrastructure/root/root.c
r27eddb52 r4069f5c 176 176 } 177 177 178 free(match_id); 179 178 180 rc = ddf_fun_bind(fun); 179 181 if (rc != EOK) { -
uspace/drv/test/test1/test1.c
r27eddb52 r4069f5c 74 74 } 75 75 76 rc = ddf_fun_add_match_id(fun, str_dup(match_id), match_score);76 rc = ddf_fun_add_match_id(fun, match_id, match_score); 77 77 if (rc != EOK) { 78 78 ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s", -
uspace/lib/c/generic/io/io.c
r27eddb52 r4069f5c 714 714 off64_t ftell(FILE *stream) 715 715 { 716 _fflushbuf(stream); 716 717 return lseek(stream->fd, 0, SEEK_CUR); 717 718 } -
uspace/lib/clui/tinput.c
r27eddb52 r4069f5c 1 1 /* 2 * Copyright (c) 201 0Jiri Svoboda2 * Copyright (c) 2011 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 #include <sort.h> 29 30 #include <stdio.h> 30 31 #include <stdlib.h> … … 42 43 #include <tinput.h> 43 44 45 #define LIN_TO_COL(ti, lpos) ((lpos) % ((ti)->con_cols)) 46 #define LIN_TO_ROW(ti, lpos) ((lpos) / ((ti)->con_cols)) 47 44 48 /** Seek direction */ 45 49 typedef enum { … … 61 65 static void tinput_post_seek(tinput_t *, bool); 62 66 67 static void tinput_console_set_lpos(tinput_t *ti, unsigned lpos) 68 { 69 console_set_pos(ti->console, LIN_TO_COL(ti, lpos), 70 LIN_TO_ROW(ti, lpos)); 71 } 72 63 73 /** Create a new text input field. */ 64 74 tinput_t *tinput_new(void) … … 66 76 tinput_t *ti; 67 77 68 ti = malloc(sizeof(tinput_t));78 ti = calloc(1, sizeof(tinput_t)); 69 79 if (ti == NULL) 70 80 return NULL; … … 77 87 void tinput_destroy(tinput_t *ti) 78 88 { 89 if (ti->prompt != NULL) 90 free(ti->prompt); 79 91 free(ti); 92 } 93 94 static void tinput_display_prompt(tinput_t *ti) 95 { 96 tinput_console_set_lpos(ti, ti->prompt_coord); 97 98 console_set_style(ti->console, STYLE_EMPHASIS); 99 printf("%s", ti->prompt); 100 console_flush(ti->console); 101 console_set_style(ti->console, STYLE_NORMAL); 80 102 } 81 103 … … 88 110 tinput_sel_get_bounds(ti, &sa, &sb); 89 111 90 console_set_pos(ti->console, (ti->col0 + start) % ti->con_cols, 91 ti->row0 + (ti->col0 + start) / ti->con_cols); 112 tinput_console_set_lpos(ti, ti->text_coord + start); 92 113 console_set_style(ti->console, STYLE_NORMAL); 93 114 … … 134 155 static void tinput_position_caret(tinput_t *ti) 135 156 { 136 console_set_pos(ti->console, (ti->col0 + ti->pos) % ti->con_cols, 137 ti->row0 + (ti->col0 + ti->pos) / ti->con_cols); 138 } 139 140 /** Update row0 in case the screen could have scrolled. */ 157 tinput_console_set_lpos(ti, ti->text_coord + ti->pos); 158 } 159 160 /** Update text_coord, prompt_coord in case the screen could have scrolled. */ 141 161 static void tinput_update_origin(tinput_t *ti) 142 162 { 143 sysarg_t width = ti->col0 + ti->nc; 144 sysarg_t rows = (width / ti->con_cols) + 1; 145 146 /* Update row0 if the screen scrolled. */ 147 if (ti->row0 + rows > ti->con_rows) 148 ti->row0 = ti->con_rows - rows; 163 unsigned end_coord = ti->text_coord + ti->nc; 164 unsigned end_row = LIN_TO_ROW(ti, end_coord); 165 166 unsigned scroll_rows; 167 168 /* Update coords if the screen scrolled. */ 169 if (end_row >= ti->con_rows) { 170 scroll_rows = end_row - ti->con_rows + 1; 171 ti->text_coord -= ti->con_cols * scroll_rows; 172 ti->prompt_coord -= ti->con_cols * scroll_rows; 173 } 174 } 175 176 static void tinput_jump_after(tinput_t *ti) 177 { 178 tinput_console_set_lpos(ti, ti->text_coord + ti->nc); 179 console_flush(ti->console); 180 putchar('\n'); 181 } 182 183 static int tinput_display(tinput_t *ti) 184 { 185 sysarg_t col0, row0; 186 187 if (console_get_pos(ti->console, &col0, &row0) != EOK) 188 return EIO; 189 190 ti->prompt_coord = row0 * ti->con_cols + col0; 191 ti->text_coord = ti->prompt_coord + str_length(ti->prompt); 192 193 tinput_display_prompt(ti); 194 tinput_display_tail(ti, 0, 0); 195 tinput_position_caret(ti); 196 197 return EOK; 149 198 } 150 199 … … 154 203 return; 155 204 156 sysarg_t new_width = ti->col0+ ti->nc + 1;205 unsigned new_width = LIN_TO_COL(ti, ti->text_coord) + ti->nc + 1; 157 206 if (new_width % ti->con_cols == 0) { 158 207 /* Advancing to new line. */ … … 185 234 return; 186 235 187 sysarg_t new_width = ti->col0+ ti->nc + ilen;188 sysarg_tnew_height = (new_width / ti->con_cols) + 1;236 unsigned new_width = LIN_TO_COL(ti, ti->text_coord) + ti->nc + ilen; 237 unsigned new_height = (new_width / ti->con_cols) + 1; 189 238 if (new_height >= ti->con_rows) { 190 239 /* Disallow text longer than 1 page for now. */ … … 511 560 } 512 561 562 /** Compare two entries in array of completions. */ 563 static int compl_cmp(void *va, void *vb, void *arg) 564 { 565 const char *a = *(const char **) va; 566 const char *b = *(const char **) vb; 567 568 return str_cmp(a, b); 569 } 570 571 static size_t common_pref_len(const char *a, const char *b) 572 { 573 size_t i; 574 size_t a_off, b_off; 575 wchar_t ca, cb; 576 577 i = 0; 578 a_off = 0; 579 b_off = 0; 580 581 while (true) { 582 ca = str_decode(a, &a_off, STR_NO_LIMIT); 583 cb = str_decode(b, &b_off, STR_NO_LIMIT); 584 585 if (ca == '\0' || cb == '\0' || ca != cb) 586 break; 587 ++i; 588 } 589 590 return i; 591 } 592 593 static void tinput_text_complete(tinput_t *ti) 594 { 595 void *state; 596 size_t cstart; 597 char *ctmp; 598 char **compl; /* Array of completions */ 599 size_t compl_len; /* Current length of @c compl array */ 600 size_t cnum; 601 size_t i; 602 int rc; 603 604 if (ti->compl_ops == NULL) 605 return; 606 607 /* 608 * Obtain list of all possible completions (growing array). 609 */ 610 611 rc = (*ti->compl_ops->init)(ti->buffer, ti->pos, &cstart, &state); 612 if (rc != EOK) 613 return; 614 615 cnum = 0; 616 617 compl_len = 1; 618 compl = malloc(compl_len * sizeof(char *)); 619 if (compl == NULL) { 620 printf("Error: Out of memory.\n"); 621 return; 622 } 623 624 while (true) { 625 rc = (*ti->compl_ops->get_next)(state, &ctmp); 626 if (rc != EOK) 627 break; 628 629 if (cnum >= compl_len) { 630 /* Extend array */ 631 compl_len = 2 * compl_len; 632 compl = realloc(compl, compl_len * sizeof(char *)); 633 if (compl == NULL) { 634 printf("Error: Out of memory.\n"); 635 break; 636 } 637 } 638 639 compl[cnum] = str_dup(ctmp); 640 if (compl[cnum] == NULL) { 641 printf("Error: Out of memory.\n"); 642 break; 643 } 644 cnum++; 645 } 646 647 (*ti->compl_ops->fini)(state); 648 649 if (cnum > 1) { 650 /* 651 * More than one match. Determine maximum common prefix. 652 */ 653 size_t cplen; 654 655 cplen = str_length(compl[0]); 656 for (i = 1; i < cnum; i++) 657 cplen = min(cplen, common_pref_len(compl[0], compl[i])); 658 659 /* Compute how many bytes we should skip. */ 660 size_t istart = str_lsize(compl[0], ti->pos - cstart); 661 662 if (cplen > istart) { 663 /* Insert common prefix. */ 664 665 /* Copy remainder of common prefix. */ 666 char *cpref = str_ndup(compl[0] + istart, 667 str_lsize(compl[0], cplen - istart)); 668 669 /* Insert it. */ 670 tinput_insert_string(ti, cpref); 671 free(cpref); 672 } else { 673 /* No common prefix. Sort and display all entries. */ 674 675 qsort(compl, cnum, sizeof(char *), compl_cmp, NULL); 676 677 tinput_jump_after(ti); 678 for (i = 0; i < cnum; i++) 679 printf("%s\n", compl[i]); 680 tinput_display(ti); 681 } 682 } else if (cnum == 1) { 683 /* 684 * We have exactly one match. Insert it. 685 */ 686 687 /* Compute how many bytes of completion string we should skip. */ 688 size_t istart = str_lsize(compl[0], ti->pos - cstart); 689 690 /* Insert remainder of completion string at current position. */ 691 tinput_insert_string(ti, compl[0] + istart); 692 } 693 694 for (i = 0; i < cnum; i++) 695 free(compl[i]); 696 free(compl); 697 } 698 513 699 /** Initialize text input field. 514 700 * … … 521 707 ti->hpos = 0; 522 708 ti->history[0] = NULL; 709 } 710 711 /** Set prompt string. 712 * 713 * @param ti Text input 714 * @param prompt Prompt string 715 * 716 * @return EOK on success, ENOMEM if out of memory. 717 */ 718 int tinput_set_prompt(tinput_t *ti, const char *prompt) 719 { 720 if (ti->prompt != NULL) 721 free(ti->prompt); 722 723 ti->prompt = str_dup(prompt); 724 if (ti->prompt == NULL) 725 return ENOMEM; 726 727 return EOK; 728 } 729 730 /** Set completion ops. 731 * 732 * Set pointer to completion ops structure that will be used for text 733 * completion. 734 */ 735 void tinput_set_compl_ops(tinput_t *ti, tinput_compl_ops_t *compl_ops) 736 { 737 ti->compl_ops = compl_ops; 523 738 } 524 739 … … 539 754 return EIO; 540 755 541 if (console_get_pos(ti->console, &ti->col0, &ti->row0) != EOK)542 return EIO;543 544 756 ti->pos = 0; 545 757 ti->sel_start = 0; … … 549 761 ti->exit_clui = false; 550 762 763 if (tinput_display(ti) != EOK) 764 return EIO; 765 551 766 while (!ti->done) { 552 767 console_flush(ti->console); … … 714 929 tinput_history_seek(ti, -1); 715 930 break; 931 case KC_TAB: 932 tinput_text_complete(ti); 933 break; 716 934 default: 717 935 break; -
uspace/lib/clui/tinput.h
r27eddb52 r4069f5c 1 1 /* 2 * Copyright (c) 201 0Jiri Svoboda2 * Copyright (c) 2011 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 37 37 #define LIBCLUI_TINPUT_H_ 38 38 39 #include < stdio.h>39 #include <adt/list.h> 40 40 #include <async.h> 41 41 #include <inttypes.h> 42 42 #include <io/console.h> 43 #include <stdio.h> 43 44 44 45 #define HISTORY_LEN 10 45 46 #define INPUT_MAX_SIZE 1024 47 48 /** Begin enumeration of text completions. 49 * 50 * When user requests text completion, tinput will call this function to start 51 * text completion operation. @a *cstart should be set to the position 52 * (character index) of the first character of the 'word' that is being 53 * completed. The resulting text is obtained by replacing the range of text 54 * starting at @a *cstart and ending at @a pos with the completion text. 55 * 56 * The function can pass information to the get_next and fini functions 57 * via @a state. The init function allocates the state object and stores 58 * a pointer to it to @a *state. The fini function destroys the state object. 59 * 60 * @param text Current contents of edit buffer (null-terminated). 61 * @param pos Current caret position. 62 * @param cstart Output, position in text where completion begins from. 63 * @param state Output, pointer to a client state object. 64 * 65 * @return EOK on success, negative error code on failure. 66 */ 67 typedef int (*tinput_compl_init_fn)(wchar_t *text, size_t pos, size_t *cstart, 68 void **state); 69 70 /** Obtain one text completion alternative. 71 * 72 * Upon success the function sets @a *compl to point to a string, the 73 * completion text. The caller (Tinput) should not modify or free the text. 74 * The pointer is only valid until the next invocation of any completion 75 * function. 76 * 77 * @param state Pointer to state object created by the init funtion. 78 * @param compl Output, the completion text, ownership retained. 79 * 80 * @return EOK on success, negative error code on failure. 81 */ 82 typedef int (*tinput_compl_get_next_fn)(void *state, char **compl); 83 84 85 /** Finish enumeration of text completions. 86 * 87 * The function must deallocate any state information allocated by the init 88 * function or temporary data allocated by the get_next function. 89 * 90 * @param state Pointer to state object created by the init funtion. 91 */ 92 typedef void (*tinput_compl_fini_fn)(void *state); 93 94 /** Text completion ops. */ 95 typedef struct { 96 tinput_compl_init_fn init; 97 tinput_compl_get_next_fn get_next; 98 tinput_compl_fini_fn fini; 99 } tinput_compl_ops_t; 46 100 47 101 /** Text input field (command line). … … 53 107 console_ctrl_t *console; 54 108 109 /** Prompt string */ 110 char *prompt; 111 112 /** Completion ops. */ 113 tinput_compl_ops_t *compl_ops; 114 55 115 /** Buffer holding text currently being edited */ 56 116 wchar_t buffer[INPUT_MAX_SIZE + 1]; 57 117 58 /** Screen coordinates of the top-left corner of the text field */ 59 sysarg_t col0; 60 sysarg_t row0; 118 /** Linear position on screen where the prompt starts */ 119 unsigned prompt_coord; 120 /** Linear position on screen where the text field starts */ 121 unsigned text_coord; 61 122 62 123 /** Screen dimensions */ … … 90 151 91 152 extern tinput_t *tinput_new(void); 153 extern int tinput_set_prompt(tinput_t *, const char *); 154 extern void tinput_set_compl_ops(tinput_t *, tinput_compl_ops_t *); 92 155 extern void tinput_destroy(tinput_t *); 93 156 extern int tinput_read(tinput_t *, char **); -
uspace/lib/drv/generic/driver.c
r27eddb52 r4069f5c 620 620 return ENOMEM; 621 621 622 match_id->id = match_id_str;622 match_id->id = str_dup(match_id_str); 623 623 match_id->score = 90; 624 624 -
uspace/lib/usb/include/usb/classes/hub.h
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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
r27eddb52 r4069f5c 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 /*----------------------------------------------------------------------------*/ -
uspace/srv/hid/input/ctl/stty.c
r27eddb52 r4069f5c 34 34 * @file 35 35 * @brief Serial TTY-like keyboard controller driver. 36 * 37 * Keyboard emulation on a serial terminal. 36 38 */ 37 39 … … 63 65 #include <stdio.h> 64 66 67 /** 68 * Sequnece definitions are primarily for Xterm. Additionally we define 69 * sequences that are unique to Gnome terminal -- most are the same but 70 * some differ. 71 */ 65 72 static int seq_defs[] = { 66 73 /* Not shifted */ … … 81 88 0, KC_MINUS, 0x2d, GSP_END, 82 89 0, KC_EQUALS, 0x3d, GSP_END, 90 83 91 0, KC_BACKSPACE, 0x08, GSP_END, 84 92 … … 216 224 0, KC_RIGHT, 0x1b, 0x5b, 0x43, GSP_END, 217 225 226 /* 227 * Sequences specific to Gnome terminal 228 */ 229 0, KC_BACKSPACE, 0x7f, GSP_END, /* ASCII DEL */ 230 0, KC_HOME, 0x1b, 0x4f, 0x48, GSP_END, 231 0, KC_END, 0x1b, 0x4f, 0x46, GSP_END, 232 218 233 0, 0 219 234 }; -
uspace/srv/hid/input/generic/gsp.c
r27eddb52 r4069f5c 104 104 if (key == 0) break; 105 105 106 /* Insert one sequence. */ 106 /* Insert one sequence. */ 107 107 rc = gsp_insert_seq(p, dp, mods, key); 108 108 if (rc != 0) … … 197 197 198 198 if (t == NULL) { 199 printf("gsp_step: not found\n"); 199 printf("gsp_step: not found, state=%d, input=0x%x\n", 200 state, input); 200 201 *mods = 0; 201 202 *key = 0; … … 205 206 *mods = t->out_mods; 206 207 *key = t->out_key; 208 207 209 return t->new_state; 208 210 } -
uspace/srv/hid/input/generic/input.c
r27eddb52 r4069f5c 410 410 #endif 411 411 #if defined(MACHINE_msim) 412 kbd_add_dev(&msim_port, & pc_ctl);412 kbd_add_dev(&msim_port, &stty_ctl); 413 413 #endif 414 414 #if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB)
Note:
See TracChangeset
for help on using the changeset viewer.