Changes in uspace/drv/bus/pci/pciintel/pci.c [92d5279:c90aed4] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/pci/pciintel/pci.c
r92d5279 rc90aed4 51 51 #include <ddf/log.h> 52 52 #include <ipc/dev_iface.h> 53 #include <irc.h> 53 #include <ipc/irc.h> 54 #include <ns.h> 55 #include <ipc/services.h> 56 #include <sysinfo.h> 54 57 #include <ops/hw_res.h> 55 58 #include <device/hw_res.h> 56 #include <ops/pio_window.h>57 #include <device/pio_window.h>58 59 #include <ddi.h> 59 60 #include <pci_dev_iface.h> … … 63 64 #define NAME "pciintel" 64 65 65 #define CONF_ADDR_ENABLE (1 << 31)66 66 #define CONF_ADDR(bus, dev, fn, reg) \ 67 (( bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))67 ((1 << 31) | (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; 106 120 107 121 size_t i = 0; … … 109 123 for (; i < res->count; i++) { 110 124 if (res->resources[i].type == INTERRUPT) { 111 int rc = irc_enable_interrupt( 112 res->resources[i].res.interrupt.irq); 113 114 if (rc != EOK) 125 const int irq = res->resources[i].res.interrupt.irq; 126 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); 115 134 return false; 135 } 116 136 } 117 137 } 118 138 139 async_hangup(irc_sess); 119 140 return true; 120 141 } 121 142 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, 143 static int pci_config_space_write_32(ddf_fun_t *fun, uint32_t address, 133 144 uint32_t data) 134 145 { … … 139 150 } 140 151 141 static int config_space_write_16(152 static int pci_config_space_write_16( 142 153 ddf_fun_t *fun, uint32_t address, uint16_t data) 143 154 { … … 148 159 } 149 160 150 static int config_space_write_8(161 static int pci_config_space_write_8( 151 162 ddf_fun_t *fun, uint32_t address, uint8_t data) 152 163 { … … 157 168 } 158 169 159 static int config_space_read_32(170 static int pci_config_space_read_32( 160 171 ddf_fun_t *fun, uint32_t address, uint32_t *data) 161 172 { … … 166 177 } 167 178 168 static int config_space_read_16(179 static int pci_config_space_read_16( 169 180 ddf_fun_t *fun, uint32_t address, uint16_t *data) 170 181 { … … 175 186 } 176 187 177 static int config_space_read_8(188 static int pci_config_space_read_8( 178 189 ddf_fun_t *fun, uint32_t address, uint8_t *data) 179 190 { … … 189 200 }; 190 201 191 static pio_window_ops_t pciintel_pio_window_ops = {192 .get_pio_window = &pciintel_get_pio_window193 };194 195 202 static pci_dev_iface_t pci_dev_ops = { 196 .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_32203 .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_32 202 209 }; 203 210 204 211 static ddf_dev_ops_t pci_fun_ops = { 205 212 .interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops, 206 .interfaces[PIO_WINDOW_DEV_IFACE] = &pciintel_pio_window_ops,207 213 .interfaces[PCI_DEV_IFACE] = &pci_dev_ops 208 214 }; … … 227 233 static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len) 228 234 { 235 pci_bus_t *bus = pci_bus_from_fun(fun); 236 237 fibril_mutex_lock(&bus->conf_mutex); 238 229 239 const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg); 230 pci_bus_t *bus = pci_bus_from_fun(fun); 231 uint32_t val; 232 233 fibril_mutex_lock(&bus->conf_mutex); 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 240 void *addr = bus->conf_data_port + (reg & 3); 241 242 pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr)); 243 250 244 switch (len) { 251 245 case 1: 252 *buf = (uint8_t) (val >> ((reg & 3) * 8)); 246 /* No endianness change for 1 byte */ 247 buf[0] = pio_read_8(addr); 253 248 break; 254 249 case 2: 255 *((uint16_t *) buf) = (uint16_t) (val >> ((reg & 3)) * 8);250 ((uint16_t *) buf)[0] = uint16_t_le2host(pio_read_16(addr)); 256 251 break; 257 252 case 4: 258 *((uint32_t *) buf) = (uint32_t) val;253 ((uint32_t *) buf)[0] = uint32_t_le2host(pio_read_32(addr)); 259 254 break; 260 255 } … … 265 260 static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len) 266 261 { 262 pci_bus_t *bus = pci_bus_from_fun(fun); 263 264 fibril_mutex_lock(&bus->conf_mutex); 265 267 266 const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg); 268 pci_bus_t *bus = pci_bus_from_fun(fun); 269 uint32_t val; 270 271 fibril_mutex_lock(&bus->conf_mutex); 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 } 267 void *addr = bus->conf_data_port + (reg & 3); 268 269 pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr)); 293 270 294 271 switch (len) { 295 272 case 1: 296 val &= ~(0xffU << ((reg & 3) * 8));297 val |= *buf << ((reg & 3) * 8);273 /* No endianness change for 1 byte */ 274 pio_write_8(addr, buf[0]); 298 275 break; 299 276 case 2: 300 val &= ~(0xffffU << ((reg & 3) * 8)); 301 val |= *((uint16_t *) buf) << ((reg & 3) * 8); 277 pio_write_16(addr, host2uint16_t_le(((uint16_t *) buf)[0])); 302 278 break; 303 279 case 4: 304 val = *((uint32_t *) buf);280 pio_write_32(addr, host2uint32_t_le(((uint32_t *) buf)[0])); 305 281 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));315 282 } 316 283 … … 444 411 hw_resources[count].res.io_range.address = range_addr; 445 412 hw_resources[count].res.io_range.size = range_size; 446 hw_resources[count].res.io_range.relative = true;447 413 hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN; 448 414 } else { … … 450 416 hw_resources[count].res.mem_range.address = range_addr; 451 417 hw_resources[count].res.mem_range.size = range_size; 452 hw_resources[count].res.mem_range.relative = false;453 418 hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN; 454 419 } … … 468 433 { 469 434 /* Value of the BAR */ 470 uint32_t val; 471 uint32_t bar; 472 uint32_t mask; 473 435 uint32_t val, mask; 474 436 /* IO space address */ 475 437 bool io; … … 509 471 /* Get the address mask. */ 510 472 pci_conf_write_32(fun, addr, 0xffffffff); 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 473 mask &= pci_conf_read_32(fun, addr); 474 521 475 /* Restore the original value. */ 522 476 pci_conf_write_32(fun, addr, val); … … 566 520 { 567 521 uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE); 568 uint8_t pin = pci_conf_read_8(fun, PCI_BRIDGE_INT_PIN); 569 570 if (pin != 0 && irq != 0xff) 522 if (irq != 0xff) 571 523 pci_add_interrupt(fun, irq); 572 524 } … … 631 583 pci_read_bars(fun); 632 584 pci_read_interrupt(fun); 633 634 /* Propagate the PIO window to the function. */635 fun->pio_window = bus->pio_win;636 585 637 586 ddf_fun_set_ops(fun->fnode, &pci_fun_ops); … … 639 588 ddf_msg(LVL_DEBUG, "Adding new function %s.", 640 589 ddf_fun_get_name(fun->fnode)); 641 590 642 591 pci_fun_create_match_ids(fun); 643 592 … … 664 613 static int pci_dev_add(ddf_dev_t *dnode) 665 614 { 666 hw_resource_list_t hw_resources;667 615 pci_bus_t *bus = NULL; 668 616 ddf_fun_t *ctl = NULL; … … 683 631 bus->dnode = dnode; 684 632 685 sess = ddf_dev_parent_sess_create(dnode );633 sess = ddf_dev_parent_sess_create(dnode, EXCHANGE_SERIALIZE); 686 634 if (sess == NULL) { 687 635 ddf_msg(LVL_ERROR, "pci_dev_add failed to connect to the " … … 690 638 goto fail; 691 639 } 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 } 640 641 hw_resource_list_t hw_resources; 699 642 700 643 rc = hw_res_get_resource_list(sess, &hw_resources); … … 707 650 708 651 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 } 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; 754 680 } 755 681 … … 803 729 { 804 730 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; 805 733 } 806 734
Note:
See TracChangeset
for help on using the changeset viewer.