Changes in / [4708657:be8d907] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ehci-hcd/pci.c
r4708657 rbe8d907 55 55 #define CMD_OFFSET 0x0 56 56 #define STS_OFFSET 0x4 57 #define INT_OFFSET 0x8 57 58 #define CFG_OFFSET 0x40 58 59 59 60 #define USBCMD_RUN 1 61 #define USBSTS_HALTED (1 << 12) 60 62 61 63 #define USBLEGSUP_OFFSET 0 … … 64 66 #define USBLEGCTLSTS_OFFSET 4 65 67 66 #define DEFAULT_WAIT 1000 068 #define DEFAULT_WAIT 1000 67 69 #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 } 68 129 69 130 /** Get address of registers and IRQ for given device. … … 80 141 assert(dev != NULL); 81 142 82 int parent_phone = devman_parent_device_connect(dev->handle,83 IPC_FLAG_BLOCKING);143 const int parent_phone = 144 devman_parent_device_connect(dev->handle, IPC_FLAG_BLOCKING); 84 145 if (parent_phone < 0) { 85 146 return parent_phone; … … 147 208 int pci_enable_interrupts(ddf_dev_t *device) 148 209 { 149 int parent_phone =210 const int parent_phone = 150 211 devman_parent_device_connect(device->handle, IPC_FLAG_BLOCKING); 151 212 if (parent_phone < 0) { 152 213 return parent_phone; 153 214 } 154 bool enabled = hw_res_enable_interrupt(parent_phone);215 const bool enabled = hw_res_enable_interrupt(parent_phone); 155 216 async_hangup(parent_phone); 156 217 return enabled ? EOK : EIO; … … 165 226 { 166 227 assert(device); 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...) \ 228 (void) pci_read16; 229 (void) pci_read8; 230 (void) pci_write16; 231 232 #define CHECK_RET_RETURN(ret, message...) \ 174 233 if (ret != EOK) { \ 175 234 usb_log_error(message); \ 176 async_hangup(parent_phone); \177 235 return ret; \ 178 236 } else (void)0 179 237 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; 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, ®_base, ®_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 199 248 200 249 /* 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; 250 void *regs = NULL; 251 ret = pio_enable((void*)reg_base, reg_size, ®s); 252 CHECK_RET_RETURN(ret, "Failed(%d) to map registers %p.\n", 253 ret, (void *) reg_base); 209 254 210 255 const uint32_t hcc_params = 211 *(uint32_t*)(reg isters + HCC_PARAMS_OFFSET);256 *(uint32_t*)(regs + HCC_PARAMS_OFFSET); 212 257 usb_log_debug("Value of hcc params register: %x.\n", hcc_params); 213 258 214 259 /* Read value of EHCI Extended Capabilities Pointer 215 * (points to PCI config space) */216 uint32_t eecp =260 * position of EEC registers (points to PCI config space) */ 261 const uint32_t eecp = 217 262 (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK; 218 263 usb_log_debug("Value of EECP: %x.\n", eecp); 219 264 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 227 265 /* Read the first EEC. i.e. Legacy Support register */ 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); 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); 233 270 234 271 /* Request control from firmware/BIOS, by writing 1 to highest byte. 235 272 * (OS Control semaphore)*/ 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); 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); 240 276 241 277 size_t wait = 0; 242 278 /* Wait for BIOS to release control. */ 243 while ((wait < DEFAULT_WAIT) && (value & USBLEGSUP_BIOS_CONTROL)) { 279 ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup); 280 while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) { 244 281 async_usleep(WAIT_STEP); 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); 282 ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup); 247 283 wait += WAIT_STEP; 248 284 } 249 285 250 286 251 if (( value& USBLEGSUP_BIOS_CONTROL) == 0) {287 if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) { 252 288 usb_log_info("BIOS released control after %zu usec.\n", wait); 253 289 } else { … … 255 291 usb_log_warning( "BIOS failed to release control after " 256 292 "%zu usecs, force it.\n", wait); 257 ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 258 IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGSUP_OFFSET, 293 ret = pci_write32(device, eecp + USBLEGSUP_OFFSET, 259 294 USBLEGSUP_OS_CONTROL); 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); 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 276 327 277 328 /* Read again Legacy Support register */ 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); 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); 282 332 283 333 /* … … 286 336 287 337 /* Get size of capability registers in memory space. */ 288 uint8_t operation_offset = *(uint8_t*)registers;338 const unsigned operation_offset = *(uint8_t*)regs; 289 339 usb_log_debug("USBCMD offset: %d.\n", operation_offset); 290 340 291 341 /* Zero USBCMD register. */ 292 342 volatile uint32_t *usbcmd = 293 (uint32_t*)((uint8_t*)reg isters + operation_offset + CMD_OFFSET);343 (uint32_t*)((uint8_t*)regs + operation_offset + CMD_OFFSET); 294 344 volatile uint32_t *usbsts = 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); 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); 298 350 usb_log_debug("USBCMD value: %x.\n", *usbcmd); 299 351 if (*usbcmd & USBCMD_RUN) { 300 352 *usbcmd = 0; 301 while (!(*usbsts & (1 << 12))); /*wait until hc is halted */ 302 *usbconfigured = 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 */ 303 358 usb_log_info("EHCI turned off.\n"); 304 359 } else { 305 360 usb_log_info("EHCI was not running.\n"); 306 361 } 307 usb_log_debug("Registers: %x(0x00080000):%x(0x00001000):%x(0x0).\n", 308 *usbcmd, *usbsts, *usbconfigured); 309 310 async_hangup(parent_phone); 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 311 369 return ret; 312 #undef CHECK_RET_ HANGUP_RETURN370 #undef CHECK_RET_RETURN 313 371 } 314 372 /*----------------------------------------------------------------------------*/
Note:
See TracChangeset
for help on using the changeset viewer.