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