xref: /netbsd-src/sys/arch/amiga/dev/grfabs_cc.c (revision 76dfffe33547c37f8bdd446e3e4ab0f3c16cea4b)
1 /*	$NetBSD: grfabs_cc.c,v 1.15 1996/10/13 03:07:09 christos 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 #ifdef GRF_AGA_VGA
1846 		aga_this_data->std_start_x = 0x40 /*STANDARD_VIEW_X*/;
1847 #else
1848 		aga_this_data->std_start_x = 0x4f /*STANDARD_VIEW_X*/;
1849 #endif
1850 		aga_this_data->std_start_y = 0x2b /*STANDARD_VIEW_Y*/;
1851 		aga_this_data->vbl_handler = (vbl_handler_func *) cc_mode_vbl_handler;
1852 		aga_this_data->beamcon0 = SPECIAL_BEAMCON ^ VSYNCTRUE;
1853 
1854 		LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes,
1855 		    aga_this, link);
1856 	}
1857 	return (aga_this);
1858 }
1859 
1860 /* static, so I can patch and play */
1861 
1862 #ifdef GRF_AGA_VGA
1863 int	AGA_htotal = 0x71;
1864 int	AGA_hsstrt = 0xc;
1865 int	AGA_hsstop = 0x16;
1866 int	AGA_hbstrt = 0x5;
1867 #else
1868 int	AGA_htotal = 0x79;
1869 int	AGA_hsstrt = 0xe;
1870 int	AGA_hsstop = 0x1c;
1871 int	AGA_hbstrt = 0x8;
1872 #endif
1873 int	AGA_hbstop = 0x1e;
1874 #ifdef GRF_AGA_VGA
1875 int	AGA_vtotal = 0x1c1;
1876 #else
1877 int	AGA_vtotal = 0x1ec;
1878 #endif
1879 int	AGA_vsstrt = 0x3;
1880 int	AGA_vsstop = 0x6;
1881 int	AGA_vbstrt = 0x0;
1882 int	AGA_vbstop = 0x19;
1883 int	AGA_hcenter = 0x4a;
1884 
1885 void
1886 display_aga_view(v)
1887 	view_t *v;
1888 {
1889 	if (aga_this_data->current_view != v) {
1890 		vdata_t *vd = VDATA(v);
1891 		cop_t  *cp = aga_this_data->frames[F_STORE_LONG], *tmp;
1892 		int     depth = v->bitmap->depth, i;
1893 		int     hstart, hstop, vstart, vstop, j;
1894 		int     x, y, w = v->display.width, h = v->display.height;
1895 		u_short ddfstart, ddfwidth, con1;
1896 
1897 #ifdef DEBUG
1898 		if (aga_enable & AGA_TRACE)
1899 			printf("display_aga_view(%dx%dx%d) %p\n", w, h,
1900 			    depth, v);
1901 #endif
1902 		/* round down to nearest even width */
1903 		/* w &= 0xfffe; */
1904 		/* calculate datafetch width. */
1905 
1906 		ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 4) << 1;
1907 
1908 		/* this will center the any overscanned display */
1909 		/* and allow user to modify. */
1910 		x = v->display.x + aga_this_data->std_start_x - ((w - 640) >> 3);
1911 		y = v->display.y + aga_this_data->std_start_y - ((h - 400) >> 1);
1912 
1913 		if (y & 1)
1914 			y--;
1915 
1916 		if (!(x & 1))
1917 			x--;
1918 
1919 		hstart = x;
1920 		hstop = x + (w >> 2);
1921 		vstart = y;
1922 		vstop = y + (h >> 0);
1923 		ddfstart = (hstart >> 1) - 8;
1924 
1925 #ifdef DEBUG
1926 		if (aga_enable & AGA_TRACE2) {
1927 			printf ("  ddfwidth %04x x %04x y %04x", ddfwidth,
1928 			    x, y);
1929 			printf (" hstart %04x hstop %04x vstart %04x vstop %04x ddfstart %04x\n",
1930 			    hstart, hstop, vstart, vstop, ddfstart);
1931 		}
1932 #endif
1933 		/* check for hardware limits, AGA may allow more..? */
1934 		/* anyone got a 4000 I can borrow :^) -ch */
1935 		if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
1936 			int     d = 0;
1937 
1938 			/* XXX anyone know the equality properties of
1939 			 * intermixed logial AND's */
1940 			/* XXX and arithmetic operators? */
1941 			while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
1942 				d++;
1943 			}
1944 
1945 			ddfstart -= d;
1946 			hstart -= d << 1;
1947 			hstop -= d << 1;
1948 		}
1949 		/* correct the datafetch to proper limits. */
1950 		/* delay the actual display of the data until we need it. */
1951 		ddfstart &= 0xfffc;
1952 #ifdef DEBUG
1953 		if (aga_enable & AGA_TRACE2) {
1954 			printf ("  ddfwidth %04x x %04x y %04x", ddfwidth,
1955 			    x, y);
1956 			printf (" hstart %04x hstop %04x vstart %04x vstop %04x ddfstart %04x\n",
1957 			    hstart, hstop, vstart, vstop, ddfstart);
1958 		}
1959 #endif
1960 		con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
1961 
1962 		if (aga_this_data->current_view) {
1963 			VDATA(aga_this_data->current_view)->flags &= ~VF_DISPLAY;	/* mark as no longer */
1964 			/* displayed. */
1965 		}
1966 		aga_this_data->current_view = v;
1967 
1968 		cp = aga_this_data->frames[F_STORE_LONG];
1969 		tmp = cp;
1970 		for (i = 0; i < 8; ++i) {
1971 			if (tmp == NULL)
1972 				break;
1973 			tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
1974 			if (tmp == NULL)
1975 				break;
1976 			tmp->cp.inst.operand = 0x0ca1 | (i << 13);
1977 			tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
1978 			if (tmp == NULL)
1979 				break;
1980 			tmp->cp.inst.operand = 0x0ea1 | (i << 13);
1981 		}
1982 		if (tmp)
1983 			tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
1984 		if (tmp)
1985 			tmp->cp.inst.operand = 0x0ca1;
1986 		tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
1987 		tmp->cp.inst.operand = 0x8003;
1988 		tmp = find_copper_inst(cp, CI_MOVE(R_HTOTAL));
1989 		tmp->cp.inst.operand = AGA_htotal; /* 81/71/73/79? */
1990 		tmp = find_copper_inst(cp, CI_MOVE(R_HBSTRT));
1991 		tmp->cp.inst.operand = AGA_hbstrt; /* 0x0008 */
1992 		tmp = find_copper_inst(cp, CI_MOVE(R_HSSTRT));
1993 		tmp->cp.inst.operand = AGA_hsstrt; /* 0x000e */
1994 		tmp = find_copper_inst(cp, CI_MOVE(R_HSSTOP));
1995 		tmp->cp.inst.operand = AGA_hsstop; /* 0x001c */
1996 		tmp = find_copper_inst(cp, CI_MOVE(R_HBSTOP));
1997 		tmp->cp.inst.operand = AGA_hsstop; /* 0x001e */
1998 		tmp = find_copper_inst(cp, CI_MOVE(R_HCENTER));
1999 		tmp->cp.inst.operand = AGA_hcenter; /*AGA_htotal / 2 + AGA_hsstrt */
2000 		tmp = find_copper_inst(cp, CI_MOVE(R_VBSTRT));
2001 		tmp->cp.inst.operand = AGA_vbstrt; /* 0x0000 */
2002 		tmp = find_copper_inst(cp, CI_MOVE(R_VSSTRT));
2003 		tmp->cp.inst.operand = AGA_vsstrt; /* 0x016b / AGA_htotal */
2004 		tmp = find_copper_inst(cp, CI_MOVE(R_VSSTOP));
2005 		tmp->cp.inst.operand = AGA_vsstop; /* 0x02d6 / AGA_htotal */
2006 		tmp = find_copper_inst(cp, CI_MOVE(R_VBSTOP));
2007 		tmp->cp.inst.operand = AGA_vbstop; /* 0x0bd1 / AGA_htotal */
2008 		tmp = find_copper_inst(cp, CI_MOVE(R_VTOTAL));
2009 		tmp->cp.inst.operand = AGA_vtotal;
2010 		tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
2011 		tmp->cp.inst.operand = aga_this_data->beamcon0;
2012 #ifdef DEBUG
2013 		if (aga_enable & AGA_TRACE2)
2014 			printf("  beamcon0 %04x", tmp->cp.inst.operand);
2015 #endif
2016 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
2017 		tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
2018 #ifdef DEBUG
2019 		if (aga_enable & AGA_TRACE2)
2020 			printf(" diwhigh %04x>", tmp->cp.inst.operand);
2021 #endif
2022 #if 0
2023 		tmp->cp.inst.operand = (vstop & 0x0700) | ((hstop & 0x0100) << 5);
2024 #endif
2025 #ifdef DEBUG
2026 		if (aga_enable & AGA_TRACE2)
2027 			printf("%04x", tmp->cp.inst.operand);
2028 #endif
2029 		tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
2030 		tmp->cp.inst.operand = aga_this_data->bplcon0 |
2031 		    ((depth & 0x7) << 12) | ((depth & 0x8) << 1);
2032 #ifdef DEBUG
2033 		if (aga_enable & AGA_TRACE2)
2034 			printf(" bplcon0 %04x", tmp->cp.inst.operand);
2035 #endif
2036 		tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
2037 		tmp->cp.inst.operand = con1;
2038 #ifdef DEBUG
2039 		if (aga_enable & AGA_TRACE2)
2040 			printf(" bplcon1 %04x>0000\n", con1);
2041 #endif
2042 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
2043 		tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
2044 #ifdef DEBUG
2045 		if (aga_enable & AGA_TRACE2)
2046 			printf("  diwstart %04x", tmp->cp.inst.operand);
2047 #endif
2048 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
2049 		tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
2050 #ifdef DEBUG
2051 		if (aga_enable & AGA_TRACE2)
2052 			printf(" diwstop %04x", tmp->cp.inst.operand);
2053 #endif
2054 		tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
2055 		tmp->cp.inst.operand = ddfstart;
2056 #ifdef DEBUG
2057 		if (aga_enable & AGA_TRACE2)
2058 			printf(" ddfstart %04x", tmp->cp.inst.operand);
2059 #endif
2060 		tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
2061 		tmp->cp.inst.operand = ddfstart + ddfwidth;
2062 #ifdef DEBUG
2063 		if (aga_enable & AGA_TRACE2)
2064 			printf(" ddfstop %04x", tmp->cp.inst.operand);
2065 #endif
2066 
2067 		tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2068 		for (i = 0, j = 0; i < depth; j += 2, i++) {
2069 			/* update the plane pointers */
2070 			tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2071 			tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2072 #ifdef DEBUG
2073 		if (aga_enable & AGA_TRACE2)
2074 			printf (" bpl%dpth %p", i, v->bitmap->plane[i]);
2075 #endif
2076 		}
2077 
2078 		/* set mods correctly. */
2079 		tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
2080 		tmp[0].cp.inst.operand = v->bitmap->row_mod;
2081 		tmp[1].cp.inst.operand = v->bitmap->row_mod;
2082 #ifdef DEBUG
2083 		if (aga_enable & AGA_TRACE2)
2084 			printf(" bplxmod %04x\n", v->bitmap->row_mod);
2085 #endif
2086 
2087 		/* set next pointers correctly */
2088 		tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2089 		tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(aga_this_data->frames[F_STORE_LONG]));
2090 		tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(aga_this_data->frames[F_STORE_LONG]));
2091 
2092 		cp = aga_this_data->frames[F_LONG];
2093 		aga_this_data->frames[F_LONG] = aga_this_data->frames[F_STORE_LONG];
2094 		aga_this_data->frames[F_STORE_LONG] = cp;
2095 
2096 		vd->flags |= VF_DISPLAY;
2097 
2098 		cc_use_aga_colormap(v, vd->colormap);
2099 	}
2100 	cc_load_mode(aga_this);
2101 #ifdef DEBUG
2102 	if (aga_enable & AGA_TRACE)
2103 		aga_enable |= AGA_TRACE2;	/* XXXX */
2104 #endif
2105 }
2106 
2107 #endif /* GRF_AGA */
2108 #endif /* GRF_NTSC */
2109 
2110 /*
2111  * PAL modes.
2112  */
2113 
2114 #if defined (GRF_PAL)
2115 
2116 dmode_t *
2117 cc_init_pal_hires()
2118 {
2119 	/* this function should only be called once. */
2120 	if (!ph_this) {
2121 		u_short len = std_copper_list_len;
2122 
2123 		ph_this = &pal_hires_mode;
2124 		ph_this_data = &pal_hires_mode_data;
2125 		bzero(ph_this, sizeof(dmode_t));
2126 		bzero(ph_this_data, sizeof(dmdata_t));
2127 
2128 		ph_this->name = "pal: hires";
2129 		ph_this->nominal_size.width = 640;
2130 		ph_this->nominal_size.height = 256;
2131 		ph_this_data->max_size.width = 724;
2132 		ph_this_data->max_size.height = 289;
2133 		ph_this_data->min_size.width = 320;
2134 		ph_this_data->min_size.height = 244;
2135 		ph_this_data->min_depth = 1;
2136 		ph_this_data->max_depth = 4;
2137 		ph_this->data = ph_this_data;
2138 
2139 		ph_this->get_monitor = cc_get_monitor;
2140 		ph_this->alloc_view = cc_alloc_view;
2141 		ph_this->get_current_view = cc_get_current_view;
2142 
2143 		ph_this_data->use_colormap = cc_use_colormap;
2144 		ph_this_data->get_colormap = cc_get_colormap;
2145 		ph_this_data->alloc_colormap = cc_alloc_colormap;
2146 		ph_this_data->display_view = display_pal_hires_view;
2147 		ph_this_data->monitor = cc_monitor;
2148 
2149 		ph_this_data->frames = pal_hires_frames;
2150 		ph_this_data->frames[F_LONG] = alloc_chipmem(std_copper_list_size * F_TOTAL);
2151 		if (!ph_this_data->frames[F_LONG]) {
2152 			panic("couldn't get chipmem for copper list");
2153 		}
2154 		ph_this_data->frames[F_STORE_LONG] = &ph_this_data->frames[F_LONG][len];
2155 
2156 		bcopy(std_copper_list, ph_this_data->frames[F_STORE_LONG], std_copper_list_size);
2157 		bcopy(std_copper_list, ph_this_data->frames[F_LONG], std_copper_list_size);
2158 
2159 		ph_this_data->bplcon0 = 0x8200 | USE_CON3;	/* pal_hires, color
2160 								 * composite enable,
2161 								 * lace. */
2162 		ph_this_data->std_start_x = STANDARD_VIEW_X;
2163 		ph_this_data->std_start_y = STANDARD_VIEW_Y;
2164 		ph_this_data->vbl_handler = (vbl_handler_func *) cc_mode_vbl_handler;
2165 #if defined (GRF_ECS) || defined (GRF_AGA)
2166 		ph_this_data->beamcon0 = STANDARD_PAL_BEAMCON;
2167 #endif
2168 
2169 		LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, ph_this, link);
2170 	}
2171 	return (ph_this);
2172 }
2173 
2174 void
2175 display_pal_hires_view(v)
2176 	view_t *v;
2177 {
2178 	if (ph_this_data->current_view != v) {
2179 		vdata_t *vd = VDATA(v);
2180 		cop_t  *cp = ph_this_data->frames[F_STORE_LONG], *tmp;
2181 		int     depth = v->bitmap->depth, i;
2182 		int     hstart, hstop, vstart, vstop, j;
2183 		int     x, y, w = v->display.width, h = v->display.height;
2184 		u_short ddfstart, ddfwidth, con1;
2185 
2186 		/* round down to nearest even width */
2187 		/* w &= 0xfffe; */
2188 
2189 		/* calculate datafetch width. */
2190 		ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
2191 
2192 		/* This will center the any overscanned display */
2193 		/* and allow user to modify. */
2194 		x = v->display.x + ph_this_data->std_start_x - ((w - 640) >> 2);
2195 		y = v->display.y + ph_this_data->std_start_y - ((h - 256) >> 1);
2196 
2197 		if (y & 1)
2198 			y--;
2199 
2200 		if (!(x & 1))
2201 			x--;
2202 
2203 		hstart = x;
2204 		hstop = x + (w >> 1);
2205 		vstart = y;
2206 		vstop = y + h;
2207 		ddfstart = (hstart - 9) >> 1;
2208 		/* check for hardware limits, AGA may allow more..? */
2209 		/* anyone got a 4000 I can borrow :^) -ch */
2210 		if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
2211 			int     d = 0;
2212 
2213 			/* XXX anyone know the equality properties of
2214 			 * intermixed logial AND's */
2215 			/* XXX and arithmetic operators? */
2216 			while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
2217 				d++;
2218 			}
2219 
2220 			ddfstart -= d;
2221 			hstart -= d << 1;
2222 			hstop -= d << 1;
2223 		}
2224 		/* correct the datafetch to proper limits. */
2225 		/* delay the actual display of the data until we need it. */
2226 		ddfstart &= 0xfffc;
2227 		con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
2228 
2229 		if (ph_this_data->current_view) {
2230 			VDATA(ph_this_data->current_view)->flags &= ~VF_DISPLAY;	/* mark as no longer */
2231 			/* displayed. */
2232 		}
2233 		ph_this_data->current_view = v;
2234 
2235 		cp = ph_this_data->frames[F_STORE_LONG];
2236 #if defined (GRF_ECS) || defined (GRF_AGA)
2237 #if defined GRF_AGA
2238 		tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
2239 		tmp->cp.inst.operand = 0;
2240 #endif
2241 		tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
2242 		tmp->cp.inst.operand = ph_this_data->beamcon0;
2243 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
2244 		tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
2245 #endif /* ECS */
2246 		tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
2247 		tmp->cp.inst.operand = ph_this_data->bplcon0 | ((depth & 0x7) << 12);
2248 		tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
2249 		tmp->cp.inst.operand = con1;
2250 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
2251 		tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
2252 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
2253 		tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
2254 		tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
2255 		tmp->cp.inst.operand = ddfstart;
2256 		tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
2257 		tmp->cp.inst.operand = ddfstart + ddfwidth;
2258 
2259 		tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2260 		for (i = 0, j = 0; i < depth; j += 2, i++) {
2261 			/* update the plane pointers */
2262 			tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2263 			tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2264 		}
2265 
2266 		/* set mods correctly. */
2267 		tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
2268 		tmp[0].cp.inst.operand = v->bitmap->row_mod;
2269 		tmp[1].cp.inst.operand = v->bitmap->row_mod;
2270 
2271 		/* set next pointers correctly */
2272 		tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2273 		tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(ph_this_data->frames[F_STORE_LONG]));
2274 		tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(ph_this_data->frames[F_STORE_LONG]));
2275 
2276 		cp = ph_this_data->frames[F_LONG];
2277 		ph_this_data->frames[F_LONG] = ph_this_data->frames[F_STORE_LONG];
2278 		ph_this_data->frames[F_STORE_LONG] = cp;
2279 
2280 		vd->flags |= VF_DISPLAY;
2281 		cc_use_colormap(v, vd->colormap);
2282 	}
2283 	cc_load_mode(ph_this);
2284 }
2285 
2286 dmode_t *
2287 cc_init_pal_hires_lace()
2288 {
2289 	/* this function should only be called once. */
2290 	if (!phl_this) {
2291 		u_short len = std_copper_list_len;
2292 
2293 		phl_this = &pal_hires_lace_mode;
2294 		phl_this_data = &pal_hires_lace_mode_data;
2295 		bzero(phl_this, sizeof(dmode_t));
2296 		bzero(phl_this_data, sizeof(dmdata_t));
2297 
2298 		phl_this->name = "pal: hires interlace";
2299 		phl_this->nominal_size.width = 640;
2300 		phl_this->nominal_size.height = 512;
2301 		phl_this_data->max_size.width = 724;
2302 		phl_this_data->max_size.height = 578;
2303 		phl_this_data->min_size.width = 320;
2304 		phl_this_data->min_size.height = 484;
2305 		phl_this_data->min_depth = 1;
2306 		phl_this_data->max_depth = 4;
2307 		phl_this->data = phl_this_data;
2308 
2309 		phl_this->get_monitor = cc_get_monitor;
2310 		phl_this->alloc_view = cc_alloc_view;
2311 		phl_this->get_current_view = cc_get_current_view;
2312 
2313 		phl_this_data->use_colormap = cc_use_colormap;
2314 		phl_this_data->get_colormap = cc_get_colormap;
2315 		phl_this_data->alloc_colormap = cc_alloc_colormap;
2316 		phl_this_data->display_view = display_pal_hires_lace_view;
2317 		phl_this_data->monitor = cc_monitor;
2318 
2319 		phl_this_data->flags |= DMF_INTERLACE;
2320 
2321 		phl_this_data->frames = pal_hires_lace_frames;
2322 		phl_this_data->frames[F_LACE_LONG] = alloc_chipmem(std_copper_list_size * F_LACE_TOTAL);
2323 		if (!phl_this_data->frames[F_LACE_LONG]) {
2324 			panic("couldn't get chipmem for copper list");
2325 		}
2326 		phl_this_data->frames[F_LACE_SHORT] = &phl_this_data->frames[F_LACE_LONG][len];
2327 		phl_this_data->frames[F_LACE_STORE_LONG] = &phl_this_data->frames[F_LACE_SHORT][len];
2328 		phl_this_data->frames[F_LACE_STORE_SHORT] = &phl_this_data->frames[F_LACE_STORE_LONG][len];
2329 
2330 		bcopy(std_copper_list, phl_this_data->frames[F_LACE_STORE_LONG], std_copper_list_size);
2331 		bcopy(std_copper_list, phl_this_data->frames[F_LACE_STORE_SHORT], std_copper_list_size);
2332 		bcopy(std_copper_list, phl_this_data->frames[F_LACE_LONG], std_copper_list_size);
2333 		bcopy(std_copper_list, phl_this_data->frames[F_LACE_SHORT], std_copper_list_size);
2334 
2335 		phl_this_data->bplcon0 = 0x8204 | USE_CON3;	/* hires, color
2336 								 * composite enable,
2337 								 * lace. */
2338 		phl_this_data->std_start_x = STANDARD_VIEW_X;
2339 		phl_this_data->std_start_y = STANDARD_VIEW_Y;
2340 		phl_this_data->vbl_handler = (vbl_handler_func *) cc_lace_mode_vbl_handler;
2341 #if defined (GRF_ECS) || defined (GRF_AGA)
2342 		phl_this_data->beamcon0 = STANDARD_PAL_BEAMCON;
2343 #endif
2344 
2345 		LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, phl_this, link);
2346 	}
2347 	return (phl_this);
2348 }
2349 
2350 void
2351 display_pal_hires_lace_view(v)
2352 	view_t *v;
2353 {
2354 	if (phl_this_data->current_view != v) {
2355 		vdata_t *vd = VDATA(v);
2356 		cop_t  *cp = phl_this_data->frames[F_LACE_STORE_LONG], *tmp;
2357 		int     depth = v->bitmap->depth, i;
2358 		int     hstart, hstop, vstart, vstop, j;
2359 		int     x, y, w = v->display.width, h = v->display.height;
2360 		u_short ddfstart, ddfwidth, con1;
2361 
2362 		/* round down to nearest even width */
2363 		/* w &= 0xfffe; */
2364 
2365 		/* calculate datafetch width. */
2366 		ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
2367 
2368 		/* This will center the any overscanned display */
2369 		/* and allow user to modify. */
2370 		x = v->display.x + phl_this_data->std_start_x - ((w - 640) >> 2);
2371 		y = v->display.y + phl_this_data->std_start_y - ((h - 512) >> 2);
2372 
2373 		if (y & 1)
2374 			y--;
2375 
2376 		if (!(x & 1))
2377 			x--;
2378 
2379 		hstart = x;
2380 		hstop = x + (w >> 1);
2381 		vstart = y;
2382 		vstop = y + (h >> 1);
2383 		ddfstart = (hstart - 9) >> 1;
2384 
2385 		/* check for hardware limits, AGA may allow more..? */
2386 		/* anyone got a 4000 I can borrow :^) -ch */
2387 		if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
2388 			int     d = 0;
2389 
2390 			/* XXX anyone know the equality properties of
2391 			 * intermixed logial AND's */
2392 			/* XXX and arithmetic operators? */
2393 			while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
2394 				d++;
2395 			}
2396 
2397 			ddfstart -= d;
2398 			hstart -= d << 1;
2399 			hstop -= d << 1;
2400 		}
2401 		/* correct the datafetch to proper limits. */
2402 		/* delay the actual display of the data until we need it. */
2403 		ddfstart &= 0xfffc;
2404 		con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
2405 
2406 		if (phl_this_data->current_view) {
2407 			VDATA(phl_this_data->current_view)->flags &= ~VF_DISPLAY;	/* mark as no longer */
2408 			/* displayed. */
2409 		}
2410 		phl_this_data->current_view = v;
2411 
2412 		cp = phl_this_data->frames[F_LACE_STORE_LONG];
2413 #if defined (GRF_ECS) || defined (GRF_AGA)
2414 #if defined GRF_AGA
2415 		tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
2416 		tmp->cp.inst.operand = 0;
2417 #endif
2418 		tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
2419 		tmp->cp.inst.operand = phl_this_data->beamcon0;
2420 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
2421 		tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
2422 #endif /* ECS */
2423 		tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
2424 		tmp->cp.inst.operand = phl_this_data->bplcon0 | ((depth & 0x7) << 12);
2425 		tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
2426 		tmp->cp.inst.operand = con1;
2427 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
2428 		tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
2429 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
2430 		tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
2431 		tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
2432 		tmp->cp.inst.operand = ddfstart;
2433 		tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
2434 		tmp->cp.inst.operand = ddfstart + ddfwidth;
2435 
2436 		tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2437 		for (i = 0, j = 0; i < depth; j += 2, i++) {
2438 			/* update the plane pointers */
2439 			tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2440 			tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
2441 		}
2442 
2443 		/* set mods correctly. */
2444 		tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
2445 		tmp[0].cp.inst.operand = v->bitmap->bytes_per_row + v->bitmap->row_mod;
2446 		tmp[1].cp.inst.operand = v->bitmap->bytes_per_row + v->bitmap->row_mod;
2447 
2448 		/* set next pointers correctly */
2449 		tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2450 		tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(phl_this_data->frames[F_LACE_STORE_SHORT]));
2451 		tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(phl_this_data->frames[F_LACE_STORE_SHORT]));
2452 
2453 
2454 		bcopy(phl_this_data->frames[F_LACE_STORE_LONG], phl_this_data->frames[F_LACE_STORE_SHORT], std_copper_list_size);
2455 
2456 		/* these are the only ones that are different from long frame. */
2457 		cp = phl_this_data->frames[F_LACE_STORE_SHORT];
2458 		tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2459 		for (i = 0, j = 0; i < depth; j += 2, i++) {
2460 			u_short mod = v->bitmap->bytes_per_row + v->bitmap->row_mod;
2461 			/* update plane pointers. high and low. */
2462 			tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
2463 			tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[i][mod]));
2464 		}
2465 
2466 		/* set next pointers correctly */
2467 		tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2468 		tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(phl_this_data->frames[F_LACE_STORE_LONG]));
2469 		tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(phl_this_data->frames[F_LACE_STORE_LONG]));
2470 
2471 
2472 		cp = phl_this_data->frames[F_LACE_LONG];
2473 		phl_this_data->frames[F_LACE_LONG] = phl_this_data->frames[F_LACE_STORE_LONG];
2474 		phl_this_data->frames[F_LACE_STORE_LONG] = cp;
2475 
2476 		cp = phl_this_data->frames[F_LACE_SHORT];
2477 		phl_this_data->frames[F_LACE_SHORT] = phl_this_data->frames[F_LACE_STORE_SHORT];
2478 		phl_this_data->frames[F_LACE_STORE_SHORT] = cp;
2479 
2480 		vd->flags |= VF_DISPLAY;
2481 		cc_use_colormap(v, vd->colormap);
2482 	}
2483 	cc_load_mode(phl_this);
2484 }
2485 #if defined (GRF_A2024)
2486 
2487 dmode_t *
2488 cc_init_pal_hires_dlace()
2489 {
2490 	/* this function should only be called once. */
2491 	if (!phdl_this) {
2492 		u_short len = std_dlace_copper_list_len;
2493 
2494 		phdl_this = &pal_hires_dlace_mode;
2495 		phdl_this_data = &pal_hires_dlace_mode_data;
2496 		bzero(phdl_this, sizeof(dmode_t));
2497 		bzero(phdl_this_data, sizeof(dmdata_t));
2498 
2499 		phdl_this->name = "pal: hires double interlace";
2500 		phdl_this->nominal_size.width = 640;
2501 		phdl_this->nominal_size.height = 1024;
2502 		phdl_this_data->max_size.width = 724;
2503 		phdl_this_data->max_size.height = 1024;
2504 		phdl_this_data->min_size.width = 320;
2505 		phdl_this_data->min_size.height = 512;
2506 		phdl_this_data->min_depth = 1;
2507 		phdl_this_data->max_depth = 2;
2508 		phdl_this->data = phdl_this_data;
2509 
2510 		phdl_this->get_monitor = cc_get_monitor;
2511 		phdl_this->alloc_view = cc_alloc_view;
2512 		phdl_this->get_current_view = cc_get_current_view;
2513 
2514 		phdl_this_data->use_colormap = cc_a2024_use_colormap;
2515 		phdl_this_data->get_colormap = cc_a2024_get_colormap;
2516 		phdl_this_data->alloc_colormap = cc_a2024_alloc_colormap;
2517 		phdl_this_data->display_view = display_pal_hires_dlace_view;
2518 		phdl_this_data->monitor = cc_monitor;
2519 
2520 		phdl_this_data->flags |= DMF_INTERLACE;
2521 
2522 		phdl_this_data->frames = pal_hires_dlace_frames;
2523 		phdl_this_data->frames[F_LACE_LONG] = alloc_chipmem(std_dlace_copper_list_size * F_LACE_TOTAL);
2524 		if (!phdl_this_data->frames[F_LACE_LONG]) {
2525 			panic("couldn't get chipmem for copper list");
2526 		}
2527 		phdl_this_data->frames[F_LACE_SHORT] = &phdl_this_data->frames[F_LACE_LONG][len];
2528 		phdl_this_data->frames[F_LACE_STORE_LONG] = &phdl_this_data->frames[F_LACE_SHORT][len];
2529 		phdl_this_data->frames[F_LACE_STORE_SHORT] = &phdl_this_data->frames[F_LACE_STORE_LONG][len];
2530 
2531 		bcopy(std_dlace_copper_list, phdl_this_data->frames[F_LACE_STORE_LONG], std_dlace_copper_list_size);
2532 		bcopy(std_dlace_copper_list, phdl_this_data->frames[F_LACE_STORE_SHORT], std_dlace_copper_list_size);
2533 		bcopy(std_dlace_copper_list, phdl_this_data->frames[F_LACE_LONG], std_dlace_copper_list_size);
2534 		bcopy(std_dlace_copper_list, phdl_this_data->frames[F_LACE_SHORT], std_dlace_copper_list_size);
2535 
2536 		phdl_this_data->bplcon0 = 0x8204 | USE_CON3;	/* hires, color
2537 								 * composite enable,
2538 								 * dlace. */
2539 		phdl_this_data->std_start_x = STANDARD_VIEW_X;
2540 		phdl_this_data->std_start_y = STANDARD_VIEW_Y;
2541 		phdl_this_data->vbl_handler = (vbl_handler_func *) cc_lace_mode_vbl_handler;
2542 #if defined (GRF_ECS) || defined (GRF_AGA)
2543 		phdl_this_data->beamcon0 = STANDARD_PAL_BEAMCON;
2544 #endif
2545 
2546 		LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, phdl_this, link);
2547 	}
2548 	return (phdl_this);
2549 }
2550 
2551 void
2552 display_pal_hires_dlace_view(v)
2553 	view_t *v;
2554 {
2555 	if (phdl_this_data->current_view != v) {
2556 		vdata_t *vd = VDATA(v);
2557 		cop_t  *cp = phdl_this_data->frames[F_LACE_STORE_LONG], *tmp;
2558 		int     depth = v->bitmap->depth;
2559 		int     hstart, hstop, vstart, vstop;
2560 		int     x, y, w = v->display.width, h = v->display.height;
2561 		u_short ddfstart, ddfwidth, con1;
2562 		u_short mod1l, mod2l;
2563 
2564 		/* round down to nearest even width */
2565 		/* w &= 0xfffe; */
2566 
2567 		/* calculate datafetch width. */
2568 		ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 2) << 2;
2569 
2570 		/* This will center the any overscanned display */
2571 		/* and allow user to modify. */
2572 		x = v->display.x + phdl_this_data->std_start_x - ((w - 640) >> 2);
2573 		y = v->display.y + phdl_this_data->std_start_y - ((h - 1024) >> 3);
2574 
2575 		if (y & 1)
2576 			y--;
2577 
2578 		if (!(x & 1))
2579 			x--;
2580 
2581 		hstart = x;
2582 		hstop = x + (w >> 1);
2583 		vstart = y;
2584 		vstop = y + (h >> 2);
2585 		ddfstart = (hstart - 9) >> 1;
2586 
2587 		/* check for hardware limits, AGA may allow more..? */
2588 		/* anyone got a 4000 I can borrow :^) -ch */
2589 		if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
2590 			int     d = 0;
2591 
2592 			/* XXX anyone know the equality properties of
2593 			 * intermixed logial AND's */
2594 			/* XXX and arithmetic operators? */
2595 			while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
2596 				d++;
2597 			}
2598 
2599 			ddfstart -= d;
2600 			hstart -= d << 1;
2601 			hstop -= d << 1;
2602 		}
2603 		/* correct the datafetch to proper limits. */
2604 		/* delay the actual display of the data until we need it. */
2605 		ddfstart &= 0xfffc;
2606 		con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
2607 
2608 		if (phdl_this_data->current_view) {
2609 			VDATA(phdl_this_data->current_view)->flags &= ~VF_DISPLAY;	/* mark as no longer */
2610 			/* displayed. */
2611 		}
2612 		phdl_this_data->current_view = v;
2613 
2614 		cp = phdl_this_data->frames[F_LACE_STORE_LONG];
2615 #if defined (GRF_ECS) || defined (GRF_AGA)
2616 #if defined GRF_AGA
2617 		tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
2618 		tmp->cp.inst.operand = 0;
2619 #endif
2620 		tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
2621 		tmp->cp.inst.operand = phdl_this_data->beamcon0;
2622 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
2623 		tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
2624 #endif /* ECS */
2625 		tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
2626 		tmp->cp.inst.operand = phdl_this_data->bplcon0 | ((depth & 0x7) << 13);	/* times two. */
2627 		tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
2628 		tmp->cp.inst.operand = con1;
2629 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
2630 		tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
2631 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
2632 		tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
2633 		tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
2634 		tmp->cp.inst.operand = ddfstart;
2635 		tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
2636 		tmp->cp.inst.operand = ddfstart + ddfwidth;
2637 
2638 		mod1l = v->bitmap->bytes_per_row + v->bitmap->row_mod;
2639 		mod2l = mod1l << 1;
2640 
2641 		tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2642 		tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][0]));	/* update plane
2643 											 * pointers. */
2644 		tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][0]));	/* high and low. */
2645 		tmp[2].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod1l]));	/* update plane
2646 												 * pointers. */
2647 		tmp[3].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod1l]));	/* high and low. */
2648 		if (depth == 2) {
2649 			tmp[4].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][0]));	/* update plane
2650 												 * pointers. */
2651 			tmp[5].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][0]));	/* high and low. */
2652 			tmp[6].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod1l]));	/* update plane
2653 													 * pointers. */
2654 			tmp[7].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod1l]));	/* high and low. */
2655 		}
2656 		/* set mods correctly. */
2657 		tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
2658 		tmp[0].cp.inst.operand = mod2l + mod1l;
2659 		tmp[1].cp.inst.operand = mod2l + mod1l;
2660 
2661 		/* set next pointers correctly */
2662 		tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2663 		tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(phdl_this_data->frames[F_LACE_STORE_SHORT]));
2664 		tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(phdl_this_data->frames[F_LACE_STORE_SHORT]));
2665 
2666 		bcopy(phdl_this_data->frames[F_LACE_STORE_LONG], phdl_this_data->frames[F_LACE_STORE_SHORT], std_dlace_copper_list_size);
2667 
2668 		/* these are the only ones that are different from long frame. */
2669 		cp = phdl_this_data->frames[F_LACE_STORE_SHORT];
2670 		tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
2671 		tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l]));	/* update plane
2672 												 * pointers. */
2673 		tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l]));	/* high and low. */
2674 		tmp[2].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l + mod1l]));	/* update plane
2675 													 * pointers. */
2676 		tmp[3].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[0][mod2l + mod1l]));	/* high and low. */
2677 		if (depth == 2) {
2678 			tmp[4].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l]));	/* update plane
2679 													 * pointers. */
2680 			tmp[5].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l]));	/* high and low. */
2681 			tmp[6].cp.inst.operand = HIADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l + mod1l]));	/* update plane
2682 														 * pointers. */
2683 			tmp[7].cp.inst.operand = LOADDR(PREP_DMA_MEM(&v->bitmap->plane[1][mod2l + mod1l]));	/* high and low. */
2684 		}
2685 		/* set next pointers correctly */
2686 		tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
2687 		tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(phdl_this_data->frames[F_LACE_STORE_LONG]));
2688 		tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(phdl_this_data->frames[F_LACE_STORE_LONG]));
2689 
2690 		cp = phdl_this_data->frames[F_LACE_LONG];
2691 		phdl_this_data->frames[F_LACE_LONG] = phdl_this_data->frames[F_LACE_STORE_LONG];
2692 		phdl_this_data->frames[F_LACE_STORE_LONG] = cp;
2693 
2694 		cp = phdl_this_data->frames[F_LACE_SHORT];
2695 		phdl_this_data->frames[F_LACE_SHORT] = phdl_this_data->frames[F_LACE_STORE_SHORT];
2696 		phdl_this_data->frames[F_LACE_STORE_SHORT] = cp;
2697 
2698 		vd->flags |= VF_DISPLAY;
2699 
2700 		cc_a2024_use_colormap(v, vd->colormap);
2701 	}
2702 	cc_load_mode(phdl_this);
2703 }
2704 
2705 dmode_t *
2706 cc_init_pal_a2024()
2707 {
2708 	/* this function should only be called once. */
2709 	if (!p24_this) {
2710 		int     i;
2711 		u_short len = std_pal_a2024_copper_list_len;
2712 		cop_t  *cp;
2713 
2714 		p24_this = &pal_a2024_mode;
2715 		p24_this_data = &pal_a2024_mode_data;
2716 		bzero(p24_this, sizeof(dmode_t));
2717 		bzero(p24_this_data, sizeof(dmdata_t));
2718 
2719 		p24_this->name = "pal: A2024 15khz";
2720 		p24_this->nominal_size.width = 1024;
2721 		p24_this->nominal_size.height = 1024;
2722 		p24_this_data->max_size.width = 1024;
2723 		p24_this_data->max_size.height = 1024;
2724 		p24_this_data->min_size.width = 1024;
2725 		p24_this_data->min_size.height = 1024;
2726 		p24_this_data->min_depth = 1;
2727 		p24_this_data->max_depth = 2;
2728 		p24_this->data = p24_this_data;
2729 
2730 		p24_this->get_monitor = cc_get_monitor;
2731 		p24_this->alloc_view = cc_alloc_view;
2732 		p24_this->get_current_view = cc_get_current_view;
2733 
2734 		p24_this_data->use_colormap = cc_a2024_use_colormap;
2735 		p24_this_data->get_colormap = cc_a2024_get_colormap;
2736 		p24_this_data->display_view = display_pal_a2024_view;
2737 		p24_this_data->alloc_colormap = cc_a2024_alloc_colormap;
2738 		p24_this_data->monitor = cc_monitor;
2739 
2740 		p24_this_data->flags |= DMF_HEDLEY_EXP;
2741 
2742 		p24_this_data->frames = pal_a2024_frames;
2743 		p24_this_data->frames[F_QD_QUAD0] = alloc_chipmem(std_pal_a2024_copper_list_size * F_QD_TOTAL);
2744 		if (!p24_this_data->frames[F_QD_QUAD0]) {
2745 			panic("couldn't get chipmem for copper list");
2746 		}
2747 		/* setup the hedley init bitplane. */
2748 		hedley_init = alloc_chipmem(128);
2749 		if (!hedley_init) {
2750 			panic("couldn't get chipmem for hedley init bitplane");
2751 		}
2752 		for (i = 1; i < 128; i++)
2753 			hedley_init[i] = 0xff;
2754 		hedley_init[0] = 0x03;
2755 
2756 		/* copy image of standard copper list. */
2757 		bcopy(std_pal_a2024_copper_list, p24_this_data->frames[0], std_pal_a2024_copper_list_size);
2758 
2759 		/* set the init plane pointer. */
2760 		cp = find_copper_inst(p24_this_data->frames[F_QD_QUAD0], CI_MOVE(R_BPL0PTH));
2761 		cp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(hedley_init));
2762 		cp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(hedley_init));
2763 
2764 		for (i = 1; i < F_QD_TOTAL; i++) {
2765 			p24_this_data->frames[i] = &p24_this_data->frames[i - 1][len];
2766 			bcopy(p24_this_data->frames[0], p24_this_data->frames[i], std_pal_a2024_copper_list_size);
2767 		}
2768 
2769 		p24_this_data->bplcon0 = 0x8200;	/* hires */
2770 		p24_this_data->vbl_handler = (vbl_handler_func *) pal_a2024_mode_vbl_handler;
2771 
2772 
2773 		LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes, p24_this, link);
2774 	}
2775 	return (p24_this);
2776 }
2777 
2778 void
2779 display_pal_a2024_view(v)
2780 	view_t *v;
2781 {
2782 	if (p24_this_data->current_view != v) {
2783 		vdata_t *vd = VDATA(v);
2784 		cop_t  *cp, *tmp;
2785 		u_char *inst_plane[2];
2786 		u_char **plane = inst_plane;
2787 		u_long  full_line = v->bitmap->bytes_per_row + v->bitmap->row_mod;
2788 		u_long  half_plane = full_line * v->bitmap->rows / 2;
2789 
2790 		int     depth = v->bitmap->depth, i, j;
2791 
2792 		plane[0] = v->bitmap->plane[0];
2793 		if (depth == 2) {
2794 			plane[1] = v->bitmap->plane[1];
2795 		}
2796 		if (p24_this_data->current_view) {
2797 			VDATA(p24_this_data->current_view)->flags &= ~VF_DISPLAY;	/* mark as no longer
2798 											 * displayed. */
2799 		}
2800 		cp = p24_this_data->frames[F_QD_STORE_QUAD0];
2801 		tmp = find_copper_inst(cp, CI_MOVE(R_COLOR1F));
2802 		tmp = find_copper_inst(tmp, CI_MOVE(R_BPLCON0));	/* grab third one. */
2803 		tmp->cp.inst.operand = p24_this_data->bplcon0 | ((depth & 0x7) << 13);	/* times 2 */
2804 
2805 		bcopy(p24_this_data->frames[F_QD_STORE_QUAD0], p24_this_data->frames[F_QD_STORE_QUAD1], std_pal_a2024_copper_list_size);
2806 		bcopy(p24_this_data->frames[F_QD_STORE_QUAD0], p24_this_data->frames[F_QD_STORE_QUAD2], std_pal_a2024_copper_list_size);
2807 		bcopy(p24_this_data->frames[F_QD_STORE_QUAD0], p24_this_data->frames[F_QD_STORE_QUAD3], std_pal_a2024_copper_list_size);
2808 
2809 		/*
2810 		 * Mark Id's
2811 		 */
2812 		tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD1], CI_WAIT(126, 29));
2813 		CBUMP(tmp);
2814 		CMOVE(tmp, R_COLOR01, QUAD1_ID);
2815 		tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD2], CI_WAIT(126, 29));
2816 		CBUMP(tmp);
2817 		CMOVE(tmp, R_COLOR01, QUAD2_ID);
2818 		tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD3], CI_WAIT(126, 29));
2819 		CBUMP(tmp);
2820 		CMOVE(tmp, R_COLOR01, QUAD3_ID);
2821 
2822 		plane[0]--;
2823 		plane[0]--;
2824 		if (depth == 2) {
2825 			plane[1]--;
2826 			plane[1]--;
2827 		}
2828 		/*
2829 		 * Set bitplane pointers.
2830 		 */
2831 		tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD0], CI_MOVE(R_BPLMOD2));
2832 		CBUMP(tmp);
2833 		CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][0])));
2834 		CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][0])));
2835 		CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][full_line])));
2836 		CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][full_line])));
2837 		if (depth == 2) {
2838 			CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][0])));
2839 			CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][0])));
2840 			CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][full_line])));
2841 			CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][full_line])));
2842 		}
2843 #if defined (GRF_ECS) || defined (GRF_AGA)
2844 		CMOVE(tmp, R_DIWHIGH, 0x2100);
2845 #endif
2846 		CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD1])));
2847 		CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD1])));
2848 		CEND(tmp);
2849 		CEND(tmp);
2850 
2851 		tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD1], CI_MOVE(R_BPLMOD2));
2852 		CBUMP(tmp);
2853 		CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][HALF_2024_LINE])));
2854 		CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][HALF_2024_LINE])));
2855 		CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][full_line + HALF_2024_LINE])));
2856 		CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][full_line + HALF_2024_LINE])));
2857 		if (depth == 2) {
2858 			CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][HALF_2024_LINE])));
2859 			CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][HALF_2024_LINE])));
2860 			CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][full_line + HALF_2024_LINE])));
2861 			CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][full_line + HALF_2024_LINE])));
2862 		}
2863 #if defined (GRF_ECS) || defined (GRF_AGA)
2864 		CMOVE(tmp, R_DIWHIGH, 0x2100);
2865 #endif
2866 		CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD2])));
2867 		CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD2])));
2868 		CEND(tmp);
2869 		CEND(tmp);
2870 
2871 		tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD2], CI_MOVE(R_BPLMOD2));
2872 		CBUMP(tmp);
2873 		CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][half_plane])));
2874 		CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][half_plane])));
2875 		CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line])));
2876 		CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line])));
2877 		if (depth == 2) {
2878 			CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][half_plane])));
2879 			CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][half_plane])));
2880 			CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line])));
2881 			CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line])));
2882 		}
2883 #if defined (GRF_ECS) || defined (GRF_AGA)
2884 		CMOVE(tmp, R_DIWHIGH, 0x2100);
2885 #endif
2886 		CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD3])));
2887 		CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD3])));
2888 		CEND(tmp);
2889 		CEND(tmp);
2890 
2891 		tmp = find_copper_inst(p24_this_data->frames[F_QD_STORE_QUAD3], CI_MOVE(R_BPLMOD2));
2892 		CBUMP(tmp);
2893 		CMOVE(tmp, R_BPL0PTH, HIADDR(PREP_DMA_MEM(&plane[0][half_plane + HALF_2024_LINE])));
2894 		CMOVE(tmp, R_BPL0PTL, LOADDR(PREP_DMA_MEM(&plane[0][half_plane + HALF_2024_LINE])));
2895 		CMOVE(tmp, R_BPL1PTH, HIADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line + HALF_2024_LINE])));
2896 		CMOVE(tmp, R_BPL1PTL, LOADDR(PREP_DMA_MEM(&plane[0][half_plane + full_line + HALF_2024_LINE])));
2897 		if (depth == 2) {
2898 			CMOVE(tmp, R_BPL2PTH, HIADDR(PREP_DMA_MEM(&plane[1][half_plane + HALF_2024_LINE])));
2899 			CMOVE(tmp, R_BPL2PTL, LOADDR(PREP_DMA_MEM(&plane[1][half_plane + HALF_2024_LINE])));
2900 			CMOVE(tmp, R_BPL3PTH, HIADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line + HALF_2024_LINE])));
2901 			CMOVE(tmp, R_BPL3PTL, LOADDR(PREP_DMA_MEM(&plane[1][half_plane + full_line + HALF_2024_LINE])));
2902 		}
2903 #if defined (GRF_ECS) || defined (GRF_AGA)
2904 		CMOVE(tmp, R_DIWHIGH, 0x2100);
2905 #endif
2906 		CMOVE(tmp, R_COP1LCH, HIADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD0])));
2907 		CMOVE(tmp, R_COP1LCL, LOADDR(PREP_DMA_MEM(p24_this_data->frames[F_QD_STORE_QUAD0])));
2908 		CEND(tmp);
2909 		CEND(tmp);
2910 
2911 		/* swap new pointers in. */
2912 		for (i = F_QD_STORE_QUAD0, j = F_QD_QUAD0;
2913 		    i <= F_QD_STORE_QUAD3; i++, j++) {
2914 			cp = p24_this_data->frames[j];
2915 			p24_this_data->frames[j] = p24_this_data->frames[i];
2916 			p24_this_data->frames[i] = cp;
2917 		}
2918 
2919 		p24_this_data->current_view = v;
2920 		vd->flags |= VF_DISPLAY;
2921 
2922 		cc_a2024_use_colormap(v, vd->colormap);
2923 	}
2924 	cc_load_mode(p24_this);
2925 }
2926 
2927 void
2928 pal_a2024_mode_vbl_handler(d)
2929 	dmode_t *d;
2930 {
2931 	u_short vp = ((custom.vposr & 0x0007) << 8) | ((custom.vhposr) >> 8);
2932 
2933 	if (vp < 20) {
2934 		custom.cop1lc = PREP_DMA_MEM(p24_this_data->frames[p24_this_data->hedley_current]);
2935 		custom.copjmp1 = 0;
2936 	}
2937 	p24_this_data->hedley_current++;
2938 	p24_this_data->hedley_current &= 0x3;	/* if 4 then 0. */
2939 }
2940 #endif /* GRF_A2024 */
2941 
2942 #if defined (GRF_AGA)
2943 
2944 dmode_t *
2945 cc_init_pal_aga()
2946 {
2947 	/* this function should only be called once. */
2948 	if (!paga_this && (custom.deniseid & 0xff) == 0xf8 &&
2949 	    aga_enable & AGA_ENABLE) {
2950 		u_short len = aga_copper_list_len;
2951 
2952 		paga_this = &paga_mode;
2953 		paga_this_data = &paga_mode_data;
2954 		bzero(paga_this, sizeof(dmode_t));
2955 		bzero(paga_this_data, sizeof(dmdata_t));
2956 
2957 		paga_this->name = "pal: AGA dbl";
2958 		paga_this->nominal_size.width = 640;
2959 		paga_this->nominal_size.height = 512;
2960 		paga_this_data->max_size.width = 720;
2961 		paga_this_data->max_size.height = 564;
2962 		paga_this_data->min_size.width = 320;
2963 		paga_this_data->min_size.height = 200;
2964 		paga_this_data->min_depth = 1;
2965 		paga_this_data->max_depth = 8;
2966 		paga_this->data = paga_this_data;
2967 
2968 		paga_this->get_monitor = cc_get_monitor;
2969 		paga_this->alloc_view = cc_alloc_view;
2970 		paga_this->get_current_view = cc_get_current_view;
2971 
2972 		paga_this_data->use_colormap = cc_use_aga_colormap;
2973 		paga_this_data->get_colormap = cc_get_colormap;
2974 		paga_this_data->alloc_colormap = cc_alloc_aga_colormap;
2975 		paga_this_data->display_view = display_pal_aga_view;
2976 		paga_this_data->monitor = cc_monitor;
2977 
2978 		paga_this_data->frames = paga_frames;
2979 		paga_this_data->frames[F_LONG] = alloc_chipmem(aga_copper_list_size * F_TOTAL);
2980 		if (!paga_this_data->frames[F_LONG]) {
2981 			panic("couldn't get chipmem for copper list");
2982 		}
2983 		paga_this_data->frames[F_STORE_LONG] = &paga_this_data->frames[F_LONG][len];
2984 
2985 		bcopy(aga_copper_list, paga_this_data->frames[F_STORE_LONG], aga_copper_list_size);
2986 		bcopy(aga_copper_list, paga_this_data->frames[F_LONG], aga_copper_list_size);
2987 
2988 		paga_this_data->bplcon0 = 0x0240 | USE_CON3;	/* color composite
2989 								 * enable,
2990 								 * shres. */
2991 		paga_this_data->std_start_x = 0x4f /*STANDARD_VIEW_X*/;
2992 		paga_this_data->std_start_y = 0x2b /*STANDARD_VIEW_Y*/;
2993 		paga_this_data->vbl_handler = (vbl_handler_func *) cc_mode_vbl_handler;
2994 		paga_this_data->beamcon0 = STANDARD_PAL_BEAMCON | (SPECIAL_BEAMCON ^ VSYNCTRUE);
2995 
2996 		LIST_INSERT_HEAD(&MDATA(cc_monitor)->modes,
2997 		    paga_this, link);
2998 	}
2999 	return (paga_this);
3000 }
3001 
3002 /* static, so I can patch and play (VGAOnly is commented-out) */
3003 
3004 int	pAGA_htotal  = 0x081;	/* 0x079 */
3005 int	pAGA_hsstrt  = 0x00f;	/* 0x00f */
3006 int	pAGA_hsstop  = 0x019;	/* 0x019 */
3007 int	pAGA_hbstrt  = 0x001;	/* 0x001 */
3008 int	pAGA_hbstop  = 0x021;	/* 0x021 */
3009 int	pAGA_vtotal  = 0x23d;	/* 0x24d */
3010 int	pAGA_vsstrt  = 0x001;	/* 0x001 */
3011 int	pAGA_vsstop  = 0x008;	/* 0x008 */
3012 int	pAGA_vbstrt  = 0x000;	/* 0x000 */
3013 int	pAGA_vbstop  = 0x017;	/* 0x019 */
3014 int	pAGA_hcenter = 0x04f;	/* 0x04b */
3015 
3016 void
3017 display_pal_aga_view(v)
3018 	view_t *v;
3019 {
3020 	if (paga_this_data->current_view != v) {
3021 		vdata_t *vd = VDATA(v);
3022 		cop_t  *cp = paga_this_data->frames[F_STORE_LONG], *tmp;
3023 		int     depth = v->bitmap->depth, i;
3024 		int     hstart, hstop, vstart, vstop, j;
3025 		int     x, y, w = v->display.width, h = v->display.height;
3026 		u_short ddfstart, ddfwidth, con1;
3027 
3028 #ifdef DEBUG
3029 		if (aga_enable & AGA_TRACE)
3030 			printf("display_aga_view(%dx%dx%d) %p\n", w, h,
3031 			    depth, v);
3032 #endif
3033 		/* round down to nearest even width */
3034 		/* w &= 0xfffe; */
3035 		/* calculate datafetch width. */
3036 
3037 		ddfwidth = ((v->bitmap->bytes_per_row >> 1) - 4) << 1;
3038 
3039 		/* this will center the any overscanned display */
3040 		/* and allow user to modify. */
3041 		x = v->display.x + paga_this_data->std_start_x - ((w - 640) >> 3);
3042 		y = v->display.y + paga_this_data->std_start_y - ((h - 512) >> 1);
3043 
3044 		if (y & 1)
3045 			y--;
3046 
3047 		if (!(x & 1))
3048 			x--;
3049 
3050 		hstart = x;
3051 		hstop = x + (w >> 2);
3052 		vstart = y;
3053 		vstop = y + (h >> 0);
3054 		ddfstart = (hstart >> 1) - 8;
3055 
3056 #ifdef DEBUG
3057 		if (aga_enable & AGA_TRACE2) {
3058 			printf ("  ddfwidth %04x x %04x y %04x", ddfwidth,
3059 			    x, y);
3060 			printf (" hstart %04x hstop %04x vstart %04x vstop %04x ddfstart %04x\n",
3061 			    hstart, hstop, vstart, vstop, ddfstart);
3062 		}
3063 #endif
3064 		/* check for hardware limits, AGA may allow more..? */
3065 		/* anyone got a 4000 I can borrow :^) -ch */
3066 		if ((ddfstart & 0xfffc) + ddfwidth > 0xd8) {
3067 			int     d = 0;
3068 
3069 			/* XXX anyone know the equality properties of
3070 			 * intermixed logial AND's */
3071 			/* XXX and arithmetic operators? */
3072 			while (((ddfstart & 0xfffc) + ddfwidth - d) > 0xd8) {
3073 				d++;
3074 			}
3075 
3076 			ddfstart -= d;
3077 			hstart -= d << 1;
3078 			hstop -= d << 1;
3079 		}
3080 		/* correct the datafetch to proper limits. */
3081 		/* delay the actual display of the data until we need it. */
3082 		ddfstart &= 0xfffc;
3083 #ifdef DEBUG
3084 		if (aga_enable & AGA_TRACE2) {
3085 			printf ("  ddfwidth %04x x %04x y %04x", ddfwidth,
3086 			    x, y);
3087 			printf (" hstart %04x hstop %04x vstart %04x vstop %04x ddfstart %04x\n",
3088 			    hstart, hstop, vstart, vstop, ddfstart);
3089 		}
3090 #endif
3091 		con1 = ((hstart - 9) - (ddfstart << 1)) | (((hstart - 9) - (ddfstart << 1)) << 4);
3092 
3093 		if (paga_this_data->current_view) {
3094 			VDATA(paga_this_data->current_view)->flags &= ~VF_DISPLAY;	/* mark as no longer */
3095 			/* displayed. */
3096 		}
3097 		paga_this_data->current_view = v;
3098 
3099 		cp = paga_this_data->frames[F_STORE_LONG];
3100 		tmp = cp;
3101 		for (i = 0; i < 8; ++i) {
3102 			if (tmp == NULL)
3103 				break;
3104 			tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
3105 			if (tmp == NULL)
3106 				break;
3107 			tmp->cp.inst.operand = 0x0ca1 | (i << 13);
3108 			tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
3109 			if (tmp == NULL)
3110 				break;
3111 			tmp->cp.inst.operand = 0x0ea1 | (i << 13);
3112 		}
3113 		if (tmp)
3114 			tmp = find_copper_inst(tmp + 1, CI_MOVE(R_BPLCON3));
3115 		if (tmp)
3116 			tmp->cp.inst.operand = 0x0ca1;
3117 		tmp = find_copper_inst(cp, CI_MOVE(R_FMODE));
3118 		tmp->cp.inst.operand = 0x8003;
3119 		tmp = find_copper_inst(cp, CI_MOVE(R_HTOTAL));
3120 		tmp->cp.inst.operand = pAGA_htotal; /* 81/71/73/79? */
3121 		tmp = find_copper_inst(cp, CI_MOVE(R_HBSTRT));
3122 		tmp->cp.inst.operand = pAGA_hbstrt; /* 0x0008 */
3123 		tmp = find_copper_inst(cp, CI_MOVE(R_HSSTRT));
3124 		tmp->cp.inst.operand = pAGA_hsstrt; /* 0x000e */
3125 		tmp = find_copper_inst(cp, CI_MOVE(R_HSSTOP));
3126 		tmp->cp.inst.operand = pAGA_hsstop; /* 0x001c */
3127 		tmp = find_copper_inst(cp, CI_MOVE(R_HBSTOP));
3128 		tmp->cp.inst.operand = pAGA_hsstop; /* 0x001e */
3129 		tmp = find_copper_inst(cp, CI_MOVE(R_HCENTER));
3130 		tmp->cp.inst.operand = pAGA_hcenter; /*AGA_htotal / 2 + AGA_hsstrt */
3131 		tmp = find_copper_inst(cp, CI_MOVE(R_VBSTRT));
3132 		tmp->cp.inst.operand = pAGA_vbstrt; /* 0x0000 */
3133 		tmp = find_copper_inst(cp, CI_MOVE(R_VSSTRT));
3134 		tmp->cp.inst.operand = pAGA_vsstrt; /* 0x016b / AGA_htotal */
3135 		tmp = find_copper_inst(cp, CI_MOVE(R_VSSTOP));
3136 		tmp->cp.inst.operand = pAGA_vsstop; /* 0x02d6 / AGA_htotal */
3137 		tmp = find_copper_inst(cp, CI_MOVE(R_VBSTOP));
3138 		tmp->cp.inst.operand = pAGA_vbstop; /* 0x0bd1 / AGA_htotal */
3139 		tmp = find_copper_inst(cp, CI_MOVE(R_VTOTAL));
3140 		tmp->cp.inst.operand = pAGA_vtotal;
3141 		tmp = find_copper_inst(cp, CI_MOVE(R_BEAMCON0));
3142 		tmp->cp.inst.operand = paga_this_data->beamcon0;
3143 #ifdef DEBUG
3144 		if (aga_enable & AGA_TRACE2)
3145 			printf("  beamcon0 %04x", tmp->cp.inst.operand);
3146 #endif
3147 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWHIGH));
3148 		tmp->cp.inst.operand = CALC_DIWHIGH(hstart, vstart, hstop, vstop);
3149 #ifdef DEBUG
3150 		if (aga_enable & AGA_TRACE2)
3151 			printf(" diwhigh %04x>", tmp->cp.inst.operand);
3152 #endif
3153 #if 0
3154 		tmp->cp.inst.operand = (vstop & 0x0700) | ((hstop & 0x0100) << 5);
3155 #endif
3156 #ifdef DEBUG
3157 		if (aga_enable & AGA_TRACE2)
3158 			printf("%04x", tmp->cp.inst.operand);
3159 #endif
3160 		tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON0));
3161 		tmp->cp.inst.operand = paga_this_data->bplcon0 |
3162 		    ((depth & 0x7) << 12) | ((depth & 0x8) << 1);
3163 #ifdef DEBUG
3164 		if (aga_enable & AGA_TRACE2)
3165 			printf(" bplcon0 %04x", tmp->cp.inst.operand);
3166 #endif
3167 		tmp = find_copper_inst(cp, CI_MOVE(R_BPLCON1));
3168 		tmp->cp.inst.operand = con1;
3169 #ifdef DEBUG
3170 		if (aga_enable & AGA_TRACE2)
3171 			printf(" bplcon1 %04x>0000\n", con1);
3172 #endif
3173 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTART));
3174 		tmp->cp.inst.operand = ((vstart & 0xff) << 8) | (hstart & 0xff);
3175 #ifdef DEBUG
3176 		if (aga_enable & AGA_TRACE2)
3177 			printf("  diwstart %04x", tmp->cp.inst.operand);
3178 #endif
3179 		tmp = find_copper_inst(cp, CI_MOVE(R_DIWSTOP));
3180 		tmp->cp.inst.operand = ((vstop & 0xff) << 8) | (hstop & 0xff);
3181 #ifdef DEBUG
3182 		if (aga_enable & AGA_TRACE2)
3183 			printf(" diwstop %04x", tmp->cp.inst.operand);
3184 #endif
3185 		tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTART));
3186 		tmp->cp.inst.operand = ddfstart;
3187 #ifdef DEBUG
3188 		if (aga_enable & AGA_TRACE2)
3189 			printf(" ddfstart %04x", tmp->cp.inst.operand);
3190 #endif
3191 		tmp = find_copper_inst(cp, CI_MOVE(R_DDFSTOP));
3192 		tmp->cp.inst.operand = ddfstart + ddfwidth;
3193 #ifdef DEBUG
3194 		if (aga_enable & AGA_TRACE2)
3195 			printf(" ddfstop %04x", tmp->cp.inst.operand);
3196 #endif
3197 
3198 		tmp = find_copper_inst(cp, CI_MOVE(R_BPL0PTH));
3199 		for (i = 0, j = 0; i < depth; j += 2, i++) {
3200 			/* update the plane pointers */
3201 			tmp[j].cp.inst.operand = HIADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
3202 			tmp[j + 1].cp.inst.operand = LOADDR(PREP_DMA_MEM(v->bitmap->plane[i]));
3203 #ifdef DEBUG
3204 		if (aga_enable & AGA_TRACE2)
3205 			printf (" bpl%dpth %p", i, v->bitmap->plane[i]);
3206 #endif
3207 		}
3208 
3209 		/* set mods correctly. */
3210 		tmp = find_copper_inst(cp, CI_MOVE(R_BPL1MOD));
3211 		tmp[0].cp.inst.operand = v->bitmap->row_mod;
3212 		tmp[1].cp.inst.operand = v->bitmap->row_mod;
3213 #ifdef DEBUG
3214 		if (aga_enable & AGA_TRACE2)
3215 			printf(" bplxmod %04x\n", v->bitmap->row_mod);
3216 #endif
3217 
3218 		/* set next pointers correctly */
3219 		tmp = find_copper_inst(cp, CI_MOVE(R_COP1LCH));
3220 		tmp[0].cp.inst.operand = HIADDR(PREP_DMA_MEM(paga_this_data->frames[F_STORE_LONG]));
3221 		tmp[1].cp.inst.operand = LOADDR(PREP_DMA_MEM(paga_this_data->frames[F_STORE_LONG]));
3222 
3223 		cp = paga_this_data->frames[F_LONG];
3224 		paga_this_data->frames[F_LONG] = paga_this_data->frames[F_STORE_LONG];
3225 		paga_this_data->frames[F_STORE_LONG] = cp;
3226 
3227 		vd->flags |= VF_DISPLAY;
3228 
3229 		cc_use_aga_colormap(v, vd->colormap);
3230 	}
3231 	cc_load_mode(paga_this);
3232 #ifdef DEBUG
3233 	if (aga_enable & AGA_TRACE)
3234 		aga_enable |= AGA_TRACE2;	/* XXXX */
3235 #endif
3236 }
3237 
3238 #endif /* GRF_AGA */
3239 #endif /* GRF_PAL */
3240