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