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