Changes in uspace/drv/bus/pci/pciintel/pci.c [c90aed4:92d5279] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/pci/pciintel/pci.c
rc90aed4 r92d5279 51 51 #include <ddf/log.h> 52 52 #include <ipc/dev_iface.h> 53 #include <ipc/irc.h> 54 #include <ns.h> 55 #include <ipc/services.h> 56 #include <sysinfo.h> 53 #include <irc.h> 57 54 #include <ops/hw_res.h> 58 55 #include <device/hw_res.h> 56 #include <ops/pio_window.h> 57 #include <device/pio_window.h> 59 58 #include <ddi.h> 60 59 #include <pci_dev_iface.h> … … 64 63 #define NAME "pciintel" 65 64 65 #define CONF_ADDR_ENABLE (1 << 31) 66 66 #define CONF_ADDR(bus, dev, fn, reg) \ 67 (( 1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))67 ((bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) 68 68 69 69 /** Obtain PCI function soft-state from DDF function node */ … … 104 104 assert(fnode); 105 105 pci_fun_t *dev_data = pci_fun(fnode); 106 107 sysarg_t apic;108 sysarg_t i8259;109 110 async_sess_t *irc_sess = NULL;111 112 if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))113 || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) {114 irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,115 SERVICE_IRC, 0, 0);116 }117 118 if (!irc_sess)119 return false;120 106 121 107 size_t i = 0; … … 123 109 for (; i < res->count; i++) { 124 110 if (res->resources[i].type == INTERRUPT) { 125 const int irq = res->resources[i].res.interrupt.irq; 111 int rc = irc_enable_interrupt( 112 res->resources[i].res.interrupt.irq); 126 113 127 async_exch_t *exch = async_exchange_begin(irc_sess); 128 const int rc = 129 async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq); 130 async_exchange_end(exch); 131 132 if (rc != EOK) { 133 async_hangup(irc_sess); 114 if (rc != EOK) 134 115 return false; 135 }136 116 } 137 117 } 138 118 139 async_hangup(irc_sess);140 119 return true; 141 120 } 142 121 143 static int pci_config_space_write_32(ddf_fun_t *fun, uint32_t address, 122 static pio_window_t *pciintel_get_pio_window(ddf_fun_t *fnode) 123 { 124 pci_fun_t *fun = pci_fun(fnode); 125 126 if (fun == NULL) 127 return NULL; 128 return &fun->pio_window; 129 } 130 131 132 static int config_space_write_32(ddf_fun_t *fun, uint32_t address, 144 133 uint32_t data) 145 134 { … … 150 139 } 151 140 152 static int pci_config_space_write_16(141 static int config_space_write_16( 153 142 ddf_fun_t *fun, uint32_t address, uint16_t data) 154 143 { … … 159 148 } 160 149 161 static int pci_config_space_write_8(150 static int config_space_write_8( 162 151 ddf_fun_t *fun, uint32_t address, uint8_t data) 163 152 { … … 168 157 } 169 158 170 static int pci_config_space_read_32(159 static int config_space_read_32( 171 160 ddf_fun_t *fun, uint32_t address, uint32_t *data) 172 161 { … … 177 166 } 178 167 179 static int pci_config_space_read_16(168 static int config_space_read_16( 180 169 ddf_fun_t *fun, uint32_t address, uint16_t *data) 181 170 { … … 186 175 } 187 176 188 static int pci_config_space_read_8(177 static int config_space_read_8( 189 178 ddf_fun_t *fun, uint32_t address, uint8_t *data) 190 179 { … … 200 189 }; 201 190 191 static pio_window_ops_t pciintel_pio_window_ops = { 192 .get_pio_window = &pciintel_get_pio_window 193 }; 194 202 195 static pci_dev_iface_t pci_dev_ops = { 203 .config_space_read_8 = & pci_config_space_read_8,204 .config_space_read_16 = & pci_config_space_read_16,205 .config_space_read_32 = & pci_config_space_read_32,206 .config_space_write_8 = & pci_config_space_write_8,207 .config_space_write_16 = & pci_config_space_write_16,208 .config_space_write_32 = & pci_config_space_write_32196 .config_space_read_8 = &config_space_read_8, 197 .config_space_read_16 = &config_space_read_16, 198 .config_space_read_32 = &config_space_read_32, 199 .config_space_write_8 = &config_space_write_8, 200 .config_space_write_16 = &config_space_write_16, 201 .config_space_write_32 = &config_space_write_32 209 202 }; 210 203 211 204 static ddf_dev_ops_t pci_fun_ops = { 212 205 .interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops, 206 .interfaces[PIO_WINDOW_DEV_IFACE] = &pciintel_pio_window_ops, 213 207 .interfaces[PCI_DEV_IFACE] = &pci_dev_ops 214 208 }; … … 233 227 static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len) 234 228 { 229 const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg); 235 230 pci_bus_t *bus = pci_bus_from_fun(fun); 231 uint32_t val; 236 232 237 233 fibril_mutex_lock(&bus->conf_mutex); 238 239 const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg); 240 void *addr = bus->conf_data_port + (reg & 3); 241 242 pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr)); 243 234 235 if (bus->conf_addr_reg) { 236 pio_write_32(bus->conf_addr_reg, 237 host2uint32_t_le(CONF_ADDR_ENABLE | conf_addr)); 238 /* 239 * Always read full 32-bits from the PCI conf_data_port 240 * register and get the desired portion of it afterwards. Some 241 * architectures do not support shorter PIO reads offset from 242 * this register. 243 */ 244 val = uint32_t_le2host(pio_read_32(bus->conf_data_reg)); 245 } else { 246 val = uint32_t_le2host(pio_read_32( 247 &bus->conf_space[conf_addr / sizeof(ioport32_t)])); 248 } 249 244 250 switch (len) { 245 251 case 1: 246 /* No endianness change for 1 byte */ 247 buf[0] = pio_read_8(addr); 252 *buf = (uint8_t) (val >> ((reg & 3) * 8)); 248 253 break; 249 254 case 2: 250 ((uint16_t *) buf)[0] = uint16_t_le2host(pio_read_16(addr));255 *((uint16_t *) buf) = (uint16_t) (val >> ((reg & 3)) * 8); 251 256 break; 252 257 case 4: 253 ((uint32_t *) buf)[0] = uint32_t_le2host(pio_read_32(addr));258 *((uint32_t *) buf) = (uint32_t) val; 254 259 break; 255 260 } … … 260 265 static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len) 261 266 { 267 const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg); 262 268 pci_bus_t *bus = pci_bus_from_fun(fun); 269 uint32_t val; 263 270 264 271 fibril_mutex_lock(&bus->conf_mutex); 265 266 const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg); 267 void *addr = bus->conf_data_port + (reg & 3); 268 269 pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr)); 272 273 /* 274 * Prepare to write full 32-bits to the PCI conf_data_port register. 275 * Some architectures do not support shorter PIO writes offset from this 276 * register. 277 */ 278 279 if (len < 4) { 280 /* 281 * We have fewer than full 32-bits, so we need to read the 282 * missing bits first. 283 */ 284 if (bus->conf_addr_reg) { 285 pio_write_32(bus->conf_addr_reg, 286 host2uint32_t_le(CONF_ADDR_ENABLE | conf_addr)); 287 val = uint32_t_le2host(pio_read_32(bus->conf_data_reg)); 288 } else { 289 val = uint32_t_le2host(pio_read_32( 290 &bus->conf_space[conf_addr / sizeof(ioport32_t)])); 291 } 292 } 270 293 271 294 switch (len) { 272 295 case 1: 273 /* No endianness change for 1 byte */274 pio_write_8(addr, buf[0]);296 val &= ~(0xffU << ((reg & 3) * 8)); 297 val |= *buf << ((reg & 3) * 8); 275 298 break; 276 299 case 2: 277 pio_write_16(addr, host2uint16_t_le(((uint16_t *) buf)[0])); 300 val &= ~(0xffffU << ((reg & 3) * 8)); 301 val |= *((uint16_t *) buf) << ((reg & 3) * 8); 278 302 break; 279 303 case 4: 280 pio_write_32(addr, host2uint32_t_le(((uint32_t *) buf)[0]));304 val = *((uint32_t *) buf); 281 305 break; 306 } 307 308 if (bus->conf_addr_reg) { 309 pio_write_32(bus->conf_addr_reg, 310 host2uint32_t_le(CONF_ADDR_ENABLE | conf_addr)); 311 pio_write_32(bus->conf_data_reg, host2uint32_t_le(val)); 312 } else { 313 pio_write_32(&bus->conf_space[conf_addr / sizeof(ioport32_t)], 314 host2uint32_t_le(val)); 282 315 } 283 316 … … 411 444 hw_resources[count].res.io_range.address = range_addr; 412 445 hw_resources[count].res.io_range.size = range_size; 446 hw_resources[count].res.io_range.relative = true; 413 447 hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN; 414 448 } else { … … 416 450 hw_resources[count].res.mem_range.address = range_addr; 417 451 hw_resources[count].res.mem_range.size = range_size; 452 hw_resources[count].res.mem_range.relative = false; 418 453 hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN; 419 454 } … … 433 468 { 434 469 /* Value of the BAR */ 435 uint32_t val, mask; 470 uint32_t val; 471 uint32_t bar; 472 uint32_t mask; 473 436 474 /* IO space address */ 437 475 bool io; … … 471 509 /* Get the address mask. */ 472 510 pci_conf_write_32(fun, addr, 0xffffffff); 473 mask &= pci_conf_read_32(fun, addr); 474 511 bar = pci_conf_read_32(fun, addr); 512 513 /* 514 * Unimplemented BARs read back as all 0's. 515 */ 516 if (!bar) 517 return addr + (addrw64 ? 8 : 4); 518 519 mask &= bar; 520 475 521 /* Restore the original value. */ 476 522 pci_conf_write_32(fun, addr, val); … … 520 566 { 521 567 uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE); 522 if (irq != 0xff) 568 uint8_t pin = pci_conf_read_8(fun, PCI_BRIDGE_INT_PIN); 569 570 if (pin != 0 && irq != 0xff) 523 571 pci_add_interrupt(fun, irq); 524 572 } … … 583 631 pci_read_bars(fun); 584 632 pci_read_interrupt(fun); 633 634 /* Propagate the PIO window to the function. */ 635 fun->pio_window = bus->pio_win; 585 636 586 637 ddf_fun_set_ops(fun->fnode, &pci_fun_ops); … … 588 639 ddf_msg(LVL_DEBUG, "Adding new function %s.", 589 640 ddf_fun_get_name(fun->fnode)); 590 641 591 642 pci_fun_create_match_ids(fun); 592 643 … … 613 664 static int pci_dev_add(ddf_dev_t *dnode) 614 665 { 666 hw_resource_list_t hw_resources; 615 667 pci_bus_t *bus = NULL; 616 668 ddf_fun_t *ctl = NULL; … … 631 683 bus->dnode = dnode; 632 684 633 sess = ddf_dev_parent_sess_create(dnode , EXCHANGE_SERIALIZE);685 sess = ddf_dev_parent_sess_create(dnode); 634 686 if (sess == NULL) { 635 687 ddf_msg(LVL_ERROR, "pci_dev_add failed to connect to the " … … 638 690 goto fail; 639 691 } 640 641 hw_resource_list_t hw_resources; 692 693 rc = pio_window_get(sess, &bus->pio_win); 694 if (rc != EOK) { 695 ddf_msg(LVL_ERROR, "pci_dev_add failed to get PIO window " 696 "for the device."); 697 goto fail; 698 } 642 699 643 700 rc = hw_res_get_resource_list(sess, &hw_resources); … … 650 707 651 708 652 assert(hw_resources.count > 1); 653 assert(hw_resources.resources[0].type == IO_RANGE); 654 assert(hw_resources.resources[0].res.io_range.size >= 4); 655 656 assert(hw_resources.resources[1].type == IO_RANGE); 657 assert(hw_resources.resources[1].res.io_range.size >= 4); 658 659 ddf_msg(LVL_DEBUG, "conf_addr = %" PRIx64 ".", 660 hw_resources.resources[0].res.io_range.address); 661 ddf_msg(LVL_DEBUG, "data_addr = %" PRIx64 ".", 662 hw_resources.resources[1].res.io_range.address); 663 664 bus->conf_io_addr = 665 (uint32_t) hw_resources.resources[0].res.io_range.address; 666 bus->conf_io_data = 667 (uint32_t) hw_resources.resources[1].res.io_range.address; 668 669 if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 4, 670 &bus->conf_addr_port)) { 671 ddf_msg(LVL_ERROR, "Failed to enable configuration ports."); 672 rc = EADDRNOTAVAIL; 673 goto fail; 674 } 675 if (pio_enable((void *)(uintptr_t)bus->conf_io_data, 4, 676 &bus->conf_data_port)) { 677 ddf_msg(LVL_ERROR, "Failed to enable configuration ports."); 678 rc = EADDRNOTAVAIL; 679 goto fail; 709 assert(hw_resources.count >= 1); 710 711 if (hw_resources.count == 1) { 712 assert(hw_resources.resources[0].type == MEM_RANGE); 713 714 ddf_msg(LVL_DEBUG, "conf_addr_space = %" PRIx64 ".", 715 hw_resources.resources[0].res.mem_range.address); 716 717 if (pio_enable_resource(&bus->pio_win, 718 &hw_resources.resources[0], 719 (void **) &bus->conf_space)) { 720 ddf_msg(LVL_ERROR, 721 "Failed to map configuration space."); 722 rc = EADDRNOTAVAIL; 723 goto fail; 724 } 725 726 } else { 727 assert(hw_resources.resources[0].type == IO_RANGE); 728 assert(hw_resources.resources[0].res.io_range.size >= 4); 729 730 assert(hw_resources.resources[1].type == IO_RANGE); 731 assert(hw_resources.resources[1].res.io_range.size >= 4); 732 733 ddf_msg(LVL_DEBUG, "conf_addr = %" PRIx64 ".", 734 hw_resources.resources[0].res.io_range.address); 735 ddf_msg(LVL_DEBUG, "data_addr = %" PRIx64 ".", 736 hw_resources.resources[1].res.io_range.address); 737 738 if (pio_enable_resource(&bus->pio_win, 739 &hw_resources.resources[0], 740 (void **) &bus->conf_addr_reg)) { 741 ddf_msg(LVL_ERROR, 742 "Failed to enable configuration ports."); 743 rc = EADDRNOTAVAIL; 744 goto fail; 745 } 746 if (pio_enable_resource(&bus->pio_win, 747 &hw_resources.resources[1], 748 (void **) &bus->conf_data_reg)) { 749 ddf_msg(LVL_ERROR, 750 "Failed to enable configuration ports."); 751 rc = EADDRNOTAVAIL; 752 goto fail; 753 } 680 754 } 681 755 … … 729 803 { 730 804 ddf_log_init(NAME); 731 pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;732 pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops;733 805 } 734 806
Note:
See TracChangeset
for help on using the changeset viewer.