Changes in uspace/drv/ehci-hcd/pci.c [8855939:c060090] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ehci-hcd/pci.c
r8855939 rc060090 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(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 } 68 129 69 130 /** Get address of registers and IRQ for given device. … … 75 136 * @return Error code. 76 137 */ 77 int pci_get_my_registers( ddf_dev_t *dev,138 int pci_get_my_registers(const ddf_dev_t *dev, 78 139 uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no) 79 140 { 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; … … 145 206 * @return Error code. 146 207 */ 147 int pci_enable_interrupts( ddf_dev_t *device)148 { 149 int parent_phone =208 int pci_enable_interrupts(const ddf_dev_t *device) 209 { 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; … … 162 223 * @return Error code. 163 224 */ 164 int pci_disable_legacy(ddf_dev_t *device) 225 int pci_disable_legacy( 226 const ddf_dev_t *device, uintptr_t reg_base, size_t reg_size, int irq) 165 227 { 166 228 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...) \ 229 (void) pci_read16; 230 (void) pci_read8; 231 (void) pci_write16; 232 233 #define CHECK_RET_RETURN(ret, message...) \ 174 234 if (ret != EOK) { \ 175 235 usb_log_error(message); \ 176 async_hangup(parent_phone); \177 236 return ret; \ 178 237 } else (void)0 179 238 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; 239 /* Map EHCI registers */ 240 void *regs = NULL; 241 int ret = pio_enable((void*)reg_base, reg_size, ®s); 242 CHECK_RET_RETURN(ret, "Failed(%d) to map registers %p.\n", 243 ret, (void *) reg_base); 209 244 210 245 const uint32_t hcc_params = 211 *(uint32_t*)(reg isters + HCC_PARAMS_OFFSET);246 *(uint32_t*)(regs + HCC_PARAMS_OFFSET); 212 247 usb_log_debug("Value of hcc params register: %x.\n", hcc_params); 213 248 214 249 /* Read value of EHCI Extended Capabilities Pointer 215 * (points to PCI config space) */216 uint32_t eecp =250 * position of EEC registers (points to PCI config space) */ 251 const uint32_t eecp = 217 252 (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK; 218 253 usb_log_debug("Value of EECP: %x.\n", eecp); 219 254 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 255 /* 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); 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); 233 260 234 261 /* Request control from firmware/BIOS, by writing 1 to highest byte. 235 262 * (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); 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); 240 266 241 267 size_t wait = 0; 242 268 /* Wait for BIOS to release control. */ 243 while ((wait < DEFAULT_WAIT) && (value & USBLEGSUP_BIOS_CONTROL)) { 269 ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup); 270 while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) { 244 271 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); 272 ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup); 247 273 wait += WAIT_STEP; 248 274 } 249 275 250 276 251 if (( value& USBLEGSUP_BIOS_CONTROL) == 0) {277 if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) { 252 278 usb_log_info("BIOS released control after %zu usec.\n", wait); 253 279 } else { … … 255 281 usb_log_warning( "BIOS failed to release control after " 256 282 "%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, 283 ret = pci_write32(device, eecp + USBLEGSUP_OFFSET, 259 284 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); 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 276 318 277 319 /* 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); 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); 282 323 283 324 /* … … 286 327 287 328 /* Get size of capability registers in memory space. */ 288 uint8_t operation_offset = *(uint8_t*)registers;329 const unsigned operation_offset = *(uint8_t*)regs; 289 330 usb_log_debug("USBCMD offset: %d.\n", operation_offset); 290 331 291 332 /* Zero USBCMD register. */ 292 333 volatile uint32_t *usbcmd = 293 (uint32_t*)((uint8_t*)reg isters + operation_offset + CMD_OFFSET);334 (uint32_t*)((uint8_t*)regs + operation_offset + CMD_OFFSET); 294 335 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); 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); 298 341 usb_log_debug("USBCMD value: %x.\n", *usbcmd); 299 342 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 300 347 *usbcmd = 0; 301 while (!(*usbsts & (1 << 12))); /*wait until hc is halted */302 *usbconfigured = 0;348 /* Wait until hc is halted */ 349 while ((*usbsts & USBSTS_HALTED) == 0); 303 350 usb_log_info("EHCI turned off.\n"); 304 351 } else { 305 352 usb_log_info("EHCI was not running.\n"); 306 353 } 307 usb_log_debug("Registers: %x(0x00080000):%x(0x00001000):%x(0x0).\n", 308 *usbcmd, *usbsts, *usbconfigured); 309 310 async_hangup(parent_phone); 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 311 361 return ret; 312 #undef CHECK_RET_ HANGUP_RETURN362 #undef CHECK_RET_RETURN 313 363 } 314 364 /*----------------------------------------------------------------------------*/
Note:
See TracChangeset
for help on using the changeset viewer.