netbsd_pci.c revision 6c7645b9
1/* 2 * Copyright (c) 2008 Juan Romero Pardines 3 * Copyright (c) 2008 Mark Kettenis 4 * Copyright (c) 2009 Michael Lorenz 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/param.h> 20#include <sys/ioctl.h> 21#include <sys/mman.h> 22#include <sys/types.h> 23 24#ifdef HAVE_MTRR 25#include <machine/sysarch.h> 26#include <machine/mtrr.h> 27#define netbsd_set_mtrr(mr, num) _X86_SYSARCH_L(set_mtrr)(mr, num) 28#endif 29 30#include <dev/pci/pcidevs.h> 31#include <dev/pci/pciio.h> 32#include <dev/pci/pcireg.h> 33 34#include <errno.h> 35#include <fcntl.h> 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <unistd.h> 40 41 42#include <pci.h> 43 44#include "pciaccess.h" 45#include "pciaccess_private.h" 46 47typedef struct _pcibus { 48 int fd; /* /dev/pci* */ 49 int num; /* bus number */ 50 int maxdevs; /* maximum number of devices */ 51} PciBus; 52 53static PciBus buses[32]; /* indexed by pci_device.domain */ 54static int nbuses = 0; /* number of buses found */ 55 56/* 57 * NetBSD's userland has a /dev/pci* entry for each bus but userland has no way 58 * to tell if a bus is a subordinate of another one or if it's on a different 59 * host bridge. On some architectures ( macppc for example ) all root buses have 60 * bus number 0 but on sparc64 for example the two roots in an Ultra60 have 61 * different bus numbers - one is 0 and the other 128. 62 * With each /dev/pci* we can map everything on the same root and we can also 63 * see all devices on the same root, trying to do that causes problems though: 64 * - since we can't tell which /dev/pci* is a subordinate we would find some 65 * devices more than once 66 * - we would have to guess subordinate bus numbers which is a waste of time 67 * since we can ask each /dev/pci* for its bus number so we can scan only the 68 * buses we know exist, not all 256 which may exist in each domain. 69 * - some bus_space_mmap() methods may limit mappings to address ranges which 70 * belong to known devices on that bus only. 71 * Each host bridge may or may not have its own IO range, to avoid guesswork 72 * here each /dev/pci* will let userland map its appropriate IO range at 73 * PCI_MAGIC_IO_RANGE if defined in <machine/param.h> 74 * With all this we should be able to use any PCI graphics device on any PCI 75 * bus on any architecture as long as Xorg has a driver, without allowing 76 * arbitrary mappings via /dev/mem and without userland having to know or care 77 * about translating bus addresses to physical addresses or the other way 78 * around. 79 */ 80 81static int 82pci_read(int domain, int bus, int dev, int func, uint32_t reg, uint32_t *val) 83{ 84 uint32_t rval; 85 86 if ((domain < 0) || (domain > nbuses)) 87 return -1; 88 89 if (pcibus_conf_read(buses[domain].fd, (unsigned int)bus, 90 (unsigned int)dev, (unsigned int)func, reg, &rval) == -1) 91 return (-1); 92 93 *val = rval; 94 95 return 0; 96} 97 98static int 99pci_write(int domain, int bus, int dev, int func, uint32_t reg, uint32_t val) 100{ 101 102 if ((domain < 0) || (domain > nbuses)) 103 return -1; 104 105 return pcibus_conf_write(buses[domain].fd, (unsigned int)bus, 106 (unsigned int)dev, (unsigned int)func, reg, val); 107} 108 109static int 110pci_nfuncs(int domain, int bus, int dev) 111{ 112 uint32_t hdr; 113 114 if ((domain < 0) || (domain > nbuses)) 115 return -1; 116 117 if (pci_read(domain, bus, dev, 0, PCI_BHLC_REG, &hdr) != 0) 118 return -1; 119 120 return (PCI_HDRTYPE_MULTIFN(hdr) ? 8 : 1); 121} 122 123/*ARGSUSED*/ 124static int 125pci_device_netbsd_map_range(struct pci_device *dev, 126 struct pci_device_mapping *map) 127{ 128#ifdef HAVE_MTRR 129 struct mtrr m; 130 int n = 1; 131#endif 132 int prot, ret = 0; 133 134 prot = PROT_READ; 135 136 if (map->flags & PCI_DEV_MAP_FLAG_WRITABLE) 137 prot |= PROT_WRITE; 138 map->memory = mmap(NULL, map->size, prot, MAP_SHARED, 139 buses[dev->domain].fd, (off_t)map->base); 140 if (map->memory == MAP_FAILED) 141 return errno; 142 143#ifdef HAVE_MTRR 144 memset(&m, 0, sizeof(m)); 145 146 /* No need to set an MTRR if it's the default mode. */ 147 if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) || 148 (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) { 149 m.base = base; 150 m.flags = MTRR_VALID | MTRR_PRIVATE; 151 m.len = size; 152 m.owner = getpid(); 153 if (map->flags & PCI_DEV_MAP_FLAG_CACHEABLE) 154 m.type = MTRR_TYPE_WB; 155 if (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE) 156 m.type = MTRR_TYPE_WC; 157 158 if ((netbsd_set_mtrr(&m, &n)) == -1) 159 ret = errno; 160 } 161#endif 162 163 return ret; 164} 165 166static int 167pci_device_netbsd_unmap_range(struct pci_device *dev, 168 struct pci_device_mapping *map) 169{ 170#ifdef HAVE_MTRR 171 struct mtrr m; 172 int n = 1; 173 174 memset(&m, 0, sizeof(m)); 175 176 if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) || 177 (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) { 178 m.base = map->base; 179 m.flags = 0; 180 m.len = size; 181 m.type = MTRR_TYPE_UC; 182 (void)netbsd_set_mtrr(&m, &n); 183 } 184#endif 185 186 return pci_device_generic_unmap_range(dev, map); 187} 188 189static int 190pci_device_netbsd_read(struct pci_device *dev, void *data, 191 pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_read) 192{ 193 u_int reg, rval; 194 195 *bytes_read = 0; 196 while (size > 0) { 197 size_t toread = MIN(size, 4 - (offset & 0x3)); 198 199 reg = (u_int)(offset & ~0x3); 200 201 if ((pcibus_conf_read(buses[dev->domain].fd, 202 (unsigned int)dev->bus, (unsigned int)dev->dev, 203 (unsigned int)dev->func, reg, &rval)) == -1) 204 return errno; 205 206 rval = htole32(rval); 207 rval >>= ((offset & 0x3) * 8); 208 209 memcpy(data, &rval, toread); 210 211 offset += toread; 212 data = (char *)data + toread; 213 size -= toread; 214 *bytes_read += toread; 215 } 216 217 return 0; 218} 219 220static int 221pci_device_netbsd_write(struct pci_device *dev, const void *data, 222 pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_written) 223{ 224 u_int reg, val; 225 226 if ((offset % 4) != 0 || (size % 4) != 0) 227 return EINVAL; 228 229 *bytes_written = 0; 230 while (size > 0) { 231 reg = (u_int)offset; 232 memcpy(&val, data, 4); 233 234 if ((pcibus_conf_write(buses[dev->domain].fd, 235 (unsigned int)dev->bus, (unsigned int)dev->dev, 236 (unsigned int)dev->func, reg, val)) == -1) 237 return errno; 238 239 offset += 4; 240 data = (const char *)data + 4; 241 size -= 4; 242 *bytes_written += 4; 243 } 244 245 return 0; 246} 247 248static void 249pci_system_netbsd_destroy(void) 250{ 251 int i; 252 253 for (i = 0; i < nbuses; i++) { 254 close(buses[i].fd); 255 } 256 free(pci_sys); 257 pci_sys = NULL; 258} 259 260static int 261pci_device_netbsd_probe(struct pci_device *device) 262{ 263 struct pci_device_private *priv = 264 (struct pci_device_private *)(void *)device; 265 struct pci_mem_region *region; 266 uint64_t reg64, size64; 267 uint32_t bar, reg, size; 268 int bus, dev, func, err, domain; 269 270 domain = device->domain; 271 bus = device->bus; 272 dev = device->dev; 273 func = device->func; 274 275 /* Enable the device if necessary */ 276 err = pci_read(domain, bus, dev, func, PCI_COMMAND_STATUS_REG, ®); 277 if (err) 278 return err; 279 if ((reg & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE)) != 280 (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE)) { 281 reg |= PCI_COMMAND_IO_ENABLE | 282 PCI_COMMAND_MEM_ENABLE | 283 PCI_COMMAND_MASTER_ENABLE; 284 err = pci_write(domain, bus, dev, func, PCI_COMMAND_STATUS_REG, 285 reg); 286 if (err) 287 return err; 288 } 289 290 err = pci_read(domain, bus, dev, func, PCI_BHLC_REG, ®); 291 if (err) 292 return err; 293 294 priv->header_type = PCI_HDRTYPE_TYPE(reg); 295 if (priv->header_type != 0) 296 return 0; 297 298 region = device->regions; 299 for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; 300 bar += sizeof(uint32_t), region++) { 301 err = pci_read(domain, bus, dev, func, bar, ®); 302 if (err) 303 return err; 304 305 /* Probe the size of the region. */ 306 err = pci_write(domain, bus, dev, func, bar, (unsigned int)~0); 307 if (err) 308 return err; 309 pci_read(domain, bus, dev, func, bar, &size); 310 pci_write(domain, bus, dev, func, bar, reg); 311 312 if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO) { 313 region->is_IO = 1; 314 region->base_addr = PCI_MAPREG_IO_ADDR(reg); 315 region->size = PCI_MAPREG_IO_SIZE(size); 316 } else { 317 if (PCI_MAPREG_MEM_PREFETCHABLE(reg)) 318 region->is_prefetchable = 1; 319 switch(PCI_MAPREG_MEM_TYPE(reg)) { 320 case PCI_MAPREG_MEM_TYPE_32BIT: 321 case PCI_MAPREG_MEM_TYPE_32BIT_1M: 322 region->base_addr = PCI_MAPREG_MEM_ADDR(reg); 323 region->size = PCI_MAPREG_MEM_SIZE(size); 324 break; 325 case PCI_MAPREG_MEM_TYPE_64BIT: 326 region->is_64 = 1; 327 328 reg64 = reg; 329 size64 = size; 330 331 bar += sizeof(uint32_t); 332 333 err = pci_read(domain, bus, dev, func, bar, ®); 334 if (err) 335 return err; 336 reg64 |= (uint64_t)reg << 32; 337 338 err = pci_write(domain, bus, dev, func, bar, 339 (unsigned int)~0); 340 if (err) 341 return err; 342 pci_read(domain, bus, dev, func, bar, &size); 343 pci_write(domain, bus, dev, func, bar, 344 (unsigned int)(reg64 >> 32)); 345 size64 |= (uint64_t)size << 32; 346 347 region->base_addr = 348 (unsigned long)PCI_MAPREG_MEM64_ADDR(reg64); 349 region->size = 350 (unsigned long)PCI_MAPREG_MEM64_SIZE(size64); 351 region++; 352 break; 353 } 354 } 355 } 356 357 return 0; 358} 359 360/** 361 * Read a VGA rom using the 0xc0000 mapping. 362 * 363 * This function should be extended to handle access through PCI resources, 364 * which should be more reliable when available. 365 */ 366static int 367pci_device_netbsd_read_rom(struct pci_device *dev, void *buffer) 368{ 369 struct pci_device_private *priv = (struct pci_device_private *)(void *)dev; 370 void *bios; 371 pciaddr_t rom_base; 372 size_t rom_size; 373 uint32_t bios_val, command_val; 374 int pci_rom, memfd; 375 376 if (((priv->base.device_class >> 16) & 0xff) != PCI_CLASS_DISPLAY || 377 ((priv->base.device_class >> 8) & 0xff) != PCI_SUBCLASS_DISPLAY_VGA) 378 return ENOSYS; 379 380 if (priv->rom_base == 0) { 381#if defined(__amd64__) || defined(__i386__) 382 rom_base = 0xc0000; 383 rom_size = 0x10000; 384 pci_rom = 0; 385#else 386 return ENOSYS; 387#endif 388 } else { 389 rom_base = priv->rom_base; 390 rom_size = dev->rom_size; 391 pci_rom = 1; 392 if ((pcibus_conf_read(buses[dev->domain].fd, (unsigned int)dev->bus, 393 (unsigned int)dev->dev, (unsigned int)dev->func, 394 PCI_COMMAND_STATUS_REG, &command_val)) == -1) 395 return errno; 396 if ((command_val & PCI_COMMAND_MEM_ENABLE) == 0) { 397 if ((pcibus_conf_write(buses[dev->domain].fd, 398 (unsigned int)dev->bus, (unsigned int)dev->dev, 399 (unsigned int)dev->func, PCI_COMMAND_STATUS_REG, 400 command_val | PCI_COMMAND_MEM_ENABLE)) == -1) 401 return errno; 402 } 403 if ((pcibus_conf_read(buses[dev->domain].fd, (unsigned int)dev->bus, 404 (unsigned int)dev->dev, (unsigned int)dev->func, 405 PCI_MAPREG_ROM, &bios_val)) == -1) 406 return errno; 407 if ((bios_val & PCI_MAPREG_ROM_ENABLE) == 0) { 408 if ((pcibus_conf_write(buses[dev->domain].fd, 409 (unsigned int)dev->bus, 410 (unsigned int)dev->dev, (unsigned int)dev->func, 411 PCI_MAPREG_ROM, bios_val | PCI_MAPREG_ROM_ENABLE)) == -1) 412 return errno; 413 } 414 } 415 416 fprintf(stderr, "Using rom_base = 0x%lx (pci_rom=%d)\n", (long)rom_base, 417 pci_rom); 418 memfd = open("/dev/mem", O_RDONLY); 419 if (memfd == -1) 420 return errno; 421 422 bios = mmap(NULL, rom_size, PROT_READ, 0, memfd, (off_t)rom_base); 423 if (bios == MAP_FAILED) { 424 int serrno = errno; 425 close(memfd); 426 return serrno; 427 } 428 429 memcpy(buffer, bios, rom_size); 430 431 munmap(bios, rom_size); 432 close(memfd); 433 434 if (pci_rom) { 435 if ((command_val & PCI_COMMAND_MEM_ENABLE) == 0) { 436 if ((pcibus_conf_write(buses[dev->domain].fd, 437 (unsigned int)dev->bus, 438 (unsigned int)dev->dev, (unsigned int)dev->func, 439 PCI_COMMAND_STATUS_REG, command_val)) == -1) 440 return errno; 441 } 442 if ((bios_val & PCI_MAPREG_ROM_ENABLE) == 0) { 443 if ((pcibus_conf_write(buses[dev->domain].fd, 444 (unsigned int)dev->bus, 445 (unsigned int)dev->dev, (unsigned int)dev->func, 446 PCI_MAPREG_ROM, bios_val)) == -1) 447 return errno; 448 } 449 } 450 451 return 0; 452} 453 454static const struct pci_system_methods netbsd_pci_methods = { 455 .destroy = pci_system_netbsd_destroy, 456 .destroy_device = NULL, 457 .read_rom = pci_device_netbsd_read_rom, 458 .probe = pci_device_netbsd_probe, 459 .map_range = pci_device_netbsd_map_range, 460 .unmap_range = pci_device_netbsd_unmap_range, 461 .read = pci_device_netbsd_read, 462 .write = pci_device_netbsd_write, 463 .fill_capabilities = pci_fill_capabilities_generic 464}; 465 466int 467pci_system_netbsd_create(void) 468{ 469 struct pci_device_private *device; 470 int bus, dev, func, ndevs, nfuncs, domain, pcifd; 471 uint32_t reg; 472 char netbsd_devname[32]; 473 struct pciio_businfo businfo; 474 475 pci_sys = calloc(1, sizeof(struct pci_system)); 476 477 pci_sys->methods = &netbsd_pci_methods; 478 479 ndevs = 0; 480 nbuses = 0; 481 snprintf(netbsd_devname, 32, "/dev/pci%d", nbuses); 482 pcifd = open(netbsd_devname, O_RDWR); 483 while (pcifd > 0) { 484 ioctl(pcifd, PCI_IOC_BUSINFO, &businfo); 485 buses[nbuses].fd = pcifd; 486 buses[nbuses].num = bus = businfo.busno; 487 buses[nbuses].maxdevs = businfo.maxdevs; 488 domain = nbuses; 489 nbuses++; 490 for (dev = 0; dev < businfo.maxdevs; dev++) { 491 nfuncs = pci_nfuncs(domain, bus, dev); 492 for (func = 0; func < nfuncs; func++) { 493 if (pci_read(domain, bus, dev, func, PCI_ID_REG, 494 ®) != 0) 495 continue; 496 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID || 497 PCI_VENDOR(reg) == 0) 498 continue; 499 500 ndevs++; 501 } 502 } 503 snprintf(netbsd_devname, 32, "/dev/pci%d", nbuses); 504 pcifd = open(netbsd_devname, O_RDWR); 505 } 506 507 pci_sys->num_devices = ndevs; 508 pci_sys->devices = calloc(ndevs, sizeof(struct pci_device_private)); 509 if (pci_sys->devices == NULL) { 510 int i; 511 512 for (i = 0; i < nbuses; i++) 513 close(buses[i].fd); 514 free(pci_sys); 515 return ENOMEM; 516 } 517 518 device = pci_sys->devices; 519 for (domain = 0; domain < nbuses; domain++) { 520 bus = buses[domain].num; 521 for (dev = 0; dev < buses[domain].maxdevs; dev++) { 522 nfuncs = pci_nfuncs(domain, bus, dev); 523 for (func = 0; func < nfuncs; func++) { 524 if (pci_read(domain, bus, dev, func, 525 PCI_ID_REG, ®) != 0) 526 continue; 527 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID || 528 PCI_VENDOR(reg) == 0) 529 continue; 530 531 device->base.domain = domain; 532 device->base.bus = bus; 533 device->base.dev = dev; 534 device->base.func = func; 535 device->base.vendor_id = PCI_VENDOR(reg); 536 device->base.device_id = PCI_PRODUCT(reg); 537 538 if (pci_read(domain, bus, dev, func, 539 PCI_CLASS_REG, ®) != 0) 540 continue; 541 542 device->base.device_class = 543 PCI_INTERFACE(reg) | PCI_CLASS(reg) << 16 | 544 PCI_SUBCLASS(reg) << 8; 545 device->base.revision = PCI_REVISION(reg); 546 547 if (pci_read(domain, bus, dev, func, 548 PCI_SUBSYS_ID_REG, ®) != 0) 549 continue; 550 551 device->base.subvendor_id = PCI_VENDOR(reg); 552 device->base.subdevice_id = PCI_PRODUCT(reg); 553 554 device++; 555 } 556 } 557 } 558 559 return 0; 560} 561