1 /* $NetBSD: macfb.c,v 1.9 2002/10/02 05:36:37 thorpej Exp $ */ 2 /* 3 * Copyright (c) 1998 Matt DeBergalis 4 * 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. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Matt DeBergalis 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "opt_wsdisplay_compat.h" 33 #include "grf.h" 34 35 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/device.h> 41 #include <sys/malloc.h> 42 43 #include <machine/cpu.h> 44 #include <machine/bus.h> 45 46 #include <machine/grfioctl.h> 47 #include <mac68k/nubus/nubus.h> 48 #include <mac68k/dev/grfvar.h> 49 #include <mac68k/dev/macfbvar.h> 50 #include <dev/wscons/wsconsio.h> 51 52 #include <dev/rcons/raster.h> 53 #include <dev/wscons/wscons_raster.h> 54 #include <dev/wscons/wsdisplayvar.h> 55 56 int macfb_match __P((struct device *, struct cfdata *, void *)); 57 void macfb_attach __P((struct device *, struct device *, void *)); 58 59 CFATTACH_DECL(macfb, sizeof(struct macfb_softc), 60 macfb_match, macfb_attach, NULL, NULL); 61 62 const struct wsdisplay_emulops macfb_emulops = { 63 rcons_cursor, 64 rcons_mapchar, 65 rcons_putchar, 66 rcons_copycols, 67 rcons_erasecols, 68 rcons_copyrows, 69 rcons_eraserows, 70 rcons_allocattr 71 }; 72 73 struct wsscreen_descr macfb_stdscreen = { 74 "std", 75 0, 0, /* will be filled in -- XXX shouldn't, it's global */ 76 &macfb_emulops, 77 0, 0, 78 WSSCREEN_REVERSE 79 }; 80 81 const struct wsscreen_descr *_macfb_scrlist[] = { 82 &macfb_stdscreen, 83 }; 84 85 const struct wsscreen_list macfb_screenlist = { 86 sizeof(_macfb_scrlist) / sizeof(struct wsscreen_descr *), 87 _macfb_scrlist 88 }; 89 90 static int macfb_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 91 static paddr_t macfb_mmap __P((void *, off_t, int)); 92 static int macfb_alloc_screen __P((void *, const struct wsscreen_descr *, 93 void **, int *, int *, long *)); 94 static void macfb_free_screen __P((void *, void *)); 95 static int macfb_show_screen __P((void *, void *, int, 96 void (*)(void *, int, int), void *)); 97 98 const struct wsdisplay_accessops macfb_accessops = { 99 macfb_ioctl, 100 macfb_mmap, 101 macfb_alloc_screen, 102 macfb_free_screen, 103 macfb_show_screen, 104 0 /* load_font */ 105 }; 106 107 void macfb_init __P((struct macfb_devconfig *)); 108 109 paddr_t macfb_consaddr; 110 static int macfb_is_console __P((paddr_t addr)); 111 #ifdef WSDISPLAY_COMPAT_ITEFONT 112 static void init_itefont __P((void)); 113 #endif /* WSDISPLAY_COMPAT_ITEFONT */ 114 115 static struct macfb_devconfig macfb_console_dc; 116 117 /* From Booter via locore */ 118 extern long videoaddr; 119 extern long videorowbytes; 120 extern long videobitdepth; 121 extern u_long videosize; 122 extern u_int32_t mac68k_vidlog; 123 extern u_int32_t mac68k_vidphys; 124 extern u_int32_t mac68k_vidlen; 125 126 static int 127 macfb_is_console(paddr_t addr) 128 { 129 if (addr != macfb_consaddr && 130 (addr >= 0xf9000000 && addr <= 0xfeffffff)) { 131 /* 132 * This is in the NuBus standard slot space range, so we 133 * may well have to look at 0xFssxxxxx, too. Mask off the 134 * slot number and duplicate it in bits 20-23, per IM:V 135 * pp 459, 463, and IM:VI ch 30 p 17. 136 * Note: this is an ugly hack and I wish I knew what 137 * to do about it. -- sr 138 */ 139 addr = (paddr_t)(((u_long)addr & 0xff0fffff) | 140 (((u_long)addr & 0x0f000000) >> 4)); 141 } 142 return ((mac68k_machine.serial_console & 0x03) == 0 143 && (addr == macfb_consaddr)); 144 } 145 146 void 147 macfb_clear(dc) 148 struct macfb_devconfig *dc; 149 { 150 int i, rows; 151 152 /* clear the display */ 153 rows = dc->dc_ht; 154 for (i = 0; rows-- > 0; i += dc->dc_rowbytes) 155 memset((u_char *)dc->dc_vaddr + dc->dc_offset + i, 156 0, dc->dc_rowbytes); 157 } 158 159 void 160 macfb_init(dc) 161 struct macfb_devconfig *dc; 162 { 163 struct raster *rap; 164 struct rcons *rcp; 165 166 macfb_clear(dc); 167 168 #ifdef WSDISPLAY_COMPAT_ITEFONT 169 init_itefont(); 170 #endif /* WSDISPLAY_COMPAT_ITEFONT */ 171 172 rap = &dc->dc_raster; 173 rap->width = dc->dc_wid; 174 rap->height = dc->dc_ht; 175 rap->depth = dc->dc_depth; 176 rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t); 177 rap->pixels = (u_int32_t *)(dc->dc_vaddr + dc->dc_offset); 178 179 /* initialize the raster console blitter */ 180 rcp = &dc->dc_rcons; 181 rcp->rc_sp = rap; 182 rcp->rc_crow = rcp->rc_ccol = -1; 183 rcp->rc_crowp = &rcp->rc_crow; 184 rcp->rc_ccolp = &rcp->rc_ccol; 185 rcons_init(rcp, 128, 192); 186 187 macfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow; 188 macfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol; 189 } 190 191 int 192 macfb_match(parent, match, aux) 193 struct device *parent; 194 struct cfdata *match; 195 void *aux; 196 { 197 return (1); 198 } 199 200 void 201 macfb_attach(parent, self, aux) 202 struct device *parent; 203 struct device *self; 204 void *aux; 205 { 206 struct grfbus_attach_args *ga = aux; 207 struct grfmode *gm = ga->ga_grfmode; 208 struct macfb_softc *sc; 209 struct wsemuldisplaydev_attach_args waa; 210 int isconsole; 211 212 sc = (struct macfb_softc *)self; 213 214 printf("\n"); 215 216 isconsole = macfb_is_console(ga->ga_phys + ga->ga_grfmode->fboff); 217 218 if (isconsole) { 219 sc->sc_dc = &macfb_console_dc; 220 sc->nscreens = 1; 221 } else { 222 sc->sc_dc = malloc(sizeof(struct macfb_devconfig), M_DEVBUF, M_WAITOK); 223 sc->sc_dc->dc_vaddr = (vaddr_t)gm->fbbase; 224 sc->sc_dc->dc_paddr = ga->ga_phys; 225 sc->sc_dc->dc_size = gm->fbsize; 226 227 sc->sc_dc->dc_wid = gm->width; 228 sc->sc_dc->dc_ht = gm->height; 229 sc->sc_dc->dc_depth = gm->psize; 230 sc->sc_dc->dc_rowbytes = gm->rowbytes; 231 232 sc->sc_dc->dc_offset = gm->fboff; 233 234 macfb_clear(sc->sc_dc); 235 236 sc->nscreens = 1; 237 } 238 239 /* initialize the raster */ 240 waa.console = isconsole; 241 waa.scrdata = &macfb_screenlist; 242 waa.accessops = &macfb_accessops; 243 waa.accesscookie = sc; 244 245 config_found(self, &waa, wsemuldisplaydevprint); 246 247 #if NGRF > 0 248 grf_attach(sc, self->dv_unit); 249 #endif 250 } 251 252 253 int 254 macfb_ioctl(v, cmd, data, flag, p) 255 void *v; 256 u_long cmd; 257 caddr_t data; 258 int flag; 259 struct proc *p; 260 { 261 struct macfb_softc *sc = v; 262 struct macfb_devconfig *dc = sc->sc_dc; 263 struct wsdisplay_fbinfo *wdf; 264 265 switch (cmd) { 266 case WSDISPLAYIO_GTYPE: 267 *(int *)data = dc->dc_type; 268 return 0; 269 270 case WSDISPLAYIO_GINFO: 271 wdf = (struct wsdisplay_fbinfo *)data; 272 wdf->height = dc->dc_raster.height; 273 wdf->width = dc->dc_raster.width; 274 wdf->depth = dc->dc_raster.depth; 275 wdf->cmsize = 256; 276 return 0; 277 278 case WSDISPLAYIO_GCURMAX: 279 case WSDISPLAYIO_GCURPOS: 280 case WSDISPLAYIO_GCURSOR: 281 case WSDISPLAYIO_GETCMAP: 282 case WSDISPLAYIO_GVIDEO: 283 case WSDISPLAYIO_PUTCMAP: 284 case WSDISPLAYIO_SCURPOS: 285 case WSDISPLAYIO_SCURSOR: 286 case WSDISPLAYIO_SVIDEO: 287 /* NONE of these operations are supported. */ 288 return EPASSTHROUGH; 289 } 290 291 return EPASSTHROUGH; 292 } 293 294 static paddr_t 295 macfb_mmap(v, offset, prot) 296 void *v; 297 off_t offset; 298 int prot; 299 { 300 struct macfb_softc *sc = v; 301 struct macfb_devconfig *dc = sc->sc_dc; 302 paddr_t addr; 303 304 if (offset >= 0 && 305 offset < m68k_round_page(dc->dc_rowbytes * dc->dc_ht)) 306 addr = m68k_btop(dc->dc_paddr + dc->dc_offset + offset); 307 else 308 addr = (-1); /* XXX bogus */ 309 310 return addr; 311 } 312 313 int 314 macfb_alloc_screen(v, type, cookiep, curxp, curyp, defattrp) 315 void *v; 316 const struct wsscreen_descr *type; 317 void **cookiep; 318 int *curxp, *curyp; 319 long *defattrp; 320 { 321 struct macfb_softc *sc = v; 322 long defattr; 323 324 if (sc->nscreens > 0) 325 return (ENOMEM); 326 327 *cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */ 328 *curxp = 0; 329 *curyp = 0; 330 rcons_allocattr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr); 331 *defattrp = defattr; 332 sc->nscreens++; 333 return (0); 334 } 335 336 void 337 macfb_free_screen(v, cookie) 338 void *v; 339 void *cookie; 340 { 341 struct macfb_softc *sc = v; 342 343 if (sc->sc_dc == &macfb_console_dc) 344 panic("cfb_free_screen: console"); 345 346 sc->nscreens--; 347 } 348 349 int 350 macfb_show_screen(v, cookie, waitok, cb, cbarg) 351 void *v; 352 void *cookie; 353 int waitok; 354 void (*cb) __P((void *, int, int)); 355 void *cbarg; 356 { 357 return 0; 358 } 359 360 int 361 macfb_cnattach(addr) 362 paddr_t addr; 363 { 364 struct macfb_devconfig *dc = &macfb_console_dc; 365 long defattr; 366 367 dc->dc_vaddr = m68k_trunc_page(videoaddr); 368 dc->dc_paddr = m68k_trunc_page(mac68k_vidphys); 369 370 dc->dc_wid = videosize & 0xffff; 371 dc->dc_ht = (videosize >> 16) & 0xffff; 372 dc->dc_depth = videobitdepth; 373 dc->dc_rowbytes = videorowbytes; 374 375 dc->dc_size = (mac68k_vidlen > 0) ? 376 mac68k_vidlen : dc->dc_ht * dc->dc_rowbytes; 377 dc->dc_offset = m68k_page_offset(mac68k_vidphys); 378 379 /* set up the display */ 380 macfb_init(&macfb_console_dc); 381 382 rcons_allocattr(&dc->dc_rcons, 0, 0, 0, &defattr); 383 384 wsdisplay_cnattach(&macfb_stdscreen, &dc->dc_rcons, 385 0, 0, defattr); 386 387 macfb_consaddr = addr; 388 dc->isconsole = 1; 389 return (0); 390 } 391 392 #ifdef WSDISPLAY_COMPAT_ITEFONT 393 #include <mac68k/dev/6x10.h> 394 395 void 396 init_itefont() 397 { 398 static int itefont_initted = 0; 399 int i, j; 400 401 extern struct raster_font gallant19; /* XXX */ 402 403 if (itefont_initted) 404 return; 405 itefont_initted = 1; 406 407 /* XXX but we cannot use malloc here... */ 408 gallant19.width = 6; 409 gallant19.height = 10; 410 gallant19.ascent = 0; 411 412 for (i = 32; i < 128; i++) { 413 u_int *p; 414 415 if (gallant19.chars[i].r == NULL) 416 continue; 417 418 gallant19.chars[i].r->width = 6; 419 gallant19.chars[i].r->height = 10; 420 p = gallant19.chars[i].r->pixels; 421 422 for (j = 0; j < 10; j++) 423 *p++ = Font6x10[i * 10 + j] << 26; 424 } 425 } 426 #endif /* WSDISPLAY_COMPAT_ITEFONT */ 427