grf_cl.c revision 1.8 1 /* $NetBSD: grf_cl.c,v 1.8 1996/03/17 05:58:35 mhitch Exp $ */
2
3 /*
4 * Copyright (c) 1995 Ezra Story
5 * Copyright (c) 1995 Kari Mettinen
6 * Copyright (c) 1994 Markus Wild
7 * Copyright (c) 1994 Lutz Vieweg
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by Lutz Vieweg.
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35 #include "grfcl.h"
36 #if NGRFCL > 0
37
38 /*
39 * Graphics routines for Cirrus CL GD 5426 boards,
40 *
41 * This code offers low-level routines to access Cirrus Cl GD 5426
42 * graphics-boards from within NetBSD for the Amiga.
43 * No warranties for any kind of function at all - this
44 * code may crash your hardware and scratch your harddisk. Use at your
45 * own risk. Freely distributable.
46 *
47 * Modified for Cirrus CL GD 5426 from
48 * Lutz Vieweg's retina driver by Kari Mettinen 08/94
49 * Contributions by Ill, ScottE, MiL
50 * Extensively hacked and rewritten by Ezra Story (Ezy) 01/95
51 * Picasso/040 patches (wee!) by crest 01/96
52 *
53 * Thanks to Village Tronic Marketing Gmbh for providing me with
54 * a Picasso-II board.
55 * Thanks for Integrated Electronics Oy Ab for providing me with
56 * Cirrus CL GD 542x family documentation.
57 *
58 * TODO:
59 * Mouse support (almost there! :-))
60 * Blitter support
61 *
62 */
63
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/errno.h>
67 #include <sys/ioctl.h>
68 #include <sys/device.h>
69 #include <sys/malloc.h>
70
71 #include <machine/cpu.h>
72 #include <dev/cons.h>
73 #include <amiga/amiga/device.h>
74 #include <amiga/dev/grfioctl.h>
75 #include <amiga/dev/grfvar.h>
76 #include <amiga/dev/grf_clreg.h>
77 #include <amiga/dev/zbusvar.h>
78
79 static int cl_mondefok __P((struct grfvideo_mode * gv));
80 static void cl_boardinit();
81 static void CompFQ __P((u_int fq, u_char * num, u_char * denom));
82 static int cl_getvmode __P((struct grf_softc * gp, struct grfvideo_mode * vm));
83 static int cl_setvmode __P((struct grf_softc * gp, unsigned int mode));
84 static int cl_toggle __P((struct grf_softc * gp, unsigned short));
85 static int cl_getcmap __P((struct grf_softc * gfp, struct grf_colormap * cmap));
86 static int cl_putcmap __P((struct grf_softc * gfp, struct grf_colormap * cmap));
87 static void cl_off __P((struct grf_softc * gp));
88 static void cl_inittextmode __P((struct grf_softc * gp));
89 static int cl_ioctl __P((register struct grf_softc * gp, int cmd, void *data));
90 static int cl_getmousepos __P((struct grf_softc * gp, struct grf_position * data));
91 static int cl_setmousepos __P((struct grf_softc * gp, struct grf_position * data));
92 static int cl_setspriteinfo __P((struct grf_softc * gp, struct grf_spriteinfo * data));
93 static int cl_getspriteinfo __P((struct grf_softc * gp, struct grf_spriteinfo * data));
94 static int cl_getspritemax __P((struct grf_softc * gp, struct grf_position * data));
95 static int cl_blank __P((struct grf_softc * gp, int * on));
96
97
98 void grfclattach __P((struct device *, struct device *, void *));
99 int grfclprint __P((void *, char *));
100 int grfclmatch __P((struct device *, void *, void *));
101 void cl_memset __P((unsigned char *d, unsigned char c, int l));
102
103 /* Graphics display definitions.
104 * These are filled by 'grfconfig' using GRFIOCSETMON.
105 */
106 #define monitor_def_max 8
107 static struct grfvideo_mode monitor_def[8] = {
108 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
109 };
110 static struct grfvideo_mode *monitor_current = &monitor_def[0];
111
112 /* Patchable maximum pixel clock */
113 unsigned long cl_maxpixelclock = 86000000;
114
115 /* Console display definition.
116 * Default hardcoded text mode. This grf_cl is set up to
117 * use one text mode only, and this is it. You may use
118 * grfconfig to change the mode after boot.
119 */
120 /* Console font */
121 #ifdef KFONT_8X11
122 #define CIRRUSFONT kernel_font_8x11
123 #define CIRRUSFONTY 11
124 #else
125 #define CIRRUSFONT kernel_font_8x8
126 #define CIRRUSFONTY 8
127 #endif
128 extern unsigned char CIRRUSFONT[];
129
130 struct grfcltext_mode clconsole_mode = {
131 {255, "", 25200000, 640, 480, 4, 80, 100, 94, 99, 100, 481, 522, 490,
132 498, 522},
133 8, CIRRUSFONTY, 80, 480 / CIRRUSFONTY, CIRRUSFONT, 32, 255
134 };
135 /* Console colors */
136 unsigned char clconscolors[3][3] = { /* background, foreground, hilite */
137 {0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255}
138 };
139
140 int cltype = 0; /* Picasso, Spectrum or Piccolo */
141 unsigned char pass_toggle; /* passthru status tracker */
142
143 /* because all 5426-boards have 2 configdev entries, one for
144 * framebuffer mem and the other for regs, we have to hold onto
145 * the pointers globally until we match on both. This and 'cltype'
146 * are the primary obsticles to multiple board support, but if you
147 * have multiple boards you have bigger problems than grf_cl.
148 */
149 static void *cl_fbaddr = 0; /* framebuffer */
150 static void *cl_regaddr = 0; /* registers */
151 static int cl_fbsize; /* framebuffer size */
152
153 /* current sprite info, if you add summport for multiple boards
154 * make this an array or something
155 */
156 struct grf_spriteinfo cl_cursprite;
157
158 /* sprite bitmaps in kernel stack, you'll need to arrayize these too if
159 * you add multiple board support
160 */
161 static unsigned char cl_imageptr[8 * 64], cl_maskptr[8 * 64];
162 static unsigned char cl_sprred[2], cl_sprgreen[2], cl_sprblue[2];
163
164 /* standard driver stuff */
165 struct cfattach grfcl_ca = {
166 sizeof(struct grf_softc), grfclmatch, grfclattach
167 };
168
169 struct cfdriver grfcl_cd = {
170 NULL, "grfcl", DV_DULL, NULL, 0
171 };
172 static struct cfdata *cfdata;
173
174 int
175 grfclmatch(pdp, match, auxp)
176 struct device *pdp;
177 void *match, *auxp;
178 {
179 struct cfdata *cfp = match;
180 struct zbus_args *zap;
181 static int regprod, fbprod;
182
183 zap = auxp;
184
185 #ifndef CL5426CONSOLE
186 if (amiga_realconfig == 0)
187 return (0);
188 #endif
189
190 /* Grab the first board we encounter as the preferred one. This will
191 * allow one board to work in a multiple 5426 board system, but not
192 * multiple boards at the same time. */
193 if (cltype == 0) {
194 switch (zap->manid) {
195 case PICASSO:
196 if (zap->prodid != 12 && zap->prodid != 11)
197 return (0);
198 regprod = 12;
199 fbprod = 11;
200 break;
201 case SPECTRUM:
202 if (zap->prodid != 2 && zap->prodid != 1)
203 return (0);
204 regprod = 2;
205 fbprod = 1;
206 break;
207 case PICCOLO:
208 if (zap->prodid != 6 && zap->prodid != 5)
209 return (0);
210 regprod = 6;
211 fbprod = 5;
212 break;
213 default:
214 return (0);
215 }
216 cltype = zap->manid;
217 } else {
218 if (cltype != zap->manid) {
219 return (0);
220 }
221 }
222
223 /* Configure either registers or framebuffer in any order */
224 if (zap->prodid == regprod)
225 cl_regaddr = zap->va;
226 else
227 if (zap->prodid == fbprod) {
228 cl_fbaddr = zap->va;
229 cl_fbsize = zap->size;
230 } else
231 return (0);
232
233 #ifdef CL5426CONSOLE
234 if (amiga_realconfig == 0) {
235 cfdata = cfp;
236 }
237 #endif
238
239 return (1);
240 }
241
242 void
243 grfclattach(pdp, dp, auxp)
244 struct device *pdp, *dp;
245 void *auxp;
246 {
247 static struct grf_softc congrf;
248 struct zbus_args *zap;
249 struct grf_softc *gp;
250 int x;
251 static char attachflag = 0;
252
253 zap = auxp;
254
255 printf("\n");
256
257 /* make sure both halves have matched */
258 if (!cl_regaddr || !cl_fbaddr)
259 return;
260
261 /* do all that messy console/grf stuff */
262 if (dp == NULL)
263 gp = &congrf;
264 else
265 gp = (struct grf_softc *) dp;
266
267 if (dp != NULL && congrf.g_regkva != 0) {
268 /*
269 * inited earlier, just copy (not device struct)
270 */
271 bcopy(&congrf.g_display, &gp->g_display,
272 (char *) &gp[1] - (char *) &gp->g_display);
273 } else {
274 gp->g_regkva = (volatile caddr_t) cl_regaddr;
275 gp->g_fbkva = (volatile caddr_t) cl_fbaddr;
276
277 gp->g_unit = GRF_CL5426_UNIT;
278 gp->g_mode = cl_mode;
279 gp->g_conpri = grfcl_cnprobe();
280 gp->g_flags = GF_ALIVE;
281
282 /* wakeup the board */
283 cl_boardinit(gp);
284
285 #ifdef CL5426CONSOLE
286 grfcl_iteinit(gp);
287 (void) cl_load_mon(gp, &clconsole_mode);
288 #endif
289
290 }
291
292 /*
293 * attach grf (once)
294 */
295 if (amiga_config_found(cfdata, &gp->g_device, gp, grfclprint)) {
296 attachflag = 1;
297 printf("grfcl: %dMB ", cl_fbsize / 0x100000);
298 switch (cltype) {
299 case PICASSO:
300 printf("Picasso II");
301 cl_maxpixelclock = 86000000;
302 break;
303 case SPECTRUM:
304 printf("Spectrum");
305 cl_maxpixelclock = 90000000;
306 break;
307 case PICCOLO:
308 printf("Piccolo");
309 cl_maxpixelclock = 90000000;
310 break;
311 }
312 printf(" being used\n");
313 #ifdef CL_OVERCLOCK
314 cl_maxpixelclock = 115000000;
315 #endif
316 } else {
317 if (!attachflag)
318 printf("grfcl unattached!!\n");
319 }
320 }
321
322 int
323 grfclprint(auxp, pnp)
324 void *auxp;
325 char *pnp;
326 {
327 if (pnp)
328 printf("ite at %s: ", pnp);
329 return (UNCONF);
330 }
331
332 void
333 cl_boardinit(gp)
334 struct grf_softc *gp;
335 {
336 unsigned char *ba = gp->g_regkva;
337 int x;
338 void *bah;
339
340 /* wakeup board and flip passthru OFF */
341
342 RegWakeup(ba);
343 RegOnpass(ba);
344
345 vgaw(ba, 0x46e8, 0x16);
346 vgaw(ba, 0x102, 1);
347 vgaw(ba, 0x46e8, 0x0e);
348 vgaw(ba, 0x3c3, 1);
349
350 /* setup initial unchanging parameters */
351
352 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); /* 8 dot - display off */
353 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe1); /* mem disable */
354
355 WGfx(ba, GCT_ID_OFFSET_1, 0xec); /* magic cookie */
356 WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x12); /* yum! cookies! */
357
358 WSeq(ba, SEQ_ID_DRAM_CNTL, 0xb0);
359 WSeq(ba, SEQ_ID_RESET, 0x03);
360 WSeq(ba, SEQ_ID_MAP_MASK, 0xff);
361 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
362 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e); /* a or 6? */
363 WSeq(ba, SEQ_ID_EXT_SEQ_MODE, (cltype == PICASSO) ? 0x20 : 0x80);
364 WSeq(ba, SEQ_ID_EEPROM_CNTL, 0x00);
365 WSeq(ba, SEQ_ID_PERF_TUNE, 0x0a); /* mouse 0a fa */
366 WSeq(ba, SEQ_ID_SIG_CNTL, 0x02);
367 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
368
369 WSeq(ba, SEQ_ID_MCLK_SELECT, 0x22);
370
371 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
372 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
373 WCrt(ba, CRT_ID_CURSOR_END, 0x08);
374 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
375 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
376 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
377 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
378
379 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07);
380 WCrt(ba, CRT_ID_MODE_CONTROL, 0xa3); /* c3 */
381 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); /* ff */
382 WCrt(ba, CRT_ID_EXT_DISP_CNTL, 0x22);
383 WSeq(ba, SEQ_ID_CURSOR_STORE, 0x3c); /* mouse 0x00 */
384
385 WGfx(ba, GCT_ID_SET_RESET, 0x00);
386 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
387 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
388 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
389 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
390 WGfx(ba, GCT_ID_MISC, 0x01);
391 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
392 WGfx(ba, GCT_ID_BITMASK, 0xff);
393 WGfx(ba, GCT_ID_MODE_EXT, 0x28);
394
395 for (x = 0; x < 0x10; x++)
396 WAttr(ba, x, x);
397 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
398 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
399 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
400 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
401 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
402
403 delay(200000);
404 WAttr(ba, 0x34, 0x00);
405 delay(200000);
406
407 vgaw(ba, VDAC_MASK, 0xff);
408 delay(200000);
409 vgaw(ba, GREG_MISC_OUTPUT_W, 0xe3); /* c3 */
410
411 WGfx(ba, GCT_ID_BLT_STAT_START, 0x40);
412 WGfx(ba, GCT_ID_BLT_STAT_START, 0x00);
413
414 /* colors initially set to greyscale */
415
416 vgaw(ba, VDAC_ADDRESS_W, 0);
417 for (x = 255; x >= 0; x--) {
418 vgaw(ba, VDAC_DATA, x);
419 vgaw(ba, VDAC_DATA, x);
420 vgaw(ba, VDAC_DATA, x);
421 }
422 /* set sprite bitmap pointers */
423 cl_cursprite.image = cl_imageptr;
424 cl_cursprite.mask = cl_maskptr;
425 cl_cursprite.cmap.red = cl_sprred;
426 cl_cursprite.cmap.green = cl_sprgreen;
427 cl_cursprite.cmap.blue = cl_sprblue;
428 }
429
430
431 int
432 cl_getvmode(gp, vm)
433 struct grf_softc *gp;
434 struct grfvideo_mode *vm;
435 {
436 struct grfvideo_mode *gv;
437
438 #ifdef CL5426CONSOLE
439 /* Handle grabbing console mode */
440 if (vm->mode_num == 255) {
441 bcopy(&clconsole_mode, vm, sizeof(struct grfvideo_mode));
442 /* XXX so grfconfig can tell us the correct text dimensions. */
443 vm->depth = clconsole_mode.fy;
444 } else
445 #endif
446 {
447 if (vm->mode_num == 0)
448 vm->mode_num = (monitor_current - monitor_def) + 1;
449 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
450 return (EINVAL);
451 gv = monitor_def + (vm->mode_num - 1);
452 if (gv->mode_num == 0)
453 return (EINVAL);
454
455 bcopy(gv, vm, sizeof(struct grfvideo_mode));
456 }
457
458 /* adjust internal values to pixel values */
459
460 vm->hblank_start *= 8;
461 vm->hblank_stop *= 8;
462 vm->hsync_start *= 8;
463 vm->hsync_stop *= 8;
464 vm->htotal *= 8;
465
466 return (0);
467 }
468
469
470 int
471 cl_setvmode(gp, mode)
472 struct grf_softc *gp;
473 unsigned mode;
474 {
475 if (!mode || (mode > monitor_def_max) ||
476 monitor_def[mode - 1].mode_num == 0)
477 return (EINVAL);
478
479 monitor_current = monitor_def + (mode - 1);
480
481 return (0);
482 }
483
484 void
485 cl_off(gp)
486 struct grf_softc *gp;
487 {
488 char *ba = gp->g_regkva;
489
490 /* we'll put the pass-through on for cc ite and set Full Bandwidth bit
491 * on just in case it didn't work...but then it doesn't matter does
492 * it? =) */
493 RegOnpass(ba);
494 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21);
495 }
496
497 int
498 cl_blank(gp, on)
499 struct grf_softc *gp;
500 int *on;
501 {
502 WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, *on ? 0x21 : 0x01);
503 return(0);
504 }
505
506 /*
507 * Change the mode of the display.
508 * Return a UNIX error number or 0 for success.
509 */
510 cl_mode(gp, cmd, arg, a2, a3)
511 register struct grf_softc *gp;
512 int cmd;
513 void *arg;
514 int a2, a3;
515 {
516 int error;
517
518 switch (cmd) {
519 case GM_GRFON:
520 error = cl_load_mon(gp,
521 (struct grfcltext_mode *) monitor_current) ? 0 : EINVAL;
522 return (error);
523
524 case GM_GRFOFF:
525 #ifndef CL5426CONSOLE
526 cl_off(gp);
527 #else
528 cl_load_mon(gp, &clconsole_mode);
529 #endif
530 return (0);
531
532 case GM_GRFCONFIG:
533 return (0);
534
535 case GM_GRFGETVMODE:
536 return (cl_getvmode(gp, (struct grfvideo_mode *) arg));
537
538 case GM_GRFSETVMODE:
539 error = cl_setvmode(gp, *(unsigned *) arg);
540 if (!error && (gp->g_flags & GF_GRFON))
541 cl_load_mon(gp,
542 (struct grfcltext_mode *) monitor_current);
543 return (error);
544
545 case GM_GRFGETNUMVM:
546 *(int *) arg = monitor_def_max;
547 return (0);
548
549 case GM_GRFIOCTL:
550 return (cl_ioctl(gp, (int) arg, (caddr_t) a2));
551
552 default:
553 break;
554 }
555
556 return (EINVAL);
557 }
558
559 int
560 cl_ioctl(gp, cmd, data)
561 register struct grf_softc *gp;
562 int cmd;
563 void *data;
564 {
565 switch (cmd) {
566 case GRFIOCGSPRITEPOS:
567 return (cl_getmousepos(gp, (struct grf_position *) data));
568
569 case GRFIOCSSPRITEPOS:
570 return (cl_setmousepos(gp, (struct grf_position *) data));
571
572 case GRFIOCSSPRITEINF:
573 return (cl_setspriteinfo(gp, (struct grf_spriteinfo *) data));
574
575 case GRFIOCGSPRITEINF:
576 return (cl_getspriteinfo(gp, (struct grf_spriteinfo *) data));
577
578 case GRFIOCGSPRITEMAX:
579 return (cl_getspritemax(gp, (struct grf_position *) data));
580
581 case GRFIOCGETCMAP:
582 return (cl_getcmap(gp, (struct grf_colormap *) data));
583
584 case GRFIOCPUTCMAP:
585 return (cl_putcmap(gp, (struct grf_colormap *) data));
586
587 case GRFIOCBITBLT:
588 break;
589
590 case GRFTOGGLE:
591 return (cl_toggle(gp, 0));
592
593 case GRFIOCSETMON:
594 return (cl_setmonitor(gp, (struct grfvideo_mode *) data));
595
596 case GRFIOCBLANK:
597 return (cl_blank(gp, (int *)data));
598
599 }
600 return (EINVAL);
601 }
602
603 int
604 cl_getmousepos(gp, data)
605 struct grf_softc *gp;
606 struct grf_position *data;
607 {
608 data->x = cl_cursprite.pos.x;
609 data->y = cl_cursprite.pos.y;
610 return (0);
611 }
612
613 void
614 cl_writesprpos(ba, x, y)
615 volatile char *ba;
616 short x;
617 short y;
618 {
619 /* we want to use a 16-bit write to 3c4 so no macros used */
620 volatile unsigned char *cwp;
621 volatile unsigned short *wp;
622
623 cwp = ba + 0x3c4;
624 wp = (unsigned short *)cwp;
625
626 /* don't ask me why, but apparently you can't do a 16-bit write with
627 * x-position like with y-position below (dagge) */
628 cwp[0] = 0x10 | ((x << 5) & 0xff);
629 cwp[1] = (x >> 3) & 0xff;
630
631 *wp = 0x1100 | ((y & 7) << 13) | ((y >> 3) & 0xff);
632
633 }
634
635 void
636 writeshifted(to, shiftx, shifty)
637 unsigned char *to;
638 char shiftx;
639 char shifty;
640 {
641 register char y;
642 unsigned long long *tptr, *iptr, *mptr, line;
643
644 tptr = (unsigned long long *) to;
645 iptr = (unsigned long long *) cl_cursprite.image;
646 mptr = (unsigned long long *) cl_cursprite.mask;
647
648 shiftx = shiftx < 0 ? 0 : shiftx;
649 shifty = shifty < 0 ? 0 : shifty;
650
651 /* start reading shifty lines down, and
652 * shift each line in by shiftx
653 */
654 for (y = shifty; y < 64; y++) {
655
656 /* image */
657 line = iptr[y];
658 *tptr++ = line << shiftx;
659
660 /* mask */
661 line = mptr[y];
662 *tptr++ = line << shiftx;
663 }
664
665 /* clear the remainder */
666 for (y = shifty; y > 0; y--) {
667 *tptr++ = 0;
668 *tptr++ = 0;
669 }
670 }
671
672 int
673 cl_setmousepos(gp, data)
674 struct grf_softc *gp;
675 struct grf_position *data;
676 {
677 volatile char *ba = gp->g_regkva;
678 volatile char *fb = gp->g_fbkva;
679 volatile char *sprite = fb + (cl_fbsize - 1024);
680 short rx, ry, prx, pry;
681
682 /* no movement */
683 if (cl_cursprite.pos.x == data->x && cl_cursprite.pos.y == data->y)
684 return (0);
685
686 /* current and previous real coordinates */
687 rx = data->x - cl_cursprite.hot.x;
688 ry = data->y - cl_cursprite.hot.y;
689 prx = cl_cursprite.pos.x - cl_cursprite.hot.x;
690 pry = cl_cursprite.pos.y - cl_cursprite.hot.y;
691
692 /* if we are/were on an edge, create (un)shifted bitmap --
693 * ripped out optimization (not extremely worthwhile,
694 * and kind of buggy anyhow).
695 */
696 #ifdef CL_SHIFTSPRITE
697 if (rx < 0 || ry < 0 || prx < 0 || pry < 0) {
698 writeshifted(sprite, rx < 0 ? -rx : 0, ry < 0 ? -ry : 0);
699 }
700 #endif
701
702 /* do movement, save position */
703 cl_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
704 cl_cursprite.pos.x = data->x;
705 cl_cursprite.pos.y = data->y;
706
707 return (0);
708 }
709
710 int
711 cl_getspriteinfo(gp, data)
712 struct grf_softc *gp;
713 struct grf_spriteinfo *data;
714 {
715 copyout(&cl_cursprite, data, sizeof(struct grf_spriteinfo));
716 copyout(cl_cursprite.image, data->image, 64 * 8);
717 copyout(cl_cursprite.mask, data->mask, 64 * 8);
718 return (0);
719 }
720
721 static
722 int
723 cl_setspriteinfo(gp, data)
724 struct grf_softc *gp;
725 struct grf_spriteinfo *data;
726 {
727 volatile unsigned char *ba = gp->g_regkva, *fb = gp->g_fbkva;
728 volatile char *sprite = fb + (cl_fbsize - 1024);
729
730 if (data->set & GRFSPRSET_SHAPE) {
731
732 short dsx, dsy, i;
733 unsigned long *di, *dm, *si, *sm;
734 unsigned long ssi[128], ssm[128];
735 struct grf_position gpos;
736
737
738 /* check for a too large sprite (no clipping!) */
739 dsy = data->size.y;
740 dsx = data->size.x;
741 if (dsy > 64 || dsx > 64)
742 return(EINVAL);
743
744 /* prepare destination */
745 di = (unsigned long *)cl_cursprite.image;
746 dm = (unsigned long *)cl_cursprite.mask;
747 cl_memset((unsigned char *)di, 0, 8*64);
748 cl_memset((unsigned char *)dm, 0, 8*64);
749
750 /* two alternatives: 64 across, then it's
751 * the same format we use, just copy. Otherwise,
752 * copy into tmp buf and recopy skipping the
753 * unused 32 bits.
754 */
755 if ((dsx - 1) / 32) {
756 copyin(data->image, di, 8 * dsy);
757 copyin(data->mask, dm, 8 * dsy);
758 } else {
759 si = ssi; sm = ssm;
760 copyin(data->image, si, 4 * dsy);
761 copyin(data->mask, sm, 4 * dsy);
762 for (i = 0; i < dsy; i++) {
763 *di = *si++;
764 *dm = *sm++;
765 di += 2;
766 dm += 2;
767 }
768 }
769
770 /* set size */
771 cl_cursprite.size.x = data->size.x;
772 cl_cursprite.size.y = data->size.y;
773
774 /* forcably load into board */
775 gpos.x = cl_cursprite.pos.x;
776 gpos.y = cl_cursprite.pos.y;
777 cl_cursprite.pos.x = -1;
778 cl_cursprite.pos.y = -1;
779 writeshifted(sprite, 0, 0);
780 cl_setmousepos(gp, &gpos);
781
782 }
783 if (data->set & GRFSPRSET_HOT) {
784
785 cl_cursprite.hot = data->hot;
786
787 }
788 if (data->set & GRFSPRSET_CMAP) {
789
790 u_char red[2], green[2], blue[2];
791
792 copyin(data->cmap.red, red, 2);
793 copyin(data->cmap.green, green, 2);
794 copyin(data->cmap.blue, blue, 2);
795 bcopy(red, cl_cursprite.cmap.red, 2);
796 bcopy(green, cl_cursprite.cmap.green, 2);
797 bcopy(blue, cl_cursprite.cmap.blue, 2);
798
799 /* enable and load colors 256 & 257 */
800 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x06);
801
802 /* 256 */
803 vgaw(ba, VDAC_ADDRESS_W, 0x00);
804 if (cltype == PICASSO) {
805 vgaw(ba, VDAC_DATA, (u_char) (red[0] >> 2));
806 vgaw(ba, VDAC_DATA, (u_char) (green[0] >> 2));
807 vgaw(ba, VDAC_DATA, (u_char) (blue[0] >> 2));
808 } else {
809 vgaw(ba, VDAC_DATA, (u_char) (blue[0] >> 2));
810 vgaw(ba, VDAC_DATA, (u_char) (green[0] >> 2));
811 vgaw(ba, VDAC_DATA, (u_char) (red[0] >> 2));
812 }
813
814 /* 257 */
815 vgaw(ba, VDAC_ADDRESS_W, 0x0f);
816 if (cltype == PICASSO) {
817 vgaw(ba, VDAC_DATA, (u_char) (red[1] >> 2));
818 vgaw(ba, VDAC_DATA, (u_char) (green[1] >> 2));
819 vgaw(ba, VDAC_DATA, (u_char) (blue[1] >> 2));
820 } else {
821 vgaw(ba, VDAC_DATA, (u_char) (blue[1] >> 2));
822 vgaw(ba, VDAC_DATA, (u_char) (green[1] >> 2));
823 vgaw(ba, VDAC_DATA, (u_char) (red[1] >> 2));
824 }
825
826 /* turn on/off sprite */
827 if (cl_cursprite.enable) {
828 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x05);
829 } else {
830 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
831 }
832
833 }
834 if (data->set & GRFSPRSET_ENABLE) {
835
836 if (data->enable == 1) {
837 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x05);
838 cl_cursprite.enable = 1;
839 } else {
840 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
841 cl_cursprite.enable = 0;
842 }
843
844 }
845 if (data->set & GRFSPRSET_POS) {
846
847 /* force placement */
848 cl_cursprite.pos.x = -1;
849 cl_cursprite.pos.y = -1;
850
851 /* do it */
852 cl_setmousepos(gp, &data->pos);
853
854 }
855 return (0);
856 }
857
858 static
859 int
860 cl_getspritemax(gp, data)
861 struct grf_softc *gp;
862 struct grf_position *data;
863 {
864 if (gp->g_display.gd_planes == 24)
865 return (EINVAL);
866 data->x = 64;
867 data->y = 64;
868 return (0);
869 }
870
871 int
872 cl_setmonitor(gp, gv)
873 struct grf_softc *gp;
874 struct grfvideo_mode *gv;
875 {
876 struct grfvideo_mode *md;
877
878 if (!cl_mondefok(gv))
879 return(EINVAL);
880
881 #ifdef CL5426CONSOLE
882 /* handle interactive setting of console mode */
883 if (gv->mode_num == 255) {
884 bcopy(gv, &clconsole_mode.gv, sizeof(struct grfvideo_mode));
885 clconsole_mode.gv.hblank_start /= 8;
886 clconsole_mode.gv.hblank_stop /= 8;
887 clconsole_mode.gv.hsync_start /= 8;
888 clconsole_mode.gv.hsync_stop /= 8;
889 clconsole_mode.gv.htotal /= 8;
890 clconsole_mode.rows = gv->disp_height / clconsole_mode.fy;
891 clconsole_mode.cols = gv->disp_width / clconsole_mode.fx;
892 if (!(gp->g_flags & GF_GRFON))
893 cl_load_mon(gp, &clconsole_mode);
894 ite_reinit(gp->g_itedev);
895 return (0);
896 }
897 #endif
898
899 md = monitor_def + (gv->mode_num - 1);
900 bcopy(gv, md, sizeof(struct grfvideo_mode));
901
902 /* adjust pixel oriented values to internal rep. */
903
904 md->hblank_start /= 8;
905 md->hblank_stop /= 8;
906 md->hsync_start /= 8;
907 md->hsync_stop /= 8;
908 md->htotal /= 8;
909
910 return (0);
911 }
912
913 int
914 cl_getcmap(gfp, cmap)
915 struct grf_softc *gfp;
916 struct grf_colormap *cmap;
917 {
918 volatile unsigned char *ba;
919 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
920 short x;
921 int error;
922
923 if (cmap->count == 0 || cmap->index >= 256)
924 return 0;
925
926 if (cmap->index + cmap->count > 256)
927 cmap->count = 256 - cmap->index;
928
929 ba = gfp->g_regkva;
930 /* first read colors out of the chip, then copyout to userspace */
931 vgaw(ba, VDAC_ADDRESS_R, cmap->index);
932 x = cmap->count - 1;
933
934 /* Some sort 'o Magic. Spectrum has some changes on the board to speed
935 * up 15 and 16Bit modes. They can access these modes with easy-to-programm
936 * rgbrgbrgb instead of rrrgggbbb. Side effect: when in 8Bit mode, rgb
937 * is swapped to bgr. I wonder if we need to check for 8Bit though, ill
938 */
939
940 switch (cltype) {
941 case SPECTRUM:
942 case PICCOLO:
943 rp = blue + cmap->index;
944 gp = green + cmap->index;
945 bp = red + cmap->index;
946 break;
947 case PICASSO:
948 rp = red + cmap->index;
949 gp = green + cmap->index;
950 bp = blue + cmap->index;
951 break;
952 }
953
954 do {
955 *rp++ = vgar(ba, VDAC_DATA) << 2;
956 *gp++ = vgar(ba, VDAC_DATA) << 2;
957 *bp++ = vgar(ba, VDAC_DATA) << 2;
958 } while (x-- > 0);
959
960 if (!(error = copyout(red + cmap->index, cmap->red, cmap->count))
961 && !(error = copyout(green + cmap->index, cmap->green, cmap->count))
962 && !(error = copyout(blue + cmap->index, cmap->blue, cmap->count)))
963 return (0);
964
965 return (error);
966 }
967
968 int
969 cl_putcmap(gfp, cmap)
970 struct grf_softc *gfp;
971 struct grf_colormap *cmap;
972 {
973 volatile unsigned char *ba;
974 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
975 short x;
976 int error;
977
978 if (cmap->count == 0 || cmap->index >= 256)
979 return (0);
980
981 if (cmap->index + cmap->count > 256)
982 cmap->count = 256 - cmap->index;
983
984 /* first copy the colors into kernelspace */
985 if (!(error = copyin(cmap->red, red + cmap->index, cmap->count))
986 && !(error = copyin(cmap->green, green + cmap->index, cmap->count))
987 && !(error = copyin(cmap->blue, blue + cmap->index, cmap->count))) {
988 ba = gfp->g_regkva;
989 vgaw(ba, VDAC_ADDRESS_W, cmap->index);
990 x = cmap->count - 1;
991
992 switch (cltype) {
993 case SPECTRUM:
994 case PICCOLO:
995 rp = blue + cmap->index;
996 gp = green + cmap->index;
997 bp = red + cmap->index;
998 break;
999 case PICASSO:
1000 rp = red + cmap->index;
1001 gp = green + cmap->index;
1002 bp = blue + cmap->index;
1003 break;
1004 }
1005
1006 do {
1007 vgaw(ba, VDAC_DATA, *rp++ >> 2);
1008 vgaw(ba, VDAC_DATA, *gp++ >> 2);
1009 vgaw(ba, VDAC_DATA, *bp++ >> 2);
1010 } while (x-- > 0);
1011 return (0);
1012 } else
1013 return (error);
1014 }
1015
1016
1017 int
1018 cl_toggle(gp, wopp)
1019 struct grf_softc *gp;
1020 unsigned short wopp; /* don't need that one yet, ill */
1021 {
1022 volatile unsigned char *ba;
1023
1024 ba = gp->g_regkva;
1025
1026 if (pass_toggle) {
1027 RegOffpass(ba);
1028 } else {
1029 /* This was in the original.. is it needed? */
1030 if (cltype == PICASSO || cltype == PICCOLO)
1031 RegWakeup(ba);
1032 RegOnpass(ba);
1033 }
1034 return (0);
1035 }
1036
1037 static void
1038 CompFQ(fq, num, denom)
1039 u_int fq;
1040 u_char *num;
1041 u_char *denom;
1042 {
1043 #define OSC 14318180
1044 /* OK, here's what we're doing here:
1045 *
1046 * OSC * NUMERATOR
1047 * VCLK = ------------------- Hz
1048 * DENOMINATOR * (1+P)
1049 *
1050 * so we're given VCLK and we should give out some useful
1051 * values....
1052 *
1053 * NUMERATOR is 7 bits wide
1054 * DENOMINATOR is 5 bits wide with bit P in the same char as bit 0.
1055 *
1056 * We run through all the possible combinations and
1057 * return the values which deviate the least from the chosen frequency.
1058 *
1059 */
1060 #define OSC 14318180
1061 #define count(n,d,p) ((OSC * n)/(d * (1+p)))
1062
1063 unsigned char n, d, p, minn, mind, minp;
1064 unsigned long err, minerr;
1065
1066 /*
1067 numer = 0x00 - 0x7f
1068 denom = 0x00 - 0x1f (1) 0x20 - 0x3e (even)
1069 */
1070
1071 /* find lowest error in 6144 iterations. */
1072 minerr = fq;
1073 minn = 0;
1074 mind = 0;
1075 p = 0;
1076
1077 for (d = 1; d < 0x20; d++) {
1078 for (n = 1; n < 0x80; n++) {
1079 err = abs(count(n, d, p) - fq);
1080 if (err < minerr) {
1081 minerr = err;
1082 minn = n;
1083 mind = d;
1084 minp = p;
1085 }
1086 }
1087 if (d == 0x1f && p == 0) {
1088 p = 1;
1089 d = 0x0f;
1090 }
1091 }
1092
1093 *num = minn;
1094 *denom = (mind << 1) | minp;
1095 if (minerr > 500000)
1096 printf("Warning: CompFQ minimum error = %d\n", minerr);
1097 return;
1098 }
1099
1100 int
1101 cl_mondefok(gv)
1102 struct grfvideo_mode *gv;
1103 {
1104 unsigned long maxpix;
1105
1106 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
1107 if (gv->mode_num != 255 || gv->depth != 4)
1108 return(0);
1109
1110 switch (gv->depth) {
1111 case 4:
1112 if (gv->mode_num != 255)
1113 return(0);
1114 case 1:
1115 case 8:
1116 maxpix = cl_maxpixelclock;
1117 break;
1118 case 15:
1119 case 16:
1120 maxpix = cl_maxpixelclock - (cl_maxpixelclock / 3);
1121 break;
1122 case 24:
1123 maxpix = cl_maxpixelclock / 3;
1124 break;
1125 default:
1126 return (0);
1127 }
1128 if (gv->pixel_clock > maxpix)
1129 return (0);
1130 return (1);
1131 }
1132
1133 int
1134 cl_load_mon(gp, md)
1135 struct grf_softc *gp;
1136 struct grfcltext_mode *md;
1137 {
1138 struct grfvideo_mode *gv;
1139 struct grfinfo *gi;
1140 volatile unsigned char *ba;
1141 volatile unsigned char *fb;
1142 unsigned char num0, denom0;
1143 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1144 VSE, VT;
1145 char LACE, DBLSCAN, TEXT;
1146 unsigned short clkdiv, clksel;
1147 int uplim, lowlim;
1148
1149 /* identity */
1150 gv = &md->gv;
1151 TEXT = (gv->depth == 4);
1152
1153 if (!cl_mondefok(gv)) {
1154 printf("mondef not ok\n");
1155 return (0);
1156 }
1157 ba = gp->g_regkva;
1158 fb = gp->g_fbkva;
1159
1160 /* provide all needed information in grf device-independant locations */
1161 gp->g_data = (caddr_t) gv;
1162 gi = &gp->g_display;
1163 gi->gd_regaddr = (caddr_t) ztwopa(ba);
1164 gi->gd_regsize = 64 * 1024;
1165 gi->gd_fbaddr = (caddr_t) kvtop(fb);
1166 gi->gd_fbsize = cl_fbsize;
1167 gi->gd_colors = 1 << gv->depth;
1168 gi->gd_planes = gv->depth;
1169 gi->gd_fbwidth = gv->disp_width;
1170 gi->gd_fbheight = gv->disp_height;
1171 gi->gd_fbx = 0;
1172 gi->gd_fby = 0;
1173 if (TEXT) {
1174 gi->gd_dwidth = md->fx * md->cols;
1175 gi->gd_dheight = md->fy * md->rows;
1176 } else {
1177 gi->gd_dwidth = gv->disp_width;
1178 gi->gd_dheight = gv->disp_height;
1179 }
1180 gi->gd_dx = 0;
1181 gi->gd_dy = 0;
1182
1183 /* get display mode parameters */
1184
1185 HBS = gv->hblank_start;
1186 HBE = gv->hblank_stop;
1187 HSS = gv->hsync_start;
1188 HSE = gv->hsync_stop;
1189 HT = gv->htotal;
1190 VBS = gv->vblank_start;
1191 VSS = gv->vsync_start;
1192 VSE = gv->vsync_stop;
1193 VBE = gv->vblank_stop;
1194 VT = gv->vtotal;
1195
1196 if (TEXT)
1197 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1198 else
1199 HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */
1200 VDE = gv->disp_height - 1;
1201
1202 /* figure out whether lace or dblscan is needed */
1203
1204 uplim = gv->disp_height + (gv->disp_height / 4);
1205 lowlim = gv->disp_height - (gv->disp_height / 4);
1206 LACE = (((VT * 2) > lowlim) && ((VT * 2) < uplim)) ? 1 : 0;
1207 DBLSCAN = (((VT / 2) > lowlim) && ((VT / 2) < uplim)) ? 1 : 0;
1208
1209 /* adjustments */
1210
1211 if (LACE)
1212 VDE /= 2;
1213
1214 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1215 WSeq(ba, SEQ_ID_DRAM_CNTL, (TEXT || (gv->depth == 1)) ? 0x90 : 0xb0);
1216 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1217 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1218 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1219
1220 /* Set clock */
1221
1222 CompFQ((gv->depth == 24) ? gv->pixel_clock * 3 : gv->pixel_clock,
1223 &num0, &denom0);
1224 WSeq(ba, SEQ_ID_VCLK_0_NUM, num0);
1225 WSeq(ba, SEQ_ID_VCLK_0_DENOM, denom0);
1226
1227 /* load display parameters into board */
1228
1229 WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1230 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
1231 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1232 WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); /* | 0x80? */
1233 WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1234 WCrt(ba, CRT_ID_END_HOR_RETR,
1235 (HSE & 0x1f) |
1236 ((HBE & 0x20) ? 0x80 : 0x00));
1237 WCrt(ba, CRT_ID_VER_TOTAL, VT);
1238 WCrt(ba, CRT_ID_OVERFLOW,
1239 0x10 |
1240 ((VT & 0x100) ? 0x01 : 0x00) |
1241 ((VDE & 0x100) ? 0x02 : 0x00) |
1242 ((VSS & 0x100) ? 0x04 : 0x00) |
1243 ((VBS & 0x100) ? 0x08 : 0x00) |
1244 ((VT & 0x200) ? 0x20 : 0x00) |
1245 ((VDE & 0x200) ? 0x40 : 0x00) |
1246 ((VSS & 0x200) ? 0x80 : 0x00));
1247
1248
1249 WCrt(ba, CRT_ID_CHAR_HEIGHT,
1250 0x40 | /* TEXT ? 0x00 ??? */
1251 (DBLSCAN ? 0x80 : 0x00) |
1252 ((VBS & 0x200) ? 0x20 : 0x00) |
1253 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1254 WCrt(ba, CRT_ID_MODE_CONTROL,
1255 ((TEXT || (gv->depth == 1)) ? 0xc3 : 0xa3));
1256
1257 /* text cursor */
1258
1259 if (TEXT) {
1260 #if CL_ULCURSOR
1261 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1262 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1263 #else
1264 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1265 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1266 #endif
1267 WCrt(ba, CRT_ID_UNDERLINE_LOC, md->fy - 1 & 0x1f);
1268
1269 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1270 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1271 }
1272 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1273 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1274
1275 WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1276 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x30);
1277 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1278 WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1279 WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1280
1281 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1282 WCrt(ba, CRT_ID_LACE_END, HT / 2); /* MW/16 */
1283 WCrt(ba, CRT_ID_LACE_CNTL,
1284 (LACE ? 0x01 : 0x00) |
1285 ((HBE & 0x40) ? 0x10 : 0x00) |
1286 ((HBE & 0x80) ? 0x20 : 0x00) |
1287 ((VBE & 0x100) ? 0x40 : 0x00) |
1288 ((VBE & 0x200) ? 0x80 : 0x00));
1289
1290 /* depth dependent stuff */
1291
1292 switch (gv->depth) {
1293 case 1:
1294 case 4:
1295 case 8:
1296 clkdiv = 0;
1297 break;
1298 case 15:
1299 case 16:
1300 clkdiv = 3;
1301 break;
1302 case 24:
1303 clkdiv = 2;
1304 break;
1305 }
1306
1307 WGfx(ba, GCT_ID_GRAPHICS_MODE,
1308 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1309 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1310
1311 WSeq(ba, SEQ_ID_EXT_SEQ_MODE,
1312 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x01) |
1313 ((cltype == PICASSO) ? 0x20 : 0x80) |
1314 (clkdiv << 1));
1315
1316 delay(200000);
1317
1318 /* write 0x00 to VDAC_MASK before accessing HDR this helps
1319 sometimes, out of "secret" application note (crest) */
1320 vgaw(ba, VDAC_MASK, 0);
1321 delay(200000);
1322 /* reset HDR "magic" access counter (crest) */
1323 vgar(ba, VDAC_ADDRESS);
1324
1325 delay(200000);
1326 vgar(ba, VDAC_MASK);
1327 delay(200000);
1328 vgar(ba, VDAC_MASK);
1329 delay(200000);
1330 vgar(ba, VDAC_MASK);
1331 delay(200000);
1332 vgar(ba, VDAC_MASK);
1333 delay(200000);
1334 switch (gv->depth) {
1335 case 1:
1336 case 4: /* text */
1337 vgaw(ba, VDAC_MASK, 0);
1338 HDE = gv->disp_width / 16;
1339 break;
1340 case 8:
1341 vgaw(ba, VDAC_MASK, 0);
1342 HDE = gv->disp_width / 8;
1343 break;
1344 case 15:
1345 vgaw(ba, VDAC_MASK, 0xd0);
1346 HDE = gv->disp_width / 4;
1347 break;
1348 case 16:
1349 vgaw(ba, VDAC_MASK, 0xc1);
1350 HDE = gv->disp_width / 4;
1351 break;
1352 case 24:
1353 vgaw(ba, VDAC_MASK, 0xc5);
1354 HDE = (gv->disp_width / 8) * 3;
1355 break;
1356 }
1357 delay(20000);
1358
1359 /* reset HDR "magic" access counter (crest) */
1360 vgar(ba, VDAC_ADDRESS);
1361 delay(200000);
1362 /* then enable all bit in VDAC_MASK afterwards (crest) */
1363 vgaw(ba, VDAC_MASK, 0xff);
1364 delay(20000);
1365
1366 WCrt(ba, CRT_ID_OFFSET, HDE);
1367 WCrt(ba, CRT_ID_EXT_DISP_CNTL,
1368 ((TEXT && gv->pixel_clock > 29000000) ? 0x40 : 0x00) |
1369 0x22 |
1370 ((HDE > 0xff) ? 0x10 : 0x00)); /* text? */
1371
1372 delay(200000);
1373 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
1374 delay(200000);
1375 WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
1376 (gv->depth == 1) ? 0x01 : 0x0f);
1377 delay(200000);
1378
1379 /* text initialization */
1380
1381 if (TEXT) {
1382 cl_inittextmode(gp);
1383 }
1384 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x14);
1385 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
1386
1387 /* Pass-through */
1388
1389 RegOffpass(ba);
1390
1391 return (1);
1392 }
1393
1394 void
1395 cl_inittextmode(gp)
1396 struct grf_softc *gp;
1397 {
1398 struct grfcltext_mode *tm = (struct grfcltext_mode *) gp->g_data;
1399 volatile unsigned char *ba = gp->g_regkva;
1400 unsigned char *fb = gp->g_fbkva;
1401 unsigned char *c, *f, y;
1402 unsigned short z;
1403
1404
1405 /* load text font into beginning of display memory. Each character
1406 * cell is 32 bytes long (enough for 4 planes) */
1407
1408 SetTextPlane(ba, 0x02);
1409 cl_memset(fb, 0, 256 * 32);
1410 c = (unsigned char *) (fb) + (32 * tm->fdstart);
1411 f = tm->fdata;
1412 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
1413 for (y = 0; y < tm->fy; y++)
1414 *c++ = *f++;
1415
1416 /* clear out text/attr planes (three screens worth) */
1417
1418 SetTextPlane(ba, 0x01);
1419 cl_memset(fb, 0x07, tm->cols * tm->rows * 3);
1420 SetTextPlane(ba, 0x00);
1421 cl_memset(fb, 0x20, tm->cols * tm->rows * 3);
1422
1423 /* print out a little init msg */
1424
1425 c = (unsigned char *) (fb) + (tm->cols - 16);
1426 strcpy(c, "CIRRUS");
1427 c[6] = 0x20;
1428
1429 /* set colors (B&W) */
1430
1431
1432 vgaw(ba, VDAC_ADDRESS_W, 0);
1433 for (z = 0; z < 256; z++) {
1434 unsigned char r, g, b;
1435
1436 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1437
1438 if (cltype == PICASSO) {
1439 r = clconscolors[y][0];
1440 g = clconscolors[y][1];
1441 b = clconscolors[y][2];
1442 } else {
1443 b = clconscolors[y][0];
1444 g = clconscolors[y][1];
1445 r = clconscolors[y][2];
1446 }
1447 vgaw(ba, VDAC_DATA, r >> 2);
1448 vgaw(ba, VDAC_DATA, g >> 2);
1449 vgaw(ba, VDAC_DATA, b >> 2);
1450 }
1451 }
1452
1453 void
1454 cl_memset(d, c, l)
1455 unsigned char *d;
1456 unsigned char c;
1457 int l;
1458 {
1459 for (; l > 0; l--)
1460 *d++ = c;
1461 }
1462 #endif /* NGRFCL */
1463