1 1.25 tsutsui /* $NetBSD: grfabs_tt.c,v 1.25 2023/01/06 10:28:28 tsutsui Exp $ */ 2 1.1 leo 3 1.1 leo /* 4 1.1 leo * Copyright (c) 1995 Leo Weppelman. 5 1.1 leo * All rights reserved. 6 1.1 leo * 7 1.1 leo * Redistribution and use in source and binary forms, with or without 8 1.1 leo * modification, are permitted provided that the following conditions 9 1.1 leo * are met: 10 1.1 leo * 1. Redistributions of source code must retain the above copyright 11 1.1 leo * notice, this list of conditions and the following disclaimer. 12 1.1 leo * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 leo * notice, this list of conditions and the following disclaimer in the 14 1.1 leo * documentation and/or other materials provided with the distribution. 15 1.1 leo * 16 1.1 leo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 leo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 leo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 leo * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 leo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 1.1 leo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 1.1 leo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 1.1 leo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 1.1 leo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 1.1 leo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 1.1 leo */ 27 1.14 lukem 28 1.14 lukem #include <sys/cdefs.h> 29 1.25 tsutsui __KERNEL_RCSID(0, "$NetBSD: grfabs_tt.c,v 1.25 2023/01/06 10:28:28 tsutsui Exp $"); 30 1.1 leo 31 1.1 leo #ifdef TT_VIDEO 32 1.1 leo /* 33 1.1 leo * atari abstract graphics driver: TT-interface 34 1.1 leo */ 35 1.1 leo #include <sys/param.h> 36 1.1 leo #include <sys/queue.h> 37 1.1 leo #include <sys/malloc.h> 38 1.1 leo #include <sys/device.h> 39 1.2 leo #include <sys/systm.h> 40 1.1 leo 41 1.12 thorpej #include <uvm/uvm_extern.h> 42 1.12 thorpej 43 1.1 leo #include <machine/iomap.h> 44 1.1 leo #include <machine/video.h> 45 1.1 leo #include <machine/mfp.h> 46 1.1 leo #include <atari/atari/device.h> 47 1.3 leo #include <atari/atari/stalloc.h> 48 1.1 leo #include <atari/dev/grfabs_reg.h> 49 1.5 leo #include <atari/dev/grfabs_tt.h> 50 1.1 leo 51 1.1 leo /* 52 1.1 leo * Function decls 53 1.1 leo */ 54 1.16 dsl static void init_view(view_t *, bmap_t *, dmode_t *, box_t *); 55 1.16 dsl static bmap_t *alloc_bitmap(u_long, u_long, u_char); 56 1.16 dsl static colormap_t *alloc_colormap(dmode_t *); 57 1.25 tsutsui static void free_bitmap(bmap_t *); 58 1.16 dsl static void tt_display_view(view_t *); 59 1.16 dsl static view_t *tt_alloc_view(dmode_t *, dimen_t *, u_char); 60 1.16 dsl static void tt_free_view(view_t *); 61 1.16 dsl static void tt_remove_view(view_t *); 62 1.16 dsl static void tt_save_view(view_t *); 63 1.16 dsl static int tt_use_colormap(view_t *, colormap_t *); 64 1.1 leo 65 1.1 leo /* 66 1.1 leo * Our function switch table 67 1.1 leo */ 68 1.1 leo struct grfabs_sw tt_vid_sw = { 69 1.1 leo tt_display_view, 70 1.1 leo tt_alloc_view, 71 1.1 leo tt_free_view, 72 1.1 leo tt_remove_view, 73 1.6 leo tt_save_view, 74 1.1 leo tt_use_colormap 75 1.1 leo }; 76 1.1 leo 77 1.5 leo struct tt_hwregs { 78 1.5 leo u_short tt_reg; /* video mode-register TT */ 79 1.5 leo }; 80 1.5 leo #define vm_reg(dm) (((struct tt_hwregs*)(dm->data))->tt_reg) 81 1.5 leo 82 1.5 leo /* 83 1.5 leo * Note that the order of this table *must* match the order of 84 1.5 leo * the table below! 85 1.5 leo */ 86 1.5 leo static struct tt_hwregs tt_hwregs[] = { 87 1.5 leo { RES_STHIGH }, 88 1.5 leo { RES_TTHIGH }, 89 1.5 leo { RES_STMID }, 90 1.5 leo { RES_STLOW }, 91 1.5 leo { RES_TTMID }, 92 1.5 leo { RES_TTLOW } 93 1.5 leo }; 94 1.5 leo 95 1.1 leo static dmode_t vid_modes[] = { 96 1.5 leo { { NULL, NULL }, "sthigh", { 640, 400 }, 1, NULL, &tt_vid_sw }, 97 1.5 leo { { NULL, NULL }, "tthigh", { 1280, 960 }, 1, NULL, &tt_vid_sw }, 98 1.5 leo { { NULL, NULL }, "stmid", { 640, 200 }, 2, NULL, &tt_vid_sw }, 99 1.5 leo { { NULL, NULL }, "stlow", { 320, 200 }, 4, NULL, &tt_vid_sw }, 100 1.5 leo { { NULL, NULL }, "ttmid", { 640, 480 }, 4, NULL, &tt_vid_sw }, 101 1.5 leo { { NULL, NULL }, "ttlow", { 320, 480 }, 8, NULL, &tt_vid_sw }, 102 1.4 leo { { NULL, NULL }, NULL, } 103 1.1 leo }; 104 1.1 leo 105 1.1 leo /* 106 1.1 leo * XXX: called from ite console init routine. 107 1.10 wiz * Initialize list of possible video modes. 108 1.1 leo */ 109 1.5 leo 110 1.1 leo void 111 1.17 dsl tt_probe_video(MODES *modelp) 112 1.1 leo { 113 1.1 leo dmode_t *dm; 114 1.1 leo int i; 115 1.1 leo int has_mono; 116 1.1 leo 117 1.1 leo /* 118 1.13 wiz * First find out what kind of monitor is attached. DMA-sound 119 1.1 leo * should be off because the 'sound-done' and 'monochrome-detect' 120 1.1 leo * are xor-ed together. I think that shutting it down here is the 121 1.1 leo * wrong place. 122 1.1 leo */ 123 1.1 leo has_mono = (MFP->mf_gpip & IA_MONO) == 0; 124 1.1 leo 125 1.1 leo for (i = 0; (dm = &vid_modes[i])->name != NULL; i++) { 126 1.5 leo dm->data = (void *)&tt_hwregs[i]; 127 1.5 leo if (has_mono && (vm_reg(dm) != RES_TTHIGH)) 128 1.1 leo continue; 129 1.5 leo if (!has_mono && (vm_reg(dm) == RES_TTHIGH)) 130 1.1 leo continue; 131 1.1 leo LIST_INSERT_HEAD(modelp, dm, link); 132 1.1 leo } 133 1.1 leo 134 1.1 leo for (i=0; i < 16; i++) 135 1.1 leo VIDEO->vd_tt_rgb[i] = CM_L2TT(gra_def_color16[i]); 136 1.1 leo } 137 1.1 leo 138 1.1 leo static void 139 1.17 dsl tt_display_view(view_t *v) 140 1.1 leo { 141 1.1 leo dmode_t *dm = v->mode; 142 1.1 leo bmap_t *bm = v->bitmap; 143 1.1 leo 144 1.1 leo if (dm->current_view) { 145 1.1 leo /* 146 1.1 leo * Mark current view for this mode as no longer displayed 147 1.1 leo */ 148 1.1 leo dm->current_view->flags &= ~VF_DISPLAY; 149 1.1 leo } 150 1.1 leo dm->current_view = v; 151 1.1 leo v->flags |= VF_DISPLAY; 152 1.1 leo 153 1.1 leo tt_use_colormap(v, v->colormap); 154 1.1 leo 155 1.1 leo /* XXX: should use vbl for this */ 156 1.5 leo VIDEO->vd_tt_res = vm_reg(dm); 157 1.1 leo VIDEO->vd_raml = (u_long)bm->hw_address & 0xff; 158 1.1 leo VIDEO->vd_ramm = ((u_long)bm->hw_address >> 8) & 0xff; 159 1.1 leo VIDEO->vd_ramh = ((u_long)bm->hw_address >> 16) & 0xff; 160 1.1 leo } 161 1.1 leo 162 1.1 leo void 163 1.17 dsl tt_remove_view(view_t *v) 164 1.1 leo { 165 1.1 leo dmode_t *mode = v->mode; 166 1.1 leo 167 1.1 leo if (mode->current_view == v) { 168 1.1 leo #if 0 169 1.1 leo if (v->flags & VF_DISPLAY) 170 1.11 provos panic("Cannot shutdown display"); /* XXX */ 171 1.1 leo #endif 172 1.1 leo mode->current_view = NULL; 173 1.1 leo } 174 1.1 leo v->flags &= ~VF_DISPLAY; 175 1.6 leo } 176 1.6 leo 177 1.6 leo void 178 1.17 dsl tt_save_view(view_t *v) 179 1.6 leo { 180 1.1 leo } 181 1.1 leo 182 1.1 leo void 183 1.17 dsl tt_free_view(view_t *v) 184 1.1 leo { 185 1.23 tsutsui 186 1.23 tsutsui if (v) { 187 1.1 leo tt_remove_view(v); 188 1.1 leo if (v->colormap != &gra_con_cmap) 189 1.1 leo free(v->colormap, M_DEVBUF); 190 1.1 leo free_bitmap(v->bitmap); 191 1.1 leo if (v != &gra_con_view) 192 1.1 leo free(v, M_DEVBUF); 193 1.1 leo } 194 1.1 leo } 195 1.1 leo 196 1.1 leo static int 197 1.17 dsl tt_use_colormap(view_t *v, colormap_t *cm) 198 1.1 leo { 199 1.1 leo dmode_t *dm; 200 1.1 leo volatile u_short *creg; 201 1.1 leo u_long *src; 202 1.1 leo colormap_t *vcm; 203 1.1 leo u_long *vcreg; 204 1.1 leo u_short ncreg; 205 1.1 leo int i; 206 1.1 leo 207 1.1 leo dm = v->mode; 208 1.1 leo vcm = v->colormap; 209 1.1 leo 210 1.1 leo /* 211 1.1 leo * I guess it seems reasonable to require the maps to be 212 1.1 leo * of the same type... 213 1.1 leo */ 214 1.1 leo if (cm->type != vcm->type) 215 1.1 leo return(EINVAL); 216 1.1 leo 217 1.1 leo /* 218 1.1 leo * First figure out where the actual colormap resides and 219 1.1 leo * howmany colors are in it. 220 1.1 leo */ 221 1.5 leo switch (vm_reg(dm)) { 222 1.1 leo case RES_STLOW: 223 1.1 leo creg = &VIDEO->vd_tt_rgb[0]; 224 1.1 leo ncreg = 16; 225 1.1 leo break; 226 1.1 leo case RES_STMID: 227 1.1 leo creg = &VIDEO->vd_tt_rgb[0]; 228 1.1 leo ncreg = 4; 229 1.1 leo break; 230 1.1 leo case RES_STHIGH: 231 1.1 leo creg = &VIDEO->vd_tt_rgb[254]; 232 1.1 leo ncreg = 2; 233 1.1 leo break; 234 1.1 leo case RES_TTLOW: 235 1.1 leo creg = &VIDEO->vd_tt_rgb[0]; 236 1.1 leo ncreg = 256; 237 1.1 leo break; 238 1.1 leo case RES_TTMID: 239 1.1 leo creg = &VIDEO->vd_tt_rgb[0]; 240 1.1 leo ncreg = 16; 241 1.1 leo break; 242 1.1 leo case RES_TTHIGH: 243 1.1 leo return(0); /* No colors */ 244 1.1 leo default: 245 1.1 leo panic("grf_tt:use_colormap: wrong mode!?"); 246 1.1 leo } 247 1.1 leo 248 1.1 leo /* If first entry specified beyond capabilities -> error */ 249 1.1 leo if (cm->first >= ncreg) 250 1.1 leo return(EINVAL); 251 1.1 leo 252 1.1 leo /* 253 1.1 leo * A little tricky, the actual colormap pointer will be NULL 254 1.1 leo * when view is not displaying, valid otherwise. 255 1.1 leo */ 256 1.1 leo if (v->flags & VF_DISPLAY) 257 1.1 leo creg = &creg[cm->first]; 258 1.23 tsutsui else 259 1.23 tsutsui creg = NULL; 260 1.1 leo 261 1.1 leo vcreg = &vcm->entry[cm->first]; 262 1.1 leo ncreg -= cm->first; 263 1.1 leo if (cm->size > ncreg) 264 1.1 leo return(EINVAL); 265 1.1 leo ncreg = cm->size; 266 1.1 leo 267 1.1 leo for (i = 0, src = cm->entry; i < ncreg; i++, vcreg++) { 268 1.1 leo *vcreg = *src++; 269 1.1 leo 270 1.1 leo /* 271 1.1 leo * If displaying, also update actual color registers. 272 1.1 leo */ 273 1.1 leo if (creg != NULL) 274 1.1 leo *creg++ = CM_L2TT(*vcreg); 275 1.1 leo } 276 1.1 leo return (0); 277 1.1 leo } 278 1.1 leo 279 1.1 leo static view_t * 280 1.17 dsl tt_alloc_view(dmode_t *mode, dimen_t *dim, u_char depth) 281 1.1 leo { 282 1.1 leo view_t *v; 283 1.1 leo bmap_t *bm; 284 1.1 leo 285 1.1 leo if (!atari_realconfig) 286 1.1 leo v = &gra_con_view; 287 1.23 tsutsui else 288 1.23 tsutsui v = malloc(sizeof(*v), M_DEVBUF, M_NOWAIT); 289 1.23 tsutsui if (v == NULL) 290 1.1 leo return (NULL); 291 1.25 tsutsui 292 1.1 leo bm = alloc_bitmap(mode->size.width, mode->size.height, mode->depth); 293 1.1 leo if (bm) { 294 1.1 leo box_t box; 295 1.1 leo 296 1.1 leo v->colormap = alloc_colormap(mode); 297 1.1 leo if (v->colormap) { 298 1.1 leo INIT_BOX(&box,0,0,mode->size.width,mode->size.height); 299 1.1 leo init_view(v, bm, mode, &box); 300 1.1 leo return (v); 301 1.1 leo } 302 1.1 leo free_bitmap(bm); 303 1.1 leo } 304 1.1 leo if (v != &gra_con_view) 305 1.1 leo free(v, M_DEVBUF); 306 1.1 leo return (NULL); 307 1.1 leo } 308 1.1 leo 309 1.1 leo static void 310 1.17 dsl init_view(view_t *v, bmap_t *bm, dmode_t *mode, box_t *dbox) 311 1.1 leo { 312 1.1 leo v->bitmap = bm; 313 1.1 leo v->mode = mode; 314 1.1 leo v->flags = 0; 315 1.21 tsutsui memcpy(&v->display, dbox, sizeof(box_t)); 316 1.1 leo } 317 1.1 leo 318 1.1 leo /* bitmap functions */ 319 1.1 leo 320 1.1 leo static bmap_t * 321 1.18 dsl alloc_bitmap(u_long width, u_long height, u_char depth) 322 1.1 leo { 323 1.1 leo u_long total_size, bm_size; 324 1.1 leo void *hw_address; 325 1.1 leo bmap_t *bm; 326 1.1 leo 327 1.1 leo /* 328 1.1 leo * Sigh, it seems for mapping to work we need the bitplane data to 329 1.24 andvar * 1: be aligned on a page boundary. 330 1.1 leo * 2: be n pages large. 331 1.25 tsutsui * 332 1.1 leo * why? because the user gets a page aligned address, if this is before 333 1.1 leo * your allocation, too bad. Also it seems that the mapping routines 334 1.1 leo * do not watch to closely to the allowable length. so if you go over 335 1.1 leo * n pages by less than another page, the user gets to write all over 336 1.24 andvar * the entire page. Since you did not allocate up to a page boundary 337 1.1 leo * (or more) the user writes into someone elses memory. -ch 338 1.1 leo */ 339 1.8 veego bm_size = m68k_round_page((width * height * depth) / NBBY); 340 1.12 thorpej total_size = bm_size + sizeof(bmap_t) + PAGE_SIZE; 341 1.1 leo 342 1.1 leo if ((bm = (bmap_t*)alloc_stmem(total_size, &hw_address)) == NULL) 343 1.1 leo return(NULL); 344 1.1 leo 345 1.1 leo bm->plane = (u_char*)bm + sizeof(bmap_t); 346 1.8 veego bm->plane = (u_char*)m68k_round_page(bm->plane); 347 1.1 leo bm->hw_address = (u_char*)hw_address + sizeof(bmap_t); 348 1.8 veego bm->hw_address = (u_char*)m68k_round_page(bm->hw_address); 349 1.1 leo bm->bytes_per_row = (width * depth) / NBBY; 350 1.1 leo bm->rows = height; 351 1.1 leo bm->depth = depth; 352 1.5 leo bm->regs = NULL; 353 1.5 leo bm->hw_regs = NULL; 354 1.5 leo bm->reg_size = 0; 355 1.7 leo bm->phys_mappable = (depth * width * height) / NBBY; 356 1.9 thomas bm->lin_base = 0; 357 1.9 thomas bm->vga_address = NULL; 358 1.9 thomas bm->vga_mappable = 0; 359 1.9 thomas bm->vga_base = 0; 360 1.1 leo 361 1.19 cegger memset(bm->plane, 0, bm_size); 362 1.1 leo return (bm); 363 1.1 leo } 364 1.1 leo 365 1.1 leo static void 366 1.17 dsl free_bitmap(bmap_t *bm) 367 1.1 leo { 368 1.1 leo if (bm) 369 1.1 leo free_stmem(bm); 370 1.1 leo } 371 1.1 leo 372 1.1 leo static colormap_t * 373 1.17 dsl alloc_colormap(dmode_t *dm) 374 1.1 leo { 375 1.1 leo int nentries, i; 376 1.1 leo colormap_t *cm; 377 1.1 leo u_char type = CM_COLOR; 378 1.1 leo 379 1.5 leo switch (vm_reg(dm)) { 380 1.1 leo case RES_STLOW: 381 1.1 leo case RES_TTMID: 382 1.1 leo nentries = 16; 383 1.1 leo break; 384 1.1 leo case RES_STMID: 385 1.1 leo nentries = 4; 386 1.1 leo break; 387 1.1 leo case RES_STHIGH: 388 1.1 leo nentries = 2; 389 1.1 leo break; 390 1.1 leo case RES_TTLOW: 391 1.1 leo nentries = 256; 392 1.1 leo break; 393 1.1 leo case RES_TTHIGH: 394 1.1 leo type = CM_MONO; 395 1.1 leo nentries = 0; 396 1.1 leo break; 397 1.1 leo default: 398 1.1 leo panic("grf_tt:alloc_colormap: wrong mode!?"); 399 1.1 leo } 400 1.1 leo if (!atari_realconfig) { 401 1.1 leo cm = &gra_con_cmap; 402 1.1 leo cm->entry = gra_con_colors; 403 1.23 tsutsui } else { 404 1.1 leo int size; 405 1.1 leo 406 1.1 leo size = sizeof(*cm) + (nentries * sizeof(cm->entry[0])); 407 1.1 leo cm = malloc(size, M_DEVBUF, M_NOWAIT); 408 1.1 leo if (cm == NULL) 409 1.1 leo return (NULL); 410 1.1 leo cm->entry = (long *)&cm[1]; 411 1.1 leo 412 1.1 leo } 413 1.1 leo if ((cm->type = type) == CM_COLOR) 414 1.1 leo cm->red_mask = cm->green_mask = cm->blue_mask = 0xf; 415 1.1 leo cm->first = 0; 416 1.1 leo cm->size = nentries; 417 1.1 leo 418 1.1 leo for (i = 0; i < nentries; i++) 419 1.1 leo cm->entry[i] = gra_def_color16[i % 16]; 420 1.1 leo return (cm); 421 1.1 leo } 422 1.1 leo #endif /* TT_VIDEO */ 423