Changes in uspace/drv/pciintel/pci.c [dc75234:fb78ae72] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/pciintel/pci.c
rdc75234 rfb78ae72 1 1 /* 2 2 * Copyright (c) 2010 Lenka Trochtova 3 * Copyright (c) 2011 Jiri Svoboda4 3 * All rights reserved. 5 4 * … … 45 44 #include <ctype.h> 46 45 #include <macros.h> 47 #include <str_error.h> 48 49 #include <ddf/driver.h> 46 47 #include <driver.h> 50 48 #include <devman.h> 51 49 #include <ipc/devman.h> … … 59 57 #include <ddi.h> 60 58 #include <libarch/ddi.h> 61 #include <pci_dev_iface.h>62 59 63 60 #include "pci.h" … … 68 65 ((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) 69 66 70 /** Obtain PCI function soft-state from DDF function node */ 71 #define PCI_FUN(fnode) ((pci_fun_t *) (fnode)->driver_data) 72 73 /** Obtain PCI bus soft-state from DDF device node */ 74 #define PCI_BUS(dnode) ((pci_bus_t *) (dnode)->driver_data) 75 76 /** Obtain PCI bus soft-state from function soft-state */ 77 #define PCI_BUS_FROM_FUN(fun) ((fun)->busptr) 78 79 static hw_resource_list_t *pciintel_get_resources(ddf_fun_t *fnode) 80 { 81 pci_fun_t *fun = PCI_FUN(fnode); 82 83 if (fun == NULL) 67 static hw_resource_list_t *pciintel_get_child_resources(device_t *dev) 68 { 69 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 70 71 if (dev_data == NULL) 84 72 return NULL; 85 return & fun->hw_resources;86 } 87 88 static bool pciintel_enable_ interrupt(ddf_fun_t *fnode)73 return &dev_data->hw_resources; 74 } 75 76 static bool pciintel_enable_child_interrupt(device_t *dev) 89 77 { 90 78 /* This is an old ugly way, copied from ne2000 driver */ 91 assert( fnode);92 pci_ fun_t *dev_data = (pci_fun_t *) fnode->driver_data;79 assert(dev); 80 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 93 81 94 82 sysarg_t apic; 95 83 sysarg_t i8259; 96 97 84 int irc_phone = -1; 98 85 int irc_service = 0; … … 104 91 } 105 92 106 if (irc_service == 0) 93 if (irc_service) { 94 while (irc_phone < 0) 95 irc_phone = service_connect_blocking(irc_service, 0, 0); 96 } else { 107 97 return false; 108 109 irc_phone = service_connect_blocking(irc_service, 0, 0); 110 if (irc_phone < 0) 111 return false; 98 } 112 99 113 100 size_t i; … … 115 102 if (dev_data->hw_resources.resources[i].type == INTERRUPT) { 116 103 int irq = dev_data->hw_resources.resources[i].res.interrupt.irq; 117 int rc = async_req_1_0(irc_phone, IRC_ENABLE_INTERRUPT, irq); 118 if (rc != EOK) { 119 async_hangup(irc_phone); 120 return false; 121 } 104 async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, irq); 122 105 } 123 106 } … … 127 110 } 128 111 129 static int pci_config_space_write_16(ddf_fun_t *fun, uint32_t address, uint16_t data) 130 { 131 if (address > 254) 132 return EINVAL; 133 pci_conf_write_16(PCI_FUN(fun), address, data); 134 return EOK; 135 } 136 137 138 static hw_res_ops_t pciintel_hw_res_ops = { 139 &pciintel_get_resources, 140 &pciintel_enable_interrupt 112 static hw_res_ops_t pciintel_child_hw_res_ops = { 113 &pciintel_get_child_resources, 114 &pciintel_enable_child_interrupt 141 115 }; 142 116 143 static pci_dev_iface_t pci_dev_ops = { 144 .config_space_read_8 = NULL, 145 .config_space_read_16 = NULL, 146 .config_space_read_32 = NULL, 147 .config_space_write_8 = NULL, 148 .config_space_write_16 = &pci_config_space_write_16, 149 .config_space_write_32 = NULL 150 }; 151 152 static ddf_dev_ops_t pci_fun_ops = { 153 .interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops, 154 .interfaces[PCI_DEV_IFACE] = &pci_dev_ops 155 }; 156 157 static int pci_add_device(ddf_dev_t *); 158 159 /** PCI bus driver standard operations */ 117 static device_ops_t pci_child_ops; 118 119 static int pci_add_device(device_t *); 120 121 /** The pci bus driver's standard operations. */ 160 122 static driver_ops_t pci_ops = { 161 123 .add_device = &pci_add_device 162 124 }; 163 125 164 /** PCI bus driver structure*/126 /** The pci bus driver structure. */ 165 127 static driver_t pci_driver = { 166 128 .name = NAME, … … 168 130 }; 169 131 170 static pci_bus_t *pci_bus_new(void) 171 { 172 pci_bus_t *bus; 173 174 bus = (pci_bus_t *) calloc(1, sizeof(pci_bus_t)); 175 if (bus == NULL) 176 return NULL; 177 178 fibril_mutex_initialize(&bus->conf_mutex); 179 return bus; 180 } 181 182 static void pci_bus_delete(pci_bus_t *bus) 183 { 184 assert(bus != NULL); 185 free(bus); 186 } 187 188 static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len) 189 { 190 pci_bus_t *bus = PCI_BUS_FROM_FUN(fun); 191 192 fibril_mutex_lock(&bus->conf_mutex); 132 typedef struct pciintel_bus_data { 133 uint32_t conf_io_addr; 134 void *conf_data_port; 135 void *conf_addr_port; 136 fibril_mutex_t conf_mutex; 137 } pci_bus_data_t; 138 139 static pci_bus_data_t *create_pci_bus_data(void) 140 { 141 pci_bus_data_t *bus_data; 142 143 bus_data = (pci_bus_data_t *) malloc(sizeof(pci_bus_data_t)); 144 if (bus_data != NULL) { 145 memset(bus_data, 0, sizeof(pci_bus_data_t)); 146 fibril_mutex_initialize(&bus_data->conf_mutex); 147 } 148 149 return bus_data; 150 } 151 152 static void delete_pci_bus_data(pci_bus_data_t *bus_data) 153 { 154 free(bus_data); 155 } 156 157 static void pci_conf_read(device_t *dev, int reg, uint8_t *buf, size_t len) 158 { 159 assert(dev->parent != NULL); 160 161 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 162 pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data; 163 164 fibril_mutex_lock(&bus_data->conf_mutex); 193 165 194 166 uint32_t conf_addr; 195 conf_addr = CONF_ADDR( fun->bus, fun->dev, fun->fn, reg);196 void *addr = bus ->conf_data_port + (reg & 3);197 198 pio_write_32(bus ->conf_addr_port, conf_addr);167 conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg); 168 void *addr = bus_data->conf_data_port + (reg & 3); 169 170 pio_write_32(bus_data->conf_addr_port, conf_addr); 199 171 200 172 switch (len) { … … 210 182 } 211 183 212 fibril_mutex_unlock(&bus->conf_mutex); 213 } 214 215 static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len) 216 { 217 pci_bus_t *bus = PCI_BUS_FROM_FUN(fun); 218 219 fibril_mutex_lock(&bus->conf_mutex); 184 fibril_mutex_unlock(&bus_data->conf_mutex); 185 } 186 187 static void pci_conf_write(device_t *dev, int reg, uint8_t *buf, size_t len) 188 { 189 assert(dev->parent != NULL); 190 191 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 192 pci_bus_data_t *bus_data = (pci_bus_data_t *) dev->parent->driver_data; 193 194 fibril_mutex_lock(&bus_data->conf_mutex); 220 195 221 196 uint32_t conf_addr; 222 conf_addr = CONF_ADDR( fun->bus, fun->dev, fun->fn, reg);223 void *addr = bus ->conf_data_port + (reg & 3);224 225 pio_write_32(bus ->conf_addr_port, conf_addr);197 conf_addr = CONF_ADDR(dev_data->bus, dev_data->dev, dev_data->fn, reg); 198 void *addr = bus_data->conf_data_port + (reg & 3); 199 200 pio_write_32(bus_data->conf_addr_port, conf_addr); 226 201 227 202 switch (len) { … … 237 212 } 238 213 239 fibril_mutex_unlock(&bus ->conf_mutex);240 } 241 242 uint8_t pci_conf_read_8( pci_fun_t *fun, int reg)214 fibril_mutex_unlock(&bus_data->conf_mutex); 215 } 216 217 uint8_t pci_conf_read_8(device_t *dev, int reg) 243 218 { 244 219 uint8_t res; 245 pci_conf_read( fun, reg, &res, 1);220 pci_conf_read(dev, reg, &res, 1); 246 221 return res; 247 222 } 248 223 249 uint16_t pci_conf_read_16( pci_fun_t *fun, int reg)224 uint16_t pci_conf_read_16(device_t *dev, int reg) 250 225 { 251 226 uint16_t res; 252 pci_conf_read( fun, reg, (uint8_t *) &res, 2);227 pci_conf_read(dev, reg, (uint8_t *) &res, 2); 253 228 return res; 254 229 } 255 230 256 uint32_t pci_conf_read_32( pci_fun_t *fun, int reg)231 uint32_t pci_conf_read_32(device_t *dev, int reg) 257 232 { 258 233 uint32_t res; 259 pci_conf_read( fun, reg, (uint8_t *) &res, 4);234 pci_conf_read(dev, reg, (uint8_t *) &res, 4); 260 235 return res; 261 236 } 262 237 263 void pci_conf_write_8(pci_fun_t *fun, int reg, uint8_t val) 264 { 265 pci_conf_write(fun, reg, (uint8_t *) &val, 1); 266 } 267 268 void pci_conf_write_16(pci_fun_t *fun, int reg, uint16_t val) 269 { 270 pci_conf_write(fun, reg, (uint8_t *) &val, 2); 271 } 272 273 void pci_conf_write_32(pci_fun_t *fun, int reg, uint32_t val) 274 { 275 pci_conf_write(fun, reg, (uint8_t *) &val, 4); 276 } 277 278 void pci_fun_create_match_ids(pci_fun_t *fun) 279 { 238 void pci_conf_write_8(device_t *dev, int reg, uint8_t val) 239 { 240 pci_conf_write(dev, reg, (uint8_t *) &val, 1); 241 } 242 243 void pci_conf_write_16(device_t *dev, int reg, uint16_t val) 244 { 245 pci_conf_write(dev, reg, (uint8_t *) &val, 2); 246 } 247 248 void pci_conf_write_32(device_t *dev, int reg, uint32_t val) 249 { 250 pci_conf_write(dev, reg, (uint8_t *) &val, 4); 251 } 252 253 void create_pci_match_ids(device_t *dev) 254 { 255 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 256 match_id_t *match_id = NULL; 280 257 char *match_id_str; 281 int rc; 282 283 asprintf(&match_id_str, "pci/ven=%04x&dev=%04x", 284 fun->vendor_id, fun->device_id); 285 286 if (match_id_str == NULL) { 287 printf(NAME ": out of memory creating match ID.\n"); 288 return; 289 } 290 291 rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 90); 292 if (rc != EOK) { 293 printf(NAME ": error adding match ID: %s\n", 294 str_error(rc)); 295 } 296 258 259 match_id = create_match_id(); 260 if (match_id != NULL) { 261 asprintf(&match_id_str, "pci/ven=%04x&dev=%04x", 262 dev_data->vendor_id, dev_data->device_id); 263 match_id->id = match_id_str; 264 match_id->score = 90; 265 add_match_id(&dev->match_ids, match_id); 266 } 267 297 268 /* TODO add more ids (with subsys ids, using class id etc.) */ 298 269 } 299 270 300 void pci_add_range(pci_fun_t *fun, uint64_t range_addr, size_t range_size, 301 bool io) 302 { 303 hw_resource_list_t *hw_res_list = &fun->hw_resources; 271 void 272 pci_add_range(device_t *dev, uint64_t range_addr, size_t range_size, bool io) 273 { 274 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 275 hw_resource_list_t *hw_res_list = &dev_data->hw_resources; 304 276 hw_resource_t *hw_resources = hw_res_list->resources; 305 277 size_t count = hw_res_list->count; … … 326 298 * address add it to the devices hw resource list. 327 299 * 328 * @param fun PCI function300 * @param dev The pci device. 329 301 * @param addr The address of the BAR in the PCI configuration address space of 330 * the device 331 * @return The addr the address of the BAR which should be read next 302 * the device. 303 * @return The addr the address of the BAR which should be read next. 332 304 */ 333 int pci_read_bar( pci_fun_t *fun, int addr)334 { 305 int pci_read_bar(device_t *dev, int addr) 306 { 335 307 /* Value of the BAR */ 336 308 uint32_t val, mask; … … 346 318 347 319 /* Get the value of the BAR. */ 348 val = pci_conf_read_32(fun, addr); 349 350 #define IO_MASK (~0x3) 351 #define MEM_MASK (~0xf) 320 val = pci_conf_read_32(dev, addr); 352 321 353 322 io = (bool) (val & 1); 354 323 if (io) { 355 324 addrw64 = false; 356 mask = IO_MASK;357 325 } else { 358 mask = MEM_MASK;359 326 switch ((val >> 1) & 3) { 360 327 case 0: … … 371 338 372 339 /* Get the address mask. */ 373 pci_conf_write_32( fun, addr, 0xffffffff);374 mask &= pci_conf_read_32(fun, addr);340 pci_conf_write_32(dev, addr, 0xffffffff); 341 mask = pci_conf_read_32(dev, addr); 375 342 376 343 /* Restore the original value. */ 377 pci_conf_write_32( fun, addr, val);378 val = pci_conf_read_32( fun, addr);344 pci_conf_write_32(dev, addr, val); 345 val = pci_conf_read_32(dev, addr); 379 346 380 347 range_size = pci_bar_mask_to_size(mask); 381 348 382 349 if (addrw64) { 383 range_addr = ((uint64_t)pci_conf_read_32( fun, addr + 4) << 32) |350 range_addr = ((uint64_t)pci_conf_read_32(dev, addr + 4) << 32) | 384 351 (val & 0xfffffff0); 385 352 } else { … … 388 355 389 356 if (range_addr != 0) { 390 printf(NAME ": function %s : ", fun->fnode->name);357 printf(NAME ": device %s : ", dev->name); 391 358 printf("address = %" PRIx64, range_addr); 392 359 printf(", size = %x\n", (unsigned int) range_size); 393 360 } 394 361 395 pci_add_range( fun, range_addr, range_size, io);362 pci_add_range(dev, range_addr, range_size, io); 396 363 397 364 if (addrw64) … … 401 368 } 402 369 403 void pci_add_interrupt(pci_fun_t *fun, int irq) 404 { 405 hw_resource_list_t *hw_res_list = &fun->hw_resources; 370 void pci_add_interrupt(device_t *dev, int irq) 371 { 372 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 373 hw_resource_list_t *hw_res_list = &dev_data->hw_resources; 406 374 hw_resource_t *hw_resources = hw_res_list->resources; 407 375 size_t count = hw_res_list->count; … … 415 383 hw_res_list->count++; 416 384 417 printf(NAME ": function %s uses irq %x.\n", fun->fnode->name, irq);418 } 419 420 void pci_read_interrupt( pci_fun_t *fun)421 { 422 uint8_t irq = pci_conf_read_8( fun, PCI_BRIDGE_INT_LINE);385 printf(NAME ": device %s uses irq %x.\n", dev->name, irq); 386 } 387 388 void pci_read_interrupt(device_t *dev) 389 { 390 uint8_t irq = pci_conf_read_8(dev, PCI_BRIDGE_INT_LINE); 423 391 if (irq != 0xff) 424 pci_add_interrupt( fun, irq);392 pci_add_interrupt(dev, irq); 425 393 } 426 394 427 395 /** Enumerate (recursively) and register the devices connected to a pci bus. 428 396 * 429 * @param bus Host-to-PCI bridge430 * @param bus_num Bus number397 * @param parent The host-to-pci bridge device. 398 * @param bus_num The bus number. 431 399 */ 432 void pci_bus_scan(pci_bus_t *bus, int bus_num) 433 { 434 ddf_fun_t *fnode; 435 pci_fun_t *fun; 400 void pci_bus_scan(device_t *parent, int bus_num) 401 { 402 device_t *dev = create_device(); 403 pci_dev_data_t *dev_data = create_pci_dev_data(); 404 dev->driver_data = dev_data; 405 dev->parent = parent; 436 406 437 407 int child_bus = 0; 438 408 int dnum, fnum; 439 409 bool multi; 440 uint8_t header_type; 441 442 fun = pci_fun_new(bus); 410 uint8_t header_type; 443 411 444 412 for (dnum = 0; dnum < 32; dnum++) { 445 413 multi = true; 446 414 for (fnum = 0; multi && fnum < 8; fnum++) { 447 pci_fun_init(fun, bus_num, dnum, fnum);448 fun->vendor_id = pci_conf_read_16(fun,415 init_pci_dev_data(dev_data, bus_num, dnum, fnum); 416 dev_data->vendor_id = pci_conf_read_16(dev, 449 417 PCI_VENDOR_ID); 450 fun->device_id = pci_conf_read_16(fun,418 dev_data->device_id = pci_conf_read_16(dev, 451 419 PCI_DEVICE_ID); 452 if ( fun->vendor_id == 0xffff) {420 if (dev_data->vendor_id == 0xffff) { 453 421 /* 454 422 * The device is not present, go on scanning the … … 461 429 } 462 430 463 header_type = pci_conf_read_8( fun, PCI_HEADER_TYPE);431 header_type = pci_conf_read_8(dev, PCI_HEADER_TYPE); 464 432 if (fnum == 0) { 465 433 /* Is the device multifunction? */ … … 469 437 header_type = header_type & 0x7F; 470 438 471 char *fun_name = pci_fun_create_name(fun); 472 if (fun_name == NULL) { 473 printf(NAME ": out of memory.\n"); 474 return; 475 } 476 477 fnode = ddf_fun_create(bus->dnode, fun_inner, fun_name); 478 if (fnode == NULL) { 479 printf(NAME ": error creating function.\n"); 480 return; 481 } 482 483 free(fun_name); 484 fun->fnode = fnode; 485 486 pci_alloc_resource_list(fun); 487 pci_read_bars(fun); 488 pci_read_interrupt(fun); 489 490 fnode->ops = &pci_fun_ops; 491 fnode->driver_data = fun; 492 493 printf(NAME ": adding new function %s.\n", 494 fnode->name); 495 496 pci_fun_create_match_ids(fun); 497 498 if (ddf_fun_bind(fnode) != EOK) { 499 pci_clean_resource_list(fun); 500 clean_match_ids(&fnode->match_ids); 501 free((char *) fnode->name); 502 fnode->name = NULL; 439 create_pci_dev_name(dev); 440 441 pci_alloc_resource_list(dev); 442 pci_read_bars(dev); 443 pci_read_interrupt(dev); 444 445 dev->ops = &pci_child_ops; 446 447 printf(NAME ": adding new child device %s.\n", 448 dev->name); 449 450 create_pci_match_ids(dev); 451 452 if (child_device_register(dev, parent) != EOK) { 453 pci_clean_resource_list(dev); 454 clean_match_ids(&dev->match_ids); 455 free((char *) dev->name); 456 dev->name = NULL; 503 457 continue; 504 458 } … … 506 460 if (header_type == PCI_HEADER_TYPE_BRIDGE || 507 461 header_type == PCI_HEADER_TYPE_CARDBUS) { 508 child_bus = pci_conf_read_8( fun,462 child_bus = pci_conf_read_8(dev, 509 463 PCI_BRIDGE_SEC_BUS_NUM); 510 464 printf(NAME ": device is pci-to-pci bridge, " 511 465 "secondary bus number = %d.\n", bus_num); 512 466 if (child_bus > bus_num) 513 pci_bus_scan( bus, child_bus);467 pci_bus_scan(parent, child_bus); 514 468 } 515 469 516 fun = pci_fun_new(bus); 470 /* Alloc new aux. dev. structure. */ 471 dev = create_device(); 472 dev_data = create_pci_dev_data(); 473 dev->driver_data = dev_data; 474 dev->parent = parent; 517 475 } 518 476 } 519 477 520 if (fun->vendor_id == 0xffff) { 521 /* Free the auxiliary function structure. */ 522 pci_fun_delete(fun); 523 } 524 } 525 526 static int pci_add_device(ddf_dev_t *dnode) 527 { 528 pci_bus_t *bus = NULL; 529 ddf_fun_t *ctl = NULL; 530 bool got_res = false; 478 if (dev_data->vendor_id == 0xffff) { 479 delete_device(dev); 480 /* Free the auxiliary device structure. */ 481 delete_pci_dev_data(dev_data); 482 } 483 } 484 485 static int pci_add_device(device_t *dev) 486 { 531 487 int rc; 532 488 533 489 printf(NAME ": pci_add_device\n"); 534 dnode->parent_phone = -1; 535 536 bus = pci_bus_new(); 537 if (bus == NULL) { 490 491 pci_bus_data_t *bus_data = create_pci_bus_data(); 492 if (bus_data == NULL) { 538 493 printf(NAME ": pci_add_device allocation failed.\n"); 539 rc = ENOMEM; 540 goto fail; 541 } 542 bus->dnode = dnode; 543 dnode->driver_data = bus; 544 545 dnode->parent_phone = devman_parent_device_connect(dnode->handle, 494 return ENOMEM; 495 } 496 497 dev->parent_phone = devman_parent_device_connect(dev->handle, 546 498 IPC_FLAG_BLOCKING); 547 if (d node->parent_phone < 0) {499 if (dev->parent_phone < 0) { 548 500 printf(NAME ": pci_add_device failed to connect to the " 549 501 "parent's driver.\n"); 550 rc = dnode->parent_phone;551 goto fail;502 delete_pci_bus_data(bus_data); 503 return dev->parent_phone; 552 504 } 553 505 554 506 hw_resource_list_t hw_resources; 555 507 556 rc = hw_res_get_resource_list(d node->parent_phone, &hw_resources);508 rc = hw_res_get_resource_list(dev->parent_phone, &hw_resources); 557 509 if (rc != EOK) { 558 510 printf(NAME ": pci_add_device failed to get hw resources for " 559 511 "the device.\n"); 560 goto fail; 561 } 562 got_res = true; 512 delete_pci_bus_data(bus_data); 513 async_hangup(dev->parent_phone); 514 return rc; 515 } 563 516 564 517 printf(NAME ": conf_addr = %" PRIx64 ".\n", … … 569 522 assert(hw_resources.resources[0].res.io_range.size == 8); 570 523 571 bus ->conf_io_addr =524 bus_data->conf_io_addr = 572 525 (uint32_t) hw_resources.resources[0].res.io_range.address; 573 526 574 if (pio_enable((void *)(uintptr_t)bus ->conf_io_addr, 8,575 &bus ->conf_addr_port)) {527 if (pio_enable((void *)(uintptr_t)bus_data->conf_io_addr, 8, 528 &bus_data->conf_addr_port)) { 576 529 printf(NAME ": failed to enable configuration ports.\n"); 577 rc = EADDRNOTAVAIL; 578 goto fail; 579 } 580 bus->conf_data_port = (char *) bus->conf_addr_port + 4; 581 582 /* Make the bus device more visible. It has no use yet. */ 583 printf(NAME ": adding a 'ctl' function\n"); 584 585 ctl = ddf_fun_create(bus->dnode, fun_exposed, "ctl"); 586 if (ctl == NULL) { 587 printf(NAME ": error creating control function.\n"); 588 rc = ENOMEM; 589 goto fail; 590 } 591 592 rc = ddf_fun_bind(ctl); 593 if (rc != EOK) { 594 printf(NAME ": error binding control function.\n"); 595 goto fail; 596 } 597 598 /* Enumerate functions. */ 530 delete_pci_bus_data(bus_data); 531 async_hangup(dev->parent_phone); 532 hw_res_clean_resource_list(&hw_resources); 533 return EADDRNOTAVAIL; 534 } 535 bus_data->conf_data_port = (char *) bus_data->conf_addr_port + 4; 536 537 dev->driver_data = bus_data; 538 539 /* Enumerate child devices. */ 599 540 printf(NAME ": scanning the bus\n"); 600 pci_bus_scan( bus, 0);541 pci_bus_scan(dev, 0); 601 542 602 543 hw_res_clean_resource_list(&hw_resources); 603 544 604 545 return EOK; 605 606 fail:607 if (bus != NULL)608 pci_bus_delete(bus);609 if (dnode->parent_phone >= 0)610 async_hangup(dnode->parent_phone);611 if (got_res)612 hw_res_clean_resource_list(&hw_resources);613 if (ctl != NULL)614 ddf_fun_destroy(ctl);615 616 return rc;617 546 } 618 547 619 548 static void pciintel_init(void) 620 549 { 621 pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops; 622 pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops; 623 } 624 625 pci_fun_t *pci_fun_new(pci_bus_t *bus) 626 { 627 pci_fun_t *fun; 628 629 fun = (pci_fun_t *) calloc(1, sizeof(pci_fun_t)); 630 if (fun == NULL) 631 return NULL; 632 633 fun->busptr = bus; 634 return fun; 635 } 636 637 void pci_fun_init(pci_fun_t *fun, int bus, int dev, int fn) 638 { 639 fun->bus = bus; 640 fun->dev = dev; 641 fun->fn = fn; 642 } 643 644 void pci_fun_delete(pci_fun_t *fun) 645 { 646 assert(fun != NULL); 647 hw_res_clean_resource_list(&fun->hw_resources); 648 free(fun); 649 } 650 651 char *pci_fun_create_name(pci_fun_t *fun) 652 { 550 pci_child_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_child_hw_res_ops; 551 } 552 553 pci_dev_data_t *create_pci_dev_data(void) 554 { 555 pci_dev_data_t *res = (pci_dev_data_t *) malloc(sizeof(pci_dev_data_t)); 556 557 if (res != NULL) 558 memset(res, 0, sizeof(pci_dev_data_t)); 559 return res; 560 } 561 562 void init_pci_dev_data(pci_dev_data_t *dev_data, int bus, int dev, int fn) 563 { 564 dev_data->bus = bus; 565 dev_data->dev = dev; 566 dev_data->fn = fn; 567 } 568 569 void delete_pci_dev_data(pci_dev_data_t *dev_data) 570 { 571 if (dev_data != NULL) { 572 hw_res_clean_resource_list(&dev_data->hw_resources); 573 free(dev_data); 574 } 575 } 576 577 void create_pci_dev_name(device_t *dev) 578 { 579 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 653 580 char *name = NULL; 654 581 655 asprintf(&name, "%02x:%02x.%01x", fun->bus, fun->dev, 656 fun->fn); 657 return name; 658 } 659 660 bool pci_alloc_resource_list(pci_fun_t *fun) 661 { 662 fun->hw_resources.resources = 582 asprintf(&name, "%02x:%02x.%01x", dev_data->bus, dev_data->dev, 583 dev_data->fn); 584 dev->name = name; 585 } 586 587 bool pci_alloc_resource_list(device_t *dev) 588 { 589 pci_dev_data_t *dev_data = (pci_dev_data_t *)dev->driver_data; 590 591 dev_data->hw_resources.resources = 663 592 (hw_resource_t *) malloc(PCI_MAX_HW_RES * sizeof(hw_resource_t)); 664 return fun->hw_resources.resources != NULL; 665 } 666 667 void pci_clean_resource_list(pci_fun_t *fun) 668 { 669 if (fun->hw_resources.resources != NULL) { 670 free(fun->hw_resources.resources); 671 fun->hw_resources.resources = NULL; 672 } 673 } 674 675 /** Read the base address registers (BARs) of the function and add the addresses 676 * to its HW resource list. 593 return dev_data->hw_resources.resources != NULL; 594 } 595 596 void pci_clean_resource_list(device_t *dev) 597 { 598 pci_dev_data_t *dev_data = (pci_dev_data_t *) dev->driver_data; 599 600 if (dev_data->hw_resources.resources != NULL) { 601 free(dev_data->hw_resources.resources); 602 dev_data->hw_resources.resources = NULL; 603 } 604 } 605 606 /** Read the base address registers (BARs) of the device and adds the addresses 607 * to its hw resource list. 677 608 * 678 * @param fun PCI function609 * @param dev the pci device. 679 610 */ 680 void pci_read_bars( pci_fun_t *fun)611 void pci_read_bars(device_t *dev) 681 612 { 682 613 /* … … 687 618 688 619 while (addr <= PCI_BASE_ADDR_5) 689 addr = pci_read_bar( fun, addr);620 addr = pci_read_bar(dev, addr); 690 621 } 691 622 692 623 size_t pci_bar_mask_to_size(uint32_t mask) 693 624 { 694 size_t size = mask & ~(mask - 1); 695 return size; 625 return ((mask & 0xfffffff0) ^ 0xffffffff) + 1; 696 626 } 697 627 … … 700 630 printf(NAME ": HelenOS pci bus driver (intel method 1).\n"); 701 631 pciintel_init(); 702 return d df_driver_main(&pci_driver);632 return driver_main(&pci_driver); 703 633 } 704 634
Note:
See TracChangeset
for help on using the changeset viewer.