1 1.31 rillig /* $NetBSD: grfabs_fal.c,v 1.31 2024/09/08 09:36:48 rillig Exp $ */ 2 1.1 leo 3 1.1 leo /* 4 1.2 leo * Copyright (c) 1995 Thomas Gerner. 5 1.1 leo * Copyright (c) 1995 Leo Weppelman. 6 1.1 leo * All rights reserved. 7 1.1 leo * 8 1.1 leo * Redistribution and use in source and binary forms, with or without 9 1.1 leo * modification, are permitted provided that the following conditions 10 1.1 leo * are met: 11 1.1 leo * 1. Redistributions of source code must retain the above copyright 12 1.1 leo * notice, this list of conditions and the following disclaimer. 13 1.1 leo * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 leo * notice, this list of conditions and the following disclaimer in the 15 1.1 leo * documentation and/or other materials provided with the distribution. 16 1.1 leo * 17 1.1 leo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 1.1 leo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 1.1 leo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 1.1 leo * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 1.1 leo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 1.1 leo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 1.1 leo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 1.1 leo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 1.1 leo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 1.1 leo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 1.1 leo */ 28 1.17 lukem 29 1.17 lukem #include <sys/cdefs.h> 30 1.31 rillig __KERNEL_RCSID(0, "$NetBSD: grfabs_fal.c,v 1.31 2024/09/08 09:36:48 rillig Exp $"); 31 1.1 leo 32 1.1 leo #ifdef FALCON_VIDEO 33 1.1 leo /* 34 1.1 leo * atari abstract graphics driver: Falcon-interface 35 1.1 leo */ 36 1.1 leo #include <sys/param.h> 37 1.1 leo #include <sys/queue.h> 38 1.1 leo #include <sys/malloc.h> 39 1.1 leo #include <sys/device.h> 40 1.4 leo #include <sys/systm.h> 41 1.1 leo 42 1.16 thorpej #include <uvm/uvm_extern.h> 43 1.16 thorpej 44 1.1 leo #include <machine/iomap.h> 45 1.1 leo #include <machine/video.h> 46 1.1 leo #include <machine/mfp.h> 47 1.1 leo #include <atari/atari/device.h> 48 1.4 leo #include <atari/atari/stalloc.h> 49 1.1 leo #include <atari/dev/grfabs_reg.h> 50 1.6 leo #include <atari/dev/grfabs_fal.h> 51 1.1 leo 52 1.1 leo /* 53 1.1 leo * Function decls 54 1.1 leo */ 55 1.19 dsl static void init_view(view_t *, bmap_t *, dmode_t *, box_t *); 56 1.19 dsl static bmap_t *alloc_bitmap(u_long, u_long, u_char); 57 1.19 dsl static colormap_t *alloc_colormap(dmode_t *); 58 1.29 tsutsui static void free_bitmap(bmap_t *); 59 1.19 dsl static void falcon_display_view(view_t *); 60 1.19 dsl static view_t *falcon_alloc_view(dmode_t *, dimen_t *, u_char); 61 1.19 dsl static void falcon_free_view(view_t *); 62 1.19 dsl static void falcon_remove_view(view_t *); 63 1.19 dsl static void falcon_save_view(view_t *); 64 1.19 dsl static int falcon_use_colormap(view_t *, colormap_t *); 65 1.19 dsl static void falcon_detect(dmode_t *); 66 1.19 dsl static struct videl *falcon_getreg(u_short); 67 1.1 leo 68 1.1 leo /* 69 1.1 leo * Our function switch table 70 1.1 leo */ 71 1.1 leo struct grfabs_sw fal_vid_sw = { 72 1.1 leo falcon_display_view, 73 1.1 leo falcon_alloc_view, 74 1.1 leo falcon_free_view, 75 1.1 leo falcon_remove_view, 76 1.7 leo falcon_save_view, 77 1.1 leo falcon_use_colormap 78 1.1 leo }; 79 1.1 leo 80 1.6 leo struct falcon_hwregs { 81 1.6 leo u_short fal_mode; /* falcon mode */ 82 1.6 leo struct videl *fal_regs; /* videl register values */ 83 1.6 leo }; 84 1.6 leo #define vm_mode(dm) (((struct falcon_hwregs*)(dm->data))->fal_mode) 85 1.6 leo #define vm_regs(dm) (((struct falcon_hwregs*)(dm->data))->fal_regs) 86 1.6 leo 87 1.6 leo /* 88 1.6 leo * Note that the order of this table *must* match the order of 89 1.6 leo * the table below! 90 1.6 leo */ 91 1.6 leo static struct falcon_hwregs fal_hwregs[] = { 92 1.6 leo { RES_FALAUTO }, 93 1.6 leo { RES_FAL_STHIGH }, 94 1.6 leo { RES_FAL_STMID }, 95 1.6 leo { RES_FAL_STLOW }, 96 1.6 leo { RES_FAL_TTLOW }, 97 1.6 leo { RES_VGA2 }, 98 1.6 leo { RES_VGA4 }, 99 1.6 leo { RES_VGA16 }, 100 1.6 leo { RES_VGA256 }, 101 1.6 leo { RES_DIRECT } 102 1.6 leo }; 103 1.6 leo 104 1.1 leo static dmode_t vid_modes[] = { 105 1.6 leo { {NULL,NULL}, "falauto", { 0, 0 }, 0, NULL, &fal_vid_sw}, 106 1.6 leo { {NULL,NULL}, "sthigh", { 640,400 }, 1, NULL, &fal_vid_sw}, 107 1.6 leo { {NULL,NULL}, "stmid", { 640,200 }, 2, NULL, &fal_vid_sw}, 108 1.6 leo { {NULL,NULL}, "stlow", { 320,200 }, 4, NULL, &fal_vid_sw}, 109 1.6 leo { {NULL,NULL}, "ttlow", { 320,480 }, 8, NULL, &fal_vid_sw}, 110 1.6 leo { {NULL,NULL}, "vga2", { 640,480 }, 1, NULL, &fal_vid_sw}, 111 1.6 leo { {NULL,NULL}, "vga4", { 640,480 }, 2, NULL, &fal_vid_sw}, 112 1.6 leo { {NULL,NULL}, "vga16", { 640,480 }, 4, NULL, &fal_vid_sw}, 113 1.6 leo { {NULL,NULL}, "vga256", { 640,480 }, 8, NULL, &fal_vid_sw}, 114 1.6 leo { {NULL,NULL}, "highcol", { 320,200 }, 16, NULL, &fal_vid_sw}, 115 1.3 leo { {NULL,NULL}, NULL, } 116 1.1 leo }; 117 1.1 leo 118 1.1 leo /* 119 1.2 leo * The following table contains timing values for the various video modes. 120 1.3 leo * I have only a multisync display, therefore I can not say if this values 121 1.3 leo * are useful at other displays. 122 1.2 leo * Use other video modes at YOUR OWN RISK. 123 1.2 leo * THERE IS NO WARRENTY ABOUT THIS VALUES TO WORK WITH A PARTICULAR 124 1.3 leo * DISPLAY. -- Thomas 125 1.2 leo */ 126 1.2 leo static struct videl videlinit[] = { 127 1.3 leo { RES_FALAUTO, /* autodedect */ 128 1.2 leo 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 129 1.2 leo 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, 130 1.2 leo 131 1.29 tsutsui { FAL_VGA | RES_FAL_STHIGH, /* sthigh, 640x400, 2 colors */ 132 1.29 tsutsui 0x2, 0x0, 0x28, 0x0, 0x400, 0xc6, 0x8d, 0x15, 0x273, 0x50, 0x96, 0x0, 133 1.2 leo 0x0, 0x419, 0x3af, 0x8f, 0x8f, 0x3af, 0x415, 0x186, 0x8 }, 134 1.2 leo 135 1.3 leo #if 0 /* not yet */ 136 1.3 leo { FAL_SM | RES_FAL_STHIGH, /* sthigh, 640x400, 2 colors */ 137 1.3 leo 0x0, 0x0, 0x28, 0x2, 0x0, 0x1a, 0x0, 0x0, 0x20f, 0xc, 0x14, 0x0, 138 1.3 leo 0x0, 0x3e9, 0x0, 0x0, 0x43, 0x363, 0x3e7, 0x80, 0x8 }, 139 1.3 leo #endif 140 1.3 leo 141 1.3 leo { FAL_VGA | RES_FAL_STMID, /* stmid, 640x200, 4 colors */ 142 1.29 tsutsui 0x2, 0x0, 0x50, 0x1, 0x0, 0x17, 0x12, 0x1, 0x20e, 0xd, 0x11, 0x0, 143 1.2 leo 0x0, 0x419, 0x3af, 0x8f, 0x8f, 0x3af, 0x415, 0x186, 0x9 }, 144 1.2 leo 145 1.3 leo { FAL_VGA | RES_FAL_STLOW, /* stlow, 320x200, 16 colors */ 146 1.29 tsutsui 0x2, 0x0, 0x50, 0x0, 0x0, 0x17, 0x12, 0x1, 0x20e, 0xd, 0x11, 0x0, 147 1.2 leo 0x0, 0x419, 0x3af, 0x8f, 0x8f, 0x3af, 0x415, 0x186, 0x5 }, 148 1.2 leo 149 1.3 leo { FAL_VGA | RES_FAL_TTLOW, /* ttlow, 320x480, 256 colors */ 150 1.29 tsutsui 0x2, 0x0, 0xa0, 0x0, 0x10, 0xc6, 0x8d, 0x15, 0x29a, 0x7b, 0x96, 0x0, 151 1.2 leo 0x0, 0x419, 0x3ff, 0x3f, 0x3f, 0x3ff, 0x415, 0x186, 0x4 }, 152 1.2 leo 153 1.3 leo { FAL_VGA | RES_VGA2, /* vga, 640x480, 2 colors */ 154 1.29 tsutsui 0x2, 0x0, 0x28, 0x0, 0x400, 0xc6, 0x8d, 0x15, 0x273, 0x50, 0x96, 0x0, 155 1.2 leo 0x0, 0x419, 0x3ff, 0x3f, 0x3f, 0x3ff, 0x415, 0x186, 0x8 }, 156 1.2 leo 157 1.3 leo { FAL_VGA | RES_VGA4, /* vga, 640x480, 4 colors */ 158 1.29 tsutsui 0x2, 0x0, 0x50, 0x1, 0x0, 0x17, 0x12, 0x1, 0x20e, 0xd, 0x11, 0x0, 159 1.2 leo 0x0, 0x419, 0x3ff, 0x3f, 0x3f, 0x3ff, 0x415, 0x186, 0x8 }, 160 1.2 leo 161 1.3 leo { FAL_VGA | RES_VGA16, /* vga, 640x480, 16 colors */ 162 1.29 tsutsui 0x2, 0x0, 0xa0, 0x1, 0x0, 0xc6, 0x8d, 0x15, 0x2a3, 0x7c, 0x96, 0x0, 163 1.2 leo 0x0, 0x419, 0x3ff, 0x3f, 0x3f, 0x3ff, 0x415, 0x186, 0x8 }, 164 1.2 leo 165 1.3 leo { FAL_VGA | RES_VGA256, /* vga, 640x480, 256 colors */ 166 1.29 tsutsui 0x2, 0x0, 0x140, 0x1, 0x10, 0xc6, 0x8d, 0x15, 0x2ab, 0x84, 0x96, 0x0, 167 1.2 leo 0x0, 0x419, 0x3ff, 0x3f, 0x3f, 0x3ff, 0x415, 0x186, 0x8 }, 168 1.2 leo 169 1.3 leo { FAL_VGA | RES_DIRECT, /* direct video, 320x200, 65536 colors */ 170 1.29 tsutsui 0x2, 0x0, 0x140, 0x0, 0x100, 0xc6, 0x8d, 0x15, 0x2ac, 0x91, 0x96, 0x0, 171 1.2 leo 0x0, 0x419, 0x3ff, 0x3f, 0x3f, 0x3ff, 0x415, 0x186, 0x4 }, 172 1.2 leo 173 1.3 leo { 0xffff } /* end of list */ 174 1.2 leo }; 175 1.2 leo 176 1.3 leo static u_short mon_type; 177 1.2 leo /* 178 1.1 leo * XXX: called from ite console init routine. 179 1.14 wiz * Initialize list of possible video modes. 180 1.1 leo */ 181 1.1 leo void 182 1.20 dsl falcon_probe_video(MODES *modelp) 183 1.1 leo { 184 1.1 leo dmode_t *dm; 185 1.3 leo struct videl *vregs; 186 1.1 leo int i; 187 1.1 leo 188 1.5 leo mon_type = *(volatile unsigned char *)(AD_FAL_MON_TYPE); 189 1.3 leo mon_type = (mon_type & 0xc0) << 2; 190 1.3 leo 191 1.3 leo /* 192 1.14 wiz * get all possible modes 193 1.1 leo */ 194 1.1 leo 195 1.1 leo for (i = 0; (dm = &vid_modes[i])->name != NULL; i++) { 196 1.6 leo dm->data = (void *)&fal_hwregs[i]; 197 1.6 leo if (vm_mode(dm) == RES_FALAUTO) { 198 1.6 leo vm_regs(dm) = falcon_getreg(RES_FALAUTO); 199 1.2 leo falcon_detect(dm); 200 1.2 leo LIST_INSERT_HEAD(modelp, dm, link); 201 1.3 leo } else { 202 1.6 leo vregs = falcon_getreg(vm_mode(dm) | mon_type); 203 1.3 leo if (vregs) { 204 1.6 leo vm_regs(dm) = vregs; 205 1.3 leo LIST_INSERT_HEAD(modelp, dm, link); 206 1.3 leo } 207 1.3 leo } 208 1.1 leo } 209 1.1 leo 210 1.1 leo /* 211 1.1 leo * This seems to prevent bordered screens. 212 1.1 leo */ 213 1.1 leo for (i=0; i < 16; i++) 214 1.1 leo VIDEO->vd_fal_rgb[i] = CM_L2FAL(gra_def_color16[i]); 215 1.1 leo } 216 1.1 leo 217 1.2 leo static struct videl * 218 1.20 dsl falcon_getreg(u_short mode) 219 1.2 leo { 220 1.2 leo int i; 221 1.2 leo struct videl *vregs; 222 1.29 tsutsui 223 1.3 leo for (i = 0; (vregs = &videlinit[i])->video_mode != 0xffff; i++) 224 1.3 leo if ((vregs->video_mode) == mode) 225 1.2 leo return vregs; 226 1.2 leo 227 1.3 leo return NULL; /* mode not found */ 228 1.2 leo } 229 1.2 leo 230 1.1 leo static void 231 1.20 dsl falcon_detect(dmode_t *dm) 232 1.1 leo { 233 1.1 leo u_short falshift, stshift; 234 1.6 leo struct videl *vregs = vm_regs(dm); 235 1.1 leo 236 1.2 leo /* 237 1.13 soren * First get the videl register values 238 1.2 leo */ 239 1.2 leo 240 1.2 leo vregs->vd_syncmode = VIDEO->vd_sync; 241 1.2 leo vregs->vd_line_wide = VIDEO->vd_line_wide; 242 1.2 leo vregs->vd_vert_wrap = VIDEO->vd_vert_wrap; 243 1.2 leo vregs->vd_st_res = VIDEO->vd_st_res; 244 1.2 leo vregs->vd_fal_res = VIDEO->vd_fal_res; 245 1.2 leo vregs->vd_h_hold_tim = VIDEO->vd_h_hold_tim; 246 1.2 leo vregs->vd_h_bord_beg = VIDEO->vd_h_bord_beg; 247 1.2 leo vregs->vd_h_bord_end = VIDEO->vd_h_bord_end; 248 1.2 leo vregs->vd_h_dis_beg = VIDEO->vd_h_dis_beg; 249 1.2 leo vregs->vd_h_dis_end = VIDEO->vd_h_dis_end; 250 1.2 leo vregs->vd_h_ss = VIDEO->vd_h_ss; 251 1.2 leo vregs->vd_h_fs = VIDEO->vd_h_fs; 252 1.2 leo vregs->vd_h_hh = VIDEO->vd_h_hh; 253 1.2 leo vregs->vd_v_freq_tim = VIDEO->vd_v_freq_tim; 254 1.2 leo vregs->vd_v_bord_beg = VIDEO->vd_v_bord_beg; 255 1.2 leo vregs->vd_v_bord_end = VIDEO->vd_v_bord_end; 256 1.2 leo vregs->vd_v_dis_beg = VIDEO->vd_v_dis_beg; 257 1.2 leo vregs->vd_v_dis_end = VIDEO->vd_v_dis_end; 258 1.2 leo vregs->vd_v_ss = VIDEO->vd_v_ss; 259 1.2 leo vregs->vd_fal_ctrl = VIDEO->vd_fal_ctrl; 260 1.2 leo vregs->vd_fal_mode = VIDEO->vd_fal_mode; 261 1.1 leo 262 1.1 leo /* 263 1.1 leo * Calculate the depth of the screen 264 1.1 leo */ 265 1.1 leo 266 1.2 leo falshift = vregs->vd_fal_res; 267 1.2 leo stshift = vregs->vd_st_res; 268 1.1 leo 269 1.1 leo if (falshift & 0x400) /* 2 color */ 270 1.1 leo dm->depth = 1; 271 1.1 leo else if (falshift & 0x100) /* high color, direct */ 272 1.1 leo dm->depth = 16; 273 1.1 leo else if (falshift & 0x10) /* 256 color */ 274 1.1 leo dm->depth = 8; 275 1.1 leo else if (stshift == 0) /* 16 color */ 276 1.1 leo dm->depth = 4; 277 1.1 leo else if (stshift == 1) /* 4 color */ 278 1.1 leo dm->depth = 2; 279 1.27 tsutsui else 280 1.27 tsutsui dm->depth = 1; /* 2 color */ 281 1.1 leo 282 1.1 leo /* 283 1.30 andvar * Now calculate the screen height 284 1.1 leo */ 285 1.1 leo 286 1.2 leo dm->size.height = vregs->vd_v_dis_end - vregs->vd_v_dis_beg; 287 1.2 leo if (!((vregs->vd_fal_mode & 0x2) >> 1)) /* if not interlaced */ 288 1.2 leo dm->size.height >>=1; 289 1.2 leo if (vregs->vd_fal_mode & 0x1) /* if doublescan */ 290 1.2 leo dm->size.height >>=1; 291 1.1 leo 292 1.1 leo /* 293 1.1 leo * And the width 294 1.1 leo */ 295 1.1 leo 296 1.2 leo dm->size.width = vregs->vd_vert_wrap * 16 / dm->depth; 297 1.2 leo 298 1.1 leo } 299 1.1 leo 300 1.9 leo u_long falcon_needs_vbl; 301 1.19 dsl void falcon_display_switch(void); 302 1.9 leo 303 1.1 leo static void 304 1.20 dsl falcon_display_view(view_t *v) 305 1.1 leo { 306 1.1 leo dmode_t *dm = v->mode; 307 1.9 leo bmap_t *bm; 308 1.9 leo struct videl *vregs; 309 1.9 leo static u_short last_mode = 0xffff; 310 1.1 leo 311 1.1 leo if (dm->current_view) { 312 1.1 leo /* 313 1.1 leo * Mark current view for this mode as no longer displayed 314 1.1 leo */ 315 1.1 leo dm->current_view->flags &= ~VF_DISPLAY; 316 1.1 leo } 317 1.1 leo dm->current_view = v; 318 1.1 leo v->flags |= VF_DISPLAY; 319 1.9 leo vregs = vm_regs(v->mode); 320 1.1 leo 321 1.1 leo falcon_use_colormap(v, v->colormap); 322 1.1 leo 323 1.9 leo bm = v->bitmap; 324 1.9 leo VIDEO->vd_ramh = ((u_long)bm->hw_address >> 16) & 0xff; 325 1.9 leo VIDEO->vd_ramm = ((u_long)bm->hw_address >> 8) & 0xff; 326 1.9 leo VIDEO->vd_raml = (u_long)bm->hw_address & 0xff; 327 1.9 leo 328 1.9 leo if (last_mode != vregs->video_mode) { 329 1.9 leo last_mode = vregs->video_mode; 330 1.9 leo 331 1.9 leo if (dm->depth == 1) { 332 1.9 leo /* 333 1.9 leo * Set the resolution registers to a mode, which guarantee 334 1.9 leo * no shifting when the register are written during vbl. 335 1.9 leo */ 336 1.9 leo VIDEO->vd_fal_res = 0; 337 1.9 leo VIDEO->vd_st_res = 0; 338 1.9 leo } 339 1.9 leo 340 1.9 leo /* 341 1.9 leo * Arrange for them to be activated 342 1.9 leo * at the second vbl interrupt. 343 1.9 leo */ 344 1.9 leo falcon_needs_vbl = (u_long)v; 345 1.9 leo } 346 1.9 leo } 347 1.9 leo 348 1.9 leo void 349 1.22 cegger falcon_display_switch(void) 350 1.9 leo { 351 1.9 leo view_t *v; 352 1.9 leo struct videl *vregs; 353 1.9 leo static int vbl_count = 1; 354 1.9 leo 355 1.27 tsutsui if (vbl_count--) 356 1.27 tsutsui return; 357 1.9 leo 358 1.9 leo v = (view_t*)falcon_needs_vbl; 359 1.3 leo 360 1.9 leo vbl_count = 1; 361 1.9 leo falcon_needs_vbl = 0; 362 1.3 leo 363 1.3 leo /* 364 1.3 leo * Write to videl registers only on VGA displays 365 1.3 leo * This is only a hack. Must be fixed soon. XXX -- Thomas 366 1.3 leo */ 367 1.27 tsutsui if (mon_type != FAL_VGA) 368 1.27 tsutsui return; 369 1.2 leo 370 1.9 leo vregs = vm_regs(v->mode); 371 1.9 leo 372 1.9 leo VIDEO->vd_v_freq_tim = vregs->vd_v_freq_tim; 373 1.9 leo VIDEO->vd_v_ss = vregs->vd_v_ss; 374 1.9 leo VIDEO->vd_v_bord_beg = vregs->vd_v_bord_beg; 375 1.9 leo VIDEO->vd_v_bord_end = vregs->vd_v_bord_end; 376 1.9 leo VIDEO->vd_v_dis_beg = vregs->vd_v_dis_beg; 377 1.9 leo VIDEO->vd_v_dis_end = vregs->vd_v_dis_end; 378 1.9 leo VIDEO->vd_h_hold_tim = vregs->vd_h_hold_tim; 379 1.9 leo VIDEO->vd_h_ss = vregs->vd_h_ss; 380 1.9 leo VIDEO->vd_h_bord_beg = vregs->vd_h_bord_beg; 381 1.9 leo VIDEO->vd_h_bord_end = vregs->vd_h_bord_end; 382 1.9 leo VIDEO->vd_h_dis_beg = vregs->vd_h_dis_beg; 383 1.9 leo VIDEO->vd_h_dis_end = vregs->vd_h_dis_end; 384 1.2 leo #if 0 /* This seems not to be necessary -- Thomas */ 385 1.2 leo VIDEO->vd_h_fs = vregs->vd_h_fs; 386 1.2 leo VIDEO->vd_h_hh = vregs->vd_h_hh; 387 1.2 leo #endif 388 1.2 leo VIDEO->vd_sync = vregs->vd_syncmode; 389 1.2 leo VIDEO->vd_fal_res = 0; 390 1.9 leo if (v->mode->depth == 2) 391 1.2 leo VIDEO->vd_st_res = vregs->vd_st_res; 392 1.2 leo else { 393 1.2 leo VIDEO->vd_st_res = 0; 394 1.2 leo VIDEO->vd_fal_res = vregs->vd_fal_res; 395 1.2 leo } 396 1.2 leo VIDEO->vd_vert_wrap = vregs->vd_vert_wrap; 397 1.2 leo VIDEO->vd_line_wide = vregs->vd_line_wide; 398 1.2 leo VIDEO->vd_fal_ctrl = vregs->vd_fal_ctrl; 399 1.2 leo VIDEO->vd_fal_mode = vregs->vd_fal_mode; 400 1.1 leo } 401 1.1 leo 402 1.1 leo static void 403 1.20 dsl falcon_remove_view(view_t *v) 404 1.1 leo { 405 1.1 leo dmode_t *mode = v->mode; 406 1.1 leo 407 1.1 leo if (mode->current_view == v) { 408 1.1 leo #if 0 409 1.1 leo if (v->flags & VF_DISPLAY) 410 1.15 provos panic("Cannot shutdown display"); /* XXX */ 411 1.1 leo #endif 412 1.1 leo mode->current_view = NULL; 413 1.1 leo } 414 1.1 leo v->flags &= ~VF_DISPLAY; 415 1.1 leo } 416 1.1 leo 417 1.7 leo void 418 1.20 dsl falcon_save_view(view_t *v) 419 1.7 leo { 420 1.7 leo } 421 1.7 leo 422 1.1 leo static void 423 1.20 dsl falcon_free_view(view_t *v) 424 1.1 leo { 425 1.1 leo if (v) { 426 1.1 leo falcon_remove_view(v); 427 1.1 leo if (v->colormap != &gra_con_cmap) 428 1.1 leo free(v->colormap, M_DEVBUF); 429 1.1 leo free_bitmap(v->bitmap); 430 1.1 leo if (v != &gra_con_view) 431 1.1 leo free(v, M_DEVBUF); 432 1.1 leo } 433 1.1 leo } 434 1.1 leo 435 1.1 leo static int 436 1.20 dsl falcon_use_colormap(view_t *v, colormap_t *cm) 437 1.1 leo { 438 1.1 leo dmode_t *dm; 439 1.1 leo volatile u_short *creg; 440 1.1 leo volatile u_long *fcreg; 441 1.1 leo u_long *src; 442 1.1 leo colormap_t *vcm; 443 1.1 leo u_long *vcreg; 444 1.1 leo u_short ncreg; 445 1.11 leo int last_streg; 446 1.1 leo int i; 447 1.1 leo 448 1.1 leo dm = v->mode; 449 1.1 leo vcm = v->colormap; 450 1.1 leo 451 1.1 leo /* 452 1.1 leo * I guess it seems reasonable to require the maps to be 453 1.1 leo * of the same type... 454 1.1 leo */ 455 1.1 leo if (cm->type != vcm->type) 456 1.1 leo return (EINVAL); 457 1.1 leo 458 1.1 leo /* 459 1.31 rillig * First get the colormap addresses and calculate 460 1.31 rillig * how many colors are in it. 461 1.1 leo */ 462 1.1 leo if (dm->depth == 16) /* direct color, no colormap; 463 1.1 leo but also not (yet) supported */ 464 1.1 leo return(0); 465 1.1 leo fcreg = &VIDEO->vd_fal_rgb[0]; 466 1.1 leo creg = &VIDEO->vd_st_rgb[0]; 467 1.1 leo ncreg = 1 << dm->depth; 468 1.1 leo 469 1.1 leo /* If first entry specified beyond capabilities -> error */ 470 1.1 leo if (cm->first >= ncreg) 471 1.1 leo return (EINVAL); 472 1.1 leo 473 1.1 leo /* 474 1.1 leo * A little tricky, the actual colormap pointer will be NULL 475 1.1 leo * when view is not displaying, valid otherwise. 476 1.1 leo */ 477 1.11 leo if (v->flags & VF_DISPLAY) { 478 1.1 leo creg = &creg[cm->first]; 479 1.11 leo fcreg = &fcreg[cm->first]; 480 1.11 leo } else { 481 1.11 leo creg = NULL; 482 1.11 leo fcreg = NULL; 483 1.11 leo } 484 1.1 leo 485 1.1 leo vcreg = &vcm->entry[cm->first]; 486 1.1 leo ncreg -= cm->first; 487 1.11 leo last_streg = 16 - cm->first; 488 1.1 leo if (cm->size > ncreg) 489 1.1 leo return (EINVAL); 490 1.1 leo ncreg = cm->size; 491 1.1 leo 492 1.1 leo for (i = 0, src = cm->entry; i < ncreg; i++, vcreg++) { 493 1.1 leo *vcreg = *src++; 494 1.1 leo 495 1.1 leo /* 496 1.1 leo * If displaying, also update actual color register. 497 1.1 leo */ 498 1.11 leo if (fcreg != NULL) { 499 1.1 leo *fcreg++ = CM_L2FAL(*vcreg); 500 1.11 leo if (i < last_streg) 501 1.1 leo *creg++ = CM_L2ST(*vcreg); 502 1.1 leo } 503 1.1 leo } 504 1.1 leo return (0); 505 1.1 leo } 506 1.1 leo 507 1.1 leo static view_t * 508 1.20 dsl falcon_alloc_view(dmode_t *mode, dimen_t *dim, u_char depth) 509 1.1 leo { 510 1.1 leo view_t *v; 511 1.1 leo bmap_t *bm; 512 1.1 leo 513 1.1 leo if (!atari_realconfig) 514 1.1 leo v = &gra_con_view; 515 1.27 tsutsui else 516 1.27 tsutsui v = malloc(sizeof(*v), M_DEVBUF, M_NOWAIT); 517 1.1 leo if (v == NULL) 518 1.1 leo return(NULL); 519 1.29 tsutsui 520 1.1 leo bm = alloc_bitmap(mode->size.width, mode->size.height, mode->depth); 521 1.1 leo if (bm) { 522 1.1 leo box_t box; 523 1.1 leo 524 1.1 leo v->colormap = alloc_colormap(mode); 525 1.1 leo if (v->colormap) { 526 1.1 leo INIT_BOX(&box,0,0,mode->size.width,mode->size.height); 527 1.1 leo init_view(v, bm, mode, &box); 528 1.1 leo return(v); 529 1.1 leo } 530 1.1 leo free_bitmap(bm); 531 1.1 leo } 532 1.1 leo if (v != &gra_con_view) 533 1.1 leo free(v, M_DEVBUF); 534 1.1 leo return (NULL); 535 1.1 leo } 536 1.1 leo 537 1.1 leo static void 538 1.20 dsl init_view(view_t *v, bmap_t *bm, dmode_t *mode, box_t *dbox) 539 1.1 leo { 540 1.1 leo v->bitmap = bm; 541 1.1 leo v->mode = mode; 542 1.1 leo v->flags = 0; 543 1.25 tsutsui memcpy(&v->display, dbox, sizeof(box_t)); 544 1.1 leo } 545 1.1 leo 546 1.1 leo /* bitmap functions */ 547 1.1 leo 548 1.1 leo static bmap_t * 549 1.21 dsl alloc_bitmap(u_long width, u_long height, u_char depth) 550 1.1 leo { 551 1.1 leo u_long total_size, bm_size; 552 1.1 leo void *hw_address; 553 1.1 leo bmap_t *bm; 554 1.1 leo 555 1.1 leo /* 556 1.1 leo * Sigh, it seems for mapping to work we need the bitplane data to 557 1.28 andvar * 1: be aligned on a page boundary. 558 1.1 leo * 2: be n pages large. 559 1.29 tsutsui * 560 1.1 leo * why? because the user gets a page aligned address, if this is before 561 1.1 leo * your allocation, too bad. Also it seems that the mapping routines 562 1.1 leo * do not watch to closely to the allowable length. so if you go over 563 1.1 leo * n pages by less than another page, the user gets to write all over 564 1.28 andvar * the entire page. Since you did not allocate up to a page boundary 565 1.1 leo * (or more) the user writes into someone elses memory. -ch 566 1.1 leo */ 567 1.10 veego bm_size = m68k_round_page((width * height * depth) / NBBY); 568 1.16 thorpej total_size = bm_size + sizeof(bmap_t) + PAGE_SIZE; 569 1.1 leo 570 1.1 leo if ((bm = (bmap_t*)alloc_stmem(total_size, &hw_address)) == NULL) 571 1.1 leo return(NULL); 572 1.1 leo 573 1.1 leo bm->plane = (u_char*)bm + sizeof(bmap_t); 574 1.10 veego bm->plane = (u_char*)m68k_round_page(bm->plane); 575 1.1 leo bm->hw_address = (u_char*)hw_address + sizeof(bmap_t); 576 1.10 veego bm->hw_address = (u_char*)m68k_round_page(bm->hw_address); 577 1.1 leo bm->bytes_per_row = (width * depth) / NBBY; 578 1.1 leo bm->rows = height; 579 1.1 leo bm->depth = depth; 580 1.8 leo bm->phys_mappable = (depth * width * height) / NBBY; 581 1.12 thomas bm->regs = NULL; 582 1.12 thomas bm->hw_regs = NULL; 583 1.12 thomas bm->reg_size = 0; 584 1.12 thomas bm->vga_address = NULL; 585 1.12 thomas bm->vga_mappable = 0; 586 1.12 thomas bm->lin_base = 0; 587 1.12 thomas bm->vga_base = 0; 588 1.1 leo 589 1.23 cegger memset(bm->plane, 0, bm_size); 590 1.1 leo return (bm); 591 1.1 leo } 592 1.1 leo 593 1.1 leo static void 594 1.20 dsl free_bitmap(bmap_t *bm) 595 1.1 leo { 596 1.1 leo if (bm) 597 1.1 leo free_stmem(bm); 598 1.1 leo } 599 1.1 leo 600 1.1 leo static colormap_t * 601 1.20 dsl alloc_colormap(dmode_t *dm) 602 1.1 leo { 603 1.1 leo int nentries, i; 604 1.1 leo colormap_t *cm; 605 1.1 leo u_char type = CM_COLOR; 606 1.1 leo 607 1.1 leo if (dm->depth == 16) /* direct color, no colormap; 608 1.1 leo not (yet) supported */ 609 1.1 leo nentries = 0; 610 1.1 leo else 611 1.1 leo nentries = 1 << dm->depth; 612 1.1 leo 613 1.1 leo if (!atari_realconfig) { 614 1.1 leo cm = &gra_con_cmap; 615 1.1 leo cm->entry = gra_con_colors; 616 1.27 tsutsui } else { 617 1.1 leo int size; 618 1.1 leo 619 1.1 leo size = sizeof(*cm) + (nentries * sizeof(cm->entry[0])); 620 1.1 leo cm = malloc(size, M_DEVBUF, M_NOWAIT); 621 1.1 leo if (cm == NULL) 622 1.1 leo return(NULL); 623 1.1 leo cm->entry = (long *)&cm[1]; 624 1.1 leo 625 1.1 leo } 626 1.1 leo 627 1.1 leo if ((cm->type = type) == CM_COLOR) 628 1.1 leo cm->red_mask = cm->green_mask = cm->blue_mask = 0x3f; 629 1.1 leo 630 1.1 leo cm->first = 0; 631 1.1 leo cm->size = nentries; 632 1.1 leo 633 1.1 leo for (i = 0; i < nentries; i++) 634 1.1 leo cm->entry[i] = gra_def_color16[i % 16]; 635 1.1 leo return (cm); 636 1.1 leo } 637 1.1 leo #endif /* FALCON_VIDEO */ 638