Changes in / [4069f5c:27eddb52] in mainline


Ignore:
Files:
4 added
7 deleted
47 edited

Legend:

Unmodified
Added
Removed
  • HelenOS.config

    r4069f5c r27eddb52  
    573573! CONFIG_RUN_VIRTUAL_USB_HC (n/y)
    574574
    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)
     575% Polling UHCI & OHCI (no interrupts)
     576! [PLATFORM=ia32|PLATFORM=amd64] CONFIG_USBHC_NO_INTERRUPTS (n/y)
     577
  • defaults/amd64/Makefile.config

    r4069f5c r27eddb52  
    6565CONFIG_MOUNT_DATA = n
    6666
    67 # OHCI root hub power switch, ganged is enough
    68 OHCI_POWER_SWITCH = ganged
  • defaults/ia32/Makefile.config

    r4069f5c r27eddb52  
    7171CONFIG_MOUNT_DATA = n
    7272
    73 # OHCI root hub power switch, ganged is enough
    74 OHCI_POWER_SWITCH = ganged
  • uspace/app/bdsh/Makefile

    r4069f5c r27eddb52  
    5454        cmds/mod_cmds.c \
    5555        cmds/builtin_cmds.c \
    56         compl.c \
    5756        errors.c \
    5857        input.c \
  • uspace/app/bdsh/config.h

    r4069f5c r27eddb52  
    4040#endif
    4141
     42/* Work around for getenv() */
     43#define PATH "/srv:/app"
     44#define PATH_DELIM ":"
     45
    4246/* Used in many places */
    4347#define SMALL_BUFLEN 256
  • uspace/app/bdsh/exec.c

    r4069f5c r27eddb52  
    5252static int try_access(const char *);
    5353
    54 const char *search_dir[] = { "app", "srv", NULL };
    55 
    5654/* work-around for access() */
    5755static int try_access(const char *f)
     
    7169static char *find_command(char *cmd)
    7270{
    73         size_t i;
     71        char *path_tok;
     72        char *path[PATH_MAX];
     73        int n = 0, i = 0;
     74        size_t x = str_size(cmd) + 2;
    7475
    7576        found = (char *)malloc(PATH_MAX);
     
    8081        }
    8182
     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
    8297        /* We now have n places to look for the command */
    83         for (i = 0; search_dir[i] != NULL; i++) {
     98        for (i=0; path[i]; i++) {
    8499                memset(found, 0, sizeof(found));
    85                 snprintf(found, PATH_MAX, "%s/%s", search_dir[i], cmd);
     100                snprintf(found, PATH_MAX, "%s/%s", path[i], cmd);
    86101                if (-1 != try_access(found)) {
     102                        free(path_tok);
    87103                        return (char *) found;
    88104                }
     
    90106
    91107        /* We didn't find it, just give it back as-is. */
     108        free(path_tok);
    92109        return (char *) cmd;
    93110}
  • uspace/app/bdsh/exec.h

    r4069f5c r27eddb52  
    3333#include "scli.h"
    3434
    35 extern const char *search_dir[];
    36 
    3735extern unsigned int try_exec(char *, char **, iostate_t *);
    3836
  • uspace/app/bdsh/input.c

    r4069f5c r27eddb52  
    11/*
    22 * Copyright (c) 2008 Tim Post
    3  * Copyright (c) 2011 Jiri Svoboda
    43 * All rights reserved.
    54 *
     
    4443
    4544#include "config.h"
    46 #include "compl.h"
    4745#include "util.h"
    4846#include "scli.h"
     
    228226        int rc;
    229227       
    230         tinput_set_prompt(tinput, usr->prompt);
     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);
    231233
    232234        rc = tinput_read(tinput, &str);
     
    261263        }
    262264
    263         tinput_set_compl_ops(tinput, &compl_ops);
    264 
    265265        return 0;
    266266}
  • uspace/app/bdsh/scli.h

    r4069f5c r27eddb52  
    3232#include "config.h"
    3333#include <stdint.h>
    34 #include <stdio.h>
    3534
    3635typedef struct {
  • uspace/app/sbi/src/input.c

    r4069f5c r27eddb52  
    176176int input_get_line(input_t *input, char **line)
    177177{
    178         const char *prompt;
    179178        const char *sp;
    180179        char *dp;
     
    213212                /* Interactive mode */
    214213                if (input->line_no == 0)
    215                         prompt = "sbi> ";
     214                        printf("sbi> ");
    216215                else
    217                         prompt = "...  ";
     216                        printf("...  ");
    218217
    219218                fflush(stdout);
    220                 if (os_input_line(prompt, &line_p) != EOK)
     219                if (os_input_line(&line_p) != EOK)
    221220                        return EIO;
    222221
  • uspace/app/sbi/src/os/helenos.c

    r4069f5c r27eddb52  
    210210 * @param ptr   Place to store pointer to new string.
    211211 */
    212 int os_input_line(const char *prompt, char **ptr)
     212int os_input_line(char **ptr)
    213213{
    214214        char *line;
     
    219219                if (tinput == NULL)
    220220                        return EIO;
    221 
    222                 tinput_set_prompt(tinput, prompt);
    223221        }
    224222
  • uspace/app/sbi/src/os/os.h

    r4069f5c r27eddb52  
    3838char *os_chr_to_astr(wchar_t chr);
    3939void os_input_disp_help(void);
    40 int os_input_line(const char *prompt, char **ptr);
     40int os_input_line(char **ptr);
    4141int os_exec(char * const cmd[]);
    4242
  • uspace/app/sbi/src/os/posix.c

    r4069f5c r27eddb52  
    193193 * @param ptr   Place to store pointer to new string.
    194194 */
    195 int os_input_line(const char *prompt, char **ptr)
    196 {
    197         printf("%s", prompt);
    198 
     195int os_input_line(char **ptr)
     196{
    199197        if (fgets(os_input_buffer, OS_INPUT_BUFFER_SIZE, stdin) == NULL)
    200198                os_input_buffer[0] = '\0';
  • uspace/drv/bus/isa/isa.c

    r4069f5c r27eddb52  
    352352                    str_error(rc));
    353353        }
    354 
    355         free(id);
    356354}
    357355
  • uspace/drv/bus/pci/pciintel/pci.c

    r4069f5c r27eddb52  
    342342        }
    343343       
    344         free(match_id_str);
    345        
    346344        /* TODO add more ids (with subsys ids, using class id etc.) */
    347345}
  • uspace/drv/bus/usb/ohci/hc.c

    r4069f5c r27eddb52  
    4646#define OHCI_USED_INTERRUPTS \
    4747    (I_SO | I_WDH | I_UE | I_RHSC)
    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 
     48static int interrupt_emulator(hc_t *instance);
    5849static void hc_gain_control(hc_t *instance);
    59 static void hc_start(hc_t *instance);
    6050static int hc_init_transfer_lists(hc_t *instance);
    6151static 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**)&registers);
    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*)&registers->interrupt_status;
    113         cmds[0].addr = address;
    114         cmds[3].addr = address;
    115         return EOK;
    116 }
    11752/*----------------------------------------------------------------------------*/
    11853/** Announce OHCI root hub to the DDF
     
    14883        int ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
    14984            USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
    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));
     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);
    15695
    15796        ret = ddf_fun_bind(hub_fun);
    158         CHECK_RET_RELEASE(ret,
    159             "Failed to bind root hub function: %s.\n", str_error(ret));
     97        CHECK_RET_RELEASE(ret, "Failed(%d) to bind root hub function.\n", ret);
    16098
    16199        return EOK;
     
    174112{
    175113        assert(instance);
    176 
     114        int ret = EOK;
    177115#define CHECK_RET_RETURN(ret, message...) \
    178116if (ret != EOK) { \
     
    181119} else (void)0
    182120
    183         int ret =
    184             pio_enable((void*)regs, reg_size, (void**)&instance->registers);
     121        ret = pio_enable((void*)regs, reg_size, (void**)&instance->registers);
    185122        CHECK_RET_RETURN(ret,
    186             "Failed to gain access to device registers: %s.\n", str_error(ret));
     123            "Failed(%d) to gain access to device registers: %s.\n",
     124            ret, str_error(ret));
    187125
    188126        list_initialize(&instance->pending_batches);
    189127        usb_device_keeper_init(&instance->manager);
    190 
    191128        ret = usb_endpoint_manager_init(&instance->ep_manager,
    192129            BANDWIDTH_AVAILABLE_USB11);
     
    200137
    201138        fibril_mutex_initialize(&instance->guard);
    202 
    203139        hc_gain_control(instance);
     140
     141        rh_init(&instance->rh, instance->registers);
    204142
    205143        if (!interrupts) {
     
    209147        }
    210148
    211         rh_init(&instance->rh, instance->registers);
    212         hc_start(instance);
    213 
    214149        return EOK;
    215150}
    216151/*----------------------------------------------------------------------------*/
    217 /** Create and register endpoint structures.
     152/** Create end register endpoint structures
    218153 *
    219154 * @param[in] instance OHCI driver structure.
     
    233168    size_t mps, size_t size, unsigned interval)
    234169{
    235         endpoint_t *ep =
    236             endpoint_get(address, endpoint, direction, type, speed, mps);
     170        endpoint_t *ep = malloc(sizeof(endpoint_t));
    237171        if (ep == NULL)
    238172                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        }
    239179
    240180        hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
     
    244184        }
    245185
    246         int ret =
    247             usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
     186        ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
    248187        if (ret != EOK) {
    249188                hcd_endpoint_clear(ep);
     
    273212                    &instance->lists[ep->transfer_type], hcd_ep);
    274213                instance->registers->control |= C_PLE | C_IE;
     214                break;
     215        default:
    275216                break;
    276217        }
     
    371312        /* Check for root hub communication */
    372313        if (batch->ep->address == instance->rh.address) {
    373                 rh_request(&instance->rh, batch);
    374                 return EOK;
     314                return rh_request(&instance->rh, batch);
    375315        }
    376316
     
    434374
    435375        if (status & I_UE) {
    436                 hc_start(instance);
     376                hc_start_hw(instance);
    437377        }
    438378
     
    459399/** Turn off any (BIOS)driver that might be in control of the device.
    460400 *
    461  * This function implements routines described in chapter 5.1.1.3 of the OHCI
    462  * specification (page 40, pdf page 54).
    463  *
    464401 * @param[in] instance OHCI hc driver structure.
    465402 */
     
    467404{
    468405        assert(instance);
    469 
    470406        usb_log_debug("Requesting OHCI control.\n");
    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         }
     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);
    487416
    488417        /* Interrupt routing enabled => smm driver is active */
     
    490419                usb_log_debug("SMM driver: request ownership change.\n");
    491420                instance->registers->command_status |= CS_OCR;
    492                 /* Hope that SMM actually knows its stuff or we can hang here */
    493421                while (instance->registers->control & C_IR) {
    494422                        async_usleep(1000);
    495423                }
    496424                usb_log_info("SMM driver: Ownership taken.\n");
    497                 C_HCFS_SET(instance->registers->control, C_HCFS_RESET);
     425                instance->registers->control &= (C_HCFS_RESET << C_HCFS_SHIFT);
    498426                async_usleep(50000);
    499427                return;
    500428        }
    501429
    502         const unsigned hc_status = C_HCFS_GET(instance->registers->control);
     430        const unsigned hc_status =
     431            (instance->registers->control >> C_HCFS_SHIFT) & C_HCFS_MASK;
    503432        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
    504433        if (hc_status != C_HCFS_RESET) {
     
    508437                        return;
    509438                }
    510                 /* HC is suspended assert resume for 20ms, */
    511                 C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
     439                /* HC is suspended assert resume for 20ms */
     440                instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
    512441                async_usleep(20000);
    513442                usb_log_info("BIOS driver: HC resumed.\n");
     
    525454 * @param[in] instance OHCI hc driver structure.
    526455 */
    527 void hc_start(hc_t *instance)
     456void hc_start_hw(hc_t *instance)
    528457{
    529458        /* OHCI guide page 42 */
     
    587516            instance->registers->periodic_start, frame_length);
    588517
    589         C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);
     518        instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
    590519        usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
    591520            instance->registers->control);
     
    605534        int ret = endpoint_list_init(&instance->lists[type], name); \
    606535        if (ret != EOK) { \
    607                 usb_log_error("Failed to setup %s endpoint list: %s.\n", \
    608                     name, str_error(ret)); \
     536                usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
     537                    ret, name); \
    609538                endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\
    610539                endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
     
    658587            instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
    659588
     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
    660621        return EOK;
    661622}
    662 
    663623/**
    664624 * @}
  • uspace/drv/bus/usb/ohci/hc.h

    r4069f5c r27eddb52  
    5151#include "hw_struct/hcca.h"
    5252
    53 /** Main OHCI driver structure */
     53#define OHCI_NEEDED_IRQ_COMMANDS 5
     54
     55/** Main OHCI drier structure */
    5456typedef struct hc {
    5557        /** USB bus driver, devices and addresses */
     
    7476        fibril_mutex_t guard;
    7577
     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
    7684        /** USB hub emulation structure */
    7785        rh_t rh;
    7886} hc_t;
    7987
    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);
     88int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
    8389int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
    84 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
     90void hc_start_hw(hc_t *instance);
    8591
    8692/** Safely dispose host controller internal structures
  • uspace/drv/bus/usb/ohci/ohci.c

    r4069f5c r27eddb52  
    5858{
    5959        assert(dev);
     60        assert(dev->driver_data);
    6061        return dev->driver_data;
    6162}
     63
    6264/** IRQ handling callback, identifies device
    6365 *
     
    6870static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
    6971{
    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         }
     72        hc_t *hc = &dev_to_ohci(dev)->hc;
     73        assert(hc);
    7774        const uint16_t status = IPC_GET_ARG1(*call);
    78         hc_interrupt(&ohci->hc, status);
     75        hc_interrupt(hc, status);
    7976}
    8077/*----------------------------------------------------------------------------*/
     
    169166        } \
    170167        free(instance); \
    171         device->driver_data = NULL; \
    172168        usb_log_error(message); \
    173169        return ret; \
     
    177173        instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc");
    178174        int ret = instance->hc_fun ? EOK : ENOMEM;
    179         CHECK_RET_DEST_FREE_RETURN(ret,
    180             "Failed to create OHCI HC function: %s.\n", str_error(ret));
     175        CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI HC function.\n");
    181176        instance->hc_fun->ops = &hc_ops;
    182177        instance->hc_fun->driver_data = &instance->hc;
     
    184179        instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh");
    185180        ret = instance->rh_fun ? EOK : ENOMEM;
    186         CHECK_RET_DEST_FREE_RETURN(ret,
    187             "Failed to create OHCI RH function: %s.\n", str_error(ret));
     181        CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create OHCI RH function.\n");
    188182        instance->rh_fun->ops = &rh_ops;
    189183
     
    199193            (void *) reg_base, reg_size, irq);
    200194
    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 */
    216195        bool interrupts = false;
     196#ifdef CONFIG_USBHC_NO_INTERRUPTS
     197        usb_log_warning("Interrupts disabled in OS config, "
     198            "falling back to polling.\n");
     199#else
    217200        ret = pci_enable_interrupts(device);
    218201        if (ret != EOK) {
    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);
     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");
    223206        } else {
    224207                usb_log_debug("Hw interrupts enabled.\n");
    225208                interrupts = true;
    226209        }
     210#endif
    227211
    228212        ret = hc_init(&instance->hc, reg_base, reg_size, interrupts);
    229         CHECK_RET_DEST_FREE_RETURN(ret,
    230             "Failed to init ohci_hcd: %s.\n", str_error(ret));
    231 
    232         device->driver_data = instance;
     213        CHECK_RET_DEST_FREE_RETURN(ret, "Failed(%d) to init ohci_hcd.\n", ret);
    233214
    234215#define CHECK_RET_FINI_RETURN(ret, message...) \
    235216if (ret != EOK) { \
    236         unregister_interrupt_handler(device, irq); \
    237217        hc_fini(&instance->hc); \
    238218        CHECK_RET_DEST_FREE_RETURN(ret, message); \
    239219} else (void)0
    240220
     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);
    241226
    242227        ret = ddf_fun_bind(instance->hc_fun);
    243228        CHECK_RET_FINI_RETURN(ret,
    244             "Failed to bind OHCI device function: %s.\n", str_error(ret));
     229            "Failed(%d) to bind OHCI device function: %s.\n",
     230            ret, str_error(ret));
    245231
    246232        ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
     
    248234            "Failed to add OHCI to HC class: %s.\n", str_error(ret));
    249235
     236        device->driver_data = instance;
     237
     238        hc_start_hw(&instance->hc);
    250239        hc_register_hub(&instance->hc, instance->rh_fun);
    251240        return EOK;
  • uspace/drv/bus/usb/ohci/ohci_regs.h

    r4069f5c r27eddb52  
    3434#ifndef DRV_OHCI_OHCI_REGS_H
    3535#define DRV_OHCI_OHCI_REGS_H
    36 #include <sys/types.h>
    37 
    38 #define LEGACY_REGS_OFFSET 0x100
     36#include <stdint.h>
    3937
    4038/** OHCI memory mapped registers structure */
    4139typedef struct ohci_regs {
    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)
     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)
    5448
    5549#define C_PLE (1 << 2)   /* Periodic list enable */
     
    6559#define C_HCFS_SHIFT       (6)
    6660
    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 
    7661#define C_IR  (1 << 8)   /* Interrupt routing, make sure it's 0 */
    7762#define C_RWC (1 << 9)   /* Remote wakeup connected, host specific */
    7863#define C_RWE (1 << 10)  /* Remote wakeup enable */
    7964
    80         ioport32_t command_status;
     65        volatile uint32_t command_status;
    8166#define CS_HCR (1 << 0)   /* Host controller reset */
    8267#define CS_CLF (1 << 1)   /* Control list filled */
     
    9075         * writing causes enable/disable,
    9176         * status is write-clean (writing 1 clears the bit*/
    92         ioport32_t interrupt_status;
    93         ioport32_t interrupt_enable;
    94         ioport32_t interrupt_disable;
     77        volatile uint32_t interrupt_status;
     78        volatile uint32_t interrupt_enable;
     79        volatile uint32_t interrupt_disable;
    9580#define I_SO   (1 << 0)   /* Scheduling overrun */
    9681#define I_WDH  (1 << 1)   /* Done head write-back */
     
    10489
    10590        /** HCCA pointer (see hw_struct hcca.h) */
    106         ioport32_t hcca;
     91        volatile uint32_t hcca;
    10792#define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */
    10893
    10994        /** Currently executed periodic endpoint */
    110         const ioport32_t periodic_current;
     95        const volatile uint32_t periodic_current;
    11196
    11297        /** The first control endpoint */
    113         ioport32_t control_head;
     98        volatile uint32_t control_head;
    11499
    115100        /** Currently executed control endpoint */
    116         ioport32_t control_current;
     101        volatile uint32_t control_current;
    117102
    118103        /** The first bulk endpoint */
    119         ioport32_t bulk_head;
     104        volatile uint32_t bulk_head;
    120105
    121106        /** Currently executed bulk endpoint */
    122         ioport32_t bulk_current;
     107        volatile uint32_t bulk_current;
    123108
    124109        /** Done TD list, this value is periodically written to HCCA */
    125         const ioport32_t done_head;
     110        const volatile uint32_t done_head;
    126111
    127112        /** Frame time and max packet size for all transfers */
    128         ioport32_t fm_interval;
     113        volatile uint32_t fm_interval;
    129114#define FMI_FI_MASK (0x3fff) /* Frame interval in bit times (should be 11999)*/
    130115#define FMI_FI_SHIFT (0)
     
    134119
    135120        /** Bit times remaining in current frame */
    136         const ioport32_t fm_remaining;
     121        const volatile uint32_t fm_remaining;
    137122#define FMR_FR_MASK FMI_FI_MASK
    138123#define FMR_FR_SHIFT FMI_FI_SHIFT
     
    140125
    141126        /** Frame number */
    142         const ioport32_t fm_number;
     127        const volatile uint32_t fm_number;
    143128#define FMN_NUMBER_MASK (0xffff)
    144129
    145130        /** Remaining bit time in frame to start periodic transfers */
    146         ioport32_t periodic_start;
     131        volatile uint32_t periodic_start;
    147132#define PS_PS_MASK (0x3fff) /* bit time when periodic get priority (0x3e67) */
    148133
    149134        /** Threshold for starting LS transaction */
    150         ioport32_t ls_threshold;
     135        volatile uint32_t ls_threshold;
    151136#define LST_LST_MASK (0x7fff)
    152137
    153138        /** The first root hub control register */
    154         ioport32_t rh_desc_a;
     139        volatile uint32_t rh_desc_a;
    155140#define RHDA_NDS_MASK (0xff) /* Number of downstream ports, max 15 */
    156141#define RHDA_NDS_SHIFT (0)
     
    159144#define RHDA_DT_FLAG   (1 << 10) /* 1-Compound device, must be 0 */
    160145#define RHDA_OCPM_FLAG (1 << 11) /* Over-current mode: 0-global, 1-per port */
    161 #define RHDA_NOCP_FLAG (1 << 12) /* OC control: 0-use OCPM, 1-OC off */
     146#define RHDA_NOCP      (1 << 12) /* OC control: 0-use OCPM, 1-OC off */
    162147#define RHDA_POTPGT_MASK (0xff)  /* Power on to power good time */
    163148#define RHDA_POTPGT_SHIFT (24)
    164149
    165150        /** The other root hub control register */
    166         ioport32_t rh_desc_b;
     151        volatile uint32_t rh_desc_b;
    167152#define RHDB_DR_MASK (0xffff) /* Device removable mask */
    168153#define RHDB_DR_SHIFT (0)
     
    176161
    177162        /** Root hub status register */
    178         ioport32_t rh_status;
     163        volatile uint32_t rh_status;
    179164#define RHS_LPS_FLAG  (1 <<  0)/* read: 0,
    180165                                * write: 0-no effect,
     
    182167                                *        specified in PPCM(RHDB), or all ports,
    183168                                *        if power is set globally */
    184 #define RHS_CLEAR_GLOBAL_POWER RHS_LPS_FLAG /* synonym for the above */
     169#define RHS_CLEAR_PORT_POWER RHS_LPS_FLAG /* synonym for the above */
    185170#define RHS_OCI_FLAG  (1 <<  1)/* Over-current indicator, if per-port: 0 */
    186171#define RHS_DRWE_FLAG (1 << 15)/* read: 0-connect status change does not wake HC
     
    193178                                *        specified in PPCM(RHDB), or all ports,
    194179                                *        if power is set globally */
    195 #define RHS_SET_GLOBAL_POWER RHS_LPSC_FLAG /* synonym for the above */
     180#define RHS_SET_PORT_POWER RHS_LPSC_FLAG /* synonym for the above */
    196181#define RHS_OCIC_FLAG (1 << 17)/* Over-current indicator change   */
    197182#define RHS_CLEAR_DRWE (1 << 31)
    198183
    199184        /** Root hub per port status */
    200         ioport32_t rh_port_status[];
     185        volatile uint32_t rh_port_status[];
    201186#define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,
    202187                                * w: 1-clear port enable, 0-nothing */
  • uspace/drv/bus/usb/ohci/root_hub.c

    r4069f5c r27eddb52  
    4040#include "root_hub.h"
    4141#include <usb/classes/classes.h>
    42 #include <usb/classes/hub.h>
    4342#include <usb/dev/driver.h>
    4443#include "ohci_regs.h"
     
    5756        .device_subclass = 0,
    5857        .device_version = 0,
    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.*/
     58        .length = sizeof (usb_standard_device_descriptor_t),
     59        .max_packet_size = 8,
     60        .vendor_id = 0x16db,
    6261        .product_id = 0x0001,
    6362        .str_serial_number = 0,
     
    7473        .descriptor_type = USB_DESCTYPE_CONFIGURATION,
    7574        .interface_count = 1,
    76         .length = sizeof(usb_standard_configuration_descriptor_t),
    77         .max_power = 0, /* root hubs don't need no power */
     75        .length = sizeof (usb_standard_configuration_descriptor_t),
     76        .max_power = 100,
    7877        .str_configuration = 0,
    7978};
     
    9089        .interface_protocol = 0,
    9190        .interface_subclass = 0,
    92         .length = sizeof(usb_standard_interface_descriptor_t),
     91        .length = sizeof (usb_standard_interface_descriptor_t),
    9392        .str_interface = 0,
    9493};
     
    101100        .descriptor_type = USB_DESCTYPE_ENDPOINT,
    102101        .endpoint_address = 1 + (1 << 7),
    103         .length = sizeof(usb_standard_endpoint_descriptor_t),
    104         .max_packet_size = 2,
     102        .length = sizeof (usb_standard_endpoint_descriptor_t),
     103        .max_packet_size = 8,
    105104        .poll_interval = 255,
    106105};
    107106
    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 {
     107/**
     108 * bitmask of hub features that are valid to be cleared
     109 */
     110static 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 */
     117static 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 */
     123static 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 */
     130static 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 */
     136static 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 */
     145static 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 */
     162static const uint32_t port_status_change_mask = RHPS_CHANGE_WC_MASK;
     163
     164static int create_serialized_hub_descriptor(rh_t *instance);
     165
     166static int rh_init_descriptors(rh_t *instance);
     167
     168static int process_get_port_status_request(rh_t *instance, uint16_t port,
     169    usb_transfer_batch_t * request);
     170
     171static int process_get_hub_status_request(rh_t *instance,
     172    usb_transfer_batch_t * request);
     173
     174static int process_get_status_request(rh_t *instance,
     175    usb_transfer_batch_t * request);
     176
     177static void create_interrupt_mask_in_instance(rh_t *instance);
     178
     179static int process_get_descriptor_request(rh_t *instance,
     180    usb_transfer_batch_t *request);
     181
     182static int process_get_configuration_request(rh_t *instance,
     183    usb_transfer_batch_t *request);
     184
     185static int process_hub_feature_set_request(rh_t *instance, uint16_t feature);
     186
     187static int process_hub_feature_clear_request(rh_t *instance,
     188    uint16_t feature);
     189
     190static int process_port_feature_set_request(rh_t *instance,
     191    uint16_t feature, uint16_t port);
     192
     193static int process_port_feature_clear_request(rh_t *instance,
     194    uint16_t feature, uint16_t port);
     195
     196static int process_address_set_request(rh_t *instance,
     197    uint16_t address);
     198
     199static int process_request_with_output(rh_t *instance,
     200    usb_transfer_batch_t *request);
     201
     202static int process_request_with_input(rh_t *instance,
     203    usb_transfer_batch_t *request);
     204
     205static int process_request_without_data(rh_t *instance,
     206    usb_transfer_batch_t *request);
     207
     208static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
     209
     210static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request);
     211
     212static bool is_zeros(void * buffer, size_t size);
     213
     214/** Root hub initialization
     215 * @return Error code.
     216 */
     217int rh_init(rh_t *instance, ohci_regs_t *regs) {
    140218        assert(instance);
    141         assert(regs);
    142 
    143219        instance->registers = regs;
    144220        instance->port_count =
    145221            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
    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);
     222        int opResult = rh_init_descriptors(instance);
     223        if (opResult != EOK) {
     224                return opResult;
     225        }
     226        // set port power mode to no-power-switching
     227        instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
    154228        instance->unfinished_interrupt_transfer = NULL;
    155 
    156 #ifdef OHCI_POWER_SWITCH_no
    157         /* Set port power mode to no power-switching. (always on) */
    158         instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
    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);
     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;
    186233
    187234        usb_log_info("Root hub (%zu ports) initialized.\n",
    188235            instance->port_count);
    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 {
     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 */
     248int rh_request(rh_t *instance, usb_transfer_batch_t *request) {
    200249        assert(instance);
    201250        assert(request);
    202 
    203         switch (request->ep->transfer_type)
    204         {
    205         case USB_TRANSFER_CONTROL:
     251        int opResult;
     252        if (request->ep->transfer_type == USB_TRANSFER_CONTROL) {
    206253                usb_log_debug("Root hub got CONTROL packet\n");
    207                 const int ret = control_request(instance, request);
    208                 usb_transfer_batch_finish_error(request, ret);
    209                 break;
    210         case USB_TRANSFER_INTERRUPT:
     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) {
    211257                usb_log_debug("Root hub got INTERRUPT packet\n");
    212                 const uint16_t mask = create_interrupt_mask(instance);
    213                 if (mask == 0) {
     258                create_interrupt_mask_in_instance(instance);
     259                if (is_zeros(instance->interrupt_buffer,
     260                    instance->interrupt_mask_size)) {
    214261                        usb_log_debug("No changes..\n");
    215                         assert(instance->unfinished_interrupt_transfer == NULL);
    216262                        instance->unfinished_interrupt_transfer = request;
    217                         break;
    218                 }
    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.
     263                        //will be finished later
     264                } else {
     265                        usb_log_debug("Processing changes..\n");
     266                        process_interrupt_mask_in_instance(instance, request);
     267                }
     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
    231281 *
    232282 * If there is no pending interrupt transfer, nothing happens.
    233283 * @param instance
    234284 */
    235 void rh_interrupt(rh_t *instance)
    236 {
    237         assert(instance);
    238 
    239         if (!instance->unfinished_interrupt_transfer)
     285void rh_interrupt(rh_t *instance) {
     286        if (!instance->unfinished_interrupt_transfer) {
    240287                return;
    241 
     288        }
    242289        usb_log_debug("Finalizing interrupt transfer\n");
    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.
     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 *
     302 * @param instance root hub instance
     303 * @return error code
     304 */
     305static 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 */
     354static 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 */
     407static 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 */
     429static 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
     443 *
     444 * This might be either hub status or port status request. If neither,
     445 * ENOTSUP is returned.
     446 * @param instance root hub instance
     447 * @param request structure containing both request and response information
     448 * @return error code
     449 */
     450static 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);
     469
     470        return ENOTSUP;
     471}
     472/*----------------------------------------------------------------------------*/
     473
     474/**
     475 * create answer to status interrupt consisting of change bitmap
    335476 *
    336477 * Result contains bitmap where bit 0 indicates change on hub and
     
    338479 * Hub and Port status bitmap specification in USB specification
    339480 * (chapter 11.13.4).
    340  * @param instance root hub instance
    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.
    367  *
    368  * This might be either hub status or port status request. If neither,
    369  * ENOTSUP is returned.
    370  * @param instance root hub instance
    371  * @param request structure containing both request and response information
    372  * @return error code
    373  */
    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         }
    407 
    408         return ENOTSUP;
    409 }
    410 /*----------------------------------------------------------------------------*/
    411 /**
    412  * Create answer to a descriptor request.
     481 * Uses instance`s interrupt buffer to store the interrupt information.
     482 * @param instance root hub instance
     483 */
     484static 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
    413505 *
    414506 * This might be a request for standard (configuration, device, endpoint or
    415507 * interface) or device specific (hub) descriptor.
    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;
     508 * @param instance root hub instance
     509 * @param request structure containing both request and response information
     510 * @return error code
     511 */
     512static 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;
    427516        size_t size;
    428         const void *descriptor = NULL;
     517        const void * result_descriptor = NULL;
    429518        const uint16_t setup_request_value = setup_request->value_high;
    430519        //(setup_request->value_low << 8);
    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;
     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                }
    480570        }
    481571        if (request->buffer_size < size) {
    482572                size = request->buffer_size;
    483573        }
    484 
    485         memcpy(request->data_buffer, descriptor, size);
    486         TRANSFER_OK(size);
    487 }
    488 /*----------------------------------------------------------------------------*/
     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 */
     589static 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 */
     609static 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 */
     630static 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
    489650/**
    490651 * process feature-enabling request on hub
     
    496657 * @return error code
    497658 */
    498 int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
    499 {
    500         assert(instance);
    501 
     659static 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;
    502663        if (port < 1 || port > instance->port_count)
    503664                return EINVAL;
    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.
     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
    530674 *
    531675 * @param instance root hub instance
     
    535679 * @return error code
    536680 */
    537 int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
    538 {
    539         assert(instance);
    540 
     681static 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;
    541685        if (port < 1 || port > instance->port_count)
    542686                return EINVAL;
    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;
     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 */
     707static 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 */
     722static 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 */
     752static 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) {
     758                return ENOTSUP;
     759        }
     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
    558764                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:
    581                 return ENOTSUP;
    582         }
    583 }
    584 /*----------------------------------------------------------------------------*/
     765        }
     766        return ENOTSUP;
     767}
     768/*----------------------------------------------------------------------------*/
     769
    585770/**
    586771 * process one of requests that do not request nor carry additional data
     
    592777 * @return error code
    593778 */
    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",
     779static 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",
    616797                    setup_request->request_type);
    617798                return EINVAL;
    618799        }
    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);
    656                 }
    657         default:
    658                 usb_log_error("Invalid clear feature request type: %d\n",
     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);
     805                }
     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",
    659813                    setup_request->request_type);
    660814                return EINVAL;
    661815        }
    662 }
    663 /*----------------------------------------------------------------------------*/
    664 /**
    665  * Process hub control request.
     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
    666830 *
    667831 * If needed, writes answer into the request structure.
     
    680844 * @return error code
    681845 */
    682 int control_request(rh_t *instance, usb_transfer_batch_t *request)
    683 {
    684         assert(instance);
    685         assert(request);
    686 
     846static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) {
    687847        if (!request->setup_buffer) {
    688                 usb_log_error("Root hub received empty transaction!");
    689                 return EINVAL;
    690         }
    691 
    692         if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) {
     848                usb_log_error("root hub received empty transaction?");
     849                return EINVAL;
     850        }
     851        int opResult;
     852        if (sizeof (usb_device_request_setup_packet_t) > request->setup_size) {
    693853                usb_log_error("Setup packet too small\n");
    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         }
     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 */
     907static 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 */
     928static 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;
    743937}
    744938
  • uspace/drv/bus/usb/ohci/root_hub.h

    r4069f5c r27eddb52  
    4141#include "batch.h"
    4242
    43 #define HUB_DESCRIPTOR_MAX_SIZE (7 + 2 + 2)
    44 
    4543/**
    4644 * ohci root hub representation
     
    5351        /** hub port count */
    5452        size_t port_count;
     53        /** hubs descriptors */
     54        usb_device_descriptors_t descriptors;
    5555        /** interrupt transfer waiting for an actual interrupt to occur */
    56         usb_transfer_batch_t *unfinished_interrupt_transfer;
     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;
    5764        /** size of interrupt buffer */
    5865        size_t interrupt_mask_size;
    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;
     66        /** instance`s descriptor*/
     67        uint8_t * hub_descriptor;
    6668        /** size of hub descriptor */
    67         size_t hub_descriptor_size;
     69        size_t descriptor_size;
     70
    6871
    6972} rh_t;
    7073
    71 void rh_init(rh_t *instance, ohci_regs_t *regs);
     74int rh_init(rh_t *instance, ohci_regs_t *regs);
    7275
    73 void rh_request(rh_t *instance, usb_transfer_batch_t *request);
     76int rh_request(rh_t *instance, usb_transfer_batch_t *request);
    7477
    7578void rh_interrupt(rh_t *instance);
  • uspace/drv/bus/usb/uhci/hc.c

    r4069f5c r27eddb52  
    4747    (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
    4848
    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 };
    5849
    5950static int hc_init_transfer_lists(hc_t *instance);
     
    6354static int hc_interrupt_emulator(void *arg);
    6455static 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*)&registers->usbsts;
    95         cmds[3].addr = (void*)&registers->usbsts;
    96         return EOK;
    97 }
    9856/*----------------------------------------------------------------------------*/
    9957/** Initialize UHCI hc driver structure
     
    11169int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts)
    11270{
    113         assert(reg_size >= sizeof(uhci_regs_t));
     71        assert(reg_size >= sizeof(regs_t));
    11472        int ret;
    11573
     
    12482
    12583        /* allow access to hc control registers */
    126         uhci_regs_t *io;
     84        regs_t *io;
    12785        ret = pio_enable(regs, reg_size, (void **)&io);
    128         CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p: %s.\n",
    129             io, str_error(ret));
     86        CHECK_RET_RETURN(ret,
     87            "Failed(%d) to gain access to registers at %p: %s.\n",
     88            ret, io, str_error(ret));
    13089        instance->registers = io;
    131         usb_log_debug(
    132             "Device registers at %p (%zuB) accessible.\n", io, reg_size);
     90        usb_log_debug("Device registers at %p (%zuB) accessible.\n",
     91            io, reg_size);
    13392
    13493        ret = hc_init_mem_structures(instance);
    13594        CHECK_RET_RETURN(ret,
    136             "Failed to initialize UHCI memory structures: %s.\n",
    137             str_error(ret));
     95            "Failed(%d) to initialize UHCI memory structures: %s.\n",
     96            ret, str_error(ret));
    13897
    13998        hc_init_hw(instance);
     
    157116{
    158117        assert(instance);
    159         uhci_regs_t *registers = instance->registers;
     118        regs_t *registers = instance->registers;
    160119
    161120        /* Reset everything, who knows what touched it before us */
    162121        pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
    163         async_usleep(50000); /* 50ms according to USB spec(root hub reset) */
     122        async_usleep(10000); /* 10ms according to USB spec */
    164123        pio_write_16(&registers->usbcmd, 0);
    165124
    166         /* Reset hc, all states and counters. Hope that hw is not broken */
     125        /* Reset hc, all states and counters */
    167126        pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
    168127        do { async_usleep(10); }
     
    182141        }
    183142
    184         const uint16_t cmd = pio_read_16(&registers->usbcmd);
    185         if (cmd != 0)
    186                 usb_log_warning("Previous command value: %x.\n", cmd);
     143        const uint16_t status = pio_read_16(&registers->usbcmd);
     144        if (status != 0)
     145                usb_log_warning("Previous command value: %x.\n", status);
    187146
    188147        /* Start the hc with large(64B) packet FSBR */
     
    211170        } else (void) 0
    212171
     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
    213205        /* Init transfer lists */
    214206        int ret = hc_init_transfer_lists(instance);
    215         CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
     207        CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n");
    216208        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        }
    217224
    218225        /* Init device keeper */
    219226        usb_device_keeper_init(&instance->manager);
    220         usb_log_debug("Initialized device keeper.\n");
     227        usb_log_debug("Initialized device manager.\n");
    221228
    222229        ret = usb_endpoint_manager_init(&instance->ep_manager,
     
    225232            str_error(ret));
    226233
    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 
    244234        return EOK;
    245235#undef CHECK_RET_RETURN
     
    262252        int ret = transfer_list_init(&instance->transfers_##type, name); \
    263253        if (ret != EOK) { \
    264                 usb_log_error("Failed to setup %s transfer list: %s.\n", \
    265                     name, str_error(ret)); \
     254                usb_log_error("Failed(%d) to setup %s transfer list: %s.\n", \
     255                    ret, name, str_error(ret)); \
    266256                transfer_list_fini(&instance->transfers_bulk_full); \
    267257                transfer_list_fini(&instance->transfers_control_full); \
  • uspace/drv/bus/usb/uhci/hc.h

    r4069f5c r27eddb52  
    8484        /** SOF modification to match external timers */
    8585        uint8_t sofmod;
    86 } uhci_regs_t;
     86} regs_t;
    8787
    8888#define UHCI_FRAME_LIST_COUNT 1024
     
    100100
    101101        /** Addresses of I/O registers */
    102         uhci_regs_t *registers;
     102        regs_t *registers;
    103103
    104104        /** Frame List contains 1024 link pointers */
     
    116116        /** Pointer table to the above lists, helps during scheduling */
    117117        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
    118125        /** Fibril periodically checking status register*/
    119126        fid_t interrupt_emulator;
     127
    120128        /** Indicator of hw interrupts availability */
    121129        bool hw_interrupts;
     
    124132        unsigned hw_failures;
    125133} hc_t;
    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);
     134
    129135int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
     136
    130137int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
     138
    131139void hc_interrupt(hc_t *instance, uint16_t status);
    132140
  • uspace/drv/bus/usb/uhci/root_hub.c

    r4069f5c r27eddb52  
    5050int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
    5151{
    52         int ret;
    53 
    5452        assert(fun);
    5553
    56         ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);
     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);
    5765        if (ret != EOK) {
    58                 usb_log_error("Failed to add root hub match id: %s\n",
    59                     str_error(ret));
     66                free(match_str);
     67                usb_log_error("Failed(%d) to add root hub match id: %s\n",
     68                    ret, str_error(ret));
    6069                return ret;
    6170        }
  • uspace/drv/bus/usb/uhci/uhci.c

    r4069f5c r27eddb52  
    6464{
    6565        assert(dev);
     66        assert(dev->driver_data);
    6667        return dev->driver_data;
    6768}
     
    7778        assert(dev);
    7879        uhci_t *uhci = dev_to_uhci(dev);
    79         if (!uhci) {
    80                 usb_log_error("Interrupt on not yet initialized device.\n");
    81                 return;
    82         }
     80        hc_t *hc = &uhci->hc;
    8381        const uint16_t status = IPC_GET_ARG1(*call);
    84         hc_interrupt(&uhci->hc, status);
     82        assert(hc);
     83        hc_interrupt(hc, status);
    8584}
    8685/*----------------------------------------------------------------------------*/
     
    193192        } \
    194193        free(instance); \
    195         device->driver_data = NULL; \
    196194        usb_log_error(message); \
    197195        return ret; \
     
    224222        ret = pci_disable_legacy(device);
    225223        CHECK_RET_DEST_FREE_RETURN(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));
     224            "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
    241225
    242226        bool interrupts = false;
     227#ifdef CONFIG_USBHC_NO_INTERRUPTS
     228        usb_log_warning("Interrupts disabled in OS config, " \
     229            "falling back to polling.\n");
     230#else
    243231        ret = pci_enable_interrupts(device);
    244232        if (ret != EOK) {
    245                 usb_log_warning("Failed to enable interrupts: %s."
    246                     " Falling back to polling.\n", str_error(ret));
     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");
    247237        } else {
    248238                usb_log_debug("Hw interrupts enabled.\n");
    249239                interrupts = true;
    250240        }
     241#endif
     242
    251243
    252244        ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
    253245        CHECK_RET_DEST_FREE_RETURN(ret,
    254             "Failed to init uhci_hcd: %s.\n", str_error(ret));
    255 
    256         device->driver_data = instance;
     246            "Failed(%d) to init uhci_hcd: %s.\n", ret, str_error(ret));
    257247
    258248#define CHECK_RET_FINI_RETURN(ret, message...) \
     
    263253} else (void)0
    264254
     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
    265262        ret = ddf_fun_bind(instance->hc_fun);
    266         CHECK_RET_FINI_RETURN(ret, "Failed to bind UHCI device function: %s.\n",
    267             str_error(ret));
     263        CHECK_RET_FINI_RETURN(ret,
     264            "Failed(%d) to bind UHCI device function: %s.\n",
     265            ret, str_error(ret));
    268266
    269267        ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
     
    274272            (uintptr_t)instance->hc.registers + 0x10, 4);
    275273        CHECK_RET_FINI_RETURN(ret,
    276             "Failed to setup UHCI root hub: %s.\n", str_error(ret));
     274            "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(ret));
    277275
    278276        ret = ddf_fun_bind(instance->rh_fun);
    279277        CHECK_RET_FINI_RETURN(ret,
    280             "Failed to register UHCI root hub: %s.\n", str_error(ret));
    281 
     278            "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
     279
     280        device->driver_data = instance;
    282281        return EOK;
    283282#undef CHECK_RET_FINI_RETURN
  • uspace/drv/bus/usb/usbhub/usbhub.c

    r4069f5c r27eddb52  
    220220 * @return error code
    221221 */
    222 int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info)
    223 {
     222static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) {
    224223        // get hub descriptor
    225         usb_log_debug("Retrieving descriptor\n");
     224        usb_log_debug("Creating serialized descriptor\n");
    226225        uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE];
     226        usb_hub_descriptor_t * descriptor;
    227227        int opResult;
    228228
     
    234234
    235235        if (opResult != EOK) {
    236                 usb_log_error("Failed to receive hub descriptor: %s.\n",
    237                     str_error(opResult));
     236                usb_log_error("Failed when receiving hub descriptor, "
     237                    "%s\n",
     238                    str_error(opResult));
     239                free(serialized_descriptor);
    238240                return opResult;
    239241        }
    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));
     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));
    254257        if (!hub_info->ports) {
    255258                return ENOMEM;
    256259        }
    257 
    258260        size_t port;
    259261        for (port = 0; port < hub_info->port_count + 1; ++port) {
    260262                usb_hub_port_init(&hub_info->ports[port]);
    261263        }
    262 
    263         const bool is_power_switched =
    264             !(descriptor.hub_characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG);
    265264        if (is_power_switched) {
    266265                usb_log_debug("Hub power switched\n");
    267                 const bool per_port_power = descriptor.hub_characteristics
    268                     & HUB_CHAR_POWER_PER_PORT_FLAG;
     266
     267                if (!has_individual_port_powering) {
     268                        //this setting actually makes no difference
     269                        usb_log_debug("Hub has global powering\n");
     270                }
    269271
    270272                for (port = 1; port <= hub_info->port_count; ++port) {
    271273                        usb_log_debug("Powering port %zu.\n", port);
    272                         opResult = usb_hub_set_port_feature(
    273                             hub_info->control_pipe,
     274                        opResult = usb_hub_set_port_feature(hub_info->control_pipe,
    274275                            port, USB_HUB_FEATURE_PORT_POWER);
    275276                        if (opResult != EOK) {
    276277                                usb_log_error("Cannot power on port %zu: %s.\n",
    277278                                    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                                 }
    285279                        }
    286280                }
     
    289283                usb_log_debug("Power not switched, not going to be powered\n");
    290284        }
     285        usb_log_debug2("Freeing data\n");
     286        free(descriptor);
    291287        return EOK;
    292288}
  • uspace/drv/bus/usb/usbhub/usbhub_private.h

    r4069f5c r27eddb52  
    171171    void * serialized_descriptor);
    172172
    173 int usb_deserialize_hub_desriptor(
    174     void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor);
     173usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
     174    void * serialized_descriptor);
     175
     176void usb_deserialize_hub_desriptor(void * serialized_descriptor,
     177    usb_hub_descriptor_t * descriptor);
    175178
    176179
  • uspace/drv/bus/usb/usbhub/utils.c

    r4069f5c r27eddb52  
    110110}
    111111
    112 /*----------------------------------------------------------------------------*/
    113112/**
    114  * Deserialize descriptor into given pointer
     113 * create deserialized desriptor structure out of serialized descriptor
    115114 *
     115 * The serialized descriptor must be proper usb hub descriptor,
     116 * otherwise an eerror might occur.
     117 *
     118 * @param sdescriptor serialized descriptor
     119 * @return newly created deserialized descriptor pointer
     120 */
     121usb_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 pointer
     139 *
    116140 * @param serialized_descriptor
    117141 * @param descriptor
    118142 * @return
    119143 */
    120 int usb_deserialize_hub_desriptor(
    121     void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor)
    122 {
     144void usb_deserialize_hub_desriptor(
     145    void * serialized_descriptor, usb_hub_descriptor_t *descriptor) {
    123146        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 
    135147        descriptor->ports_count = sdescriptor[2];
    136         descriptor->hub_characteristics = sdescriptor[3] + 256 * sdescriptor[4];
     148        /// @fixme handling of endianness??
     149        descriptor->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3];
    137150        descriptor->pwr_on_2_good_time = sdescriptor[5];
    138151        descriptor->current_requirement = sdescriptor[6];
    139         const size_t var_size = (descriptor->ports_count + 7) / 8;
     152        size_t var_size = (descriptor->ports_count + 7) / 8;
    140153        //descriptor->devices_removable = (uint8_t*) malloc(var_size);
    141154
    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) {
     155        size_t i;
     156        for (i = 0; i < var_size; ++i) {
    148157                descriptor->devices_removable[i] = sdescriptor[7 + i];
    149158        }
    150         return EOK;
    151159}
    152 /*----------------------------------------------------------------------------*/
     160
    153161/**
    154162 * @}
  • uspace/drv/bus/usb/usbmast/Makefile

    r4069f5c r27eddb52  
    4444
    4545SOURCES = \
    46         bo_trans.c \
    47         cmdw.c \
     46        cmds.c \
    4847        main.c \
     48        mast.c \
    4949        scsi_ms.c
    5050
  • uspace/drv/bus/usb/usbmast/main.c

    r4069f5c r27eddb52  
    4545#include <errno.h>
    4646#include <str_error.h>
    47 #include "cmdw.h"
    48 #include "bo_trans.h"
     47#include "cmds.h"
     48#include "mast.h"
    4949#include "scsi_ms.h"
    50 #include "usbmast.h"
    5150
    5251#define NAME "usbmast"
     
    7877};
    7978
    80 static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun);
     79/** Mass storage function.
     80 *
     81 * Serves as soft state for function/LUN.
     82 */
     83typedef 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
    8194static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
    8295    void *arg);
     
    90103{
    91104        int rc;
    92         usbmast_dev_t *mdev = NULL;
    93         unsigned i;
     105        const char *fun_name = "a";
     106        ddf_fun_t *fun = NULL;
     107        usbmast_fun_t *msfun = NULL;
    94108
    95109        /* Allocate softstate */
    96         mdev = calloc(1, sizeof(usbmast_dev_t));
    97         if (mdev == NULL) {
     110        msfun = calloc(1, sizeof(usbmast_fun_t));
     111        if (msfun == NULL) {
    98112                usb_log_error("Failed allocating softstate.\n");
    99113                rc = ENOMEM;
     
    101115        }
    102116
    103         mdev->ddf_dev = dev->ddf_dev;
    104         mdev->usb_dev = dev;
     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;
    105127
    106128        usb_log_info("Initializing mass storage `%s'.\n",
     
    114136
    115137        usb_log_debug("Get LUN count...\n");
    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;
     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        }
    177145
    178146        usb_log_debug("Inquire...\n");
    179147        usbmast_inquiry_data_t inquiry;
    180         rc = usbmast_inquiry(mfun, &inquiry);
     148        rc = usbmast_inquiry(dev, &inquiry);
    181149        if (rc != EOK) {
    182150                usb_log_warning("Failed to inquire device `%s': %s.\n",
    183                     mdev->ddf_dev->name, str_error(rc));
     151                    dev->ddf_dev->name, str_error(rc));
    184152                rc = EIO;
    185153                goto error;
    186154        }
    187155
    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,
     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,
    192159            inquiry.product,
    193160            inquiry.vendor,
    194161            inquiry.revision,
    195162            usbmast_scsi_dev_type_str(inquiry.device_type),
    196             inquiry.removable ? "removable" : "non-removable");
     163            inquiry.removable ? "removable" : "non-removable",
     164            lun_count);
    197165
    198166        uint32_t nblocks, block_size;
    199167
    200         rc = usbmast_read_capacity(mfun, &nblocks, &block_size);
     168        rc = usbmast_read_capacity(dev, &nblocks, &block_size);
    201169        if (rc != EOK) {
    202170                usb_log_warning("Failed to read capacity, device `%s': %s.\n",
    203                     mdev->ddf_dev->name, str_error(rc));
     171                    dev->ddf_dev->name, str_error(rc));
    204172                rc = EIO;
    205173                goto error;
     
    209177            "block_size=%" PRIu32 "\n", nblocks, block_size);
    210178
    211         mfun->nblocks = nblocks;
    212         mfun->block_size = block_size;
     179        msfun->nblocks = nblocks;
     180        msfun->block_size = block_size;
     181        msfun->usb_dev = dev;
    213182
    214183        rc = ddf_fun_bind(fun);
     
    225194        if (fun != NULL)
    226195                ddf_fun_destroy(fun);
    227         if (fun_name != NULL)
    228                 free(fun_name);
    229         if (mfun != NULL)
    230                 free(mfun);
     196        if (msfun != NULL)
     197                free(msfun);
    231198        return rc;
    232199}
     
    236203    void *arg)
    237204{
    238         usbmast_fun_t *mfun;
     205        usbmast_fun_t *msfun;
    239206        void *comm_buf = NULL;
    240207        size_t comm_size;
     
    262229        (void) async_share_out_finalize(callid, comm_buf);
    263230
    264         mfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
     231        msfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
    265232
    266233        while (true) {
     
    276243                switch (method) {
    277244                case BD_GET_BLOCK_SIZE:
    278                         async_answer_1(callid, EOK, mfun->block_size);
     245                        async_answer_1(callid, EOK, msfun->block_size);
    279246                        break;
    280247                case BD_GET_NUM_BLOCKS:
    281                         async_answer_2(callid, EOK, LOWER32(mfun->nblocks),
    282                             UPPER32(mfun->nblocks));
     248                        async_answer_2(callid, EOK, LOWER32(msfun->nblocks),
     249                            UPPER32(msfun->nblocks));
    283250                        break;
    284251                case BD_READ_BLOCKS:
    285252                        ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
    286253                        cnt = IPC_GET_ARG3(call);
    287                         retval = usbmast_read(mfun, ba, cnt, comm_buf);
     254                        retval = usbmast_read(msfun->usb_dev, ba, cnt,
     255                            msfun->block_size, comm_buf);
    288256                        async_answer_0(callid, retval);
    289257                        break;
     
    291259                        ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
    292260                        cnt = IPC_GET_ARG3(call);
    293                         retval = usbmast_write(mfun, ba, cnt, comm_buf);
     261                        retval = usbmast_write(msfun->usb_dev, ba, cnt,
     262                            msfun->block_size, comm_buf);
    294263                        async_answer_0(callid, retval);
    295264                        break;
  • uspace/drv/bus/usb/usbmast/scsi_ms.c

    r4069f5c r27eddb52  
    4646#include <scsi/sbc.h>
    4747#include <scsi/spc.h>
    48 #include "cmdw.h"
    49 #include "bo_trans.h"
     48#include "cmds.h"
     49#include "mast.h"
    5050#include "scsi_ms.h"
    51 #include "usbmast.h"
    5251
    5352/** Get string representation for SCSI peripheral device type.
     
    6362/** Perform SCSI Inquiry command on USB mass storage device.
    6463 *
    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)
     64 * @param dev           USB device.
     65 * @param inquiry_result Where to store parsed inquiry result.
     66 * @return              Error code.
     67 */
     68int usbmast_inquiry(usb_device_t *dev, usbmast_inquiry_data_t *inq_res)
    7069{
    7170        scsi_std_inquiry_data_t inq_data;
     
    7877        cdb.alloc_len = host2uint16_t_be(sizeof(inq_data));
    7978
    80         rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
     79        rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
    8180            sizeof(cdb), &inq_data, sizeof(inq_data), &response_len);
    8281
    8382        if (rc != EOK) {
    8483                usb_log_error("Inquiry failed, device %s: %s.\n",
    85                    mfun->mdev->ddf_dev->name, str_error(rc));
     84                   dev->ddf_dev->name, str_error(rc));
    8685                return rc;
    8786        }
     
    119118/** Perform SCSI Request Sense command on USB mass storage device.
    120119 *
    121  * @param mfun          Mass storage function
     120 * @param dev           USB device
    122121 * @param buf           Destination buffer
    123122 * @param size          Size of @a buf
     
    125124 * @return              Error code.
    126125 */
    127 int usbmast_request_sense(usbmast_fun_t *mfun, void *buf, size_t size)
     126int usbmast_request_sense(usb_device_t *dev, void *buf, size_t size)
    128127{
    129128        scsi_cdb_request_sense_t cdb;
     
    135134        cdb.alloc_len = min(size, SCSI_SENSE_DATA_MAX_SIZE);
    136135
    137         rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
     136        rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
    138137            sizeof(cdb), buf, size, &data_len);
    139138
    140139        if (rc != EOK) {
    141140                usb_log_error("Request Sense failed, device %s: %s.\n",
    142                    mfun->mdev->ddf_dev->name, str_error(rc));
     141                   dev->ddf_dev->name, str_error(rc));
    143142                return rc;
    144143        }
     
    155154/** Perform SCSI Read Capacity command on USB mass storage device.
    156155 *
    157  * @param mfun          Mass storage function
    158  * @param nblocks       Output, number of blocks
    159  * @param block_size    Output, block size in bytes
    160  *
    161  * @return              Error code.
    162  */
    163 int usbmast_read_capacity(usbmast_fun_t *mfun, uint32_t *nblocks,
     156 * @param dev           USB device.
     157 * @param nblocks       Output, number of blocks.
     158 * @param block_size    Output, block size in bytes.
     159 *
     160 * @return              Error code.
     161 */
     162int usbmast_read_capacity(usb_device_t *dev, uint32_t *nblocks,
    164163    uint32_t *block_size)
    165164{
     
    172171        cdb.op_code = SCSI_CMD_READ_CAPACITY_10;
    173172
    174         rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
     173        rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
    175174            sizeof(cdb), &data, sizeof(data), &data_len);
    176175
    177176        if (rc != EOK) {
    178177                usb_log_error("Read Capacity (10) failed, device %s: %s.\n",
    179                    mfun->mdev->ddf_dev->name, str_error(rc));
     178                   dev->ddf_dev->name, str_error(rc));
    180179                return rc;
    181180        }
     
    195194/** Perform SCSI Read command on USB mass storage device.
    196195 *
    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)
     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 */
     203int usbmast_read(usb_device_t *dev, uint64_t ba, size_t nblocks, size_t bsize,
     204    void *buf)
    204205{
    205206        scsi_cdb_read_12_t cdb;
     
    212213                return ELIMIT;
    213214
    214         if ((uint64_t)nblocks * mfun->block_size > UINT32_MAX)
     215        if ((uint64_t)nblocks * bsize > UINT32_MAX)
    215216                return ELIMIT;
    216217
     
    220221        cdb.xfer_len = host2uint32_t_be(nblocks);
    221222
    222         rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
    223             sizeof(cdb), buf, nblocks * mfun->block_size, &data_len);
     223        rc = usb_massstor_data_in(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
     224            sizeof(cdb), buf, nblocks * bsize, &data_len);
    224225
    225226        if (rc != EOK) {
    226227                usb_log_error("Read (12) failed, device %s: %s.\n",
    227                    mfun->mdev->ddf_dev->name, str_error(rc));
    228                 return rc;
    229         }
    230 
    231         if (data_len < nblocks * mfun->block_size) {
     228                   dev->ddf_dev->name, str_error(rc));
     229                return rc;
     230        }
     231
     232        if (data_len < nblocks * bsize) {
    232233                usb_log_error("SCSI Read response too short (%zu).\n",
    233234                    data_len);
     
    240241/** Perform SCSI Write command on USB mass storage device.
    241242 *
    242  * @param mfun          Mass storage function
     243 * @param dev           USB device
    243244 * @param ba            Address of first block
    244245 * @param nblocks       Number of blocks to read
     246 * @param bsize         Block size
    245247 * @param data          Data to write
    246248 *
    247249 * @return              Error code
    248250 */
    249 int usbmast_write(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks,
     251int usbmast_write(usb_device_t *dev, uint64_t ba, size_t nblocks, size_t bsize,
    250252    const void *data)
    251253{
     
    254256        int rc;
    255257
     258        /* XXX Need softstate to store block size. */
     259
    256260        if (ba > UINT32_MAX)
    257261                return ELIMIT;
    258262
    259         if ((uint64_t)nblocks * mfun->block_size > UINT32_MAX)
     263        if ((uint64_t)nblocks * bsize > UINT32_MAX)
    260264                return ELIMIT;
    261265
     
    265269        cdb.xfer_len = host2uint32_t_be(nblocks);
    266270
    267         rc = usb_massstor_data_out(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
    268             sizeof(cdb), data, nblocks * mfun->block_size, &sent_len);
     271        rc = usb_massstor_data_out(dev, 0xDEADBEEF, 0, (uint8_t *) &cdb,
     272            sizeof(cdb), data, nblocks * bsize, &sent_len);
    269273
    270274        if (rc != EOK) {
    271275                usb_log_error("Write (12) failed, device %s: %s.\n",
    272                    mfun->mdev->ddf_dev->name, str_error(rc));
    273                 return rc;
    274         }
    275 
    276         if (sent_len < nblocks * mfun->block_size) {
     276                   dev->ddf_dev->name, str_error(rc));
     277                return rc;
     278        }
     279
     280        if (sent_len < nblocks * bsize) {
    277281                usb_log_error("SCSI Write not all bytes transferred (%zu).\n",
    278282                    sent_len);
  • uspace/drv/bus/usb/usbmast/scsi_ms.h

    r4069f5c r27eddb52  
    5959} usbmast_inquiry_data_t;
    6060
    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 *);
     61extern int usbmast_inquiry(usb_device_t *, usbmast_inquiry_data_t *);
     62extern int usbmast_request_sense(usb_device_t *, void *, size_t);
     63extern int usbmast_read_capacity(usb_device_t *, uint32_t *, uint32_t *);
     64extern int usbmast_read(usb_device_t *, uint64_t, size_t, size_t, void *);
     65extern int usbmast_write(usb_device_t *, uint64_t, size_t, size_t,
     66    const void *);
    6667extern const char *usbmast_scsi_dev_type_str(unsigned);
    6768
  • uspace/drv/bus/usb/vhc/connhost.c

    r4069f5c r27eddb52  
    141141    size_t max_packet_size, unsigned int interval)
    142142{
    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);
     143        VHC_DATA(vhc, fun);
     144
     145        endpoint_t *ep = malloc(sizeof(endpoint_t));
    148146        if (ep == NULL) {
    149147                return ENOMEM;
    150148        }
    151149
    152         int rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
     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);
    153158        if (rc != EOK) {
    154159                endpoint_destroy(ep);
  • uspace/drv/infrastructure/root/root.c

    r4069f5c r27eddb52  
    176176        }
    177177
    178         free(match_id);
    179 
    180178        rc = ddf_fun_bind(fun);
    181179        if (rc != EOK) {
  • uspace/drv/test/test1/test1.c

    r4069f5c r27eddb52  
    7474        }
    7575
    76         rc = ddf_fun_add_match_id(fun, match_id, match_score);
     76        rc = ddf_fun_add_match_id(fun, str_dup(match_id), match_score);
    7777        if (rc != EOK) {
    7878                ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
  • uspace/lib/c/generic/io/io.c

    r4069f5c r27eddb52  
    714714off64_t ftell(FILE *stream)
    715715{
    716         _fflushbuf(stream);
    717716        return lseek(stream->fd, 0, SEEK_CUR);
    718717}
  • uspace/lib/clui/tinput.c

    r4069f5c r27eddb52  
    11/*
    2  * Copyright (c) 2011 Jiri Svoboda
     2 * Copyright (c) 2010 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    2727 */
    2828
    29 #include <sort.h>
    3029#include <stdio.h>
    3130#include <stdlib.h>
     
    4342#include <tinput.h>
    4443
    45 #define LIN_TO_COL(ti, lpos) ((lpos) % ((ti)->con_cols))
    46 #define LIN_TO_ROW(ti, lpos) ((lpos) / ((ti)->con_cols))
    47 
    4844/** Seek direction */
    4945typedef enum {
     
    6561static void tinput_post_seek(tinput_t *, bool);
    6662
    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 
    7363/** Create a new text input field. */
    7464tinput_t *tinput_new(void)
     
    7666        tinput_t *ti;
    7767       
    78         ti = calloc(1, sizeof(tinput_t));
     68        ti = malloc(sizeof(tinput_t));
    7969        if (ti == NULL)
    8070                return NULL;
     
    8777void tinput_destroy(tinput_t *ti)
    8878{
    89         if (ti->prompt != NULL)
    90                 free(ti->prompt);
    9179        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);
    10280}
    10381
     
    11088        tinput_sel_get_bounds(ti, &sa, &sb);
    11189       
    112         tinput_console_set_lpos(ti, ti->text_coord + start);
     90        console_set_pos(ti->console, (ti->col0 + start) % ti->con_cols,
     91            ti->row0 + (ti->col0 + start) / ti->con_cols);
    11392        console_set_style(ti->console, STYLE_NORMAL);
    11493       
     
    155134static void tinput_position_caret(tinput_t *ti)
    156135{
    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. */
     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. */
    161141static void tinput_update_origin(tinput_t *ti)
    162142{
    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;
     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;
    198149}
    199150
     
    203154                return;
    204155       
    205         unsigned new_width = LIN_TO_COL(ti, ti->text_coord) + ti->nc + 1;
     156        sysarg_t new_width = ti->col0 + ti->nc + 1;
    206157        if (new_width % ti->con_cols == 0) {
    207158                /* Advancing to new line. */
     
    234185                return;
    235186       
    236         unsigned new_width = LIN_TO_COL(ti, ti->text_coord) + ti->nc + ilen;
    237         unsigned new_height = (new_width / ti->con_cols) + 1;
     187        sysarg_t new_width = ti->col0 + ti->nc + ilen;
     188        sysarg_t new_height = (new_width / ti->con_cols) + 1;
    238189        if (new_height >= ti->con_rows) {
    239190                /* Disallow text longer than 1 page for now. */
     
    560511}
    561512
    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 
    699513/** Initialize text input field.
    700514 *
     
    707521        ti->hpos = 0;
    708522        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;
    738523}
    739524
     
    754539                return EIO;
    755540       
     541        if (console_get_pos(ti->console, &ti->col0, &ti->row0) != EOK)
     542                return EIO;
     543       
    756544        ti->pos = 0;
    757545        ti->sel_start = 0;
     
    761549        ti->exit_clui = false;
    762550       
    763         if (tinput_display(ti) != EOK)
    764                 return EIO;
    765        
    766551        while (!ti->done) {
    767552                console_flush(ti->console);
     
    929714                tinput_history_seek(ti, -1);
    930715                break;
    931         case KC_TAB:
    932                 tinput_text_complete(ti);
    933                 break;
    934716        default:
    935717                break;
  • uspace/lib/clui/tinput.h

    r4069f5c r27eddb52  
    11/*
    2  * Copyright (c) 2011 Jiri Svoboda
     2 * Copyright (c) 2010 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3737#define LIBCLUI_TINPUT_H_
    3838
    39 #include <adt/list.h>
     39#include <stdio.h>
    4040#include <async.h>
    4141#include <inttypes.h>
    4242#include <io/console.h>
    43 #include <stdio.h>
    4443
    4544#define HISTORY_LEN     10
    4645#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;
    10046
    10147/** Text input field (command line).
     
    10753        console_ctrl_t *console;
    10854       
    109         /** Prompt string */
    110         char *prompt;
    111        
    112         /** Completion ops. */
    113         tinput_compl_ops_t *compl_ops;
    114        
    11555        /** Buffer holding text currently being edited */
    11656        wchar_t buffer[INPUT_MAX_SIZE + 1];
    11757       
    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;
     58        /** Screen coordinates of the top-left corner of the text field */
     59        sysarg_t col0;
     60        sysarg_t row0;
    12261       
    12362        /** Screen dimensions */
     
    15190
    15291extern 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 *);
    15592extern void tinput_destroy(tinput_t *);
    15693extern int tinput_read(tinput_t *, char **);
  • uspace/lib/drv/generic/driver.c

    r4069f5c r27eddb52  
    620620                return ENOMEM;
    621621       
    622         match_id->id = str_dup(match_id_str);
     622        match_id->id = match_id_str;
    623623        match_id->score = 90;
    624624       
  • uspace/lib/usb/include/usb/classes/hub.h

    r4069f5c r27eddb52  
    119119     */
    120120    uint16_t hub_characteristics;
    121 #define HUB_CHAR_POWER_PER_PORT_FLAG  (1 << 0)
    122 #define HUB_CHAR_NO_POWER_SWITCH_FLAG (1 << 1)
    123121
    124122    /**
  • uspace/lib/usbhost/include/usb/host/endpoint.h

    r4069f5c r27eddb52  
    6161} endpoint_t;
    6262
    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);
     63int 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);
    6666
    6767void endpoint_destroy(endpoint_t *instance);
  • uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h

    r4069f5c r27eddb52  
    8282    size_t data_size)
    8383{
    84         endpoint_t *ep = endpoint_get(
    85             address, endpoint, direction, type, speed, max_packet_size);
    86         if (!ep)
     84        endpoint_t *ep = malloc(sizeof(endpoint_t));
     85        if (ep == NULL)
    8786                return ENOMEM;
    8887
    89         const int ret =
    90             usb_endpoint_manager_register_ep(instance, ep, data_size);
     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);
    9196        if (ret != EOK) {
    9297                endpoint_destroy(ep);
     98                return ret;
    9399        }
    94         return ret;
     100        return EOK;
    95101}
    96102#endif
  • uspace/lib/usbhost/src/batch.c

    r4069f5c r27eddb52  
    109109        assert(instance);
    110110        assert(instance->ep);
    111         assert(instance->next_step);
    112111        endpoint_release(instance->ep);
    113112        instance->next_step(instance);
  • uspace/lib/usbhost/src/endpoint.c

    r4069f5c r27eddb52  
    3939#include <usb/host/endpoint.h>
    4040
    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)
     41int 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)
    4444{
    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;
     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;
    6058}
    6159/*----------------------------------------------------------------------------*/
  • uspace/srv/hid/input/ctl/stty.c

    r4069f5c r27eddb52  
    3434 * @file
    3535 * @brief Serial TTY-like keyboard controller driver.
    36  *
    37  * Keyboard emulation on a serial terminal.
    3836 */
    3937
     
    6563#include <stdio.h>
    6664
    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  */
    7265static int seq_defs[] = {
    7366        /* Not shifted */
     
    8881        0,      KC_MINUS,       0x2d, GSP_END,
    8982        0,      KC_EQUALS,      0x3d, GSP_END,
    90 
    9183        0,      KC_BACKSPACE,   0x08, GSP_END,
    9284
     
    224216        0,      KC_RIGHT,       0x1b, 0x5b, 0x43, GSP_END,
    225217
    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 
    233218        0,      0
    234219};
  • uspace/srv/hid/input/generic/gsp.c

    r4069f5c r27eddb52  
    104104                if (key == 0) break;
    105105
    106                 /* Insert one sequence. */
     106                /* Insert one sequence. */             
    107107                rc = gsp_insert_seq(p, dp, mods, key);
    108108                if (rc != 0)
     
    197197
    198198        if (t == NULL) {
    199                 printf("gsp_step: not found, state=%d, input=0x%x\n",
    200                     state, input);
     199                printf("gsp_step: not found\n");
    201200                *mods = 0;
    202201                *key = 0;
     
    206205        *mods = t->out_mods;
    207206        *key = t->out_key;
    208 
    209207        return t->new_state;
    210208}
  • uspace/srv/hid/input/generic/input.c

    r4069f5c r27eddb52  
    410410#endif
    411411#if defined(MACHINE_msim)
    412         kbd_add_dev(&msim_port, &stty_ctl);
     412        kbd_add_dev(&msim_port, &pc_ctl);
    413413#endif
    414414#if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB)
Note: See TracChangeset for help on using the changeset viewer.