Changeset 3f3afb9 in mainline for uspace/drv/ohci/hc.c


Ignore:
Timestamp:
2011-04-11T20:38:37Z (13 years ago)
Author:
Matus Dekanek <smekideki@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1324ff3, a39cfb8
Parents:
58226b4 (diff), d91645ab (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

forgotten hub port powering

File:
1 edited

Legend:

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

    r58226b4 r3f3afb9  
    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
    110119        if (!interrupts) {
    111120                instance->interrupt_emulator =
     
    114123        }
    115124
    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 */
    124125        return EOK;
    125126}
     
    135136        }
    136137
    137         transfer_list_add_batch(
    138             instance->transfers[batch->transfer_type], batch);
    139 
     138        fibril_mutex_lock(&instance->guard);
    140139        switch (batch->transfer_type) {
    141140        case USB_TRANSFER_CONTROL:
     141                instance->registers->control &= ~C_CLE;
     142                transfer_list_add_batch(
     143                    instance->transfers[batch->transfer_type], batch);
    142144                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;
    143149                break;
    144150        case USB_TRANSFER_BULK:
     151                instance->registers->control &= ~C_BLE;
     152                transfer_list_add_batch(
     153                    instance->transfers[batch->transfer_type], batch);
    145154                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);
    146167                break;
    147168        default:
    148169                break;
    149170        }
     171        fibril_mutex_unlock(&instance->guard);
    150172        return EOK;
    151173}
     
    154176{
    155177        assert(instance);
    156         if (status == 0)
     178        if ((status & ~IS_SF) == 0) /* ignore sof status */
    157179                return;
    158180        if (status & IS_RHSC)
    159181                rh_interrupt(&instance->rh);
    160182
    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);
     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);
    175209        }
    176210}
     
    184218                instance->registers->interrupt_status = status;
    185219                hc_interrupt(instance, status);
    186                 async_usleep(1000);
     220                async_usleep(50000);
    187221        }
    188222        return EOK;
     
    192226{
    193227        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
    194235        /* Interrupt routing enabled => smm driver is active */
    195236        if (instance->registers->control & C_IR) {
    196                 usb_log_info("Found SMM driver requesting ownership change.\n");
     237                usb_log_debug("SMM driver: request ownership change.\n");
    197238                instance->registers->command_status |= CS_OCR;
    198239                while (instance->registers->control & C_IR) {
    199240                        async_usleep(1000);
    200241                }
    201                 usb_log_info("Ownership taken from SMM driver.\n");
     242                usb_log_info("SMM driver: Ownership taken.\n");
    202243                return;
    203244        }
     
    207248        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
    208249        if (hc_status != C_HCFS_RESET) {
    209                 usb_log_info("Found BIOS driver.\n");
     250                usb_log_debug("BIOS driver found.\n");
    210251                if (hc_status == C_HCFS_OPERATIONAL) {
    211                         usb_log_info("HC operational(BIOS).\n");
     252                        usb_log_info("BIOS driver: HC operational.\n");
    212253                        return;
    213254                }
     
    215256                instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
    216257                async_usleep(20000);
     258                usb_log_info("BIOS driver: HC resumed.\n");
    217259                return;
    218260        }
     
    220262        /* HC is in reset (hw startup) => no other driver
    221263         * maintain reset for at least the time specified in USB spec (50 ms)*/
     264        usb_log_info("HC found in reset.\n");
    222265        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 
    231266}
    232267/*----------------------------------------------------------------------------*/
    233268void hc_init_hw(hc_t *instance)
    234269{
    235         assert(instance);
     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 */
    236275        const uint32_t fm_interval = instance->registers->fm_interval;
    237 
    238         /* reset hc */
     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;
    239281        instance->registers->command_status = CS_HCR;
    240         async_usleep(10);
    241 
    242         /* restore fm_interval */
     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 */
    243289        instance->registers->fm_interval = fm_interval;
    244290        assert((instance->registers->command_status & CS_HCR) == 0);
    245291
    246292        /* hc is now in suspend state */
    247 
    248         /* enable queues */
     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 */
    249312        instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
    250         /* TODO: enable interrupts */
    251         /* set periodic start to 90% */
    252         instance->registers->periodic_start = (fm_interval / 10) * 9;
     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);
    253330
    254331        instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
    255         usb_log_info("OHCI HC up and running.\n");
     332        usb_log_info("OHCI HC up and running(%x).\n",
     333            instance->registers->control);
    256334}
    257335/*----------------------------------------------------------------------------*/
     
    277355        SETUP_TRANSFER_LIST(transfers_control, "CONTROL");
    278356        SETUP_TRANSFER_LIST(transfers_bulk, "BULK");
    279 
     357#undef SETUP_TRANSFER_LIST
    280358        transfer_list_set_next(&instance->transfers_interrupt,
    281359            &instance->transfers_isochronous);
     
    292370
    293371        return EOK;
    294 #undef CHECK_RET_CLEAR_RETURN
    295372}
    296373/*----------------------------------------------------------------------------*/
     
    298375{
    299376        assert(instance);
    300         /* init queues */
     377        /* Init queues */
    301378        hc_init_transfer_lists(instance);
    302379
    303         /* init HCCA */
     380        /*Init HCCA */
    304381        instance->hcca = malloc32(sizeof(hcca_t));
    305382        if (instance->hcca == NULL)
    306383                return ENOMEM;
    307384        bzero(instance->hcca, sizeof(hcca_t));
    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;
     385        usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
    314386
    315387        unsigned i = 0;
     
    318390                    instance->transfers_interrupt.list_head_pa;
    319391        }
     392        usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
     393            instance->transfers_interrupt.list_head,
     394            instance->transfers_interrupt.list_head_pa);
    320395
    321396        return EOK;
Note: See TracChangeset for help on using the changeset viewer.