Changes in / [3ae26a8:0dd3e49] in mainline


Ignore:
Location:
uspace/drv
Files:
1 added
1 edited

Legend:

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

    r3ae26a8 r0dd3e49  
    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(ddf_dev_t *dev, int address, uint32_t *value)
    90 {
    91         PCI_READ(32);
    92 }
    93 static int pci_read16(ddf_dev_t *dev, int address, uint16_t *value)
    94 {
    95         PCI_READ(16);
    96 }
    97 static int pci_read8(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(ddf_dev_t *dev, int address, uint32_t value)
    118 {
    119         PCI_WRITE(32);
    120 }
    121 static int pci_write16(ddf_dev_t *dev, int address, uint16_t value)
    122 {
    123         PCI_WRITE(16);
    124 }
    125 static int pci_write8(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.
     
    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;
     
    208147int 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;
     
    226165{
    227166        assert(device);
    228         (void) pci_read16;
    229         (void) pci_read8;
    230         (void) pci_write16;
    231 
    232 #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...) \
    233174        if (ret != EOK) { \
    234175                usb_log_error(message); \
     176                async_hangup(parent_phone); \
    235177                return ret; \
    236178        } else (void)0
    237179
    238         uintptr_t reg_base = 0;
    239         size_t reg_size = 0;
    240         int irq = 0;
    241 
    242         int ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
    243         CHECK_RET_RETURN(ret, "Failed(%d) to get EHCI registers.\n", ret);
    244 
    245         usb_log_info("EHCI: Memory registers:%p size: %zu irq:%d.\n",
    246             (void *) reg_base, reg_size, irq);
    247 
     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;
    248199
    249200        /* map EHCI registers */
    250         void *regs = NULL;
    251         ret = pio_enable((void*)reg_base, reg_size, &regs);
    252         CHECK_RET_RETURN(ret, "Failed(%d) to map registers %p.\n",
    253             ret, (void *) reg_base);
     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;
    254209
    255210        const uint32_t hcc_params =
    256             *(uint32_t*)(regs + HCC_PARAMS_OFFSET);
     211            *(uint32_t*)(registers + HCC_PARAMS_OFFSET);
    257212        usb_log_debug("Value of hcc params register: %x.\n", hcc_params);
    258213
    259214        /* Read value of EHCI Extended Capabilities Pointer
    260          * position of EEC registers (points to PCI config space) */
    261         const uint32_t eecp =
     215         * (points to PCI config space) */
     216        uint32_t eecp =
    262217            (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
    263218        usb_log_debug("Value of EECP: %x.\n", eecp);
    264219
     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
    265227        /* Read the first EEC. i.e. Legacy Support register */
    266         uint32_t usblegsup;
    267         ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
    268         CHECK_RET_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
    269         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);
    270233
    271234        /* Request control from firmware/BIOS, by writing 1 to highest byte.
    272235         * (OS Control semaphore)*/
    273         usb_log_debug("Requesting OS control.\n");
    274         ret = pci_write8(device, eecp + USBLEGSUP_OFFSET + 3, 1);
    275         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);
    276240
    277241        size_t wait = 0;
    278242        /* Wait for BIOS to release control. */
    279         ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
    280         while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
     243        while ((wait < DEFAULT_WAIT) && (value & USBLEGSUP_BIOS_CONTROL)) {
    281244                async_usleep(WAIT_STEP);
    282                 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);
    283247                wait += WAIT_STEP;
    284248        }
    285249
    286250
    287         if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) {
     251        if ((value & USBLEGSUP_BIOS_CONTROL) == 0) {
    288252                usb_log_info("BIOS released control after %zu usec.\n", wait);
    289253        } else {
     
    291255                usb_log_warning( "BIOS failed to release control after "
    292256                    "%zu usecs, force it.\n", wait);
    293                 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,
    294259                    USBLEGSUP_OS_CONTROL);
    295                 CHECK_RET_RETURN(ret, "Failed(%d) to force OS control.\n", ret);
    296                 /* Check capability type here, A value of 01h
    297                  * identifies the capability as Legacy Support.
    298                  * This extended capability requires one
    299                  * additional 32-bit register for control/status information,
    300                  * and this register is located at offset EECP+04h
    301                  * */
    302                 if ((usblegsup & 0xff) == 1) {
    303                         /* Read the second EEC
    304                          * Legacy Support and Control register */
    305                         uint32_t usblegctlsts;
    306                         ret = pci_read32(
    307                             device, eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    308                         CHECK_RET_RETURN(ret,
    309                             "Failed(%d) to get USBLEGCTLSTS.\n", ret);
    310                         usb_log_debug("USBLEGCTLSTS: %" PRIxn ".\n",
    311                             usblegctlsts);
    312                         /* Zero SMI enables in legacy control register.
    313                          * It should prevent pre-OS code from interfering. */
    314                         ret = pci_write32(device, eecp + USBLEGCTLSTS_OFFSET,
    315                             0xe0000000); /* three upper bits are WC */
    316                         CHECK_RET_RETURN(ret,
    317                             "Failed(%d) zero USBLEGCTLSTS.\n", ret);
    318                         ret = pci_read32(
    319                             device, eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
    320                         CHECK_RET_RETURN(ret,
    321                             "Failed(%d) to get USBLEGCTLSTS 2.\n", ret);
    322                         usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIxn ".\n",
    323                             usblegctlsts);
    324                 }
    325         }
    326 
     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);
    327276
    328277        /* Read again Legacy Support register */
    329         ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
    330         CHECK_RET_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
    331         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);
    332282
    333283        /*
     
    336286
    337287        /* Get size of capability registers in memory space. */
    338         const unsigned operation_offset = *(uint8_t*)regs;
     288        uint8_t operation_offset = *(uint8_t*)registers;
    339289        usb_log_debug("USBCMD offset: %d.\n", operation_offset);
    340290
    341291        /* Zero USBCMD register. */
    342292        volatile uint32_t *usbcmd =
    343             (uint32_t*)((uint8_t*)regs + operation_offset + CMD_OFFSET);
     293            (uint32_t*)((uint8_t*)registers + operation_offset + CMD_OFFSET);
    344294        volatile uint32_t *usbsts =
    345             (uint32_t*)((uint8_t*)regs + operation_offset + STS_OFFSET);
    346         volatile uint32_t *usbconf =
    347             (uint32_t*)((uint8_t*)regs + operation_offset + CFG_OFFSET);
    348         volatile uint32_t *usbint =
    349             (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);
    350298        usb_log_debug("USBCMD value: %x.\n", *usbcmd);
    351299        if (*usbcmd & USBCMD_RUN) {
    352300                *usbcmd = 0;
    353                 /* Wait until hc is halted */
    354                 while ((*usbsts & USBSTS_HALTED) != 0);
    355                 *usbsts = 0x3f; /* ack all interrupts */
    356                 *usbint = 0; /* disable all interrutps */
    357                 *usbconf = 0; /* relase control of RH ports */
     301                while (!(*usbsts & (1 << 12))); /*wait until hc is halted */
     302                *usbconfigured = 0;
    358303                usb_log_info("EHCI turned off.\n");
    359304        } else {
    360305                usb_log_info("EHCI was not running.\n");
    361306        }
    362         usb_log_debug("Registers: \n"
    363             "\t USBCMD: %x(0x00080000 = at least 1ms between interrupts)\n"
    364             "\t USBSTS: %x(0x00001000 = HC halted)\n"
    365             "\t USBINT: %x(0x0 = no interrupts).\n"
    366             "\t CONFIG: %x(0x0 = ports controlled by companion hc).\n",
    367             *usbcmd, *usbsts, *usbint, *usbconf);
    368 
     307        usb_log_debug("Registers: %x(0x00080000):%x(0x00001000):%x(0x0).\n",
     308            *usbcmd, *usbsts, *usbconfigured);
     309
     310        async_hangup(parent_phone);
    369311        return ret;
    370 #undef CHECK_RET_RETURN
     312#undef CHECK_RET_HANGUP_RETURN
    371313}
    372314/*----------------------------------------------------------------------------*/
Note: See TracChangeset for help on using the changeset viewer.