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, &reg, 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