Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/uhci-hcd/uhci.c

    r4abc304 rb9d910f  
    3333 */
    3434#include <errno.h>
    35 #include <str_error.h>
    3635#include <adt/list.h>
    37 #include <libarch/ddi.h>
    3836
    3937#include <usb/debug.h>
    4038#include <usb/usb.h>
    41 #include <usb/ddfiface.h>
    42 #include <usb_iface.h>
    4339
    4440#include "uhci.h"
    45 #include "iface.h"
    46 
    4741static irq_cmd_t uhci_cmds[] = {
    4842        {
    4943                .cmd = CMD_PIO_READ_16,
    50                 .addr = NULL, /* patched for every instance */
     44                .addr = (void*)0xc022,
    5145                .dstarg = 1
    5246        },
    5347        {
    5448                .cmd = CMD_PIO_WRITE_16,
    55                 .addr = NULL, /* pathed for every instance */
     49                .addr = (void*)0xc022,
    5650                .value = 0x1f
    5751        },
     
    6155};
    6256
    63 static int usb_iface_get_address(ddf_fun_t *fun, devman_handle_t handle,
    64     usb_address_t *address)
    65 {
    66         assert(fun);
    67         uhci_t *hc = fun_to_uhci(fun);
    68         assert(hc);
    69 
    70         usb_address_t addr = device_keeper_find(&hc->device_manager,
    71             handle);
    72         if (addr < 0) {
    73                 return addr;
    74         }
    75 
    76         if (address != NULL) {
    77                 *address = addr;
    78         }
    79 
    80         return EOK;
    81 }
    82 /*----------------------------------------------------------------------------*/
    83 static usb_iface_t hc_usb_iface = {
    84         .get_hc_handle = usb_iface_get_hc_handle_hc_impl,
    85         .get_address = usb_iface_get_address
    86 };
    87 /*----------------------------------------------------------------------------*/
    88 static ddf_dev_ops_t uhci_ops = {
    89         .interfaces[USB_DEV_IFACE] = &hc_usb_iface,
    90         .interfaces[USBHC_DEV_IFACE] = &uhci_iface,
    91 };
    92 
    9357static int uhci_init_transfer_lists(uhci_t *instance);
    9458static int uhci_init_mem_structures(uhci_t *instance);
     
    10165        bool low_speed, usb_transfer_type_t, size_t size);
    10266
    103 
    104 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size)
    105 {
    106         assert(reg_size >= sizeof(regs_t));
    107         int ret;
    108 
    109 #define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
     67#define CHECK_RET_RETURN(ret, message...) \
    11068        if (ret != EOK) { \
    11169                usb_log_error(message); \
    112                 if (instance->ddf_instance) \
    113                         ddf_fun_destroy(instance->ddf_instance); \
    11470                return ret; \
    11571        } else (void) 0
    11672
    117         /*
    118          * Create UHCI function.
    119          */
    120         instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci");
    121         ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK;
    122         CHECK_RET_DEST_FUN_RETURN(ret, "Failed to create UHCI device function.\n");
    123 
    124         instance->ddf_instance->ops = &uhci_ops;
    125         instance->ddf_instance->driver_data = instance;
    126 
    127         ret = ddf_fun_bind(instance->ddf_instance);
    128         CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to bind UHCI device function: %s.\n",
    129             ret, str_error(ret));
     73int uhci_init(uhci_t *instance, void *regs, size_t reg_size)
     74{
     75        assert(reg_size >= sizeof(regs_t));
    13076
    13177        /* allow access to hc control registers */
    13278        regs_t *io;
    133         ret = pio_enable(regs, reg_size, (void**)&io);
    134         CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to gain access to registers at %p: %s.\n",
    135             ret, str_error(ret), io);
     79        int ret = pio_enable(regs, reg_size, (void**)&io);
     80        CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p.\n", io);
    13681        instance->registers = io;
    137         usb_log_debug("Device registers at %p(%u) accessible.\n", io, reg_size);
     82        usb_log_debug("Device registers accessible.\n");
    13883
    13984        ret = uhci_init_mem_structures(instance);
    140         CHECK_RET_DEST_FUN_RETURN(ret, "Failed to initialize UHCI memory structures.\n");
     85        CHECK_RET_RETURN(ret, "Failed to initialize memory structures.\n");
    14186
    14287        uhci_init_hw(instance);
    14388
    14489        instance->cleaner = fibril_create(uhci_interrupt_emulator, instance);
    145         fibril_add_ready(instance->cleaner);
     90//      fibril_add_ready(instance->cleaner);
    14691
    14792        instance->debug_checker = fibril_create(uhci_debug_checker, instance);
    14893        fibril_add_ready(instance->debug_checker);
    14994
    150         usb_log_info("Started UHCI driver.\n");
    151         return EOK;
    152 #undef CHECK_RET_DEST_FUN_RETURN
     95        return EOK;
    15396}
    15497/*----------------------------------------------------------------------------*/
    15598void uhci_init_hw(uhci_t *instance)
    15699{
    157         /* reset everything, who knows what touched it before us */
    158         pio_write_16(&instance->registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
    159         async_usleep(10000); /* 10ms according to USB spec */
    160         pio_write_16(&instance->registers->usbcmd, 0);
    161 
    162         /* reset hc, all states and counters */
    163         pio_write_16(&instance->registers->usbcmd, UHCI_CMD_HCRESET);
    164         while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0)
    165                 { async_usleep(10); }
    166100
    167101        /* set framelist pointer */
     
    176110        pio_write_16(&instance->registers->usbcmd,
    177111            UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
     112        usb_log_debug("Started UHCI HC.\n");
    178113}
    179114/*----------------------------------------------------------------------------*/
     
    181116{
    182117        assert(instance);
    183 #define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \
    184         if (ret != EOK) { \
    185                 usb_log_error(message); \
    186                 if (instance->interrupt_code.cmds != NULL) \
    187                         free(instance->interrupt_code.cmds); \
    188                 return ret; \
    189         } else (void) 0
    190118
    191119        /* init interrupt code */
    192         instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds));
    193         int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK;
    194         CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to allocate interrupt cmds space.\n");
    195 
    196         {
    197                 irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds;
    198                 memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
    199                 interrupt_commands[0].addr = (void*)&instance->registers->usbsts;
    200                 interrupt_commands[1].addr = (void*)&instance->registers->usbsts;
    201                 instance->interrupt_code.cmdcount =
    202                                 sizeof(uhci_cmds) / sizeof(irq_cmd_t);
    203         }
     120        irq_cmd_t *interrupt_commands = malloc(sizeof(uhci_cmds));
     121        if (interrupt_commands == NULL) {
     122                return ENOMEM;
     123        }
     124        memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
     125        interrupt_commands[0].addr = (void*)&instance->registers->usbsts;
     126        interrupt_commands[1].addr = (void*)&instance->registers->usbsts;
     127        instance->interrupt_code.cmds = interrupt_commands;
     128        instance->interrupt_code.cmdcount =
     129            sizeof(uhci_cmds) / sizeof(irq_cmd_t);
    204130
    205131        /* init transfer lists */
    206         ret = uhci_init_transfer_lists(instance);
    207         CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to initialize transfer lists.\n");
     132        int ret = uhci_init_transfer_lists(instance);
     133        CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
    208134        usb_log_debug("Initialized transfer lists.\n");
    209135
     
    211137        instance->frame_list = get_page();
    212138        ret = instance ? EOK : ENOMEM;
    213         CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n");
     139        CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
    214140        usb_log_debug("Initialized frame list.\n");
    215141
     
    218144          instance->transfers_interrupt.queue_head_pa
    219145          | LINK_POINTER_QUEUE_HEAD_FLAG;
    220 
    221146        unsigned i = 0;
    222147        for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
     
    225150
    226151        /* init address keeper(libusb) */
    227         device_keeper_init(&instance->device_manager);
    228         usb_log_debug("Initialized device manager.\n");
    229 
    230         return EOK;
    231 #undef CHECK_RET_DEST_CMDS_RETURN
     152        usb_address_keeping_init(&instance->address_manager, USB11_ADDRESS_MAX);
     153        usb_log_debug("Initialized address manager.\n");
     154
     155        return EOK;
    232156}
    233157/*----------------------------------------------------------------------------*/
     
    235159{
    236160        assert(instance);
    237 #define CHECK_RET_CLEAR_RETURN(ret, message...) \
    238         if (ret != EOK) { \
    239                 usb_log_error(message); \
    240                 transfer_list_fini(&instance->transfers_bulk_full); \
    241                 transfer_list_fini(&instance->transfers_control_full); \
    242                 transfer_list_fini(&instance->transfers_control_slow); \
    243                 transfer_list_fini(&instance->transfers_interrupt); \
    244                 return ret; \
    245         } else (void) 0
    246161
    247162        /* initialize TODO: check errors */
    248163        int ret;
    249164        ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
    250         CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
     165        assert(ret == EOK);
    251166        ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL");
    252         CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
     167        assert(ret == EOK);
    253168        ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW");
    254         CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
     169        assert(ret == EOK);
    255170        ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
    256         CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list.");
     171        assert(ret == EOK);
    257172
    258173        transfer_list_set_next(&instance->transfers_control_full,
     
    281196
    282197        return EOK;
    283 #undef CHECK_RET_CLEAR_RETURN
    284198}
    285199/*----------------------------------------------------------------------------*/
     
    288202        assert(instance);
    289203        assert(batch);
    290         const int low_speed = (batch->speed == USB_SPEED_LOW);
     204        const int low_speed = (batch->speed == LOW_SPEED);
    291205        if (!allowed_usb_packet(
    292206            low_speed, batch->transfer_type, batch->max_packet_size)) {
     
    309223{
    310224        assert(instance);
    311 //      if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0)
    312 //              return;
    313 //      usb_log_debug2("UHCI interrupt: %X.\n", status);
    314         transfer_list_remove_finished(&instance->transfers_interrupt);
    315         transfer_list_remove_finished(&instance->transfers_control_slow);
    316         transfer_list_remove_finished(&instance->transfers_control_full);
    317         transfer_list_remove_finished(&instance->transfers_bulk_full);
     225        if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0)
     226                return;
     227        usb_log_debug("UHCI interrupt: %X.\n", status);
     228        transfer_list_check(&instance->transfers_interrupt);
     229        transfer_list_check(&instance->transfers_control_slow);
     230        transfer_list_check(&instance->transfers_control_full);
     231        transfer_list_check(&instance->transfers_bulk_full);
    318232}
    319233/*----------------------------------------------------------------------------*/
     
    324238        assert(instance);
    325239
    326         while (1) {
     240        while(1) {
    327241                uint16_t status = pio_read_16(&instance->registers->usbsts);
    328                 if (status != 0)
    329                         usb_log_debug2("UHCI status: %x.\n", status);
    330                 status |= 1;
    331242                uhci_interrupt(instance, status);
    332                 pio_write_16(&instance->registers->usbsts, 0x1f);
    333                 async_usleep(UHCI_CLEANER_TIMEOUT * 5);
     243                async_usleep(UHCI_CLEANER_TIMEOUT);
    334244        }
    335245        return EOK;
     
    344254                const uint16_t sts = pio_read_16(&instance->registers->usbsts);
    345255                const uint16_t intr = pio_read_16(&instance->registers->usbintr);
    346                 if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
    347                         usb_log_debug2("Command: %X Status: %X Intr: %x\n",
    348                             cmd, sts, intr);
    349                 }
    350 
    351                 uintptr_t frame_list =
    352                     pio_read_32(&instance->registers->flbaseadd) & ~0xfff;
     256                usb_log_debug("Command: %X Status: %X Interrupts: %x\n",
     257                    cmd, sts, intr);
     258
     259                uintptr_t frame_list = pio_read_32(&instance->registers->flbaseadd);
    353260                if (frame_list != addr_to_phys(instance->frame_list)) {
    354261                        usb_log_debug("Framelist address: %p vs. %p.\n",
Note: See TracChangeset for help on using the changeset viewer.