Changeset 4c7c251 in mainline


Ignore:
Timestamp:
2011-03-01T23:08:25Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
37b1651d
Parents:
ac8285d (diff), 0e2fdcf (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:

New PCI device interface, USB legacy disabled during device initialization

Location:
uspace
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/pciintel/pci.c

    rac8285d r4c7c251  
    5959#include <ddi.h>
    6060#include <libarch/ddi.h>
     61#include <pci_dev_iface.h>
    6162
    6263#include "pci.h"
     
    121122}
    122123
     124static int pci_config_space_write_16(ddf_fun_t *fun, uint32_t address, uint16_t data)
     125{
     126        if (address > 254)
     127                return EINVAL;
     128        pci_conf_write_16(PCI_FUN(fun), address, data);
     129        return EOK;
     130}
     131
     132
    123133static hw_res_ops_t pciintel_hw_res_ops = {
    124134        &pciintel_get_resources,
     
    126136};
    127137
    128 static ddf_dev_ops_t pci_fun_ops;
     138static pci_dev_iface_t pci_dev_ops = {
     139        .config_space_read_8 = NULL,
     140        .config_space_read_16 = NULL,
     141        .config_space_read_32 = NULL,
     142        .config_space_write_8 = NULL,
     143        .config_space_write_16 = &pci_config_space_write_16,
     144        .config_space_write_32 = NULL
     145};
     146
     147static ddf_dev_ops_t pci_fun_ops = {
     148        .interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops,
     149        .interfaces[PCI_DEV_IFACE] = &pci_dev_ops
     150};
    129151
    130152static int pci_add_device(ddf_dev_t *);
     
    593615{
    594616        pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
     617        pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops;
    595618}
    596619
  • uspace/drv/uhci-hcd/main.c

    rac8285d r4c7c251  
    3434#include <ddf/driver.h>
    3535#include <ddf/interrupt.h>
     36#include <device/hw_res.h>
     37#include <errno.h>
     38#include <str_error.h>
     39
    3640#include <usb_iface.h>
    3741#include <usb/ddfiface.h>
    38 #include <device/hw_res.h>
    39 
    40 #include <errno.h>
    41 
    4242#include <usb/debug.h>
    4343
     
    5050
    5151static int uhci_add_device(ddf_dev_t *device);
    52 
    5352/*----------------------------------------------------------------------------*/
    5453static driver_ops_t uhci_driver_ops = {
     
    7069}
    7170/*----------------------------------------------------------------------------*/
    72 #define CHECK_RET_RETURN(ret, message...) \
    73 if (ret != EOK) { \
    74         usb_log_error(message); \
    75         return ret; \
    76 }
    77 
    7871static int uhci_add_device(ddf_dev_t *device)
    7972{
    8073        assert(device);
     74        uhci_t *hcd = NULL;
     75#define CHECK_RET_FREE_HC_RETURN(ret, message...) \
     76if (ret != EOK) { \
     77        usb_log_error(message); \
     78        if (hcd != NULL) \
     79                free(hcd); \
     80        return ret; \
     81}
    8182
    8283        usb_log_info("uhci_add_device() called\n");
     
    8889        int ret =
    8990            pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
    90 
    91         CHECK_RET_RETURN(ret,
     91        CHECK_RET_FREE_HC_RETURN(ret,
    9292            "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
    9393        usb_log_info("I/O regs at 0x%X (size %zu), IRQ %d.\n",
    9494            io_reg_base, io_reg_size, irq);
    9595
    96 //      ret = pci_enable_interrupts(device);
    97 //      CHECK_RET_RETURN(ret, "Failed(%d) to get enable interrupts:\n", ret);
     96        ret = pci_disable_legacy(device);
     97        CHECK_RET_FREE_HC_RETURN(ret,
     98            "Failed(%d) disable legacy USB: %s.\n", ret, str_error(ret));
    9899
    99         uhci_t *uhci_hc = malloc(sizeof(uhci_t));
    100         ret = (uhci_hc != NULL) ? EOK : ENOMEM;
    101         CHECK_RET_RETURN(ret, "Failed to allocate memory for uhci hcd driver.\n");
     100#if 0
     101        ret = pci_enable_interrupts(device);
     102        if (ret != EOK) {
     103                usb_log_warning(
     104                    "Failed(%d) to enable interrupts, fall back to polling.\n",
     105                    ret);
     106        }
     107#endif
    102108
    103         ret = uhci_init(uhci_hc, device, (void*)io_reg_base, io_reg_size);
    104         if (ret != EOK) {
    105                 usb_log_error("Failed to init uhci-hcd.\n");
    106                 free(uhci_hc);
    107                 return ret;
    108         }
     109        hcd = malloc(sizeof(uhci_t));
     110        ret = (hcd != NULL) ? EOK : ENOMEM;
     111        CHECK_RET_FREE_HC_RETURN(ret,
     112            "Failed(%d) to allocate memory for uhci hcd.\n", ret);
     113
     114        ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size);
     115        CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n",
     116            ret);
     117#undef CHECK_RET_FREE_HC_RETURN
    109118
    110119        /*
    111          * We might free uhci_hc, but that does not matter since no one
     120         * We might free hcd, but that does not matter since no one
    112121         * else would access driver_data anyway.
    113122         */
    114         device->driver_data = uhci_hc;
     123        device->driver_data = hcd;
     124
     125        ddf_fun_t *rh = NULL;
     126#define CHECK_RET_FINI_FREE_RETURN(ret, message...) \
     127if (ret != EOK) { \
     128        usb_log_error(message); \
     129        if (hcd != NULL) {\
     130                uhci_fini(hcd); \
     131                free(hcd); \
     132        } \
     133        if (rh != NULL) \
     134                free(rh); \
     135        return ret; \
     136}
     137
     138        /* It does no harm if we register this on polling */
    115139        ret = register_interrupt_handler(device, irq, irq_handler,
    116             &uhci_hc->interrupt_code);
    117         if (ret != EOK) {
    118                 usb_log_error("Failed to register interrupt handler.\n");
    119                 uhci_fini(uhci_hc);
    120                 free(uhci_hc);
    121                 return ret;
    122         }
     140            &hcd->interrupt_code);
     141        CHECK_RET_FINI_FREE_RETURN(ret,
     142            "Failed(%d) to register interrupt handler.\n", ret);
    123143
    124         ddf_fun_t *rh;
    125144        ret = setup_root_hub(&rh, device);
    126         if (ret != EOK) {
    127                 usb_log_error("Failed to setup uhci root hub.\n");
    128                 uhci_fini(uhci_hc);
    129                 free(uhci_hc);
    130                 return ret;
    131         }
    132         rh->driver_data = uhci_hc->ddf_instance;
     145        CHECK_RET_FINI_FREE_RETURN(ret,
     146            "Failed(%d) to setup UHCI root hub.\n", ret);
     147        rh->driver_data = hcd->ddf_instance;
    133148
    134149        ret = ddf_fun_bind(rh);
    135         if (ret != EOK) {
    136                 usb_log_error("Failed to register root hub.\n");
    137                 uhci_fini(uhci_hc);
    138                 free(uhci_hc);
    139                 free(rh);
    140                 return ret;
    141         }
     150        CHECK_RET_FINI_FREE_RETURN(ret,
     151            "Failed(%d) to register UHCI root hub.\n", ret);
    142152
    143153        return EOK;
     154#undef CHECK_RET_FINI_FREE_RETURN
    144155}
    145156/*----------------------------------------------------------------------------*/
  • uspace/drv/uhci-hcd/pci.c

    rac8285d r4c7c251  
    4040
    4141#include <usb/debug.h>
     42#include <pci_dev_iface.h>
    4243
    4344#include "pci.h"
     
    128129        return enabled ? EOK : EIO;
    129130}
     131/*----------------------------------------------------------------------------*/
     132int pci_disable_legacy(ddf_dev_t *device)
     133{
     134        assert(device);
     135        int parent_phone = devman_parent_device_connect(device->handle,
     136                IPC_FLAG_BLOCKING);
     137        if (parent_phone < 0) {
     138                return parent_phone;
     139        }
     140
     141        /* See UHCI design guide for these values,
     142         * write all WC bits in USB legacy register */
     143        sysarg_t address = 0xc0;
     144        sysarg_t value = 0x8f00;
     145
     146  int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     147            IPC_M_CONFIG_SPACE_WRITE_16, address, value);
     148        async_hangup(parent_phone);
     149
     150  return rc;
     151}
     152/*----------------------------------------------------------------------------*/
    130153/**
    131154 * @}
  • uspace/drv/uhci-hcd/pci.h

    rac8285d r4c7c251  
    4040int pci_get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
    4141int pci_enable_interrupts(ddf_dev_t *);
     42int pci_disable_legacy(ddf_dev_t *);
    4243
    4344#endif
  • uspace/drv/uhci-hcd/uhci.c

    rac8285d r4c7c251  
    9090        .interfaces[USBHC_DEV_IFACE] = &uhci_iface,
    9191};
    92 
     92/*----------------------------------------------------------------------------*/
    9393static int uhci_init_transfer_lists(uhci_t *instance);
    9494static int uhci_init_mem_structures(uhci_t *instance);
     
    115115        } else (void) 0
    116116
    117         /*
    118          * Create UHCI function.
    119          */
     117        /* Create UHCI function. */
    120118        instance->ddf_instance = ddf_fun_create(dev, fun_exposed, "uhci");
    121119        ret = (instance->ddf_instance == NULL) ? ENOMEM : EOK;
    122         CHECK_RET_DEST_FUN_RETURN(ret, "Failed to create UHCI device function.\n");
     120        CHECK_RET_DEST_FUN_RETURN(ret,
     121            "Failed to create UHCI device function.\n");
    123122
    124123        instance->ddf_instance->ops = &uhci_ops;
     
    126125
    127126        ret = ddf_fun_bind(instance->ddf_instance);
    128         CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to bind UHCI device function: %s.\n",
     127        CHECK_RET_DEST_FUN_RETURN(ret,
     128            "Failed(%d) to bind UHCI device function: %s.\n",
    129129            ret, str_error(ret));
    130130
     
    132132        regs_t *io;
    133133        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",
     134        CHECK_RET_DEST_FUN_RETURN(ret,
     135            "Failed(%d) to gain access to registers at %p: %s.\n",
    135136            ret, str_error(ret), io);
    136137        instance->registers = io;
    137         usb_log_debug("Device registers at %p(%u) accessible.\n", io, reg_size);
     138        usb_log_debug("Device registers at %p(%u) accessible.\n",
     139            io, reg_size);
    138140
    139141        ret = uhci_init_mem_structures(instance);
    140         CHECK_RET_DEST_FUN_RETURN(ret, "Failed to initialize UHCI memory structures.\n");
     142        CHECK_RET_DEST_FUN_RETURN(ret,
     143            "Failed to initialize UHCI memory structures.\n");
    141144
    142145        uhci_init_hw(instance);
    143 
    144         instance->cleaner = fibril_create(uhci_interrupt_emulator, instance);
     146        instance->cleaner =
     147            fibril_create(uhci_interrupt_emulator, instance);
    145148        fibril_add_ready(instance->cleaner);
    146149
     
    155158void uhci_init_hw(uhci_t *instance)
    156159{
     160        assert(instance);
     161
    157162        /* reset everything, who knows what touched it before us */
    158163        pio_write_16(&instance->registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
     
    171176        /* enable all interrupts, but resume interrupt */
    172177        pio_write_16(&instance->registers->usbintr,
    173                   UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
     178            UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
    174179
    175180        /* Start the hc with large(64B) packet FSBR */
     
    200205                interrupt_commands[1].addr = (void*)&instance->registers->usbsts;
    201206                instance->interrupt_code.cmdcount =
    202                                 sizeof(uhci_cmds) / sizeof(irq_cmd_t);
     207                    sizeof(uhci_cmds) / sizeof(irq_cmd_t);
    203208        }
    204209
     
    249254        ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
    250255        CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
     256
    251257        ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL");
    252258        CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
     259
    253260        ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW");
    254261        CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
     262
    255263        ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
    256264        CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list.");
     
    292300            low_speed, batch->transfer_type, batch->max_packet_size)) {
    293301                usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n",
    294                           low_speed ? "LOW" : "FULL" , batch->transfer_type,
     302                    low_speed ? "LOW" : "FULL" , batch->transfer_type,
    295303                    batch->max_packet_size);
    296304                return ENOTSUP;
     
    309317{
    310318        assert(instance);
    311 //      if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0)
    312 //              return;
    313 //      usb_log_debug2("UHCI interrupt: %X.\n", status);
    314319        transfer_list_remove_finished(&instance->transfers_interrupt);
    315320        transfer_list_remove_finished(&instance->transfers_control_slow);
     
    340345        uhci_t *instance = (uhci_t*)arg;
    341346        assert(instance);
     347
     348#define QH(queue) \
     349        instance->transfers_##queue.queue_head
     350
    342351        while (1) {
    343352                const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
    344353                const uint16_t sts = pio_read_16(&instance->registers->usbsts);
    345                 const uint16_t intr = pio_read_16(&instance->registers->usbintr);
     354                const uint16_t intr =
     355                    pio_read_16(&instance->registers->usbintr);
     356
    346357                if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
    347358                        usb_log_debug2("Command: %X Status: %X Intr: %x\n",
     
    353364                if (frame_list != addr_to_phys(instance->frame_list)) {
    354365                        usb_log_debug("Framelist address: %p vs. %p.\n",
    355                                 frame_list, addr_to_phys(instance->frame_list));
    356                 }
     366                            frame_list, addr_to_phys(instance->frame_list));
     367                }
     368
    357369                int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
    358370                usb_log_debug2("Framelist item: %d \n", frnum );
    359371
    360                 queue_head_t* qh = instance->transfers_interrupt.queue_head;
    361 
    362                 if ((instance->frame_list[frnum] & (~0xf)) != (uintptr_t)addr_to_phys(qh)) {
     372                uintptr_t expected_pa = instance->frame_list[frnum] & (~0xf);
     373                uintptr_t real_pa = addr_to_phys(QH(interrupt));
     374                if (expected_pa != real_pa) {
    363375                        usb_log_debug("Interrupt QH: %p vs. %p.\n",
    364                                 instance->frame_list[frnum] & (~0xf), addr_to_phys(qh));
    365                 }
    366 
    367                 if ((qh->next_queue & (~0xf))
    368                   != (uintptr_t)addr_to_phys(instance->transfers_control_slow.queue_head)) {
    369                         usb_log_debug("Control Slow QH: %p vs. %p.\n", qh->next_queue & (~0xf),
    370                                 addr_to_phys(instance->transfers_control_slow.queue_head));
    371                 }
    372                 qh = instance->transfers_control_slow.queue_head;
    373 
    374                 if ((qh->next_queue & (~0xf))
    375                   != (uintptr_t)addr_to_phys(instance->transfers_control_full.queue_head)) {
    376                         usb_log_debug("Control Full QH: %p vs. %p.\n", qh->next_queue & (~0xf),
    377                                 addr_to_phys(instance->transfers_control_full.queue_head));\
    378                 }
    379                 qh = instance->transfers_control_full.queue_head;
    380 
    381                 if ((qh->next_queue & (~0xf))
    382                   != (uintptr_t)addr_to_phys(instance->transfers_bulk_full.queue_head)) {
    383                         usb_log_debug("Bulk QH: %p vs. %p.\n", qh->next_queue & (~0xf),
    384                                 addr_to_phys(instance->transfers_bulk_full.queue_head));
    385                 }
    386 /*
    387         uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
    388         cmd |= UHCI_CMD_RUN_STOP;
    389         pio_write_16(&instance->registers->usbcmd, cmd);
    390 */
     376                            expected_pa, real_pa);
     377                }
     378
     379                expected_pa = QH(interrupt)->next_queue & (~0xf);
     380                real_pa = addr_to_phys(QH(control_slow));
     381                if (expected_pa != real_pa) {
     382                        usb_log_debug("Control Slow QH: %p vs. %p.\n",
     383                            expected_pa, real_pa);
     384                }
     385
     386                expected_pa = QH(control_slow)->next_queue & (~0xf);
     387                real_pa = addr_to_phys(QH(control_full));
     388                if (expected_pa != real_pa) {
     389                        usb_log_debug("Control Full QH: %p vs. %p.\n",
     390                            expected_pa, real_pa);
     391                }
     392
     393                expected_pa = QH(control_full)->next_queue & (~0xf);
     394                real_pa = addr_to_phys(QH(bulk_full));
     395                if (expected_pa != real_pa ) {
     396                        usb_log_debug("Bulk QH: %p vs. %p.\n",
     397                            expected_pa, real_pa);
     398                }
    391399                async_usleep(UHCI_DEBUGER_TIMEOUT);
    392400        }
    393401        return 0;
     402#undef QH
    394403}
    395404/*----------------------------------------------------------------------------*/
    396405bool allowed_usb_packet(
    397         bool low_speed, usb_transfer_type_t transfer, size_t size)
     406    bool low_speed, usb_transfer_type_t transfer, size_t size)
    398407{
    399408        /* see USB specification chapter 5.5-5.8 for magic numbers used here */
    400         switch(transfer) {
    401                 case USB_TRANSFER_ISOCHRONOUS:
    402                         return (!low_speed && size < 1024);
    403                 case USB_TRANSFER_INTERRUPT:
    404                         return size <= (low_speed ? 8 : 64);
    405                 case USB_TRANSFER_CONTROL: /* device specifies its own max size */
    406                         return (size <= (low_speed ? 8 : 64));
    407                 case USB_TRANSFER_BULK: /* device specifies its own max size */
    408                         return (!low_speed && size <= 64);
     409        switch(transfer)
     410        {
     411        case USB_TRANSFER_ISOCHRONOUS:
     412                return (!low_speed && size < 1024);
     413        case USB_TRANSFER_INTERRUPT:
     414                return size <= (low_speed ? 8 : 64);
     415        case USB_TRANSFER_CONTROL: /* device specifies its own max size */
     416                return (size <= (low_speed ? 8 : 64));
     417        case USB_TRANSFER_BULK: /* device specifies its own max size */
     418                return (!low_speed && size <= 64);
    409419        }
    410420        return false;
  • uspace/lib/c/include/ipc/dev_iface.h

    rac8285d r4c7c251  
    3838        CHAR_DEV_IFACE,
    3939
     40        /** Interface provided by any PCI device. */
     41        PCI_DEV_IFACE,
     42
    4043        /** Interface provided by any USB device. */
    4144        USB_DEV_IFACE,
  • uspace/lib/drv/Makefile

    rac8285d r4c7c251  
    3838        generic/remote_hw_res.c \
    3939        generic/remote_usb.c \
     40        generic/remote_pci.c \
    4041        generic/remote_usbhc.c
    4142
  • uspace/lib/drv/generic/dev_iface.c

    rac8285d r4c7c251  
    4343#include "remote_usb.h"
    4444#include "remote_usbhc.h"
     45#include "remote_pci.h"
    4546
    4647static iface_dipatch_table_t remote_ifaces = {
     
    4849                &remote_hw_res_iface,
    4950                &remote_char_dev_iface,
     51                &remote_pci_iface,
    5052                &remote_usb_iface,
    5153                &remote_usbhc_iface
Note: See TracChangeset for help on using the changeset viewer.