OSDN Git Service

73c68f46023ebfbdd1056e3666f6268a125643eb
[android-x86/external-libpciaccess.git] / src / openbsd_pci.c
1 /*
2  * Copyright (c) 2008, 2011 Mark Kettenis
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <sys/param.h>
18 #include <sys/ioctl.h>
19 #include <sys/memrange.h>
20 #include <sys/mman.h>
21 #include <sys/pciio.h>
22
23 #include <dev/pci/pcireg.h>
24 #include <dev/pci/pcidevs.h>
25
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32
33 #include "pciaccess.h"
34 #include "pciaccess_private.h"
35
36 /*
37  * This should allow for 16 domains, which should cover everything
38  * except perhaps the really big fridge-sized sparc64 server machines
39  * that are unlikely to have any graphics hardware in them.
40  */
41 static int pcifd[16];
42 static int ndomains;
43
44 static int aperturefd = -1;
45
46 static int
47 pci_read(int domain, int bus, int dev, int func, uint32_t reg, uint32_t *val)
48 {
49         struct pci_io io;
50         int err;
51
52         bzero(&io, sizeof(io));
53         io.pi_sel.pc_bus = bus;
54         io.pi_sel.pc_dev = dev;
55         io.pi_sel.pc_func = func;
56         io.pi_reg = reg;
57         io.pi_width = 4;
58
59         err = ioctl(pcifd[domain], PCIOCREAD, &io);
60         if (err)
61                 return (err);
62
63         *val = io.pi_data;
64
65         return 0;
66 }
67
68 static int
69 pci_write(int domain, int bus, int dev, int func, uint32_t reg, uint32_t val)
70 {
71         struct pci_io io;
72
73         bzero(&io, sizeof(io));
74         io.pi_sel.pc_bus = bus;
75         io.pi_sel.pc_dev = dev;
76         io.pi_sel.pc_func = func;
77         io.pi_reg = reg;
78         io.pi_width = 4;
79         io.pi_data = val;
80
81         return ioctl(pcifd[domain], PCIOCWRITE, &io);
82 }
83
84 /**
85  * Read a VGA ROM
86  *
87  */
88 static int
89 pci_device_openbsd_read_rom(struct pci_device *device, void *buffer)
90 {
91         struct pci_device_private *priv = (struct pci_device_private *)device;
92         unsigned char *bios;
93         pciaddr_t rom_base;
94         pciaddr_t rom_size;
95         u_int32_t csr, rom;
96         int pci_rom, domain, bus, dev, func;
97
98         domain = device->domain;
99         if (domain < 0 || domain >= ndomains)
100                 return ENXIO;
101
102         bus = device->bus;
103         dev = device->dev;
104         func = device->func;
105
106         if (aperturefd == -1)
107                 return ENOSYS;
108
109         if (priv->base.rom_size == 0) {
110 #if defined(__alpha__) || defined(__amd64__) || defined(__i386__)
111                 if ((device->device_class & 0x00ffff00) ==
112                     ((PCI_CLASS_DISPLAY << 16) |
113                         (PCI_SUBCLASS_DISPLAY_VGA << 8))) {
114                         rom_base = 0xc0000;
115                         rom_size = 0x10000;
116                         pci_rom = 0;
117                 } else
118 #endif
119                         return ENOSYS;
120         } else {
121                 rom_base = priv->rom_base;
122                 rom_size = priv->base.rom_size;
123                 pci_rom = 1;
124
125                 pci_read(domain, bus, dev, func, PCI_COMMAND_STATUS_REG, &csr);
126                 pci_write(domain, bus, dev, func, PCI_COMMAND_STATUS_REG,
127                     csr | PCI_COMMAND_MEM_ENABLE);
128                 pci_read(domain, bus, dev, func, PCI_ROM_REG, &rom);
129                 pci_write(domain, bus, dev, func, PCI_ROM_REG,
130                     rom | PCI_ROM_ENABLE);
131         }
132
133         bios = mmap(NULL, rom_size, PROT_READ, MAP_SHARED,
134             aperturefd, (off_t)rom_base);
135         if (bios == MAP_FAILED)
136                 return errno;
137
138         memcpy(buffer, bios, rom_size);
139         munmap(bios, rom_size);
140
141         if (pci_rom) {
142                 /* Restore PCI config space */
143                 pci_write(domain, bus, dev, func, PCI_ROM_REG, rom);
144                 pci_write(domain, bus, dev, func, PCI_COMMAND_STATUS_REG, csr);
145         }
146         return 0;
147 }
148
149 static int
150 pci_nfuncs(int domain, int bus, int dev)
151 {
152         uint32_t hdr;
153
154         if (domain < 0 || domain >= ndomains)
155                 return ENXIO;
156
157         if (pci_read(domain, bus, dev, 0, PCI_BHLC_REG, &hdr) != 0)
158                 return -1;
159
160         return (PCI_HDRTYPE_MULTIFN(hdr) ? 8 : 1);
161 }
162
163 static int
164 pci_device_openbsd_map_range(struct pci_device *dev,
165     struct pci_device_mapping *map)
166 {
167         struct mem_range_desc mr;
168         struct mem_range_op mo;
169         int prot = PROT_READ;
170
171         if (map->flags & PCI_DEV_MAP_FLAG_WRITABLE)
172                 prot |= PROT_WRITE;
173
174         map->memory = mmap(NULL, map->size, prot, MAP_SHARED, aperturefd,
175             map->base);
176         if (map->memory == MAP_FAILED)
177                 return  errno;
178 #if defined(__i386__) || defined(__amd64__)
179         /* No need to set an MTRR if it's the default mode. */
180         if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) ||
181             (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) {
182                 mr.mr_base = map->base;
183                 mr.mr_len = map->size;
184                 mr.mr_flags = 0;
185                 if (map->flags & PCI_DEV_MAP_FLAG_CACHABLE)
186                         mr.mr_flags |= MDF_WRITEBACK;
187                 if (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)
188                         mr.mr_flags |= MDF_WRITECOMBINE;
189                 strlcpy(mr.mr_owner, "pciaccess", sizeof(mr.mr_owner));
190
191                 mo.mo_desc = &mr;
192                 mo.mo_arg[0] = MEMRANGE_SET_UPDATE;
193
194                 if (ioctl(aperturefd, MEMRANGE_SET, &mo))
195                         (void)fprintf(stderr, "mtrr set failed: %s\n",
196                             strerror(errno));
197         }
198 #endif
199         return 0;
200 }
201
202 static int
203 pci_device_openbsd_unmap_range(struct pci_device *dev,
204     struct pci_device_mapping *map)
205 {
206 #if defined(__i386__) || defined(__amd64__)
207         struct mem_range_desc mr;
208         struct mem_range_op mo;
209
210         if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) ||
211             (map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE)) {
212                 mr.mr_base = map->base;
213                 mr.mr_len = map->size;
214                 mr.mr_flags = MDF_UNCACHEABLE;
215                 strlcpy(mr.mr_owner, "pciaccess", sizeof(mr.mr_owner));
216
217                 mo.mo_desc = &mr;
218                 mo.mo_arg[0] = MEMRANGE_SET_REMOVE;
219
220                 (void)ioctl(aperturefd, MEMRANGE_SET, &mo);
221         }
222 #endif
223         return pci_device_generic_unmap_range(dev, map);
224 }
225
226 static int
227 pci_device_openbsd_read(struct pci_device *dev, void *data,
228     pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_read)
229 {
230         struct pci_io io;
231
232         io.pi_sel.pc_bus = dev->bus;
233         io.pi_sel.pc_dev = dev->dev;
234         io.pi_sel.pc_func = dev->func;
235
236         *bytes_read = 0;
237         while (size > 0) {
238                 int toread = MIN(size, 4 - (offset & 0x3));
239
240                 io.pi_reg = (offset & ~0x3);
241                 io.pi_width = 4;
242
243                 if (ioctl(pcifd[dev->domain], PCIOCREAD, &io) == -1)
244                         return errno;
245
246                 io.pi_data = htole32(io.pi_data);
247                 io.pi_data >>= ((offset & 0x3) * 8);
248
249                 memcpy(data, &io.pi_data, toread);
250
251                 offset += toread;
252                 data = (char *)data + toread;
253                 size -= toread;
254                 *bytes_read += toread;
255         }
256
257         return 0;
258 }
259
260 static int
261 pci_device_openbsd_write(struct pci_device *dev, const void *data,
262     pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_written)
263 {
264         struct pci_io io;
265
266         if ((offset % 4) != 0 || (size % 4) != 0)
267                 return EINVAL;
268
269         io.pi_sel.pc_bus = dev->bus;
270         io.pi_sel.pc_dev = dev->dev;
271         io.pi_sel.pc_func = dev->func;
272
273         *bytes_written = 0;
274         while (size > 0) {
275                 io.pi_reg = offset;
276                 io.pi_width = 4;
277                 memcpy(&io.pi_data, data, 4);
278
279                 if (ioctl(pcifd[dev->domain], PCIOCWRITE, &io) == -1)
280                         return errno;
281
282                 offset += 4;
283                 data = (char *)data + 4;
284                 size -= 4;
285                 *bytes_written += 4;
286         }
287
288         return 0;
289 }
290
291 static void
292 pci_system_openbsd_destroy(void)
293 {
294         int domain;
295
296         for (domain = 0; domain < ndomains; domain++)
297                 close(pcifd[domain]);
298         ndomains = 0;
299 }
300
301 static int
302 pci_device_openbsd_probe(struct pci_device *device)
303 {
304         struct pci_device_private *priv = (struct pci_device_private *)device;
305         struct pci_mem_region *region;
306         uint64_t reg64, size64;
307         uint32_t bar, reg, size;
308         int domain, bus, dev, func, err;
309
310         domain = device->domain;
311         bus = device->bus;
312         dev = device->dev;
313         func = device->func;
314
315         err = pci_read(domain, bus, dev, func, PCI_BHLC_REG, &reg);
316         if (err)
317                 return err;
318
319         priv->header_type = PCI_HDRTYPE_TYPE(reg);
320         if (priv->header_type != 0)
321                 return 0;
322
323         region = device->regions;
324         for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END;
325              bar += sizeof(uint32_t), region++) {
326                 err = pci_read(domain, bus, dev, func, bar, &reg);
327                 if (err)
328                         return err;
329
330                 /* Probe the size of the region. */
331                 err = pci_write(domain, bus, dev, func, bar, ~0);
332                 if (err)
333                         return err;
334                 pci_read(domain, bus, dev, func, bar, &size);
335                 pci_write(domain, bus, dev, func, bar, reg);
336
337                 if (PCI_MAPREG_TYPE(reg) == PCI_MAPREG_TYPE_IO) {
338                         region->is_IO = 1;
339                         region->base_addr = PCI_MAPREG_IO_ADDR(reg);
340                         region->size = PCI_MAPREG_IO_SIZE(size);
341                 } else {
342                         if (PCI_MAPREG_MEM_PREFETCHABLE(reg))
343                                 region->is_prefetchable = 1;
344                         switch(PCI_MAPREG_MEM_TYPE(reg)) {
345                         case PCI_MAPREG_MEM_TYPE_32BIT:
346                         case PCI_MAPREG_MEM_TYPE_32BIT_1M:
347                                 region->base_addr = PCI_MAPREG_MEM_ADDR(reg);
348                                 region->size = PCI_MAPREG_MEM_SIZE(size);
349                                 break;
350                         case PCI_MAPREG_MEM_TYPE_64BIT:
351                                 region->is_64 = 1;
352
353                                 reg64 = reg;
354                                 size64 = size;
355
356                                 bar += sizeof(uint32_t);
357
358                                 err = pci_read(domain, bus, dev, func, bar, &reg);
359                                 if (err)
360                                         return err;
361                                 reg64 |= (uint64_t)reg << 32;
362
363                                 err = pci_write(domain, bus, dev, func, bar, ~0);
364                                 if (err)
365                                         return err;
366                                 pci_read(domain, bus, dev, func, bar, &size);
367                                 pci_write(domain, bus, dev, func, bar, reg64 >> 32);
368                                 size64 |= (uint64_t)size << 32;
369
370                                 region->base_addr = PCI_MAPREG_MEM64_ADDR(reg64);
371                                 region->size = PCI_MAPREG_MEM64_SIZE(size64);
372                                 region++;
373                                 break;
374                         }
375                 }
376         }
377
378         /* Probe expansion ROM if present */
379         err = pci_read(domain, bus, dev, func, PCI_ROM_REG, &reg);
380         if (err)
381                 return err;
382         if (reg != 0) {
383                 err = pci_write(domain, bus, dev, func, PCI_ROM_REG, ~PCI_ROM_ENABLE);
384                 if (err)
385                         return err;
386                 pci_read(domain, bus, dev, func, PCI_ROM_REG, &size);
387                 pci_write(domain, bus, dev, func, PCI_ROM_REG, reg);
388
389                 if (PCI_ROM_ADDR(reg) != 0) {
390                         priv->rom_base = PCI_ROM_ADDR(reg);
391                         device->rom_size = PCI_ROM_SIZE(size);
392                 }
393         }
394         return 0;
395 }
396
397 #if defined(__i386__) || defined(__amd64__)
398 #include <machine/sysarch.h>
399 #include <machine/pio.h>
400 #endif
401
402 static struct pci_io_handle *
403 pci_device_openbsd_open_legacy_io(struct pci_io_handle *ret,
404     struct pci_device *dev, pciaddr_t base, pciaddr_t size)
405 {
406 #if defined(__i386__)
407         struct i386_iopl_args ia;
408
409         ia.iopl = 1;
410         if (sysarch(I386_IOPL, &ia))
411                 return NULL;
412
413         ret->base = base;
414         ret->size = size;
415         return ret;
416 #elif defined(__amd64__)
417         struct amd64_iopl_args ia;
418
419         ia.iopl = 1;
420         if (sysarch(AMD64_IOPL, &ia))
421                 return NULL;
422
423         ret->base = base;
424         ret->size = size;
425         return ret;
426 #elif defined(PCI_MAGIC_IO_RANGE)
427         ret->memory = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
428             aperturefd, PCI_MAGIC_IO_RANGE + base);
429         if (ret->memory == MAP_FAILED)
430                 return NULL;
431
432         ret->base = base;
433         ret->size = size;
434         return ret;
435 #else
436         return NULL;
437 #endif
438 }
439
440 static uint32_t
441 pci_device_openbsd_read32(struct pci_io_handle *handle, uint32_t reg)
442 {
443 #if defined(__i386__) || defined(__amd64__)
444         return inl(handle->base + reg);
445 #else
446         return *(uint32_t *)((uintptr_t)handle->memory + reg);
447 #endif
448 }
449
450 static uint16_t
451 pci_device_openbsd_read16(struct pci_io_handle *handle, uint32_t reg)
452 {
453 #if defined(__i386__) || defined(__amd64__)
454         return inw(handle->base + reg);
455 #else
456         return *(uint16_t *)((uintptr_t)handle->memory + reg);
457 #endif
458 }
459
460 static uint8_t
461 pci_device_openbsd_read8(struct pci_io_handle *handle, uint32_t reg)
462 {
463 #if defined(__i386__) || defined(__amd64__)
464         return inb(handle->base + reg);
465 #else
466         return *(uint8_t *)((uintptr_t)handle->memory + reg);
467 #endif
468 }
469
470 static void
471 pci_device_openbsd_write32(struct pci_io_handle *handle, uint32_t reg,
472     uint32_t data)
473 {
474 #if defined(__i386__) || defined(__amd64__)
475         outl(handle->base + reg, data);
476 #else
477         *(uint16_t *)((uintptr_t)handle->memory + reg) = data;
478 #endif
479 }
480
481 static void
482 pci_device_openbsd_write16(struct pci_io_handle *handle, uint32_t reg,
483     uint16_t data)
484 {
485 #if defined(__i386__) || defined(__amd64__)
486         outw(handle->base + reg, data);
487 #else
488         *(uint8_t *)((uintptr_t)handle->memory + reg) = data;
489 #endif
490 }
491
492 static void
493 pci_device_openbsd_write8(struct pci_io_handle *handle, uint32_t reg,
494     uint8_t data)
495 {
496 #if defined(__i386__) || defined(__amd64__)
497         outb(handle->base + reg, data);
498 #else
499         *(uint32_t *)((uintptr_t)handle->memory + reg) = data;
500 #endif
501 }
502
503 static int
504 pci_device_openbsd_map_legacy(struct pci_device *dev, pciaddr_t base,
505     pciaddr_t size, unsigned map_flags, void **addr)
506 {
507         struct pci_device_mapping map;
508         int err;
509
510         map.base = base;
511         map.size = size;
512         map.flags = map_flags;
513         map.memory = NULL;
514         err = pci_device_openbsd_map_range(dev, &map);
515         *addr = map.memory;
516
517         return err;
518 }
519
520 static int
521 pci_device_openbsd_unmap_legacy(struct pci_device *dev, void *addr,
522     pciaddr_t size)
523 {
524         struct pci_device_mapping map;
525
526         map.memory = addr;
527         map.size = size;
528         map.flags = 0;
529         return pci_device_openbsd_unmap_range(dev, &map);
530 }
531
532 static const struct pci_system_methods openbsd_pci_methods = {
533         pci_system_openbsd_destroy,
534         NULL,
535         pci_device_openbsd_read_rom,
536         pci_device_openbsd_probe,
537         pci_device_openbsd_map_range,
538         pci_device_openbsd_unmap_range,
539         pci_device_openbsd_read,
540         pci_device_openbsd_write,
541         pci_fill_capabilities_generic,
542         NULL,
543         NULL,
544         NULL,
545         NULL,
546         pci_device_openbsd_open_legacy_io,
547         NULL,
548         pci_device_openbsd_read32,
549         pci_device_openbsd_read16,
550         pci_device_openbsd_read8,
551         pci_device_openbsd_write32,
552         pci_device_openbsd_write16,
553         pci_device_openbsd_write8,
554         pci_device_openbsd_map_legacy,
555         pci_device_openbsd_unmap_legacy
556 };
557
558 int
559 pci_system_openbsd_create(void)
560 {
561         struct pci_device_private *device;
562         int domain, bus, dev, func, ndevs, nfuncs;
563         char path[MAXPATHLEN];
564         uint32_t reg;
565
566         if (ndomains > 0)
567                 return 0;
568
569         for (domain = 0; domain < sizeof(pcifd) / sizeof(pcifd[0]); domain++) {
570                 snprintf(path, sizeof(path), "/dev/pci%d", domain);
571                 pcifd[domain] = open(path, O_RDWR | O_CLOEXEC);
572                 if (pcifd[domain] == -1)
573                         break;
574                 ndomains++;
575         }
576
577         if (ndomains == 0)
578                 return ENXIO;
579
580         pci_sys = calloc(1, sizeof(struct pci_system));
581         if (pci_sys == NULL) {
582                 for (domain = 0; domain < ndomains; domain++)
583                         close(pcifd[domain]);
584                 ndomains = 0;
585                 return ENOMEM;
586         }
587
588         pci_sys->methods = &openbsd_pci_methods;
589
590         ndevs = 0;
591         for (domain = 0; domain < ndomains; domain++) {
592                 for (bus = 0; bus < 256; bus++) {
593                         for (dev = 0; dev < 32; dev++) {
594                                 nfuncs = pci_nfuncs(domain, bus, dev);
595                                 for (func = 0; func < nfuncs; func++) {
596                                         if (pci_read(domain, bus, dev, func,
597                                             PCI_ID_REG, &reg) != 0)
598                                                 continue;
599                                         if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID ||
600                                             PCI_VENDOR(reg) == 0)
601                                                 continue;
602
603                                         ndevs++;
604                                 }
605                         }
606                 }
607         }
608
609         pci_sys->num_devices = ndevs;
610         pci_sys->devices = calloc(ndevs, sizeof(struct pci_device_private));
611         if (pci_sys->devices == NULL) {
612                 free(pci_sys);
613                 pci_sys = NULL;
614                 for (domain = 0; domain < ndomains; domain++)
615                         close(pcifd[domain]);
616                 ndomains = 0;
617                 return ENOMEM;
618         }
619
620         device = pci_sys->devices;
621         for (domain = 0; domain < ndomains; domain++) {
622                 for (bus = 0; bus < 256; bus++) {
623                         for (dev = 0; dev < 32; dev++) {
624                                 nfuncs = pci_nfuncs(domain, bus, dev);
625                                 for (func = 0; func < nfuncs; func++) {
626                                         if (pci_read(domain, bus, dev, func,
627                                             PCI_ID_REG, &reg) != 0)
628                                                 continue;
629                                         if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID ||
630                                             PCI_VENDOR(reg) == 0)
631                                                 continue;
632
633                                         device->base.domain = domain;
634                                         device->base.bus = bus;
635                                         device->base.dev = dev;
636                                         device->base.func = func;
637                                         device->base.vendor_id = PCI_VENDOR(reg);
638                                         device->base.device_id = PCI_PRODUCT(reg);
639
640                                         if (pci_read(domain, bus, dev, func,
641                                             PCI_CLASS_REG, &reg) != 0)
642                                                 continue;
643
644                                         device->base.device_class =
645                                             PCI_INTERFACE(reg) |
646                                             PCI_CLASS(reg) << 16 |
647                                             PCI_SUBCLASS(reg) << 8;
648                                         device->base.revision = PCI_REVISION(reg);
649
650                                         if (pci_read(domain, bus, dev, func,
651                                             PCI_SUBVEND_0, &reg) != 0)
652                                                 continue;
653
654                                         device->base.subvendor_id = PCI_VENDOR(reg);
655                                         device->base.subdevice_id = PCI_PRODUCT(reg);
656
657                                         device->base.vgaarb_rsrc =
658                                             VGA_ARB_RSRC_LEGACY_IO |
659                                             VGA_ARB_RSRC_LEGACY_MEM;
660
661                                         device++;
662                                 }
663                         }
664                 }
665         }
666
667         return 0;
668 }
669
670 void
671 pci_system_openbsd_init_dev_mem(int fd)
672 {
673         aperturefd = fd;
674 }
675
676 int
677 pci_device_vgaarb_init(void)
678 {
679         struct pci_device *dev = pci_sys->vga_target;
680         struct pci_device_iterator *iter;
681         struct pci_id_match vga_match = {
682                 PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY,
683                 (PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8),
684                 0x00ffff00
685         };
686         struct pci_vga pv;
687         int err;
688
689         pv.pv_sel.pc_bus = 0;
690         pv.pv_sel.pc_dev = 0;
691         pv.pv_sel.pc_func = 0;
692         err = ioctl(pcifd[0], PCIOCGETVGA, &pv);
693         if (err)
694                 return err;
695
696         pci_sys->vga_target = pci_device_find_by_slot(0, pv.pv_sel.pc_bus,
697             pv.pv_sel.pc_dev, pv.pv_sel.pc_func);
698
699         /* Count the number of VGA devices in domain 0. */
700         iter = pci_id_match_iterator_create(&vga_match);
701         if (iter == NULL)
702                 return -1;
703         pci_sys->vga_count = 0;
704         while ((dev = pci_device_next(iter)) != NULL) {
705                 if (dev->domain == 0)
706                         pci_sys->vga_count++;
707         }
708         pci_iterator_destroy(iter);
709
710         return 0;
711 }
712
713 void
714 pci_device_vgaarb_fini(void)
715 {
716         struct pci_device *dev;
717         struct pci_vga pv;
718
719         if (pci_sys == NULL)
720                 return;
721         dev = pci_sys->vga_target;
722         if (dev == NULL)
723                 return;
724
725         pv.pv_sel.pc_bus = dev->bus;
726         pv.pv_sel.pc_dev = dev->dev;
727         pv.pv_sel.pc_func = dev->func;
728         pv.pv_lock = PCI_VGA_UNLOCK;
729         ioctl(pcifd[dev->domain], PCIOCSETVGA, &pv);
730 }
731
732 int
733 pci_device_vgaarb_set_target(struct pci_device *dev)
734 {
735         pci_sys->vga_target = dev;
736         return (0);
737 }
738
739 int
740 pci_device_vgaarb_lock(void)
741 {
742         struct pci_device *dev = pci_sys->vga_target;
743         struct pci_vga pv;
744
745         if (dev == NULL)
746                 return -1;
747
748 #if 0
749         if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
750                 return 0;
751 #else
752         if (pci_sys->vga_count == 1)
753                 return 0;
754 #endif
755
756         pv.pv_sel.pc_bus = dev->bus;
757         pv.pv_sel.pc_dev = dev->dev;
758         pv.pv_sel.pc_func = dev->func;
759         pv.pv_lock = PCI_VGA_LOCK;
760         return ioctl(pcifd[dev->domain], PCIOCSETVGA, &pv);
761 }
762
763 int
764 pci_device_vgaarb_unlock(void)
765 {
766         struct pci_device *dev = pci_sys->vga_target;
767         struct pci_vga pv;
768
769         if (dev == NULL)
770                 return -1;
771
772 #if 0
773         if (dev->vgaarb_rsrc == 0 || pci_sys->vga_count == 1)
774                 return 0;
775 #else
776         if (pci_sys->vga_count == 1)
777                 return 0;
778 #endif
779
780         pv.pv_sel.pc_bus = dev->bus;
781         pv.pv_sel.pc_dev = dev->dev;
782         pv.pv_sel.pc_func = dev->func;
783         pv.pv_lock = PCI_VGA_UNLOCK;
784         return ioctl(pcifd[dev->domain], PCIOCSETVGA, &pv);
785 }
786
787 int
788 pci_device_vgaarb_get_info(struct pci_device *dev, int *vga_count,
789     int *rsrc_decodes)
790 {
791         *vga_count = pci_sys->vga_count;
792
793         if (dev)
794                 *rsrc_decodes = dev->vgaarb_rsrc;
795
796         return 0;
797 }
798
799 int
800 pci_device_vgaarb_decodes(int rsrc_decodes)
801 {
802         struct pci_device *dev = pci_sys->vga_target;
803
804         if (dev == NULL)
805                 return -1;
806
807         dev->vgaarb_rsrc = rsrc_decodes;
808         return 0;
809 }