grfabs_cc.c revision 1.21 1 /* $NetBSD: grfabs_cc.c,v 1.21 2002/01/26 13:40:55 aymeric Exp $ */
2
3 /*
4 * Copyright (c) 1994 Christian E. Hopps
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 Christian E. Hopps.
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 * abstract interface for custom chips to the amiga abstract graphics driver.
35 *
36 */
37
38 #include "opt_amigaccgrf.h"
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/errno.h>
43 #include <sys/cdefs.h>
44 #include <sys/queue.h>
45
46 #include <amiga/amiga/custom.h>
47 #include <amiga/amiga/cc.h>
48
49 #include <amiga/dev/grfabs_reg.h>
50 #include <amiga/dev/grfabs_ccreg.h>
51
52 monitor_t *m_this;
53 mdata_t *m_this_data;
54 char *monitor_name = "CCMONITOR";
55 monitor_t monitor;
56 mdata_t monitor_data;
57 cop_t *null_mode_copper_list;
58
59 #if defined (GRF_PAL)
60 # if defined (GRF_A2024)
61 dmode_t pal_a2024_mode;
62 dmdata_t pal_a2024_mode_data;
63 cop_t *pal_a2024_frames[F_QD_TOTAL];
64 u_char *hedley_init; /* init bitplane. */
65 dmode_t *p24_this;
66 dmdata_t *p24_this_data;
67
68 dmode_t pal_hires_dlace_mode;
69 dmdata_t pal_hires_dlace_mode_data;
70 cop_t *pal_hires_dlace_frames[F_LACE_TOTAL];
71 dmode_t *phdl_this;
72 dmdata_t *phdl_this_data;
73 # endif /* GRF_A2024 */
74
75 # if defined (GRF_AGA)
76 dmode_t paga_mode;
77 dmdata_t paga_mode_data;
78 cop_t *paga_frames[F_TOTAL];
79 dmode_t *paga_this;
80 dmdata_t *paga_this_data;
81
82 # endif /* GRF_AGA */
83
84 dmode_t pal_hires_lace_mode;
85 dmdata_t pal_hires_lace_mode_data;
86 cop_t *pal_hires_lace_frames[F_LACE_TOTAL];
87 dmode_t *phl_this;
88 dmdata_t *phl_this_data;
89
90 dmode_t pal_hires_mode;
91 dmdata_t pal_hires_mode_data;
92 cop_t *pal_hires_frames[F_TOTAL];
93 dmode_t *ph_this;
94 dmdata_t *ph_this_data;
95 #endif /* PAL */
96
97 #if defined (GRF_NTSC)
98 # if defined (GRF_A2024)
99 dmode_t a2024_mode;
100 dmdata_t a2024_mode_data;
101 cop_t *a2024_frames[F_QD_TOTAL];
102 u_char *hedley_init; /* init bitplane. */
103 dmode_t *a24_this;
104 dmdata_t *a24_this_data;
105
106 dmode_t hires_dlace_mode;
107 dmdata_t hires_dlace_mode_data;
108 cop_t *hires_dlace_frames[F_LACE_TOTAL];
109 dmode_t *hdl_this;
110 dmdata_t *hdl_this_data;
111 # endif /* GRF_A2024 */
112
113 # if defined (GRF_AGA)
114 dmode_t aga_mode;
115 dmdata_t aga_mode_data;
116 cop_t *aga_frames[F_TOTAL];
117 dmode_t *aga_this;
118 dmdata_t *aga_this_data;
119
120 #if defined (GRF_SUPER72)
121 dmode_t super72_mode;
122 dmdata_t super72_mode_data;
123 cop_t *super72_frames[F_LACE_TOTAL];
124 dmode_t *super72_this;
125 dmdata_t *super72_this_data;
126 #endif /* GRF_SUPER72 */
127
128 # endif /* GRF_AGA */
129
130 dmode_t hires_lace_mode;
131 dmdata_t hires_lace_mode_data;
132 cop_t *hires_lace_frames[F_LACE_TOTAL];
133 dmode_t *hl_this;
134 dmdata_t *hl_this_data;
135
136 void display_hires_view(view_t * v);
137 dmode_t hires_mode;
138 dmdata_t hires_mode_data;
139 cop_t *hires_frames[F_TOTAL];
140 dmode_t *h_this;
141 dmdata_t *h_this_data;
142 #endif /* GRF_NTSC */
143
144 #ifdef GRF_AGA
145 #define AGA_ENABLE 0x0001
146 #define AGA_ENABLE2 0x0002
147 #define AGA_TRACE 0x0004
148 #define AGA_TRACE2 0x0008
149 #define AGA_VGAONLY 0x0010
150 #define AGA_VGA31KHZ 0x0020
151
152 int aga_enable = 0; /* set by start_c(), or can be patched */
153 colormap_t *cc_alloc_aga_colormap(int);
154 int cc_use_aga_colormap(view_t *, colormap_t *);
155 #endif
156
157 /* monitor functions. */
158 monitor_t *
159 cc_init_monitor(void)
160 {
161 cop_t *cp;
162
163 if (m_this)
164 return(m_this);
165
166 cc_monitor = m_this = &monitor;
167 /* turn sprite DMA off. we don't support them yet. */
168 custom.dmacon = DMAF_SPRITE;
169
170 /* makre sure sprite data registers are clear as well */
171 custom.spr[0].data = 0;
172 custom.spr[0].datb = 0;
173
174 m_this->name = monitor_name;
175 m_this_data = m_this->data = &monitor_data;
176
177 m_this->get_current_mode = get_current_mode;
178 m_this->vbl_handler = (vbl_handler_func *) monitor_vbl_handler;
179 m_this->get_next_mode = get_next_mode;
180 m_this->get_best_mode = get_best_mode;
181
182 m_this->alloc_bitmap = alloc_bitmap;
183 m_this->free_bitmap = free_bitmap;
184
185 m_this_data->current_mode = NULL;
186 LIST_INIT(&m_this_data->modes);
187
188 cp = null_mode_copper_list = alloc_chipmem(sizeof(cop_t) * 4);
189 if (!cp)
190 panic("no chipmem for grf.");
191
192 CMOVE(cp, R_COLOR00, 0x0000); /* background is black */
193 CMOVE(cp, R_BPLCON0, 0x0000); /* no planes to fetch from */
194 CWAIT(cp, 255, 255); /* COPEND */
195 CWAIT(cp, 255, 255); /* COPEND really */
196
197 /* install this list and turn DMA on */
198 custom.cop1lc = PREP_DMA_MEM(null_mode_copper_list);
199 custom.copjmp1 = 0;
200 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER \
201 |DMAF_COPPER;
202
203 cc_init_modes();
204 LIST_INSERT_HEAD(monitors, m_this, link);
205 return (m_this);
206 }
207
208 void
209 monitor_vbl_handler(monitor_t *m)
210 {
211 dmdata_t *dmd;
212
213 if (m_this_data->current_mode == NULL)
214 return;
215
216 dmd = DMDATA(m_this_data->current_mode);
217 if (dmd)
218 dmd->vbl_handler(m_this_data->current_mode);
219 }
220
221 dmode_t *
222 get_current_mode(void)
223 {
224 if (m_this_data->current_mode)
225 return(m_this_data->current_mode);
226 else
227 return(NULL);
228 }
229
230 dmode_t *
231 get_next_mode(dmode_t *d)
232 {
233 if (d)
234 return(d->link.le_next);
235 return(m_this_data->modes.lh_first);
236 }
237
238 /* XXX needs to have more control attributes */
239 dmode_t *
240 get_best_mode(dimen_t *size, u_char depth)
241 {
242 dmode_t *save;
243 dmode_t *dm;
244 long dt = 0, dx, dy, ct;
245 dmdata_t *dmd;
246
247 save = NULL;
248 dm = m_this_data->modes.lh_first;
249 while (dm != NULL) {
250 dmd = dm->data;
251 if (depth > dmd->max_depth || depth < dmd->min_depth) {
252 dm = dm->link.le_next;
253 continue;
254 } else if (size->width > dmd->max_size.width ||
255 size->height > dmd->max_size.height) {
256 dm = dm->link.le_next;
257 continue;
258 } else if (size->width < dmd->min_size.width ||
259 size->height < dmd->min_size.height) {
260 dm = dm->link.le_next;
261 continue;
262 }
263 dx = abs(dm->nominal_size.width - size->width);
264 dy = abs(dm->nominal_size.height - size->height);
265 ct = dx + dy;
266
267 if (ct < dt || save == NULL) {
268 save = dm;
269 dt = ct;
270 }
271 dm = dm->link.le_next;
272 }
273 return (save);
274 }
275 /* bitmap functions */
276 bmap_t *
277 alloc_bitmap(u_short width, u_short height, u_short depth, u_short flags)
278 {
279 int i;
280 u_long total_size;
281 #ifdef GRF_AGA
282 u_short lwpr = (flags & BMF_ALIGN64) ? ((width + 63) / 64) * 2 :
283 (width + 31) / 32; /* AGA needs 64 bit align */
284 #else
285 u_short lwpr = (width + 31) / 32;
286 #endif
287 u_short wpr = lwpr << 1;
288 u_short bpr = wpr << 1;
289 u_short array_size = sizeof(u_char *) * depth;
290 u_long plane_size = bpr * height;
291 u_short temp_size = bpr + sizeof(u_long);
292 bmap_t *bm;
293
294 /* note the next allocation will give everything, also note that all
295 * the stuff we want (including bitmaps) will be long short aligned.
296 * This is a function of the data being allocated and the fact that
297 * alloc_chipmem() returns long short aligned data. note also that
298 * each row of the bitmap is long word aligned and made of exactly n
299 * longwords. -ch */
300
301 /* Sigh, it seems for mapping to work we need the bitplane data to 1:
302 * be aligned on a page boundry. 2: be n pages large.
303 *
304 * why? becuase the user gets a page aligned address, if this is before
305 * your allocation, too bad. Also it seems that the mapping routines
306 * do not watch to closely to the allowable length. so if you go over
307 * n pages by less than another page, the user gets to write all over
308 * the entire page. Since you did not allocate up to a page boundry
309 * (or more) the user writes into someone elses memory. -ch */
310 #ifdef __powerpc__
311 #define m68k_round_page(x) ((((unsigned)(x)) + PGOFSET) & ~PGOFSET)
312 #endif
313 total_size = m68k_round_page(plane_size * depth) + /* for length */
314 (temp_size) + (array_size) + sizeof(bmap_t) +
315 NBPG; /* for alignment */
316 bm = alloc_chipmem(total_size);
317 if (bm) {
318 if (flags & BMF_CLEAR) {
319 bzero(bm, total_size);
320 }
321 bm->bytes_per_row = bpr;
322 bm->rows = height;
323 bm->depth = depth;
324 bm->flags = flags;
325 bm->plane = (u_char **) & bm[1];
326 bm->blit_temp = ((u_char *) bm->plane) + array_size;
327 bm->plane[0] = (u_char *) m68k_round_page((u_long)
328 (bm->blit_temp + temp_size));
329 if (flags & BMF_INTERLEAVED) {
330 bm->row_mod = bm->bytes_per_row * (depth - 1);
331 for (i = 1; i < depth; i++) {
332 bm->plane[i] = bm->plane[i - 1] + bpr;
333 }
334 } else {
335 bm->row_mod = 0;
336 for (i = 1; i < depth; i++) {
337 bm->plane[i] = bm->plane[i - 1] + plane_size;
338 }
339 }
340 bm->hardware_address = PREP_DMA_MEM(bm->plane[0]);
341 return (bm);
342 }
343 return (NULL);
344 }
345
346
347 void
348 free_bitmap(bmap_t *bm)
349 {
350 if (bm)
351 free_chipmem(bm);
352 }
353 /* load a new mode into the current display, if NULL shut display off. */
354 void
355 cc_load_mode(dmode_t *d)
356 {
357 if (d) {
358 m_this_data->current_mode = d;
359 #ifdef __powerpc__ /* XXX ???? */
360 custom.cop1lc = PREP_DMA_MEM(DMDATA(d)->frames[F_LONG]);
361 custom.copjmp1 = 0;
362 #endif
363 return;
364 }
365 /* turn off display */
366 m_this_data->current_mode = NULL;
367 wait_tof();
368 wait_tof();
369 custom.cop1lc = PREP_DMA_MEM(null_mode_copper_list);
370 }
371 /*
372 * CC Mode Stuff.
373 */
374
375 dmode_t *(*mode_init_funcs[]) (void) = {
376 #if defined (GRF_NTSC)
377 #if defined (GRF_A2024)
378 cc_init_ntsc_a2024,
379 cc_init_ntsc_hires_dlace,
380 #endif /* GRF_A2024 */
381 cc_init_ntsc_hires_lace,
382 cc_init_ntsc_hires,
383 #if defined (GRF_AGA)
384 cc_init_ntsc_aga,
385 #if defined (GRF_SUPER72)
386 cc_init_super72,
387 #endif /* GRF_SUPER72 */
388 #endif /* GRF_AGA */
389 #endif /* GRF_NTSC */
390 #if defined (GRF_PAL)
391 #if defined (GRF_A2024)
392 cc_init_pal_a2024,
393 cc_init_pal_hires_dlace,
394 #endif /* GRF_A2024 */
395 cc_init_pal_hires_lace,
396 cc_init_pal_hires,
397 #if defined (GRF_AGA)
398 cc_init_pal_aga,
399 #endif /* GRF_AGA */
400 #endif /* GRF_PAL */
401 NULL
402 };
403
404 int
405 cc_init_modes(void)
406 {
407 int i = 0;
408 int error = 0;
409 while (mode_init_funcs[i]) {
410 mode_init_funcs[i] ();
411 i++;
412 }
413 return (error);
414 }
415
416 monitor_t *
417 cc_get_monitor(dmode_t *d)
418 {
419 return (DMDATA(d)->monitor);
420 }
421
422 view_t *
423 cc_get_current_view(dmode_t *d)
424 {
425 return (DMDATA(d)->current_view);
426 }
427
428
429 view_t *
430 cc_alloc_view(dmode_t *mode, dimen_t *dim, u_char depth)
431 {
432 view_t *v = alloc_chipmem(sizeof(*v) + sizeof(vdata_t));
433 if (v) {
434 bmap_t *bm = cc_monitor->alloc_bitmap(dim->width, dim->height,
435 depth, BMF_CLEAR | (DMDATA(mode)->max_depth == 8 ? BMF_ALIGN64 : 0));
436 if (bm) {
437 box_t box;
438
439 v->data = &v[1]; /* at the end of view */
440 VDATA(v)->colormap = DMDATA(mode)->alloc_colormap(depth);
441 if (VDATA(v)->colormap) {
442 INIT_BOX(&box, 0, 0, dim->width, dim->height);
443 cc_init_view(v, bm, mode, &box);
444 return (v);
445 }
446 cc_monitor->free_bitmap(bm);
447 }
448 free_chipmem(v);
449 }
450 return (NULL);
451 }
452
453 colormap_t *
454 cc_alloc_colormap(int depth)
455 {
456 u_long size = 1U << depth, i;
457 colormap_t *cm = alloc_chipmem(sizeof(u_long) * size + sizeof(*cm));
458
459 if (cm) {
460 cm->type = CM_COLOR;
461 cm->red_mask = 0x0F;
462 cm->green_mask = 0x0F;
463 cm->blue_mask = 0x0F;
464 cm->first = 0;
465 cm->size = size;
466 cm->entry = (u_long *) & cm[1]; /* table directly after. */
467 for (i = 0; i < size; i++) {
468 cm->entry[i] = CM_WTOL(cc_default_colors[i&31]);
469 }
470 return (cm);
471 }
472 return (NULL);
473 }
474
475 #ifdef GRF_AGA
476 colormap_t *
477 cc_alloc_aga_colormap(int depth)
478 {
479 u_long size = 1U << depth, i;
480 colormap_t *cm = alloc_chipmem(sizeof(u_long) * size + sizeof(*cm));
481
482 if (cm) {
483 cm->type = CM_COLOR;
484 cm->red_mask = 0x0FF;
485 cm->green_mask = 0x0FF;
486 cm->blue_mask = 0x0FF;
487 cm->first = 0;
488 cm->size = size;
489 cm->entry = (u_long *) & cm[1]; /* table directly after. */
490 for (i = 0; i < size; i++) {
491 cm->entry[i] = CM_WTOL(cc_default_colors[i&31]) |
492 (CM_WTOL(cc_default_colors[i&31]) << 4);
493 }
494 return (cm);
495 }
496 return (NULL);
497 }
498 #endif
499
500 int
501 cc_colormap_checkvals(colormap_t *vcm, colormap_t *cm, int use)
502 {
503 if (use) {
504 /* check to see if its the view's colormap, if so just do
505 * update. */
506 if (vcm != cm) {
507 if (cm->first >= vcm->size ||
508 (cm->first + cm->size) > (cm->first + vcm->size) ||
509 cm->type != vcm->type) {
510 return (0);
511 }
512 switch (vcm->type) {
513 case CM_COLOR:
514 if (cm->red_mask != vcm->red_mask ||
515 cm->green_mask != vcm->green_mask ||
516 cm->blue_mask != vcm->blue_mask) {
517 return (0);
518 }
519 break;
520 case CM_GREYSCALE:
521 if (cm->grey_mask != vcm->grey_mask) {
522 return (0);
523 }
524 break;
525 }
526 }
527 } else {
528 if (cm->first >= vcm->size ||
529 (cm->first + cm->size) > (cm->first + vcm->size)) {
530 return (0);
531 }
532 }
533 return (1);
534 }
535
536 /* does sanity check on values */
537 int
538 cc_get_colormap(view_t *v, colormap_t *cm)
539 {
540 colormap_t *vcm = VDATA(v)->colormap;
541 int i;
542
543 if (!cc_colormap_checkvals(vcm, cm, 0)) {
544 return (EINVAL);
545 }
546 cm->type = vcm->type;
547
548 switch (vcm->type) {
549 case CM_COLOR:
550 cm->red_mask = vcm->red_mask;
551 cm->green_mask = vcm->green_mask;
552 cm->blue_mask = vcm->blue_mask;
553 break;
554 case CM_GREYSCALE:
555 cm->grey_mask = vcm->grey_mask;
556 break;
557 }
558
559 /* copy entries into colormap. */
560 for (i = cm->first; i < (cm->first + cm->size); i++) {
561 cm->entry[i] = vcm->entry[i];
562 }
563 return (0);
564 }
565
566 /* does sanity check on values */
567 int
568 cc_use_colormap(view_t *v, colormap_t *cm)
569 {
570 colormap_t *vcm = VDATA(v)->colormap;
571 int s, i;
572
573 if (!cc_colormap_checkvals(vcm, cm, 1)) {
574 return (EINVAL);
575 }
576 /* check to see if its the view's colormap, if so just do update. */
577 if (vcm != cm) {
578 /* copy entries into colormap. */
579 for (i = cm->first; i < (cm->first + cm->size); i++) {
580 vcm->entry[i] = cm->entry[i];
581 }
582 }
583 s = spltty();
584
585 /* is view currently being displayed? */
586 if (VDATA(v)->flags & VF_DISPLAY) {
587 /* yes, update the copper lists */
588 cop_t *tmp, *cp;
589 int nframes = 1, j;
590
591 if (DMDATA(VDATA(v)->mode)->flags & DMF_INTERLACE) {
592 nframes = 2;
593 }
594 for (i = 0; i < nframes; i++) {
595 cp = DMDATA(VDATA(v)->mode)->frames[i];
596
597 tmp = find_copper_inst(cp, CI_MOVE(R_COLOR07));
598 tmp -= 7;
599
600 for (j = 0; j < 32; j++) {
601 CMOVE(tmp, (R_COLOR00 + (j << 1)),
602 CM_LTOW(vcm->entry[j]));
603 }
604 }
605 }
606 splx(s);
607 return (0);
608 }
609
610 #ifdef GRF_AGA
611 /* does sanity check on values */
612 int
613 cc_use_aga_colormap(view_t *v, colormap_t *cm)
614 {
615 colormap_t *vcm = VDATA(v)->colormap;
616 int s, i;
617
618 if (!cc_colormap_checkvals(vcm, cm, 1)) {
619 return (EINVAL);
620 }
621 /* check to see if its the view's colormap, if so just do update. */
622 if (vcm != cm) {
623 /* copy entries into colormap. */
624 for (i = cm->first; i < (cm->first + cm->size); i++) {
625 vcm->entry[i] = cm->entry[i];
626 }
627 }
628 s = spltty();
629
630 /* is view currently being displayed? */
631 if (VDATA(v)->flags & VF_DISPLAY) {
632 /* yes, update the copper lists */
633 cop_t *tmp, *cp;
634 int nframes = 1, j;
635
636 if (DMDATA(VDATA(v)->mode)->flags & DMF_INTERLACE) {
637 nframes = 2;
638 }
639 for (i = 0; i < nframes; i++) {
640 cp = DMDATA(VDATA(v)->mode)->frames[i];
641
642 tmp = find_copper_inst(cp, CI_MOVE(R_COLOR00));
643 for (j = 0; j < vcm->size; j += 32) {
644 int k;
645
646 for (k = 0; k < 32; k++) {
647 int ce = vcm->entry[j + k] >> 4;
648 CMOVE(tmp, (R_COLOR00 + (k << 1)),
649 CM_LTOW(ce));
650 }
651 tmp++;
652 for (k = 0; k < 32; k++) {
653 int ce =vcm->entry[j + k];
654 CMOVE(tmp, (R_COLOR00 + (k << 1)),
655 CM_LTOW(ce));
656 }
657 tmp++;
658 }
659 }
660 }
661 splx(s);
662 return (0);
663 }
664 #endif
665
666 #if defined (GRF_A2024)
667 colormap_t *
668 cc_a2024_alloc_colormap(int depth)
669 {
670 u_long size = 1U << depth, i;
671 colormap_t *cm = alloc_chipmem(sizeof(u_long) * size + sizeof(*cm));
672
673 if (cm) {
674 cm->type = CM_GREYSCALE;
675 cm->grey_mask = 0x03;
676 cm->first = 0;
677 cm->size = size;
678 cm->entry = (u_long *) & cm[1]; /* table directly after. */
679 for (i = 0; i < size; i++) {
680 cm->entry[i] = CM_WTOL(cc_a2024_default_colors[i]);
681 }
682 return (cm);
683 }
684 return (NULL);
685 }
686
687 int
688 cc_a2024_get_colormap(view_t *v, colormap_t *cm)
689 {
690 /* there are no differences (yet) in the way the cm's are stored */
691 return (cc_get_colormap(v, cm));
692 }
693
694 int
695 cc_a2024_use_colormap(view_t *v, colormap_t *cm)
696 {
697 colormap_t *vcm = VDATA(v)->colormap;
698 int s, i;
699
700 if (!cc_colormap_checkvals(vcm, cm, 1)) {
701 return (EINVAL);
702 }
703 /* check to see if its the view's colormap, if so just do update. */
704 if (vcm != cm) {
705 /* copy entries into colormap. */
706 for (i = cm->first; i < (cm->first + cm->size); i++) {
707 vcm->entry[i] = cm->entry[i];
708 }
709 }
710 s = spltty();
711
712 /* is view currently being displayed? */
713 if (VDATA(v)->flags & VF_DISPLAY) {
714 /* yes, update the copper lists */
715 cop_t *tmp, *cp;
716 int nframes = 2, nregs = cm->size == 4 ? 16 : 8, j;
717
718 if (DMDATA(VDATA(v)->mode)->flags & DMF_HEDLEY_EXP) {
719 nframes = 4;
720 }
721 for (i = 0; i < nframes; i++) {
722 cp = DMDATA(VDATA(v)->mode)->frames[i];
723
724 tmp = find_copper_inst(cp, CI_MOVE(R_COLOR07));
725 tmp -= 7;
726
727 for (j = 0; j < nregs; j++) {
728 CMOVE(tmp, (R_COLOR00 + (j << 1)),
729 A2024_CM_TO_CR(vcm, j));
730 }
731 }
732 }
733 splx(s);
734 return (0);
735 }
736 #endif /* GRF_A2024 */
737
738
739 /*
740 * CC View stuff.
741 */
742
743 void
744 cc_init_view(view_t *v, bmap_t *bm, dmode_t *mode, box_t *dbox)
745 {
746 vdata_t *vd = VDATA(v);
747 v->bitmap = bm;
748 vd->mode = mode;
749 bcopy(dbox, &v->display, sizeof(box_t));
750
751 v->display_view = DMDATA(vd->mode)->display_view;
752 v->use_colormap = DMDATA(vd->mode)->use_colormap;
753 v->get_colormap = DMDATA(vd->mode)->get_colormap;
754 v->free_view = cc_free_view;
755 v->get_display_mode = cc_get_display_mode;
756 v->remove_view = cc_remove_view;
757 }
758
759 void
760 cc_free_view(view_t *v)
761 {
762 if (v) {
763 v->remove_view(v);
764 free_chipmem(VDATA(v)->colormap);
765 cc_monitor->free_bitmap(v->bitmap);
766 free_chipmem(v);
767 }
768 }
769
770 void
771 cc_remove_view(view_t *v)
772 {
773 dmode_t *mode = VDATA(v)->mode;
774
775 if (MDATA(cc_monitor)->current_mode == mode) {
776 if (DMDATA(mode)->current_view == v) {
777 cc_load_mode(NULL);
778 }
779 }
780 if (DMDATA(mode)->current_view == v) {
781 DMDATA(mode)->current_view = NULL;
782 }
783 VDATA(v)->flags &= ~VF_DISPLAY;
784 }
785
786 dmode_t *
787 cc_get_display_mode(view_t *v)
788 {
789 return (VDATA(v)->mode);
790 }
791
792 void
793 cc_mode_vbl_handler(dmode_t *d)
794 {
795 u_short vp = ((custom.vposr & 0x0007) << 8) | ((custom.vhposr) >> 8);
796
797 if (vp < 12) {
798 custom.cop1lc = PREP_DMA_MEM(DMDATA(d)->frames[F_LONG]);
799 custom.copjmp1 = 0;
800 }
801 }
802
803 void
804 cc_lace_mode_vbl_handler(dmode_t *d)
805 {
806 u_short vp = ((custom.vposr & 0x0007) << 8) | ((custom.vhposr) >> 8);
807
808 if (vp < 12) {
809 if (custom.vposr & 0x8000) {
810 custom.cop1lc = PREP_DMA_MEM(DMDATA(d)->frames[F_LACE_LONG]);
811 } else {
812 custom.cop1lc = PREP_DMA_MEM(DMDATA(d)->frames[F_LACE_SHORT]);
813 }
814 custom.copjmp1 = 0;
815 }
816 }
817
818 /*
819 * Modes. (ick)
820 */
821
822 /*
823 * NTSC Modes
824 */
825
826 #if defined (GRF_NTSC)
827
828 dmode_t *
829 cc_init_ntsc_hires(void)
830 {
831 /* this function should only be called once. */
832 if (!h_this) {
833 u_short len = std_copper_list_len;
834
835 h_this = &hires_mode;
836 h_this_data = &hires_mode_data;
837 bzero(h_this, sizeof(dmode_t));
838 bzero(h_this_data, sizeof(dmdata_t));
839
840 h_this->name = "ntsc: hires";
841 h_this->nominal_size.width = 640;
842 h_this->nominal_size.height = 200;
843 h_this_data->max_size.width = 724;
844 h_this_data->max_size.height = 242;
845 h_this_data->min_size.width = 320;
846 h_this_data->min_size.height = 100;
847 h_this_data->min_depth = 1;
848 h_this_data->max_depth = 4;
849 h_this->data = h_this_data;
850
851 h_this->get_monitor = cc_get_monitor;
852 h_this->alloc_view = cc_alloc_view;
853 h_this->get_current_view = cc_get_current_view;
854
855 h_this_data->use_colormap = cc_use_colormap;
856 h_this_data->get_colormap = cc_get_colormap;
857 h_this_data->alloc_colormap = cc_alloc_colormap;
858 h_this_data->display_view = display_hires_view;
859 h_this_data->monitor = cc_monitor;
860
861 h_this_data->frames = hires_frames;
862 h_this_data->frames[F_LONG] =
863 alloc_chipmem(std_copper_list_size * F_TOTAL);
864 if (!h_this_data->frames[F_LONG]) {
865 panic("couldn't get chipmem for copper list");
866 }
867 h_this_data->frames[F_STORE_LONG] =
868 &h_this_data->frames[F_LONG][len];
869
870 bcopy(std_copper_list, h_this_data->frames[F_STORE_LONG],
871 std_copper_list_size);
872 bcopy(std_copper_list, h_this_data->frames[F_LONG],
873 std_copper_list_size);
874
875 h_this_data->bplcon0 = 0x8200 | USE_CON3; /* hires, color
876 * composite enable */
877 h_this_data->std_start_x = STANDARD_VIEW_X;
878 h_this_data->std_start_y = STANDARD_VIEW_Y;
879 h_this_data->vbl_handler =
880 (vbl_handler_func *) cc_mode_vbl_handler;
881 #if defined (GRF_ECS) || defined (GRF_AGA)
882 h_this_data->beamcon0 = STANDARD_NTSC_BEAMCON;
883 #endif
884
885 LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, h_this, link);
886 }
887 return (h_this);
888 }
889
890 void
891 display_hires_view(view_t *v)
892 {
893 if (h_this_data->current_view != v) {
894 vdata_t *vd = VDATA(v);
895 cop_t *cp = h_this_data->frames[F_STORE_LONG], *tmp;
896 int depth = v->bitmap->depth, i;
897 int hstart, hstop, vstart, vstop, j;
898 int x, y, w = v->display.width, h = v->display.height;
899 u_short ddfstart, ddfwidth, con1;
900
901 /* round down to nearest even width */
902 /* w &= 0xfffe; */
903 /* calculate datafetch width. */
904
905 ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
906
907 /* This will center the any overscanned display */
908 /* and allow user to modify. */
909 x = v->display.x + h_this_data->std_start_x - ((w - 640) >> 2);
910 y = v->display.y + h_this_data->std_start_y - ((h - 200) >> 1);
911
912 if (y & 1)
913 y--;
914
915 if (!(x & 1))
916 x--;
917
918 hstart = x;
919 hstop = x + (w >> 1);
920 vstart = y;
921 vstop = y + h;
922 ddfstart = (hstart - 9) >> 1;
923
924 /* check for hardware limits, AGA may allow more..? */
925 /* anyone got a 4000 I can borrow :^) -ch */
926 if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
927 int d = 0;
928
929 /* XXX anyone know the equality properties of
930 * intermixed logial AND's */
931 /* XXX and arithmetic operators? */
932 while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
933 d++;
934 }
935
936 ddfstart -= d;
937 hstart -= d << 1;
938 hstop -= d << 1;
939 }
940 /* correct the datafetch to proper limits. */
941 /* delay the actual display of the data until we need it. */
942 ddfstart &= 0xfffc;
943 con1 = ((hstart - 9) - (ddfstart << 1)) |
944 (((hstart - 9) - (ddfstart << 1)) << 4);
945
946 if (h_this_data->current_view) {
947 VDATA(h_this_data->current_view)->flags &=
948 ~VF_DISPLAY; /* mark as no longer displayed. */
949 }
950 h_this_data->current_view = v;
951
952 cp = h_this_data->frames[F_STORE_LONG];
953 #if defined (GRF_ECS) || defined (GRF_AGA)
954 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON3));
955 tmp->cp.inst.operand = 0x0020;
956 #if defined GRF_AGA
957 tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
958 tmp->cp.inst.operand = 0;
959 #endif
960 tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
961 tmp->cp.inst.operand = h_this_data->beamcon0;
962 tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
963 tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
964 #endif /* ECS */
965 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
966 tmp->cp.inst.operand = h_this_data->bplcon0 | ((depth & 0x7) << 12);
967 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
968 tmp->cp.inst.operand = con1;
969 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
970 tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
971 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
972 tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
973 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
974 tmp->cp.inst.operand = ddfstart;
975 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
976 tmp->cp.inst.operand = ddfstart + ddfwidth;
977
978 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
979 for (i = 0, j = 0; i < depth; j += 2, i++) {
980 /* update the plane pointers */
981 tmp[j].cp.inst.operand =
982 HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
983 tmp[j + 1].cp.inst.operand =
984 LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
985 }
986
987 /* set mods correctly. */
988 tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
989 tmp[0].cp.inst.operand = v->bitmap->row_mod;
990 tmp[1].cp.inst.operand = v->bitmap->row_mod;
991
992 /* set next pointers correctly */
993 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
994 tmp[0].cp.inst.operand =
995 HIADDR(PREP_DMA_MEM(h_this_data->frames[F_STORE_LONG]));
996 tmp[1].cp.inst.operand =
997 LOADDR(PREP_DMA_MEM(h_this_data->frames[F_STORE_LONG]));
998
999 cp = h_this_data->frames[F_LONG];
1000 h_this_data->frames[F_LONG] = h_this_data->frames[F_STORE_LONG];
1001 h_this_data->frames[F_STORE_LONG] = cp;
1002
1003 vd->flags |= VF_DISPLAY;
1004
1005 cc_use_colormap(v, vd->colormap);
1006 }
1007 cc_load_mode(h_this);
1008 }
1009
1010 dmode_t *
1011 cc_init_ntsc_hires_lace(void)
1012 {
1013 /* this function should only be called once. */
1014 if (!hl_this) {
1015 u_short len = std_copper_list_len;
1016
1017 hl_this = &hires_lace_mode;
1018 hl_this_data = &hires_lace_mode_data;
1019 bzero(hl_this, sizeof(dmode_t));
1020 bzero(hl_this_data, sizeof(dmdata_t));
1021
1022 hl_this->name = "ntsc: hires interlace";
1023 hl_this->nominal_size.width = 640;
1024 hl_this->nominal_size.height = 400;
1025 hl_this_data->max_size.width = 724;
1026 hl_this_data->max_size.height = 482;
1027 hl_this_data->min_size.width = 320;
1028 hl_this_data->min_size.height = 200;
1029 hl_this_data->min_depth = 1;
1030 hl_this_data->max_depth = 4;
1031 hl_this->data = hl_this_data;
1032
1033 hl_this->get_monitor = cc_get_monitor;
1034 hl_this->alloc_view = cc_alloc_view;
1035 hl_this->get_current_view = cc_get_current_view;
1036
1037 hl_this_data->use_colormap = cc_use_colormap;
1038 hl_this_data->get_colormap = cc_get_colormap;
1039 hl_this_data->alloc_colormap = cc_alloc_colormap;
1040 hl_this_data->display_view = display_hires_lace_view;
1041 hl_this_data->monitor = cc_monitor;
1042
1043 hl_this_data->flags |= DMF_INTERLACE;
1044
1045 hl_this_data->frames = hires_lace_frames;
1046 hl_this_data->frames[F_LACE_LONG] =
1047 alloc_chipmem(std_copper_list_size * F_LACE_TOTAL);
1048 if (!hl_this_data->frames[F_LACE_LONG]) {
1049 panic("couldn't get chipmem for copper list");
1050 }
1051 hl_this_data->frames[F_LACE_SHORT] =
1052 &hl_this_data->frames[F_LACE_LONG][len];
1053 hl_this_data->frames[F_LACE_STORE_LONG] =
1054 &hl_this_data->frames[F_LACE_SHORT][len];
1055 hl_this_data->frames[F_LACE_STORE_SHORT] =
1056 &hl_this_data->frames[F_LACE_STORE_LONG][len];
1057
1058 bcopy(std_copper_list, hl_this_data->frames[F_LACE_STORE_LONG],
1059 std_copper_list_size);
1060 bcopy(std_copper_list, hl_this_data->frames[F_LACE_STORE_SHORT],
1061 std_copper_list_size);
1062 bcopy(std_copper_list, hl_this_data->frames[F_LACE_LONG],
1063 std_copper_list_size);
1064 bcopy(std_copper_list, hl_this_data->frames[F_LACE_SHORT],
1065 std_copper_list_size);
1066
1067 hl_this_data->bplcon0 = 0x8204 | USE_CON3; /* hires, color
1068 * composite enable,
1069 * lace. */
1070 hl_this_data->std_start_x = STANDARD_VIEW_X;
1071 hl_this_data->std_start_y = STANDARD_VIEW_Y;
1072 hl_this_data->vbl_handler =
1073 (vbl_handler_func *) cc_lace_mode_vbl_handler;
1074 #if defined (GRF_ECS) || defined (GRF_AGA)
1075 hl_this_data->beamcon0 = STANDARD_NTSC_BEAMCON;
1076 #endif
1077
1078 LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, hl_this, link);
1079 }
1080 return (hl_this);
1081 }
1082
1083 void
1084 display_hires_lace_view(view_t *v)
1085 {
1086 if (hl_this_data->current_view != v) {
1087 vdata_t *vd = VDATA(v);
1088 cop_t *cp = hl_this_data->frames[F_LACE_STORE_LONG], *tmp;
1089 int depth = v->bitmap->depth, i;
1090 int hstart, hstop, vstart, vstop, j;
1091 int x, y, w = v->display.width, h = v->display.height;
1092 u_short ddfstart, ddfwidth, con1;
1093
1094 /* round down to nearest even width */
1095 /* w &= 0xfffe; */
1096
1097
1098 /* calculate datafetch width. */
1099
1100 ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
1101
1102 /* This will center the any overscanned display */
1103 /* and allow user to modify. */
1104 x = v->display.x + hl_this_data->std_start_x - ((w - 640) >> 2);
1105 y = v->display.y + hl_this_data->std_start_y - ((h - 400) >> 2);
1106
1107 if (y & 1)
1108 y--;
1109
1110 if (!(x & 1))
1111 x--;
1112
1113 hstart = x;
1114 hstop = x + (w >> 1);
1115 vstart = y;
1116 vstop = y + (h >> 1);
1117 ddfstart = (hstart - 9) >> 1;
1118
1119 /* check for hardware limits, AGA may allow more..? */
1120 /* anyone got a 4000 I can borrow :^) -ch */
1121 if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
1122 int d = 0;
1123
1124 /* XXX anyone know the equality properties of
1125 * intermixed logial AND's */
1126 /* XXX and arithmetic operators? */
1127 while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
1128 d++;
1129 }
1130
1131 ddfstart -= d;
1132 hstart -= d << 1;
1133 hstop -= d << 1;
1134 }
1135 /* correct the datafetch to proper limits. */
1136 /* delay the actual display of the data until we need it. */
1137 ddfstart &= 0xfffc;
1138 con1 = ((hstart - 9) - (ddfstart << 1)) |
1139 (((hstart - 9) - (ddfstart << 1)) << 4);
1140
1141 if (hl_this_data->current_view) {
1142 VDATA(hl_this_data->current_view)->flags &=
1143 ~VF_DISPLAY; /* mark as no longer displayed. */
1144 }
1145 hl_this_data->current_view = v;
1146
1147 cp = hl_this_data->frames[F_LACE_STORE_LONG];
1148 #if defined (GRF_ECS) || defined (GRF_AGA)
1149 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON3));
1150 tmp->cp.inst.operand = 0x0020;
1151 #if defined GRF_AGA
1152 tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
1153 tmp->cp.inst.operand = 0;
1154 #endif
1155 tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
1156 tmp->cp.inst.operand = hl_this_data->beamcon0;
1157 tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
1158 tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
1159 #endif /* ECS */
1160 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
1161 tmp->cp.inst.operand = hl_this_data->bplcon0 | ((depth & 0x7) << 12);
1162 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
1163 tmp->cp.inst.operand = con1;
1164 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
1165 tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
1166 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
1167 tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
1168 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
1169 tmp->cp.inst.operand = ddfstart;
1170 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
1171 tmp->cp.inst.operand = ddfstart + ddfwidth;
1172
1173 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
1174 for (i = 0, j = 0; i < depth; j += 2, i++) {
1175 /* update the plane pointers */
1176 tmp[j].cp.inst.operand =
1177 HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
1178 tmp[j + 1].cp.inst.operand =
1179 LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
1180 }
1181
1182 /* set mods correctly. */
1183 tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
1184 tmp[0].cp.inst.operand = v->bitmap->bytes_per_row + v->bitmap->row_mod;
1185 tmp[1].cp.inst.operand = v->bitmap->bytes_per_row + v->bitmap->row_mod;
1186
1187 /* set next pointers correctly */
1188 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
1189 tmp[0].cp.inst.operand =
1190 HIADDR(PREP_DMA_MEM(hl_this_data->frames[F_LACE_STORE_SHORT]));
1191 tmp[1].cp.inst.operand =
1192 LOADDR(PREP_DMA_MEM(hl_this_data->frames[F_LACE_STORE_SHORT]));
1193
1194
1195 bcopy(hl_this_data->frames[F_LACE_STORE_LONG],
1196 hl_this_data->frames[F_LACE_STORE_SHORT], std_copper_list_size);
1197
1198 /* these are the only ones that are different from long frame. */
1199 cp = hl_this_data->frames[F_LACE_STORE_SHORT];
1200 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
1201 for (i = 0, j = 0; i < depth; j += 2, i++) {
1202 u_short mod = v->bitmap->bytes_per_row + v->bitmap->row_mod;
1203 /* update plane pointers. high and low. */
1204 tmp[j].cp.inst.operand =
1205 HIADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
1206 tmp[j + 1].cp.inst.operand =
1207 LOADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
1208 }
1209
1210 /* set next pointers correctly */
1211 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
1212 tmp[0].cp.inst.operand =
1213 HIADDR(PREP_DMA_MEM(hl_this_data->frames[F_LACE_STORE_LONG]));
1214 tmp[1].cp.inst.operand =
1215 LOADDR(PREP_DMA_MEM(hl_this_data->frames[F_LACE_STORE_LONG]));
1216
1217
1218 cp = hl_this_data->frames[F_LACE_LONG];
1219 hl_this_data->frames[F_LACE_LONG] =
1220 hl_this_data->frames[F_LACE_STORE_LONG];
1221 hl_this_data->frames[F_LACE_STORE_LONG] = cp;
1222
1223 cp = hl_this_data->frames[F_LACE_SHORT];
1224 hl_this_data->frames[F_LACE_SHORT] =
1225 hl_this_data->frames[F_LACE_STORE_SHORT];
1226 hl_this_data->frames[F_LACE_STORE_SHORT] = cp;
1227
1228 vd->flags |= VF_DISPLAY;
1229
1230 cc_use_colormap(v, vd->colormap);
1231 }
1232 cc_load_mode(hl_this);
1233 }
1234 #if defined (GRF_A2024)
1235
1236 dmode_t *
1237 cc_init_ntsc_hires_dlace(void)
1238 {
1239 /* this function should only be called once. */
1240 if (!hdl_this) {
1241 u_short len = std_dlace_copper_list_len;
1242
1243 hdl_this = &hires_dlace_mode;
1244 hdl_this_data = &hires_dlace_mode_data;
1245 bzero(hdl_this, sizeof(dmode_t));
1246 bzero(hdl_this_data, sizeof(dmdata_t));
1247
1248 hdl_this->name = "ntsc: hires double interlace";
1249 hdl_this->nominal_size.width = 640;
1250 hdl_this->nominal_size.height = 800;
1251 hdl_this_data->max_size.width = 724;
1252 hdl_this_data->max_size.height = 800;
1253 hdl_this_data->min_size.width = 320;
1254 hdl_this_data->min_size.height = 400;
1255 hdl_this_data->min_depth = 1;
1256 hdl_this_data->max_depth = 2;
1257 hdl_this->data = hdl_this_data;
1258
1259 hdl_this->get_monitor = cc_get_monitor;
1260 hdl_this->alloc_view = cc_alloc_view;
1261 hdl_this->get_current_view = cc_get_current_view;
1262
1263 hdl_this_data->use_colormap = cc_a2024_use_colormap;
1264 hdl_this_data->get_colormap = cc_a2024_get_colormap;
1265 hdl_this_data->alloc_colormap = cc_a2024_alloc_colormap;
1266 hdl_this_data->display_view = display_hires_dlace_view;
1267 hdl_this_data->monitor = cc_monitor;
1268
1269 hdl_this_data->flags |= DMF_INTERLACE;
1270
1271 hdl_this_data->frames = hires_dlace_frames;
1272 hdl_this_data->frames[F_LACE_LONG] =
1273 alloc_chipmem(std_dlace_copper_list_size * F_LACE_TOTAL);
1274 if (!hdl_this_data->frames[F_LACE_LONG]) {
1275 panic("couldn't get chipmem for copper list");
1276 }
1277 hdl_this_data->frames[F_LACE_SHORT] =
1278 &hdl_this_data->frames[F_LACE_LONG][len];
1279 hdl_this_data->frames[F_LACE_STORE_LONG] =
1280 &hdl_this_data->frames[F_LACE_SHORT][len];
1281 hdl_this_data->frames[F_LACE_STORE_SHORT] =
1282 &hdl_this_data->frames[F_LACE_STORE_LONG][len];
1283
1284 bcopy(std_dlace_copper_list,
1285 hdl_this_data->frames[F_LACE_STORE_LONG],
1286 std_dlace_copper_list_size);
1287 bcopy(std_dlace_copper_list,
1288 hdl_this_data->frames[F_LACE_STORE_SHORT],
1289 std_dlace_copper_list_size);
1290 bcopy(std_dlace_copper_list,
1291 hdl_this_data->frames[F_LACE_LONG],
1292 std_dlace_copper_list_size);
1293 bcopy(std_dlace_copper_list,
1294 hdl_this_data->frames[F_LACE_SHORT],
1295 std_dlace_copper_list_size);
1296
1297 hdl_this_data->bplcon0 = 0x8204 | USE_CON3; /* hires, color
1298 * composite enable,
1299 * dlace. */
1300 hdl_this_data->std_start_x = STANDARD_VIEW_X;
1301 hdl_this_data->std_start_y = STANDARD_VIEW_Y;
1302 hdl_this_data->vbl_handler =
1303 (vbl_handler_func *) cc_lace_mode_vbl_handler;
1304 #if defined (GRF_ECS) || defined (GRF_AGA)
1305 hdl_this_data->beamcon0 = STANDARD_NTSC_BEAMCON;
1306 #endif
1307 LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, hdl_this, link);
1308 }
1309 return (hdl_this);
1310 }
1311
1312 void
1313 display_hires_dlace_view(view_t *v)
1314 {
1315 if (hdl_this_data->current_view != v) {
1316 vdata_t *vd = VDATA(v);
1317 cop_t *cp = hdl_this_data->frames[F_LACE_STORE_LONG], *tmp;
1318 int depth = v->bitmap->depth;
1319 int hstart, hstop, vstart, vstop;
1320 int x, y, w = v->display.width, h = v->display.height;
1321 u_short ddfstart, ddfwidth, con1;
1322 u_short mod1l, mod2l;
1323
1324 /* round down to nearest even width */
1325 /* w &= 0xfffe; */
1326
1327 /* calculate datafetch width. */
1328
1329 ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
1330
1331 /* This will center the any overscanned display */
1332 /* and allow user to modify. */
1333 x = v->display.x + hdl_this_data->std_start_x - ((w - 640) >> 2);
1334 y = v->display.y + hdl_this_data->std_start_y - ((h - 800) >> 3);
1335
1336 if (y & 1)
1337 y--;
1338
1339 if (!(x & 1))
1340 x--;
1341
1342 hstart = x;
1343 hstop = x + (w >> 1);
1344 vstart = y;
1345 vstop = y + (h >> 2);
1346
1347 ddfstart = (hstart - 9) >> 1;
1348
1349 /* check for hardware limits, AGA may allow more..? */
1350 /* anyone got a 4000 I can borrow :^) -ch */
1351 if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
1352 int d = 0;
1353
1354 /* XXX anyone know the equality properties of
1355 * intermixed logial AND's */
1356 /* XXX and arithmetic operators? */
1357 while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
1358 d++;
1359 }
1360
1361 ddfstart -= d;
1362 hstart -= d << 1;
1363 hstop -= d << 1;
1364 }
1365 /* correct the datafetch to proper limits. */
1366 /* delay the actual display of the data until we need it. */
1367 ddfstart &= 0xfffc;
1368 con1 = ((hstart - 9) - (ddfstart << 1)) |
1369 (((hstart - 9) - (ddfstart << 1)) << 4);
1370
1371 if (hdl_this_data->current_view) {
1372 VDATA(hdl_this_data->current_view)->flags &=
1373 ~VF_DISPLAY; /* mark as no longer displayed. */
1374 }
1375 hdl_this_data->current_view = v;
1376
1377 cp = hdl_this_data->frames[F_LACE_STORE_LONG];
1378 #if defined (GRF_ECS) || defined (GRF_AGA)
1379 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON3));
1380 tmp->cp.inst.operand = 0x0020;
1381 #if defined GRF_AGA
1382 tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
1383 tmp->cp.inst.operand = 0;
1384 #endif
1385 tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
1386 tmp->cp.inst.operand = hdl_this_data->beamcon0;
1387 tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
1388 tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
1389 #endif /* ECS */
1390 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
1391 tmp->cp.inst.operand =
1392 hdl_this_data->bplcon0 | ((depth & 0x7) << 13); /* times two. */
1393 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
1394 tmp->cp.inst.operand = con1;
1395 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
1396 tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
1397 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
1398 tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
1399 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
1400 tmp->cp.inst.operand = ddfstart;
1401 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
1402 tmp->cp.inst.operand = ddfstart + ddfwidth;
1403
1404 mod1l = v->bitmap->bytes_per_row + v->bitmap->row_mod;
1405 mod2l = mod1l << 1;
1406
1407 /* update plane pointers. */
1408 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
1409 tmp[0].cp.inst.operand =
1410 HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][0]));
1411 tmp[1].cp.inst.operand =
1412 LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][0]));
1413 tmp[2].cp.inst.operand =
1414 HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod1l]));
1415 tmp[3].cp.inst.operand =
1416 LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod1l]));
1417 if (depth == 2) {
1418 tmp[4].cp.inst.operand =
1419 HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][0]));
1420 tmp[5].cp.inst.operand =
1421 LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][0]));
1422 tmp[6].cp.inst.operand =
1423 HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod1l]));
1424 tmp[7].cp.inst.operand =
1425 LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod1l]));
1426 }
1427 /* set modulos. */
1428 tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
1429 tmp[0].cp.inst.operand = mod2l + mod1l;
1430 tmp[1].cp.inst.operand = mod2l + mod1l;
1431
1432
1433 /* set next coper list pointers */
1434 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
1435 tmp[0].cp.inst.operand =
1436 HIADDR(PREP_DMA_MEM(hdl_this_data->frames[F_LACE_STORE_SHORT]));
1437 tmp[1].cp.inst.operand =
1438 LOADDR(PREP_DMA_MEM(hdl_this_data->frames[F_LACE_STORE_SHORT]));
1439
1440 bcopy(hdl_this_data->frames[F_LACE_STORE_LONG],
1441 hdl_this_data->frames[F_LACE_STORE_SHORT],
1442 std_dlace_copper_list_size);
1443
1444 /* these are the only ones that are different from long frame. */
1445 cp = hdl_this_data->frames[F_LACE_STORE_SHORT];
1446 /* update plane pointers. */
1447 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
1448 tmp[0].cp.inst.operand =
1449 HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l]));
1450 tmp[1].cp.inst.operand =
1451 LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l]));
1452 tmp[2].cp.inst.operand =
1453 HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l + mod1l]));
1454 tmp[3].cp.inst.operand =
1455 LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l + mod1l]));
1456 if (depth == 2) {
1457 tmp[4].cp.inst.operand =
1458 HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l]));
1459 tmp[5].cp.inst.operand =
1460 LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l]));
1461 tmp[6].cp.inst.operand =
1462 HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l + mod1l]));
1463 tmp[7].cp.inst.operand =
1464 LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l + mod1l]));
1465 }
1466 /* set next copper list pointers */
1467 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
1468 tmp[0].cp.inst.operand =
1469 HIADDR(PREP_DMA_MEM(hdl_this_data->frames[F_LACE_STORE_LONG]));
1470 tmp[1].cp.inst.operand =
1471 LOADDR(PREP_DMA_MEM(hdl_this_data->frames[F_LACE_STORE_LONG]));
1472
1473 cp = hdl_this_data->frames[F_LACE_LONG];
1474 hdl_this_data->frames[F_LACE_LONG] =
1475 hdl_this_data->frames[F_LACE_STORE_LONG];
1476 hdl_this_data->frames[F_LACE_STORE_LONG] = cp;
1477
1478 cp = hdl_this_data->frames[F_LACE_SHORT];
1479 hdl_this_data->frames[F_LACE_SHORT] =
1480 hdl_this_data->frames[F_LACE_STORE_SHORT];
1481 hdl_this_data->frames[F_LACE_STORE_SHORT] = cp;
1482
1483 vd->flags |= VF_DISPLAY;
1484 cc_a2024_use_colormap(v, vd->colormap);
1485 }
1486 cc_load_mode(hdl_this);
1487 }
1488
1489
1490 dmode_t *
1491 cc_init_ntsc_a2024(void)
1492 {
1493 /* this function should only be called once. */
1494 if (!a24_this) {
1495 int i;
1496 u_short len = std_a2024_copper_list_len;
1497 cop_t *cp;
1498
1499 a24_this = &a2024_mode;
1500 a24_this_data = &a2024_mode_data;
1501 bzero(a24_this, sizeof(dmode_t));
1502 bzero(a24_this_data, sizeof(dmdata_t));
1503
1504 a24_this->name = "ntsc: A2024 15khz";
1505 a24_this->nominal_size.width = 1024;
1506 a24_this->nominal_size.height = 800;
1507 a24_this_data->max_size.width = 1024;
1508 a24_this_data->max_size.height = 800;
1509 a24_this_data->min_size.width = 1024;
1510 a24_this_data->min_size.height = 800;
1511 a24_this_data->min_depth = 1;
1512 a24_this_data->max_depth = 2;
1513 a24_this->data = a24_this_data;
1514
1515 a24_this->get_monitor = cc_get_monitor;
1516 a24_this->alloc_view = cc_alloc_view;
1517 a24_this->get_current_view = cc_get_current_view;
1518
1519 a24_this_data->use_colormap = cc_a2024_use_colormap;
1520 a24_this_data->get_colormap = cc_a2024_get_colormap;
1521 a24_this_data->display_view = display_a2024_view;
1522 a24_this_data->alloc_colormap = cc_a2024_alloc_colormap;
1523 a24_this_data->monitor = cc_monitor;
1524
1525 a24_this_data->flags |= DMF_HEDLEY_EXP;
1526
1527 a24_this_data->frames = a2024_frames;
1528 a24_this_data->frames[F_QD_QUAD0] =
1529 alloc_chipmem(std_a2024_copper_list_size * F_QD_TOTAL);
1530 if (!a24_this_data->frames[F_QD_QUAD0]) {
1531 panic("couldn't get chipmem for copper list");
1532 }
1533 /* setup the hedley init bitplane. */
1534 hedley_init = alloc_chipmem(128);
1535 if (!hedley_init) {
1536 panic("couldn't get chipmem for hedley init bitplane");
1537 }
1538 for (i = 1; i < 128; i++)
1539 hedley_init[i] = 0xff;
1540 hedley_init[0] = 0x03;
1541
1542 /* copy image of standard copper list. */
1543 bcopy(std_a2024_copper_list, a24_this_data->frames[0],
1544 std_a2024_copper_list_size);
1545
1546 /* set the init plane pointer. */
1547 cp = find_copper_inst(a24_this_data->frames[F_QD_QUAD0],
1548 CI_MOVE(R_BPL0PTH));
1549 cp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(hedley_init));
1550 cp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(hedley_init));
1551
1552 for (i = 1; i < F_QD_TOTAL; i++) {
1553 a24_this_data->frames[i] = &a24_this_data->frames[i - 1][len];
1554 bcopy(a24_this_data->frames[0],
1555 a24_this_data->frames[i],
1556 std_a2024_copper_list_size);
1557 }
1558
1559 a24_this_data->bplcon0 = 0x8200; /* hires */
1560 a24_this_data->vbl_handler =
1561 (vbl_handler_func *) a2024_mode_vbl_handler;
1562
1563
1564 LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, a24_this, link);
1565 }
1566 return (a24_this);
1567 }
1568
1569 void
1570 display_a2024_view(view_t *v)
1571 {
1572 if (a24_this_data->current_view != v) {
1573 vdata_t *vd = VDATA(v);
1574 cop_t *cp, *tmp;
1575 u_char *inst_plane[2];
1576 u_char **plane = inst_plane;
1577 u_long full_line = v->bitmap->bytes_per_row + v->bitmap->row_mod;
1578 u_long half_plane = full_line * v->bitmap->rows / 2;
1579
1580 int depth = v->bitmap->depth, i, j;
1581
1582 plane[0] = v->bitmap->plane[0];
1583 if (depth == 2) {
1584 plane[1] = v->bitmap->plane[1];
1585 }
1586 if (a24_this_data->current_view) {
1587 VDATA(a24_this_data->current_view)->flags &=
1588 ~VF_DISPLAY; /* mark as no longer displayed. */
1589 }
1590 cp = a24_this_data->frames[F_QD_STORE_QUAD0];
1591 tmp = find_copper_inst(cp, CI_MOVE(R_COLOR1F));
1592 tmp = find_copper_inst(tmp, CI_MOVE(R_BPLCON0)); /* grab third one. */
1593 tmp->cp.inst.operand = a24_this_data->bplcon0 |
1594 ((depth & 0x7) << 13); /* times 2 */
1595
1596 bcopy(a24_this_data->frames[F_QD_STORE_QUAD0],
1597 a24_this_data->frames[F_QD_STORE_QUAD1],
1598 std_a2024_copper_list_size);
1599 bcopy(a24_this_data->frames[F_QD_STORE_QUAD0],
1600 a24_this_data->frames[F_QD_STORE_QUAD2],
1601 std_a2024_copper_list_size);
1602 bcopy(a24_this_data->frames[F_QD_STORE_QUAD0],
1603 a24_this_data->frames[F_QD_STORE_QUAD3],
1604 std_a2024_copper_list_size);
1605
1606 /*
1607 * Mark Id's
1608 */
1609 tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD1],
1610 CI_WAIT(126, 21));
1611 CBUMP(tmp);
1612 CMOVE(tmp, R_COLOR01, QUAD1_ID);
1613 tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD2],
1614 CI_WAIT(126, 21));
1615 CBUMP(tmp);
1616 CMOVE(tmp, R_COLOR01, QUAD2_ID);
1617 tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD3],
1618 CI_WAIT(126, 21));
1619 CBUMP(tmp);
1620 CMOVE(tmp, R_COLOR01, QUAD3_ID);
1621
1622 plane[0]--;
1623 plane[0]--;
1624 if (depth == 2) {
1625 plane[1]--;
1626 plane[1]--;
1627 }
1628 /*
1629 * Set bitplane pointers.
1630 */
1631 tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD0],
1632 CI_MOVE(R_BPLMOD2));
1633 CBUMP(tmp);
1634 CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][0])));
1635 CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][0])));
1636 CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][full_line])));
1637 CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][full_line])));
1638 if (depth == 2) {
1639 CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][0])));
1640 CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][0])));
1641 CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][full_line])));
1642 CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][full_line])));
1643 }
1644 #if defined (GRF_ECS) || defined (GRF_AGA)
1645 CMOVE(tmp, R_DIWHIGH, 0x2000);
1646 #endif
1647 CMOVE(tmp, R_COP1LCH,
1648 HIADDR(PREP_DMA_MEM(a24_this_data->frames[F_QD_STORE_QUAD1])));
1649 CMOVE(tmp, R_COP1LCL,
1650 LOADDR(PREP_DMA_MEM(a24_this_data->frames[F_QD_STORE_QUAD1])));
1651 CEND(tmp);
1652 CEND(tmp);
1653
1654 tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD1],
1655 CI_MOVE(R_BPLMOD2));
1656 CBUMP(tmp);
1657 CMOVE(tmp, R_BPL0PTH,
1658 HIADDR(PREP_DMA_MEM(&plane[0][HALF_2024_LINE])));
1659 CMOVE(tmp, R_BPL0PTL,
1660 LOADDR(PREP_DMA_MEM(&plane[0][HALF_2024_LINE])));
1661 CMOVE(tmp, R_BPL1PTH,
1662 HIADDR(PREP_DMA_MEM(&plane[0][full_line + HALF_2024_LINE])));
1663 CMOVE(tmp, R_BPL1PTL,
1664 LOADDR(PREP_DMA_MEM(&plane[0][full_line + HALF_2024_LINE])));
1665 if (depth == 2) {
1666 CMOVE(tmp, R_BPL2PTH,
1667 HIADDR(PREP_DMA_MEM(&plane[1][HALF_2024_LINE])));
1668 CMOVE(tmp, R_BPL2PTL,
1669 LOADDR(PREP_DMA_MEM(&plane[1][HALF_2024_LINE])));
1670 CMOVE(tmp, R_BPL3PTH,
1671 HIADDR(PREP_DMA_MEM(&plane[1][full_line + HALF_2024_LINE])));
1672 CMOVE(tmp, R_BPL3PTL,
1673 LOADDR(PREP_DMA_MEM(&plane[1][full_line + HALF_2024_LINE])));
1674 }
1675 #if defined (GRF_ECS) || defined (GRF_AGA)
1676 CMOVE(tmp, R_DIWHIGH, 0x2000);
1677 #endif
1678 CMOVE(tmp, R_COP1LCH,
1679 HIADDR(PREP_DMA_MEM(a24_this_data->frames[F_QD_STORE_QUAD2])));
1680 CMOVE(tmp, R_COP1LCL,
1681 LOADDR(PREP_DMA_MEM(a24_this_data->frames[F_QD_STORE_QUAD2])));
1682 CEND(tmp);
1683 CEND(tmp);
1684
1685 tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD2],
1686 CI_MOVE(R_BPLMOD2));
1687 CBUMP(tmp);
1688 CMOVE(tmp, R_BPL0PTH,
1689 HIADDR(PREP_DMA_MEM(&plane[0][half_plane])));
1690 CMOVE(tmp, R_BPL0PTL,
1691 LOADDR(PREP_DMA_MEM(&plane[0][half_plane])));
1692 CMOVE(tmp, R_BPL1PTH,
1693 HIADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line])));
1694 CMOVE(tmp, R_BPL1PTL,
1695 LOADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line])));
1696 if (depth == 2) {
1697 CMOVE(tmp, R_BPL2PTH,
1698 HIADDR(PREP_DMA_MEM(&plane[1][half_plane])));
1699 CMOVE(tmp, R_BPL2PTL,
1700 LOADDR(PREP_DMA_MEM(&plane[1][half_plane])));
1701 CMOVE(tmp, R_BPL3PTH,
1702 HIADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line])));
1703 CMOVE(tmp, R_BPL3PTL,
1704 LOADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line])));
1705 }
1706 #if defined (GRF_ECS) || defined (GRF_AGA)
1707 CMOVE(tmp, R_DIWHIGH, 0x2000);
1708 #endif
1709 CMOVE(tmp, R_COP1LCH,
1710 HIADDR(PREP_DMA_MEM(a24_this_data->frames[F_QD_STORE_QUAD3])));
1711 CMOVE(tmp, R_COP1LCL,
1712 LOADDR(PREP_DMA_MEM(a24_this_data->frames[F_QD_STORE_QUAD3])));
1713 CEND(tmp);
1714 CEND(tmp);
1715
1716 tmp = find_copper_inst(a24_this_data->frames[F_QD_STORE_QUAD3],
1717 CI_MOVE(R_BPLMOD2));
1718 CBUMP(tmp);
1719 CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(
1720 &plane[0][half_plane + HALF_2024_LINE])));
1721 CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(
1722 &plane[0][half_plane + HALF_2024_LINE])));
1723 CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(
1724 &plane[0][half_plane + full_line + HALF_2024_LINE])));
1725 CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(
1726 &plane[0][half_plane + full_line + HALF_2024_LINE])));
1727 if (depth == 2) {
1728 CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(
1729 &plane[1][half_plane + HALF_2024_LINE])));
1730 CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(
1731 &plane[1][half_plane + HALF_2024_LINE])));
1732 CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(
1733 &plane[1][half_plane + full_line + HALF_2024_LINE])));
1734 CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(
1735 &plane[1][half_plane + full_line + HALF_2024_LINE])));
1736 }
1737 #if defined (GRF_ECS) || defined (GRF_AGA)
1738 CMOVE(tmp, R_DIWHIGH, 0x2000);
1739 #endif
1740 CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(
1741 a24_this_data->frames[F_QD_STORE_QUAD0])));
1742 CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(
1743 a24_this_data->frames[F_QD_STORE_QUAD0])));
1744 CEND(tmp);
1745 CEND(tmp);
1746
1747 /* swap new pointers in. */
1748 for (i = F_QD_STORE_QUAD0, j = F_QD_QUAD0;
1749 i <= F_QD_STORE_QUAD3; i++, j++) {
1750 cp = a24_this_data->frames[j];
1751 a24_this_data->frames[j] = a24_this_data->frames[i];
1752 a24_this_data->frames[i] = cp;
1753 }
1754
1755 a24_this_data->current_view = v;
1756 vd->flags |= VF_DISPLAY;
1757
1758 cc_a2024_use_colormap(v, vd->colormap);
1759 }
1760 cc_load_mode(a24_this);
1761 }
1762
1763 void
1764 a2024_mode_vbl_handler(dmode_t *d)
1765 {
1766 u_short vp = ((custom.vposr & 0x0007) << 8) | ((custom.vhposr) >> 8);
1767
1768 if (vp < 12) {
1769 custom.cop1lc =
1770 PREP_DMA_MEM(a24_this_data->frames[a24_this_data->hedley_current]);
1771 custom.copjmp1 = 0;
1772 }
1773 a24_this_data->hedley_current++;
1774 a24_this_data->hedley_current &= 0x3; /* if 4 then 0. */
1775 }
1776 #endif /* GRF_A2024 */
1777
1778 #if defined (GRF_AGA)
1779
1780 dmode_t *
1781 cc_init_ntsc_aga(void)
1782 {
1783 /* this function should only be called once. */
1784 if (!aga_this && (custom.deniseid & 0xff) == 0xf8 &&
1785 aga_enable & AGA_ENABLE) {
1786 u_short len = aga_copper_list_len;
1787
1788 aga_this = &aga_mode;
1789 aga_this_data = &aga_mode_data;
1790 bzero(aga_this, sizeof(dmode_t));
1791 bzero(aga_this_data, sizeof(dmdata_t));
1792
1793 aga_this->name = "ntsc: AGA dbl";
1794 aga_this->nominal_size.width = 640;
1795 aga_this->nominal_size.height = 400;
1796 aga_this_data->max_size.width = 724;
1797 aga_this_data->max_size.height = 482;
1798 aga_this_data->min_size.width = 320;
1799 aga_this_data->min_size.height = 200;
1800 aga_this_data->min_depth = 1;
1801 aga_this_data->max_depth = 8;
1802 aga_this->data = aga_this_data;
1803
1804 aga_this->get_monitor = cc_get_monitor;
1805 aga_this->alloc_view = cc_alloc_view;
1806 aga_this->get_current_view = cc_get_current_view;
1807
1808 aga_this_data->use_colormap = cc_use_aga_colormap;
1809 aga_this_data->get_colormap = cc_get_colormap;
1810 aga_this_data->alloc_colormap = cc_alloc_aga_colormap;
1811 aga_this_data->display_view = display_aga_view;
1812 aga_this_data->monitor = cc_monitor;
1813
1814 aga_this_data->frames = aga_frames;
1815 aga_this_data->frames[F_LONG] = alloc_chipmem(aga_copper_list_size * F_TOTAL);
1816 if (!aga_this_data->frames[F_LONG]) {
1817 panic("couldn't get chipmem for copper list");
1818 }
1819 aga_this_data->frames[F_STORE_LONG] = &aga_this_data->frames[F_LONG][len];
1820
1821 bcopy(aga_copper_list, aga_this_data->frames[F_STORE_LONG], aga_copper_list_size);
1822 bcopy(aga_copper_list, aga_this_data->frames[F_LONG], aga_copper_list_size);
1823
1824 aga_this_data->bplcon0 = 0x0240 | USE_CON3; /* color composite
1825 * enable,
1826 * shres. */
1827 #ifdef GRF_AGA_VGA
1828 aga_this_data->std_start_x = 0x40 /*STANDARD_VIEW_X*/;
1829 #else
1830 aga_this_data->std_start_x = 0x4f /*STANDARD_VIEW_X*/;
1831 #endif
1832 aga_this_data->std_start_y = 0x2b /*STANDARD_VIEW_Y*/;
1833 aga_this_data->vbl_handler = (vbl_handler_func *) cc_mode_vbl_handler;
1834 aga_this_data->beamcon0 = SPECIAL_BEAMCON ^ VSYNCTRUE;
1835
1836 LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes,
1837 aga_this, link);
1838 }
1839 return (aga_this);
1840 }
1841
1842 /* static, so I can patch and play */
1843
1844 #ifdef GRF_AGA_VGA
1845 int AGA_htotal = 0x71;
1846 int AGA_hsstrt = 0xc;
1847 int AGA_hsstop = 0x16;
1848 int AGA_hbstrt = 0x5;
1849 int AGA_vtotal = 0x1c1;
1850 #else
1851 int AGA_htotal = 0x79;
1852 int AGA_hsstrt = 0xe;
1853 int AGA_hsstop = 0x1c;
1854 int AGA_hbstrt = 0x8;
1855 int AGA_vtotal = 0x1ec;
1856 #endif
1857 int AGA_hbstop = 0x1e;
1858 int AGA_vsstrt = 0x3;
1859 int AGA_vsstop = 0x6;
1860 int AGA_vbstrt = 0x0;
1861 int AGA_vbstop = 0x19;
1862 int AGA_hcenter = 0x4a;
1863
1864 void
1865 display_aga_view(view_t *v)
1866 {
1867 if (aga_this_data->current_view != v) {
1868 vdata_t *vd = VDATA(v);
1869 cop_t *cp = aga_this_data->frames[F_STORE_LONG], *tmp;
1870 int depth = v->bitmap->depth, i;
1871 int hstart, hstop, vstart, vstop, j;
1872 int x, y, w = v->display.width, h = v->display.height;
1873 u_short ddfstart, ddfwidth, con1;
1874
1875 #ifdef DEBUG
1876 if (aga_enable & AGA_TRACE)
1877 printf("display_aga_view(%dx%dx%d) %p\n", w, h,
1878 depth, v);
1879 #endif
1880 /* round down to nearest even width */
1881 /* w &= 0xfffe; */
1882 /* calculate datafetch width. */
1883
1884 ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 4) << 1;
1885
1886 /* this will center the any overscanned display */
1887 /* and allow user to modify. */
1888 x = v->display.x + aga_this_data->std_start_x - ((w - 640) >> 3);
1889 y = v->display.y + aga_this_data->std_start_y - ((h - 400) >> 1);
1890
1891 if (y & 1)
1892 y--;
1893
1894 if (!(x & 1))
1895 x--;
1896
1897 hstart = x;
1898 hstop = x + (w >> 2);
1899 vstart = y;
1900 vstop = y + (h >> 0);
1901 ddfstart = (hstart >> 1) - 8;
1902
1903 #ifdef DEBUG
1904 if (aga_enable & AGA_TRACE2) {
1905 printf (" ddfwidth %04x x %04x y %04x", ddfwidth,
1906 x, y);
1907 printf (" hstart %04x hstop %04x vstart %04x vstop %04x ddfstart %04x\n",
1908 hstart, hstop, vstart, vstop, ddfstart);
1909 }
1910 #endif
1911 /* check for hardware limits, AGA may allow more..? */
1912 /* anyone got a 4000 I can borrow :^) -ch */
1913 if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
1914 int d = 0;
1915
1916 /* XXX anyone know the equality properties of
1917 * intermixed logial AND's */
1918 /* XXX and arithmetic operators? */
1919 while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
1920 d++;
1921 }
1922
1923 ddfstart -= d;
1924 hstart -= d << 1;
1925 hstop -= d << 1;
1926 }
1927 /* correct the datafetch to proper limits. */
1928 /* delay the actual display of the data until we need it. */
1929 ddfstart &= 0xfffc;
1930 #ifdef DEBUG
1931 if (aga_enable & AGA_TRACE2) {
1932 printf (" ddfwidth %04x x %04x y %04x", ddfwidth,
1933 x, y);
1934 printf (" hstart %04x hstop %04x vstart %04x vstop %04x ddfstart %04x\n",
1935 hstart, hstop, vstart, vstop, ddfstart);
1936 }
1937 #endif
1938 con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
1939
1940 if (aga_this_data->current_view) {
1941 VDATA(aga_this_data->current_view)->flags &= ~VF_DISPLAY; /* mark as no longer */
1942 /* displayed. */
1943 }
1944 aga_this_data->current_view = v;
1945
1946 cp = aga_this_data->frames[F_STORE_LONG];
1947 tmp = cp;
1948 for (i = 0; i < 8; ++i) {
1949 if (tmp == NULL)
1950 break;
1951 tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
1952 if (tmp == NULL)
1953 break;
1954 tmp->cp.inst.operand = 0x0ca1 | (i << 13);
1955 tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
1956 if (tmp == NULL)
1957 break;
1958 tmp->cp.inst.operand = 0x0ea1 | (i << 13);
1959 }
1960 if (tmp)
1961 tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
1962 if (tmp)
1963 tmp->cp.inst.operand = 0x0ca1;
1964 tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
1965 tmp->cp.inst.operand = 0x8003;
1966 tmp = find_copper_inst(cp, CI_MOVE(R_HTOTAL));
1967 tmp->cp.inst.operand = AGA_htotal; /* 81/71/73/79? */
1968 tmp = find_copper_inst(cp, CI_MOVE(R_HBSTRT));
1969 tmp->cp.inst.operand = AGA_hbstrt; /* 0x0008 */
1970 tmp = find_copper_inst(cp, CI_MOVE(R_HSSTRT));
1971 tmp->cp.inst.operand = AGA_hsstrt; /* 0x000e */
1972 tmp = find_copper_inst(cp, CI_MOVE(R_HSSTOP));
1973 tmp->cp.inst.operand = AGA_hsstop; /* 0x001c */
1974 tmp = find_copper_inst(cp, CI_MOVE(R_HBSTOP));
1975 tmp->cp.inst.operand = AGA_hsstop; /* 0x001e */
1976 tmp = find_copper_inst(cp, CI_MOVE(R_HCENTER));
1977 tmp->cp.inst.operand = AGA_hcenter; /*AGA_htotal / 2 + AGA_hsstrt */
1978 tmp = find_copper_inst(cp, CI_MOVE(R_VBSTRT));
1979 tmp->cp.inst.operand = AGA_vbstrt; /* 0x0000 */
1980 tmp = find_copper_inst(cp, CI_MOVE(R_VSSTRT));
1981 tmp->cp.inst.operand = AGA_vsstrt; /* 0x016b / AGA_htotal */
1982 tmp = find_copper_inst(cp, CI_MOVE(R_VSSTOP));
1983 tmp->cp.inst.operand = AGA_vsstop; /* 0x02d6 / AGA_htotal */
1984 tmp = find_copper_inst(cp, CI_MOVE(R_VBSTOP));
1985 tmp->cp.inst.operand = AGA_vbstop; /* 0x0bd1 / AGA_htotal */
1986 tmp = find_copper_inst(cp, CI_MOVE(R_VTOTAL));
1987 tmp->cp.inst.operand = AGA_vtotal;
1988 tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
1989 tmp->cp.inst.operand = aga_this_data->beamcon0;
1990 #ifdef DEBUG
1991 if (aga_enable & AGA_TRACE2)
1992 printf(" beamcon0 %04x", tmp->cp.inst.operand);
1993 #endif
1994 tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
1995 tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
1996 #ifdef DEBUG
1997 if (aga_enable & AGA_TRACE2)
1998 printf(" diwhigh %04x>", tmp->cp.inst.operand);
1999 #endif
2000 #if 0
2001 tmp->cp.inst.operand = (vstop & 0x0700) | ((hstop & 0x0100) << 5);
2002 #endif
2003 #ifdef DEBUG
2004 if (aga_enable & AGA_TRACE2)
2005 printf("%04x", tmp->cp.inst.operand);
2006 #endif
2007 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
2008 tmp->cp.inst.operand = aga_this_data->bplcon0 |
2009 ((depth & 0x7) << 12) | ((depth & 0x8) << 1);
2010 #ifdef DEBUG
2011 if (aga_enable & AGA_TRACE2)
2012 printf(" bplcon0 %04x", tmp->cp.inst.operand);
2013 #endif
2014 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
2015 tmp->cp.inst.operand = con1;
2016 #ifdef DEBUG
2017 if (aga_enable & AGA_TRACE2)
2018 printf(" bplcon1 %04x>0000\n", con1);
2019 #endif
2020 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
2021 tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
2022 #ifdef DEBUG
2023 if (aga_enable & AGA_TRACE2)
2024 printf(" diwstart %04x", tmp->cp.inst.operand);
2025 #endif
2026 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
2027 tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
2028 #ifdef DEBUG
2029 if (aga_enable & AGA_TRACE2)
2030 printf(" diwstop %04x", tmp->cp.inst.operand);
2031 #endif
2032 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
2033 tmp->cp.inst.operand = ddfstart;
2034 #ifdef DEBUG
2035 if (aga_enable & AGA_TRACE2)
2036 printf(" ddfstart %04x", tmp->cp.inst.operand);
2037 #endif
2038 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
2039 tmp->cp.inst.operand = ddfstart + ddfwidth;
2040 #ifdef DEBUG
2041 if (aga_enable & AGA_TRACE2)
2042 printf(" ddfstop %04x", tmp->cp.inst.operand);
2043 #endif
2044
2045 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2046 for (i = 0, j = 0; i < depth; j += 2, i++) {
2047 /* update the plane pointers */
2048 tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2049 tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2050 #ifdef DEBUG
2051 if (aga_enable & AGA_TRACE2)
2052 printf (" bpl%dpth %p", i, v->bitmap->plane[i]);
2053 #endif
2054 }
2055
2056 /* set mods correctly. */
2057 tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
2058 tmp[0].cp.inst.operand = v->bitmap->row_mod;
2059 tmp[1].cp.inst.operand = v->bitmap->row_mod;
2060 #ifdef DEBUG
2061 if (aga_enable & AGA_TRACE2)
2062 printf(" bplxmod %04x\n", v->bitmap->row_mod);
2063 #endif
2064
2065 /* set next pointers correctly */
2066 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2067 tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(aga_this_data->frames[F_STORE_LONG]));
2068 tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(aga_this_data->frames[F_STORE_LONG]));
2069
2070 cp = aga_this_data->frames[F_LONG];
2071 aga_this_data->frames[F_LONG] = aga_this_data->frames[F_STORE_LONG];
2072 aga_this_data->frames[F_STORE_LONG] = cp;
2073
2074 vd->flags |= VF_DISPLAY;
2075
2076 cc_use_aga_colormap(v, vd->colormap);
2077 }
2078 cc_load_mode(aga_this);
2079 #ifdef DEBUG
2080 if (aga_enable & AGA_TRACE)
2081 aga_enable |= AGA_TRACE2; /* XXXX */
2082 #endif
2083 }
2084
2085 /*
2086 * SUPER72 Mode
2087 */
2088
2089 #if defined (GRF_SUPER72)
2090 dmode_t *
2091 cc_init_super72(void)
2092 {
2093 /* this function should only be called once. */
2094 if (!super72_this && (custom.deniseid & 0xff) == 0xf8) {
2095 u_short len = aga_copper_list_len;
2096
2097 super72_this = &super72_mode;
2098 super72_this_data = &super72_mode_data;
2099 bzero(super72_this, sizeof(dmode_t));
2100 bzero(super72_this_data, sizeof(dmdata_t));
2101
2102 super72_this->name = "super72: superhires interlace";
2103 super72_this->nominal_size.width = 800;
2104 super72_this->nominal_size.height = 600;
2105 super72_this_data->max_size.width = 848;
2106 super72_this_data->max_size.height = 614;
2107 super72_this_data->min_size.width = 320;
2108 super72_this_data->min_size.height = 484;
2109 super72_this_data->min_depth = 1;
2110 super72_this_data->max_depth = 8;
2111 super72_this->data = super72_this_data;
2112
2113 super72_this->get_monitor = cc_get_monitor;
2114 super72_this->alloc_view = cc_alloc_view;
2115 super72_this->get_current_view = cc_get_current_view;
2116
2117 super72_this_data->use_colormap = cc_use_aga_colormap;
2118 super72_this_data->get_colormap = cc_get_colormap;
2119 super72_this_data->alloc_colormap = cc_alloc_aga_colormap;
2120 super72_this_data->display_view = display_super72_view;
2121 super72_this_data->monitor = cc_monitor;
2122
2123 super72_this_data->flags |= DMF_INTERLACE;
2124
2125 super72_this_data->frames = super72_frames; /* MAY NEED TO CHANGE COPLIST */
2126 super72_this_data->frames[F_LACE_LONG] =
2127 alloc_chipmem(aga_copper_list_size * F_LACE_TOTAL);
2128 if (!super72_this_data->frames[F_LACE_LONG]) {
2129 panic("couldn't get chipmem for copper list");
2130 }
2131 super72_this_data->frames[F_LACE_SHORT] =
2132 &super72_this_data->frames[F_LACE_LONG][len];
2133 super72_this_data->frames[F_LACE_STORE_LONG] =
2134 &super72_this_data->frames[F_LACE_SHORT][len];
2135 super72_this_data->frames[F_LACE_STORE_SHORT] =
2136 &super72_this_data->frames[F_LACE_STORE_LONG][len];
2137
2138 bcopy(aga_copper_list,
2139 super72_this_data->frames[F_LACE_STORE_LONG],
2140 aga_copper_list_size);
2141 bcopy(aga_copper_list,
2142 super72_this_data->frames[F_LACE_STORE_SHORT],
2143 aga_copper_list_size);
2144 bcopy(aga_copper_list,
2145 super72_this_data->frames[F_LACE_LONG],
2146 aga_copper_list_size);
2147 bcopy(aga_copper_list,
2148 super72_this_data->frames[F_LACE_SHORT],
2149 aga_copper_list_size);
2150
2151 super72_this_data->bplcon0 = 0x0244 | USE_CON3; /* color
2152 * composite enable,
2153 * shres
2154 * lace. */
2155 #if 0 /* patchable variables for testing */
2156 super72_this_data->std_start_x = 0x6c;
2157 super72_this_data->std_start_y = 0x1b;
2158 #endif
2159 super72_this_data->vbl_handler =
2160 (vbl_handler_func *) cc_lace_mode_vbl_handler;
2161 super72_this_data->beamcon0 = (SPECIAL_BEAMCON ^ VSYNCTRUE) |
2162 DISPLAYPAL | 0x4000;
2163 super72_this_data->beamcon0 = 0x5bb0;
2164
2165 LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, super72_this, link);
2166 }
2167 return (super72_this);
2168 }
2169
2170 /* Super72 83Hz hack monitor values */
2171 /*int super72_htotal = 0x083;
2172 int super72_hsstrt = 0x00d;
2173 int super72_hsstop = 0x01b;
2174 int super72_hbstrt = 0x001;
2175 int super72_hbstop = 0x021;
2176 int super72_vtotal = 0x148;
2177 int super72_vsstrt = 0x2d5;
2178 int super72_vsstop = 0x3ca;
2179 int super72_vbstrt = 0x000;
2180 int super72_vbstop = 0xfdc;
2181 int super72_hcenter = 0x04e;
2182 */
2183
2184 /* Super72 standard monitor values */
2185 int super72_htotal = 154; /* 0x099*/
2186 int super72_hsstrt = 17; /* 0x01c*/
2187 int super72_hsstop = 27; /* 0x038*/
2188 int super72_hbstrt = 154; /* 0x008*/
2189 int super72_hbstop = 55; /* 0x01e*/
2190 int super72_vtotal = 328; /* 0x147*/
2191 int super72_vsstrt = 11; /* 0x030*/
2192 int super72_vsstop = 18; /* 0x033*/
2193 int super72_vbstrt = 327; /* 0x000*/
2194 int super72_vbstop = 27; /* 0x019*/
2195 int super72_hcenter = 94; /* 0x057*/
2196 int super72_startx = 100;
2197 int super72_starty = 27;
2198
2199 void
2200 display_super72_view(view_t *v)
2201 {
2202 if (super72_this_data->current_view != v) {
2203 vdata_t *vd = VDATA(v);
2204 cop_t *cp = super72_this_data->frames[F_LACE_STORE_LONG], *tmp;
2205 int depth = v->bitmap->depth, i;
2206 int hstart, hstop, vstart, vstop, j;
2207 int x, y, w = v->display.width, h = v->display.height;
2208 u_short ddfstart, ddfwidth, con1;
2209
2210 /* round down to nearest even width */
2211 /* w &= 0xfffe; */
2212
2213 /* calculate datafetch width. */
2214 ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 4) << 1;
2215
2216 /* This will center any overscanned display */
2217 /* and allow user to modify. */
2218 x = (v->display.x >> 1) + super72_startx - ((w - 800) >> 3);
2219 y = v->display.y + super72_starty - ((h - 600) >> 2);
2220
2221 hstart = x;
2222 hstop = x + (w >> 2);
2223 vstart = y;
2224 vstop = y + (h >> 1);
2225 ddfstart = (hstart >> 1) - 16;
2226
2227 ddfstart = (hstart << 2) - 4;
2228 con1 = ddfstart & 63;
2229 ddfstart = (ddfstart & -64) - 64;
2230 ddfwidth = ((w + 64 - 1) & -64) - 64;
2231 ddfwidth = ddfwidth >> 3;
2232 ddfstart = ddfstart >> 3;
2233 super72_hbstrt = ((x << 2) + w + 4) >> 3;
2234 super72_hbstop = (hstart + 1) >> 1;
2235 super72_vbstrt = vstop;
2236 super72_vbstop = vstart - 2;
2237
2238 if ((hstop >> 1) > super72_htotal) {
2239 int d;
2240
2241 d = (hstop >> 1) - super72_htotal;
2242 ddfstart -= d;
2243 hstart -= d << 1;
2244 hstop -= d << 1;
2245 }
2246 if (vstop >= super72_vtotal) {
2247 int d;
2248 d = (vstop - super72_vtotal + 1);
2249 vstart -= d;
2250 vstop -= d;
2251 }
2252 con1 = ((con1 >> 2) & 0x000f) | /* PF1H2-PF1H5 */
2253 ((con1 << 8) & 0x0300) | /* PF1H0-PF1H2 */
2254 ((con1 << 4) & 0x0c00); /* PF1H6-PF1H7 */
2255 con1 |= con1 << 4; /* PF2H2-PF2H7 */
2256
2257 if (super72_this_data->current_view) {
2258 VDATA(super72_this_data->current_view)->flags &=
2259 ~VF_DISPLAY; /* mark as no longer */
2260 /* displayed. */
2261 }
2262 super72_this_data->current_view = v;
2263
2264 cp = super72_this_data->frames[F_LACE_STORE_LONG];
2265 tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
2266 tmp->cp.inst.operand = 0x8003;
2267 tmp = find_copper_inst(cp, CI_MOVE(R_HTOTAL));
2268 tmp->cp.inst.operand = super72_htotal;
2269 tmp = find_copper_inst(cp, CI_MOVE(R_HBSTRT));
2270 tmp->cp.inst.operand = super72_hbstrt;
2271 tmp = find_copper_inst(cp, CI_MOVE(R_HSSTRT));
2272 tmp->cp.inst.operand = super72_hsstrt;
2273 tmp = find_copper_inst(cp, CI_MOVE(R_HSSTOP));
2274 tmp->cp.inst.operand = super72_hsstop;
2275 tmp = find_copper_inst(cp, CI_MOVE(R_HBSTOP));
2276 tmp->cp.inst.operand = super72_hbstop;
2277 tmp = find_copper_inst(cp, CI_MOVE(R_HCENTER));
2278 tmp->cp.inst.operand = super72_hcenter;
2279 tmp = find_copper_inst(cp, CI_MOVE(R_VBSTRT));
2280 tmp->cp.inst.operand = super72_vbstrt;
2281 tmp = find_copper_inst(cp, CI_MOVE(R_VSSTRT));
2282 tmp->cp.inst.operand = super72_vsstrt;
2283 tmp = find_copper_inst(cp, CI_MOVE(R_VSSTOP));
2284 tmp->cp.inst.operand = super72_vsstop;
2285 tmp = find_copper_inst(cp, CI_MOVE(R_VBSTOP));
2286 tmp->cp.inst.operand = super72_vbstop;
2287 tmp = find_copper_inst(cp, CI_MOVE(R_VTOTAL));
2288 tmp->cp.inst.operand = super72_vtotal;
2289
2290 tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
2291 tmp->cp.inst.operand = super72_this_data->beamcon0;
2292 tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
2293 tmp->cp.inst.operand =
2294 CALC_DIWHIGH(hstart, vstart, hstop, vstop);
2295 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
2296 tmp->cp.inst.operand = super72_this_data->bplcon0 |
2297 ((depth & 0x7) << 12) | ((depth & 0x8) << 1);
2298 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
2299 tmp->cp.inst.operand = con1;
2300 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
2301 tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
2302 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
2303 tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
2304 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
2305 tmp->cp.inst.operand = ddfstart;
2306 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
2307 tmp->cp.inst.operand = ddfstart + ddfwidth;
2308
2309 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2310 for (i = 0, j = 0; i < depth; j += 2, i++) {
2311 /* update the plane pointers */
2312 tmp[j].cp.inst.operand =
2313 HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2314 tmp[j + 1].cp.inst.operand =
2315 LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2316 }
2317
2318 /* set mods correctly. */
2319 tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
2320 tmp[0].cp.inst.operand = v->bitmap->bytes_per_row +
2321 v->bitmap->row_mod;
2322 tmp[1].cp.inst.operand = v->bitmap->bytes_per_row +
2323 v->bitmap->row_mod;
2324
2325 /* set next pointers correctly */
2326 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2327 tmp[0].cp.inst.operand =
2328 HIADDR(PREP_DMA_MEM(super72_this_data->frames[F_LACE_STORE_SHORT]));
2329 tmp[1].cp.inst.operand =
2330 LOADDR(PREP_DMA_MEM(super72_this_data->frames[F_LACE_STORE_SHORT]));
2331
2332 bcopy(super72_this_data->frames[F_LACE_STORE_LONG],
2333 super72_this_data->frames[F_LACE_STORE_SHORT],
2334 aga_copper_list_size);
2335
2336 /* these are the only ones that are different from long frame. */
2337 cp = super72_this_data->frames[F_LACE_STORE_SHORT];
2338 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2339 for (i = 0, j = 0; i < depth; j += 2, i++) {
2340 u_short mod = v->bitmap->bytes_per_row +
2341 v->bitmap->row_mod;
2342 /* update plane pointers. high and low. */
2343 tmp[j].cp.inst.operand =
2344 HIADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
2345 tmp[j + 1].cp.inst.operand =
2346 LOADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
2347 }
2348
2349 /* set next pointers correctly */
2350 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2351 tmp[0].cp.inst.operand =
2352 HIADDR(PREP_DMA_MEM(super72_this_data->frames[F_LACE_STORE_LONG]));
2353 tmp[1].cp.inst.operand =
2354 LOADDR(PREP_DMA_MEM(super72_this_data->frames[F_LACE_STORE_LONG]));
2355
2356 cp = super72_this_data->frames[F_LACE_LONG];
2357 super72_this_data->frames[F_LACE_LONG] =
2358 super72_this_data->frames[F_LACE_STORE_LONG];
2359 super72_this_data->frames[F_LACE_STORE_LONG] = cp;
2360
2361 cp = super72_this_data->frames[F_LACE_SHORT];
2362 super72_this_data->frames[F_LACE_SHORT] =
2363 super72_this_data->frames[F_LACE_STORE_SHORT];
2364 super72_this_data->frames[F_LACE_STORE_SHORT] = cp;
2365
2366 vd->flags |= VF_DISPLAY;
2367 cc_use_aga_colormap(v, vd->colormap);
2368 }
2369 cc_load_mode(super72_this);
2370 }
2371 #endif /* GRF_SUPER72 */
2372
2373 #endif /* GRF_AGA */
2374 #endif /* GRF_NTSC */
2375
2376 /*
2377 * PAL modes.
2378 */
2379
2380 #if defined (GRF_PAL)
2381
2382 dmode_t *
2383 cc_init_pal_hires(void)
2384 {
2385 /* this function should only be called once. */
2386 if (!ph_this) {
2387 u_short len = std_copper_list_len;
2388
2389 ph_this = &pal_hires_mode;
2390 ph_this_data = &pal_hires_mode_data;
2391 bzero(ph_this, sizeof(dmode_t));
2392 bzero(ph_this_data, sizeof(dmdata_t));
2393
2394 ph_this->name = "pal: hires";
2395 ph_this->nominal_size.width = 640;
2396 ph_this->nominal_size.height = 256;
2397 ph_this_data->max_size.width = 724;
2398 ph_this_data->max_size.height = 289;
2399 ph_this_data->min_size.width = 320;
2400 ph_this_data->min_size.height = 244;
2401 ph_this_data->min_depth = 1;
2402 ph_this_data->max_depth = 4;
2403 ph_this->data = ph_this_data;
2404
2405 ph_this->get_monitor = cc_get_monitor;
2406 ph_this->alloc_view = cc_alloc_view;
2407 ph_this->get_current_view = cc_get_current_view;
2408
2409 ph_this_data->use_colormap = cc_use_colormap;
2410 ph_this_data->get_colormap = cc_get_colormap;
2411 ph_this_data->alloc_colormap = cc_alloc_colormap;
2412 ph_this_data->display_view = display_pal_hires_view;
2413 ph_this_data->monitor = cc_monitor;
2414
2415 ph_this_data->frames = pal_hires_frames;
2416 ph_this_data->frames[F_LONG] = alloc_chipmem(std_copper_list_size * F_TOTAL);
2417 if (!ph_this_data->frames[F_LONG]) {
2418 panic("couldn't get chipmem for copper list");
2419 }
2420 ph_this_data->frames[F_STORE_LONG] = &ph_this_data->frames[F_LONG][len];
2421
2422 bcopy(std_copper_list, ph_this_data->frames[F_STORE_LONG], std_copper_list_size);
2423 bcopy(std_copper_list, ph_this_data->frames[F_LONG], std_copper_list_size);
2424
2425 ph_this_data->bplcon0 = 0x8200 | USE_CON3; /* pal_hires, color
2426 * composite enable,
2427 * lace. */
2428 ph_this_data->std_start_x = STANDARD_VIEW_X;
2429 ph_this_data->std_start_y = STANDARD_VIEW_Y;
2430 ph_this_data->vbl_handler = (vbl_handler_func *) cc_mode_vbl_handler;
2431 #if defined (GRF_ECS) || defined (GRF_AGA)
2432 ph_this_data->beamcon0 = STANDARD_PAL_BEAMCON;
2433 #endif
2434
2435 LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, ph_this, link);
2436 }
2437 return (ph_this);
2438 }
2439
2440 void
2441 display_pal_hires_view(view_t *v)
2442 {
2443 if (ph_this_data->current_view != v) {
2444 vdata_t *vd = VDATA(v);
2445 cop_t *cp = ph_this_data->frames[F_STORE_LONG], *tmp;
2446 int depth = v->bitmap->depth, i;
2447 int hstart, hstop, vstart, vstop, j;
2448 int x, y, w = v->display.width, h = v->display.height;
2449 u_short ddfstart, ddfwidth, con1;
2450
2451 /* round down to nearest even width */
2452 /* w &= 0xfffe; */
2453
2454 /* calculate datafetch width. */
2455 ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
2456
2457 /* This will center the any overscanned display */
2458 /* and allow user to modify. */
2459 x = v->display.x + ph_this_data->std_start_x - ((w - 640) >> 2);
2460 y = v->display.y + ph_this_data->std_start_y - ((h - 256) >> 1);
2461
2462 if (y & 1)
2463 y--;
2464
2465 if (!(x & 1))
2466 x--;
2467
2468 hstart = x;
2469 hstop = x + (w >> 1);
2470 vstart = y;
2471 vstop = y + h;
2472 ddfstart = (hstart - 9) >> 1;
2473 /* check for hardware limits, AGA may allow more..? */
2474 /* anyone got a 4000 I can borrow :^) -ch */
2475 if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
2476 int d = 0;
2477
2478 /* XXX anyone know the equality properties of
2479 * intermixed logial AND's */
2480 /* XXX and arithmetic operators? */
2481 while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
2482 d++;
2483 }
2484
2485 ddfstart -= d;
2486 hstart -= d << 1;
2487 hstop -= d << 1;
2488 }
2489 /* correct the datafetch to proper limits. */
2490 /* delay the actual display of the data until we need it. */
2491 ddfstart &= 0xfffc;
2492 con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
2493
2494 if (ph_this_data->current_view) {
2495 VDATA(ph_this_data->current_view)->flags &= ~VF_DISPLAY; /* mark as no longer */
2496 /* displayed. */
2497 }
2498 ph_this_data->current_view = v;
2499
2500 cp = ph_this_data->frames[F_STORE_LONG];
2501 #if defined (GRF_ECS) || defined (GRF_AGA)
2502 #if defined GRF_AGA
2503 tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
2504 tmp->cp.inst.operand = 0;
2505 #endif
2506 tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
2507 tmp->cp.inst.operand = ph_this_data->beamcon0;
2508 tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
2509 tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
2510 #endif /* ECS */
2511 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
2512 tmp->cp.inst.operand = ph_this_data->bplcon0 | ((depth & 0x7) << 12);
2513 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
2514 tmp->cp.inst.operand = con1;
2515 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
2516 tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
2517 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
2518 tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
2519 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
2520 tmp->cp.inst.operand = ddfstart;
2521 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
2522 tmp->cp.inst.operand = ddfstart + ddfwidth;
2523
2524 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2525 for (i = 0, j = 0; i < depth; j += 2, i++) {
2526 /* update the plane pointers */
2527 tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2528 tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2529 }
2530
2531 /* set mods correctly. */
2532 tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
2533 tmp[0].cp.inst.operand = v->bitmap->row_mod;
2534 tmp[1].cp.inst.operand = v->bitmap->row_mod;
2535
2536 /* set next pointers correctly */
2537 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2538 tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(ph_this_data->frames[F_STORE_LONG]));
2539 tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(ph_this_data->frames[F_STORE_LONG]));
2540
2541 cp = ph_this_data->frames[F_LONG];
2542 ph_this_data->frames[F_LONG] = ph_this_data->frames[F_STORE_LONG];
2543 ph_this_data->frames[F_STORE_LONG] = cp;
2544
2545 vd->flags |= VF_DISPLAY;
2546 cc_use_colormap(v, vd->colormap);
2547 }
2548 cc_load_mode(ph_this);
2549 }
2550
2551 dmode_t *
2552 cc_init_pal_hires_lace(void)
2553 {
2554 /* this function should only be called once. */
2555 if (!phl_this) {
2556 u_short len = std_copper_list_len;
2557
2558 phl_this = &pal_hires_lace_mode;
2559 phl_this_data = &pal_hires_lace_mode_data;
2560 bzero(phl_this, sizeof(dmode_t));
2561 bzero(phl_this_data, sizeof(dmdata_t));
2562
2563 phl_this->name = "pal: hires interlace";
2564 phl_this->nominal_size.width = 640;
2565 phl_this->nominal_size.height = 512;
2566 phl_this_data->max_size.width = 724;
2567 phl_this_data->max_size.height = 578;
2568 phl_this_data->min_size.width = 320;
2569 phl_this_data->min_size.height = 484;
2570 phl_this_data->min_depth = 1;
2571 phl_this_data->max_depth = 4;
2572 phl_this->data = phl_this_data;
2573
2574 phl_this->get_monitor = cc_get_monitor;
2575 phl_this->alloc_view = cc_alloc_view;
2576 phl_this->get_current_view = cc_get_current_view;
2577
2578 phl_this_data->use_colormap = cc_use_colormap;
2579 phl_this_data->get_colormap = cc_get_colormap;
2580 phl_this_data->alloc_colormap = cc_alloc_colormap;
2581 phl_this_data->display_view = display_pal_hires_lace_view;
2582 phl_this_data->monitor = cc_monitor;
2583
2584 phl_this_data->flags |= DMF_INTERLACE;
2585
2586 phl_this_data->frames = pal_hires_lace_frames;
2587 phl_this_data->frames[F_LACE_LONG] = alloc_chipmem(std_copper_list_size * F_LACE_TOTAL);
2588 if (!phl_this_data->frames[F_LACE_LONG]) {
2589 panic("couldn't get chipmem for copper list");
2590 }
2591 phl_this_data->frames[F_LACE_SHORT] = &phl_this_data->frames[F_LACE_LONG][len];
2592 phl_this_data->frames[F_LACE_STORE_LONG] = &phl_this_data->frames[F_LACE_SHORT][len];
2593 phl_this_data->frames[F_LACE_STORE_SHORT] = &phl_this_data->frames[F_LACE_STORE_LONG][len];
2594
2595 bcopy(std_copper_list, phl_this_data->frames[F_LACE_STORE_LONG], std_copper_list_size);
2596 bcopy(std_copper_list, phl_this_data->frames[F_LACE_STORE_SHORT], std_copper_list_size);
2597 bcopy(std_copper_list, phl_this_data->frames[F_LACE_LONG], std_copper_list_size);
2598 bcopy(std_copper_list, phl_this_data->frames[F_LACE_SHORT], std_copper_list_size);
2599
2600 phl_this_data->bplcon0 = 0x8204 | USE_CON3; /* hires, color
2601 * composite enable,
2602 * lace. */
2603 phl_this_data->std_start_x = STANDARD_VIEW_X;
2604 phl_this_data->std_start_y = STANDARD_VIEW_Y;
2605 phl_this_data->vbl_handler = (vbl_handler_func *) cc_lace_mode_vbl_handler;
2606 #if defined (GRF_ECS) || defined (GRF_AGA)
2607 phl_this_data->beamcon0 = STANDARD_PAL_BEAMCON;
2608 #endif
2609
2610 LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, phl_this, link);
2611 }
2612 return (phl_this);
2613 }
2614
2615 void
2616 display_pal_hires_lace_view(view_t *v)
2617 {
2618 if (phl_this_data->current_view != v) {
2619 vdata_t *vd = VDATA(v);
2620 cop_t *cp = phl_this_data->frames[F_LACE_STORE_LONG], *tmp;
2621 int depth = v->bitmap->depth, i;
2622 int hstart, hstop, vstart, vstop, j;
2623 int x, y, w = v->display.width, h = v->display.height;
2624 u_short ddfstart, ddfwidth, con1;
2625
2626 /* round down to nearest even width */
2627 /* w &= 0xfffe; */
2628
2629 /* calculate datafetch width. */
2630 ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
2631
2632 /* This will center the any overscanned display */
2633 /* and allow user to modify. */
2634 x = v->display.x + phl_this_data->std_start_x - ((w - 640) >> 2);
2635 y = v->display.y + phl_this_data->std_start_y - ((h - 512) >> 2);
2636
2637 if (y & 1)
2638 y--;
2639
2640 if (!(x & 1))
2641 x--;
2642
2643 hstart = x;
2644 hstop = x + (w >> 1);
2645 vstart = y;
2646 vstop = y + (h >> 1);
2647 ddfstart = (hstart - 9) >> 1;
2648
2649 /* check for hardware limits, AGA may allow more..? */
2650 /* anyone got a 4000 I can borrow :^) -ch */
2651 if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
2652 int d = 0;
2653
2654 /* XXX anyone know the equality properties of
2655 * intermixed logial AND's */
2656 /* XXX and arithmetic operators? */
2657 while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
2658 d++;
2659 }
2660
2661 ddfstart -= d;
2662 hstart -= d << 1;
2663 hstop -= d << 1;
2664 }
2665 /* correct the datafetch to proper limits. */
2666 /* delay the actual display of the data until we need it. */
2667 ddfstart &= 0xfffc;
2668 con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
2669
2670 if (phl_this_data->current_view) {
2671 VDATA(phl_this_data->current_view)->flags &= ~VF_DISPLAY; /* mark as no longer */
2672 /* displayed. */
2673 }
2674 phl_this_data->current_view = v;
2675
2676 cp = phl_this_data->frames[F_LACE_STORE_LONG];
2677 #if defined (GRF_ECS) || defined (GRF_AGA)
2678 #if defined GRF_AGA
2679 tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
2680 tmp->cp.inst.operand = 0;
2681 #endif
2682 tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
2683 tmp->cp.inst.operand = phl_this_data->beamcon0;
2684 tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
2685 tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
2686 #endif /* ECS */
2687 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
2688 tmp->cp.inst.operand = phl_this_data->bplcon0 | ((depth & 0x7) << 12);
2689 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
2690 tmp->cp.inst.operand = con1;
2691 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
2692 tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
2693 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
2694 tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
2695 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
2696 tmp->cp.inst.operand = ddfstart;
2697 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
2698 tmp->cp.inst.operand = ddfstart + ddfwidth;
2699
2700 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2701 for (i = 0, j = 0; i < depth; j += 2, i++) {
2702 /* update the plane pointers */
2703 tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2704 tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2705 }
2706
2707 /* set mods correctly. */
2708 tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
2709 tmp[0].cp.inst.operand = v->bitmap->bytes_per_row + v->bitmap->row_mod;
2710 tmp[1].cp.inst.operand = v->bitmap->bytes_per_row + v->bitmap->row_mod;
2711
2712 /* set next pointers correctly */
2713 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2714 tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(phl_this_data->frames[F_LACE_STORE_SHORT]));
2715 tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(phl_this_data->frames[F_LACE_STORE_SHORT]));
2716
2717
2718 bcopy(phl_this_data->frames[F_LACE_STORE_LONG], phl_this_data->frames[F_LACE_STORE_SHORT], std_copper_list_size);
2719
2720 /* these are the only ones that are different from long frame. */
2721 cp = phl_this_data->frames[F_LACE_STORE_SHORT];
2722 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2723 for (i = 0, j = 0; i < depth; j += 2, i++) {
2724 u_short mod = v->bitmap->bytes_per_row + v->bitmap->row_mod;
2725 /* update plane pointers. high and low. */
2726 tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
2727 tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
2728 }
2729
2730 /* set next pointers correctly */
2731 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2732 tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(phl_this_data->frames[F_LACE_STORE_LONG]));
2733 tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(phl_this_data->frames[F_LACE_STORE_LONG]));
2734
2735
2736 cp = phl_this_data->frames[F_LACE_LONG];
2737 phl_this_data->frames[F_LACE_LONG] = phl_this_data->frames[F_LACE_STORE_LONG];
2738 phl_this_data->frames[F_LACE_STORE_LONG] = cp;
2739
2740 cp = phl_this_data->frames[F_LACE_SHORT];
2741 phl_this_data->frames[F_LACE_SHORT] = phl_this_data->frames[F_LACE_STORE_SHORT];
2742 phl_this_data->frames[F_LACE_STORE_SHORT] = cp;
2743
2744 vd->flags |= VF_DISPLAY;
2745 cc_use_colormap(v, vd->colormap);
2746 }
2747 cc_load_mode(phl_this);
2748 }
2749 #if defined (GRF_A2024)
2750
2751 dmode_t *
2752 cc_init_pal_hires_dlace(void)
2753 {
2754 /* this function should only be called once. */
2755 if (!phdl_this) {
2756 u_short len = std_dlace_copper_list_len;
2757
2758 phdl_this = &pal_hires_dlace_mode;
2759 phdl_this_data = &pal_hires_dlace_mode_data;
2760 bzero(phdl_this, sizeof(dmode_t));
2761 bzero(phdl_this_data, sizeof(dmdata_t));
2762
2763 phdl_this->name = "pal: hires double interlace";
2764 phdl_this->nominal_size.width = 640;
2765 phdl_this->nominal_size.height = 1024;
2766 phdl_this_data->max_size.width = 724;
2767 phdl_this_data->max_size.height = 1024;
2768 phdl_this_data->min_size.width = 320;
2769 phdl_this_data->min_size.height = 512;
2770 phdl_this_data->min_depth = 1;
2771 phdl_this_data->max_depth = 2;
2772 phdl_this->data = phdl_this_data;
2773
2774 phdl_this->get_monitor = cc_get_monitor;
2775 phdl_this->alloc_view = cc_alloc_view;
2776 phdl_this->get_current_view = cc_get_current_view;
2777
2778 phdl_this_data->use_colormap = cc_a2024_use_colormap;
2779 phdl_this_data->get_colormap = cc_a2024_get_colormap;
2780 phdl_this_data->alloc_colormap = cc_a2024_alloc_colormap;
2781 phdl_this_data->display_view = display_pal_hires_dlace_view;
2782 phdl_this_data->monitor = cc_monitor;
2783
2784 phdl_this_data->flags |= DMF_INTERLACE;
2785
2786 phdl_this_data->frames = pal_hires_dlace_frames;
2787 phdl_this_data->frames[F_LACE_LONG] = alloc_chipmem(std_dlace_copper_list_size * F_LACE_TOTAL);
2788 if (!phdl_this_data->frames[F_LACE_LONG]) {
2789 panic("couldn't get chipmem for copper list");
2790 }
2791 phdl_this_data->frames[F_LACE_SHORT] = &phdl_this_data->frames[F_LACE_LONG][len];
2792 phdl_this_data->frames[F_LACE_STORE_LONG] = &phdl_this_data->frames[F_LACE_SHORT][len];
2793 phdl_this_data->frames[F_LACE_STORE_SHORT] = &phdl_this_data->frames[F_LACE_STORE_LONG][len];
2794
2795 bcopy(std_dlace_copper_list, phdl_this_data->frames[F_LACE_STORE_LONG], std_dlace_copper_list_size);
2796 bcopy(std_dlace_copper_list, phdl_this_data->frames[F_LACE_STORE_SHORT], std_dlace_copper_list_size);
2797 bcopy(std_dlace_copper_list, phdl_this_data->frames[F_LACE_LONG], std_dlace_copper_list_size);
2798 bcopy(std_dlace_copper_list, phdl_this_data->frames[F_LACE_SHORT], std_dlace_copper_list_size);
2799
2800 phdl_this_data->bplcon0 = 0x8204 | USE_CON3; /* hires, color
2801 * composite enable,
2802 * dlace. */
2803 phdl_this_data->std_start_x = STANDARD_VIEW_X;
2804 phdl_this_data->std_start_y = STANDARD_VIEW_Y;
2805 phdl_this_data->vbl_handler = (vbl_handler_func *) cc_lace_mode_vbl_handler;
2806 #if defined (GRF_ECS) || defined (GRF_AGA)
2807 phdl_this_data->beamcon0 = STANDARD_PAL_BEAMCON;
2808 #endif
2809
2810 LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, phdl_this, link);
2811 }
2812 return (phdl_this);
2813 }
2814
2815 void
2816 display_pal_hires_dlace_view(view_t *v)
2817 {
2818 if (phdl_this_data->current_view != v) {
2819 vdata_t *vd = VDATA(v);
2820 cop_t *cp = phdl_this_data->frames[F_LACE_STORE_LONG], *tmp;
2821 int depth = v->bitmap->depth;
2822 int hstart, hstop, vstart, vstop;
2823 int x, y, w = v->display.width, h = v->display.height;
2824 u_short ddfstart, ddfwidth, con1;
2825 u_short mod1l, mod2l;
2826
2827 /* round down to nearest even width */
2828 /* w &= 0xfffe; */
2829
2830 /* calculate datafetch width. */
2831 ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
2832
2833 /* This will center the any overscanned display */
2834 /* and allow user to modify. */
2835 x = v->display.x + phdl_this_data->std_start_x - ((w - 640) >> 2);
2836 y = v->display.y + phdl_this_data->std_start_y - ((h - 1024) >> 3);
2837
2838 if (y & 1)
2839 y--;
2840
2841 if (!(x & 1))
2842 x--;
2843
2844 hstart = x;
2845 hstop = x + (w >> 1);
2846 vstart = y;
2847 vstop = y + (h >> 2);
2848 ddfstart = (hstart - 9) >> 1;
2849
2850 /* check for hardware limits, AGA may allow more..? */
2851 /* anyone got a 4000 I can borrow :^) -ch */
2852 if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
2853 int d = 0;
2854
2855 /* XXX anyone know the equality properties of
2856 * intermixed logial AND's */
2857 /* XXX and arithmetic operators? */
2858 while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
2859 d++;
2860 }
2861
2862 ddfstart -= d;
2863 hstart -= d << 1;
2864 hstop -= d << 1;
2865 }
2866 /* correct the datafetch to proper limits. */
2867 /* delay the actual display of the data until we need it. */
2868 ddfstart &= 0xfffc;
2869 con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
2870
2871 if (phdl_this_data->current_view) {
2872 VDATA(phdl_this_data->current_view)->flags &= ~VF_DISPLAY; /* mark as no longer */
2873 /* displayed. */
2874 }
2875 phdl_this_data->current_view = v;
2876
2877 cp = phdl_this_data->frames[F_LACE_STORE_LONG];
2878 #if defined (GRF_ECS) || defined (GRF_AGA)
2879 #if defined GRF_AGA
2880 tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
2881 tmp->cp.inst.operand = 0;
2882 #endif
2883 tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
2884 tmp->cp.inst.operand = phdl_this_data->beamcon0;
2885 tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
2886 tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
2887 #endif /* ECS */
2888 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
2889 tmp->cp.inst.operand = phdl_this_data->bplcon0 | ((depth & 0x7) << 13); /* times two. */
2890 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
2891 tmp->cp.inst.operand = con1;
2892 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
2893 tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
2894 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
2895 tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
2896 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
2897 tmp->cp.inst.operand = ddfstart;
2898 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
2899 tmp->cp.inst.operand = ddfstart + ddfwidth;
2900
2901 mod1l = v->bitmap->bytes_per_row + v->bitmap->row_mod;
2902 mod2l = mod1l << 1;
2903
2904 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2905 tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][0])); /* update plane
2906 * pointers. */
2907 tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][0])); /* high and low. */
2908 tmp[2].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod1l])); /* update plane
2909 * pointers. */
2910 tmp[3].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod1l])); /* high and low. */
2911 if (depth == 2) {
2912 tmp[4].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][0])); /* update plane
2913 * pointers. */
2914 tmp[5].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][0])); /* high and low. */
2915 tmp[6].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod1l])); /* update plane
2916 * pointers. */
2917 tmp[7].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod1l])); /* high and low. */
2918 }
2919 /* set mods correctly. */
2920 tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
2921 tmp[0].cp.inst.operand = mod2l + mod1l;
2922 tmp[1].cp.inst.operand = mod2l + mod1l;
2923
2924 /* set next pointers correctly */
2925 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2926 tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(phdl_this_data->frames[F_LACE_STORE_SHORT]));
2927 tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(phdl_this_data->frames[F_LACE_STORE_SHORT]));
2928
2929 bcopy(phdl_this_data->frames[F_LACE_STORE_LONG], phdl_this_data->frames[F_LACE_STORE_SHORT], std_dlace_copper_list_size);
2930
2931 /* these are the only ones that are different from long frame. */
2932 cp = phdl_this_data->frames[F_LACE_STORE_SHORT];
2933 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2934 tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l])); /* update plane
2935 * pointers. */
2936 tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l])); /* high and low. */
2937 tmp[2].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l + mod1l])); /* update plane
2938 * pointers. */
2939 tmp[3].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l + mod1l])); /* high and low. */
2940 if (depth == 2) {
2941 tmp[4].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l])); /* update plane
2942 * pointers. */
2943 tmp[5].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l])); /* high and low. */
2944 tmp[6].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l + mod1l])); /* update plane
2945 * pointers. */
2946 tmp[7].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l + mod1l])); /* high and low. */
2947 }
2948 /* set next pointers correctly */
2949 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2950 tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(phdl_this_data->frames[F_LACE_STORE_LONG]));
2951 tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(phdl_this_data->frames[F_LACE_STORE_LONG]));
2952
2953 cp = phdl_this_data->frames[F_LACE_LONG];
2954 phdl_this_data->frames[F_LACE_LONG] = phdl_this_data->frames[F_LACE_STORE_LONG];
2955 phdl_this_data->frames[F_LACE_STORE_LONG] = cp;
2956
2957 cp = phdl_this_data->frames[F_LACE_SHORT];
2958 phdl_this_data->frames[F_LACE_SHORT] = phdl_this_data->frames[F_LACE_STORE_SHORT];
2959 phdl_this_data->frames[F_LACE_STORE_SHORT] = cp;
2960
2961 vd->flags |= VF_DISPLAY;
2962
2963 cc_a2024_use_colormap(v, vd->colormap);
2964 }
2965 cc_load_mode(phdl_this);
2966 }
2967
2968 dmode_t *
2969 cc_init_pal_a2024(void)
2970 {
2971 /* this function should only be called once. */
2972 if (!p24_this) {
2973 int i;
2974 u_short len = std_pal_a2024_copper_list_len;
2975 cop_t *cp;
2976
2977 p24_this = &pal_a2024_mode;
2978 p24_this_data = &pal_a2024_mode_data;
2979 bzero(p24_this, sizeof(dmode_t));
2980 bzero(p24_this_data, sizeof(dmdata_t));
2981
2982 p24_this->name = "pal: A2024 15khz";
2983 p24_this->nominal_size.width = 1024;
2984 p24_this->nominal_size.height = 1024;
2985 p24_this_data->max_size.width = 1024;
2986 p24_this_data->max_size.height = 1024;
2987 p24_this_data->min_size.width = 1024;
2988 p24_this_data->min_size.height = 1024;
2989 p24_this_data->min_depth = 1;
2990 p24_this_data->max_depth = 2;
2991 p24_this->data = p24_this_data;
2992
2993 p24_this->get_monitor = cc_get_monitor;
2994 p24_this->alloc_view = cc_alloc_view;
2995 p24_this->get_current_view = cc_get_current_view;
2996
2997 p24_this_data->use_colormap = cc_a2024_use_colormap;
2998 p24_this_data->get_colormap = cc_a2024_get_colormap;
2999 p24_this_data->display_view = display_pal_a2024_view;
3000 p24_this_data->alloc_colormap = cc_a2024_alloc_colormap;
3001 p24_this_data->monitor = cc_monitor;
3002
3003 p24_this_data->flags |= DMF_HEDLEY_EXP;
3004
3005 p24_this_data->frames = pal_a2024_frames;
3006 p24_this_data->frames[F_QD_QUAD0] = alloc_chipmem(std_pal_a2024_copper_list_size * F_QD_TOTAL);
3007 if (!p24_this_data->frames[F_QD_QUAD0]) {
3008 panic("couldn't get chipmem for copper list");
3009 }
3010 /* setup the hedley init bitplane. */
3011 hedley_init = alloc_chipmem(128);
3012 if (!hedley_init) {
3013 panic("couldn't get chipmem for hedley init bitplane");
3014 }
3015 for (i = 1; i < 128; i++)
3016 hedley_init[i] = 0xff;
3017 hedley_init[0] = 0x03;
3018
3019 /* copy image of standard copper list. */
3020 bcopy(std_pal_a2024_copper_list, p24_this_data->frames[0], std_pal_a2024_copper_list_size);
3021
3022 /* set the init plane pointer. */
3023 cp = find_copper_inst(p24_this_data->frames[F_QD_QUAD0], CI_MOVE(R_BPL0PTH));
3024 cp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(hedley_init));
3025 cp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(hedley_init));
3026
3027 for (i = 1; i < F_QD_TOTAL; i++) {
3028 p24_this_data->frames[i] = &p24_this_data->frames[i - 1][len];
3029 bcopy(p24_this_data->frames[0], p24_this_data->frames[i], std_pal_a2024_copper_list_size);
3030 }
3031
3032 p24_this_data->bplcon0 = 0x8200; /* hires */
3033 p24_this_data->vbl_handler = (vbl_handler_func *) pal_a2024_mode_vbl_handler;
3034
3035
3036 LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, p24_this, link);
3037 }
3038 return (p24_this);
3039 }
3040
3041 void
3042 display_pal_a2024_view(view_t *v)
3043 {
3044 if (p24_this_data->current_view != v) {
3045 vdata_t *vd = VDATA(v);
3046 cop_t *cp, *tmp;
3047 u_char *inst_plane[2];
3048 u_char **plane = inst_plane;
3049 u_long full_line = v->bitmap->bytes_per_row + v->bitmap->row_mod;
3050 u_long half_plane = full_line * v->bitmap->rows / 2;
3051
3052 int depth = v->bitmap->depth, i, j;
3053
3054 plane[0] = v->bitmap->plane[0];
3055 if (depth == 2) {
3056 plane[1] = v->bitmap->plane[1];
3057 }
3058 if (p24_this_data->current_view) {
3059 VDATA(p24_this_data->current_view)->flags &= ~VF_DISPLAY; /* mark as no longer
3060 * displayed. */
3061 }
3062 cp = p24_this_data->frames[F_QD_STORE_QUAD0];
3063 tmp = find_copper_inst(cp, CI_MOVE(R_COLOR1F));
3064 tmp = find_copper_inst(tmp, CI_MOVE(R_BPLCON0)); /* grab third one. */
3065 tmp->cp.inst.operand = p24_this_data->bplcon0 | ((depth & 0x7) << 13); /* times 2 */
3066
3067 bcopy(p24_this_data->frames[F_QD_STORE_QUAD0], p24_this_data->frames[F_QD_STORE_QUAD1], std_pal_a2024_copper_list_size);
3068 bcopy(p24_this_data->frames[F_QD_STORE_QUAD0], p24_this_data->frames[F_QD_STORE_QUAD2], std_pal_a2024_copper_list_size);
3069 bcopy(p24_this_data->frames[F_QD_STORE_QUAD0], p24_this_data->frames[F_QD_STORE_QUAD3], std_pal_a2024_copper_list_size);
3070
3071 /*
3072 * Mark Id's
3073 */
3074 tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD1], CI_WAIT(126, 29));
3075 CBUMP(tmp);
3076 CMOVE(tmp, R_COLOR01, QUAD1_ID);
3077 tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD2], CI_WAIT(126, 29));
3078 CBUMP(tmp);
3079 CMOVE(tmp, R_COLOR01, QUAD2_ID);
3080 tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD3], CI_WAIT(126, 29));
3081 CBUMP(tmp);
3082 CMOVE(tmp, R_COLOR01, QUAD3_ID);
3083
3084 plane[0]--;
3085 plane[0]--;
3086 if (depth == 2) {
3087 plane[1]--;
3088 plane[1]--;
3089 }
3090 /*
3091 * Set bitplane pointers.
3092 */
3093 tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD0], CI_MOVE(R_BPLMOD2));
3094 CBUMP(tmp);
3095 CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][0])));
3096 CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][0])));
3097 CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][full_line])));
3098 CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][full_line])));
3099 if (depth == 2) {
3100 CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][0])));
3101 CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][0])));
3102 CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][full_line])));
3103 CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][full_line])));
3104 }
3105 #if defined (GRF_ECS) || defined (GRF_AGA)
3106 CMOVE(tmp, R_DIWHIGH, 0x2100);
3107 #endif
3108 CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD1])));
3109 CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD1])));
3110 CEND(tmp);
3111 CEND(tmp);
3112
3113 tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD1], CI_MOVE(R_BPLMOD2));
3114 CBUMP(tmp);
3115 CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][HALF_2024_LINE])));
3116 CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][HALF_2024_LINE])));
3117 CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][full_line + HALF_2024_LINE])));
3118 CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][full_line + HALF_2024_LINE])));
3119 if (depth == 2) {
3120 CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][HALF_2024_LINE])));
3121 CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][HALF_2024_LINE])));
3122 CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][full_line + HALF_2024_LINE])));
3123 CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][full_line + HALF_2024_LINE])));
3124 }
3125 #if defined (GRF_ECS) || defined (GRF_AGA)
3126 CMOVE(tmp, R_DIWHIGH, 0x2100);
3127 #endif
3128 CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD2])));
3129 CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD2])));
3130 CEND(tmp);
3131 CEND(tmp);
3132
3133 tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD2], CI_MOVE(R_BPLMOD2));
3134 CBUMP(tmp);
3135 CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][half_plane])));
3136 CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][half_plane])));
3137 CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line])));
3138 CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line])));
3139 if (depth == 2) {
3140 CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][half_plane])));
3141 CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][half_plane])));
3142 CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line])));
3143 CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line])));
3144 }
3145 #if defined (GRF_ECS) || defined (GRF_AGA)
3146 CMOVE(tmp, R_DIWHIGH, 0x2100);
3147 #endif
3148 CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD3])));
3149 CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD3])));
3150 CEND(tmp);
3151 CEND(tmp);
3152
3153 tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD3], CI_MOVE(R_BPLMOD2));
3154 CBUMP(tmp);
3155 CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][half_plane + HALF_2024_LINE])));
3156 CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][half_plane + HALF_2024_LINE])));
3157 CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line + HALF_2024_LINE])));
3158 CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line + HALF_2024_LINE])));
3159 if (depth == 2) {
3160 CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][half_plane + HALF_2024_LINE])));
3161 CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][half_plane + HALF_2024_LINE])));
3162 CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line + HALF_2024_LINE])));
3163 CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line + HALF_2024_LINE])));
3164 }
3165 #if defined (GRF_ECS) || defined (GRF_AGA)
3166 CMOVE(tmp, R_DIWHIGH, 0x2100);
3167 #endif
3168 CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD0])));
3169 CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD0])));
3170 CEND(tmp);
3171 CEND(tmp);
3172
3173 /* swap new pointers in. */
3174 for (i = F_QD_STORE_QUAD0, j = F_QD_QUAD0;
3175 i <= F_QD_STORE_QUAD3; i++, j++) {
3176 cp = p24_this_data->frames[j];
3177 p24_this_data->frames[j] = p24_this_data->frames[i];
3178 p24_this_data->frames[i] = cp;
3179 }
3180
3181 p24_this_data->current_view = v;
3182 vd->flags |= VF_DISPLAY;
3183
3184 cc_a2024_use_colormap(v, vd->colormap);
3185 }
3186 cc_load_mode(p24_this);
3187 }
3188
3189 void
3190 pal_a2024_mode_vbl_handler(dmode_t *d)
3191 {
3192 u_short vp = ((custom.vposr & 0x0007) << 8) | ((custom.vhposr) >> 8);
3193
3194 if (vp < 20) {
3195 custom.cop1lc = PREP_DMA_MEM(p24_this_data->frames[p24_this_data->hedley_current]);
3196 custom.copjmp1 = 0;
3197 }
3198 p24_this_data->hedley_current++;
3199 p24_this_data->hedley_current &= 0x3; /* if 4 then 0. */
3200 }
3201 #endif /* GRF_A2024 */
3202
3203 #if defined (GRF_AGA)
3204
3205 dmode_t *
3206 cc_init_pal_aga(void)
3207 {
3208 /* this function should only be called once. */
3209 if (!paga_this && (custom.deniseid & 0xff) == 0xf8 &&
3210 aga_enable & AGA_ENABLE) {
3211 u_short len = aga_copper_list_len;
3212
3213 paga_this = &paga_mode;
3214 paga_this_data = &paga_mode_data;
3215 bzero(paga_this, sizeof(dmode_t));
3216 bzero(paga_this_data, sizeof(dmdata_t));
3217
3218 paga_this->name = "pal: AGA dbl";
3219 paga_this->nominal_size.width = 640;
3220 paga_this->nominal_size.height = 512;
3221 paga_this_data->max_size.width = 720;
3222 paga_this_data->max_size.height = 564;
3223 paga_this_data->min_size.width = 320;
3224 paga_this_data->min_size.height = 200;
3225 paga_this_data->min_depth = 1;
3226 paga_this_data->max_depth = 8;
3227 paga_this->data = paga_this_data;
3228
3229 paga_this->get_monitor = cc_get_monitor;
3230 paga_this->alloc_view = cc_alloc_view;
3231 paga_this->get_current_view = cc_get_current_view;
3232
3233 paga_this_data->use_colormap = cc_use_aga_colormap;
3234 paga_this_data->get_colormap = cc_get_colormap;
3235 paga_this_data->alloc_colormap = cc_alloc_aga_colormap;
3236 paga_this_data->display_view = display_pal_aga_view;
3237 paga_this_data->monitor = cc_monitor;
3238
3239 paga_this_data->frames = paga_frames;
3240 paga_this_data->frames[F_LONG] = alloc_chipmem(aga_copper_list_size * F_TOTAL);
3241 if (!paga_this_data->frames[F_LONG]) {
3242 panic("couldn't get chipmem for copper list");
3243 }
3244 paga_this_data->frames[F_STORE_LONG] = &paga_this_data->frames[F_LONG][len];
3245
3246 bcopy(aga_copper_list, paga_this_data->frames[F_STORE_LONG], aga_copper_list_size);
3247 bcopy(aga_copper_list, paga_this_data->frames[F_LONG], aga_copper_list_size);
3248
3249 paga_this_data->bplcon0 = 0x0240 | USE_CON3; /* color composite
3250 * enable,
3251 * shres. */
3252 paga_this_data->std_start_x = 0x4f /*STANDARD_VIEW_X*/;
3253 paga_this_data->std_start_y = 0x2b /*STANDARD_VIEW_Y*/;
3254 paga_this_data->vbl_handler = (vbl_handler_func *) cc_mode_vbl_handler;
3255 paga_this_data->beamcon0 = STANDARD_PAL_BEAMCON | (SPECIAL_BEAMCON ^ VSYNCTRUE);
3256
3257 LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes,
3258 paga_this, link);
3259 }
3260 return (paga_this);
3261 }
3262
3263 /* static, so I can patch and play */
3264
3265 #ifdef GRF_AGA_VGA
3266 int pAGA_htotal = 0x079;
3267 int pAGA_vtotal = 0x24d;
3268 int pAGA_vbstop = 0x019;
3269 int pAGA_hcenter = 0x04b;
3270 #else
3271 int pAGA_htotal = 0x081;
3272 int pAGA_vtotal = 0x23d;
3273 int pAGA_vbstop = 0x017;
3274 int pAGA_hcenter = 0x04f;
3275 #endif
3276 int pAGA_hsstrt = 0x00f;
3277 int pAGA_hsstop = 0x019;
3278 int pAGA_hbstrt = 0x001;
3279 int pAGA_hbstop = 0x021;
3280 int pAGA_vsstrt = 0x001;
3281 int pAGA_vsstop = 0x008;
3282 int pAGA_vbstrt = 0x000;
3283
3284 void
3285 display_pal_aga_view(view_t *v)
3286 {
3287 if (paga_this_data->current_view != v) {
3288 vdata_t *vd = VDATA(v);
3289 cop_t *cp = paga_this_data->frames[F_STORE_LONG], *tmp;
3290 int depth = v->bitmap->depth, i;
3291 int hstart, hstop, vstart, vstop, j;
3292 int x, y, w = v->display.width, h = v->display.height;
3293 u_short ddfstart, ddfwidth, con1;
3294
3295 #ifdef DEBUG
3296 if (aga_enable & AGA_TRACE)
3297 printf("display_aga_view(%dx%dx%d) %p\n", w, h,
3298 depth, v);
3299 #endif
3300 /* round down to nearest even width */
3301 /* w &= 0xfffe; */
3302 /* calculate datafetch width. */
3303
3304 ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 4) << 1;
3305
3306 /* this will center the any overscanned display */
3307 /* and allow user to modify. */
3308 x = v->display.x + paga_this_data->std_start_x - ((w - 640) >> 3);
3309 y = v->display.y + paga_this_data->std_start_y - ((h - 512) >> 1);
3310
3311 if (y & 1)
3312 y--;
3313
3314 if (!(x & 1))
3315 x--;
3316
3317 hstart = x;
3318 hstop = x + (w >> 2);
3319 vstart = y;
3320 vstop = y + (h >> 0);
3321 ddfstart = (hstart >> 1) - 8;
3322
3323 #ifdef DEBUG
3324 if (aga_enable & AGA_TRACE2) {
3325 printf (" ddfwidth %04x x %04x y %04x", ddfwidth,
3326 x, y);
3327 printf (" hstart %04x hstop %04x vstart %04x vstop %04x ddfstart %04x\n",
3328 hstart, hstop, vstart, vstop, ddfstart);
3329 }
3330 #endif
3331 /* check for hardware limits, AGA may allow more..? */
3332 /* anyone got a 4000 I can borrow :^) -ch */
3333 if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
3334 int d = 0;
3335
3336 /* XXX anyone know the equality properties of
3337 * intermixed logial AND's */
3338 /* XXX and arithmetic operators? */
3339 while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
3340 d++;
3341 }
3342
3343 ddfstart -= d;
3344 hstart -= d << 1;
3345 hstop -= d << 1;
3346 }
3347 /* correct the datafetch to proper limits. */
3348 /* delay the actual display of the data until we need it. */
3349 ddfstart &= 0xfffc;
3350 #ifdef DEBUG
3351 if (aga_enable & AGA_TRACE2) {
3352 printf (" ddfwidth %04x x %04x y %04x", ddfwidth,
3353 x, y);
3354 printf (" hstart %04x hstop %04x vstart %04x vstop %04x ddfstart %04x\n",
3355 hstart, hstop, vstart, vstop, ddfstart);
3356 }
3357 #endif
3358 con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
3359
3360 if (paga_this_data->current_view) {
3361 VDATA(paga_this_data->current_view)->flags &= ~VF_DISPLAY; /* mark as no longer */
3362 /* displayed. */
3363 }
3364 paga_this_data->current_view = v;
3365
3366 cp = paga_this_data->frames[F_STORE_LONG];
3367 tmp = cp;
3368 for (i = 0; i < 8; ++i) {
3369 if (tmp == NULL)
3370 break;
3371 tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
3372 if (tmp == NULL)
3373 break;
3374 tmp->cp.inst.operand = 0x0ca1 | (i << 13);
3375 tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
3376 if (tmp == NULL)
3377 break;
3378 tmp->cp.inst.operand = 0x0ea1 | (i << 13);
3379 }
3380 if (tmp)
3381 tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
3382 if (tmp)
3383 tmp->cp.inst.operand = 0x0ca1;
3384 tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
3385 tmp->cp.inst.operand = 0x8003;
3386 tmp = find_copper_inst(cp, CI_MOVE(R_HTOTAL));
3387 tmp->cp.inst.operand = pAGA_htotal; /* 81/71/73/79? */
3388 tmp = find_copper_inst(cp, CI_MOVE(R_HBSTRT));
3389 tmp->cp.inst.operand = pAGA_hbstrt; /* 0x0008 */
3390 tmp = find_copper_inst(cp, CI_MOVE(R_HSSTRT));
3391 tmp->cp.inst.operand = pAGA_hsstrt; /* 0x000e */
3392 tmp = find_copper_inst(cp, CI_MOVE(R_HSSTOP));
3393 tmp->cp.inst.operand = pAGA_hsstop; /* 0x001c */
3394 tmp = find_copper_inst(cp, CI_MOVE(R_HBSTOP));
3395 tmp->cp.inst.operand = pAGA_hsstop; /* 0x001e */
3396 tmp = find_copper_inst(cp, CI_MOVE(R_HCENTER));
3397 tmp->cp.inst.operand = pAGA_hcenter; /*AGA_htotal / 2 + AGA_hsstrt */
3398 tmp = find_copper_inst(cp, CI_MOVE(R_VBSTRT));
3399 tmp->cp.inst.operand = pAGA_vbstrt; /* 0x0000 */
3400 tmp = find_copper_inst(cp, CI_MOVE(R_VSSTRT));
3401 tmp->cp.inst.operand = pAGA_vsstrt; /* 0x016b / AGA_htotal */
3402 tmp = find_copper_inst(cp, CI_MOVE(R_VSSTOP));
3403 tmp->cp.inst.operand = pAGA_vsstop; /* 0x02d6 / AGA_htotal */
3404 tmp = find_copper_inst(cp, CI_MOVE(R_VBSTOP));
3405 tmp->cp.inst.operand = pAGA_vbstop; /* 0x0bd1 / AGA_htotal */
3406 tmp = find_copper_inst(cp, CI_MOVE(R_VTOTAL));
3407 tmp->cp.inst.operand = pAGA_vtotal;
3408 tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
3409 tmp->cp.inst.operand = paga_this_data->beamcon0;
3410 #ifdef DEBUG
3411 if (aga_enable & AGA_TRACE2)
3412 printf(" beamcon0 %04x", tmp->cp.inst.operand);
3413 #endif
3414 tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
3415 tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
3416 #ifdef DEBUG
3417 if (aga_enable & AGA_TRACE2)
3418 printf(" diwhigh %04x>", tmp->cp.inst.operand);
3419 #endif
3420 #if 0
3421 tmp->cp.inst.operand = (vstop & 0x0700) | ((hstop & 0x0100) << 5);
3422 #endif
3423 #ifdef DEBUG
3424 if (aga_enable & AGA_TRACE2)
3425 printf("%04x", tmp->cp.inst.operand);
3426 #endif
3427 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
3428 tmp->cp.inst.operand = paga_this_data->bplcon0 |
3429 ((depth & 0x7) << 12) | ((depth & 0x8) << 1);
3430 #ifdef DEBUG
3431 if (aga_enable & AGA_TRACE2)
3432 printf(" bplcon0 %04x", tmp->cp.inst.operand);
3433 #endif
3434 tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
3435 tmp->cp.inst.operand = con1;
3436 #ifdef DEBUG
3437 if (aga_enable & AGA_TRACE2)
3438 printf(" bplcon1 %04x>0000\n", con1);
3439 #endif
3440 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
3441 tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
3442 #ifdef DEBUG
3443 if (aga_enable & AGA_TRACE2)
3444 printf(" diwstart %04x", tmp->cp.inst.operand);
3445 #endif
3446 tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
3447 tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
3448 #ifdef DEBUG
3449 if (aga_enable & AGA_TRACE2)
3450 printf(" diwstop %04x", tmp->cp.inst.operand);
3451 #endif
3452 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
3453 tmp->cp.inst.operand = ddfstart;
3454 #ifdef DEBUG
3455 if (aga_enable & AGA_TRACE2)
3456 printf(" ddfstart %04x", tmp->cp.inst.operand);
3457 #endif
3458 tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
3459 tmp->cp.inst.operand = ddfstart + ddfwidth;
3460 #ifdef DEBUG
3461 if (aga_enable & AGA_TRACE2)
3462 printf(" ddfstop %04x", tmp->cp.inst.operand);
3463 #endif
3464
3465 tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
3466 for (i = 0, j = 0; i < depth; j += 2, i++) {
3467 /* update the plane pointers */
3468 tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
3469 tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
3470 #ifdef DEBUG
3471 if (aga_enable & AGA_TRACE2)
3472 printf (" bpl%dpth %p", i, v->bitmap->plane[i]);
3473 #endif
3474 }
3475
3476 /* set mods correctly. */
3477 tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
3478 tmp[0].cp.inst.operand = v->bitmap->row_mod;
3479 tmp[1].cp.inst.operand = v->bitmap->row_mod;
3480 #ifdef DEBUG
3481 if (aga_enable & AGA_TRACE2)
3482 printf(" bplxmod %04x\n", v->bitmap->row_mod);
3483 #endif
3484
3485 /* set next pointers correctly */
3486 tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
3487 tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(paga_this_data->frames[F_STORE_LONG]));
3488 tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(paga_this_data->frames[F_STORE_LONG]));
3489
3490 cp = paga_this_data->frames[F_LONG];
3491 paga_this_data->frames[F_LONG] = paga_this_data->frames[F_STORE_LONG];
3492 paga_this_data->frames[F_STORE_LONG] = cp;
3493
3494 vd->flags |= VF_DISPLAY;
3495
3496 cc_use_aga_colormap(v, vd->colormap);
3497 }
3498 cc_load_mode(paga_this);
3499 #ifdef DEBUG
3500 if (aga_enable & AGA_TRACE)
3501 aga_enable |= AGA_TRACE2; /* XXXX */
3502 #endif
3503 }
3504
3505 #endif /* GRF_AGA */
3506 #endif /* GRF_PAL */
3507