xref: /netbsd-src/sys/dev/pci/vga_pci.c (revision 13d4bb4cc874de96add7fc4227d38a1d656b03d1)
1*13d4bb4cSthorpej /*	$NetBSD: vga_pci.c,v 1.59 2022/09/25 17:52:25 thorpej Exp $	*/
2013507e3Sdrochner 
3013507e3Sdrochner /*
4013507e3Sdrochner  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
5013507e3Sdrochner  * All rights reserved.
6013507e3Sdrochner  *
7013507e3Sdrochner  * Author: Chris G. Demetriou
8013507e3Sdrochner  *
9013507e3Sdrochner  * Permission to use, copy, modify and distribute this software and
10013507e3Sdrochner  * its documentation is hereby granted, provided that both the copyright
11013507e3Sdrochner  * notice and this permission notice appear in all copies of the
12013507e3Sdrochner  * software, derivative works or modified versions, and any portions
13013507e3Sdrochner  * thereof, and that both notices appear in supporting documentation.
14013507e3Sdrochner  *
15013507e3Sdrochner  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16013507e3Sdrochner  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17013507e3Sdrochner  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18013507e3Sdrochner  *
19013507e3Sdrochner  * Carnegie Mellon requests users of this software to return to
20013507e3Sdrochner  *
21013507e3Sdrochner  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22013507e3Sdrochner  *  School of Computer Science
23013507e3Sdrochner  *  Carnegie Mellon University
24013507e3Sdrochner  *  Pittsburgh PA 15213-3890
25013507e3Sdrochner  *
26013507e3Sdrochner  * any improvements or extensions that they make and grant Carnegie the
27013507e3Sdrochner  * rights to redistribute these changes.
28013507e3Sdrochner  */
29013507e3Sdrochner 
309048aaaeSlukem #include <sys/cdefs.h>
31*13d4bb4cSthorpej __KERNEL_RCSID(0, "$NetBSD: vga_pci.c,v 1.59 2022/09/25 17:52:25 thorpej Exp $");
329048aaaeSlukem 
33013507e3Sdrochner #include <sys/param.h>
34013507e3Sdrochner #include <sys/systm.h>
35013507e3Sdrochner #include <sys/kernel.h>
36013507e3Sdrochner #include <sys/device.h>
37013507e3Sdrochner 
38013507e3Sdrochner #include <dev/pci/pcireg.h>
39013507e3Sdrochner #include <dev/pci/pcivar.h>
40013507e3Sdrochner #include <dev/pci/pcidevs.h>
415b09c93aSthorpej #include <dev/pci/pciio.h>
42013507e3Sdrochner 
43b84dbbb3Sdrochner #include <dev/ic/mc6845reg.h>
44b84dbbb3Sdrochner #include <dev/ic/pcdisplayvar.h>
45013507e3Sdrochner #include <dev/ic/vgareg.h>
46013507e3Sdrochner #include <dev/ic/vgavar.h>
47013507e3Sdrochner #include <dev/pci/vga_pcivar.h>
48013507e3Sdrochner 
49915af95aSthorpej #include <dev/isa/isareg.h>	/* For legacy VGA address ranges */
50915af95aSthorpej 
51013507e3Sdrochner #include <dev/wscons/wsconsio.h>
52013507e3Sdrochner #include <dev/wscons/wsdisplayvar.h>
53e28cc170Scegger #include <dev/pci/wsdisplay_pci.h>
54013507e3Sdrochner 
559a98cd19Sjoerg #include "opt_vga.h"
569a98cd19Sjoerg 
579a98cd19Sjoerg #ifdef VGA_POST
583ea923f7Sjoerg #  if defined(__i386__) || defined(__amd64__)
59a3abcdbcSjmcneill #    include "acpica.h"
603ea923f7Sjoerg #  endif
619a98cd19Sjoerg #include <x86/vga_post.h>
629a98cd19Sjoerg #endif
639a98cd19Sjoerg 
64915af95aSthorpej #define	NBARS		6	/* number of PCI BARs */
65915af95aSthorpej 
66915af95aSthorpej struct vga_bar {
67915af95aSthorpej 	bus_addr_t vb_base;
68915af95aSthorpej 	bus_size_t vb_size;
69915af95aSthorpej 	pcireg_t vb_type;
70915af95aSthorpej 	int vb_flags;
71915af95aSthorpej };
72915af95aSthorpej 
73013507e3Sdrochner struct vga_pci_softc {
74b9fffe19Sthorpej 	struct vga_softc sc_vga;
75013507e3Sdrochner 
765b09c93aSthorpej 	pci_chipset_tag_t sc_pc;
77b9fffe19Sthorpej 	pcitag_t sc_pcitag;
78915af95aSthorpej 
79915af95aSthorpej 	struct vga_bar sc_bars[NBARS];
80915af95aSthorpej 	struct vga_bar sc_rom;
814c1d81b2Sjmcneill 
829a98cd19Sjoerg #ifdef VGA_POST
839a98cd19Sjoerg 	struct vga_post *sc_posth;
849a98cd19Sjoerg #endif
854db90e1fSjmcneill 
864db90e1fSjmcneill 	struct pci_attach_args sc_paa;
87013507e3Sdrochner };
88013507e3Sdrochner 
89a591bc88Scegger static int	vga_pci_match(device_t, cfdata_t, void *);
90a591bc88Scegger static void	vga_pci_attach(device_t, device_t, void *);
91a591bc88Scegger static int	vga_pci_rescan(device_t, const char *, const int *);
929b3975fdSdrochner static int	vga_pci_lookup_quirks(struct pci_attach_args *);
93c1b390d4Sdyoung static bool	vga_pci_resume(device_t dv, const pmf_qual_t *);
94013507e3Sdrochner 
954db90e1fSjmcneill CFATTACH_DECL2_NEW(vga_pci, sizeof(struct vga_pci_softc),
964db90e1fSjmcneill     vga_pci_match, vga_pci_attach, NULL, NULL, vga_pci_rescan, NULL);
97013507e3Sdrochner 
9853524e44Schristos static int	vga_pci_ioctl(void *, u_long, void *, int, struct lwp *);
99d36c43c5Sthorpej static paddr_t	vga_pci_mmap(void *, off_t, int);
1005b09c93aSthorpej 
101d36c43c5Sthorpej static const struct vga_funcs vga_pci_funcs = {
1025b09c93aSthorpej 	vga_pci_ioctl,
1035b09c93aSthorpej 	vga_pci_mmap,
1045b09c93aSthorpej };
1055b09c93aSthorpej 
1069b3975fdSdrochner static const struct {
1079b3975fdSdrochner 	int id;
1089b3975fdSdrochner 	int quirks;
1099b3975fdSdrochner } vga_pci_quirks[] = {
1101014d5a4Ssalo 	{PCI_ID_CODE(PCI_VENDOR_SILMOTION, PCI_PRODUCT_SILMOTION_SM712),
11132f7789dSdrochner 	 VGA_QUIRK_NOFASTSCROLL},
1123a1b5ff0Sshattered 	{PCI_ID_CODE(PCI_VENDOR_CYRIX, PCI_PRODUCT_CYRIX_CX5530_VIDEO),
1133a1b5ff0Sshattered 	 VGA_QUIRK_NOFASTSCROLL},
1149b3975fdSdrochner };
1158ae04c4bSdrochner 
1168ae04c4bSdrochner static const struct {
1178ae04c4bSdrochner 	int vid;
1188ae04c4bSdrochner 	int quirks;
1198ae04c4bSdrochner } vga_pci_vquirks[] = {
1208ae04c4bSdrochner 	{PCI_VENDOR_ATI, VGA_QUIRK_ONEFONT},
1218ae04c4bSdrochner };
1229b3975fdSdrochner 
1239b3975fdSdrochner static int
vga_pci_lookup_quirks(struct pci_attach_args * pa)124d36c43c5Sthorpej vga_pci_lookup_quirks(struct pci_attach_args *pa)
1259b3975fdSdrochner {
1269b3975fdSdrochner 	int i;
1279b3975fdSdrochner 
1289b3975fdSdrochner 	for (i = 0; i < sizeof(vga_pci_quirks) / sizeof (vga_pci_quirks[0]);
1299b3975fdSdrochner 	     i++) {
1309b3975fdSdrochner 		if (vga_pci_quirks[i].id == pa->pa_id)
1319b3975fdSdrochner 			return (vga_pci_quirks[i].quirks);
1329b3975fdSdrochner 	}
1338ae04c4bSdrochner 	for (i = 0; i < sizeof(vga_pci_vquirks) / sizeof (vga_pci_vquirks[0]);
1348ae04c4bSdrochner 	     i++) {
1358ae04c4bSdrochner 		if (vga_pci_vquirks[i].vid == PCI_VENDOR(pa->pa_id))
1368ae04c4bSdrochner 			return (vga_pci_vquirks[i].quirks);
1378ae04c4bSdrochner 	}
1389b3975fdSdrochner 	return (0);
1399b3975fdSdrochner }
1409b3975fdSdrochner 
141d36c43c5Sthorpej static int
vga_pci_match(device_t parent,cfdata_t match,void * aux)142a591bc88Scegger vga_pci_match(device_t parent, cfdata_t match, void *aux)
143013507e3Sdrochner {
144013507e3Sdrochner 	struct pci_attach_args *pa = aux;
145013507e3Sdrochner 	int potential;
146013507e3Sdrochner 
147013507e3Sdrochner 	potential = 0;
148013507e3Sdrochner 
149013507e3Sdrochner 	/*
150013507e3Sdrochner 	 * If it's prehistoric/vga or display/vga, we might match.
1518989ce5fSwiz 	 * For the console device, this is just a sanity check.
152013507e3Sdrochner 	 */
153013507e3Sdrochner 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_PREHISTORIC &&
154013507e3Sdrochner 	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_PREHISTORIC_VGA)
155013507e3Sdrochner 		potential = 1;
156013507e3Sdrochner 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
157013507e3Sdrochner 	     PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA)
158013507e3Sdrochner 		potential = 1;
159013507e3Sdrochner 
160013507e3Sdrochner 	if (!potential)
161013507e3Sdrochner 		return (0);
162013507e3Sdrochner 
163013507e3Sdrochner 	/* check whether it is disabled by firmware */
164013507e3Sdrochner 	if ((pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG)
165013507e3Sdrochner 	    & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
166013507e3Sdrochner 	    != (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
167013507e3Sdrochner 		return (0);
168013507e3Sdrochner 
169013507e3Sdrochner 	/* If it's the console, we have a winner! */
170013507e3Sdrochner 	if (vga_is_console(pa->pa_iot, WSDISPLAY_TYPE_PCIVGA))
171013507e3Sdrochner 		return (1);
172013507e3Sdrochner 
173013507e3Sdrochner 	/*
174013507e3Sdrochner 	 * If we might match, make sure that the card actually looks OK.
175013507e3Sdrochner 	 */
176013507e3Sdrochner 	if (!vga_common_probe(pa->pa_iot, pa->pa_memt))
177013507e3Sdrochner 		return (0);
178013507e3Sdrochner 
179013507e3Sdrochner 	return (1);
180013507e3Sdrochner }
181013507e3Sdrochner 
182d36c43c5Sthorpej static void
vga_pci_attach(device_t parent,device_t self,void * aux)183a591bc88Scegger vga_pci_attach(device_t parent, device_t self, void *aux)
184013507e3Sdrochner {
185d293cfcaScube 	struct vga_pci_softc *psc = device_private(self);
186b9fffe19Sthorpej 	struct vga_softc *sc = &psc->sc_vga;
187013507e3Sdrochner 	struct pci_attach_args *pa = aux;
188915af95aSthorpej 	int bar, reg;
189013507e3Sdrochner 
190d293cfcaScube 	sc->sc_dev = self;
1915b09c93aSthorpej 	psc->sc_pc = pa->pa_pc;
192b9fffe19Sthorpej 	psc->sc_pcitag = pa->pa_tag;
1934db90e1fSjmcneill 	psc->sc_paa = *pa;
194013507e3Sdrochner 
195d8e1a7b6Sdrochner 	pci_aprint_devinfo(pa, NULL);
196013507e3Sdrochner 
197915af95aSthorpej 	/*
198915af95aSthorpej 	 * Gather info about all the BARs.  These are used to allow
199915af95aSthorpej 	 * the X server to map the VGA device.
200915af95aSthorpej 	 */
201915af95aSthorpej 	for (bar = 0; bar < NBARS; bar++) {
202915af95aSthorpej 		reg = PCI_MAPREG_START + (bar * 4);
20334c0afbfSdrochner 		if (!pci_mapreg_probe(psc->sc_pc, psc->sc_pcitag, reg,
20434c0afbfSdrochner 				      &psc->sc_bars[bar].vb_type)) {
20534c0afbfSdrochner 			/* there is no valid mapping register */
20634c0afbfSdrochner 			continue;
20734c0afbfSdrochner 		}
208915af95aSthorpej 		if (PCI_MAPREG_TYPE(psc->sc_bars[bar].vb_type) ==
209915af95aSthorpej 		    PCI_MAPREG_TYPE_IO) {
210915af95aSthorpej 			/* Don't bother fetching I/O BARs. */
211915af95aSthorpej 			continue;
212915af95aSthorpej 		}
21324201ba6Smartin #ifndef __LP64__
214915af95aSthorpej 		if (PCI_MAPREG_MEM_TYPE(psc->sc_bars[bar].vb_type) ==
215915af95aSthorpej 		    PCI_MAPREG_MEM_TYPE_64BIT) {
216915af95aSthorpej 			/* XXX */
217d293cfcaScube 			aprint_error_dev(self,
218d293cfcaScube 			    "WARNING: ignoring 64-bit BAR @ 0x%02x\n", reg);
21934c0afbfSdrochner 			bar++;
220915af95aSthorpej 			continue;
221915af95aSthorpej 		}
22224201ba6Smartin #endif
22334c0afbfSdrochner 		if (pci_mapreg_info(psc->sc_pc, psc->sc_pcitag, reg,
224915af95aSthorpej 		     psc->sc_bars[bar].vb_type,
225915af95aSthorpej 		     &psc->sc_bars[bar].vb_base,
226915af95aSthorpej 		     &psc->sc_bars[bar].vb_size,
22734c0afbfSdrochner 		     &psc->sc_bars[bar].vb_flags))
228d293cfcaScube 			aprint_error_dev(self,
229d293cfcaScube 			    "WARNING: strange BAR @ 0x%02x\n", reg);
230915af95aSthorpej 	}
231915af95aSthorpej 
232e1d78452Sjdolecek 	/*
233e1d78452Sjdolecek 	 * Disable INTx interrupts, there is no specific chipset driver for
234e1d78452Sjdolecek 	 * this PCI device. Else unhandled display adapter interrupts
235e1d78452Sjdolecek 	 * might freeze the CPU.
236e1d78452Sjdolecek 	 */
237e1d78452Sjdolecek 	pcireg_t cmd  = pci_conf_read(pa->pa_pc, pa->pa_tag,
238e1d78452Sjdolecek 	    PCI_COMMAND_STATUS_REG);
239e1d78452Sjdolecek 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
240e1d78452Sjdolecek 	    cmd | PCI_COMMAND_INTERRUPT_DISABLE);
241e1d78452Sjdolecek 
242915af95aSthorpej 	/* XXX Expansion ROM? */
243915af95aSthorpej 
244b9fffe19Sthorpej 	vga_common_attach(sc, pa->pa_iot, pa->pa_memt, WSDISPLAY_TYPE_PCIVGA,
2459b3975fdSdrochner 			  vga_pci_lookup_quirks(pa), &vga_pci_funcs);
2462d9e04fcSdrochner 
2479a98cd19Sjoerg #ifdef VGA_POST
2488bc54e5bSmsaitoh 	psc->sc_posth = vga_post_init(pa->pa_bus, pa->pa_device,
2498bc54e5bSmsaitoh 	    pa->pa_function);
2509a98cd19Sjoerg 	if (psc->sc_posth == NULL)
2518bc54e5bSmsaitoh 		aprint_error_dev(self,
2528bc54e5bSmsaitoh 		    "WARNING: could not prepare POST handler\n");
2539a98cd19Sjoerg #endif
2549a98cd19Sjoerg 
2554c1d81b2Sjmcneill 	/*
2564c1d81b2Sjmcneill 	 * XXX Do not use the generic PCI framework for now as
2574c1d81b2Sjmcneill 	 * XXX it would power down the device when the console
2584c1d81b2Sjmcneill 	 * XXX is still using it.
2594c1d81b2Sjmcneill 	 */
2604c1d81b2Sjmcneill 	if (!pmf_device_register(self, NULL, vga_pci_resume))
2614c1d81b2Sjmcneill 		aprint_error_dev(self, "couldn't establish power handler\n");
2622685996bSthorpej 	config_found(self, aux, vga_drm_print,
263c7fb772bSthorpej 	    CFARGS(.iattr = "drm"));
264013507e3Sdrochner }
265013507e3Sdrochner 
2664db90e1fSjmcneill static int
vga_pci_rescan(device_t self,const char * ifattr,const int * locators)267a591bc88Scegger vga_pci_rescan(device_t self, const char *ifattr, const int *locators)
2684db90e1fSjmcneill {
2694db90e1fSjmcneill 	struct vga_pci_softc *psc = device_private(self);
2704db90e1fSjmcneill 
2712685996bSthorpej 	config_found(self, &psc->sc_paa, vga_drm_print,
272c7fb772bSthorpej 	    CFARGS(.iattr = "drm"));
2734db90e1fSjmcneill 
2744db90e1fSjmcneill 	return 0;
2754db90e1fSjmcneill }
2764db90e1fSjmcneill 
2774c1d81b2Sjmcneill static bool
vga_pci_resume(device_t dv,const pmf_qual_t * qual)278c1b390d4Sdyoung vga_pci_resume(device_t dv, const pmf_qual_t *qual)
2794c1d81b2Sjmcneill {
280a3abcdbcSjmcneill #if defined(VGA_POST) && NACPICA > 0
2810b2a6aefSjoerg 	extern int acpi_md_vbios_reset;
2820b2a6aefSjoerg #endif
2834c1d81b2Sjmcneill 	struct vga_pci_softc *sc = device_private(dv);
2844c1d81b2Sjmcneill 
2854c1d81b2Sjmcneill 	vga_resume(&sc->sc_vga);
2864c1d81b2Sjmcneill 
287a3abcdbcSjmcneill #if defined(VGA_POST) && NACPICA > 0
2880b2a6aefSjoerg 	if (sc->sc_posth != NULL && acpi_md_vbios_reset == 2)
2899a98cd19Sjoerg 		vga_post_call(sc->sc_posth);
2909a98cd19Sjoerg #endif
2919a98cd19Sjoerg 
2924c1d81b2Sjmcneill 	return true;
2934c1d81b2Sjmcneill }
2944c1d81b2Sjmcneill 
295013507e3Sdrochner int
vga_pci_cnattach(bus_space_tag_t iot,bus_space_tag_t memt,pci_chipset_tag_t pc,int bus,int device,int function)2969dbc5fd1Sjunyoung vga_pci_cnattach(bus_space_tag_t iot, bus_space_tag_t memt,
297168cd830Schristos     pci_chipset_tag_t pc, int bus, int device,
298168cd830Schristos     int function)
299013507e3Sdrochner {
30075cfc612Sjunyoung 
301013507e3Sdrochner 	return (vga_cnattach(iot, memt, WSDISPLAY_TYPE_PCIVGA, 0));
302013507e3Sdrochner }
3035b09c93aSthorpej 
3042d9e04fcSdrochner int
vga_drm_print(void * aux,const char * pnp)3052d9e04fcSdrochner vga_drm_print(void *aux, const char *pnp)
3062d9e04fcSdrochner {
3072d9e04fcSdrochner 	if (pnp)
3081a53395eSjmcneill 		aprint_normal("drm at %s", pnp);
3091a53395eSjmcneill 	return (UNCONF);
3102d9e04fcSdrochner }
3112d9e04fcSdrochner 
3122d9e04fcSdrochner 
313d36c43c5Sthorpej static int
vga_pci_ioctl(void * v,u_long cmd,void * data,int flag,struct lwp * l)31453524e44Schristos vga_pci_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
3155b09c93aSthorpej {
3165b09c93aSthorpej 	struct vga_config *vc = v;
3175b09c93aSthorpej 	struct vga_pci_softc *psc = (void *) vc->softc;
3185b09c93aSthorpej 
3195b09c93aSthorpej 	switch (cmd) {
3205b09c93aSthorpej 	/* PCI config read/write passthrough. */
3215b09c93aSthorpej 	case PCI_IOC_CFGREAD:
3225b09c93aSthorpej 	case PCI_IOC_CFGWRITE:
323ca7fa246Scegger 		return pci_devioctl(psc->sc_pc, psc->sc_pcitag,
324ca7fa246Scegger 		    cmd, data, flag, l);
3255b09c93aSthorpej 
326e28cc170Scegger 	case WSDISPLAYIO_GET_BUSID:
327e28cc170Scegger 		return wsdisplayio_busid_pci(vc->softc->sc_dev,
328e28cc170Scegger 		    psc->sc_pc, psc->sc_pcitag, data);
329e28cc170Scegger 
3305b09c93aSthorpej 	default:
331ca7fa246Scegger 		return EPASSTHROUGH;
3325b09c93aSthorpej 	}
3335b09c93aSthorpej }
3345b09c93aSthorpej 
335d36c43c5Sthorpej static paddr_t
vga_pci_mmap(void * v,off_t offset,int prot)3365b09c93aSthorpej vga_pci_mmap(void *v, off_t offset, int prot)
3375b09c93aSthorpej {
338915af95aSthorpej 	struct vga_config *vc = v;
339915af95aSthorpej 	struct vga_pci_softc *psc = (void *) vc->softc;
340915af95aSthorpej 	struct vga_bar *vb;
341915af95aSthorpej 	int bar;
3425b09c93aSthorpej 
343915af95aSthorpej 	for (bar = 0; bar < NBARS; bar++) {
344915af95aSthorpej 		vb = &psc->sc_bars[bar];
345915af95aSthorpej 		if (vb->vb_size == 0)
346915af95aSthorpej 			continue;
347915af95aSthorpej 		if (offset >= vb->vb_base &&
348915af95aSthorpej 		    offset < (vb->vb_base + vb->vb_size)) {
349915af95aSthorpej 			/* XXX This the right thing to do with flags? */
350915af95aSthorpej 			return (bus_space_mmap(vc->hdl.vh_memt, vb->vb_base,
351915af95aSthorpej 			    (offset - vb->vb_base), prot, vb->vb_flags));
352915af95aSthorpej 		}
353915af95aSthorpej 	}
354915af95aSthorpej 
355915af95aSthorpej 	/* XXX Expansion ROM? */
356915af95aSthorpej 
357915af95aSthorpej 	/*
358915af95aSthorpej 	 * Allow mmap access to the legacy ISA hole.  This is where
359915af95aSthorpej 	 * the legacy video BIOS will be located, and also where
360915af95aSthorpej 	 * the legacy VGA display buffer is located.
361915af95aSthorpej 	 *
362915af95aSthorpej 	 * XXX Security implications, here?
363915af95aSthorpej 	 */
364915af95aSthorpej 	if (offset >= IOM_BEGIN && offset < IOM_END)
365915af95aSthorpej 		return (bus_space_mmap(vc->hdl.vh_memt, IOM_BEGIN,
366915af95aSthorpej 		    (offset - IOM_BEGIN), prot, 0));
367915af95aSthorpej 
368486592abSmacallan #ifdef PCI_MAGIC_IO_RANGE
369486592abSmacallan 	/* allow to map our IO space on non-x86 machines */
370486592abSmacallan 	if ((offset >= PCI_MAGIC_IO_RANGE) &&
371486592abSmacallan 	    (offset < PCI_MAGIC_IO_RANGE + 0x10000)) {
372486592abSmacallan 		return bus_space_mmap(vc->hdl.vh_iot,
373486592abSmacallan 		    offset - PCI_MAGIC_IO_RANGE,
374486592abSmacallan 		    0, prot, BUS_SPACE_MAP_LINEAR);
375486592abSmacallan 	}
376486592abSmacallan #endif
377486592abSmacallan 
378915af95aSthorpej 	/* Range not found. */
3795b09c93aSthorpej 	return (-1);
3805b09c93aSthorpej }
381