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