grfabs.c revision 1.1
1/* $NetBSD: grfabs.c,v 1.1 1995/03/26 07:12:15 leo Exp $ */ 2 3/* 4 * Copyright (c) 1995 Leo Weppelman. 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 Leo Weppelman. 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 WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33/* 34 * atari abstract graphics driver. 35 */ 36#include <sys/param.h> 37#include <sys/queue.h> 38#include <sys/malloc.h> 39 40#include <machine/iomap.h> 41#include <machine/video.h> 42#include <machine/mfp.h> 43#include <atari/dev/grfabs_reg.h> 44 45/* 46 * Function decls 47 */ 48static dmode_t *get_best_display_mode __P((int, int, int)); 49static view_t *alloc_view __P((dmode_t *, dimen_t *, u_char)); 50static void init_view __P((view_t *, bmap_t *, dmode_t *, box_t *)); 51static bmap_t *alloc_bitmap __P((u_long, u_long, u_char, int)); 52static void free_bitmap __P((bmap_t *)); 53static colormap_t *alloc_colormap __P((dmode_t *)); 54 55/* 56 * Ugh.. Stuff needed to allocate console structures before the VM-system 57 * is running. There is no malloc() available at that time. 58 */ 59extern int atari_realconfig; /* 0 -> no malloc */ 60static view_t con_view; 61static colormap_t con_cmap; 62static u_short con_colors[MAX_CENTRIES]; 63 64/* 65 * List of available graphic modes 66 */ 67static LIST_HEAD(modelist, display_mode) modes; 68 69static dmode_t vid_modes[] = { 70 { { NULL, NULL }, "stlow", { 320, 200 }, 1, RES_STLOW }, 71 { { NULL, NULL }, "stmid", { 640, 200 }, 2, RES_STMID }, 72 { { NULL, NULL }, "sthigh", { 640, 400 }, 1, RES_STHIGH }, 73 { { NULL, NULL }, "ttlow", { 320, 480 }, 8, RES_TTLOW }, 74 { { NULL, NULL }, "ttmid", { 640, 480 }, 4, RES_TTMID }, 75 { { NULL, NULL }, "tthigh", { 1280, 960 }, 1, RES_TTHIGH }, 76 { { NULL, NULL }, NULL, } 77}; 78 79/* 80 * Default colors..... 81 * Currently the TT-low (256 colors) just uses 16 time the 16-color default. 82 * If you have a sensible 256 scale, feel free to add..... 83 * The first 2 colors in all maps are {black,white}, so ite (text) displays 84 * are initially readable. Also, this enables me to supply only 1 map. The 85 * 4 color mode uses the first four entries of the 16 color mode thus giving 86 * a gray scale display. (Maybe we can add an intensity bit to the ite...) 87 */ 88static u_short def_color16[16] = { 89 0x000, /* black */ 90 0xfff, /* white */ 91 0xccc, /* light gray */ 92 0x888, /* gray */ 93 0x00c, /* blue */ 94 0x0c0, /* green */ 95 0x0cc, /* cyan */ 96 0xc00, /* red */ 97 0xc0c, /* magenta */ 98 0xcc0, /* brown */ 99 0x00f, /* light blue */ 100 0x0f0, /* light green */ 101 0x0ff, /* light cyan */ 102 0xf00, /* light red */ 103 0xf0f, /* light magenta */ 104 0xff0 /* light brown */ 105}; 106 107/* 108 * XXX: called from ite console init routine. 109 * Initialize list of posible video modes. 110 */ 111int 112grfabs_probe() 113{ 114 dmode_t *dm; 115 int i; 116 int has_mono; 117 static int inited = 0; 118 119 if(inited) 120 return; /* Has to be done only once */ 121 inited++; 122 123 /* 124 * First find out what kind of monitor is attached. Dma-sound 125 * should be off because the 'sound-done' and 'monochrome-detect' 126 * are xor-ed together. I think that shutting it down here is the 127 * wrong place. 128 */ 129 has_mono = (MFP->mf_gpip & IA_MONO) == 0; 130 131 LIST_INIT(&modes); 132 for(i = 0; (dm = &vid_modes[i])->name != NULL; i++) { 133 if(has_mono && (dm->vm_reg != RES_TTHIGH)) 134 continue; 135 if(!has_mono && (dm->vm_reg == RES_TTHIGH)) 136 continue; 137 LIST_INSERT_HEAD(&modes, dm, link); 138 } 139 return(1); 140} 141 142view_t * 143grf_alloc_view(d, dim, depth) 144dmode_t *d; 145dimen_t *dim; 146u_char depth; 147{ 148 if(!d) 149 d = get_best_display_mode(dim->width, dim->height, depth); 150 if(d) 151 return(alloc_view(d, dim, depth)); 152 return(NULL); 153} 154 155void grf_display_view(v) 156view_t *v; 157{ 158 dmode_t *dm = v->mode; 159 bmap_t *bm = v->bitmap; 160 161 if(dm->current_view) { 162 /* 163 * Mark current view for this mode as no longer displayed 164 */ 165 dm->current_view->flags &= ~VF_DISPLAY; 166 } 167 dm->current_view = v; 168 v->flags |= VF_DISPLAY; 169 170 grf_use_colormap(v, v->colormap); 171 172 /* XXX: should use vbl for this */ 173 VIDEO->vd_tt_res = dm->vm_reg; 174 VIDEO->vd_raml = (u_long)bm->hw_address & 0xff; 175 VIDEO->vd_ramm = ((u_long)bm->hw_address >> 8) & 0xff; 176 VIDEO->vd_ramh = ((u_long)bm->hw_address >> 16) & 0xff; 177} 178 179void grf_remove_view(v) 180view_t *v; 181{ 182 dmode_t *mode = v->mode; 183 184 if(mode->current_view == v) { 185#if 0 186 if(v->flags & VF_DISPLAY) 187 panic("Cannot shutdown display\n"); /* XXX */ 188#endif 189 mode->current_view = NULL; 190 } 191 v->flags &= ~VF_DISPLAY; 192} 193 194void grf_free_view(v) 195view_t *v; 196{ 197 if(v) { 198 dmode_t *md = v->mode; 199 200 grf_remove_view(v); 201 if(v->colormap != &con_cmap) 202 free(v->colormap, M_DEVBUF); 203 free_bitmap(v->bitmap); 204 if(v != &con_view) 205 free(v, M_DEVBUF); 206 } 207} 208 209int 210grf_get_colormap(v, cm) 211view_t *v; 212colormap_t *cm; 213{ 214 colormap_t *gcm; 215 int i, n; 216 217 bzero(cm->centry, cm->nentries * sizeof(u_short)); 218 219 gcm = v->colormap; 220 n = cm->nentries < gcm->nentries ? cm->nentries : gcm->nentries; 221 for(i = 0; i < n; i++) 222 cm->centry[i] = gcm->centry[i]; 223 return(0); 224} 225 226int 227grf_use_colormap(v, cm) 228view_t *v; 229colormap_t *cm; 230{ 231 dmode_t *dm; 232 volatile u_short *creg; 233 u_short *src; 234 u_short ncreg; 235 int i; 236 237 dm = v->mode; 238 239 switch(dm->vm_reg) { 240 case RES_STLOW: 241 creg = &VIDEO->vd_tt_rgb[0]; 242 ncreg = 16; 243 break; 244 case RES_STMID: 245 creg = &VIDEO->vd_tt_rgb[0]; 246 ncreg = 4; 247 break; 248 case RES_STHIGH: 249 creg = &VIDEO->vd_tt_rgb[254]; 250 ncreg = 2; 251 break; 252 case RES_TTLOW: 253 creg = &VIDEO->vd_tt_rgb[0]; 254 ncreg = 256; 255 break; 256 case RES_TTMID: 257 creg = &VIDEO->vd_tt_rgb[0]; 258 ncreg = 16; 259 break; 260 case RES_TTHIGH: 261 return(0); /* No colors */ 262 default: 263 panic("grf_get_colormap: wrong mode!?"); 264 } 265 if(cm->nentries < ncreg) 266 ncreg = cm->nentries; 267 268 for(i = 0, src = cm->centry; i < ncreg; i++) 269 *creg++ = *src++; 270 return(0); 271} 272 273static dmode_t * 274get_best_display_mode(width, height, depth) 275int width, height, depth; 276{ 277 dmode_t *save; 278 dmode_t *dm; 279 long dt, dx, dy, ct; 280 281 save = NULL; 282 dm = modes.lh_first; 283 while(dm != NULL) { 284 if(depth > dm->depth) { 285 dm = dm->link.le_next; 286 continue; 287 } 288 else if(width > dm->size.width || height > dm->size.height) { 289 dm = dm->link.le_next; 290 continue; 291 } 292 else if (width < dm->size.width || height < dm->size.height) { 293 dm = dm->link.le_next; 294 continue; 295 } 296 dx = abs(dm->size.width - width); 297 dy = abs(dm->size.height - height); 298 ct = dx + dy; 299 300 if (ct < dt || save == NULL) { 301 save = dm; 302 dt = ct; 303 } 304 dm = dm->link.le_next; 305 } 306 return (save); 307} 308 309static view_t * 310alloc_view(mode, dim, depth) 311dmode_t *mode; 312dimen_t *dim; 313u_char depth; 314{ 315 view_t *v; 316 bmap_t *bm; 317 318 if(!atari_realconfig) 319 v = &con_view; 320 else v = malloc(sizeof(*v), M_DEVBUF, M_WAITOK); 321 322 bm = alloc_bitmap(mode->size.width, mode->size.height, mode->depth, 1); 323 if(bm) { 324 int i; 325 box_t box; 326 327 v->colormap = alloc_colormap(mode); 328 if(v->colormap) { 329 INIT_BOX(&box,0,0,mode->size.width,mode->size.height); 330 init_view(v, bm, mode, &box); 331 return(v); 332 } 333 free_bitmap(bm); 334 } 335 if(v != &con_view) 336 free(v, M_DEVBUF); 337 return (NULL); 338} 339 340static void 341init_view(v, bm, mode, dbox) 342view_t *v; 343bmap_t *bm; 344dmode_t *mode; 345box_t *dbox; 346{ 347 v->bitmap = bm; 348 v->mode = mode; 349 bcopy(dbox, &v->display, sizeof(box_t)); 350} 351 352/* bitmap functions */ 353 354static bmap_t * 355alloc_bitmap(width, height, depth, clear) 356u_long width, height; 357u_char depth; 358int clear; 359{ 360 int i; 361 u_long total_size, bm_size; 362 void *hw_address; 363 bmap_t *bm; 364 365 /* 366 * Sigh, it seems for mapping to work we need the bitplane data to 367 * 1: be aligned on a page boundry. 368 * 2: be n pages large. 369 * 370 * why? because the user gets a page aligned address, if this is before 371 * your allocation, too bad. Also it seems that the mapping routines 372 * do not watch to closely to the allowable length. so if you go over 373 * n pages by less than another page, the user gets to write all over 374 * the entire page. Since you did not allocate up to a page boundry 375 * (or more) the user writes into someone elses memory. -ch 376 */ 377 bm_size = atari_round_page((width * height * depth) / NBBY); 378 total_size = bm_size + sizeof(bmap_t) + NBPG; 379 380 if((bm = (bmap_t*)alloc_stmem(total_size, &hw_address)) == NULL) 381 return(NULL); 382 383 bm->plane = (u_char*)bm + sizeof(bmap_t); 384 bm->plane = (u_char*)atari_round_page(bm->plane); 385 bm->hw_address = (u_char*)hw_address + sizeof(bmap_t); 386 bm->hw_address = (u_char*)atari_round_page(bm->hw_address); 387 bm->bytes_per_row = (width * depth) / NBBY; 388 bm->rows = height; 389 bm->depth = depth; 390 391 if(clear) 392 bzero(bm->plane, bm_size); 393 return(bm); 394} 395 396static void 397free_bitmap(bm) 398bmap_t *bm; 399{ 400 if(bm) 401 free_stmem(bm); 402} 403 404static colormap_t * 405alloc_colormap(dm) 406dmode_t *dm; 407{ 408 int nentries, i; 409 colormap_t *cm; 410 411 switch(dm->vm_reg) { 412 case RES_STLOW: 413 case RES_TTMID: 414 nentries = 16; 415 break; 416 case RES_STMID: 417 nentries = 4; 418 break; 419 case RES_STHIGH: 420 nentries = 2; 421 break; 422 case RES_TTLOW: 423 nentries = 256; 424 break; 425 case RES_TTHIGH: 426 nentries = 0; 427 default: 428 panic("grf:alloc_colormap: wrong mode!?"); 429 } 430 if(!atari_realconfig) { 431 cm = &con_cmap; 432 cm->centry = con_colors; 433 } 434 else { 435 int size; 436 437 size = sizeof(*cm) + (nentries * sizeof(u_short)); 438 cm = malloc(size, M_DEVBUF, M_WAITOK); 439 if(cm == NULL) 440 return(NULL); 441 cm->centry = (u_short *)&cm[1]; 442 443 } 444 cm->nentries = nentries; 445 446 for(i = 0; i < nentries; i++) 447 cm->centry[i] = def_color16[i % 16]; 448 return(cm); 449} 450