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