Changes in uspace/drv/bus/pci/pciintel/pci.c [267f235:ebc9c2c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/pci/pciintel/pci.c
r267f235 rebc9c2c 41 41 #include <stdio.h> 42 42 #include <errno.h> 43 #include < bool.h>43 #include <stdbool.h> 44 44 #include <fibril_synch.h> 45 45 #include <str.h> … … 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 #include <libarch/ddi.h>61 59 #include <pci_dev_iface.h> 62 60 … … 105 103 assert(fnode); 106 104 pci_fun_t *dev_data = pci_fun(fnode); 107 108 sysarg_t apic;109 sysarg_t i8259;110 111 async_sess_t *irc_sess = NULL;112 113 if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))114 || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) {115 irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,116 SERVICE_IRC, 0, 0);117 }118 119 if (!irc_sess)120 return false;121 105 122 106 size_t i = 0; … … 124 108 for (; i < res->count; i++) { 125 109 if (res->resources[i].type == INTERRUPT) { 126 const int irq = res->resources[i].res.interrupt.irq; 127 128 async_exch_t *exch = async_exchange_begin(irc_sess); 129 const int rc = 130 async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq); 131 async_exchange_end(exch); 132 133 if (rc != EOK) { 134 async_hangup(irc_sess); 110 int rc = irc_enable_interrupt( 111 res->resources[i].res.interrupt.irq); 112 113 if (rc != EOK) 135 114 return false; 136 }137 115 } 138 116 } 139 117 140 async_hangup(irc_sess);141 118 return true; 142 119 } 143 120 144 static int pci_config_space_write_32(ddf_fun_t *fun, uint32_t address, 121 static pio_window_t *pciintel_get_pio_window(ddf_fun_t *fnode) 122 { 123 pci_fun_t *fun = pci_fun(fnode); 124 125 if (fun == NULL) 126 return NULL; 127 return &fun->pio_window; 128 } 129 130 131 static int config_space_write_32(ddf_fun_t *fun, uint32_t address, 145 132 uint32_t data) 146 133 { … … 151 138 } 152 139 153 static int pci_config_space_write_16(140 static int config_space_write_16( 154 141 ddf_fun_t *fun, uint32_t address, uint16_t data) 155 142 { … … 160 147 } 161 148 162 static int pci_config_space_write_8(149 static int config_space_write_8( 163 150 ddf_fun_t *fun, uint32_t address, uint8_t data) 164 151 { … … 169 156 } 170 157 171 static int pci_config_space_read_32(158 static int config_space_read_32( 172 159 ddf_fun_t *fun, uint32_t address, uint32_t *data) 173 160 { … … 178 165 } 179 166 180 static int pci_config_space_read_16(167 static int config_space_read_16( 181 168 ddf_fun_t *fun, uint32_t address, uint16_t *data) 182 169 { … … 187 174 } 188 175 189 static int pci_config_space_read_8(176 static int config_space_read_8( 190 177 ddf_fun_t *fun, uint32_t address, uint8_t *data) 191 178 { … … 201 188 }; 202 189 190 static pio_window_ops_t pciintel_pio_window_ops = { 191 .get_pio_window = &pciintel_get_pio_window 192 }; 193 203 194 static pci_dev_iface_t pci_dev_ops = { 204 .config_space_read_8 = & pci_config_space_read_8,205 .config_space_read_16 = & pci_config_space_read_16,206 .config_space_read_32 = & pci_config_space_read_32,207 .config_space_write_8 = & pci_config_space_write_8,208 .config_space_write_16 = & pci_config_space_write_16,209 .config_space_write_32 = & pci_config_space_write_32195 .config_space_read_8 = &config_space_read_8, 196 .config_space_read_16 = &config_space_read_16, 197 .config_space_read_32 = &config_space_read_32, 198 .config_space_write_8 = &config_space_write_8, 199 .config_space_write_16 = &config_space_write_16, 200 .config_space_write_32 = &config_space_write_32 210 201 }; 211 202 212 203 static ddf_dev_ops_t pci_fun_ops = { 213 204 .interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops, 205 .interfaces[PIO_WINDOW_DEV_IFACE] = &pciintel_pio_window_ops, 214 206 .interfaces[PCI_DEV_IFACE] = &pci_dev_ops 215 207 }; … … 234 226 static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len) 235 227 { 228 const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg); 236 229 pci_bus_t *bus = pci_bus_from_fun(fun); 230 uint32_t val; 237 231 238 232 fibril_mutex_lock(&bus->conf_mutex); 239 240 const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg); 241 void *addr = bus->conf_data_port + (reg & 3); 242 243 pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr)); 244 233 234 pio_write_32(bus->conf_addr_reg, host2uint32_t_le(conf_addr)); 235 236 /* 237 * Always read full 32-bits from the PCI conf_data_port register and 238 * get the desired portion of it afterwards. Some architectures do not 239 * support shorter PIO reads offset from this register. 240 */ 241 val = uint32_t_le2host(pio_read_32(bus->conf_data_reg)); 242 245 243 switch (len) { 246 244 case 1: 247 /* No endianness change for 1 byte */ 248 buf[0] = pio_read_8(addr); 245 *buf = (uint8_t) (val >> ((reg & 3) * 8)); 249 246 break; 250 247 case 2: 251 ((uint16_t *) buf)[0] = uint16_t_le2host(pio_read_16(addr));248 *((uint16_t *) buf) = (uint16_t) (val >> ((reg & 3)) * 8); 252 249 break; 253 250 case 4: 254 ((uint32_t *) buf)[0] = uint32_t_le2host(pio_read_32(addr));251 *((uint32_t *) buf) = (uint32_t) val; 255 252 break; 256 253 } … … 261 258 static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len) 262 259 { 260 const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg); 263 261 pci_bus_t *bus = pci_bus_from_fun(fun); 262 uint32_t val = 0; // Prevent -Werror=maybe-uninitialized 264 263 265 264 fibril_mutex_lock(&bus->conf_mutex); 266 267 const uint32_t conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg); 268 void *addr = bus->conf_data_port + (reg & 3); 269 270 pio_write_32(bus->conf_addr_port, host2uint32_t_le(conf_addr)); 265 266 /* 267 * Prepare to write full 32-bits to the PCI conf_data_port register. 268 * Some architectures do not support shorter PIO writes offset from this 269 * register. 270 */ 271 272 if (len < 4) { 273 /* 274 * We have fewer than full 32-bits, so we need to read the 275 * missing bits first. 276 */ 277 pio_write_32(bus->conf_addr_reg, host2uint32_t_le(conf_addr)); 278 val = uint32_t_le2host(pio_read_32(bus->conf_data_reg)); 279 } 271 280 272 281 switch (len) { 273 282 case 1: 274 /* No endianness change for 1 byte */275 pio_write_8(addr, buf[0]);283 val &= ~(0xffU << ((reg & 3) * 8)); 284 val |= *buf << ((reg & 3) * 8); 276 285 break; 277 286 case 2: 278 pio_write_16(addr, host2uint16_t_le(((uint16_t *) buf)[0])); 287 val &= ~(0xffffU << ((reg & 3) * 8)); 288 val |= *((uint16_t *) buf) << ((reg & 3) * 8); 279 289 break; 280 290 case 4: 281 pio_write_32(addr, host2uint32_t_le(((uint32_t *) buf)[0]));291 val = *((uint32_t *) buf); 282 292 break; 283 293 } 294 295 pio_write_32(bus->conf_addr_reg, host2uint32_t_le(conf_addr)); 296 pio_write_32(bus->conf_data_reg, host2uint32_t_le(val)); 284 297 285 298 fibril_mutex_unlock(&bus->conf_mutex); … … 328 341 329 342 /* Vendor ID & Device ID, length(incl \0) 22 */ 330 rc = snprintf(match_id_str, ID_MAX_STR_LEN, "pci/ven=%04 x&dev=%04x",331 fun->vendor_id, fun->device_id);343 rc = snprintf(match_id_str, ID_MAX_STR_LEN, "pci/ven=%04" 344 PRIx16 "&dev=%04" PRIx16, fun->vendor_id, fun->device_id); 332 345 if (rc < 0) { 333 346 ddf_msg(LVL_ERROR, "Failed creating match ID str: %s", … … 412 425 hw_resources[count].res.io_range.address = range_addr; 413 426 hw_resources[count].res.io_range.size = range_size; 427 hw_resources[count].res.io_range.relative = true; 414 428 hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN; 415 429 } else { … … 417 431 hw_resources[count].res.mem_range.address = range_addr; 418 432 hw_resources[count].res.mem_range.size = range_size; 433 hw_resources[count].res.mem_range.relative = false; 419 434 hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN; 420 435 } … … 434 449 { 435 450 /* Value of the BAR */ 436 uint32_t val, mask; 451 uint32_t val; 452 uint32_t bar; 453 uint32_t mask; 454 437 455 /* IO space address */ 438 456 bool io; … … 472 490 /* Get the address mask. */ 473 491 pci_conf_write_32(fun, addr, 0xffffffff); 474 mask &= pci_conf_read_32(fun, addr); 475 492 bar = pci_conf_read_32(fun, addr); 493 494 /* 495 * Unimplemented BARs read back as all 0's. 496 */ 497 if (!bar) 498 return addr + (addrw64 ? 8 : 4); 499 500 mask &= bar; 501 476 502 /* Restore the original value. */ 477 503 pci_conf_write_32(fun, addr, val); … … 521 547 { 522 548 uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE); 523 if (irq != 0xff) 549 uint8_t pin = pci_conf_read_8(fun, PCI_BRIDGE_INT_PIN); 550 551 if (pin != 0 && irq != 0xff) 524 552 pci_add_interrupt(fun, irq); 525 553 } … … 584 612 pci_read_bars(fun); 585 613 pci_read_interrupt(fun); 614 615 /* Propagate the PIO window to the function. */ 616 fun->pio_window = bus->pio_win; 586 617 587 618 ddf_fun_set_ops(fun->fnode, &pci_fun_ops); … … 614 645 static int pci_dev_add(ddf_dev_t *dnode) 615 646 { 647 hw_resource_list_t hw_resources; 616 648 pci_bus_t *bus = NULL; 617 649 ddf_fun_t *ctl = NULL; … … 639 671 goto fail; 640 672 } 641 642 hw_resource_list_t hw_resources; 673 674 rc = pio_window_get(sess, &bus->pio_win); 675 if (rc != EOK) { 676 ddf_msg(LVL_ERROR, "pci_dev_add failed to get PIO window " 677 "for the device."); 678 goto fail; 679 } 643 680 644 681 rc = hw_res_get_resource_list(sess, &hw_resources); … … 663 700 hw_resources.resources[1].res.io_range.address); 664 701 665 bus->conf_io_addr = 666 (uint32_t) hw_resources.resources[0].res.io_range.address; 667 bus->conf_io_data = 668 (uint32_t) hw_resources.resources[1].res.io_range.address; 669 670 if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 4, 671 &bus->conf_addr_port)) { 702 if (pio_enable_resource(&bus->pio_win, &hw_resources.resources[0], 703 (void **) &bus->conf_addr_reg)) { 672 704 ddf_msg(LVL_ERROR, "Failed to enable configuration ports."); 673 705 rc = EADDRNOTAVAIL; 674 706 goto fail; 675 707 } 676 if (pio_enable ((void *)(uintptr_t)bus->conf_io_data, 4,677 &bus->conf_data_port)) {708 if (pio_enable_resource(&bus->pio_win, &hw_resources.resources[1], 709 (void **) &bus->conf_data_reg)) { 678 710 ddf_msg(LVL_ERROR, "Failed to enable configuration ports."); 679 711 rc = EADDRNOTAVAIL; … … 730 762 { 731 763 ddf_log_init(NAME); 732 pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;733 pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops;734 764 } 735 765 … … 759 789 fun->vendor_id = pci_conf_read_16(fun, PCI_VENDOR_ID); 760 790 fun->device_id = pci_conf_read_16(fun, PCI_DEVICE_ID); 791 792 /* Explicitly enable PCI bus mastering */ 793 fun->command = pci_conf_read_16(fun, PCI_COMMAND) | 794 PCI_COMMAND_MASTER; 795 pci_conf_write_16(fun, PCI_COMMAND, fun->command); 796 761 797 fun->class_code = pci_conf_read_8(fun, PCI_BASE_CLASS); 762 798 fun->subclass_code = pci_conf_read_8(fun, PCI_SUB_CLASS);
Note:
See TracChangeset
for help on using the changeset viewer.