xref: /openbsd-src/sys/dev/pci/vga_pci_common.c (revision 9b9d2a55a62c8e82206c25f94fcc7f4e2765250e)
1 /*
2  * Copyright (c) 2008 Owain G. Ainsworth <oga@nicotinebsd.org>
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 "vga.h"
18 #include "drm.h"
19 #if defined(__i386__) || defined(__amd64__)
20 #include "acpi.h"
21 #endif
22 
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/malloc.h>
26 
27 #include <machine/bus.h>
28 
29 #include <dev/pci/pcireg.h>
30 #include <dev/pci/pcivar.h>
31 #include <dev/pci/pcidevs.h>
32 
33 #include <dev/ic/mc6845reg.h>
34 #include <dev/ic/pcdisplayvar.h>
35 #include <dev/ic/vgareg.h>
36 
37 #include <dev/wscons/wsdisplayvar.h>
38 #include <dev/ic/vgavar.h>
39 #include <dev/pci/vga_pcivar.h>
40 
41 #include <dev/pci/drm/i915/i915_devlist.h>
42 #include <dev/pci/drm/radeon/radeon_devlist.h>
43 
44 #if NDRM > 0
45 int
46 vga_drmsubmatch(struct device *parent, void *match, void *aux)
47 {
48 	struct cfdata *cf = match;
49 	struct cfdriver *cd;
50 	size_t len = 0;
51 	char *sm;
52 
53 	cd = cf->cf_driver;
54 
55 	/* is this a *drm device? */
56 	len = strlen(cd->cd_name);
57 	sm = cd->cd_name + len - 3;
58 	if (strncmp(sm, "drm", 3) == 0)
59 		return ((*cf->cf_attach->ca_match)(parent, match, aux));
60 
61 	return (0);
62 }
63 #endif
64 
65 /*
66  * Prepare dev->bars to be used for information. we do this at startup
67  * so we can do the whole array at once, dealing with 64-bit BARs correctly.
68  */
69 void
70 vga_pci_bar_init(struct vga_pci_softc *dev, struct pci_attach_args *pa)
71 {
72 	pcireg_t type;
73 	int addr = PCI_MAPREG_START, i = 0;
74 	memcpy(&dev->pa, pa, sizeof(dev->pa));
75 
76 	while (i < VGA_PCI_MAX_BARS) {
77 		dev->bars[i] = malloc(sizeof((*dev->bars[i])), M_DEVBUF,
78 		    M_NOWAIT | M_ZERO);
79 		if (dev->bars[i] == NULL) {
80 			return;
81 		}
82 
83 		dev->bars[i]->addr = addr;
84 
85 		type = dev->bars[i]->maptype = pci_mapreg_type(pa->pa_pc,
86 		    pa->pa_tag, addr);
87 		if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, addr,
88 		    dev->bars[i]->maptype, &dev->bars[i]->base,
89 		    &dev->bars[i]->maxsize, &dev->bars[i]->flags) != 0) {
90 			free(dev->bars[i], M_DEVBUF, 0);
91 			dev->bars[i] = NULL;
92 		}
93 
94 		if (type == PCI_MAPREG_MEM_TYPE_64BIT) {
95 			addr += 8;
96 			i += 2;
97 		} else {
98 			addr += 4;
99 			i++;
100 		}
101 	}
102 }
103 
104 /*
105  * Get the vga_pci_bar struct for the address in question. returns NULL if
106  * invalid BAR is passed.
107  */
108 struct vga_pci_bar*
109 vga_pci_bar_info(struct vga_pci_softc *dev, int no)
110 {
111 	if (dev == NULL || no >= VGA_PCI_MAX_BARS)
112 		return (NULL);
113 	return (dev->bars[no]);
114 }
115 
116 /*
117  * map the BAR in question, returning the vga_pci_bar struct in case any more
118  * processing needs to be done. Returns NULL on failure. Can be called multiple
119  * times.
120  */
121 struct vga_pci_bar*
122 vga_pci_bar_map(struct vga_pci_softc *dev, int addr, bus_size_t size,
123     int busflags)
124 {
125 	struct vga_pci_bar *bar = NULL;
126 	int i;
127 
128 	if (dev == NULL)
129 		return (NULL);
130 
131 	for (i = 0; i < VGA_PCI_MAX_BARS; i++) {
132 		if (dev->bars[i] && dev->bars[i]->addr == addr) {
133 			bar = dev->bars[i];
134 			break;
135 		}
136 	}
137 	if (bar == NULL) {
138 		printf("vga_pci_bar_map: given invalid address 0x%x\n", addr);
139 		return (NULL);
140 	}
141 
142 	if (bar->mapped == 0) {
143 		if (pci_mapreg_map(&dev->pa, bar->addr, bar->maptype,
144 		    bar->flags | busflags, &bar->bst, &bar->bsh, NULL,
145 		    &bar->size, size)) {
146 			printf("vga_pci_bar_map: can't map bar 0x%x\n", addr);
147 			return (NULL);
148 		}
149 	}
150 
151 	bar->mapped++;
152 	return (bar);
153 }
154 
155 /*
156  * "unmap" the BAR referred to by argument. If more than one place has mapped it
157  * we just decrement the reference counter so nothing untoward happens.
158  */
159 void
160 vga_pci_bar_unmap(struct vga_pci_bar *bar)
161 {
162 	if (bar != NULL && bar->mapped != 0) {
163 		if (--bar->mapped == 0)
164 			bus_space_unmap(bar->bst, bar->bsh, bar->size);
165 	}
166 }
167 
168 #ifdef RAMDISK_HOOKS
169 static const struct pci_matchid aperture_blacklist[] = {
170 	/* server adapters found in mga200 drm driver */
171 	{ PCI_VENDOR_MATROX,	PCI_PRODUCT_MATROX_G200E_SE },
172 	{ PCI_VENDOR_MATROX,	PCI_PRODUCT_MATROX_G200E_SE_B },
173 	{ PCI_VENDOR_MATROX,	PCI_PRODUCT_MATROX_G200EH },
174 	{ PCI_VENDOR_MATROX,	PCI_PRODUCT_MATROX_G200ER },
175 	{ PCI_VENDOR_MATROX,	PCI_PRODUCT_MATROX_G200EV },
176 	{ PCI_VENDOR_MATROX,	PCI_PRODUCT_MATROX_G200EW },
177 
178 	/* server adapters found in ast drm driver */
179 	{ PCI_VENDOR_ASPEED,	PCI_PRODUCT_ASPEED_AST2000 },
180 	{ PCI_VENDOR_ASPEED,	PCI_PRODUCT_ASPEED_AST2100 },
181 
182 	/* ati adapters found in servers */
183 	{ PCI_VENDOR_ATI,		PCI_PRODUCT_ATI_RAGEXL },
184 	{ PCI_VENDOR_ATI,		PCI_PRODUCT_ATI_ES1000 },
185 
186 	/* xgi found in some poweredges/supermicros/tyans */
187 	{ PCI_VENDOR_XGI,		PCI_PRODUCT_XGI_VOLARI_Z7 },
188 	{ PCI_VENDOR_XGI,		PCI_PRODUCT_XGI_VOLARI_Z9 },
189 };
190 
191 int
192 vga_aperture_needed(struct pci_attach_args *pa)
193 {
194 #if defined(__i386__) || defined(__amd64__) || \
195     defined(__sparc64__) || defined(__macppc__)
196 	if (pci_matchbyid(pa, i915_devices, nitems(i915_devices)) ||
197 	    pci_matchbyid(pa, radeon_devices, nitems(radeon_devices)) ||
198 	    pci_matchbyid(pa, aperture_blacklist, nitems(aperture_blacklist)))
199 		return (0);
200 #endif
201 	return (1);
202 }
203 #endif /* RAMDISK_HOOKS */
204