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