Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/ohci/root_hub.c

    r361fcec rf35b294  
    149149
    150150
    151 static int create_serialized_hub_descriptor(rh_t *instance);
    152 
    153 static int rh_init_descriptors(rh_t *instance);
     151static void usb_create_serialized_hub_descriptor(rh_t *instance,
     152        uint8_t ** out_result,
     153        size_t * out_size);
     154
     155static void rh_init_descriptors(rh_t *instance);
    154156
    155157static int process_get_port_status_request(rh_t *instance, uint16_t port,
     
    162164        usb_transfer_batch_t * request);
    163165
    164 static void create_interrupt_mask_in_instance(rh_t *instance);
     166static void create_interrupt_mask(rh_t *instance, void ** buffer,
     167        size_t * buffer_size);
    165168
    166169static int process_get_descriptor_request(rh_t *instance,
     
    195198static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
    196199
    197 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request);
    198 
    199 static bool is_zeros(void * buffer, size_t size);
     200
    200201
    201202
     
    204205 * @return Error code.
    205206 */
    206 int rh_init(rh_t *instance, ohci_regs_t *regs) {
     207int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs) {
    207208        assert(instance);
     209        //instance->address = -1;
    208210        instance->registers = regs;
    209         instance->port_count =
    210             (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
    211         int opResult = rh_init_descriptors(instance);
    212         if(opResult != EOK){
    213                 return opResult;
    214         }
     211        instance->device = dev;
     212        instance->port_count = instance->registers->rh_desc_a & 0xff;
     213        rh_init_descriptors(instance);
    215214        // set port power mode to no-power-switching
    216         instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
    217         instance->unfinished_interrupt_transfer = NULL;
    218         instance->interrupt_mask_size = (instance->port_count + 8)/8;
    219         instance->interrupt_buffer = malloc(instance->interrupt_mask_size);
    220         if(!instance->interrupt_buffer)
    221                 return ENOMEM;
    222        
     215        instance->registers->rh_desc_a =
     216                instance->registers->rh_desc_a | (1<<9);
    223217
    224218        usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
     219
     220        //start generic usb hub driver
     221
     222        /* TODO: implement */
    225223        return EOK;
    226224}
     
    238236        assert(request);
    239237        int opResult;
    240         if (request->ep->transfer_type == USB_TRANSFER_CONTROL) {
     238        if (request->transfer_type == USB_TRANSFER_CONTROL) {
    241239                usb_log_info("Root hub got CONTROL packet\n");
    242240                opResult = process_ctrl_request(instance, request);
    243                 usb_transfer_batch_finish_error(request, opResult);
    244         } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
     241        } else if (request->transfer_type == USB_TRANSFER_INTERRUPT) {
    245242                usb_log_info("Root hub got INTERRUPT packet\n");
    246                 create_interrupt_mask_in_instance(instance);
    247                 if(is_zeros(instance->interrupt_buffer,
    248                     instance->interrupt_mask_size)){
    249                         usb_log_debug("no changes..\n");
    250                         instance->unfinished_interrupt_transfer = request;
    251                         //will be finished later
    252                 }else{
    253                         usb_log_debug("processing changes..\n");
    254                         process_interrupt_mask_in_instance(instance, request);
    255                 }
     243                void * buffer;
     244                create_interrupt_mask(instance, &buffer,
     245                        &(request->transfered_size));
     246                memcpy(request->transport_buffer, buffer,
     247                        request->transfered_size);
    256248                opResult = EOK;
    257249        } else {
    258250                opResult = EINVAL;
    259                 usb_transfer_batch_finish_error(request, opResult);
    260         }
    261         return EOK;
    262 }
    263 
    264 /*----------------------------------------------------------------------------*/
    265 
    266 /**
    267  * process interrupt on a hub
    268  *
    269  * If there is no pending interrupt transfer, nothing happens.
    270  * @param instance
    271  */
     251        }
     252        usb_transfer_batch_finish_error(request, opResult);
     253        return EOK;
     254}
     255
     256/*----------------------------------------------------------------------------*/
     257
     258
    272259void rh_interrupt(rh_t *instance) {
    273         if(!instance->unfinished_interrupt_transfer){
    274                 return;
    275         }
    276         usb_log_debug("finalizing interrupt transfer\n");
    277         create_interrupt_mask_in_instance(instance);
    278         process_interrupt_mask_in_instance(instance,
    279             instance->unfinished_interrupt_transfer);
     260        usb_log_info("Whoa whoa wait, I`m not supposed to receive any "
     261                "interrupts, am I?\n");
     262        /* TODO: implement? */
    280263}
    281264/*----------------------------------------------------------------------------*/
     
    288271 *
    289272 * @param instance root hub instance
    290  * @return error code
    291  */
    292 static int create_serialized_hub_descriptor(rh_t *instance) {
    293         size_t size = 7 +
    294             ((instance->port_count +7 )/ 8) * 2;
    295         size_t var_size = (instance->port_count +7 )/ 8;
     273 * @param@out out_result pointer to resultant serialized descriptor
     274 * @param@out out_size size of serialized descriptor
     275 */
     276static void usb_create_serialized_hub_descriptor(rh_t *instance,
     277        uint8_t ** out_result,
     278        size_t * out_size) {
     279        //base size
     280        size_t size = 7;
     281        //variable size according to port count
     282        size_t var_size = instance->port_count / 8 +
     283                ((instance->port_count % 8 > 0) ? 1 : 0);
     284        size += 2 * var_size;
    296285        uint8_t * result = (uint8_t*) malloc(size);
    297         if(!result) return ENOMEM;
    298 
    299286        bzero(result, size);
    300287        //size
     
    325312                result[7 + var_size + i] = 255;
    326313        }
    327         instance->hub_descriptor = result;
    328         instance->descriptor_size = size;
    329         return EOK;
     314        (*out_result) = result;
     315        (*out_size) = size;
    330316}
    331317/*----------------------------------------------------------------------------*/
     
    336322 * be initialized only once per hub.
    337323 * @instance root hub instance
    338  * @return error code
    339  */
    340 static int rh_init_descriptors(rh_t *instance) {
     324 */
     325static void rh_init_descriptors(rh_t *instance) {
    341326        memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
    342327                sizeof (ohci_rh_device_descriptor)
     
    345330        memcpy(&descriptor, &ohci_rh_conf_descriptor,
    346331                sizeof (ohci_rh_conf_descriptor));
    347 
    348         int opResult = create_serialized_hub_descriptor(instance);
    349         if(opResult != EOK){
    350                 return opResult;
    351         }
     332        uint8_t * hub_descriptor;
     333        size_t hub_desc_size;
     334        usb_create_serialized_hub_descriptor(instance, &hub_descriptor,
     335                &hub_desc_size);
     336
    352337        descriptor.total_length =
    353338                sizeof (usb_standard_configuration_descriptor_t) +
    354339                sizeof (usb_standard_endpoint_descriptor_t) +
    355340                sizeof (usb_standard_interface_descriptor_t) +
    356                 instance->descriptor_size;
     341                hub_desc_size;
    357342
    358343        uint8_t * full_config_descriptor =
    359344                (uint8_t*) malloc(descriptor.total_length);
    360         if(!full_config_descriptor){
    361                 return ENOMEM;
    362         }
    363345        memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
    364346        memcpy(full_config_descriptor + sizeof (descriptor),
     
    370352                sizeof (ohci_rh_iface_descriptor) +
    371353                sizeof (ohci_rh_ep_descriptor),
    372                 instance->hub_descriptor, instance->descriptor_size);
    373        
     354                hub_descriptor, hub_desc_size);
     355
    374356        instance->descriptors.configuration = full_config_descriptor;
    375357        instance->descriptors.configuration_size = descriptor.total_length;
    376         return EOK;
    377358}
    378359/*----------------------------------------------------------------------------*/
     
    392373        if (port < 1 || port > instance->port_count)
    393374                return EINVAL;
    394         uint32_t * uint32_buffer = (uint32_t*) request->data_buffer;
     375        uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;
    395376        request->transfered_size = 4;
    396377        uint32_buffer[0] = instance->registers->rh_port_status[port - 1];
     
    418399static int process_get_hub_status_request(rh_t *instance,
    419400        usb_transfer_batch_t * request) {
    420         uint32_t * uint32_buffer = (uint32_t*) request->data_buffer;
     401        uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;
    421402        request->transfered_size = 4;
    422403        //bits, 0,1,16,17
     
    465446 * bit i indicates change on i`th port (i>0). For more info see
    466447 * Hub and Port status bitmap specification in USB specification
    467  * (chapter 11.13.4).
    468  * Uses instance`s interrupt buffer to store the interrupt information.
    469  * @param instance root hub instance
    470  */
    471 static void create_interrupt_mask_in_instance(rh_t * instance) {
    472         uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer);
     448 * (chapter 11.13.4)
     449 * @param instance root hub instance
     450 * @param@out buffer pointer to created interrupt mas
     451 * @param@out buffer_size size of created interrupt mask
     452 */
     453static void create_interrupt_mask(rh_t *instance, void ** buffer,
     454        size_t * buffer_size) {
     455        int bit_count = instance->port_count + 1;
     456        (*buffer_size) = (bit_count / 8) + ((bit_count % 8 == 0) ? 0 : 1);
     457
     458        (*buffer) = malloc(*buffer_size);
     459        uint8_t * bitmap = (uint8_t*) (*buffer);
    473460        uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
    474461                | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
    475         bzero(bitmap, instance->interrupt_mask_size);
     462        bzero(bitmap, (*buffer_size));
    476463        if (instance->registers->rh_status & mask) {
    477464                bitmap[0] = 1;
     
    504491        const uint16_t setup_request_value = setup_request->value_high;
    505492        //(setup_request->value_low << 8);
     493        bool del = false;
    506494        switch (setup_request_value) {
    507495                case USB_DESCTYPE_HUB:
    508496                {
    509                         usb_log_debug("USB_DESCTYPE_HUB\n");
    510                         result_descriptor = instance->hub_descriptor;
    511                         size = instance->descriptor_size;
     497                        uint8_t * descriptor;
     498                        usb_create_serialized_hub_descriptor(
     499                                instance, &descriptor, &size);
     500                        result_descriptor = descriptor;
     501                        if (result_descriptor) del = true;
    512502                        break;
    513503                }
     
    559549        }
    560550        request->transfered_size = size;
    561         memcpy(request->data_buffer, result_descriptor, size);
     551        memcpy(request->transport_buffer, result_descriptor, size);
     552        if (del)
     553                free(result_descriptor);
    562554        return EOK;
    563555}
     
    578570        if (request->buffer_size != 1)
    579571                return EINVAL;
    580         request->data_buffer[0] = 1;
     572        request->transport_buffer[0] = 1;
    581573        request->transfered_size = 1;
    582574        return EOK;
     
    873865        return opResult;
    874866}
    875 /*----------------------------------------------------------------------------*/
    876 
    877 /**
    878  * process hanging interrupt request
    879  *
    880  * If an interrupt transfer has been received and there was no change,
    881  * the driver stores the transfer information and waits for change to occcur.
    882  * This routine is called when that happens and it finalizes the interrupt
    883  * transfer.
    884  *
    885  * @param instance hub instance
    886  * @param request batch request to be processed
    887  *
    888  * @return
    889  */
    890 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request){
    891         memcpy(request->data_buffer, instance->interrupt_buffer,
    892             instance->interrupt_mask_size);
    893         request->transfered_size = instance->interrupt_mask_size;
    894         instance->unfinished_interrupt_transfer = NULL;
    895         usb_transfer_batch_finish_error(request, EOK);
    896         return EOK;
    897 }
    898 
    899 /*----------------------------------------------------------------------------*/
    900 
    901 /**
    902  * return whether the buffer is full of zeros
    903  *
    904  * Convenience function.
    905  * @param buffer
    906  * @param size
    907  * @return
    908  */
    909 static bool is_zeros(void * buffer, size_t size){
    910         if(!buffer) return true;
    911         if(!size) return true;
    912         size_t i;
    913         for(i=0;i<size;++i){
    914                 if(((char*)buffer)[i])
    915                         return false;
    916         }
    917         return true;
    918 }
    919867
    920868/**
Note: See TracChangeset for help on using the changeset viewer.