Changes in uspace/drv/ohci/hc.c [8790650:049eb87] in mainline


Ignore:
File:
1 edited

Legend:

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

    r8790650 r049eb87  
    4747static void hc_gain_control(hc_t *instance);
    4848static void hc_init_hw(hc_t *instance);
    49 static int hc_init_transfer_lists(hc_t *instance);
    50 static int hc_init_memory(hc_t *instance);
    5149/*----------------------------------------------------------------------------*/
    5250int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
     
    6159            &instance->manager, hub_address, hub_fun->handle);
    6260
    63         endpoint_t *ep = malloc(sizeof(endpoint_t));
    64         assert(ep);
    65         int ret = endpoint_init(ep, hub_address, 0, USB_DIRECTION_BOTH,
    66             USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64);
    67         assert(ret == EOK);
    68         ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, 0);
    69         assert(ret == EOK);
    70 
    7161        char *match_str = NULL;
    72         ret = asprintf(&match_str, "usb&class=hub");
    73 //      ret = (match_str == NULL) ? ret : EOK;
     62        int ret = asprintf(&match_str, "usb&class=hub");
     63        ret = (match_str == NULL) ? ret : EOK;
    7464        if (ret < 0) {
    75                 usb_log_error(
    76                     "Failed(%d) to create root hub match-id string.\n", ret);
     65                usb_log_error("Failed to create root hub match-id string.\n");
    7766                return ret;
    7867        }
     
    10897            ret, str_error(ret));
    10998
    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 
    116         rh_init(&instance->rh, dev, instance->registers);
    117 
    11899        if (!interrupts) {
    119100                instance->interrupt_emulator =
     
    122103        }
    123104
     105        hc_gain_control(instance);
     106
     107        rh_init(&instance->rh, dev, instance->registers);
     108
     109        hc_init_hw(instance);
     110
     111        /* TODO: implement */
    124112        return EOK;
    125113}
     
    129117        assert(instance);
    130118        assert(batch);
    131 
    132         /* check for root hub communication */
    133119        if (batch->target.address == instance->rh.address) {
    134120                return rh_request(&instance->rh, batch);
    135121        }
    136 
    137         transfer_list_add_batch(
    138             instance->transfers[batch->transfer_type], batch);
    139 
    140         switch (batch->transfer_type) {
    141         case USB_TRANSFER_CONTROL:
    142                 instance->registers->control &= ~C_CLE;
    143                 instance->registers->command_status |= CS_CLF;
    144                 usb_log_debug2("Set control transfer filled: %x.\n",
    145                         instance->registers->command_status);
    146                 instance->registers->control |= C_CLE;
    147                 break;
    148         case USB_TRANSFER_BULK:
    149                 instance->registers->command_status |= CS_BLF;
    150                 usb_log_debug2("Set bulk transfer filled: %x.\n",
    151                         instance->registers->command_status);
    152                 break;
    153         default:
    154                 break;
    155         }
    156         return EOK;
     122        /* TODO: implement */
     123        return ENOTSUP;
    157124}
    158125/*----------------------------------------------------------------------------*/
     
    160127{
    161128        assert(instance);
    162         if ((status & ~IS_SF) == 0) /* ignore sof status */
     129        if (status == 0)
    163130                return;
    164131        if (status & IS_RHSC)
     
    167134        usb_log_info("OHCI interrupt: %x.\n", status);
    168135
    169 
    170         LIST_INITIALIZE(done);
    171         transfer_list_remove_finished(&instance->transfers_interrupt, &done);
    172         transfer_list_remove_finished(&instance->transfers_isochronous, &done);
    173         transfer_list_remove_finished(&instance->transfers_control, &done);
    174         transfer_list_remove_finished(&instance->transfers_bulk, &done);
    175 
    176         while (!list_empty(&done)) {
    177                 link_t *item = done.next;
    178                 list_remove(item);
    179                 usb_transfer_batch_t *batch =
    180                     list_get_instance(item, usb_transfer_batch_t, link);
    181                 usb_transfer_batch_finish(batch);
    182         }
     136        /* TODO: Check for further interrupt causes */
     137        /* TODO: implement */
    183138}
    184139/*----------------------------------------------------------------------------*/
     
    199154{
    200155        assert(instance);
    201         /* Turn off legacy emulation */
    202         volatile uint32_t *ohci_emulation_reg =
    203             (uint32_t*)((char*)instance->registers + 0x100);
    204         usb_log_debug("OHCI legacy register %p: %x.\n",
    205                 ohci_emulation_reg, *ohci_emulation_reg);
    206         *ohci_emulation_reg = 0;
    207 
    208156        /* Interrupt routing enabled => smm driver is active */
    209157        if (instance->registers->control & C_IR) {
    210                 usb_log_debug("SMM driver: request ownership change.\n");
     158                usb_log_info("Found SMM driver requesting ownership change.\n");
    211159                instance->registers->command_status |= CS_OCR;
    212160                while (instance->registers->control & C_IR) {
    213161                        async_usleep(1000);
    214162                }
    215                 usb_log_info("SMM driver: Ownership taken.\n");
     163                usb_log_info("Ownership taken from SMM driver.\n");
    216164                return;
    217165        }
     
    221169        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
    222170        if (hc_status != C_HCFS_RESET) {
    223                 usb_log_debug("BIOS driver found.\n");
     171                usb_log_info("Found BIOS driver.\n");
    224172                if (hc_status == C_HCFS_OPERATIONAL) {
    225                         usb_log_info("BIOS driver: HC operational.\n");
     173                        usb_log_info("HC operational(BIOS).\n");
    226174                        return;
    227175                }
     
    229177                instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
    230178                async_usleep(20000);
    231                 usb_log_info("BIOS driver: HC resumed.\n");
    232179                return;
    233180        }
     
    235182        /* HC is in reset (hw startup) => no other driver
    236183         * maintain reset for at least the time specified in USB spec (50 ms)*/
    237         usb_log_info("HC found in reset.\n");
    238184        async_usleep(50000);
     185
     186        /* turn off legacy emulation */
     187        volatile uint32_t *ohci_emulation_reg =
     188            (uint32_t*)((char*)instance->registers + 0x100);
     189        usb_log_info("OHCI legacy register status %p: %x.\n",
     190                ohci_emulation_reg, *ohci_emulation_reg);
     191        *ohci_emulation_reg = 0;
     192
    239193}
    240194/*----------------------------------------------------------------------------*/
    241195void hc_init_hw(hc_t *instance)
    242196{
    243         /* OHCI guide page 42 */
    244         assert(instance);
    245         usb_log_debug2("Started hc initialization routine.\n");
    246 
    247         /* Save contents of fm_interval register */
     197        assert(instance);
    248198        const uint32_t fm_interval = instance->registers->fm_interval;
    249         usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
    250 
    251         /* Reset hc */
    252         usb_log_debug2("HC reset.\n");
    253         size_t time = 0;
    254199        instance->registers->command_status = CS_HCR;
    255         while (instance->registers->command_status & CS_HCR) {
    256                 async_usleep(10);
    257                 time += 10;
    258         }
    259         usb_log_debug2("HC reset complete in %zu us.\n", time);
    260 
    261         /* Restore fm_interval */
     200        async_usleep(10);
    262201        instance->registers->fm_interval = fm_interval;
    263202        assert((instance->registers->command_status & CS_HCR) == 0);
    264 
    265203        /* hc is now in suspend state */
    266         usb_log_debug2("HC should be in suspend state(%x).\n",
    267             instance->registers->control);
    268 
    269         /* Enable queues */
    270         instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
    271         usb_log_debug2("All queues enabled(%x).\n",
    272             instance->registers->control);
    273 
    274         /* Disable interrupts */
    275         instance->registers->interrupt_disable = I_SF | I_OC;
    276         usb_log_debug2("Disabling interrupts: %x.\n",
    277             instance->registers->interrupt_disable);
    278         instance->registers->interrupt_disable = I_MI;
    279         usb_log_debug2("Enabled interrupts: %x.\n",
    280             instance->registers->interrupt_enable);
    281 
    282         /* Set periodic start to 90% */
    283         uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
    284         instance->registers->periodic_start = (frame_length / 10) * 9;
    285         usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
    286             instance->registers->periodic_start,
    287             instance->registers->periodic_start, frame_length);
     204        /* TODO: init HCCA block */
     205        /* TODO: init queues */
     206        /* TODO: enable queues */
     207        /* TODO: enable interrupts */
     208        /* TODO: set periodic start to 90% */
    288209
    289210        instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
    290         usb_log_info("OHCI HC up and running(%x).\n",
    291             instance->registers->control);
    292 }
    293 /*----------------------------------------------------------------------------*/
    294 int hc_init_transfer_lists(hc_t *instance)
    295 {
    296         assert(instance);
    297 
    298 #define SETUP_TRANSFER_LIST(type, name) \
    299 do { \
    300         int ret = transfer_list_init(&instance->type, name); \
    301         if (ret != EOK) { \
    302                 usb_log_error("Failed(%d) to setup %s transfer list.\n", \
    303                     ret, name); \
    304                 transfer_list_fini(&instance->transfers_isochronous); \
    305                 transfer_list_fini(&instance->transfers_interrupt); \
    306                 transfer_list_fini(&instance->transfers_control); \
    307                 transfer_list_fini(&instance->transfers_bulk); \
    308         } \
    309 } while (0)
    310 
    311         SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS");
    312         SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT");
    313         SETUP_TRANSFER_LIST(transfers_control, "CONTROL");
    314         SETUP_TRANSFER_LIST(transfers_bulk, "BULK");
    315 
    316         transfer_list_set_next(&instance->transfers_interrupt,
    317             &instance->transfers_isochronous);
    318 
    319         /* Assign pointers to be used during scheduling */
    320         instance->transfers[USB_TRANSFER_INTERRUPT] =
    321           &instance->transfers_interrupt;
    322         instance->transfers[USB_TRANSFER_ISOCHRONOUS] =
    323           &instance->transfers_interrupt;
    324         instance->transfers[USB_TRANSFER_CONTROL] =
    325           &instance->transfers_control;
    326         instance->transfers[USB_TRANSFER_BULK] =
    327           &instance->transfers_bulk;
    328 
    329         return EOK;
    330 #undef CHECK_RET_CLEAR_RETURN
    331 }
    332 /*----------------------------------------------------------------------------*/
    333 int hc_init_memory(hc_t *instance)
    334 {
    335         assert(instance);
    336         /* Init queues */
    337         hc_init_transfer_lists(instance);
    338 
    339         /*Init HCCA */
    340         instance->hcca = malloc32(sizeof(hcca_t));
    341         if (instance->hcca == NULL)
    342                 return ENOMEM;
    343         bzero(instance->hcca, sizeof(hcca_t));
    344         instance->registers->hcca = addr_to_phys(instance->hcca);
    345         usb_log_debug2("OHCI HCCA initialized at %p(%p).\n",
    346             instance->hcca, instance->registers->hcca);
    347 
    348         /* Use queues */
    349         instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
    350         usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
    351             instance->transfers_bulk.list_head,
    352             instance->transfers_bulk.list_head_pa);
    353 
    354         instance->registers->control_head =
    355             instance->transfers_control.list_head_pa;
    356         usb_log_debug2("Control HEAD set to: %p(%p).\n",
    357             instance->transfers_control.list_head,
    358             instance->transfers_control.list_head_pa);
    359 
    360         unsigned i = 0;
    361         for (; i < 32; ++i) {
    362                 instance->hcca->int_ep[i] =
    363                     instance->transfers_interrupt.list_head_pa;
    364         }
    365         usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
    366             instance->transfers_interrupt.list_head,
    367             instance->transfers_interrupt.list_head_pa);
    368 
    369         return EOK;
     211        usb_log_info("OHCI HC up and running.\n");
    370212}
    371213/**
Note: See TracChangeset for help on using the changeset viewer.