Changeset 663f41c4 in mainline for uspace/drv/pciintel/pci.c
- Timestamp:
- 2010-10-23T10:56:44Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5291411
- Parents:
- 49698fa
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/pciintel/pci.c
r49698fa r663f41c4 58 58 #define NAME "pciintel" 59 59 60 #define CONF_ADDR(bus, dev, fn, reg) ((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) 61 62 63 static hw_resource_list_t * pciintel_get_child_resources(device_t *dev) 64 { 65 pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data; 66 if (NULL == dev_data) { 60 #define CONF_ADDR(bus, dev, fn, reg) \ 61 ((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) 62 63 static hw_resource_list_t *pciintel_get_child_resources(device_t *dev) 64 { 65 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 66 67 if (NULL == dev_data) 67 68 return NULL; 68 }69 69 return &dev_data->hw_resources; 70 70 } 71 71 72 static bool pciintel_enable_child_interrupt(device_t *dev) 73 { 74 / / TODO72 static bool pciintel_enable_child_interrupt(device_t *dev) 73 { 74 /* TODO */ 75 75 76 76 return false; … … 79 79 static resource_iface_t pciintel_child_res_iface = { 80 80 &pciintel_get_child_resources, 81 &pciintel_enable_child_interrupt 81 &pciintel_enable_child_interrupt 82 82 }; 83 83 84 84 static device_ops_t pci_child_ops; 85 85 86 87 static int pci_add_device(device_t *dev); 88 89 /** The pci bus driver's standard operations. 90 */ 86 static int pci_add_device(device_t *); 87 88 /** The pci bus driver's standard operations. */ 91 89 static driver_ops_t pci_ops = { 92 90 .add_device = &pci_add_device 93 91 }; 94 92 95 /** The pci bus driver structure. 96 */ 93 /** The pci bus driver structure. */ 97 94 static driver_t pci_driver = { 98 95 .name = NAME, … … 103 100 uint32_t conf_io_addr; 104 101 void *conf_data_port; 105 void *conf_addr_port; 102 void *conf_addr_port; 106 103 fibril_mutex_t conf_mutex; 107 104 } pci_bus_data_t; 108 105 109 static inline pci_bus_data_t *create_pci_bus_data() 110 { 111 pci_bus_data_t *bus_data = (pci_bus_data_t *)malloc(sizeof(pci_bus_data_t)); 112 if(NULL != bus_data) { 106 static pci_bus_data_t *create_pci_bus_data(void) 107 { 108 pci_bus_data_t *bus_data; 109 110 bus_data = (pci_bus_data_t *) malloc(sizeof(pci_bus_data_t)); 111 if (NULL != bus_data) { 113 112 memset(bus_data, 0, sizeof(pci_bus_data_t)); 114 113 fibril_mutex_initialize(&bus_data->conf_mutex); 115 114 } 116 return bus_data; 117 } 118 119 static inline void delete_pci_bus_data(pci_bus_data_t *bus_data)120 { 121 free(bus_data); 115 return bus_data; 116 } 117 118 static void delete_pci_bus_data(pci_bus_data_t *bus_data) 119 { 120 free(bus_data); 122 121 } 123 122 … … 126 125 assert(NULL != dev->parent); 127 126 128 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;129 pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data;127 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 128 pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data; 130 129 131 130 fibril_mutex_lock(&bus_data->conf_mutex); 132 131 133 uint32_t conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg); 132 uint32_t conf_addr; 133 conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg); 134 134 void *addr = bus_data->conf_data_port + (reg & 3); 135 135 … … 137 137 138 138 switch (len) { 139 140 141 142 143 ((uint16_t *)buf)[0] = pio_read_16(addr);144 145 146 ((uint32_t *)buf)[0] = pio_read_32(addr);147 148 } 149 150 fibril_mutex_unlock(&bus_data->conf_mutex); 139 case 1: 140 buf[0] = pio_read_8(addr); 141 break; 142 case 2: 143 ((uint16_t *) buf)[0] = pio_read_16(addr); 144 break; 145 case 4: 146 ((uint32_t *) buf)[0] = pio_read_32(addr); 147 break; 148 } 149 150 fibril_mutex_unlock(&bus_data->conf_mutex); 151 151 } 152 152 … … 155 155 assert(NULL != dev->parent); 156 156 157 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;158 pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data;157 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 158 pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data; 159 159 160 160 fibril_mutex_lock(&bus_data->conf_mutex); 161 161 162 uint32_t conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg); 162 uint32_t conf_addr; 163 conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg); 163 164 void *addr = bus_data->conf_data_port + (reg & 3); 164 165 … … 166 167 167 168 switch (len) { 168 169 170 171 172 pio_write_16(addr, ((uint16_t *)buf)[0]);173 174 175 pio_write_32(addr, ((uint32_t *)buf)[0]);176 177 } 178 179 fibril_mutex_unlock(&bus_data->conf_mutex); 169 case 1: 170 pio_write_8(addr, buf[0]); 171 break; 172 case 2: 173 pio_write_16(addr, ((uint16_t *) buf)[0]); 174 break; 175 case 4: 176 pio_write_32(addr, ((uint32_t *) buf)[0]); 177 break; 178 } 179 180 fibril_mutex_unlock(&bus_data->conf_mutex); 180 181 } 181 182 … … 190 191 { 191 192 uint16_t res; 192 pci_conf_read(dev, reg, (uint8_t *) &res, 2);193 pci_conf_read(dev, reg, (uint8_t *) &res, 2); 193 194 return res; 194 195 } … … 197 198 { 198 199 uint32_t res; 199 pci_conf_read(dev, reg, (uint8_t *)&res, 4); 200 return res; 201 } 202 203 void pci_conf_write_8(device_t *dev, int reg, uint8_t val) 204 { 205 pci_conf_write(dev, reg, (uint8_t *)&val, 1); 206 } 207 208 void pci_conf_write_16(device_t *dev, int reg, uint16_t val) 209 { 210 pci_conf_write(dev, reg, (uint8_t *)&val, 2); 211 } 212 213 void pci_conf_write_32(device_t *dev, int reg, uint32_t val) 214 { 215 pci_conf_write(dev, reg, (uint8_t *)&val, 4); 216 } 217 200 pci_conf_read(dev, reg, (uint8_t *) &res, 4); 201 return res; 202 } 203 204 void pci_conf_write_8(device_t *dev, int reg, uint8_t val) 205 { 206 pci_conf_write(dev, reg, (uint8_t *) &val, 1); 207 } 208 209 void pci_conf_write_16(device_t *dev, int reg, uint16_t val) 210 { 211 pci_conf_write(dev, reg, (uint8_t *) &val, 2); 212 } 213 214 void pci_conf_write_32(device_t *dev, int reg, uint32_t val) 215 { 216 pci_conf_write(dev, reg, (uint8_t *) &val, 4); 217 } 218 218 219 219 void create_pci_match_ids(device_t *dev) 220 220 { 221 pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data; 222 match_id_t *match_id = NULL; 223 char *match_id_str; 221 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 222 match_id_t *match_id = NULL; 223 char *match_id_str; 224 224 225 match_id = create_match_id(); 225 226 if (NULL != match_id) { 226 asprintf(&match_id_str, "pci/ven=%04x&dev=%04x", dev_data->vendor_id, dev_data->device_id); 227 asprintf(&match_id_str, "pci/ven=%04x&dev=%04x", 228 dev_data->vendor_id, dev_data->device_id); 227 229 match_id->id = match_id_str; 228 230 match_id->score = 90; 229 231 add_match_id(&dev->match_ids, match_id); 230 232 } 231 // TODO add more ids (with subsys ids, using class id etc.) 232 } 233 234 void pci_add_range(device_t *dev, uint64_t range_addr, size_t range_size, bool io) 235 { 236 pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data; 233 /* TODO add more ids (with subsys ids, using class id etc.) */ 234 } 235 236 void 237 pci_add_range(device_t *dev, uint64_t range_addr, size_t range_size, bool io) 238 { 239 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 237 240 hw_resource_list_t *hw_res_list = &dev_data->hw_resources; 238 241 hw_resource_t *hw_resources = hw_res_list->resources; 239 size_t count = hw_res_list->count; 242 size_t count = hw_res_list->count; 240 243 241 244 assert(NULL != hw_resources); … … 245 248 hw_resources[count].type = IO_RANGE; 246 249 hw_resources[count].res.io_range.address = range_addr; 247 hw_resources[count].res.io_range.size = range_size; 248 hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN; 250 hw_resources[count].res.io_range.size = range_size; 251 hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN; 249 252 } else { 250 253 hw_resources[count].type = MEM_RANGE; 251 254 hw_resources[count].res.mem_range.address = range_addr; 252 hw_resources[count].res.mem_range.size = range_size; 255 hw_resources[count].res.mem_range.size = range_size; 253 256 hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN; 254 257 } 255 258 256 hw_res_list->count++; 257 } 258 259 260 /** Read the base address register (BAR) of the device 261 * and if it contains valid address add it to the devices hw resource list. 262 * 263 * @param dev the pci device. 264 * @param addr the address of the BAR in the PCI configuration address space of the device. 265 * 266 * @return the addr the address of the BAR which should be read next. 259 hw_res_list->count++; 260 } 261 262 /** Read the base address register (BAR) of the device and if it contains valid 263 * address add it to the devices hw resource list. 264 * 265 * @param dev The pci device. 266 * @param addr The address of the BAR in the PCI configuration address space of 267 * the device. 268 * @return The addr the address of the BAR which should be read next. 267 269 */ 268 int pci_read_bar(device_t *dev, int addr) 270 int pci_read_bar(device_t *dev, int addr) 269 271 { 270 / / value of the BAR272 /* Value of the BAR */ 271 273 uint32_t val, mask; 272 / / IO space address274 /* IO space address */ 273 275 bool io; 274 / / 64-bit wide address276 /* 64-bit wide address */ 275 277 bool w64; 276 278 277 / / size of the io or memory range specified by the BAR279 /* Size of the io or memory range specified by the BAR */ 278 280 size_t range_size; 279 / / beginning of the io or memory range specified by the BAR281 /* Beginning of the io or memory range specified by the BAR */ 280 282 uint64_t range_addr; 281 283 282 / / get the value of the BAR284 /* Get the value of the BAR. */ 283 285 val = pci_conf_read_32(dev, addr); 284 286 285 io = (bool) (val & 1);287 io = (bool) (val & 1); 286 288 if (io) { 287 289 w64 = false; … … 295 297 break; 296 298 default: 297 / / reserved, go to the next BAR298 return addr + 4; 299 /* reserved, go to the next BAR */ 300 return addr + 4; 299 301 } 300 302 } 301 303 302 / / get the address mask304 /* Get the address mask. */ 303 305 pci_conf_write_32(dev, addr, 0xffffffff); 304 mask = pci_conf_read_32(dev, addr); 305 306 / / restore the original value306 mask = pci_conf_read_32(dev, addr); 307 308 /* Restore the original value. */ 307 309 pci_conf_write_32(dev, addr, val); 308 val = pci_conf_read_32(dev, addr); 310 val = pci_conf_read_32(dev, addr); 309 311 310 312 range_size = pci_bar_mask_to_size(mask); 311 313 312 314 if (w64) { 313 range_addr = ((uint64_t)pci_conf_read_32(dev, addr + 4) << 32) | (val & 0xfffffff0); 315 range_addr = ((uint64_t)pci_conf_read_32(dev, addr + 4) << 32) | 316 (val & 0xfffffff0); 314 317 } else { 315 318 range_addr = (val & 0xfffffff0); 316 } 319 } 320 317 321 if (0 != range_addr) { 318 322 printf(NAME ": device %s : ", dev->name); 319 printf("address = %x", range_addr); 323 printf("address = %x", range_addr); 320 324 printf(", size = %x\n", range_size); 321 325 } … … 323 327 pci_add_range(dev, range_addr, range_size, io); 324 328 325 if (w64) {329 if (w64) 326 330 return addr + 8; 327 }328 return addr + 4; 331 332 return addr + 4; 329 333 } 330 334 331 335 void pci_add_interrupt(device_t *dev, int irq) 332 336 { 333 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data;337 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 334 338 hw_resource_list_t *hw_res_list = &dev_data->hw_resources; 335 hw_resource_t *hw_resources = 336 size_t count = hw_res_list->count; 339 hw_resource_t *hw_resources = hw_res_list->resources; 340 size_t count = hw_res_list->count; 337 341 338 342 assert(NULL != hw_resources); … … 342 346 hw_resources[count].res.interrupt.irq = irq; 343 347 344 hw_res_list->count++; 345 348 hw_res_list->count++; 346 349 347 350 printf(NAME ": device %s uses irq %x.\n", dev->name, irq); … … 351 354 { 352 355 uint8_t irq = pci_conf_read_8(dev, PCI_BRIDGE_INT_LINE); 353 if (0xff != irq) {356 if (0xff != irq) 354 357 pci_add_interrupt(dev, irq); 355 }356 358 } 357 359 358 360 /** Enumerate (recursively) and register the devices connected to a pci bus. 359 * 360 * @param parent the host-to-pci bridge device.361 * @param bus_num the bus number.361 * 362 * @param parent The host-to-pci bridge device. 363 * @param bus_num The bus number. 362 364 */ 363 365 void pci_bus_scan(device_t *parent, int bus_num) … … 377 379 for (fnum = 0; multi && fnum < 8; fnum++) { 378 380 init_pci_dev_data(dev_data, bus_num, dnum, fnum); 379 dev_data->vendor_id = pci_conf_read_16(dev, PCI_VENDOR_ID); 380 dev_data->device_id = pci_conf_read_16(dev, PCI_DEVICE_ID); 381 if (dev_data->vendor_id == 0xffff) { // device is not present, go on scanning the bus 382 if (fnum == 0) { 381 dev_data->vendor_id = pci_conf_read_16(dev, 382 PCI_VENDOR_ID); 383 dev_data->device_id = pci_conf_read_16(dev, 384 PCI_DEVICE_ID); 385 if (dev_data->vendor_id == 0xffff) { 386 /* 387 * The device is not present, go on scanning the 388 * bus. 389 */ 390 if (fnum == 0) 383 391 break; 384 } else { 385 continue; 386 } 392 else 393 continue; 387 394 } 395 388 396 header_type = pci_conf_read_8(dev, PCI_HEADER_TYPE); 389 397 if (fnum == 0) { 390 multi = header_type >> 7; // is the device multifunction? 398 /* Is the device multifunction? */ 399 multi = header_type >> 7; 391 400 } 392 header_type = header_type & 0x7F; // clear the multifunction bit 401 /* Clear the multifunction bit. */ 402 header_type = header_type & 0x7F; 393 403 394 404 create_pci_dev_name(dev); … … 398 408 pci_read_interrupt(dev); 399 409 400 dev->ops = &pci_child_ops; 401 402 printf(NAME ": adding new child device %s.\n", dev->name); 410 dev->ops = &pci_child_ops; 411 412 printf(NAME ": adding new child device %s.\n", 413 dev->name); 403 414 404 415 create_pci_match_ids(dev); 405 416 406 if (EOK != child_device_register(dev, parent)) { 407 pci_clean_resource_list(dev); 417 if (EOK != child_device_register(dev, parent)) { 418 pci_clean_resource_list(dev); 408 419 clean_match_ids(&dev->match_ids); 409 free((char *) dev->name);420 free((char *) dev->name); 410 421 dev->name = NULL; 411 422 continue; 412 423 } 413 424 414 //printf(NAME ": new device %s was successfully registered by device manager.\n", dev->name);415 416 if (header_type == PCI_HEADER_TYPE_BRIDGE || header_type == PCI_HEADER_TYPE_CARDBUS ) {417 child_bus = pci_conf_read_8(dev,PCI_BRIDGE_SEC_BUS_NUM);418 printf(NAME ": device is pci-to-pci bridge, secondary bus number = %d.\n", bus_num);419 if(child_bus > bus_num) {420 pci_bus_scan(parent, child_bus);421 }425 if (header_type == PCI_HEADER_TYPE_BRIDGE || 426 header_type == PCI_HEADER_TYPE_CARDBUS ) { 427 child_bus = pci_conf_read_8(dev, 428 PCI_BRIDGE_SEC_BUS_NUM); 429 printf(NAME ": device is pci-to-pci bridge, " 430 "secondary bus number = %d.\n", bus_num); 431 if(child_bus > bus_num) 432 pci_bus_scan(parent, child_bus); 422 433 } 423 434 424 dev = create_device(); // alloc new aux. dev. structure 435 /* Alloc new aux. dev. structure. */ 436 dev = create_device(); 425 437 dev_data = create_pci_dev_data(); 426 438 dev->driver_data = dev_data; … … 431 443 if (dev_data->vendor_id == 0xffff) { 432 444 delete_device(dev); 433 delete_pci_dev_data(dev_data); // free the auxiliary device structure 434 } 445 /* Free the auxiliary device structure. */ 446 delete_pci_dev_data(dev_data); 447 } 435 448 } 436 449 … … 443 456 printf(NAME ": pci_add_device allocation failed.\n"); 444 457 return ENOMEM; 445 } 446 447 dev->parent_phone = devman_parent_device_connect(dev->handle, IPC_FLAG_BLOCKING); 448 if (dev->parent_phone <= 0) { 449 printf(NAME ": pci_add_device failed to connect to the parent's driver.\n"); 458 } 459 460 dev->parent_phone = devman_parent_device_connect(dev->handle, 461 IPC_FLAG_BLOCKING); 462 if (dev->parent_phone < 0) { 463 printf(NAME ": pci_add_device failed to connect to the " 464 "parent's driver.\n"); 450 465 delete_pci_bus_data(bus_data); 451 466 return EPARTY; /* FIXME: use another EC */ … … 455 470 456 471 if (!get_hw_resources(dev->parent_phone, &hw_resources)) { 457 printf(NAME ": pci_add_device failed to get hw resources for the device.\n"); 472 printf(NAME ": pci_add_device failed to get hw resources for " 473 "the device.\n"); 458 474 delete_pci_bus_data(bus_data); 459 475 ipc_hangup(dev->parent_phone); … … 461 477 } 462 478 463 printf(NAME ": conf_addr = %x.\n", hw_resources.resources[0].res.io_range.address); 479 printf(NAME ": conf_addr = %x.\n", 480 hw_resources.resources[0].res.io_range.address); 464 481 465 482 assert(hw_resources.count > 0); … … 467 484 assert(hw_resources.resources[0].res.io_range.size == 8); 468 485 469 bus_data->conf_io_addr = (uint32_t)hw_resources.resources[0].res.io_range.address; 470 471 if (pio_enable((void *)bus_data->conf_io_addr, 8, &bus_data->conf_addr_port)) { 486 bus_data->conf_io_addr = 487 (uint32_t) hw_resources.resources[0].res.io_range.address; 488 489 if (pio_enable((void *)bus_data->conf_io_addr, 8, 490 &bus_data->conf_addr_port)) { 472 491 printf(NAME ": failed to enable configuration ports.\n"); 473 492 delete_pci_bus_data(bus_data); 474 493 ipc_hangup(dev->parent_phone); 475 494 clean_hw_resource_list(&hw_resources); 476 return EADDRNOTAVAIL; 477 } 478 bus_data->conf_data_port = (char *) bus_data->conf_addr_port + 4;495 return EADDRNOTAVAIL; 496 } 497 bus_data->conf_data_port = (char *) bus_data->conf_addr_port + 4; 479 498 480 499 dev->driver_data = bus_data; 481 500 482 / / enumerate child devices501 /* Enumerate child devices. */ 483 502 printf(NAME ": scanning the bus\n"); 484 503 pci_bus_scan(dev, 0); … … 489 508 } 490 509 491 static void pciintel_init( )510 static void pciintel_init(void) 492 511 { 493 512 pci_child_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_child_res_iface;
Note:
See TracChangeset
for help on using the changeset viewer.