1 /* $OpenBSD: vga_pci.c,v 1.25 2006/11/27 18:04:28 gwk Exp $ */ 2 /* $NetBSD: vga_pci.c,v 1.3 1998/06/08 06:55:58 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 2001 Wasabi Systems, Inc. 6 * All rights reserved. 7 * 8 * Written by Frank van der Linden for Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed for the NetBSD Project by 21 * Wasabi Systems, Inc. 22 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 23 * or promote products derived from this software without specific prior 24 * written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 /* 39 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 40 * All rights reserved. 41 * 42 * Author: Chris G. Demetriou 43 * 44 * Permission to use, copy, modify and distribute this software and 45 * its documentation is hereby granted, provided that both the copyright 46 * notice and this permission notice appear in all copies of the 47 * software, derivative works or modified versions, and any portions 48 * thereof, and that both notices appear in supporting documentation. 49 * 50 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 51 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 52 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 53 * 54 * Carnegie Mellon requests users of this software to return to 55 * 56 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 57 * School of Computer Science 58 * Carnegie Mellon University 59 * Pittsburgh PA 15213-3890 60 * 61 * any improvements or extensions that they make and grant Carnegie the 62 * rights to redistribute these changes. 63 */ 64 65 #include "vga.h" 66 67 #include <sys/param.h> 68 #include <sys/systm.h> 69 #include <sys/kernel.h> 70 #include <sys/device.h> 71 #include <sys/malloc.h> 72 #include <sys/agpio.h> 73 74 #include <uvm/uvm.h> 75 76 #include <machine/bus.h> 77 78 #include <dev/pci/pcireg.h> 79 #include <dev/pci/pcivar.h> 80 #include <dev/pci/pcidevs.h> 81 82 #include <dev/ic/mc6845reg.h> 83 #include <dev/ic/pcdisplayvar.h> 84 #include <dev/ic/vgareg.h> 85 #include <dev/ic/vgavar.h> 86 #include <dev/pci/vga_pcivar.h> 87 88 89 #include <dev/wscons/wsconsio.h> 90 #include <dev/wscons/wsdisplayvar.h> 91 92 #ifdef VESAFB 93 #include <dev/vesa/vesabiosvar.h> 94 #endif 95 96 int vga_pci_match(struct device *, void *, void *); 97 void vga_pci_attach(struct device *, struct device *, void *); 98 paddr_t vga_pci_mmap(void* v, off_t off, int prot); 99 100 #ifdef VESAFB 101 int vesafb_putcmap(struct vga_pci_softc *, struct wsdisplay_cmap *); 102 int vesafb_getcmap(struct vga_pci_softc *, struct wsdisplay_cmap *); 103 #endif 104 105 struct cfattach vga_pci_ca = { 106 sizeof(struct vga_pci_softc), vga_pci_match, vga_pci_attach, 107 }; 108 109 int 110 vga_pci_match(struct device *parent, void *match, void *aux) 111 { 112 struct pci_attach_args *pa = aux; 113 int potential; 114 115 potential = 0; 116 117 /* 118 * If it's prehistoric/vga or display/vga, we might match. 119 * For the console device, this is jut a sanity check. 120 */ 121 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_PREHISTORIC && 122 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_PREHISTORIC_VGA) 123 potential = 1; 124 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY && 125 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA) 126 potential = 1; 127 128 if (!potential) 129 return (0); 130 131 /* check whether it is disabled by firmware */ 132 if ((pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) 133 & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) 134 != (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE)) 135 return (0); 136 137 /* If it's the console, we have a winner! */ 138 if (vga_is_console(pa->pa_iot, WSDISPLAY_TYPE_PCIVGA)) 139 return (1); 140 141 /* 142 * If we might match, make sure that the card actually looks OK. 143 */ 144 if (!vga_common_probe(pa->pa_iot, pa->pa_memt)) 145 return (0); 146 147 return (1); 148 } 149 150 void 151 vga_pci_attach(struct device *parent, struct device *self, void *aux) 152 { 153 struct pci_attach_args *pa = aux; 154 pcireg_t reg; 155 #ifdef VESAFB 156 struct vga_pci_softc *sc = (struct vga_pci_softc *)self; 157 #endif 158 159 /* 160 * Enable bus master; X might need this for accelerated graphics. 161 */ 162 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 163 reg |= PCI_COMMAND_MASTER_ENABLE; 164 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg); 165 166 #ifdef PCIAGP 167 agp_attach(parent, self, aux); 168 #endif 169 #ifdef VESAFB 170 if (vesabios_softc != NULL && vesabios_softc->sc_nmodes > 0) { 171 sc->sc_textmode = vesafb_get_mode(sc); 172 printf(", vesafb\n"); 173 vga_extended_attach(self, pa->pa_iot, pa->pa_memt, 174 WSDISPLAY_TYPE_PCIVGA, vga_pci_mmap); 175 return; 176 } 177 #endif 178 printf("\n"); 179 vga_common_attach(self, pa->pa_iot, pa->pa_memt, 180 WSDISPLAY_TYPE_PCIVGA); 181 } 182 183 paddr_t 184 vga_pci_mmap(void *v, off_t off, int prot) 185 { 186 #ifdef VESAFB 187 struct vga_config *vc = (struct vga_config *)v; 188 struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc; 189 190 if (sc->sc_mode == WSDISPLAYIO_MODE_DUMBFB) { 191 return atop(sc->sc_base + off); 192 } 193 #endif 194 #ifdef PCIAGP 195 return agp_mmap(v, off, prot); 196 #else 197 return -1; 198 #endif 199 } 200 201 int 202 vga_pci_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, 203 pci_chipset_tag_t pc, int bus, int device, int function) 204 { 205 return (vga_cnattach(iot, memt, WSDISPLAY_TYPE_PCIVGA, 0)); 206 } 207 208 int 209 vga_pci_ioctl(void *v, u_long cmd, caddr_t addr, int flag, struct proc *pb) 210 { 211 int error = 0; 212 #ifdef VESAFB 213 struct vga_config *vc = (struct vga_config *)v; 214 struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc; 215 struct wsdisplay_fbinfo *wdf; 216 struct wsdisplay_gfx_mode *gfxmode; 217 int mode; 218 #endif 219 220 switch (cmd) { 221 #ifdef VESAFB 222 case WSDISPLAYIO_SMODE: 223 mode = *(u_int *)addr; 224 switch (mode) { 225 case WSDISPLAYIO_MODE_EMUL: 226 /* back to text mode */ 227 vesafb_set_mode(sc, sc->sc_textmode); 228 sc->sc_mode = mode; 229 break; 230 case WSDISPLAYIO_MODE_DUMBFB: 231 if (sc->sc_gfxmode == -1) 232 return (-1); 233 vesafb_set_mode(sc, sc->sc_gfxmode); 234 sc->sc_mode = mode; 235 break; 236 default: 237 error = -1; 238 } 239 break; 240 case WSDISPLAYIO_GINFO: 241 if (sc->sc_gfxmode == -1) 242 return (-1); 243 wdf = (void *)addr; 244 wdf->height = sc->sc_height; 245 wdf->width = sc->sc_width; 246 wdf->depth = sc->sc_depth; 247 wdf->cmsize = 256; 248 break; 249 250 case WSDISPLAYIO_LINEBYTES: 251 if (sc->sc_gfxmode == -1) 252 return (-1); 253 *(u_int *)addr = sc->sc_linebytes; 254 break; 255 256 case WSDISPLAYIO_SVIDEO: 257 case WSDISPLAYIO_GVIDEO: 258 break; 259 case WSDISPLAYIO_GETCMAP: 260 if (sc->sc_depth == 8) 261 error = vesafb_getcmap(sc, 262 (struct wsdisplay_cmap *)addr); 263 break; 264 265 case WSDISPLAYIO_PUTCMAP: 266 if (sc->sc_depth == 8) 267 error = vesafb_putcmap(sc, 268 (struct wsdisplay_cmap *)addr); 269 break; 270 271 case WSDISPLAYIO_GETSUPPORTEDDEPTH: 272 *(int *)addr = vesafb_get_supported_depth(sc); 273 break; 274 275 case WSDISPLAYIO_SETGFXMODE: 276 gfxmode = (struct wsdisplay_gfx_mode *)addr; 277 sc->sc_gfxmode = vesafb_find_mode(sc, gfxmode->width, 278 gfxmode->height, gfxmode->depth); 279 if (sc->sc_gfxmode == -1) 280 error = -1; 281 break; 282 283 #endif 284 #ifdef PCIAGP 285 case AGPIOC_INFO: 286 case AGPIOC_ACQUIRE: 287 case AGPIOC_RELEASE: 288 case AGPIOC_SETUP: 289 case AGPIOC_ALLOCATE: 290 case AGPIOC_DEALLOCATE: 291 case AGPIOC_BIND: 292 case AGPIOC_UNBIND: 293 error = agp_ioctl(v, cmd, addr, flag, pb); 294 break; 295 #endif 296 default: 297 error = ENOTTY; 298 } 299 300 return (error); 301 } 302 303 #ifdef notyet 304 void 305 vga_pci_close(void *v) 306 { 307 #ifdef PCIAGP 308 agp_close(v); 309 #endif 310 } 311 #endif 312