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


Ignore:
File:
1 edited

Legend:

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

    r53f1c87 r049eb87  
    4545
    4646static int interrupt_emulator(hc_t *instance);
     47static void hc_gain_control(hc_t *instance);
     48static void hc_init_hw(hc_t *instance);
    4749/*----------------------------------------------------------------------------*/
    4850int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
     
    5860
    5961        char *match_str = NULL;
    60         int ret = asprintf(&match_str, "usb&mid");
     62        int ret = asprintf(&match_str, "usb&class=hub");
    6163        ret = (match_str == NULL) ? ret : EOK;
    6264        if (ret < 0) {
     
    7779        assert(instance);
    7880        int ret = EOK;
     81#define CHECK_RET_RETURN(ret, message...) \
     82if (ret != EOK) { \
     83        usb_log_error(message); \
     84        return ret; \
     85} else (void)0
    7986
    8087        ret = pio_enable((void*)regs, reg_size, (void**)&instance->registers);
    81         if (ret != EOK) {
    82                 usb_log_error("Failed to gain access to device registers.\n");
    83                 return ret;
    84         }
     88        CHECK_RET_RETURN(ret,
     89            "Failed(%d) to gain access to device registers: %s.\n",
     90            ret, str_error(ret));
     91
    8592        instance->ddf_instance = fun;
    8693        usb_device_keeper_init(&instance->manager);
     94        ret = usb_endpoint_manager_init(&instance->ep_manager,
     95            BANDWIDTH_AVAILABLE_USB11);
     96        CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
     97            ret, str_error(ret));
    8798
    8899        if (!interrupts) {
     
    92103        }
    93104
     105        hc_gain_control(instance);
     106
    94107        rh_init(&instance->rh, dev, instance->registers);
     108
     109        hc_init_hw(instance);
    95110
    96111        /* TODO: implement */
     
    117132                rh_interrupt(&instance->rh);
    118133
     134        usb_log_info("OHCI interrupt: %x.\n", status);
     135
    119136        /* TODO: Check for further interrupt causes */
    120137        /* TODO: implement */
     
    126143        usb_log_info("Started interrupt emulator.\n");
    127144        while (1) {
    128                 uint32_t status = instance->registers->interrupt_status;
     145                const uint32_t status = instance->registers->interrupt_status;
    129146                instance->registers->interrupt_status = status;
    130147                hc_interrupt(instance, status);
     
    133150        return EOK;
    134151}
     152/*----------------------------------------------------------------------------*/
     153void hc_gain_control(hc_t *instance)
     154{
     155        assert(instance);
     156        /* Interrupt routing enabled => smm driver is active */
     157        if (instance->registers->control & C_IR) {
     158                usb_log_info("Found SMM driver requesting ownership change.\n");
     159                instance->registers->command_status |= CS_OCR;
     160                while (instance->registers->control & C_IR) {
     161                        async_usleep(1000);
     162                }
     163                usb_log_info("Ownership taken from SMM driver.\n");
     164                return;
     165        }
     166
     167        const unsigned hc_status =
     168            (instance->registers->control >> C_HCFS_SHIFT) & C_HCFS_MASK;
     169        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
     170        if (hc_status != C_HCFS_RESET) {
     171                usb_log_info("Found BIOS driver.\n");
     172                if (hc_status == C_HCFS_OPERATIONAL) {
     173                        usb_log_info("HC operational(BIOS).\n");
     174                        return;
     175                }
     176                /* HC is suspended assert resume for 20ms */
     177                instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
     178                async_usleep(20000);
     179                return;
     180        }
     181
     182        /* HC is in reset (hw startup) => no other driver
     183         * maintain reset for at least the time specified in USB spec (50 ms)*/
     184        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
     193}
     194/*----------------------------------------------------------------------------*/
     195void hc_init_hw(hc_t *instance)
     196{
     197        assert(instance);
     198        const uint32_t fm_interval = instance->registers->fm_interval;
     199        instance->registers->command_status = CS_HCR;
     200        async_usleep(10);
     201        instance->registers->fm_interval = fm_interval;
     202        assert((instance->registers->command_status & CS_HCR) == 0);
     203        /* hc is now in suspend state */
     204        /* TODO: init HCCA block */
     205        /* TODO: init queues */
     206        /* TODO: enable queues */
     207        /* TODO: enable interrupts */
     208        /* TODO: set periodic start to 90% */
     209
     210        instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
     211        usb_log_info("OHCI HC up and running.\n");
     212}
    135213/**
    136214 * @}
Note: See TracChangeset for help on using the changeset viewer.