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