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