Changes in uspace/drv/ohci/hc.c [aa9ccf7:9ff5ff82] in mainline


Ignore:
File:
1 edited

Legend:

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

    raa9ccf7 r9ff5ff82  
    108108            ret, str_error(ret));
    109109
    110         hc_gain_control(instance);
    111         ret = hc_init_memory(instance);
    112         CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures:%s.\n",
    113             ret, str_error(ret));
    114         hc_init_hw(instance);
    115         fibril_mutex_initialize(&instance->guard);
    116 
    117         rh_init(&instance->rh, dev, instance->registers);
    118 
    119110        if (!interrupts) {
    120111                instance->interrupt_emulator =
     
    123114        }
    124115
     116        hc_gain_control(instance);
     117
     118        rh_init(&instance->rh, dev, instance->registers);
     119
     120        hc_init_memory(instance);
     121        hc_init_hw(instance);
     122
     123        /* TODO: implement */
    125124        return EOK;
    126125}
     
    136135        }
    137136
    138         fibril_mutex_lock(&instance->guard);
     137        transfer_list_add_batch(
     138            instance->transfers[batch->transfer_type], batch);
     139
    139140        switch (batch->transfer_type) {
    140141        case USB_TRANSFER_CONTROL:
    141                 instance->registers->control &= ~C_CLE;
    142                 transfer_list_add_batch(
    143                     instance->transfers[batch->transfer_type], batch);
    144142                instance->registers->command_status |= CS_CLF;
    145                 usb_log_debug2("Set CS control transfer filled: %x.\n",
    146                         instance->registers->command_status);
    147                 instance->registers->control_current = 0;
    148                 instance->registers->control |= C_CLE;
    149143                break;
    150144        case USB_TRANSFER_BULK:
    151                 instance->registers->control &= ~C_BLE;
    152                 transfer_list_add_batch(
    153                     instance->transfers[batch->transfer_type], batch);
    154145                instance->registers->command_status |= CS_BLF;
    155                 usb_log_debug2("Set bulk transfer filled: %x.\n",
    156                         instance->registers->command_status);
    157                 instance->registers->control |= C_BLE;
    158                 break;
    159         case USB_TRANSFER_INTERRUPT:
    160         case USB_TRANSFER_ISOCHRONOUS:
    161                 instance->registers->control &= (~C_PLE & ~C_IE);
    162                 transfer_list_add_batch(
    163                     instance->transfers[batch->transfer_type], batch);
    164                 instance->registers->control |= C_PLE | C_IE;
    165                 usb_log_debug2("Added periodic transfer: %x.\n",
    166                     instance->registers->periodic_current);
    167146                break;
    168147        default:
    169148                break;
    170149        }
    171         fibril_mutex_unlock(&instance->guard);
    172150        return EOK;
    173151}
     
    176154{
    177155        assert(instance);
    178         if ((status & ~IS_SF) == 0) /* ignore sof status */
     156        if (status == 0)
    179157                return;
    180158        if (status & IS_RHSC)
    181159                rh_interrupt(&instance->rh);
    182160
    183         usb_log_debug("OHCI interrupt: %x.\n", status);
    184 
    185         if (status & IS_WDH) {
    186                 fibril_mutex_lock(&instance->guard);
    187                 usb_log_debug2("HCCA: %p-%p(%p).\n", instance->hcca,
    188                     instance->registers->hcca, addr_to_phys(instance->hcca));
    189                 usb_log_debug2("Periodic current: %p.\n",
    190                     instance->registers->periodic_current);
    191                 LIST_INITIALIZE(done);
    192                 transfer_list_remove_finished(
    193                     &instance->transfers_interrupt, &done);
    194                 transfer_list_remove_finished(
    195                     &instance->transfers_isochronous, &done);
    196                 transfer_list_remove_finished(
    197                     &instance->transfers_control, &done);
    198                 transfer_list_remove_finished(
    199                     &instance->transfers_bulk, &done);
    200 
    201                 while (!list_empty(&done)) {
    202                         link_t *item = done.next;
    203                         list_remove(item);
    204                         usb_transfer_batch_t *batch =
    205                             list_get_instance(item, usb_transfer_batch_t, link);
    206                         usb_transfer_batch_finish(batch);
    207                 }
    208                 fibril_mutex_unlock(&instance->guard);
     161        usb_log_info("OHCI interrupt: %x.\n", status);
     162
     163        LIST_INITIALIZE(done);
     164        transfer_list_remove_finished(&instance->transfers_interrupt, &done);
     165        transfer_list_remove_finished(&instance->transfers_isochronous, &done);
     166        transfer_list_remove_finished(&instance->transfers_control, &done);
     167        transfer_list_remove_finished(&instance->transfers_bulk, &done);
     168
     169        while (!list_empty(&done)) {
     170                link_t *item = done.next;
     171                list_remove(item);
     172                usb_transfer_batch_t *batch =
     173                    list_get_instance(item, usb_transfer_batch_t, link);
     174                usb_transfer_batch_finish(batch);
    209175        }
    210176}
     
    218184                instance->registers->interrupt_status = status;
    219185                hc_interrupt(instance, status);
    220                 async_usleep(50000);
     186                async_usleep(1000);
    221187        }
    222188        return EOK;
     
    226192{
    227193        assert(instance);
    228         /* Turn off legacy emulation */
    229         volatile uint32_t *ohci_emulation_reg =
    230             (uint32_t*)((char*)instance->registers + 0x100);
    231         usb_log_debug("OHCI legacy register %p: %x.\n",
    232                 ohci_emulation_reg, *ohci_emulation_reg);
    233         *ohci_emulation_reg = 0;
    234 
    235194        /* Interrupt routing enabled => smm driver is active */
    236195        if (instance->registers->control & C_IR) {
    237                 usb_log_debug("SMM driver: request ownership change.\n");
     196                usb_log_info("Found SMM driver requesting ownership change.\n");
    238197                instance->registers->command_status |= CS_OCR;
    239198                while (instance->registers->control & C_IR) {
    240199                        async_usleep(1000);
    241200                }
    242                 usb_log_info("SMM driver: Ownership taken.\n");
     201                usb_log_info("Ownership taken from SMM driver.\n");
    243202                return;
    244203        }
     
    248207        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
    249208        if (hc_status != C_HCFS_RESET) {
    250                 usb_log_debug("BIOS driver found.\n");
     209                usb_log_info("Found BIOS driver.\n");
    251210                if (hc_status == C_HCFS_OPERATIONAL) {
    252                         usb_log_info("BIOS driver: HC operational.\n");
     211                        usb_log_info("HC operational(BIOS).\n");
    253212                        return;
    254213                }
     
    256215                instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
    257216                async_usleep(20000);
    258                 usb_log_info("BIOS driver: HC resumed.\n");
    259217                return;
    260218        }
     
    262220        /* HC is in reset (hw startup) => no other driver
    263221         * maintain reset for at least the time specified in USB spec (50 ms)*/
    264         usb_log_info("HC found in reset.\n");
    265222        async_usleep(50000);
     223
     224        /* turn off legacy emulation */
     225        volatile uint32_t *ohci_emulation_reg =
     226            (uint32_t*)((char*)instance->registers + 0x100);
     227        usb_log_info("OHCI legacy register status %p: %x.\n",
     228                ohci_emulation_reg, *ohci_emulation_reg);
     229        *ohci_emulation_reg = 0;
     230
    266231}
    267232/*----------------------------------------------------------------------------*/
    268233void hc_init_hw(hc_t *instance)
    269234{
    270         /* OHCI guide page 42 */
    271         assert(instance);
    272         usb_log_debug2("Started hc initialization routine.\n");
    273 
    274         /* Save contents of fm_interval register */
     235        assert(instance);
    275236        const uint32_t fm_interval = instance->registers->fm_interval;
    276         usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
    277 
    278         /* Reset hc */
    279         usb_log_debug2("HC reset.\n");
    280         size_t time = 0;
     237
     238        /* reset hc */
    281239        instance->registers->command_status = CS_HCR;
    282         while (instance->registers->command_status & CS_HCR) {
    283                 async_usleep(10);
    284                 time += 10;
    285         }
    286         usb_log_debug2("HC reset complete in %zu us.\n", time);
    287 
    288         /* Restore fm_interval */
     240        async_usleep(10);
     241
     242        /* restore fm_interval */
    289243        instance->registers->fm_interval = fm_interval;
    290244        assert((instance->registers->command_status & CS_HCR) == 0);
    291245
    292246        /* hc is now in suspend state */
    293         usb_log_debug2("HC should be in suspend state(%x).\n",
    294             instance->registers->control);
    295 
    296         /* Use HCCA */
    297         instance->registers->hcca = addr_to_phys(instance->hcca);
    298 
    299         /* Use queues */
    300         instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
    301         usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
    302             instance->transfers_bulk.list_head,
    303             instance->transfers_bulk.list_head_pa);
    304 
    305         instance->registers->control_head =
    306             instance->transfers_control.list_head_pa;
    307         usb_log_debug2("Control HEAD set to: %p(%p).\n",
    308             instance->transfers_control.list_head,
    309             instance->transfers_control.list_head_pa);
    310 
    311         /* Enable queues */
     247
     248        /* enable queues */
    312249        instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
    313         usb_log_debug2("All queues enabled(%x).\n",
    314             instance->registers->control);
    315 
    316         /* Disable interrupts */
    317         instance->registers->interrupt_disable = I_SF | I_OC;
    318         usb_log_debug2("Disabling interrupts: %x.\n",
    319             instance->registers->interrupt_disable);
    320         instance->registers->interrupt_disable = I_MI;
    321         usb_log_debug2("Enabled interrupts: %x.\n",
    322             instance->registers->interrupt_enable);
    323 
    324         /* Set periodic start to 90% */
    325         uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
    326         instance->registers->periodic_start = (frame_length / 10) * 9;
    327         usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
    328             instance->registers->periodic_start,
    329             instance->registers->periodic_start, frame_length);
     250        /* TODO: enable interrupts */
     251        /* set periodic start to 90% */
     252        instance->registers->periodic_start = (fm_interval / 10) * 9;
    330253
    331254        instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
    332         usb_log_info("OHCI HC up and running(%x).\n",
    333             instance->registers->control);
     255        usb_log_info("OHCI HC up and running.\n");
    334256}
    335257/*----------------------------------------------------------------------------*/
     
    355277        SETUP_TRANSFER_LIST(transfers_control, "CONTROL");
    356278        SETUP_TRANSFER_LIST(transfers_bulk, "BULK");
    357 #undef SETUP_TRANSFER_LIST
     279
    358280        transfer_list_set_next(&instance->transfers_interrupt,
    359281            &instance->transfers_isochronous);
     
    370292
    371293        return EOK;
     294#undef CHECK_RET_CLEAR_RETURN
    372295}
    373296/*----------------------------------------------------------------------------*/
     
    375298{
    376299        assert(instance);
    377         /* Init queues */
     300        /* init queues */
    378301        hc_init_transfer_lists(instance);
    379302
    380         /*Init HCCA */
     303        /* init HCCA */
    381304        instance->hcca = malloc32(sizeof(hcca_t));
    382305        if (instance->hcca == NULL)
    383306                return ENOMEM;
    384307        bzero(instance->hcca, sizeof(hcca_t));
    385         usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
     308        instance->registers->hcca = addr_to_phys(instance->hcca);
     309
     310        /* use queues */
     311        instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
     312        instance->registers->control_head =
     313            instance->transfers_control.list_head_pa;
    386314
    387315        unsigned i = 0;
     
    390318                    instance->transfers_interrupt.list_head_pa;
    391319        }
    392         usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
    393             instance->transfers_interrupt.list_head,
    394             instance->transfers_interrupt.list_head_pa);
    395320
    396321        return EOK;
Note: See TracChangeset for help on using the changeset viewer.