Changes in / [f16a76b:ec4538d] in mainline


Ignore:
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

    rf16a76b rec4538d  
    7777./uspace/dist/srv/*
    7878./uspace/drv/root/root
    79 ./uspace/drv/ehci-hcd/ehci-hcd
    8079./uspace/drv/isa/isa
    8180./uspace/drv/ns8250/ns8250
     
    8584./uspace/drv/test1/test1
    8685./uspace/drv/test2/test2
     86./uspace/drv/ehci-hcd/ehci-hcd
    8787./uspace/drv/uhci-hcd/uhci-hcd
    8888./uspace/drv/uhci-rhd/uhci-rhd
  • uspace/drv/ehci-hcd/main.c

    rf16a76b rec4538d  
    5757};
    5858/*----------------------------------------------------------------------------*/
     59/** Initializes a new ddf driver instance of EHCI hcd.
     60 *
     61 * @param[in] device DDF instance of the device to initialize.
     62 * @return Error code.
     63 */
    5964static int ehci_add_device(ddf_dev_t *device)
    6065{
     
    8792}
    8893/*----------------------------------------------------------------------------*/
     94/** Initializes global driver structures (NONE).
     95 *
     96 * @param[in] argc Nmber of arguments in argv vector (ignored).
     97 * @param[in] argv Cmdline argument vector (ignored).
     98 * @return Error code.
     99 *
     100 * Driver debug level is set here.
     101 */
    89102int main(int argc, char *argv[])
    90103{
  • uspace/drv/ehci-hcd/pci.c

    rf16a76b rec4538d  
    4848
    4949#define PAGE_SIZE_MASK 0xfffff000
     50
    5051#define HCC_PARAMS_OFFSET 0x8
    5152#define HCC_PARAMS_EECP_MASK 0xff
    5253#define HCC_PARAMS_EECP_OFFSET 8
     54
     55#define CMD_OFFSET 0x0
     56#define CONFIGFLAG_OFFSET 0x40
    5357
    5458#define USBCMD_RUN 1
     
    6266#define WAIT_STEP 10
    6367
    64 
    6568/** Get address of registers and IRQ for given device.
    6669 *
    6770 * @param[in] dev Device asking for the addresses.
    68  * @param[out] io_reg_address Base address of the I/O range.
    69  * @param[out] io_reg_size Size of the I/O range.
     71 * @param[out] mem_reg_address Base address of the memory range.
     72 * @param[out] mem_reg_size Size of the memory range.
    7073 * @param[out] irq_no IRQ assigned to the device.
    7174 * @return Error code.
     
    8790        rc = hw_res_get_resource_list(parent_phone, &hw_resources);
    8891        if (rc != EOK) {
    89                 goto leave;
     92                async_hangup(parent_phone);
     93                return rc;
    9094        }
    9195
     
    100104        for (i = 0; i < hw_resources.count; i++) {
    101105                hw_resource_t *res = &hw_resources.resources[i];
    102                 switch (res->type) {
    103                         case INTERRUPT:
    104                                 irq = res->res.interrupt.irq;
    105                                 irq_found = true;
    106                                 usb_log_debug2("Found interrupt: %d.\n", irq);
    107                                 break;
    108                         case MEM_RANGE:
    109                                 if (res->res.mem_range.address != 0
    110                                     && res->res.mem_range.size != 0 ) {
    111                                         mem_address = res->res.mem_range.address;
    112                                         mem_size = res->res.mem_range.size;
    113                                         usb_log_debug2("Found mem: %llx %zu.\n",
    114                                                         res->res.mem_range.address, res->res.mem_range.size);
    115                                         mem_found = true;
     106                switch (res->type)
     107                {
     108                case INTERRUPT:
     109                        irq = res->res.interrupt.irq;
     110                        irq_found = true;
     111                        usb_log_debug2("Found interrupt: %d.\n", irq);
     112                        break;
     113
     114                case MEM_RANGE:
     115                        if (res->res.mem_range.address != 0
     116                            && res->res.mem_range.size != 0 ) {
     117                                mem_address = res->res.mem_range.address;
     118                                mem_size = res->res.mem_range.size;
     119                                usb_log_debug2("Found mem: %llx %zu.\n",
     120                                    mem_address, mem_size);
     121                                mem_found = true;
    116122                                }
    117                                 break;
    118                         default:
    119                                 break;
     123                default:
     124                        break;
    120125                }
    121126        }
    122127
    123         if (!mem_found) {
     128        if (mem_found && irq_found) {
     129                *mem_reg_address = mem_address;
     130                *mem_reg_size = mem_size;
     131                *irq_no = irq;
     132                rc = EOK;
     133        } else {
    124134                rc = ENOENT;
    125                 goto leave;
    126         }
    127 
    128         if (!irq_found) {
    129                 rc = ENOENT;
    130                 goto leave;
    131         }
    132 
    133         *mem_reg_address = mem_address;
    134         *mem_reg_size = mem_size;
    135         *irq_no = irq;
    136 
    137         rc = EOK;
    138 leave:
     135        }
     136
    139137        async_hangup(parent_phone);
    140 
    141138        return rc;
    142139}
    143140/*----------------------------------------------------------------------------*/
     141/** Calls the PCI driver with a request to enable interrupts
     142 *
     143 * @param[in] device Device asking for interrupts
     144 * @return Error code.
     145 */
    144146int pci_enable_interrupts(ddf_dev_t *device)
    145147{
    146         int parent_phone = devman_parent_device_connect(device->handle,
    147             IPC_FLAG_BLOCKING);
     148        int parent_phone =
     149            devman_parent_device_connect(device->handle, IPC_FLAG_BLOCKING);
     150        if (parent_phone < 0) {
     151                return parent_phone;
     152        }
    148153        bool enabled = hw_res_enable_interrupt(parent_phone);
    149154        async_hangup(parent_phone);
     
    151156}
    152157/*----------------------------------------------------------------------------*/
     158/** Implements BIOS handoff routine as decribed in EHCI spec
     159 *
     160 * @param[in] device Device asking for interrupts
     161 * @return Error code.
     162 */
    153163int pci_disable_legacy(ddf_dev_t *device)
    154164{
     
    160170        }
    161171
    162         /* read register space BAR */
     172#define CHECK_RET_HANGUP_RETURN(ret, message...) \
     173        if (ret != EOK) { \
     174                usb_log_error(message); \
     175                async_hangup(parent_phone); \
     176                return ret; \
     177        } else (void)0
     178
     179
     180        /* read register space BASE BAR */
    163181        sysarg_t address = 0x10;
    164182        sysarg_t value;
    165183
    166   int ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     184        int ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    167185            IPC_M_CONFIG_SPACE_READ_32, address, &value);
     186        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read PCI config space.\n",
     187            ret);
    168188        usb_log_info("Register space BAR at %p:%x.\n", address, value);
    169189
    170         /* clear lower byte, it's not part of the address */
     190        /* clear lower byte, it's not part of the BASE address */
    171191        uintptr_t registers = (value & 0xffffff00);
    172         usb_log_info("Mem register address:%p.\n", registers);
    173 
    174         /* if nothing setup the hc, the we don't need to to turn it off */
     192        usb_log_info("Memory registers BASE address:%p.\n", registers);
     193
     194        /* if nothing setup the hc, we don't need to turn it off */
    175195        if (registers == 0)
    176196                return ENOTSUP;
    177197
    178         /* EHCI registers need 20 bytes*/
     198        /* map EHCI registers */
    179199        void *regs = as_get_mappable_page(4096);
    180200        ret = physmem_map((void*)(registers & PAGE_SIZE_MASK), regs, 1,
    181201            AS_AREA_READ | AS_AREA_WRITE);
    182         if (ret != EOK) {
    183                 usb_log_error("Failed(%d) to map registers %p:%p.\n",
    184                     ret, regs, registers);
    185         }
     202        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to map registers %p:%p.\n",
     203            ret, regs, registers);
     204
    186205        /* calculate value of BASE */
    187206        registers = (registers & 0xf00) | (uintptr_t)regs;
    188207
    189         uint32_t hcc_params = *(uint32_t*)(registers + HCC_PARAMS_OFFSET);
    190 
     208        const uint32_t hcc_params =
     209            *(uint32_t*)(registers + HCC_PARAMS_OFFSET);
    191210        usb_log_debug("Value of hcc params register: %x.\n", hcc_params);
    192         uint32_t eecp = (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
     211
     212        /* Read value of EHCI Extended Capabilities Pointer
     213         * (points to PCI config space) */
     214        uint32_t eecp =
     215            (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
    193216        usb_log_debug("Value of EECP: %x.\n", eecp);
    194217
     218        /* Read the second EEC. i.e. Legacy Support and Control register */
     219        /* TODO: Check capability type here */
    195220        ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    196221            IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGCTLSTS_OFFSET, &value);
    197         if (ret != EOK) {
    198                 usb_log_error("Failed(%d) to read USBLEGCTLSTS.\n", ret);
    199                 return ret;
    200         }
    201         usb_log_debug2("USBLEGCTLSTS: %x.\n", value);
    202 
     222        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGCTLSTS.\n", ret);
     223        usb_log_debug("USBLEGCTLSTS: %x.\n", value);
     224
     225        /* Read the first EEC. i.e. Legacy Support register */
     226        /* TODO: Check capability type here */
    203227        ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    204228            IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
    205         if (ret != EOK) {
    206                 usb_log_error("Failed(%d) to read USBLEGSUP.\n", ret);
    207                 return ret;
    208         }
     229        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
    209230        usb_log_debug2("USBLEGSUP: %x.\n", value);
    210231
    211         /* request control from firmware/BIOS, by writing 1 to highest byte */
     232        /* Request control from firmware/BIOS, by writing 1 to highest byte.
     233         * (OS Control semaphore)*/
    212234        ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    213235           IPC_M_CONFIG_SPACE_WRITE_8, eecp + USBLEGSUP_OFFSET + 3, 1);
    214         if (ret != EOK) {
    215                 usb_log_error("Failed(%d) request OS EHCI control.\n", ret);
    216                 return ret;
    217         }
    218 
    219         size_t wait = 0; /* might be anything */
    220         /* wait for BIOS to release control */
     236        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to request OS EHCI control.\n",
     237            ret);
     238
     239        size_t wait = 0;
     240        /* Wait for BIOS to release control. */
    221241        while ((wait < DEFAULT_WAIT) && (value & USBLEGSUP_BIOS_CONTROL)) {
    222242                async_usleep(WAIT_STEP);
    223243                ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    224                                 IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
     244                    IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
    225245                wait += WAIT_STEP;
    226246        }
    227247
     248
    228249        if ((value & USBLEGSUP_BIOS_CONTROL) != 0) {
    229                 usb_log_warning(
    230                     "BIOS failed to release control after %d usecs, force it.\n",
    231                     wait);
     250                usb_log_info("BIOS released control after %d usec.\n", wait);
     251        } else {
     252                /* BIOS failed to hand over control, this should not happen. */
     253                usb_log_warning( "BIOS failed to release control after"
     254                    "%d usecs, force it.\n", wait);
    232255                ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    233                           IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGSUP_OFFSET,
     256                    IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGSUP_OFFSET,
    234257                    USBLEGSUP_OS_CONTROL);
    235                 if (ret != EOK) {
    236                         usb_log_error("Failed(%d) to force OS EHCI control.\n", ret);
    237                         return ret;
    238                 }
    239         } else {
    240                 usb_log_info("BIOS released control after %d usec.\n",
    241                     wait);
    242         }
    243 
    244 
    245         /* zero SMI enables in legacy control register */
     258                CHECK_RET_HANGUP_RETURN(ret,
     259                    "Failed(%d) to force OS EHCI control.\n", ret);
     260                /* TODO: This does not seem to work on my machine */
     261        }
     262
     263        /* Zero SMI enables in legacy control register.
     264         * It would prevent pre-OS code from interfering. */
    246265        ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    247266           IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGCTLSTS_OFFSET, 0);
    248         if (ret != EOK) {
    249                 usb_log_error("Failed(%d) zero USBLEGCTLSTS.\n", ret);
    250                 return ret;
    251         }
     267        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) zero USBLEGCTLSTS.\n", ret);
    252268        usb_log_debug("Zeroed USBLEGCTLSTS register.\n");
    253269
     270        /* Read again Legacy Support and Control register */
    254271        ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    255272            IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGCTLSTS_OFFSET, &value);
    256         if (ret != EOK) {
    257                 usb_log_error("Failed(%d) to read USBLEGCTLSTS.\n", ret);
    258                 return ret;
    259         }
     273        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGCTLSTS.\n", ret);
    260274        usb_log_debug2("USBLEGCTLSTS: %x.\n", value);
    261275
     276        /* Read again Legacy Support register */
    262277        ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    263278            IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
    264         if (ret != EOK) {
    265                 usb_log_error("Failed(%d) to read USBLEGSUP.\n", ret);
    266                 return ret;
    267         }
     279        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
    268280        usb_log_debug2("USBLEGSUP: %x.\n", value);
    269281
     
    272284 */
    273285
    274         /* size of capability registers in memory space */
     286        /* Get size of capability registers in memory space. */
    275287        uint8_t operation_offset = *(uint8_t*)registers;
    276288        usb_log_debug("USBCMD offset: %d.\n", operation_offset);
    277         /* zero USBCMD register */
     289
     290        /* Zero USBCMD register. */
    278291        volatile uint32_t *usbcmd =
    279          (uint32_t*)((uint8_t*)registers + operation_offset);
     292            (uint32_t*)((uint8_t*)registers + operation_offset + CMD_OFFSET);
     293        volatile uint32_t *usbconfigured =
     294            (uint32_t*)((uint8_t*)registers + operation_offset
     295            + CONFIGFLAG_OFFSET);
    280296        usb_log_debug("USBCMD value: %x.\n", *usbcmd);
    281297        if (*usbcmd & USBCMD_RUN) {
    282298                *usbcmd = 0;
     299                *usbconfigured = 0;
    283300                usb_log_info("EHCI turned off.\n");
    284301        } else {
     
    286303        }
    287304
    288 
    289305        async_hangup(parent_phone);
    290 
    291   return ret;
     306        return ret;
     307#undef CHECK_RET_HANGUP_RETURN
    292308}
    293309/*----------------------------------------------------------------------------*/
  • uspace/drv/uhci-hcd/batch.c

    rf16a76b rec4538d  
    5757
    5858
     59/** Allocates memory and initializes internal data structures.
     60 *
     61 * @param[in] fun DDF function to pass to callback.
     62 * @param[in] target Device and endpoint target of the transaction.
     63 * @param[in] transfer_type Interrupt, Control or Bulk.
     64 * @param[in] max_packet_size maximum allowed size of data packets.
     65 * @param[in] speed Speed of the transaction.
     66 * @param[in] buffer Data source/destination.
     67 * @param[in] size Size of the buffer.
     68 * @param[in] setup_buffer Setup data source (if not NULL)
     69 * @param[in] setup_size Size of setup_buffer (should be always 8)
     70 * @param[in] func_in function to call on inbound transaction completion
     71 * @param[in] func_out function to call on outbound transaction completion
     72 * @param[in] arg additional parameter to func_in or func_out
     73 * @param[in] manager Pointer to toggle management structure.
     74 * @return False, if there is an active TD, true otherwise.
     75 */
    5976batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
    6077    usb_transfer_type_t transfer_type, size_t max_packet_size,
     
    6986        assert(func_in != NULL || func_out != NULL);
    7087
     88#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
     89        if (ptr == NULL) { \
     90                usb_log_error(message); \
     91                if (instance) { \
     92                        batch_dispose(instance); \
     93                } \
     94                return NULL; \
     95        } else (void)0
     96
    7197        batch_t *instance = malloc(sizeof(batch_t));
    72         if (instance == NULL) {
    73                 usb_log_error("Failed to allocate batch instance.\n");
    74                 return NULL;
    75         }
    76 
    77         instance->qh = queue_head_get();
    78         if (instance->qh == NULL) {
    79                 usb_log_error("Failed to allocate queue head.\n");
    80                 free(instance);
    81                 return NULL;
    82         }
     98        CHECK_NULL_DISPOSE_RETURN(instance,
     99            "Failed to allocate batch instance.\n");
     100        bzero(instance, sizeof(batch_t));
     101
     102        instance->qh = malloc32(sizeof(queue_head_t));
     103        CHECK_NULL_DISPOSE_RETURN(instance->qh,
     104            "Failed to allocate batch queue head.\n");
     105        queue_head_init(instance->qh);
    83106
    84107        instance->packets = (size + max_packet_size - 1) / max_packet_size;
     
    88111
    89112        instance->tds = malloc32(sizeof(td_t) * instance->packets);
    90         if (instance->tds == NULL) {
    91                 usb_log_error("Failed to allocate transfer descriptors.\n");
    92                 queue_head_dispose(instance->qh);
    93                 free(instance);
    94                 return NULL;
    95         }
     113        CHECK_NULL_DISPOSE_RETURN(
     114            instance->tds, "Failed to allocate transfer descriptors.\n");
    96115        bzero(instance->tds, sizeof(td_t) * instance->packets);
    97116
    98         const size_t transport_size = max_packet_size * instance->packets;
    99 
    100         instance->transport_buffer =
    101            (size > 0) ? malloc32(transport_size) : NULL;
    102 
    103         if ((size > 0) && (instance->transport_buffer == NULL)) {
    104                 usb_log_error("Failed to allocate device accessible buffer.\n");
    105                 queue_head_dispose(instance->qh);
    106                 free32(instance->tds);
    107                 free(instance);
    108                 return NULL;
    109         }
    110 
    111         instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL;
    112         if ((setup_size > 0) && (instance->setup_buffer == NULL)) {
    113                 usb_log_error("Failed to allocate device accessible setup buffer.\n");
    114                 queue_head_dispose(instance->qh);
    115                 free32(instance->tds);
    116                 free32(instance->transport_buffer);
    117                 free(instance);
    118                 return NULL;
    119         }
    120         if (instance->setup_buffer) {
     117//      const size_t transport_size = max_packet_size * instance->packets;
     118
     119        if (size > 0) {
     120                instance->transport_buffer = malloc32(size);
     121                CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
     122                    "Failed to allocate device accessible buffer.\n");
     123        }
     124
     125        if (setup_size > 0) {
     126                instance->setup_buffer = malloc32(setup_size);
     127                CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
     128                    "Failed to allocate device accessible setup buffer.\n");
    121129                memcpy(instance->setup_buffer, setup_buffer, setup_size);
    122130        }
    123131
     132
     133        link_initialize(&instance->link);
     134
    124135        instance->max_packet_size = max_packet_size;
    125 
    126         link_initialize(&instance->link);
    127 
    128136        instance->target = target;
    129137        instance->transfer_type = transfer_type;
    130 
    131         if (func_out)
    132                 instance->callback_out = func_out;
    133         if (func_in)
    134                 instance->callback_in = func_in;
    135 
    136138        instance->buffer = buffer;
    137139        instance->buffer_size = size;
     
    142144        instance->manager = manager;
    143145
    144         queue_head_element_td(instance->qh, addr_to_phys(instance->tds));
     146        if (func_out)
     147                instance->callback_out = func_out;
     148        if (func_in)
     149                instance->callback_in = func_in;
     150
     151        queue_head_set_element_td(instance->qh, addr_to_phys(instance->tds));
     152
    145153        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
    146154            instance, target.address, target.endpoint);
     
    148156}
    149157/*----------------------------------------------------------------------------*/
     158/** Checks batch TDs for activity.
     159 *
     160 * @param[in] instance Batch structure to use.
     161 * @return False, if there is an active TD, true otherwise.
     162 */
    150163bool batch_is_complete(batch_t *instance)
    151164{
     
    165178                            instance, i, instance->tds[i].status);
    166179
    167                         device_keeper_set_toggle(instance->manager, instance->target,
    168                             td_toggle(&instance->tds[i]));
     180                        device_keeper_set_toggle(instance->manager,
     181                            instance->target, td_toggle(&instance->tds[i]));
    169182                        if (i > 0)
    170183                                goto substract_ret;
     
    181194}
    182195/*----------------------------------------------------------------------------*/
     196/** Prepares control write transaction.
     197 *
     198 * @param[in] instance Batch structure to use.
     199 */
    183200void batch_control_write(batch_t *instance)
    184201{
    185202        assert(instance);
    186203        /* we are data out, we are supposed to provide data */
    187         memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
     204        memcpy(instance->transport_buffer, instance->buffer,
     205            instance->buffer_size);
    188206        batch_control(instance, USB_PID_OUT, USB_PID_IN);
    189207        instance->next_step = batch_call_out_and_dispose;
     
    192210}
    193211/*----------------------------------------------------------------------------*/
     212/** Prepares control read transaction.
     213 *
     214 * @param[in] instance Batch structure to use.
     215 */
    194216void batch_control_read(batch_t *instance)
    195217{
     
    201223}
    202224/*----------------------------------------------------------------------------*/
     225/** Prepares interrupt in transaction.
     226 *
     227 * @param[in] instance Batch structure to use.
     228 */
    203229void batch_interrupt_in(batch_t *instance)
    204230{
     
    210236}
    211237/*----------------------------------------------------------------------------*/
     238/** Prepares interrupt out transaction.
     239 *
     240 * @param[in] instance Batch structure to use.
     241 */
    212242void batch_interrupt_out(batch_t *instance)
    213243{
    214244        assert(instance);
     245        /* we are data out, we are supposed to provide data */
    215246        memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size);
    216247        batch_data(instance, USB_PID_OUT);
     
    220251}
    221252/*----------------------------------------------------------------------------*/
     253/** Prepares bulk in transaction.
     254 *
     255 * @param[in] instance Batch structure to use.
     256 */
    222257void batch_bulk_in(batch_t *instance)
    223258{
     
    229264}
    230265/*----------------------------------------------------------------------------*/
     266/** Prepares bulk out transaction.
     267 *
     268 * @param[in] instance Batch structure to use.
     269 */
    231270void batch_bulk_out(batch_t *instance)
    232271{
     
    239278}
    240279/*----------------------------------------------------------------------------*/
     280/** Prepares generic data transaction
     281 *
     282 * @param[in] instance Batch structure to use.
     283 * @param[in] pid to use for data packets.
     284 */
    241285void batch_data(batch_t *instance, usb_packet_id pid)
    242286{
    243287        assert(instance);
    244288        const bool low_speed = instance->speed == USB_SPEED_LOW;
    245         int toggle = device_keeper_get_toggle(instance->manager, instance->target);
     289        int toggle =
     290            device_keeper_get_toggle(instance->manager, instance->target);
    246291        assert(toggle == 0 || toggle == 1);
    247292
     
    253298                    - remain_size;
    254299
    255 
    256300                const size_t packet_size =
    257301                    (instance->max_packet_size > remain_size) ?
    258302                    remain_size : instance->max_packet_size;
    259303
    260                 td_init(&instance->tds[packet],
    261                     DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,
    262                     instance->target, pid, data,
    263                     &instance->tds[packet + 1]);
     304                td_t *next_packet = (packet + 1 < instance->packets)
     305                    ? &instance->tds[packet + 1] : NULL;
     306
     307                assert(packet < instance->packets);
     308                assert(packet_size <= remain_size);
     309
     310                td_init(
     311                    &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
     312                    toggle, false, low_speed, instance->target, pid, data,
     313                    next_packet);
     314
    264315
    265316                toggle = 1 - toggle;
     317                remain_size -= packet_size;
    266318                ++packet;
    267                 assert(packet <= instance->packets);
    268                 assert(packet_size <= remain_size);
    269                 remain_size -= packet_size;
    270319        }
    271320        device_keeper_set_toggle(instance->manager, instance->target, toggle);
    272 
    273         instance->tds[packet - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG;
    274         instance->tds[packet - 1].next = 0 | LINK_POINTER_TERMINATE_FLAG;
    275 }
    276 /*----------------------------------------------------------------------------*/
     321}
     322/*----------------------------------------------------------------------------*/
     323/** Prepares generic control transaction
     324 *
     325 * @param[in] instance Batch structure to use.
     326 * @param[in] data_stage to use for data packets.
     327 * @param[in] status_stage to use for data packets.
     328 */
    277329void batch_control(batch_t *instance,
    278330   usb_packet_id data_stage, usb_packet_id status_stage)
     
    301353                    remain_size : instance->max_packet_size;
    302354
    303                 td_init(&instance->tds[packet],
    304                     DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,
    305                     instance->target, data_stage, data,
    306                     &instance->tds[packet + 1]);
     355                td_init(
     356                    &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,
     357                    toggle, false, low_speed, instance->target, data_stage,
     358                    data, &instance->tds[packet + 1]);
    307359
    308360                ++packet;
     
    323375}
    324376/*----------------------------------------------------------------------------*/
     377/** Prepares data, gets error status and calls callback in.
     378 *
     379 * @param[in] instance Batch structure to use.
     380 */
    325381void batch_call_in(batch_t *instance)
    326382{
     
    328384        assert(instance->callback_in);
    329385
    330         memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size);
     386        /* we are data in, we need data */
     387        memcpy(instance->buffer, instance->transport_buffer,
     388            instance->buffer_size);
    331389
    332390        int err = instance->error;
     
    335393            instance->transfered_size);
    336394
    337         instance->callback_in(instance->fun,
    338             err, instance->transfered_size,
    339             instance->arg);
    340 }
    341 /*----------------------------------------------------------------------------*/
     395        instance->callback_in(
     396            instance->fun, err, instance->transfered_size, instance->arg);
     397}
     398/*----------------------------------------------------------------------------*/
     399/** Gets error status and calls callback out.
     400 *
     401 * @param[in] instance Batch structure to use.
     402 */
    342403void batch_call_out(batch_t *instance)
    343404{
     
    352413}
    353414/*----------------------------------------------------------------------------*/
     415/** Prepares data, gets error status, calls callback in and dispose.
     416 *
     417 * @param[in] instance Batch structure to use.
     418 */
    354419void batch_call_in_and_dispose(batch_t *instance)
    355420{
     
    359424}
    360425/*----------------------------------------------------------------------------*/
     426/** Gets error status, calls callback out and dispose.
     427 *
     428 * @param[in] instance Batch structure to use.
     429 */
    361430void batch_call_out_and_dispose(batch_t *instance)
    362431{
     
    366435}
    367436/*----------------------------------------------------------------------------*/
     437/** Correctly disposes all used data structures.
     438 *
     439 * @param[in] instance Batch structure to use.
     440 */
    368441void batch_dispose(batch_t *instance)
    369442{
    370443        assert(instance);
    371444        usb_log_debug("Batch(%p) disposing.\n", instance);
     445        /* free32 is NULL safe */
    372446        free32(instance->tds);
    373447        free32(instance->qh);
  • uspace/drv/uhci-hcd/iface.c

    rf16a76b rec4538d  
    4343#include "utils/device_keeper.h"
    4444
     45/** Reserve default address interface function
     46 *
     47 * @param[in] fun DDF function that was called.
     48 * @param[in] speed Speed to associate with the new default address.
     49 * @return Error code.
     50 */
    4551/*----------------------------------------------------------------------------*/
    4652static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
     
    5460}
    5561/*----------------------------------------------------------------------------*/
     62/** Release default address interface function
     63 *
     64 * @param[in] fun DDF function that was called.
     65 * @return Error code.
     66 */
    5667static int release_default_address(ddf_fun_t *fun)
    5768{
     
    6475}
    6576/*----------------------------------------------------------------------------*/
     77/** Request address interface function
     78 *
     79 * @param[in] fun DDF function that was called.
     80 * @param[in] speed Speed to associate with the new default address.
     81 * @param[out] address Place to write a new address.
     82 * @return Error code.
     83 */
    6684static int request_address(ddf_fun_t *fun, usb_speed_t speed,
    6785    usb_address_t *address)
     
    8098}
    8199/*----------------------------------------------------------------------------*/
     100/** Bind address interface function
     101 *
     102 * @param[in] fun DDF function that was called.
     103 * @param[in] address Address of the device
     104 * @param[in] handle Devman handle of the device driver.
     105 * @return Error code.
     106 */
    82107static int bind_address(
    83108  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
     
    91116}
    92117/*----------------------------------------------------------------------------*/
     118/** Release address interface function
     119 *
     120 * @param[in] fun DDF function that was called.
     121 * @param[in] address USB address to be released.
     122 * @return Error code.
     123 */
    93124static int release_address(ddf_fun_t *fun, usb_address_t address)
    94125{
     
    101132}
    102133/*----------------------------------------------------------------------------*/
     134/** Interrupt out transaction interface function
     135 *
     136 * @param[in] fun DDF function that was called.
     137 * @param[in] target USB device to write to.
     138 * @param[in] max_packet_size maximum size of data packet the device accepts
     139 * @param[in] data Source of data.
     140 * @param[in] size Size of data source.
     141 * @param[in] callback Function to call on transaction completion
     142 * @param[in] arg Additional for callback function.
     143 * @return Error code.
     144 */
    103145static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
    104146    size_t max_packet_size, void *data, size_t size,
     
    122164}
    123165/*----------------------------------------------------------------------------*/
     166/** Interrupt in transaction interface function
     167 *
     168 * @param[in] fun DDF function that was called.
     169 * @param[in] target USB device to write to.
     170 * @param[in] max_packet_size maximum size of data packet the device accepts
     171 * @param[out] data Data destination.
     172 * @param[in] size Size of data source.
     173 * @param[in] callback Function to call on transaction completion
     174 * @param[in] arg Additional for callback function.
     175 * @return Error code.
     176 */
    124177static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
    125178    size_t max_packet_size, void *data, size_t size,
     
    142195}
    143196/*----------------------------------------------------------------------------*/
     197/** Bulk out transaction interface function
     198 *
     199 * @param[in] fun DDF function that was called.
     200 * @param[in] target USB device to write to.
     201 * @param[in] max_packet_size maximum size of data packet the device accepts
     202 * @param[in] data Source of data.
     203 * @param[in] size Size of data source.
     204 * @param[in] callback Function to call on transaction completion
     205 * @param[in] arg Additional for callback function.
     206 * @return Error code.
     207 */
    144208static int bulk_out(ddf_fun_t *fun, usb_target_t target,
    145209    size_t max_packet_size, void *data, size_t size,
     
    163227}
    164228/*----------------------------------------------------------------------------*/
     229/** Bulk in transaction interface function
     230 *
     231 * @param[in] fun DDF function that was called.
     232 * @param[in] target USB device to write to.
     233 * @param[in] max_packet_size maximum size of data packet the device accepts
     234 * @param[out] data Data destination.
     235 * @param[in] size Size of data source.
     236 * @param[in] callback Function to call on transaction completion
     237 * @param[in] arg Additional for callback function.
     238 * @return Error code.
     239 */
    165240static int bulk_in(ddf_fun_t *fun, usb_target_t target,
    166241    size_t max_packet_size, void *data, size_t size,
     
    183258}
    184259/*----------------------------------------------------------------------------*/
     260/** Control write transaction interface function
     261 *
     262 * @param[in] fun DDF function that was called.
     263 * @param[in] target USB device to write to.
     264 * @param[in] max_packet_size maximum size of data packet the device accepts.
     265 * @param[in] setup_data Data to send with SETUP packet.
     266 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
     267 * @param[in] data Source of data.
     268 * @param[in] size Size of data source.
     269 * @param[in] callback Function to call on transaction completion.
     270 * @param[in] arg Additional for callback function.
     271 * @return Error code.
     272 */
    185273static int control_write(ddf_fun_t *fun, usb_target_t target,
    186274    size_t max_packet_size,
     
    208296}
    209297/*----------------------------------------------------------------------------*/
     298/** Control read transaction interface function
     299 *
     300 * @param[in] fun DDF function that was called.
     301 * @param[in] target USB device to write to.
     302 * @param[in] max_packet_size maximum size of data packet the device accepts.
     303 * @param[in] setup_data Data to send with SETUP packet.
     304 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
     305 * @param[out] data Source of data.
     306 * @param[in] size Size of data source.
     307 * @param[in] callback Function to call on transaction completion.
     308 * @param[in] arg Additional for callback function.
     309 * @return Error code.
     310 */
    210311static int control_read(ddf_fun_t *fun, usb_target_t target,
    211312    size_t max_packet_size,
  • uspace/drv/uhci-hcd/main.c

    rf16a76b rec4538d  
    6060};
    6161/*----------------------------------------------------------------------------*/
     62/** IRQ handling callback, identifies devic
     63 *
     64 * @param[in] dev DDF instance of the device to use.
     65 * @param[in] iid (Unused).
     66 * @param[in] call Pointer to the call that represents interrupt.
     67 */
    6268static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
    6369{
     
    6975}
    7076/*----------------------------------------------------------------------------*/
    71 static int uhci_add_device(ddf_dev_t *device)
     77/** Initializes a new ddf driver instance of UHCI hcd.
     78 *
     79 * @param[in] device DDF instance of the device to initialize.
     80 * @return Error code.
     81 *
     82 * Gets and initialies hardware resources, disables any legacy support,
     83 * and reports root hub device.
     84 */
     85int uhci_add_device(ddf_dev_t *device)
    7286{
    7387        assert(device);
     
    96110        ret = pci_disable_legacy(device);
    97111        CHECK_RET_FREE_HC_RETURN(ret,
    98             "Failed(%d) disable legacy USB: %s.\n", ret, str_error(ret));
     112            "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
    99113
    100114#if 0
     
    113127
    114128        ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size);
    115         CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n",
    116             ret);
     129        CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret);
    117130#undef CHECK_RET_FREE_HC_RETURN
    118131
     
    155168}
    156169/*----------------------------------------------------------------------------*/
     170/** Initializes global driver structures (NONE).
     171 *
     172 * @param[in] argc Nmber of arguments in argv vector (ignored).
     173 * @param[in] argv Cmdline argument vector (ignored).
     174 * @return Error code.
     175 *
     176 * Driver debug level is set here.
     177 */
    157178int main(int argc, char *argv[])
    158179{
  • uspace/drv/uhci-hcd/pci.c

    rf16a76b rec4538d  
    6565
    6666        int rc;
    67 
    6867        hw_resource_list_t hw_resources;
    6968        rc = hw_res_get_resource_list(parent_phone, &hw_resources);
     
    8281        for (i = 0; i < hw_resources.count; i++) {
    8382                hw_resource_t *res = &hw_resources.resources[i];
    84                 switch (res->type) {
    85                         case INTERRUPT:
    86                                 irq = res->res.interrupt.irq;
    87                                 irq_found = true;
    88                                 usb_log_debug2("Found interrupt: %d.\n", irq);
    89                                 break;
    90                         case IO_RANGE:
    91                                 io_address = res->res.io_range.address;
    92                                 io_size = res->res.io_range.size;
    93                                 usb_log_debug2("Found io: %llx %zu.\n",
    94                                     res->res.io_range.address, res->res.io_range.size);
    95                                 io_found = true;
    96                                 break;
    97                         default:
    98                                 break;
     83                switch (res->type)
     84                {
     85                case INTERRUPT:
     86                        irq = res->res.interrupt.irq;
     87                        irq_found = true;
     88                        usb_log_debug2("Found interrupt: %d.\n", irq);
     89                        break;
     90
     91                case IO_RANGE:
     92                        io_address = res->res.io_range.address;
     93                        io_size = res->res.io_range.size;
     94                        usb_log_debug2("Found io: %llx %zu.\n",
     95                            res->res.io_range.address, res->res.io_range.size);
     96                        io_found = true;
     97
     98                default:
     99                        break;
    99100                }
    100101        }
    101102
    102         if (!io_found) {
    103                 rc = ENOENT;
    104                 goto leave;
    105         }
    106 
    107         if (!irq_found) {
     103        if (!io_found || !irq_found) {
    108104                rc = ENOENT;
    109105                goto leave;
     
    121117}
    122118/*----------------------------------------------------------------------------*/
     119/** Calls the PCI driver with a request to enable interrupts
     120 *
     121 * @param[in] device Device asking for interrupts
     122 * @return Error code.
     123 */
    123124int pci_enable_interrupts(ddf_dev_t *device)
    124125{
     
    130131}
    131132/*----------------------------------------------------------------------------*/
     133/** Calls the PCI driver with a request to clear legacy support register
     134 *
     135 * @param[in] device Device asking to disable interrupts
     136 * @return Error code.
     137 */
    132138int pci_disable_legacy(ddf_dev_t *device)
    133139{
    134140        assert(device);
    135         int parent_phone = devman_parent_device_connect(device->handle,
    136                 IPC_FLAG_BLOCKING);
     141        int parent_phone =
     142            devman_parent_device_connect(device->handle, IPC_FLAG_BLOCKING);
    137143        if (parent_phone < 0) {
    138144                return parent_phone;
     
    144150        sysarg_t value = 0x8f00;
    145151
    146   int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     152        int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
    147153            IPC_M_CONFIG_SPACE_WRITE_16, address, value);
    148154        async_hangup(parent_phone);
    149155
    150   return rc;
     156        return rc;
    151157}
    152158/*----------------------------------------------------------------------------*/
  • uspace/drv/uhci-hcd/root_hub.c

    rf16a76b rec4538d  
    4545
    4646/*----------------------------------------------------------------------------*/
    47 static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun,
    48     devman_handle_t *handle)
     47/** Gets handle of the respective hc (parent device).
     48 *
     49 * @param[in] root_hub_fun Root hub function seeking hc handle.
     50 * @param[out] handle Place to write the handle.
     51 * @return Error code.
     52 */
     53static int usb_iface_get_hc_handle_rh_impl(
     54    ddf_fun_t *root_hub_fun, devman_handle_t *handle)
    4955{
     56        /* TODO: Can't this use parent pointer? */
    5057        ddf_fun_t *hc_fun = root_hub_fun->driver_data;
    5158        assert(hc_fun != NULL);
     
    5663}
    5764/*----------------------------------------------------------------------------*/
    58 static int usb_iface_get_address_rh_impl(ddf_fun_t *fun, devman_handle_t handle,
    59     usb_address_t *address)
     65/** Gets USB address of the calling device.
     66 *
     67 * @param[in] fun Root hub function.
     68 * @param[in] handle Handle of the device seeking address.
     69 * @param[out] address Place to store found address.
     70 * @return Error code.
     71 */
     72static int usb_iface_get_address_rh_impl(
     73    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
    6074{
     75        /* TODO: What does this do? Is it neccessary? Can't it use implemented
     76         * hc function?*/
    6177        assert(fun);
    6278        ddf_fun_t *hc_fun = fun->driver_data;
     
    6581        assert(hc);
    6682
    67         usb_address_t addr = device_keeper_find(&hc->device_manager,
    68             handle);
     83        usb_address_t addr = device_keeper_find(&hc->device_manager, handle);
    6984        if (addr < 0) {
    7085                return addr;
     
    8398};
    8499/*----------------------------------------------------------------------------*/
     100/** Gets root hub hw resources.
     101 *
     102 * @param[in] fun Root hub function.
     103 * @return Pointer to the resource list used by the root hub.
     104 */
    85105static hw_resource_list_t *get_resource_list(ddf_fun_t *dev)
    86106{
     
    91111        assert(hc);
    92112
    93         //TODO: fix memory leak
     113        /* TODO: fix memory leak */
    94114        hw_resource_list_t *resource_list = malloc(sizeof(hw_resource_list_t));
    95115        assert(resource_list);
  • uspace/drv/uhci-hcd/transfer_list.c

    rf16a76b rec4538d  
    3838#include "transfer_list.h"
    3939
     40static void transfer_list_remove_batch(
     41    transfer_list_t *instance, batch_t *batch);
     42/*----------------------------------------------------------------------------*/
     43/** Initializes transfer list structures.
     44 *
     45 * @param[in] instance Memory place to use.
     46 * @param[in] name Name of te new list.
     47 * @return Error code
     48 *
     49 * Allocates memory for internat queue_head_t structure.
     50 */
    4051int transfer_list_init(transfer_list_t *instance, const char *name)
    4152{
     
    4354        instance->next = NULL;
    4455        instance->name = name;
    45         instance->queue_head = queue_head_get();
     56        instance->queue_head = malloc32(sizeof(queue_head_t));
    4657        if (!instance->queue_head) {
    4758                usb_log_error("Failed to allocate queue head.\n");
    4859                return ENOMEM;
    4960        }
    50         instance->queue_head_pa = (uintptr_t)addr_to_phys(instance->queue_head);
     61        instance->queue_head_pa = addr_to_phys(instance->queue_head);
    5162
    5263        queue_head_init(instance->queue_head);
     
    5667}
    5768/*----------------------------------------------------------------------------*/
     69/** Set the next list in chain.
     70 *
     71 * @param[in] instance List to lead.
     72 * @param[in] next List to append.
     73 * @return Error code
     74 */
    5875void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
    5976{
     
    6683}
    6784/*----------------------------------------------------------------------------*/
     85/** Submits a new transfer batch to list and queue.
     86 *
     87 * @param[in] instance List to use.
     88 * @param[in] batch Transfer batch to submit.
     89 * @return Error code
     90 */
    6891void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch)
    6992{
    7093        assert(instance);
    7194        assert(batch);
    72         usb_log_debug2("Adding batch(%p) to queue %s.\n", batch, instance->name);
     95        usb_log_debug2(
     96            "Adding batch(%p) to queue %s.\n", batch, instance->name);
    7397
    7498        uint32_t pa = (uintptr_t)addr_to_phys(batch->qh);
     
    97121        queue_head_append_qh(last->qh, pa);
    98122        list_append(&batch->link, &instance->batch_list);
     123
    99124        usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n",
    100                 batch, instance->name, first );
     125                batch, instance->name, first);
    101126        fibril_mutex_unlock(&instance->guard);
    102127}
    103128/*----------------------------------------------------------------------------*/
    104 static void transfer_list_remove_batch(
    105     transfer_list_t *instance, batch_t *batch)
     129/** Removes a transfer batch from list and queue.
     130 *
     131 * @param[in] instance List to use.
     132 * @param[in] batch Transfer batch to remove.
     133 * @return Error code
     134 */
     135void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch)
    106136{
    107137        assert(instance);
     
    109139        assert(instance->queue_head);
    110140        assert(batch->qh);
    111         usb_log_debug2("Removing batch(%p) from queue %s.\n", batch, instance->name);
     141        usb_log_debug2(
     142            "Removing batch(%p) from queue %s.\n", batch, instance->name);
    112143
    113         /* I'm the first one here */
    114144        if (batch->link.prev == &instance->batch_list) {
    115                 usb_log_debug("Batch(%p) removed (FIRST) from queue %s, next element %x.\n",
    116                         batch, instance->name, batch->qh->next_queue);
     145                /* I'm the first one here */
     146                usb_log_debug(
     147                    "Batch(%p) removed (FIRST) from %s, next element %x.\n",
     148                    batch, instance->name, batch->qh->next_queue);
    117149                instance->queue_head->element = batch->qh->next_queue;
    118150        } else {
    119                 usb_log_debug("Batch(%p) removed (NOT FIRST) from queue, next element %x.\n",
    120                         batch, instance->name, batch->qh->next_queue);
    121                 batch_t *prev = list_get_instance(batch->link.prev, batch_t, link);
     151                usb_log_debug(
     152                    "Batch(%p) removed (FIRST:NO) from %s, next element %x.\n",
     153                    batch, instance->name, batch->qh->next_queue);
     154                batch_t *prev =
     155                    list_get_instance(batch->link.prev, batch_t, link);
    122156                prev->qh->next_queue = batch->qh->next_queue;
    123157        }
     
    125159}
    126160/*----------------------------------------------------------------------------*/
     161/** Checks list for finished transfers.
     162 *
     163 * @param[in] instance List to use.
     164 * @return Error code
     165 */
    127166void transfer_list_remove_finished(transfer_list_t *instance)
    128167{
  • uspace/drv/uhci-hcd/transfer_list.h

    rf16a76b rec4538d  
    5858{
    5959        assert(instance);
    60         queue_head_dispose(instance->queue_head);
     60        free32(instance->queue_head);
    6161}
    6262void transfer_list_remove_finished(transfer_list_t *instance);
  • uspace/drv/uhci-hcd/uhci.c

    rf16a76b rec4538d  
    6161};
    6262
    63 static int usb_iface_get_address(ddf_fun_t *fun, devman_handle_t handle,
    64     usb_address_t *address)
     63/** Gets USB address of the calling device.
     64 *
     65 * @param[in] fun UHCI hc function.
     66 * @param[in] handle Handle of the device seeking address.
     67 * @param[out] address Place to store found address.
     68 * @return Error code.
     69 */
     70static int usb_iface_get_address(
     71    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
    6572{
    6673        assert(fun);
     
    99106
    100107static bool allowed_usb_packet(
    101         bool low_speed, usb_transfer_type_t, size_t size);
    102 
    103 
     108    bool low_speed, usb_transfer_type_t transfer, size_t size);
     109/*----------------------------------------------------------------------------*/
     110/** Initializes UHCI hcd driver structure
     111 *
     112 * @param[in] instance Memory place to initialize.
     113 * @param[in] dev DDF device.
     114 * @param[in] regs Address of I/O control registers.
     115 * @param[in] size Size of I/O control registers.
     116 * @return Error code.
     117 * @note Should be called only once on any structure.
     118 */
    104119int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size)
    105120{
     
    156171}
    157172/*----------------------------------------------------------------------------*/
     173/** Initializes UHCI hcd hw resources.
     174 *
     175 * @param[in] instance UHCI structure to use.
     176 */
    158177void uhci_init_hw(uhci_t *instance)
    159178{
    160179        assert(instance);
    161 
    162         /* reset everything, who knows what touched it before us */
    163         pio_write_16(&instance->registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
     180        regs_t *registers = instance->registers;
     181
     182        /* Reset everything, who knows what touched it before us */
     183        pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
    164184        async_usleep(10000); /* 10ms according to USB spec */
    165         pio_write_16(&instance->registers->usbcmd, 0);
    166 
    167         /* reset hc, all states and counters */
    168         pio_write_16(&instance->registers->usbcmd, UHCI_CMD_HCRESET);
     185        pio_write_16(&registers->usbcmd, 0);
     186
     187        /* Reset hc, all states and counters */
     188        pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
    169189        do { async_usleep(10); }
    170         while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0);
    171 
    172         /* set framelist pointer */
     190        while ((pio_read_16(&registers->usbcmd) & UHCI_CMD_HCRESET) != 0);
     191
     192        /* Set framelist pointer */
    173193        const uint32_t pa = addr_to_phys(instance->frame_list);
    174         pio_write_32(&instance->registers->flbaseadd, pa);
    175 
    176         /* enable all interrupts, but resume interrupt */
     194        pio_write_32(&registers->flbaseadd, pa);
     195
     196        /* Enable all interrupts, but resume interrupt */
    177197//      pio_write_16(&instance->registers->usbintr,
    178198//          UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
    179199
    180         uint16_t status = pio_read_16(&instance->registers->usbcmd);
    181         usb_log_warning("Previous command value: %x.\n", status);
     200        uint16_t status = pio_read_16(&registers->usbcmd);
     201        if (status != 0)
     202                usb_log_warning("Previous command value: %x.\n", status);
     203
    182204        /* Start the hc with large(64B) packet FSBR */
    183         pio_write_16(&instance->registers->usbcmd,
     205        pio_write_16(&registers->usbcmd,
    184206            UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
    185207}
    186208/*----------------------------------------------------------------------------*/
     209/** Initializes UHCI hcd memory structures.
     210 *
     211 * @param[in] instance UHCI structure to use.
     212 * @return Error code
     213 * @note Should be called only once on any structure.
     214 */
    187215int uhci_init_mem_structures(uhci_t *instance)
    188216{
     
    196224        } else (void) 0
    197225
    198         /* init interrupt code */
     226        /* Init interrupt code */
    199227        instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds));
    200228        int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK;
    201         CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to allocate interrupt cmds space.\n");
     229        CHECK_RET_DEST_CMDS_RETURN(ret,
     230            "Failed to allocate interrupt cmds space.\n");
    202231
    203232        {
    204233                irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds;
    205234                memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
    206                 interrupt_commands[0].addr = (void*)&instance->registers->usbsts;
    207                 interrupt_commands[1].addr = (void*)&instance->registers->usbsts;
     235                interrupt_commands[0].addr =
     236                    (void*)&instance->registers->usbsts;
     237                interrupt_commands[1].addr =
     238                    (void*)&instance->registers->usbsts;
    208239                instance->interrupt_code.cmdcount =
    209240                    sizeof(uhci_cmds) / sizeof(irq_cmd_t);
    210241        }
    211242
    212         /* init transfer lists */
     243        /* Init transfer lists */
    213244        ret = uhci_init_transfer_lists(instance);
    214         CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to initialize transfer lists.\n");
     245        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n");
    215246        usb_log_debug("Initialized transfer lists.\n");
    216247
    217         /* frame list initialization */
     248        /* Init USB frame list page*/
    218249        instance->frame_list = get_page();
    219250        ret = instance ? EOK : ENOMEM;
     
    221252        usb_log_debug("Initialized frame list.\n");
    222253
    223         /* initialize all frames to point to the first queue head */
     254        /* Set all frames to point to the first queue head */
    224255        const uint32_t queue =
    225256          instance->transfers_interrupt.queue_head_pa
     
    231262        }
    232263
    233         /* init address keeper(libusb) */
     264        /* Init device keeper*/
    234265        device_keeper_init(&instance->device_manager);
    235266        usb_log_debug("Initialized device manager.\n");
     
    239270}
    240271/*----------------------------------------------------------------------------*/
     272/** Initializes UHCI hcd transfer lists.
     273 *
     274 * @param[in] instance UHCI structure to use.
     275 * @return Error code
     276 * @note Should be called only once on any structure.
     277 */
    241278int uhci_init_transfer_lists(uhci_t *instance)
    242279{
     
    257294        CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
    258295
    259         ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL");
     296        ret = transfer_list_init(
     297            &instance->transfers_control_full, "CONTROL_FULL");
    260298        CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
    261299
    262         ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW");
     300        ret = transfer_list_init(
     301            &instance->transfers_control_slow, "CONTROL_SLOW");
    263302        CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
    264303
     
    279318#endif
    280319
    281         instance->transfers[0][USB_TRANSFER_INTERRUPT] =
     320        /* Assign pointers to be used during scheduling */
     321        instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] =
    282322          &instance->transfers_interrupt;
    283         instance->transfers[1][USB_TRANSFER_INTERRUPT] =
     323        instance->transfers[USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] =
    284324          &instance->transfers_interrupt;
    285         instance->transfers[0][USB_TRANSFER_CONTROL] =
     325        instance->transfers[USB_SPEED_FULL][USB_TRANSFER_CONTROL] =
    286326          &instance->transfers_control_full;
    287         instance->transfers[1][USB_TRANSFER_CONTROL] =
     327        instance->transfers[USB_SPEED_LOW][USB_TRANSFER_CONTROL] =
    288328          &instance->transfers_control_slow;
    289         instance->transfers[0][USB_TRANSFER_BULK] =
     329        instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] =
    290330          &instance->transfers_bulk_full;
    291331
     
    294334}
    295335/*----------------------------------------------------------------------------*/
     336/** Schedules batch for execution.
     337 *
     338 * @param[in] instance UHCI structure to use.
     339 * @param[in] batch Transfer batch to schedule.
     340 * @return Error code
     341 */
    296342int uhci_schedule(uhci_t *instance, batch_t *batch)
    297343{
     
    301347        if (!allowed_usb_packet(
    302348            low_speed, batch->transfer_type, batch->max_packet_size)) {
    303                 usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n",
     349                usb_log_warning(
     350                    "Invalid USB packet specified %s SPEED %d %zu.\n",
    304351                    low_speed ? "LOW" : "FULL" , batch->transfer_type,
    305352                    batch->max_packet_size);
     
    316363}
    317364/*----------------------------------------------------------------------------*/
     365/** Takes action based on the interrupt cause.
     366 *
     367 * @param[in] instance UHCI structure to use.
     368 * @param[in] status Value of the stsatus regiser at the time of interrupt.
     369 */
    318370void uhci_interrupt(uhci_t *instance, uint16_t status)
    319371{
    320372        assert(instance);
     373        /* TODO: Check interrupt cause here */
    321374        transfer_list_remove_finished(&instance->transfers_interrupt);
    322375        transfer_list_remove_finished(&instance->transfers_control_slow);
     
    325378}
    326379/*----------------------------------------------------------------------------*/
     380/** Polling function, emulates interrupts.
     381 *
     382 * @param[in] arg UHCI structure to use.
     383 * @return EOK
     384 */
    327385int uhci_interrupt_emulator(void* arg)
    328386{
     
    343401}
    344402/*---------------------------------------------------------------------------*/
     403/** Debug function, checks consistency of memory structures.
     404 *
     405 * @param[in] arg UHCI structure to use.
     406 * @return EOK
     407 */
    345408int uhci_debug_checker(void *arg)
    346409{
     
    401464                async_usleep(UHCI_DEBUGER_TIMEOUT);
    402465        }
    403         return 0;
     466        return EOK;
    404467#undef QH
    405468}
    406469/*----------------------------------------------------------------------------*/
     470/** Checks transfer packets, for USB validity
     471 *
     472 * @param[in] low_speed Transfer speed.
     473 * @param[in] transfer Transer type
     474 * @param[in] size Maximum size of used packets
     475 * @return EOK
     476 */
    407477bool allowed_usb_packet(
    408478    bool low_speed, usb_transfer_type_t transfer, size_t size)
  • uspace/drv/uhci-hcd/uhci.h

    rf16a76b rec4538d  
    8484        device_keeper_t device_manager;
    8585
    86         volatile regs_t *registers;
     86        regs_t *registers;
    8787
    8888        link_pointer_t *frame_list;
  • uspace/drv/uhci-hcd/uhci_struct/queue_head.h

    rf16a76b rec4538d  
    7171}
    7272
    73 static inline void queue_head_element_td(queue_head_t *instance, uint32_t pa)
     73static inline void queue_head_set_element_td(queue_head_t *instance, uint32_t pa)
    7474{
    7575        if (pa) {
     
    7878}
    7979
    80 static inline queue_head_t * queue_head_get() {
    81         queue_head_t *ret = malloc32(sizeof(queue_head_t));
    82         if (ret)
    83                 queue_head_init(ret);
    84         return ret;
    85 }
    86 
    87 static inline void queue_head_dispose(queue_head_t *head)
    88         { free32(head); }
    89 
    90 
    9180#endif
    9281/**
  • uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c

    rf16a76b rec4538d  
    3838#include "utils/malloc32.h"
    3939
     40/** Initializes Transfer Descriptor
     41 *
     42 * @param[in] instance Memory place to initialize.
     43 * @param[in] err_count Number of retries hc should attempt.
     44 * @param[in] size Size of data source.
     45 * @param[in] toggle Value of toggle bit.
     46 * @param[in] iso True if TD is for Isochronous transfer.
     47 * @param[in] low_speed Target device's speed.
     48 * @param[in] target Address and endpoint receiving the transfer.
     49 * @param[in] pid Packet identification (SETUP, IN or OUT).
     50 * @param[in] buffer Source of data.
     51 * @param[in] next Net TD in transaction.
     52 * @return Error code.
     53 */
    4054void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
    41     bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer, td_t *next)
     55    bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
     56    td_t *next)
    4257{
    4358        assert(instance);
    4459        assert(size < 1024);
    45         assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN) || (pid == USB_PID_OUT));
     60        assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN)
     61            || (pid == USB_PID_OUT));
    4662
    4763        instance->next = 0
     
    8197}
    8298/*----------------------------------------------------------------------------*/
     99/** Converts TD status into standard error code
     100 *
     101 * @param[in] instance TD structure to use.
     102 * @return Error code.
     103 */
    83104int td_status(td_t *instance)
    84105{
  • uspace/drv/uhci-hcd/utils/device_keeper.c

    rf16a76b rec4538d  
    3939
    4040/*----------------------------------------------------------------------------*/
     41/** Initializes device keeper structure.
     42 *
     43 * @param[in] instance Memory place to initialize.
     44 */
    4145void device_keeper_init(device_keeper_t *instance)
    4246{
     
    5357}
    5458/*----------------------------------------------------------------------------*/
    55 void device_keeper_reserve_default(
    56     device_keeper_t *instance, usb_speed_t speed)
     59/** Attempts to obtain address 0, blocks.
     60 *
     61 * @param[in] instance Device keeper structure to use.
     62 * @param[in] speed Speed of the device requesting default address.
     63 */
     64void device_keeper_reserve_default(device_keeper_t *instance, usb_speed_t speed)
    5765{
    5866        assert(instance);
     
    6775}
    6876/*----------------------------------------------------------------------------*/
     77/** Attempts to obtain address 0, blocks.
     78 *
     79 * @param[in] instance Device keeper structure to use.
     80 * @param[in] speed Speed of the device requesting default address.
     81 */
    6982void device_keeper_release_default(device_keeper_t *instance)
    7083{
     
    7689}
    7790/*----------------------------------------------------------------------------*/
     91/** Checks setup data for signs of toggle reset.
     92 *
     93 * @param[in] instance Device keeper structure to use.
     94 * @param[in] target Device to receive setup packet.
     95 * @param[in] data Setup packet data.
     96 */
    7897void device_keeper_reset_if_need(
    7998    device_keeper_t *instance, usb_target_t target, const unsigned char *data)
     
    84103            || target.address >= USB_ADDRESS_COUNT || target.address < 0
    85104            || !instance->devices[target.address].occupied) {
    86                 goto the_end;
     105                fibril_mutex_unlock(&instance->guard);
     106                return;
    87107        }
    88108
     
    90110        {
    91111        case 0x01: /*clear feature*/
    92                 /* recipient is enpoint, value is zero (ENDPOINT_STALL) */
     112                /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
    93113                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    94                         /* enpoint number is < 16, thus first byte is enough */
    95                         instance->devices[target.address].toggle_status &= ~(1 << data[4]);
     114                        /* endpoint number is < 16, thus first byte is enough */
     115                        instance->devices[target.address].toggle_status &=
     116                            ~(1 << data[4]);
    96117                }
    97118        break;
     
    102123        break;
    103124        }
    104 the_end:
    105         fibril_mutex_unlock(&instance->guard);
    106 }
    107 /*----------------------------------------------------------------------------*/
     125        fibril_mutex_unlock(&instance->guard);
     126}
     127/*----------------------------------------------------------------------------*/
     128/** Gets current value of endpoint toggle.
     129 *
     130 * @param[in] instance Device keeper structure to use.
     131 * @param[in] target Device and endpoint used.
     132 * @return Error code
     133 */
    108134int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target)
    109135{
     
    116142                ret = EINVAL;
    117143        } else {
    118                 ret = (instance->devices[target.address].toggle_status >> target.endpoint) & 1;
     144                ret =
     145                    (instance->devices[target.address].toggle_status
     146                        >> target.endpoint) & 1;
    119147        }
    120148        fibril_mutex_unlock(&instance->guard);
     
    122150}
    123151/*----------------------------------------------------------------------------*/
     152/** Sets current value of endpoint toggle.
     153 *
     154 * @param[in] instance Device keeper structure to use.
     155 * @param[in] target Device and endpoint used.
     156 * @param[in] toggle Current toggle value.
     157 * @return Error code.
     158 */
    124159int device_keeper_set_toggle(
    125160    device_keeper_t *instance, usb_target_t target, bool toggle)
     
    144179}
    145180/*----------------------------------------------------------------------------*/
     181/** Gets a free USB address
     182 *
     183 * @param[in] instance Device keeper structure to use.
     184 * @param[in] speed Speed of the device requiring address.
     185 * @return Free address, or error code.
     186 */
    146187usb_address_t device_keeper_request(
    147188    device_keeper_t *instance, usb_speed_t speed)
     
    171212}
    172213/*----------------------------------------------------------------------------*/
     214/** Binds USB address to devman handle.
     215 *
     216 * @param[in] instance Device keeper structure to use.
     217 * @param[in] address Device address
     218 * @param[in] handle Devman handle of the device.
     219 */
    173220void device_keeper_bind(
    174221    device_keeper_t *instance, usb_address_t address, devman_handle_t handle)
     
    183230}
    184231/*----------------------------------------------------------------------------*/
     232/** Releases used USB address.
     233 *
     234 * @param[in] instance Device keeper structure to use.
     235 * @param[in] address Device address
     236 */
    185237void device_keeper_release(device_keeper_t *instance, usb_address_t address)
    186238{
     
    195247}
    196248/*----------------------------------------------------------------------------*/
     249/** Finds USB address associated with the device
     250 *
     251 * @param[in] instance Device keeper structure to use.
     252 * @param[in] handle Devman handle of the device seeking its address.
     253 * @return USB Address, or error code.
     254 */
    197255usb_address_t device_keeper_find(
    198256    device_keeper_t *instance, devman_handle_t handle)
     
    212270}
    213271/*----------------------------------------------------------------------------*/
     272/** Gets speed associated with the address
     273 *
     274 * @param[in] instance Device keeper structure to use.
     275 * @param[in] address Address of the device.
     276 * @return USB speed.
     277 */
    214278usb_speed_t device_keeper_speed(
    215279    device_keeper_t *instance, usb_address_t address)
  • uspace/drv/uhci-rhd/main.c

    rf16a76b rec4538d  
    3535#include <devman.h>
    3636#include <device/hw_res.h>
     37#include <errno.h>
    3738#include <usb_iface.h>
    3839#include <usb/ddfiface.h>
     40#include <usb/debug.h>
    3941
    40 #include <errno.h>
    4142
    42 #include <usb/debug.h>
    4343
    4444#include "root_hub.h"
     
    4747static int hc_get_my_registers(ddf_dev_t *dev,
    4848    uintptr_t *io_reg_address, size_t *io_reg_size);
    49 
     49/*----------------------------------------------------------------------------*/
    5050static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
    5151{
     
    5858        return EOK;
    5959}
    60 
     60/*----------------------------------------------------------------------------*/
    6161static usb_iface_t uhci_rh_usb_iface = {
    6262        .get_hc_handle = usb_iface_get_hc_handle,
    6363        .get_address = usb_iface_get_address_hub_impl
    6464};
    65 
     65/*----------------------------------------------------------------------------*/
    6666static ddf_dev_ops_t uhci_rh_ops = {
    6767        .interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface,
    6868};
    69 
     69/*----------------------------------------------------------------------------*/
     70/** Initializes a new ddf driver instance of UHCI root hub.
     71 *
     72 * @param[in] device DDF instance of the device to initialize.
     73 * @return Error code.
     74 */
    7075static int uhci_rh_add_device(ddf_dev_t *device)
    7176{
     
    104109        return EOK;
    105110}
    106 
     111/*----------------------------------------------------------------------------*/
    107112static driver_ops_t uhci_rh_driver_ops = {
    108113        .add_device = uhci_rh_add_device,
    109114};
    110 
     115/*----------------------------------------------------------------------------*/
    111116static driver_t uhci_rh_driver = {
    112117        .name = NAME,
     
    114119};
    115120/*----------------------------------------------------------------------------*/
     121/** Initializes global driver structures (NONE).
     122 *
     123 * @param[in] argc Nmber of arguments in argv vector (ignored).
     124 * @param[in] argv Cmdline argument vector (ignored).
     125 * @return Error code.
     126 *
     127 * Driver debug level is set here.
     128 */
    116129int main(int argc, char *argv[])
    117130{
     
    120133}
    121134/*----------------------------------------------------------------------------*/
    122 int hc_get_my_registers(ddf_dev_t *dev,
    123     uintptr_t *io_reg_address, size_t *io_reg_size)
     135/** Get address of I/O registers.
     136 *
     137 * @param[in] dev Device asking for the addresses.
     138 * @param[out] io_reg_address Base address of the memory range.
     139 * @param[out] io_reg_size Size of the memory range.
     140 * @return Error code.
     141 */
     142int hc_get_my_registers(
     143    ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size)
    124144{
    125145        assert(dev != NULL);
     
    146166        for (i = 0; i < hw_resources.count; i++) {
    147167                hw_resource_t *res = &hw_resources.resources[i];
    148                 switch (res->type) {
    149                         case IO_RANGE:
    150                                 io_address = (uintptr_t)
    151                                     res->res.io_range.address;
    152                                 io_size = res->res.io_range.size;
    153                                 io_found = true;
    154                                 break;
    155                         default:
    156                                 break;
     168                switch (res->type)
     169                {
     170                case IO_RANGE:
     171                        io_address = (uintptr_t) res->res.io_range.address;
     172                        io_size = res->res.io_range.size;
     173                        io_found = true;
     174
     175                default:
     176                        break;
    157177                }
    158178        }
     
    170190        }
    171191        rc = EOK;
     192
    172193leave:
    173194        async_hangup(parent_phone);
    174 
    175195        return rc;
    176196}
  • uspace/drv/uhci-rhd/port.c

    rf16a76b rec4538d  
    4646#include "port_status.h"
    4747
    48 static int uhci_port_new_device(uhci_port_t *port, uint16_t status);
     48static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed);
    4949static int uhci_port_remove_device(uhci_port_t *port);
    5050static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
    5151static int uhci_port_check(void *port);
    52 static int new_device_enable_port(int portno, void *arg);
    53 
    54 int uhci_port_init(
    55   uhci_port_t *port, port_status_t *address, unsigned number,
    56   unsigned usec, ddf_dev_t *rh)
     52static int uhci_port_reset_enable(int portno, void *arg);
     53/*----------------------------------------------------------------------------*/
     54/** Initializes UHCI root hub port instance.
     55 *
     56 * @param[in] port Memory structure to use.
     57 * @param[in] addr Address of I/O register.
     58 * @param[in] number Port number.
     59 * @param[in] usec Polling interval.
     60 * @param[in] rh Pointer to ddf instance fo the root hub driver.
     61 * @return Error code.
     62 *
     63 * Starts the polling fibril.
     64 */
     65int uhci_port_init(uhci_port_t *port,
     66    port_status_t *address, unsigned number, unsigned usec, ddf_dev_t *rh)
    5767{
    5868        assert(port);
     69
    5970        port->address = address;
    6071        port->number = number;
     
    6273        port->attached_device = 0;
    6374        port->rh = rh;
     75
    6476        int rc = usb_hc_connection_initialize_from_device(
    6577            &port->hc_connection, rh);
     
    7587                return ENOMEM;
    7688        }
     89
    7790        fibril_add_ready(port->checker);
    7891        usb_log_debug("Port(%p - %d): Added fibril. %x\n",
     
    8194}
    8295/*----------------------------------------------------------------------------*/
     96/** Finishes UHCI root hub port instance.
     97 *
     98 * @param[in] port Memory structure to use.
     99 *
     100 * Stops the polling fibril.
     101 */
    83102void uhci_port_fini(uhci_port_t *port)
    84103{
    85 // TODO: destroy fibril
    86 // TODO: hangup phone
    87 //      fibril_teardown(port->checker);
     104        /* TODO: Kill fibril here */
    88105        return;
    89106}
    90107/*----------------------------------------------------------------------------*/
     108/** Periodically checks port status and reports new devices.
     109 *
     110 * @param[in] port Memory structure to use.
     111 * @return Error code.
     112 */
    91113int uhci_port_check(void *port)
    92114{
    93         uhci_port_t *port_instance = port;
    94         assert(port_instance);
    95 //      port_status_write(port_instance->address, 0);
    96 
     115        uhci_port_t *instance = port;
     116        assert(instance);
     117
     118        /* Iteration count, for debug purposes only */
    97119        unsigned count = 0;
    98120
    99121        while (1) {
    100                 async_usleep(port_instance->wait_period_usec);
     122                async_usleep(instance->wait_period_usec);
    101123
    102124                /* read register value */
    103                 port_status_t port_status =
    104                         port_status_read(port_instance->address);
    105 
    106                 /* debug print */
    107                 static fibril_mutex_t dbg_mtx = FIBRIL_MUTEX_INITIALIZER(dbg_mtx);
     125                port_status_t port_status = port_status_read(instance->address);
     126
     127                /* debug print mutex */
     128                static fibril_mutex_t dbg_mtx =
     129                    FIBRIL_MUTEX_INITIALIZER(dbg_mtx);
    108130                fibril_mutex_lock(&dbg_mtx);
    109131                usb_log_debug2("Port(%p - %d): Status: %#04x. === %u\n",
    110                   port_instance->address, port_instance->number, port_status, count++);
     132                  instance->address, instance->number, port_status, count++);
    111133//              print_port_status(port_status);
    112134                fibril_mutex_unlock(&dbg_mtx);
    113135
    114                 if ((port_status & STATUS_CONNECTED_CHANGED) != 0) {
    115                         usb_log_debug("Port(%p - %d): Connected change detected: %x.\n",
    116                             port_instance->address, port_instance->number, port_status);
    117 
    118 
    119                         int rc = usb_hc_connection_open(
    120                             &port_instance->hc_connection);
    121                         if (rc != EOK) {
    122                                 usb_log_error("Port(%p - %d): Failed to connect to HC.",
    123                                     port_instance->address, port_instance->number);
    124                                 continue;
    125                         }
    126 
    127                         /* remove any old device */
    128                         if (port_instance->attached_device) {
    129                                 usb_log_debug("Port(%p - %d): Removing device.\n",
    130                                     port_instance->address, port_instance->number);
    131                                 uhci_port_remove_device(port_instance);
    132                         }
    133 
    134                         if ((port_status & STATUS_CONNECTED) != 0) {
    135                                 /* new device */
    136                                 uhci_port_new_device(port_instance, port_status);
    137                         } else {
    138                                 /* ack changes by writing one to WC bits */
    139                                 port_status_write(port_instance->address, port_status);
    140                                 usb_log_debug("Port(%p - %d): Change status ACK.\n",
    141                                                 port_instance->address, port_instance->number);
    142                         }
    143 
    144                         rc = usb_hc_connection_close(
    145                             &port_instance->hc_connection);
    146                         if (rc != EOK) {
    147                                 usb_log_error("Port(%p - %d): Failed to disconnect from HC.",
    148                                     port_instance->address, port_instance->number);
    149                         }
    150                 }
    151         }
    152         return EOK;
    153 }
    154 
     136                if ((port_status & STATUS_CONNECTED_CHANGED) == 0)
     137                        continue;
     138
     139                usb_log_debug("Port(%p - %d): Connected change detected: %x.\n",
     140                    instance->address, instance->number, port_status);
     141
     142                int rc =
     143                    usb_hc_connection_open(&instance->hc_connection);
     144                if (rc != EOK) {
     145                        usb_log_error("Port(%p - %d): Failed to connect to HC.",
     146                            instance->address, instance->number);
     147                        continue;
     148                }
     149
     150                /* Remove any old device */
     151                if (instance->attached_device) {
     152                        usb_log_debug2("Port(%p - %d): Removing device.\n",
     153                            instance->address, instance->number);
     154                        uhci_port_remove_device(instance);
     155                }
     156
     157                if ((port_status & STATUS_CONNECTED) != 0) {
     158                        /* New device */
     159                        const usb_speed_t speed =
     160                            ((port_status & STATUS_LOW_SPEED) != 0) ?
     161                            USB_SPEED_LOW : USB_SPEED_FULL;
     162                        uhci_port_new_device(instance, speed);
     163                } else {
     164                        /* Write one to WC bits, to ack changes */
     165                        port_status_write(instance->address, port_status);
     166                        usb_log_debug("Port(%p - %d): Change status ACK.\n",
     167                            instance->address, instance->number);
     168                }
     169
     170                rc = usb_hc_connection_close(&instance->hc_connection);
     171                if (rc != EOK) {
     172                        usb_log_error("Port(%p - %d): Failed to disconnect.",
     173                            instance->address, instance->number);
     174                }
     175        }
     176        return EOK;
     177}
     178/*----------------------------------------------------------------------------*/
    155179/** Callback for enabling port during adding a new device.
    156180 *
     
    159183 * @return Error code.
    160184 */
    161 static int new_device_enable_port(int portno, void *arg)
     185int uhci_port_reset_enable(int portno, void *arg)
    162186{
    163187        uhci_port_t *port = (uhci_port_t *) arg;
     
    184208                port_status_write(port->address, port_status);
    185209                async_usleep(10000);
    186                 port_status =
    187                         port_status_read(port->address);
     210                port_status = port_status_read(port->address);
    188211                port_status &= ~STATUS_IN_RESET;
    189212                port_status_write(port->address, port_status);
     
    194217        /* Enable the port. */
    195218        uhci_port_set_enabled(port, true);
    196 
    197         return EOK;
    198 }
    199 
    200 /*----------------------------------------------------------------------------*/
    201 static int uhci_port_new_device(uhci_port_t *port, uint16_t status)
     219        return EOK;
     220}
     221/*----------------------------------------------------------------------------*/
     222/** Initializes and reports connected device.
     223 *
     224 * @param[in] port Memory structure to use.
     225 * @param[in] speed Detected speed.
     226 * @return Error code.
     227 *
     228 * Uses libUSB function to do the actual work.
     229 */
     230int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed)
    202231{
    203232        assert(port);
     
    209238        usb_address_t dev_addr;
    210239        int rc = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
    211             ((status & STATUS_LOW_SPEED) != 0) ? USB_SPEED_LOW : USB_SPEED_FULL,
    212             new_device_enable_port, port->number, port,
     240            speed, uhci_port_reset_enable, port->number, port,
    213241            &dev_addr, &port->attached_device, NULL, NULL, NULL);
    214242
    215243        if (rc != EOK) {
    216                 usb_log_error("Port(%p-%d): Failed(%d) adding new device: %s.\n",
     244                usb_log_error("Port(%p-%d): Failed(%d) to add device: %s.\n",
    217245                    port->address, port->number, rc, str_error(rc));
    218246                uhci_port_set_enabled(port, false);
     
    225253        return EOK;
    226254}
    227 
    228 /*----------------------------------------------------------------------------*/
    229 static int uhci_port_remove_device(uhci_port_t *port)
     255/*----------------------------------------------------------------------------*/
     256/** Removes device.
     257 *
     258 * @param[in] port Memory structure to use.
     259 * @return Error code.
     260 *
     261 * Does not work DDF does not support device removal.
     262 */
     263int uhci_port_remove_device(uhci_port_t *port)
    230264{
    231265        usb_log_error("Port(%p-%d): Don't know how to remove device %#x.\n",
    232                 port->address, port->number, (unsigned int)port->attached_device);
    233 //      uhci_port_set_enabled(port, false);
    234         return EOK;
    235 }
    236 /*----------------------------------------------------------------------------*/
    237 static int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
     266            port->address, port->number, (unsigned int)port->attached_device);
     267        return EOK;
     268}
     269/*----------------------------------------------------------------------------*/
     270/** Enables and disables port.
     271 *
     272 * @param[in] port Memory structure to use.
     273 * @return Error code. (Always EOK)
     274 */
     275int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
    238276{
    239277        assert(port);
    240278
    241         /* read register value */
    242         port_status_t port_status
    243                 = port_status_read(port->address);
    244 
    245         /* enable port: register write */
     279        /* Read register value */
     280        port_status_t port_status = port_status_read(port->address);
     281
     282        /* Set enabled bit */
    246283        if (enabled) {
    247284                port_status |= STATUS_ENABLED;
     
    249286                port_status &= ~STATUS_ENABLED;
    250287        }
     288
     289        /* Write new value. */
    251290        port_status_write(port->address, port_status);
    252291
  • uspace/drv/uhci-rhd/port_status.c

    rf16a76b rec4538d  
    6060};
    6161
     62/** Prints portr status in a human readable way.
     63 *
     64 * @param[in] value Port value to print.
     65 * @return Error code.
     66 */
    6267void print_port_status(port_status_t value)
    6368{
  • uspace/drv/uhci-rhd/root_hub.c

    rf16a76b rec4538d  
    4040#include "root_hub.h"
    4141
     42/** Initializes UHCI root hub instance.
     43 *
     44 * @param[in] instance Driver memory structure to use.
     45 * @param[in] addr Address of I/O registers.
     46 * @param[in] size Size of available I/O space.
     47 * @param[in] rh Pointer to ddf instance fo the root hub driver.
     48 * @return Error code.
     49 */
    4250int uhci_root_hub_init(
    4351  uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh)
     
    4755        int ret;
    4856
    49         /* allow access to root hub registers */
    50         assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT == size);
     57        /* Allow access to root hub port registers */
     58        assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT <= size);
    5159        port_status_t *regs;
    5260        ret = pio_enable(addr, size, (void**)&regs);
    53 
    5461        if (ret < 0) {
    55                 usb_log_error("Failed to gain access to port registers at %p\n", regs);
     62                usb_log_error(
     63                    "Failed to gain access to port registers at %p\n", regs);
    5664                return ret;
    5765        }
     
    6068        unsigned i = 0;
    6169        for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
    62                 /* mind pointer arithmetics */
     70                /* NOTE: mind pointer arithmetics here */
    6371                ret = uhci_port_init(
    64                   &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);
     72                    &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh);
    6573                if (ret != EOK) {
    6674                        unsigned j = 0;
     
    7482}
    7583/*----------------------------------------------------------------------------*/
    76 int uhci_root_hub_fini( uhci_root_hub_t* instance )
     84/** Finishes UHCI root hub instance.
     85 *
     86 * @param[in] instance Driver memory structure to use.
     87 * @return Error code.
     88 */
     89int uhci_root_hub_fini(uhci_root_hub_t* instance)
    7790{
    78         assert( instance );
    79         // TODO:
    80         //destroy fibril here
    81         //disable access to registers
     91        assert(instance);
     92        unsigned i = 0;
     93        for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
     94                uhci_port_fini(&instance->ports[i]);
     95        }
    8296        return EOK;
    8397}
Note: See TracChangeset for help on using the changeset viewer.