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