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