1 /* $OpenBSD: vgafb.c,v 1.2 2001/12/14 19:17:02 jason Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Jason L. Wright (jason@thought.net) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Jason L. Wright 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/errno.h> 38 #include <sys/device.h> 39 #include <sys/ioctl.h> 40 #include <sys/malloc.h> 41 42 #include <machine/bus.h> 43 #include <machine/intr.h> 44 #include <machine/autoconf.h> 45 #include <machine/openfirm.h> 46 47 #include <dev/pci/pcivar.h> 48 #include <dev/wscons/wsconsio.h> 49 #include <dev/wscons/wsdisplayvar.h> 50 #include <dev/wscons/wscons_raster.h> 51 #include <dev/rcons/raster.h> 52 53 struct vgafb_softc { 54 struct device sc_dev; 55 struct sbusdev sc_sd; 56 int sc_nscreens; 57 int sc_width, sc_height, sc_depth, sc_linebytes, sc_node; 58 bus_space_tag_t sc_bt; 59 bus_space_handle_t sc_bh; 60 struct rcons sc_rcons; 61 struct raster sc_raster; 62 }; 63 64 struct wsdisplay_emulops vgafb_emulops = { 65 rcons_cursor, 66 rcons_mapchar, 67 rcons_putchar, 68 rcons_copycols, 69 rcons_erasecols, 70 rcons_copyrows, 71 rcons_eraserows, 72 rcons_alloc_attr 73 }; 74 75 struct wsscreen_descr vgafb_stdscreen = { 76 "std", 77 0, 0, /* will be filled in -- XXX shouldn't, it's global. */ 78 0, 79 0, 0, 80 WSSCREEN_REVERSE 81 }; 82 83 const struct wsscreen_descr *vgafb_scrlist[] = { 84 &vgafb_stdscreen, 85 /* XXX other formats? */ 86 }; 87 88 struct wsscreen_list vgafb_screenlist = { 89 sizeof(vgafb_scrlist) / sizeof(struct wsscreen_descr *), vgafb_scrlist 90 }; 91 92 int vgafb_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 93 int vgafb_alloc_screen __P((void *, const struct wsscreen_descr *, void **, 94 int *, int *, long *)); 95 void vgafb_free_screen __P((void *, void *)); 96 int vgafb_show_screen __P((void *, void *, int, 97 void (*cb) __P((void *, int, int)), void *)); 98 paddr_t vgafb_mmap __P((void *, off_t, int)); 99 int vgafb_is_console __P((int)); 100 101 static int a2int __P((char *, int)); 102 103 struct wsdisplay_accessops vgafb_accessops = { 104 vgafb_ioctl, 105 vgafb_mmap, 106 vgafb_alloc_screen, 107 vgafb_free_screen, 108 vgafb_show_screen, 109 0 /* load_font */ 110 }; 111 112 int vgafbmatch __P((struct device *, void *, void *)); 113 void vgafbattach __P((struct device *, struct device *, void *)); 114 115 struct cfattach vgafb_ca = { 116 sizeof (struct vgafb_softc), vgafbmatch, vgafbattach 117 }; 118 119 struct cfdriver vgafb_cd = { 120 NULL, "vgafb", DV_DULL 121 }; 122 123 int 124 vgafbmatch(parent, vcf, aux) 125 struct device *parent; 126 void *vcf, *aux; 127 { 128 struct pci_attach_args *pa = aux; 129 130 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_PREHISTORIC && 131 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_PREHISTORIC_VGA) 132 return (1); 133 134 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY && 135 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA) 136 return (1); 137 138 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY && 139 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_MISC) 140 return (1); 141 142 return (0); 143 } 144 145 void 146 vgafbattach(parent, self, aux) 147 struct device *parent, *self; 148 void *aux; 149 { 150 struct vgafb_softc *sc = (struct vgafb_softc *)self; 151 struct pci_attach_args *pa = aux; 152 struct wsemuldisplaydev_attach_args waa; 153 bus_size_t memsize; 154 long defattr; 155 int console; 156 bus_addr_t membase; 157 158 sc->sc_node = PCITAG_NODE(pa->pa_tag); 159 160 sc->sc_depth = getpropint(sc->sc_node, "depth", -1); 161 if (sc->sc_depth == -1) 162 sc->sc_depth = 8; 163 164 sc->sc_linebytes = getpropint(sc->sc_node, "linebytes", -1); 165 if (sc->sc_linebytes == -1) 166 sc->sc_linebytes = 1152; 167 168 sc->sc_height = getpropint(sc->sc_node, "height", -1); 169 if (sc->sc_height == -1) 170 sc->sc_height = 900; 171 172 sc->sc_width = getpropint(sc->sc_node, "width", -1); 173 if (sc->sc_width == -1) 174 sc->sc_width = 1152; 175 176 console = vgafb_is_console(sc->sc_node); 177 178 if (pci_mem_find(pa->pa_pc, pa->pa_tag, 0x10, 179 &membase, &memsize, NULL)) { 180 printf(": can't find mem space\n"); 181 goto fail; 182 } 183 if (bus_space_map2(pa->pa_memt, SBUS_BUS_SPACE, 184 membase, memsize, 0, NULL, &sc->sc_bh)) { 185 printf(": can't map mem space\n"); 186 goto fail; 187 } 188 sc->sc_bt = pa->pa_memt; 189 190 sc->sc_rcons.rc_sp = &sc->sc_raster; 191 sc->sc_raster.width = sc->sc_width; 192 sc->sc_raster.height = sc->sc_height; 193 sc->sc_raster.depth = sc->sc_depth; 194 sc->sc_raster.linelongs = sc->sc_linebytes / 4; 195 sc->sc_raster.pixels = (void *)sc->sc_bh; 196 197 if (console == 0 || 198 romgetcursoraddr(&sc->sc_rcons.rc_crowp, &sc->sc_rcons.rc_ccolp)) { 199 sc->sc_rcons.rc_crow = sc->sc_rcons.rc_ccol = -1; 200 sc->sc_rcons.rc_crowp = &sc->sc_rcons.rc_crow; 201 sc->sc_rcons.rc_ccolp = &sc->sc_rcons.rc_ccol; 202 } 203 204 sc->sc_rcons.rc_maxcol = 205 a2int(getpropstring(optionsnode, "screen-#columns"), 80); 206 sc->sc_rcons.rc_maxrow = 207 a2int(getpropstring(optionsnode, "screen-#rows"), 34); 208 209 rcons_init(&sc->sc_rcons, 210 sc->sc_rcons.rc_maxrow, sc->sc_rcons.rc_maxcol); 211 212 vgafb_stdscreen.nrows = sc->sc_rcons.rc_maxrow; 213 vgafb_stdscreen.ncols = sc->sc_rcons.rc_maxcol; 214 vgafb_stdscreen.textops = &vgafb_emulops; 215 rcons_alloc_attr(&sc->sc_rcons, 0, 0, 0, &defattr); 216 217 printf("\n"); 218 219 if (console) 220 wsdisplay_cnattach(&vgafb_stdscreen, &sc->sc_rcons, 221 *sc->sc_rcons.rc_ccolp, *sc->sc_rcons.rc_crowp, defattr); 222 223 waa.console = console; 224 waa.scrdata = &vgafb_screenlist; 225 waa.accessops = &vgafb_accessops; 226 waa.accesscookie = sc; 227 config_found(self, &waa, wsemuldisplaydevprint); 228 229 return; 230 fail: 231 } 232 233 int 234 vgafb_ioctl(v, cmd, data, flags, p) 235 void *v; 236 u_long cmd; 237 caddr_t data; 238 int flags; 239 struct proc *p; 240 { 241 struct vgafb_softc *sc = v; 242 struct wsdisplay_fbinfo *wdf; 243 244 switch (cmd) { 245 case WSDISPLAYIO_GTYPE: 246 *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; 247 break; 248 case WSDISPLAYIO_GINFO: 249 wdf = (void *)data; 250 wdf->height = sc->sc_height; 251 wdf->width = sc->sc_width; 252 wdf->depth = sc->sc_depth; 253 wdf->cmsize = 256; 254 break; 255 case WSDISPLAYIO_LINEBYTES: 256 *(u_int *)data = sc->sc_linebytes; 257 break; 258 259 #if 0 260 case WSDISPLAYIO_GETCMAP: 261 return vgafb_getcmap(vc, (struct wsdisplay_cmap *)data); 262 case WSDISPLAYIO_PUTCMAP: 263 return vgafb_putcmap(vc, (struct wsdisplay_cmap *)data); 264 #endif 265 266 case WSDISPLAYIO_SVIDEO: 267 case WSDISPLAYIO_GVIDEO: 268 case WSDISPLAYIO_GCURPOS: 269 case WSDISPLAYIO_SCURPOS: 270 case WSDISPLAYIO_GCURMAX: 271 case WSDISPLAYIO_GCURSOR: 272 case WSDISPLAYIO_SCURSOR: 273 default: 274 return -1; /* not supported yet */ 275 } 276 277 return (0); 278 } 279 280 int 281 vgafb_alloc_screen(v, type, cookiep, curxp, curyp, attrp) 282 void *v; 283 const struct wsscreen_descr *type; 284 void **cookiep; 285 int *curxp, *curyp; 286 long *attrp; 287 { 288 struct vgafb_softc *sc = v; 289 290 if (sc->sc_nscreens > 0) 291 return (ENOMEM); 292 293 *cookiep = &sc->sc_rcons; 294 *curyp = *sc->sc_rcons.rc_crowp; 295 *curxp = *sc->sc_rcons.rc_ccolp; 296 rcons_alloc_attr(&sc->sc_rcons, 0, 0, 0, attrp); 297 sc->sc_nscreens++; 298 return (0); 299 } 300 301 void 302 vgafb_free_screen(v, cookie) 303 void *v; 304 void *cookie; 305 { 306 struct vgafb_softc *sc = v; 307 308 sc->sc_nscreens--; 309 } 310 311 int 312 vgafb_show_screen(v, cookie, waitok, cb, cbarg) 313 void *v; 314 void *cookie; 315 int waitok; 316 void (*cb) __P((void *, int, int)); 317 void *cbarg; 318 { 319 return (0); 320 } 321 322 paddr_t 323 vgafb_mmap(v, offset, prot) 324 void *v; 325 off_t offset; 326 int prot; 327 { 328 #if 0 329 struct vgafb_softc *sc = v; 330 #endif 331 332 if (offset & PGOFSET) 333 return (-1); 334 return (-1); 335 } 336 337 static int 338 a2int(char *cp, int deflt) 339 { 340 int i = 0; 341 342 if (*cp == '\0') 343 return (deflt); 344 while (*cp != '\0') 345 i = i * 10 + *cp++ - '0'; 346 return (i); 347 } 348 349 int 350 vgafb_is_console(node) 351 int node; 352 { 353 extern int fbnode; 354 355 return (fbnode == node); 356 } 357