Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/ehci-hcd/pci.c

    rc060090 r8855939  
    5555#define CMD_OFFSET 0x0
    5656#define STS_OFFSET 0x4
    57 #define INT_OFFSET 0x8
    5857#define CFG_OFFSET 0x40
    5958
    6059#define USBCMD_RUN 1
    61 #define USBSTS_HALTED (1 << 12)
    6260
    6361#define USBLEGSUP_OFFSET 0
     
    6664#define USBLEGCTLSTS_OFFSET 4
    6765
    68 #define DEFAULT_WAIT 1000
     66#define DEFAULT_WAIT 10000
    6967#define WAIT_STEP 10
    70 
    71 #define PCI_READ(size) \
    72 do { \
    73         const int parent_phone = \
    74             devman_parent_device_connect(dev->handle, IPC_FLAG_BLOCKING);\
    75         if (parent_phone < 0) {\
    76                 return parent_phone; \
    77         } \
    78         sysarg_t add = (sysarg_t)address; \
    79         sysarg_t val; \
    80         const int ret = \
    81             async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), \
    82                 IPC_M_CONFIG_SPACE_READ_##size, add, &val); \
    83         assert(value); \
    84         *value = val; \
    85         async_hangup(parent_phone); \
    86         return ret; \
    87 } while(0)
    88 
    89 static int pci_read32(const ddf_dev_t *dev, int address, uint32_t *value)
    90 {
    91         PCI_READ(32);
    92 }
    93 static int pci_read16(const ddf_dev_t *dev, int address, uint16_t *value)
    94 {
    95         PCI_READ(16);
    96 }
    97 static int pci_read8(const ddf_dev_t *dev, int address, uint8_t *value)
    98 {
    99         PCI_READ(8);
    100 }
    101 #define PCI_WRITE(size) \
    102 do { \
    103         const int parent_phone = \
    104             devman_parent_device_connect(dev->handle, IPC_FLAG_BLOCKING);\
    105         if (parent_phone < 0) {\
    106                 return parent_phone; \
    107         } \
    108         sysarg_t add = (sysarg_t)address; \
    109         sysarg_t val = value; \
    110         const int ret = \
    111             async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), \
    112                 IPC_M_CONFIG_SPACE_WRITE_##size, add, val); \
    113         async_hangup(parent_phone); \
    114         return ret; \
    115 } while(0)
    116 
    117 static int pci_write32(const ddf_dev_t *dev, int address, uint32_t value)
    118 {
    119         PCI_WRITE(32);
    120 }
    121 static int pci_write16(const ddf_dev_t *dev, int address, uint16_t value)
    122 {
    123         PCI_WRITE(16);
    124 }
    125 static int pci_write8(const ddf_dev_t *dev, int address, uint8_t value)
    126 {
    127         PCI_WRITE(8);
    128 }
    12968
    13069/** Get address of registers and IRQ for given device.
     
    13675 * @return Error code.
    13776 */
    138 int pci_get_my_registers(const ddf_dev_t *dev,
     77int pci_get_my_registers(ddf_dev_t *dev,
    13978    uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
    14079{
    14180        assert(dev != NULL);
    14281
    143         const int parent_phone =
    144             devman_parent_device_connect(dev->handle, IPC_FLAG_BLOCKING);
     82        int parent_phone = devman_parent_device_connect(dev->handle,
     83            IPC_FLAG_BLOCKING);
    14584        if (parent_phone < 0) {
    14685                return parent_phone;
     
    206145 * @return Error code.
    207146 */
    208 int pci_enable_interrupts(const ddf_dev_t *device)
     147int pci_enable_interrupts(ddf_dev_t *device)
    209148{
    210         const int parent_phone =
     149        int parent_phone =
    211150            devman_parent_device_connect(device->handle, IPC_FLAG_BLOCKING);
    212151        if (parent_phone < 0) {
    213152                return parent_phone;
    214153        }
    215         const bool enabled = hw_res_enable_interrupt(parent_phone);
     154        bool enabled = hw_res_enable_interrupt(parent_phone);
    216155        async_hangup(parent_phone);
    217156        return enabled ? EOK : EIO;
     
    223162 * @return Error code.
    224163 */
    225 int pci_disable_legacy(
    226     const ddf_dev_t *device, uintptr_t reg_base, size_t reg_size, int irq)
     164int pci_disable_legacy(ddf_dev_t *device)
    227165{
    228166        assert(device);
    229         (void) pci_read16;
    230         (void) pci_read8;
    231         (void) pci_write16;
    232 
    233 #define CHECK_RET_RETURN(ret, message...) \
     167        int parent_phone = devman_parent_device_connect(device->handle,
     168                IPC_FLAG_BLOCKING);
     169        if (parent_phone < 0) {
     170                return parent_phone;
     171        }
     172
     173#define CHECK_RET_HANGUP_RETURN(ret, message...) \
    234174        if (ret != EOK) { \
    235175                usb_log_error(message); \
     176                async_hangup(parent_phone); \
    236177                return ret; \
    237178        } else (void)0
    238179
    239         /* Map EHCI registers */
    240         void *regs = NULL;
    241         int ret = pio_enable((void*)reg_base, reg_size, &regs);
    242         CHECK_RET_RETURN(ret, "Failed(%d) to map registers %p.\n",
    243             ret, (void *) reg_base);
     180
     181        /* read register space BASE BAR */
     182        sysarg_t address = 0x10;
     183        sysarg_t value;
     184
     185        int ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     186            IPC_M_CONFIG_SPACE_READ_32, address, &value);
     187        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read PCI config space.\n",
     188            ret);
     189        usb_log_info("Register space BAR at %p:%" PRIxn ".\n",
     190            (void *) address, value);
     191
     192        /* clear lower byte, it's not part of the BASE address */
     193        uintptr_t registers = (value & 0xffffff00);
     194        usb_log_info("Memory registers BASE address:%p.\n", (void *) registers);
     195
     196        /* if nothing setup the hc, we don't need to turn it off */
     197        if (registers == 0)
     198                return ENOTSUP;
     199
     200        /* map EHCI registers */
     201        void *regs = as_get_mappable_page(4096);
     202        ret = physmem_map((void*)(registers & PAGE_SIZE_MASK), regs, 1,
     203            AS_AREA_READ | AS_AREA_WRITE);
     204        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to map registers %p:%p.\n",
     205            ret, regs, (void *) registers);
     206
     207        /* calculate value of BASE */
     208        registers = (registers & 0xf00) | (uintptr_t)regs;
    244209
    245210        const uint32_t hcc_params =
    246             *(uint32_t*)(regs + HCC_PARAMS_OFFSET);
     211            *(uint32_t*)(registers + HCC_PARAMS_OFFSET);
    247212        usb_log_debug("Value of hcc params register: %x.\n", hcc_params);
    248213
    249214        /* Read value of EHCI Extended Capabilities Pointer
    250          * position of EEC registers (points to PCI config space) */
    251         const uint32_t eecp =
     215         * (points to PCI config space) */
     216        uint32_t eecp =
    252217            (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
    253218        usb_log_debug("Value of EECP: %x.\n", eecp);
    254219
     220        /* Read the second EEC. i.e. Legacy Support and Control register */
     221        /* TODO: Check capability type here */
     222        ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     223            IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGCTLSTS_OFFSET, &value);
     224        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGCTLSTS.\n", ret);
     225        usb_log_debug("USBLEGCTLSTS: %" PRIxn ".\n", value);
     226
    255227        /* Read the first EEC. i.e. Legacy Support register */
    256         uint32_t usblegsup;
    257         ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
    258         CHECK_RET_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
    259         usb_log_debug("USBLEGSUP: %" PRIxn ".\n", usblegsup);
     228        /* TODO: Check capability type here */
     229        ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     230            IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
     231        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
     232        usb_log_debug2("USBLEGSUP: %" PRIxn ".\n", value);
    260233
    261234        /* Request control from firmware/BIOS, by writing 1 to highest byte.
    262235         * (OS Control semaphore)*/
    263         usb_log_debug("Requesting OS control.\n");
    264         ret = pci_write8(device, eecp + USBLEGSUP_OFFSET + 3, 1);
    265         CHECK_RET_RETURN(ret, "Failed(%d) to request OS EHCI control.\n", ret);
     236        ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     237           IPC_M_CONFIG_SPACE_WRITE_8, eecp + USBLEGSUP_OFFSET + 3, 1);
     238        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to request OS EHCI control.\n",
     239            ret);
    266240
    267241        size_t wait = 0;
    268242        /* Wait for BIOS to release control. */
    269         ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
    270         while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
     243        while ((wait < DEFAULT_WAIT) && (value & USBLEGSUP_BIOS_CONTROL)) {
    271244                async_usleep(WAIT_STEP);
    272                 ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
     245                ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     246                    IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
    273247                wait += WAIT_STEP;
    274248        }
    275249
    276250
    277         if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) {
     251        if ((value & USBLEGSUP_BIOS_CONTROL) == 0) {
    278252                usb_log_info("BIOS released control after %zu usec.\n", wait);
    279253        } else {
     
    281255                usb_log_warning( "BIOS failed to release control after "
    282256                    "%zu usecs, force it.\n", wait);
    283                 ret = pci_write32(device, eecp + USBLEGSUP_OFFSET,
     257                ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     258                    IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGSUP_OFFSET,
    284259                    USBLEGSUP_OS_CONTROL);
    285                 CHECK_RET_RETURN(ret, "Failed(%d) to force OS control.\n", ret);
    286                 /* Check capability type here, A value of 01h
    287                  * identifies the capability as Legacy Support.
    288                  * This extended capability requires one
    289                  * additional 32-bit register for control/status information,
    290                  * and this register is located at offset EECP+04h
    291                  * */
    292                 if ((usblegsup & 0xff) == 1) {
    293                         /* Read the second EEC
    294                          * Legacy Support and Control register */
    295                         uint32_t usblegctlsts;
    296                         ret = pci_read32(
    297                             device, eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    298                         CHECK_RET_RETURN(ret,
    299                             "Failed(%d) to get USBLEGCTLSTS.\n", ret);
    300                         usb_log_debug("USBLEGCTLSTS: %" PRIxn ".\n",
    301                             usblegctlsts);
    302                         /* Zero SMI enables in legacy control register.
    303                          * It should prevent pre-OS code from interfering. */
    304                         ret = pci_write32(device, eecp + USBLEGCTLSTS_OFFSET,
    305                             0xe0000000); /* three upper bits are WC */
    306                         CHECK_RET_RETURN(ret,
    307                             "Failed(%d) zero USBLEGCTLSTS.\n", ret);
    308                         udelay(10);
    309                         ret = pci_read32(
    310                             device, eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    311                         CHECK_RET_RETURN(ret,
    312                             "Failed(%d) to get USBLEGCTLSTS 2.\n", ret);
    313                         usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIxn ".\n",
    314                             usblegctlsts);
    315                 }
    316         }
    317 
     260                CHECK_RET_HANGUP_RETURN(ret,
     261                    "Failed(%d) to force OS EHCI control.\n", ret);
     262        }
     263
     264        /* Zero SMI enables in legacy control register.
     265         * It would prevent pre-OS code from interfering. */
     266        ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     267           IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGCTLSTS_OFFSET,
     268           0xe0000000);
     269        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) zero USBLEGCTLSTS.\n", ret);
     270
     271        /* Read again Legacy Support and Control register */
     272        ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     273            IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGCTLSTS_OFFSET, &value);
     274        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGCTLSTS.\n", ret);
     275        usb_log_debug2("USBLEGCTLSTS: %" PRIxn ".\n", value);
    318276
    319277        /* Read again Legacy Support register */
    320         ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
    321         CHECK_RET_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
    322         usb_log_debug("USBLEGSUP: %" PRIxn ".\n", usblegsup);
     278        ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
     279            IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
     280        CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
     281        usb_log_debug2("USBLEGSUP: %" PRIxn ".\n", value);
    323282
    324283        /*
     
    327286
    328287        /* Get size of capability registers in memory space. */
    329         const unsigned operation_offset = *(uint8_t*)regs;
     288        uint8_t operation_offset = *(uint8_t*)registers;
    330289        usb_log_debug("USBCMD offset: %d.\n", operation_offset);
    331290
    332291        /* Zero USBCMD register. */
    333292        volatile uint32_t *usbcmd =
    334             (uint32_t*)((uint8_t*)regs + operation_offset + CMD_OFFSET);
     293            (uint32_t*)((uint8_t*)registers + operation_offset + CMD_OFFSET);
    335294        volatile uint32_t *usbsts =
    336             (uint32_t*)((uint8_t*)regs + operation_offset + STS_OFFSET);
    337         volatile uint32_t *usbconf =
    338             (uint32_t*)((uint8_t*)regs + operation_offset + CFG_OFFSET);
    339         volatile uint32_t *usbint =
    340             (uint32_t*)((uint8_t*)regs + operation_offset + INT_OFFSET);
     295            (uint32_t*)((uint8_t*)registers + operation_offset + STS_OFFSET);
     296        volatile uint32_t *usbconfigured =
     297            (uint32_t*)((uint8_t*)registers + operation_offset + CFG_OFFSET);
    341298        usb_log_debug("USBCMD value: %x.\n", *usbcmd);
    342299        if (*usbcmd & USBCMD_RUN) {
    343                 *usbsts = 0x3f; /* ack all interrupts */
    344                 *usbint = 0; /* disable all interrutps */
    345                 *usbconf = 0; /* relase control of RH ports */
    346 
    347300                *usbcmd = 0;
    348                 /* Wait until hc is halted */
    349                 while ((*usbsts & USBSTS_HALTED) == 0);
     301                while (!(*usbsts & (1 << 12))); /*wait until hc is halted */
     302                *usbconfigured = 0;
    350303                usb_log_info("EHCI turned off.\n");
    351304        } else {
    352305                usb_log_info("EHCI was not running.\n");
    353306        }
    354         usb_log_debug("Registers: \n"
    355             "\t USBCMD: %x(0x00080000 = at least 1ms between interrupts)\n"
    356             "\t USBSTS: %x(0x00001000 = HC halted)\n"
    357             "\t USBINT: %x(0x0 = no interrupts).\n"
    358             "\t CONFIG: %x(0x0 = ports controlled by companion hc).\n",
    359             *usbcmd, *usbsts, *usbint, *usbconf);
    360 
     307        usb_log_debug("Registers: %x(0x00080000):%x(0x00001000):%x(0x0).\n",
     308            *usbcmd, *usbsts, *usbconfigured);
     309
     310        async_hangup(parent_phone);
    361311        return ret;
    362 #undef CHECK_RET_RETURN
     312#undef CHECK_RET_HANGUP_RETURN
    363313}
    364314/*----------------------------------------------------------------------------*/
Note: See TracChangeset for help on using the changeset viewer.