1 /* $NetBSD: xafb.c,v 1.2 2002/03/17 19:40:46 atatat 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 struct cfattach xafb_ca = { 96 sizeof(struct xafb_softc), xafb_match, xafb_attach, 97 }; 98 99 struct xafb_devconfig xafb_console_dc; 100 101 struct wsdisplay_accessops xafb_accessops = { 102 xafb_ioctl, 103 xafb_mmap, 104 xafb_alloc_screen, 105 xafb_free_screen, 106 xafb_show_screen, 107 NULL /* load_font */ 108 }; 109 110 struct wsscreen_descr xafb_stdscreen = { 111 "std", 112 0, 0, 113 0, 114 0, 0, 115 WSSCREEN_REVERSE 116 }; 117 118 const struct wsscreen_descr *xafb_scrlist[] = { 119 &xafb_stdscreen 120 }; 121 122 struct wsscreen_list xafb_screenlist = { 123 sizeof(xafb_scrlist) / sizeof(xafb_scrlist[0]), xafb_scrlist 124 }; 125 126 int 127 xafb_match(parent, match, aux) 128 struct device *parent; 129 struct cfdata *match; 130 void *aux; 131 { 132 struct apbus_attach_args *apa = aux; 133 134 if (strcmp(apa->apa_name, "xa") != 0) 135 return 0; 136 137 return 1; 138 } 139 140 void 141 xafb_attach(parent, self, aux) 142 struct device *parent, *self; 143 void *aux; 144 { 145 struct xafb_softc *sc = (void *)self; 146 struct apbus_attach_args *apa = aux; 147 struct wsemuldisplaydev_attach_args wsa; 148 struct xafb_devconfig *dc; 149 struct rasops_info *ri; 150 int console, i; 151 152 console = xafb_is_console(); 153 154 if (console) { 155 dc = &xafb_console_dc; 156 ri = &dc->dc_ri; 157 sc->sc_nscreens = 1; 158 } else { 159 dc = malloc(sizeof(struct xafb_devconfig), M_DEVBUF, M_WAITOK); 160 bzero(dc, sizeof(struct xafb_devconfig)); 161 162 dc->dc_fbbase = (void *)0xb0000000; /* XXX */ 163 dc->dc_reg = (void *)(apa->apa_hwbase + 0x3000); 164 if (xafb_common_init(dc) != 0) { 165 printf(": couldn't initialize device\n"); 166 return; 167 } 168 169 ri = &dc->dc_ri; 170 171 /* clear screen */ 172 (*ri->ri_ops.eraserows)(ri, 0, ri->ri_rows, 0); 173 } 174 sc->sc_dc = dc; 175 176 for (i = 0; i < 256; i++) { 177 sc->sc_cmap_red[i] = i; 178 sc->sc_cmap_green[i] = i; 179 sc->sc_cmap_blue[i] = i; 180 } 181 182 printf(": %d x %d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth); 183 184 wsa.console = console; 185 wsa.scrdata = &xafb_screenlist; 186 wsa.accessops = &xafb_accessops; 187 wsa.accesscookie = sc; 188 189 config_found(self, &wsa, wsemuldisplaydevprint); 190 } 191 192 void 193 xafb_setcolor(dc, index, r, g, b) 194 struct xafb_devconfig *dc; 195 int index, r, g, b; 196 { 197 volatile struct xafb_reg *reg = dc->dc_reg; 198 199 reg->index = index; 200 reg->zero = 0; 201 reg->rgb = r; 202 reg->rgb = g; 203 reg->rgb = b; 204 } 205 206 int 207 xafb_common_init(dc) 208 struct xafb_devconfig *dc; 209 { 210 struct rasops_info *ri = &dc->dc_ri; 211 int i; 212 213 for (i = 0; i < 256; i++) 214 xafb_setcolor(dc, i, i, i, i); 215 216 /* initialize rasops */ 217 ri->ri_width = 1280; 218 ri->ri_height = 1024; 219 ri->ri_depth = 8; 220 ri->ri_stride = 2048; 221 ri->ri_bits = (void *)dc->dc_fbbase; 222 ri->ri_flg = RI_FORCEMONO | RI_FULLCLEAR; 223 224 rasops_init(ri, 44, 100); 225 226 /* mono */ 227 ri->ri_devcmap[0] = 0; /* bg */ 228 ri->ri_devcmap[1] = 0xffffffff; /* fg */ 229 230 xafb_stdscreen.nrows = ri->ri_rows; 231 xafb_stdscreen.ncols = ri->ri_cols; 232 xafb_stdscreen.textops = &ri->ri_ops; 233 xafb_stdscreen.capabilities = ri->ri_caps; 234 235 return 0; 236 } 237 238 int 239 xafb_is_console() 240 { 241 volatile u_int *dipsw = (void *)NEWS5000_DIP_SWITCH; 242 243 if (*dipsw & 1) /* XXX right? */ 244 return 1; 245 246 return 0; 247 } 248 249 int 250 xafb_ioctl(v, cmd, data, flag, p) 251 void *v; 252 u_long cmd; 253 caddr_t data; 254 int flag; 255 struct proc *p; 256 { 257 struct xafb_softc *sc = v; 258 struct xafb_devconfig *dc = sc->sc_dc; 259 struct wsdisplay_fbinfo *wdf; 260 261 switch (cmd) { 262 case WSDISPLAYIO_GTYPE: 263 *(int *)data = WSDISPLAY_TYPE_UNKNOWN; /* XXX */ 264 return 0; 265 266 case WSDISPLAYIO_GINFO: 267 wdf = (void *)data; 268 wdf->height = dc->dc_ri.ri_height; 269 wdf->width = dc->dc_ri.ri_width; 270 wdf->depth = dc->dc_ri.ri_depth; 271 wdf->cmsize = 256; 272 return 0; 273 274 case WSDISPLAYIO_GETCMAP: 275 return xafb_getcmap(sc, (struct wsdisplay_cmap *)data); 276 277 case WSDISPLAYIO_PUTCMAP: 278 return xafb_putcmap(sc, (struct wsdisplay_cmap *)data); 279 280 /* case WSDISPLAYIO_SVIDEO: */ 281 } 282 return EPASSTHROUGH; 283 } 284 285 paddr_t 286 xafb_mmap(v, offset, prot) 287 void *v; 288 off_t offset; 289 int prot; 290 { 291 struct xafb_softc *sc = v; 292 struct xafb_devconfig *dc = sc->sc_dc; 293 struct rasops_info *ri = &dc->dc_ri; 294 295 if (offset >= (ri->ri_stride * ri->ri_height) || offset < 0) 296 return -1; 297 298 return mips_btop((int)dc->dc_fbbase + offset); 299 } 300 301 int 302 xafb_alloc_screen(v, scrdesc, cookiep, ccolp, crowp, attrp) 303 void *v; 304 const struct wsscreen_descr *scrdesc; 305 void **cookiep; 306 int *ccolp, *crowp; 307 long *attrp; 308 { 309 struct xafb_softc *sc = v; 310 struct rasops_info *ri = &sc->sc_dc->dc_ri; 311 long defattr; 312 313 if (sc->sc_nscreens > 0) 314 return ENOMEM; 315 316 *cookiep = ri; 317 *ccolp = *crowp = 0; 318 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr); 319 *attrp = defattr; 320 sc->sc_nscreens++; 321 322 return 0; 323 } 324 325 void 326 xafb_free_screen(v, cookie) 327 void *v; 328 void *cookie; 329 { 330 struct xafb_softc *sc = v; 331 332 if (sc->sc_dc == &xafb_console_dc) 333 panic("xafb_free_screen: console"); 334 335 sc->sc_nscreens--; 336 } 337 338 int 339 xafb_show_screen(v, cookie, waitok, cb, cbarg) 340 void *v; 341 void *cookie; 342 int waitok; 343 void (*cb) __P((void *, int, int)); 344 void *cbarg; 345 { 346 return 0; 347 } 348 349 int 350 xafb_cnattach() 351 { 352 struct xafb_devconfig *dc = &xafb_console_dc; 353 struct rasops_info *ri = &dc->dc_ri; 354 long defattr; 355 int crow = 0; 356 357 if (!xafb_is_console()) 358 return -1; 359 360 dc->dc_fbbase = (void *)0xb0000000; /* XXX */ 361 dc->dc_reg = (void *)0xb4903000; /* XXX */ 362 xafb_common_init(dc); 363 364 crow = 0; /* XXX current cursor pos */ 365 366 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr); 367 wsdisplay_cnattach(&xafb_stdscreen, &dc->dc_ri, 0, crow, defattr); 368 369 return 0; 370 } 371 372 int 373 xafb_getcmap(sc, cm) 374 struct xafb_softc *sc; 375 struct wsdisplay_cmap *cm; 376 { 377 u_int index = cm->index; 378 u_int count = cm->count; 379 int error; 380 381 if (index >= 256 || count > 256 || index + count > 256) 382 return EINVAL; 383 384 error = copyout(&sc->sc_cmap_red[index], cm->red, count); 385 if (error) 386 return error; 387 error = copyout(&sc->sc_cmap_green[index], cm->green, count); 388 if (error) 389 return error; 390 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count); 391 if (error) 392 return error; 393 394 return 0; 395 } 396 397 int 398 xafb_putcmap(sc, cm) 399 struct xafb_softc *sc; 400 struct wsdisplay_cmap *cm; 401 { 402 u_int index = cm->index; 403 u_int count = cm->count; 404 int i; 405 u_char *r, *g, *b; 406 407 if (index >= 256 || count > 256 || index + count > 256) 408 return EINVAL; 409 if (!uvm_useracc(cm->red, count, B_READ) || 410 !uvm_useracc(cm->green, count, B_READ) || 411 !uvm_useracc(cm->blue, count, B_READ)) 412 return EFAULT; 413 copyin(cm->red, &sc->sc_cmap_red[index], count); 414 copyin(cm->green, &sc->sc_cmap_green[index], count); 415 copyin(cm->blue, &sc->sc_cmap_blue[index], count); 416 417 r = &sc->sc_cmap_red[index]; 418 g = &sc->sc_cmap_green[index]; 419 b = &sc->sc_cmap_blue[index]; 420 421 for (i = 0; i < count; i++) 422 xafb_setcolor(sc->sc_dc, index++, *r++, *g++, *b++); 423 424 return 0; 425 } 426