freebsd_pci.c revision 2029f493
1/* 2 * (C) Copyright Eric Anholt 2006 3 * (C) Copyright IBM Corporation 2006 4 * (C) Copyright Mark Kettenis 2011 5 * (C) Copyright Robert Millan 2012 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * on the rights to use, copy, modify, merge, publish, distribute, sub 12 * license, and/or sell copies of the Software, and to permit persons to whom 13 * the Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the next 16 * paragraph) shall be included in all copies or substantial portions of the 17 * Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 22 * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 * DEALINGS IN THE SOFTWARE. 26 */ 27 28/** 29 * \file freebsd_pci.c 30 * 31 * Access the kernel PCI support using /dev/pci's ioctl and mmap interface. 32 * 33 * \author Eric Anholt <eric@anholt.net> 34 */ 35 36#ifdef HAVE_CONFIG_H 37#include "config.h" 38#endif 39 40#include <stdlib.h> 41#include <stdio.h> 42#include <string.h> 43#include <unistd.h> 44#include <fcntl.h> 45#include <errno.h> 46#if defined(__i386__) || defined(__amd64__) 47#include <machine/cpufunc.h> 48#else 49#include <dev/io/iodev.h> 50#endif 51#include <sys/types.h> 52#include <sys/param.h> 53#include <sys/pciio.h> 54#include <sys/mman.h> 55#include <sys/memrange.h> 56 57#include "pciaccess.h" 58#include "pciaccess_private.h" 59 60#define PCIC_DISPLAY 0x03 61#define PCIS_DISPLAY_VGA 0x00 62#define PCIS_DISPLAY_XGA 0x01 63#define PCIS_DISPLAY_3D 0x02 64#define PCIS_DISPLAY_OTHER 0x80 65 66/* Registers taken from pcireg.h */ 67#define PCIR_COMMAND 0x04 68#define PCIM_CMD_PORTEN 0x0001 69#define PCIM_CMD_MEMEN 0x0002 70#define PCIR_BIOS 0x30 71#define PCIM_BIOS_ENABLE 0x01 72#define PCIM_BIOS_ADDR_MASK 0xfffff800 73 74#define PCIR_BARS 0x10 75#define PCIR_BAR(x) (PCIR_BARS + (x) * 4) 76#define PCI_BAR_IO(x) (((x) & PCIM_BAR_SPACE) == PCIM_BAR_IO_SPACE) 77#define PCI_BAR_MEM(x) (((x) & PCIM_BAR_SPACE) == PCIM_BAR_MEM_SPACE) 78#define PCIM_BAR_MEM_TYPE 0x00000006 79#define PCIM_BAR_MEM_64 4 80#define PCIM_BAR_MEM_PREFETCH 0x00000008 81#define PCIM_BAR_SPACE 0x00000001 82#define PCIM_BAR_MEM_SPACE 0 83#define PCIM_BAR_IO_SPACE 1 84 85#if defined(__sparc64__) 86static int screenfd; 87#endif 88 89/** 90 * FreeBSD private pci_system structure that extends the base pci_system 91 * structure. 92 * 93 * It is initialized once and used as a global, just as pci_system is used. 94 */ 95_pci_hidden 96struct freebsd_pci_system { 97 /* This must be the first entry in the structure, as pci_system_cleanup() 98 * frees pci_sys. 99 */ 100 struct pci_system pci_sys; 101 102 int pcidev; /**< fd for /dev/pci */ 103} *freebsd_pci_sys; 104 105/** 106 * Map a memory region for a device using /dev/mem. 107 * 108 * \param dev Device whose memory region is to be mapped. 109 * \param map Parameters of the mapping that is to be created. 110 * 111 * \return 112 * Zero on success or an \c errno value on failure. 113 */ 114static int 115pci_device_freebsd_map_range( struct pci_device *dev, 116 struct pci_device_mapping *map ) 117{ 118 const int prot = ((map->flags & PCI_DEV_MAP_FLAG_WRITABLE) != 0) 119 ? (PROT_READ | PROT_WRITE) : PROT_READ; 120#if !defined(__sparc64__) 121 struct mem_range_desc mrd; 122 struct mem_range_op mro; 123#endif 124 125 int fd, err = 0; 126 127#if defined(__sparc64__) 128 fd = screenfd; 129#else 130 fd = open("/dev/mem", O_RDWR | O_CLOEXEC); 131#endif 132 if (fd == -1) 133 return errno; 134 135 map->memory = mmap(NULL, map->size, prot, MAP_SHARED, fd, map->base); 136 137 if (map->memory == MAP_FAILED) { 138 err = errno; 139 } 140 141#if !defined(__sparc64__) 142 mrd.mr_base = map->base; 143 mrd.mr_len = map->size; 144 strncpy(mrd.mr_owner, "pciaccess", sizeof(mrd.mr_owner)); 145 if (map->flags & PCI_DEV_MAP_FLAG_CACHABLE) 146 mrd.mr_flags = MDF_WRITEBACK; 147 else if (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE) 148 mrd.mr_flags = MDF_WRITECOMBINE; 149 else 150 mrd.mr_flags = MDF_UNCACHEABLE; 151 mro.mo_desc = &mrd; 152 mro.mo_arg[0] = MEMRANGE_SET_UPDATE; 153 154 /* No need to set an MTRR if it's the default mode. */ 155 if (mrd.mr_flags != MDF_UNCACHEABLE) { 156 if (ioctl(fd, MEMRANGE_SET, &mro)) { 157 fprintf(stderr, "failed to set mtrr: %s\n", strerror(errno)); 158 } 159 } 160 161 close(fd); 162#endif 163 164 return err; 165} 166 167static int 168pci_device_freebsd_unmap_range( struct pci_device *dev, 169 struct pci_device_mapping *map ) 170{ 171#if !defined(__sparc64__) 172 struct mem_range_desc mrd; 173 struct mem_range_op mro; 174 int fd; 175 176 if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) || 177 (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) 178 { 179 fd = open("/dev/mem", O_RDWR | O_CLOEXEC); 180 if (fd != -1) { 181 mrd.mr_base = map->base; 182 mrd.mr_len = map->size; 183 strncpy(mrd.mr_owner, "pciaccess", sizeof(mrd.mr_owner)); 184 mrd.mr_flags = MDF_UNCACHEABLE; 185 mro.mo_desc = &mrd; 186 mro.mo_arg[0] = MEMRANGE_SET_REMOVE; 187 188 if (ioctl(fd, MEMRANGE_SET, &mro)) { 189 fprintf(stderr, "failed to unset mtrr: %s\n", strerror(errno)); 190 } 191 192 close(fd); 193 } else { 194 fprintf(stderr, "Failed to open /dev/mem\n"); 195 } 196 } 197#endif 198 199 return pci_device_generic_unmap_range(dev, map); 200} 201 202static int 203pci_device_freebsd_read( struct pci_device * dev, void * data, 204 pciaddr_t offset, pciaddr_t size, 205 pciaddr_t * bytes_read ) 206{ 207 struct pci_io io; 208 209 io.pi_sel.pc_domain = dev->domain; 210 io.pi_sel.pc_bus = dev->bus; 211 io.pi_sel.pc_dev = dev->dev; 212 io.pi_sel.pc_func = dev->func; 213 214 *bytes_read = 0; 215 while ( size > 0 ) { 216 int toread = (size < 4) ? size : 4; 217 218 /* Only power of two allowed. */ 219 if (toread == 3) 220 toread = 2; 221 222 io.pi_reg = offset; 223 io.pi_width = toread; 224 225 if ( ioctl( freebsd_pci_sys->pcidev, PCIOCREAD, &io ) < 0 ) 226 return errno; 227 228 memcpy(data, &io.pi_data, toread ); 229 230 offset += toread; 231 data = (char *)data + toread; 232 size -= toread; 233 *bytes_read += toread; 234 } 235 236 return 0; 237} 238 239 240static int 241pci_device_freebsd_write( struct pci_device * dev, const void * data, 242 pciaddr_t offset, pciaddr_t size, 243 pciaddr_t * bytes_written ) 244{ 245 struct pci_io io; 246 247 io.pi_sel.pc_domain = dev->domain; 248 io.pi_sel.pc_bus = dev->bus; 249 io.pi_sel.pc_dev = dev->dev; 250 io.pi_sel.pc_func = dev->func; 251 252 *bytes_written = 0; 253 while ( size > 0 ) { 254 int towrite = (size < 4 ? size : 4); 255 256 /* Only power of two allowed. */ 257 if (towrite == 3) 258 towrite = 2; 259 260 io.pi_reg = offset; 261 io.pi_width = towrite; 262 memcpy( &io.pi_data, data, towrite ); 263 264 if ( ioctl( freebsd_pci_sys->pcidev, PCIOCWRITE, &io ) < 0 ) 265 return errno; 266 267 offset += towrite; 268 data = (char *)data + towrite; 269 size -= towrite; 270 *bytes_written += towrite; 271 } 272 273 return 0; 274} 275 276/** 277 * Read a VGA rom using the 0xc0000 mapping. 278 * 279 * This function should be extended to handle access through PCI resources, 280 * which should be more reliable when available. 281 */ 282static int 283pci_device_freebsd_read_rom( struct pci_device * dev, void * buffer ) 284{ 285 struct pci_device_private *priv = (struct pci_device_private *) dev; 286 void *bios; 287 pciaddr_t rom_base; 288 uint32_t rom; 289 uint16_t reg; 290 int pci_rom, memfd; 291 292 if ( ( dev->device_class & 0x00ffff00 ) != 293 ( ( PCIC_DISPLAY << 16 ) | ( PCIS_DISPLAY_VGA << 8 ) ) ) 294 { 295 return ENOSYS; 296 } 297 298 if (priv->rom_base == 0) { 299#if defined(__amd64__) || defined(__i386__) 300 rom_base = 0xc0000; 301 pci_rom = 0; 302#else 303 return ENOSYS; 304#endif 305 } else { 306 rom_base = priv->rom_base; 307 pci_rom = 1; 308 309 pci_device_cfg_read_u16( dev, ®, PCIR_COMMAND ); 310 pci_device_cfg_write_u16( dev, reg | PCIM_CMD_MEMEN, PCIR_COMMAND ); 311 pci_device_cfg_read_u32( dev, &rom, PCIR_BIOS ); 312 pci_device_cfg_write_u32( dev, rom | PCIM_BIOS_ENABLE, PCIR_BIOS ); 313 } 314 315 printf("Using rom_base = 0x%lx\n", (long)rom_base); 316#if defined(__sparc64__) 317 memfd = screenfd; 318#else 319 memfd = open( "/dev/mem", O_RDONLY | O_CLOEXEC ); 320#endif 321 if ( memfd == -1 ) 322 return errno; 323 324 bios = mmap( NULL, dev->rom_size, PROT_READ, 0, memfd, rom_base ); 325 if ( bios == MAP_FAILED ) { 326 close( memfd ); 327 return errno; 328 } 329 330 memcpy( buffer, bios, dev->rom_size ); 331 332 munmap( bios, dev->rom_size ); 333#if !defined(__sparc64__) 334 close( memfd ); 335#endif 336 337 if (pci_rom) { 338 pci_device_cfg_write_u32( dev, PCIR_BIOS, rom ); 339 pci_device_cfg_write_u16( dev, PCIR_COMMAND, reg ); 340 } 341 342 return 0; 343} 344 345/** Returns the number of regions (base address registers) the device has */ 346 347static int 348pci_device_freebsd_get_num_regions( struct pci_device * dev ) 349{ 350 struct pci_device_private *priv = (struct pci_device_private *) dev; 351 352 switch (priv->header_type) { 353 case 0: 354 return 6; 355 case 1: 356 return 2; 357 case 2: 358 return 1; 359 default: 360 printf("unknown header type %02x\n", priv->header_type); 361 return 0; 362 } 363} 364 365static int 366pci_device_freebsd_probe( struct pci_device * dev ) 367{ 368 struct pci_bar_io bar; 369 uint8_t irq; 370 int err, i; 371 372 bar.pbi_sel.pc_domain = dev->domain; 373 bar.pbi_sel.pc_bus = dev->bus; 374 bar.pbi_sel.pc_dev = dev->dev; 375 bar.pbi_sel.pc_func = dev->func; 376 377 378 /* Many of the fields were filled in during initial device enumeration. 379 * At this point, we need to fill in regions, rom_size, and irq. 380 */ 381 382 err = pci_device_cfg_read_u8( dev, &irq, 60 ); 383 if (err) 384 return errno; 385 dev->irq = irq; 386 387 for (i = 0; i < pci_device_freebsd_get_num_regions( dev ); i++) { 388 bar.pbi_reg = PCIR_BAR(i); 389 if ( ioctl( freebsd_pci_sys->pcidev, PCIOCGETBAR, &bar ) < 0 ) 390 continue; 391 392 if (PCI_BAR_IO(bar.pbi_base)) 393 dev->regions[i].is_IO = 1; 394 395 if ((bar.pbi_base & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64) 396 dev->regions[i].is_64 = 1; 397 398 if (bar.pbi_base & PCIM_BAR_MEM_PREFETCH) 399 dev->regions[i].is_prefetchable = 1; 400 401 dev->regions[i].base_addr = bar.pbi_base & ~((uint64_t)0xf); 402 dev->regions[i].size = bar.pbi_length; 403 } 404 405 /* If it's a VGA device, set up the rom size for read_rom using the 406 * 0xc0000 mapping. 407 */ 408 if ((dev->device_class & 0x00ffff00) == 409 ((PCIC_DISPLAY << 16) | (PCIS_DISPLAY_VGA << 8))) { 410 dev->rom_size = 64 * 1024; 411 } 412 413 return 0; 414} 415 416static void 417pci_system_freebsd_destroy( void ) 418{ 419 close(freebsd_pci_sys->pcidev); 420 free(freebsd_pci_sys->pci_sys.devices); 421 freebsd_pci_sys = NULL; 422} 423 424static int 425pci_device_freebsd_has_kernel_driver( struct pci_device *dev ) 426{ 427 struct pci_io io; 428 429 io.pi_sel.pc_domain = dev->domain; 430 io.pi_sel.pc_bus = dev->bus; 431 io.pi_sel.pc_dev = dev->dev; 432 io.pi_sel.pc_func = dev->func; 433 434 if ( ioctl( freebsd_pci_sys->pcidev, PCIOCATTACHED, &io ) < 0 ) { 435 return 0; 436 } 437 438 /* if io.pi_data is 0, no driver is attached */ 439 return io.pi_data == 0 ? 0 : 1; 440} 441 442static struct pci_io_handle * 443pci_device_freebsd_open_legacy_io( struct pci_io_handle *ret, 444 struct pci_device *dev, pciaddr_t base, 445 pciaddr_t size ) 446{ 447#if defined(__sparc64__) 448 ret->memory = mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, 449 screenfd, base ); 450 if ( ret->memory == MAP_FAILED ) 451 return NULL; 452#else 453 ret->fd = open( "/dev/io", O_RDWR | O_CLOEXEC ); 454 if ( ret->fd < 0 ) 455 return NULL; 456#endif 457 ret->base = base; 458 ret->size = size; 459 ret->is_legacy = 1; 460 return ret; 461} 462 463static struct pci_io_handle * 464pci_device_freebsd_open_io( struct pci_io_handle *ret, 465 struct pci_device *dev, int bar, 466 pciaddr_t base, pciaddr_t size ) 467{ 468 ret = pci_device_freebsd_open_legacy_io( ret, dev, base, size ); 469 if ( ret != NULL ) 470 ret->is_legacy = 0; 471 return ret; 472} 473 474static void 475pci_device_freebsd_close_io( struct pci_device *dev, 476 struct pci_io_handle *handle ) 477{ 478#if !defined(__sparc64__) 479 if ( handle->fd > -1 ) 480 close( handle->fd ); 481#endif 482} 483 484static uint32_t 485pci_device_freebsd_read32( struct pci_io_handle *handle, uint32_t reg ) 486{ 487#if defined(__sparc64__) 488 return *(uint32_t *)((uintptr_t)handle->memory + reg); 489#elif defined(__i386__) || defined(__amd64__) 490 return inl( handle->base + reg ); 491#else 492 struct iodev_pio_req req = { IODEV_PIO_READ, handle->base + reg, 4, 0 }; 493 if ( handle->fd > -1 ) 494 ioctl( handle->fd, IODEV_PIO, &req ); 495 return req.val; 496#endif 497} 498 499static uint16_t 500pci_device_freebsd_read16( struct pci_io_handle *handle, uint32_t reg ) 501{ 502#if defined(__sparc64__) 503 return *(uint16_t *)((uintptr_t)handle->memory + reg); 504#elif defined(__i386__) || defined(__amd64__) 505 return inw( handle->base + reg ); 506#else 507 struct iodev_pio_req req = { IODEV_PIO_READ, handle->base + reg, 2, 0 }; 508 if ( handle->fd > -1 ) 509 ioctl( handle->fd, IODEV_PIO, &req ); 510 return req.val; 511#endif 512} 513 514static uint8_t 515pci_device_freebsd_read8( struct pci_io_handle *handle, uint32_t reg ) 516{ 517#if defined(__sparc64__) 518 return *(uint8_t *)((uintptr_t)handle->memory + reg); 519#elif defined(__i386__) || defined(__amd64__) 520 return inb( handle->base + reg ); 521#else 522 struct iodev_pio_req req = { IODEV_PIO_READ, handle->base + reg, 1, 0 }; 523 if ( handle->fd > -1 ) 524 ioctl( handle->fd, IODEV_PIO, &req ); 525 return req.val; 526#endif 527} 528 529static void 530pci_device_freebsd_write32( struct pci_io_handle *handle, uint32_t reg, 531 uint32_t data ) 532{ 533#if defined(__sparc64__) 534 *(uint32_t *)((uintptr_t)handle->memory + reg) = data; 535#elif defined(__i386__) || defined(__amd64__) 536 outl( handle->base + reg, data ); 537#else 538 struct iodev_pio_req req = { IODEV_PIO_WRITE, handle->base + reg, 4, data }; 539 if ( handle->fd > -1 ) 540 ioctl( handle->fd, IODEV_PIO, &req ); 541#endif 542} 543 544static void 545pci_device_freebsd_write16( struct pci_io_handle *handle, uint32_t reg, 546 uint16_t data ) 547{ 548#if defined(__sparc64__) 549 *(uint16_t *)((uintptr_t)handle->memory + reg) = data; 550#elif defined(__i386__) || defined(__amd64__) 551 outw( handle->base + reg, data ); 552#else 553 struct iodev_pio_req req = { IODEV_PIO_WRITE, handle->base + reg, 2, data }; 554 if ( handle->fd > -1 ) 555 ioctl( handle->fd, IODEV_PIO, &req ); 556#endif 557} 558 559static void 560pci_device_freebsd_write8( struct pci_io_handle *handle, uint32_t reg, 561 uint8_t data ) 562{ 563#if defined(__sparc64__) 564 *(uint8_t *)((uintptr_t)handle->memory + reg) = data; 565#elif defined(__i386__) || defined(__amd64__) 566 outb( handle->base + reg, data ); 567#else 568 struct iodev_pio_req req = { IODEV_PIO_WRITE, handle->base + reg, 1, data }; 569 if ( handle->fd > -1 ) 570 ioctl( handle->fd, IODEV_PIO, &req ); 571#endif 572} 573 574static int 575pci_device_freebsd_map_legacy( struct pci_device *dev, pciaddr_t base, 576 pciaddr_t size, unsigned map_flags, void **addr ) 577{ 578 struct pci_device_mapping map; 579 int err; 580 581 map.base = base; 582 map.size = size; 583 map.flags = map_flags; 584 map.memory = NULL; 585 err = pci_device_freebsd_map_range( dev, &map ); 586 *addr = map.memory; 587 588 return err; 589} 590 591static int 592pci_device_freebsd_unmap_legacy( struct pci_device *dev, void *addr, 593 pciaddr_t size ) 594{ 595 struct pci_device_mapping map; 596 597 map.memory = addr; 598 map.size = size; 599 map.flags = 0; 600 return pci_device_freebsd_unmap_range( dev, &map ); 601} 602 603static const struct pci_system_methods freebsd_pci_methods = { 604 .destroy = pci_system_freebsd_destroy, 605 .destroy_device = NULL, /* nothing to do for this */ 606 .read_rom = pci_device_freebsd_read_rom, 607 .probe = pci_device_freebsd_probe, 608 .map_range = pci_device_freebsd_map_range, 609 .unmap_range = pci_device_freebsd_unmap_range, 610 611 .read = pci_device_freebsd_read, 612 .write = pci_device_freebsd_write, 613 614 .fill_capabilities = pci_fill_capabilities_generic, 615 .enable = NULL, 616 .boot_vga = NULL, 617 .has_kernel_driver = pci_device_freebsd_has_kernel_driver, 618 619 .open_device_io = pci_device_freebsd_open_io, 620 .open_legacy_io = pci_device_freebsd_open_legacy_io, 621 .close_io = pci_device_freebsd_close_io, 622 .read32 = pci_device_freebsd_read32, 623 .read16 = pci_device_freebsd_read16, 624 .read8 = pci_device_freebsd_read8, 625 .write32 = pci_device_freebsd_write32, 626 .write16 = pci_device_freebsd_write16, 627 .write8 = pci_device_freebsd_write8, 628 629 .map_legacy = pci_device_freebsd_map_legacy, 630 .unmap_legacy = pci_device_freebsd_unmap_legacy, 631}; 632 633/** 634 * Attempt to access the FreeBSD PCI interface. 635 */ 636_pci_hidden int 637pci_system_freebsd_create( void ) 638{ 639 struct pci_conf_io pciconfio; 640 struct pci_conf pciconf[255]; 641 int pcidev; 642 int i; 643 644 /* Try to open the PCI device */ 645 pcidev = open( "/dev/pci", O_RDWR | O_CLOEXEC ); 646 if ( pcidev == -1 ) 647 return ENXIO; 648 649 freebsd_pci_sys = calloc( 1, sizeof( struct freebsd_pci_system ) ); 650 if ( freebsd_pci_sys == NULL ) { 651 close( pcidev ); 652 return ENOMEM; 653 } 654 pci_sys = &freebsd_pci_sys->pci_sys; 655 656 pci_sys->methods = & freebsd_pci_methods; 657 freebsd_pci_sys->pcidev = pcidev; 658 659 /* Probe the list of devices known by the system */ 660 bzero( &pciconfio, sizeof( struct pci_conf_io ) ); 661 pciconfio.match_buf_len = sizeof(pciconf); 662 pciconfio.matches = pciconf; 663 664 if ( ioctl( pcidev, PCIOCGETCONF, &pciconfio ) == -1) { 665 free( pci_sys ); 666 close( pcidev ); 667 return errno; 668 } 669 670 if (pciconfio.status == PCI_GETCONF_ERROR ) { 671 free( pci_sys ); 672 close( pcidev ); 673 return EINVAL; 674 } 675 676 /* Translate the list of devices into pciaccess's format. */ 677 pci_sys->num_devices = pciconfio.num_matches; 678 pci_sys->devices = calloc( pciconfio.num_matches, 679 sizeof( struct pci_device_private ) ); 680 681 for ( i = 0; i < pciconfio.num_matches; i++ ) { 682 struct pci_conf *p = &pciconf[ i ]; 683 684 pci_sys->devices[ i ].base.domain = p->pc_sel.pc_domain; 685 pci_sys->devices[ i ].base.bus = p->pc_sel.pc_bus; 686 pci_sys->devices[ i ].base.dev = p->pc_sel.pc_dev; 687 pci_sys->devices[ i ].base.func = p->pc_sel.pc_func; 688 pci_sys->devices[ i ].base.vendor_id = p->pc_vendor; 689 pci_sys->devices[ i ].base.device_id = p->pc_device; 690 pci_sys->devices[ i ].base.subvendor_id = p->pc_subvendor; 691 pci_sys->devices[ i ].base.subdevice_id = p->pc_subdevice; 692 pci_sys->devices[ i ].base.revision = p->pc_revid; 693 pci_sys->devices[ i ].base.device_class = (uint32_t)p->pc_class << 16 | 694 (uint32_t)p->pc_subclass << 8 | (uint32_t)p->pc_progif; 695 pci_sys->devices[ i ].header_type = p->pc_hdr & 0x7f; 696 } 697 698 return 0; 699} 700 701void 702pci_system_freebsd_init_dev_mem(int fd) 703{ 704#if defined(__sparc64__) 705 screenfd = fd; 706#endif 707} 708