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