1 /* $NetBSD: xafb.c,v 1.5 2002/10/02 04:27:51 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 Tsubai Masanari. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* "xa" frame buffer driver. Currently supports 1280x1024x8 only. */ 30 31 #include <sys/param.h> 32 #include <sys/buf.h> 33 #include <sys/device.h> 34 #include <sys/ioctl.h> 35 #include <sys/malloc.h> 36 #include <sys/systm.h> 37 38 #include <uvm/uvm_extern.h> 39 40 #include <machine/adrsmap.h> 41 #include <machine/apcall.h> 42 43 #include <dev/wscons/wsconsio.h> 44 #include <dev/wscons/wsdisplayvar.h> 45 #include <dev/rasops/rasops.h> 46 47 #include <newsmips/apbus/apbusvar.h> 48 49 struct xafb_reg { 50 volatile u_int r0; 51 volatile u_int index; 52 volatile u_int r2; 53 volatile u_int zero; 54 volatile u_int r4; 55 volatile u_int r5; 56 volatile u_int r6; 57 volatile u_int rgb; 58 }; 59 60 struct xafb_devconfig { 61 volatile u_char *dc_fbbase; /* VRAM base address */ 62 struct xafb_reg *dc_reg; /* register address */ 63 struct rasops_info dc_ri; 64 }; 65 66 struct xafb_softc { 67 struct device sc_dev; 68 struct xafb_devconfig *sc_dc; 69 int sc_nscreens; 70 u_char sc_cmap_red[256]; 71 u_char sc_cmap_green[256]; 72 u_char sc_cmap_blue[256]; 73 }; 74 75 int xafb_match __P((struct device *, struct cfdata *, void *)); 76 void xafb_attach __P((struct device *, struct device *, void *)); 77 78 int xafb_common_init __P((struct xafb_devconfig *)); 79 int xafb_is_console __P((void)); 80 81 int xafb_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 82 paddr_t xafb_mmap __P((void *, off_t, int)); 83 int xafb_alloc_screen __P((void *, const struct wsscreen_descr *, 84 void **, int *, int *, long *)); 85 void xafb_free_screen __P((void *, void *)); 86 int xafb_show_screen __P((void *, void *, int, 87 void (*) (void *, int, int), void *)); 88 89 int xafb_cnattach __P((void)); 90 int xafb_getcmap __P((struct xafb_softc *, struct wsdisplay_cmap *)); 91 int xafb_putcmap __P((struct xafb_softc *, struct wsdisplay_cmap *)); 92 93 static __inline void xafb_setcolor(struct xafb_devconfig *, int, int, int, int); 94 95 CFATTACH_DECL(xafb, sizeof(struct xafb_softc), 96 xafb_match, xafb_attach, NULL, NULL); 97 98 struct xafb_devconfig xafb_console_dc; 99 100 struct wsdisplay_accessops xafb_accessops = { 101 xafb_ioctl, 102 xafb_mmap, 103 xafb_alloc_screen, 104 xafb_free_screen, 105 xafb_show_screen, 106 NULL /* load_font */ 107 }; 108 109 struct wsscreen_descr xafb_stdscreen = { 110 "std", 111 0, 0, 112 0, 113 0, 0, 114 WSSCREEN_REVERSE 115 }; 116 117 const struct wsscreen_descr *xafb_scrlist[] = { 118 &xafb_stdscreen 119 }; 120 121 struct wsscreen_list xafb_screenlist = { 122 sizeof(xafb_scrlist) / sizeof(xafb_scrlist[0]), xafb_scrlist 123 }; 124 125 int 126 xafb_match(parent, match, aux) 127 struct device *parent; 128 struct cfdata *match; 129 void *aux; 130 { 131 struct apbus_attach_args *apa = aux; 132 133 if (strcmp(apa->apa_name, "xa") != 0) 134 return 0; 135 136 return 1; 137 } 138 139 void 140 xafb_attach(parent, self, aux) 141 struct device *parent, *self; 142 void *aux; 143 { 144 struct xafb_softc *sc = (void *)self; 145 struct apbus_attach_args *apa = aux; 146 struct wsemuldisplaydev_attach_args wsa; 147 struct xafb_devconfig *dc; 148 struct rasops_info *ri; 149 int console, i; 150 151 console = xafb_is_console(); 152 153 if (console) { 154 dc = &xafb_console_dc; 155 ri = &dc->dc_ri; 156 sc->sc_nscreens = 1; 157 } else { 158 dc = malloc(sizeof(struct xafb_devconfig), M_DEVBUF, M_WAITOK); 159 bzero(dc, sizeof(struct xafb_devconfig)); 160 161 dc->dc_fbbase = (void *)0xb0000000; /* XXX */ 162 dc->dc_reg = (void *)(apa->apa_hwbase + 0x3000); 163 if (xafb_common_init(dc) != 0) { 164 printf(": couldn't initialize device\n"); 165 return; 166 } 167 168 ri = &dc->dc_ri; 169 170 /* clear screen */ 171 (*ri->ri_ops.eraserows)(ri, 0, ri->ri_rows, 0); 172 } 173 sc->sc_dc = dc; 174 175 for (i = 0; i < 256; i++) { 176 sc->sc_cmap_red[i] = i; 177 sc->sc_cmap_green[i] = i; 178 sc->sc_cmap_blue[i] = i; 179 } 180 181 printf(": %d x %d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth); 182 183 wsa.console = console; 184 wsa.scrdata = &xafb_screenlist; 185 wsa.accessops = &xafb_accessops; 186 wsa.accesscookie = sc; 187 188 config_found(self, &wsa, wsemuldisplaydevprint); 189 } 190 191 void 192 xafb_setcolor(dc, index, r, g, b) 193 struct xafb_devconfig *dc; 194 int index, r, g, b; 195 { 196 volatile struct xafb_reg *reg = dc->dc_reg; 197 198 reg->index = index; 199 reg->zero = 0; 200 reg->rgb = r; 201 reg->rgb = g; 202 reg->rgb = b; 203 } 204 205 int 206 xafb_common_init(dc) 207 struct xafb_devconfig *dc; 208 { 209 struct rasops_info *ri = &dc->dc_ri; 210 int i; 211 212 for (i = 0; i < 256; i++) 213 xafb_setcolor(dc, i, i, i, i); 214 215 /* initialize rasops */ 216 ri->ri_width = 1280; 217 ri->ri_height = 1024; 218 ri->ri_depth = 8; 219 ri->ri_stride = 2048; 220 ri->ri_bits = (void *)dc->dc_fbbase; 221 ri->ri_flg = RI_FORCEMONO | RI_FULLCLEAR; 222 223 rasops_init(ri, 44, 100); 224 225 /* mono */ 226 ri->ri_devcmap[0] = 0; /* bg */ 227 ri->ri_devcmap[1] = 0xffffffff; /* fg */ 228 229 xafb_stdscreen.nrows = ri->ri_rows; 230 xafb_stdscreen.ncols = ri->ri_cols; 231 xafb_stdscreen.textops = &ri->ri_ops; 232 xafb_stdscreen.capabilities = ri->ri_caps; 233 234 return 0; 235 } 236 237 int 238 xafb_is_console() 239 { 240 volatile u_int *dipsw = (void *)NEWS5000_DIP_SWITCH; 241 242 if (*dipsw & 1) /* XXX right? */ 243 return 1; 244 245 return 0; 246 } 247 248 int 249 xafb_ioctl(v, cmd, data, flag, p) 250 void *v; 251 u_long cmd; 252 caddr_t data; 253 int flag; 254 struct proc *p; 255 { 256 struct xafb_softc *sc = v; 257 struct xafb_devconfig *dc = sc->sc_dc; 258 struct wsdisplay_fbinfo *wdf; 259 260 switch (cmd) { 261 case WSDISPLAYIO_GTYPE: 262 *(int *)data = WSDISPLAY_TYPE_UNKNOWN; /* XXX */ 263 return 0; 264 265 case WSDISPLAYIO_GINFO: 266 wdf = (void *)data; 267 wdf->height = dc->dc_ri.ri_height; 268 wdf->width = dc->dc_ri.ri_width; 269 wdf->depth = dc->dc_ri.ri_depth; 270 wdf->cmsize = 256; 271 return 0; 272 273 case WSDISPLAYIO_GETCMAP: 274 return xafb_getcmap(sc, (struct wsdisplay_cmap *)data); 275 276 case WSDISPLAYIO_PUTCMAP: 277 return xafb_putcmap(sc, (struct wsdisplay_cmap *)data); 278 279 /* case WSDISPLAYIO_SVIDEO: */ 280 } 281 return EPASSTHROUGH; 282 } 283 284 paddr_t 285 xafb_mmap(v, offset, prot) 286 void *v; 287 off_t offset; 288 int prot; 289 { 290 struct xafb_softc *sc = v; 291 struct xafb_devconfig *dc = sc->sc_dc; 292 struct rasops_info *ri = &dc->dc_ri; 293 294 if (offset >= (ri->ri_stride * ri->ri_height) || offset < 0) 295 return -1; 296 297 return mips_btop((int)dc->dc_fbbase + offset); 298 } 299 300 int 301 xafb_alloc_screen(v, scrdesc, cookiep, ccolp, crowp, attrp) 302 void *v; 303 const struct wsscreen_descr *scrdesc; 304 void **cookiep; 305 int *ccolp, *crowp; 306 long *attrp; 307 { 308 struct xafb_softc *sc = v; 309 struct rasops_info *ri = &sc->sc_dc->dc_ri; 310 long defattr; 311 312 if (sc->sc_nscreens > 0) 313 return ENOMEM; 314 315 *cookiep = ri; 316 *ccolp = *crowp = 0; 317 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 318 *attrp = defattr; 319 sc->sc_nscreens++; 320 321 return 0; 322 } 323 324 void 325 xafb_free_screen(v, cookie) 326 void *v; 327 void *cookie; 328 { 329 struct xafb_softc *sc = v; 330 331 if (sc->sc_dc == &xafb_console_dc) 332 panic("xafb_free_screen: console"); 333 334 sc->sc_nscreens--; 335 } 336 337 int 338 xafb_show_screen(v, cookie, waitok, cb, cbarg) 339 void *v; 340 void *cookie; 341 int waitok; 342 void (*cb) __P((void *, int, int)); 343 void *cbarg; 344 { 345 return 0; 346 } 347 348 int 349 xafb_cnattach() 350 { 351 struct xafb_devconfig *dc = &xafb_console_dc; 352 struct rasops_info *ri = &dc->dc_ri; 353 long defattr; 354 int crow = 0; 355 356 if (!xafb_is_console()) 357 return -1; 358 359 dc->dc_fbbase = (void *)0xb0000000; /* XXX */ 360 dc->dc_reg = (void *)0xb4903000; /* XXX */ 361 xafb_common_init(dc); 362 363 crow = 0; /* XXX current cursor pos */ 364 365 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 366 wsdisplay_cnattach(&xafb_stdscreen, &dc->dc_ri, 0, crow, defattr); 367 368 return 0; 369 } 370 371 int 372 xafb_getcmap(sc, cm) 373 struct xafb_softc *sc; 374 struct wsdisplay_cmap *cm; 375 { 376 u_int index = cm->index; 377 u_int count = cm->count; 378 int error; 379 380 if (index >= 256 || count > 256 || index + count > 256) 381 return EINVAL; 382 383 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 384 if (error) 385 return error; 386 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 387 if (error) 388 return error; 389 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 390 if (error) 391 return error; 392 393 return 0; 394 } 395 396 int 397 xafb_putcmap(sc, cm) 398 struct xafb_softc *sc; 399 struct wsdisplay_cmap *cm; 400 { 401 u_int index = cm->index; 402 u_int count = cm->count; 403 int i; 404 u_char *r, *g, *b; 405 406 if (index >= 256 || count > 256 || index + count > 256) 407 return EINVAL; 408 if (!uvm_useracc(cm->red, count, B_READ) || 409 !uvm_useracc(cm->green, count, B_READ) || 410 !uvm_useracc(cm->blue, count, B_READ)) 411 return EFAULT; 412 copyin(cm->red, &sc->sc_cmap_red[index], count); 413 copyin(cm->green, &sc->sc_cmap_green[index], count); 414 copyin(cm->blue, &sc->sc_cmap_blue[index], count); 415 416 r = &sc->sc_cmap_red[index]; 417 g = &sc->sc_cmap_green[index]; 418 b = &sc->sc_cmap_blue[index]; 419 420 for (i = 0; i < count; i++) 421 xafb_setcolor(sc->sc_dc, index++, *r++, *g++, *b++); 422 423 return 0; 424 } 425