Ignore:
File:
1 edited

Legend:

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

    rf35b294 rbe11749  
    198198static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
    199199
    200 
     200static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request,
     201    void * change_buffer, size_t buffe_size);
     202
     203static bool is_zeros(void * buffer, size_t size);
    201204
    202205
     
    205208 * @return Error code.
    206209 */
    207 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs) {
     210int rh_init(rh_t *instance, ohci_regs_t *regs) {
    208211        assert(instance);
    209         //instance->address = -1;
    210212        instance->registers = regs;
    211         instance->device = dev;
    212         instance->port_count = instance->registers->rh_desc_a & 0xff;
     213        instance->port_count =
     214            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
    213215        rh_init_descriptors(instance);
    214216        // set port power mode to no-power-switching
    215         instance->registers->rh_desc_a =
    216                 instance->registers->rh_desc_a | (1<<9);
    217 
     217        instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
     218        instance->unfinished_interrupt_transfer = NULL;
    218219        usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
    219 
    220         //start generic usb hub driver
    221 
    222         /* TODO: implement */
    223220        return EOK;
    224221}
     
    236233        assert(request);
    237234        int opResult;
    238         if (request->transfer_type == USB_TRANSFER_CONTROL) {
     235        if (request->ep->transfer_type == USB_TRANSFER_CONTROL) {
    239236                usb_log_info("Root hub got CONTROL packet\n");
    240237                opResult = process_ctrl_request(instance, request);
    241         } else if (request->transfer_type == USB_TRANSFER_INTERRUPT) {
     238                usb_transfer_batch_finish_error(request, opResult);
     239        } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
    242240                usb_log_info("Root hub got INTERRUPT packet\n");
    243241                void * buffer;
     242                size_t buffer_size;
    244243                create_interrupt_mask(instance, &buffer,
    245                         &(request->transfered_size));
    246                 memcpy(request->transport_buffer, buffer,
    247                         request->transfered_size);
     244                        &buffer_size);
     245                if(is_zeros(buffer,buffer_size)){
     246                        usb_log_debug("no changes..");
     247                        instance->unfinished_interrupt_transfer=
     248                            request;
     249                        //will be finished later
     250                }else{
     251                        usb_log_debug("processing changes..");
     252                        process_interrupt(instance, request,
     253                            buffer, buffer_size);
     254                }
     255                free(buffer);
    248256                opResult = EOK;
    249257        } else {
    250258                opResult = EINVAL;
    251         }
    252         usb_transfer_batch_finish_error(request, opResult);
     259                usb_transfer_batch_finish_error(request, opResult);
     260        }
    253261        return EOK;
    254262}
     
    258266
    259267void rh_interrupt(rh_t *instance) {
    260         usb_log_info("Whoa whoa wait, I`m not supposed to receive any "
    261                 "interrupts, am I?\n");
    262         /* TODO: implement? */
     268        //usb_log_info("Whoa whoa wait, I`m not supposed to receive any "
     269        //      "interrupts, am I?\n");
     270        if(!instance->unfinished_interrupt_transfer){
     271                return;
     272        }
     273        size_t size;
     274        void * buffer;
     275        create_interrupt_mask(instance, &buffer,
     276                        &size);
     277        process_interrupt(instance,instance->unfinished_interrupt_transfer,
     278            buffer,size);
     279        free(buffer);
    263280}
    264281/*----------------------------------------------------------------------------*/
     
    373390        if (port < 1 || port > instance->port_count)
    374391                return EINVAL;
    375         uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;
     392        uint32_t * uint32_buffer = (uint32_t*) request->data_buffer;
    376393        request->transfered_size = 4;
    377394        uint32_buffer[0] = instance->registers->rh_port_status[port - 1];
     
    399416static int process_get_hub_status_request(rh_t *instance,
    400417        usb_transfer_batch_t * request) {
    401         uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer;
     418        uint32_t * uint32_buffer = (uint32_t*) request->data_buffer;
    402419        request->transfered_size = 4;
    403420        //bits, 0,1,16,17
     
    549566        }
    550567        request->transfered_size = size;
    551         memcpy(request->transport_buffer, result_descriptor, size);
     568        memcpy(request->data_buffer, result_descriptor, size);
    552569        if (del)
    553570                free(result_descriptor);
     
    570587        if (request->buffer_size != 1)
    571588                return EINVAL;
    572         request->transport_buffer[0] = 1;
     589        request->data_buffer[0] = 1;
    573590        request->transfered_size = 1;
    574591        return EOK;
     
    865882        return opResult;
    866883}
     884/*----------------------------------------------------------------------------*/
     885
     886/**
     887 * process hanging interrupt request
     888 *
     889 * If an interrupt transfer has been received and there was no change,
     890 * the driver stores the transfer information and waits for change to occcur.
     891 * This routine is called when that happens and it finalizes the interrupt
     892 * transfer.
     893 *
     894 * @param instance hub instance
     895 * @param request batch request to be processed
     896 * @param change_buffer chages on hub
     897 * @param buffer_size size of change buffer
     898 *
     899 * @return
     900 */
     901static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request,
     902    void * change_buffer, size_t buffe_size){
     903        create_interrupt_mask(instance, &change_buffer,
     904            &(request->transfered_size));
     905        memcpy(request->data_buffer, change_buffer,request->transfered_size);
     906        instance->unfinished_interrupt_transfer = NULL;
     907        usb_transfer_batch_finish_error(request, EOK);
     908        return EOK;
     909}
     910
     911/*----------------------------------------------------------------------------*/
     912
     913/**
     914 * return whether the buffer is full of zeros
     915 *
     916 * Convenience function.
     917 * @param buffer
     918 * @param size
     919 * @return
     920 */
     921static bool is_zeros(void * buffer, size_t size){
     922        if(!buffer) return true;
     923        if(!size) return true;
     924        size_t i;
     925        for(i=0;i<size;++i){
     926                if(((char*)buffer)[i])
     927                        return false;
     928        }
     929        return true;
     930}
    867931
    868932/**
Note: See TracChangeset for help on using the changeset viewer.