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