grfabs_tt.c revision 1.16 1 /* $NetBSD: grfabs_tt.c,v 1.16 2009/03/14 14:45:56 dsl 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 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: grfabs_tt.c,v 1.16 2009/03/14 14:45:56 dsl Exp $");
35
36 #ifdef TT_VIDEO
37 /*
38 * atari abstract graphics driver: TT-interface
39 */
40 #include <sys/param.h>
41 #include <sys/queue.h>
42 #include <sys/malloc.h>
43 #include <sys/device.h>
44 #include <sys/systm.h>
45
46 #include <uvm/uvm_extern.h>
47
48 #include <machine/iomap.h>
49 #include <machine/video.h>
50 #include <machine/mfp.h>
51 #include <atari/atari/device.h>
52 #include <atari/atari/stalloc.h>
53 #include <atari/dev/grfabs_reg.h>
54 #include <atari/dev/grfabs_tt.h>
55
56 /*
57 * Function decls
58 */
59 static void init_view(view_t *, bmap_t *, dmode_t *, box_t *);
60 static bmap_t *alloc_bitmap(u_long, u_long, u_char);
61 static colormap_t *alloc_colormap(dmode_t *);
62 static void free_bitmap(bmap_t *);
63 static void tt_display_view(view_t *);
64 static view_t *tt_alloc_view(dmode_t *, dimen_t *, u_char);
65 static void tt_free_view(view_t *);
66 static void tt_remove_view(view_t *);
67 static void tt_save_view(view_t *);
68 static int tt_use_colormap(view_t *, colormap_t *);
69
70 /*
71 * Our function switch table
72 */
73 struct grfabs_sw tt_vid_sw = {
74 tt_display_view,
75 tt_alloc_view,
76 tt_free_view,
77 tt_remove_view,
78 tt_save_view,
79 tt_use_colormap
80 };
81
82 struct tt_hwregs {
83 u_short tt_reg; /* video mode-register TT */
84 };
85 #define vm_reg(dm) (((struct tt_hwregs*)(dm->data))->tt_reg)
86
87 /*
88 * Note that the order of this table *must* match the order of
89 * the table below!
90 */
91 static struct tt_hwregs tt_hwregs[] = {
92 { RES_STHIGH },
93 { RES_TTHIGH },
94 { RES_STMID },
95 { RES_STLOW },
96 { RES_TTMID },
97 { RES_TTLOW }
98 };
99
100 static dmode_t vid_modes[] = {
101 { { NULL, NULL }, "sthigh", { 640, 400 }, 1, NULL, &tt_vid_sw },
102 { { NULL, NULL }, "tthigh", { 1280, 960 }, 1, NULL, &tt_vid_sw },
103 { { NULL, NULL }, "stmid", { 640, 200 }, 2, NULL, &tt_vid_sw },
104 { { NULL, NULL }, "stlow", { 320, 200 }, 4, NULL, &tt_vid_sw },
105 { { NULL, NULL }, "ttmid", { 640, 480 }, 4, NULL, &tt_vid_sw },
106 { { NULL, NULL }, "ttlow", { 320, 480 }, 8, NULL, &tt_vid_sw },
107 { { NULL, NULL }, NULL, }
108 };
109
110 /*
111 * XXX: called from ite console init routine.
112 * Initialize list of possible video modes.
113 */
114
115 void
116 tt_probe_video(modelp)
117 MODES *modelp;
118 {
119 dmode_t *dm;
120 int i;
121 int has_mono;
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 for (i = 0; (dm = &vid_modes[i])->name != NULL; i++) {
132 dm->data = (void *)&tt_hwregs[i];
133 if (has_mono && (vm_reg(dm) != RES_TTHIGH))
134 continue;
135 if (!has_mono && (vm_reg(dm) == RES_TTHIGH))
136 continue;
137 LIST_INSERT_HEAD(modelp, dm, link);
138 }
139
140 for (i=0; i < 16; i++)
141 VIDEO->vd_tt_rgb[i] = CM_L2TT(gra_def_color16[i]);
142 }
143
144 static void
145 tt_display_view(v)
146 view_t *v;
147 {
148 dmode_t *dm = v->mode;
149 bmap_t *bm = v->bitmap;
150
151 if (dm->current_view) {
152 /*
153 * Mark current view for this mode as no longer displayed
154 */
155 dm->current_view->flags &= ~VF_DISPLAY;
156 }
157 dm->current_view = v;
158 v->flags |= VF_DISPLAY;
159
160 tt_use_colormap(v, v->colormap);
161
162 /* XXX: should use vbl for this */
163 VIDEO->vd_tt_res = vm_reg(dm);
164 VIDEO->vd_raml = (u_long)bm->hw_address & 0xff;
165 VIDEO->vd_ramm = ((u_long)bm->hw_address >> 8) & 0xff;
166 VIDEO->vd_ramh = ((u_long)bm->hw_address >> 16) & 0xff;
167 }
168
169 void
170 tt_remove_view(v)
171 view_t *v;
172 {
173 dmode_t *mode = v->mode;
174
175 if (mode->current_view == v) {
176 #if 0
177 if (v->flags & VF_DISPLAY)
178 panic("Cannot shutdown display"); /* XXX */
179 #endif
180 mode->current_view = NULL;
181 }
182 v->flags &= ~VF_DISPLAY;
183 }
184
185 void
186 tt_save_view(v)
187 view_t *v;
188 {
189 }
190
191 void
192 tt_free_view(v)
193 view_t *v;
194 {
195 if(v) {
196 tt_remove_view(v);
197 if (v->colormap != &gra_con_cmap)
198 free(v->colormap, M_DEVBUF);
199 free_bitmap(v->bitmap);
200 if (v != &gra_con_view)
201 free(v, M_DEVBUF);
202 }
203 }
204
205 static int
206 tt_use_colormap(v, cm)
207 view_t *v;
208 colormap_t *cm;
209 {
210 dmode_t *dm;
211 volatile u_short *creg;
212 u_long *src;
213 colormap_t *vcm;
214 u_long *vcreg;
215 u_short ncreg;
216 int i;
217
218 dm = v->mode;
219 vcm = v->colormap;
220
221 /*
222 * I guess it seems reasonable to require the maps to be
223 * of the same type...
224 */
225 if (cm->type != vcm->type)
226 return(EINVAL);
227
228 /*
229 * First figure out where the actual colormap resides and
230 * howmany colors are in it.
231 */
232 switch (vm_reg(dm)) {
233 case RES_STLOW:
234 creg = &VIDEO->vd_tt_rgb[0];
235 ncreg = 16;
236 break;
237 case RES_STMID:
238 creg = &VIDEO->vd_tt_rgb[0];
239 ncreg = 4;
240 break;
241 case RES_STHIGH:
242 creg = &VIDEO->vd_tt_rgb[254];
243 ncreg = 2;
244 break;
245 case RES_TTLOW:
246 creg = &VIDEO->vd_tt_rgb[0];
247 ncreg = 256;
248 break;
249 case RES_TTMID:
250 creg = &VIDEO->vd_tt_rgb[0];
251 ncreg = 16;
252 break;
253 case RES_TTHIGH:
254 return(0); /* No colors */
255 default:
256 panic("grf_tt:use_colormap: wrong mode!?");
257 }
258
259 /* If first entry specified beyond capabilities -> error */
260 if (cm->first >= ncreg)
261 return(EINVAL);
262
263 /*
264 * A little tricky, the actual colormap pointer will be NULL
265 * when view is not displaying, valid otherwise.
266 */
267 if (v->flags & VF_DISPLAY)
268 creg = &creg[cm->first];
269 else creg = NULL;
270
271 vcreg = &vcm->entry[cm->first];
272 ncreg -= cm->first;
273 if (cm->size > ncreg)
274 return(EINVAL);
275 ncreg = cm->size;
276
277 for (i = 0, src = cm->entry; i < ncreg; i++, vcreg++) {
278 *vcreg = *src++;
279
280 /*
281 * If displaying, also update actual color registers.
282 */
283 if (creg != NULL)
284 *creg++ = CM_L2TT(*vcreg);
285 }
286 return (0);
287 }
288
289 static view_t *
290 tt_alloc_view(mode, dim, depth)
291 dmode_t *mode;
292 dimen_t *dim;
293 u_char depth;
294 {
295 view_t *v;
296 bmap_t *bm;
297
298 if (!atari_realconfig)
299 v = &gra_con_view;
300 else v = malloc(sizeof(*v), M_DEVBUF, M_NOWAIT);
301 if(v == NULL)
302 return (NULL);
303
304 bm = alloc_bitmap(mode->size.width, mode->size.height, mode->depth);
305 if (bm) {
306 box_t box;
307
308 v->colormap = alloc_colormap(mode);
309 if (v->colormap) {
310 INIT_BOX(&box,0,0,mode->size.width,mode->size.height);
311 init_view(v, bm, mode, &box);
312 return (v);
313 }
314 free_bitmap(bm);
315 }
316 if (v != &gra_con_view)
317 free(v, M_DEVBUF);
318 return (NULL);
319 }
320
321 static void
322 init_view(v, bm, mode, dbox)
323 view_t *v;
324 bmap_t *bm;
325 dmode_t *mode;
326 box_t *dbox;
327 {
328 v->bitmap = bm;
329 v->mode = mode;
330 v->flags = 0;
331 bcopy(dbox, &v->display, sizeof(box_t));
332 }
333
334 /* bitmap functions */
335
336 static bmap_t *
337 alloc_bitmap(width, height, depth)
338 u_long width, height;
339 u_char depth;
340 {
341 u_long total_size, bm_size;
342 void *hw_address;
343 bmap_t *bm;
344
345 /*
346 * Sigh, it seems for mapping to work we need the bitplane data to
347 * 1: be aligned on a page boundry.
348 * 2: be n pages large.
349 *
350 * why? because the user gets a page aligned address, if this is before
351 * your allocation, too bad. Also it seems that the mapping routines
352 * do not watch to closely to the allowable length. so if you go over
353 * n pages by less than another page, the user gets to write all over
354 * the entire page. Since you did not allocate up to a page boundry
355 * (or more) the user writes into someone elses memory. -ch
356 */
357 bm_size = m68k_round_page((width * height * depth) / NBBY);
358 total_size = bm_size + sizeof(bmap_t) + PAGE_SIZE;
359
360 if ((bm = (bmap_t*)alloc_stmem(total_size, &hw_address)) == NULL)
361 return(NULL);
362
363 bm->plane = (u_char*)bm + sizeof(bmap_t);
364 bm->plane = (u_char*)m68k_round_page(bm->plane);
365 bm->hw_address = (u_char*)hw_address + sizeof(bmap_t);
366 bm->hw_address = (u_char*)m68k_round_page(bm->hw_address);
367 bm->bytes_per_row = (width * depth) / NBBY;
368 bm->rows = height;
369 bm->depth = depth;
370 bm->regs = NULL;
371 bm->hw_regs = NULL;
372 bm->reg_size = 0;
373 bm->phys_mappable = (depth * width * height) / NBBY;
374 bm->lin_base = 0;
375 bm->vga_address = NULL;
376 bm->vga_mappable = 0;
377 bm->vga_base = 0;
378
379 bzero(bm->plane, bm_size);
380 return (bm);
381 }
382
383 static void
384 free_bitmap(bm)
385 bmap_t *bm;
386 {
387 if (bm)
388 free_stmem(bm);
389 }
390
391 static colormap_t *
392 alloc_colormap(dm)
393 dmode_t *dm;
394 {
395 int nentries, i;
396 colormap_t *cm;
397 u_char type = CM_COLOR;
398
399 switch (vm_reg(dm)) {
400 case RES_STLOW:
401 case RES_TTMID:
402 nentries = 16;
403 break;
404 case RES_STMID:
405 nentries = 4;
406 break;
407 case RES_STHIGH:
408 nentries = 2;
409 break;
410 case RES_TTLOW:
411 nentries = 256;
412 break;
413 case RES_TTHIGH:
414 type = CM_MONO;
415 nentries = 0;
416 break;
417 default:
418 panic("grf_tt:alloc_colormap: wrong mode!?");
419 }
420 if (!atari_realconfig) {
421 cm = &gra_con_cmap;
422 cm->entry = gra_con_colors;
423 }
424 else {
425 int size;
426
427 size = sizeof(*cm) + (nentries * sizeof(cm->entry[0]));
428 cm = malloc(size, M_DEVBUF, M_NOWAIT);
429 if (cm == NULL)
430 return (NULL);
431 cm->entry = (long *)&cm[1];
432
433 }
434 if ((cm->type = type) == CM_COLOR)
435 cm->red_mask = cm->green_mask = cm->blue_mask = 0xf;
436 cm->first = 0;
437 cm->size = nentries;
438
439 for (i = 0; i < nentries; i++)
440 cm->entry[i] = gra_def_color16[i % 16];
441 return (cm);
442 }
443 #endif /* TT_VIDEO */
444