grf_cl.c revision 1.49.6.1 1 /* $NetBSD: grf_cl.c,v 1.49.6.1 2015/12/27 12:09:28 skrll Exp $ */
2
3 /*
4 * Copyright (c) 1997 Klaus Burkert
5 * Copyright (c) 1995 Ezra Story
6 * Copyright (c) 1995 Kari Mettinen
7 * Copyright (c) 1994 Markus Wild
8 * Copyright (c) 1994 Lutz Vieweg
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Lutz Vieweg.
22 * 4. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36 #include "opt_amigacons.h"
37
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: grf_cl.c,v 1.49.6.1 2015/12/27 12:09:28 skrll Exp $");
40
41 #include "grfcl.h"
42 #include "ite.h"
43 #include "wsdisplay.h"
44 #if NGRFCL > 0
45
46 /*
47 * Graphics routines for Cirrus CL GD 5426 boards,
48 *
49 * This code offers low-level routines to access Cirrus Cl GD 5426
50 * graphics-boards from within NetBSD for the Amiga.
51 * No warranties for any kind of function at all - this
52 * code may crash your hardware and scratch your harddisk. Use at your
53 * own risk. Freely distributable.
54 *
55 * Modified for Cirrus CL GD 5426 from
56 * Lutz Vieweg's retina driver by Kari Mettinen 08/94
57 * Contributions by Ill, ScottE, MiL
58 * Extensively hacked and rewritten by Ezra Story (Ezy) 01/95
59 * Picasso/040 patches (wee!) by crest 01/96
60 *
61 * PicassoIV support bz Klaus "crest" Burkert.
62 * Fixed interlace and doublescan, added clockdoubling and
63 * HiColor&TrueColor suuport by crest 01/97
64 *
65 * Thanks to Village Tronic Marketing Gmbh for providing me with
66 * a Picasso-II board.
67 * Thanks for Integrated Electronics Oy Ab for providing me with
68 * Cirrus CL GD 542x family documentation.
69 *
70 * TODO:
71 * Mouse support (almost there! :-))
72 * Blitter support
73 *
74 */
75
76 #include <sys/param.h>
77 #include <sys/systm.h>
78 #include <sys/errno.h>
79 #include <sys/ioctl.h>
80 #include <sys/device.h>
81 #include <sys/malloc.h>
82
83 #include <machine/cpu.h>
84 #include <dev/cons.h>
85 #if NWSDISPLAY > 0
86 #include <dev/wscons/wsconsio.h>
87 #include <dev/wscons/wsdisplayvar.h>
88 #include <dev/rasops/rasops.h>
89 #include <dev/wscons/wsdisplay_vconsvar.h>
90 #endif
91 #include <amiga/dev/itevar.h>
92 #include <amiga/amiga/device.h>
93 #include <amiga/dev/grfioctl.h>
94 #include <amiga/dev/grfvar.h>
95 #include <amiga/dev/grf_clreg.h>
96 #include <amiga/dev/zbusvar.h>
97
98 int cl_mondefok(struct grfvideo_mode *);
99 void cl_boardinit(struct grf_softc *);
100 static void cl_CompFQ(u_int, u_char *, u_char *, u_char *);
101 int cl_getvmode(struct grf_softc *, struct grfvideo_mode *);
102 int cl_setvmode(struct grf_softc *, unsigned int);
103 int cl_toggle(struct grf_softc *, unsigned short);
104 int cl_getcmap(struct grf_softc *, struct grf_colormap *);
105 int cl_putcmap(struct grf_softc *, struct grf_colormap *);
106 #ifndef CL5426CONSOLE
107 void cl_off(struct grf_softc *);
108 #endif
109 void cl_inittextmode(struct grf_softc *);
110 int cl_ioctl(register struct grf_softc *, u_long, void *);
111 int cl_getmousepos(struct grf_softc *, struct grf_position *);
112 int cl_setmousepos(struct grf_softc *, struct grf_position *);
113 static int cl_setspriteinfo(struct grf_softc *, struct grf_spriteinfo *);
114 int cl_getspriteinfo(struct grf_softc *, struct grf_spriteinfo *);
115 static int cl_getspritemax(struct grf_softc *, struct grf_position *);
116 int cl_blank(struct grf_softc *, int);
117 int cl_isblank(struct grf_softc *);
118 int cl_setmonitor(struct grf_softc *, struct grfvideo_mode *);
119 void cl_writesprpos(volatile char *, short, short);
120 void writeshifted(volatile char *, signed char, signed char);
121
122 static void RegWakeup(volatile void *);
123 static void RegOnpass(volatile void *);
124 static void RegOffpass(volatile void *);
125
126 void grfclattach(device_t, device_t, void *);
127 int grfclprint(void *, const char *);
128 int grfclmatch(device_t, cfdata_t, void *);
129 void cl_memset(unsigned char *, unsigned char, int);
130
131 #if NWSDISPLAY > 0
132 /* wsdisplay acessops, emulops */
133 static int cl_wsioctl(void *, void *, u_long, void *, int, struct lwp *);
134 static int cl_get_fbinfo(struct grf_softc *, struct wsdisplayio_fbinfo *);
135
136 static void cl_wscursor(void *, int, int, int);
137 static void cl_wsputchar(void *, int, int, u_int, long);
138 static void cl_wscopycols(void *, int, int, int, int);
139 static void cl_wserasecols(void *, int, int, int, long);
140 static void cl_wscopyrows(void *, int, int, int);
141 static void cl_wseraserows(void *, int, int, long);
142 static int cl_wsallocattr(void *, int, int, int, long *);
143 static int cl_wsmapchar(void *, int, unsigned int *);
144 #endif /* NWSDISPLAY > 0 */
145
146 /* Graphics display definitions.
147 * These are filled by 'grfconfig' using GRFIOCSETMON.
148 */
149 #define monitor_def_max 24
150 static struct grfvideo_mode monitor_def[24] = {
151 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
152 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
153 {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}
154 };
155 static struct grfvideo_mode *monitor_current = &monitor_def[0];
156
157 /* Patchable maximum pixel clock */
158 unsigned long cl_maxpixelclock = 86000000;
159
160 /* Console display definition.
161 * Default hardcoded text mode. This grf_cl is set up to
162 * use one text mode only, and this is it. You may use
163 * grfconfig to change the mode after boot.
164 */
165 /* Console font */
166 #ifdef KFONT_8X11
167 #define CIRRUSFONT kernel_font_8x11
168 #define CIRRUSFONTY 11
169 #else
170 #define CIRRUSFONT kernel_font_8x8
171 #define CIRRUSFONTY 8
172 #endif
173 extern unsigned char CIRRUSFONT[];
174
175 struct grfcltext_mode clconsole_mode = {
176 {255, "", 25000000, 640, 480, 4, 640/8, 680/8, 768/8, 800/8,
177 481, 490, 498, 522, 0},
178 8, CIRRUSFONTY, 80, 480 / CIRRUSFONTY, CIRRUSFONT, 32, 255
179 };
180 /* Console colors */
181 unsigned char clconscolors[3][3] = { /* background, foreground, hilite */
182 {0, 0x40, 0x50}, {152, 152, 152}, {255, 255, 255}
183 };
184
185 int cltype = 0; /* Picasso, Spectrum or Piccolo */
186 int cl_64bit = 0; /* PiccoloSD64 or PicassoIV */
187 unsigned char cl_pass_toggle; /* passthru status tracker */
188 static int cl_blanked; /* true when video is currently blanked out */
189
190 /*
191 * because all 542x-boards have 2 configdev entries, one for
192 * framebuffer mem and the other for regs, we have to hold onto
193 * the pointers globally until we match on both. This and 'cltype'
194 * are the primary obsticles to multiple board support, but if you
195 * have multiple boards you have bigger problems than grf_cl.
196 */
197 static void *cl_fbaddr = 0; /* framebuffer */
198 static void *cl_regaddr = 0; /* registers */
199 static int cl_fbsize; /* framebuffer size */
200 static int cl_fbautosize; /* framebuffer autoconfig size */
201
202
203 /*
204 * current sprite info, if you add support for multiple boards
205 * make this an array or something
206 */
207 struct grf_spriteinfo cl_cursprite;
208
209 /* sprite bitmaps in kernel stack, you'll need to arrayize these too if
210 * you add multiple board support
211 */
212 static unsigned char cl_imageptr[8 * 64], cl_maskptr[8 * 64];
213 static unsigned char cl_sprred[2], cl_sprgreen[2], cl_sprblue[2];
214
215 #if NWSDISPLAY > 0
216 static struct wsdisplay_accessops cl_accessops = {
217 .ioctl = cl_wsioctl,
218 .mmap = grf_wsmmap
219 };
220
221 static struct wsdisplay_emulops cl_textops = {
222 .cursor = cl_wscursor,
223 .mapchar = cl_wsmapchar,
224 .putchar = cl_wsputchar,
225 .copycols = cl_wscopycols,
226 .erasecols = cl_wserasecols,
227 .copyrows = cl_wscopyrows,
228 .eraserows = cl_wseraserows,
229 .allocattr = cl_wsallocattr
230 };
231
232 static struct wsscreen_descr cl_defaultscreen = {
233 .name = "default",
234 .textops = &cl_textops,
235 .fontwidth = 8,
236 .fontheight = CIRRUSFONTY,
237 .capabilities = WSSCREEN_HILIT | WSSCREEN_BLINK |
238 WSSCREEN_REVERSE | WSSCREEN_UNDERLINE
239 };
240
241 static const struct wsscreen_descr *cl_screens[] = {
242 &cl_defaultscreen,
243 };
244
245 static struct wsscreen_list cl_screenlist = {
246 sizeof(cl_screens) / sizeof(struct wsscreen_descr *), cl_screens
247 };
248 #endif /* NWSDISPLAY > 0 */
249
250 /* standard driver stuff */
251 CFATTACH_DECL_NEW(grfcl, sizeof(struct grf_softc),
252 grfclmatch, grfclattach, NULL, NULL);
253
254 static struct cfdata *cfdata;
255
256 int
257 grfclmatch(device_t parent, cfdata_t cf, void *aux)
258 {
259 struct zbus_args *zap;
260 static int regprod, fbprod;
261 int error;
262
263 zap = aux;
264
265 #ifndef CL5426CONSOLE
266 if (amiga_realconfig == 0)
267 return (0);
268 #endif
269
270 /* Grab the first board we encounter as the preferred one. This will
271 * allow one board to work in a multiple 5426 board system, but not
272 * multiple boards at the same time. */
273 if (cltype == 0) {
274 switch (zap->manid) {
275 case PICASSO:
276 switch (zap->prodid) {
277 case 11:
278 case 12:
279 regprod = 12;
280 fbprod = 11;
281 error = 0;
282 break;
283 case 22:
284 error = 0;
285 break;
286 case 21:
287 case 23:
288 regprod = 23;
289 fbprod = 21;
290 cl_64bit = 1;
291 error = 0;
292 break;
293 case 24:
294 regprod = 24;
295 fbprod = 24;
296 cl_64bit = 1;
297 error = 0;
298 break;
299 default:
300 error = 1;
301 break;
302 }
303 if (error == 1)
304 return (0);
305 else
306 break;
307 case SPECTRUM:
308 if (zap->prodid != 2 && zap->prodid != 1)
309 return (0);
310 regprod = 2;
311 fbprod = 1;
312 break;
313 case PICCOLO:
314 switch (zap->prodid) {
315 case 5:
316 case 6:
317 regprod = 6;
318 fbprod = 5;
319 error = 0;
320 break;
321 case 10:
322 case 11:
323 regprod = 11;
324 fbprod = 10;
325 cl_64bit = 1;
326 error = 0;
327 break;
328 default:
329 error = 1;
330 break;
331 }
332 if (error == 1)
333 return (0);
334 else
335 break;
336 default:
337 return (0);
338 }
339 cltype = zap->manid;
340 } else {
341 if (cltype != zap->manid) {
342 return (0);
343 }
344 }
345
346 /* Configure either registers or framebuffer in any order */
347 if ((cltype == PICASSO) && (cl_64bit == 1)) {
348 switch (zap->prodid) {
349 case 21:
350 cl_fbaddr = zap->va;
351 cl_fbautosize = zap->size;
352 break;
353 case 22:
354 cl_fbautosize += zap->size;
355 break;
356 case 23:
357 cl_regaddr = (void *)((unsigned long)(zap->va) + 0x10000);
358 break;
359 case 24:
360 cl_regaddr = (void *)((unsigned long)(zap->va) + 0x600000);
361 /* check for PicassoIV with 64MB config and handle it */
362 if (zap->size == 0x04000000) {
363 cl_fbaddr = (void *)((unsigned long)(zap->va) + 0x02000000);
364 } else {
365 cl_fbaddr = (void *)((unsigned long)(zap->va) + 0x01000000);
366 }
367 cl_fbautosize = 0x400000;
368 break;
369 default:
370 return (0);
371 }
372 }
373 else {
374 if (zap->prodid == regprod)
375 cl_regaddr = zap->va;
376 else
377 if (zap->prodid == fbprod) {
378 cl_fbaddr = zap->va;
379 cl_fbautosize = zap->size;
380 } else
381 return (0);
382 }
383
384 #ifdef CL5426CONSOLE
385 if (amiga_realconfig == 0) {
386 cfdata = cf;
387 }
388 #endif
389
390 return (1);
391 }
392
393 void
394 grfclattach(device_t parent, device_t self, void *aux)
395 {
396 static struct grf_softc congrf;
397 struct zbus_args *zap;
398 struct grf_softc *gp;
399 struct device temp;
400 static char attachflag = 0;
401
402 zap = aux;
403
404 printf("\n");
405
406 /* make sure both halves have matched */
407 if (!cl_regaddr || !cl_fbaddr)
408 return;
409
410 /* do all that messy console/grf stuff */
411 if (self == NULL) {
412 gp = &congrf;
413 gp->g_device = &temp;
414 temp.dv_private = gp;
415 } else {
416 gp = device_private(self);
417 gp->g_device = self;
418 }
419
420 if (self != NULL && congrf.g_regkva != 0) {
421 /*
422 * inited earlier, just copy (not device struct)
423 */
424 memcpy(&gp->g_display, &congrf.g_display,
425 (char *) &gp[1] - (char *) &gp->g_display);
426 } else {
427 gp->g_regkva = (volatile void *) cl_regaddr;
428 gp->g_fbkva = (volatile void *) cl_fbaddr;
429
430 gp->g_unit = GRF_CL5426_UNIT;
431 gp->g_mode = cl_mode;
432 #if NITE > 0
433 gp->g_conpri = grfcl_cnprobe();
434 #endif
435 gp->g_flags = GF_ALIVE;
436
437 /* wakeup the board */
438 cl_boardinit(gp);
439
440 #ifdef CL5426CONSOLE
441 #if NWSDISPLAY > 0
442 gp->g_accessops = &cl_accessops;
443 gp->g_emulops = &cl_textops;
444 gp->g_defaultscr = &cl_defaultscreen;
445 gp->g_scrlist = &cl_screenlist;
446 #else
447 #if NITE > 0
448 grfcl_iteinit(gp);
449 #endif
450 #endif /* NWSDISPLAY > 0 */
451 (void) cl_load_mon(gp, &clconsole_mode);
452 #endif
453 }
454
455 /*
456 * attach grf (once)
457 */
458 if (amiga_config_found(cfdata, gp->g_device, gp, grfclprint)) {
459 attachflag = 1;
460 printf("grfcl: %dMB ", cl_fbsize / 0x100000);
461 switch (cltype) {
462 case PICASSO:
463 if (cl_64bit == 1) {
464 printf("Picasso IV");
465 /* 135MHz will be supported if we
466 * have a palette doubling mode.
467 */
468 cl_maxpixelclock = 86000000;
469 }
470 else {
471 printf("Picasso II");
472
473 /* check for PicassoII+ (crest) */
474 if(zap->serno == 0x00100000)
475 printf("+");
476
477 /* determine used Gfx/chipset (crest) */
478 vgaw(gp->g_regkva, CRT_ADDRESS, 0x27); /* Chip ID */
479 switch(vgar(gp->g_regkva, CRT_ADDRESS_R)>>2) {
480 case 0x24:
481 printf(" (with CL-GD5426)");
482 break;
483 case 0x26:
484 printf(" (with CL-GD5428)");
485 break;
486 case 0x27:
487 printf(" (with CL-GD5429)");
488 break;
489 }
490 cl_maxpixelclock = 86000000;
491 }
492 break;
493 case SPECTRUM:
494 printf("Spectrum");
495 cl_maxpixelclock = 90000000;
496 break;
497 case PICCOLO:
498 if (cl_64bit == 1) {
499 printf("Piccolo SD64");
500 /* 110MHz will be supported if we
501 * have a palette doubling mode.
502 */
503 cl_maxpixelclock = 90000000;
504 } else {
505 printf("Piccolo");
506 cl_maxpixelclock = 90000000;
507 }
508 break;
509 }
510 printf(" being used\n");
511 #ifdef CL_OVERCLOCK
512 cl_maxpixelclock = 115000000;
513 #endif
514 } else {
515 if (!attachflag)
516 printf("grfcl unattached!!\n");
517 }
518 }
519
520 int
521 grfclprint(void *aux, const char *pnp)
522 {
523 if (pnp)
524 aprint_normal("ite at %s: ", pnp);
525 return (UNCONF);
526 }
527
528 void
529 cl_boardinit(struct grf_softc *gp)
530 {
531 volatile unsigned char *ba = gp->g_regkva;
532 int x;
533
534 if ((cltype == PICASSO) && (cl_64bit == 1)) { /* PicassoIV */
535 WCrt(ba, 0x51, 0x00); /* disable capture (FlickerFixer) */
536 delay(200000); /* wait some time (two frames as of now) */
537 WGfx(ba, 0x2f, 0x00); /* get Blitter into 542x */
538 WGfx(ba, GCT_ID_RESERVED, 0x00); /* compatibility mode */
539 WGfx(ba, GCT_ID_BLT_STAT_START, 0x00); /* or at least, try so... */
540 cl_fbsize = cl_fbautosize;
541 } else {
542
543 /* wakeup board and flip passthru OFF */
544 RegWakeup(ba);
545 RegOnpass(ba);
546
547 vgaw(ba, 0x46e8, 0x16);
548 vgaw(ba, 0x102, 1);
549 vgaw(ba, 0x46e8, 0x0e);
550 if (cl_64bit != 1)
551 vgaw(ba, 0x3c3, 1);
552
553 cl_fbsize = cl_fbautosize;
554
555 /* setup initial unchanging parameters */
556
557 cl_blanked = 1;
558 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x21); /* 8 dot - display off */
559 vgaw(ba, GREG_MISC_OUTPUT_W, 0xed); /* mem disable */
560
561 WGfx(ba, GCT_ID_OFFSET_1, 0xec); /* magic cookie */
562 WSeq(ba, SEQ_ID_UNLOCK_EXT, 0x12); /* yum! cookies! */
563
564 if (cl_64bit == 1) {
565 WSeq(ba, SEQ_ID_CONF_RBACK, 0x00);
566 WSeq(ba, SEQ_ID_DRAM_CNTL, (cl_fbsize / 0x100000 == 2) ? 0x38 : 0xb8);
567 } else {
568 WSeq(ba, SEQ_ID_DRAM_CNTL, 0xb0);
569 }
570 WSeq(ba, SEQ_ID_RESET, 0x03);
571 WSeq(ba, SEQ_ID_MAP_MASK, 0xff);
572 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
573 WSeq(ba, SEQ_ID_MEMORY_MODE, 0x0e); /* a or 6? */
574 WSeq(ba, SEQ_ID_EXT_SEQ_MODE, (cltype == PICASSO) ? 0x21 : 0x81);
575 WSeq(ba, SEQ_ID_EEPROM_CNTL, 0x00);
576 if (cl_64bit == 1)
577 WSeq(ba, SEQ_ID_PERF_TUNE, 0x5a);
578 else
579 WSeq(ba, SEQ_ID_PERF_TUNE, 0x0a); /* mouse 0a fa */
580 WSeq(ba, SEQ_ID_SIG_CNTL, 0x02);
581 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
582
583 if (cl_64bit == 1)
584 WSeq(ba, SEQ_ID_MCLK_SELECT, 0x1c);
585 else
586 WSeq(ba, SEQ_ID_MCLK_SELECT, 0x22);
587
588 WCrt(ba, CRT_ID_PRESET_ROW_SCAN, 0x00);
589 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
590 WCrt(ba, CRT_ID_CURSOR_END, 0x08);
591 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
592 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
593 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
594 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
595
596 WCrt(ba, CRT_ID_UNDERLINE_LOC, 0x07);
597 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
598 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff); /* ff */
599 WCrt(ba, CRT_ID_EXT_DISP_CNTL, 0x22);
600 if (cl_64bit == 1) {
601 WCrt(ba, CRT_ID_SYNC_ADJ_GENLOCK, 0x00);
602 WCrt(ba, CRT_ID_OVERLAY_EXT_CTRL_REG, 0x40);
603 }
604 WSeq(ba, SEQ_ID_CURSOR_STORE, 0x3c); /* mouse 0x00 */
605
606 WGfx(ba, GCT_ID_SET_RESET, 0x00);
607 WGfx(ba, GCT_ID_ENABLE_SET_RESET, 0x00);
608 WGfx(ba, GCT_ID_DATA_ROTATE, 0x00);
609 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
610 WGfx(ba, GCT_ID_GRAPHICS_MODE, 0x00);
611 WGfx(ba, GCT_ID_MISC, 0x01);
612 WGfx(ba, GCT_ID_COLOR_XCARE, 0x0f);
613 WGfx(ba, GCT_ID_BITMASK, 0xff);
614 WGfx(ba, GCT_ID_MODE_EXT, 0x28);
615
616 for (x = 0; x < 0x10; x++)
617 WAttr(ba, x, x);
618 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, 0x01);
619 WAttr(ba, ACT_ID_OVERSCAN_COLOR, 0x00);
620 WAttr(ba, ACT_ID_COLOR_PLANE_ENA, 0x0f);
621 WAttr(ba, ACT_ID_HOR_PEL_PANNING, 0x00);
622 WAttr(ba, ACT_ID_COLOR_SELECT, 0x00);
623 WAttr(ba, 0x34, 0x00);
624
625 vgaw(ba, VDAC_MASK, 0xff);
626 vgaw(ba, GREG_MISC_OUTPUT_W, 0xef);
627
628 WGfx(ba, GCT_ID_BLT_STAT_START, 0x04);
629 WGfx(ba, GCT_ID_BLT_STAT_START, 0x00);
630 }
631
632 /* colors initially set to greyscale */
633 vgaw(ba, VDAC_ADDRESS_W, 0);
634 for (x = 255; x >= 0; x--) {
635 vgaw(ba, VDAC_DATA, x);
636 vgaw(ba, VDAC_DATA, x);
637 vgaw(ba, VDAC_DATA, x);
638 }
639 /* set sprite bitmap pointers */
640 cl_cursprite.image = cl_imageptr;
641 cl_cursprite.mask = cl_maskptr;
642 cl_cursprite.cmap.red = cl_sprred;
643 cl_cursprite.cmap.green = cl_sprgreen;
644 cl_cursprite.cmap.blue = cl_sprblue;
645
646 if (cl_64bit == 0) {
647
648 /* check for 1MB or 2MB board (crest) */
649 volatile unsigned long *cl_fbtestaddr;
650 cl_fbtestaddr = (volatile unsigned long *)gp->g_fbkva;
651
652 WGfx(ba, GCT_ID_OFFSET_0, 0x40);
653 *cl_fbtestaddr = 0x12345678;
654
655 if (*cl_fbtestaddr != 0x12345678) {
656 WSeq(ba, SEQ_ID_DRAM_CNTL, 0x30);
657 cl_fbsize = 0x100000;
658 }
659 else
660 {
661 cl_fbsize = 0x200000;
662 }
663 }
664 WGfx(ba, GCT_ID_OFFSET_0, 0x00);
665 }
666
667
668 int
669 cl_getvmode(struct grf_softc *gp, struct grfvideo_mode *vm)
670 {
671 struct grfvideo_mode *gv;
672
673 #ifdef CL5426CONSOLE
674 /* Handle grabbing console mode */
675 if (vm->mode_num == 255) {
676 memcpy(vm, &clconsole_mode, sizeof(struct grfvideo_mode));
677 /* XXX so grfconfig can tell us the correct text dimensions. */
678 vm->depth = clconsole_mode.fy;
679 } else
680 #endif
681 {
682 if (vm->mode_num == 0)
683 vm->mode_num = (monitor_current - monitor_def) + 1;
684 if (vm->mode_num < 1 || vm->mode_num > monitor_def_max)
685 return (EINVAL);
686 gv = monitor_def + (vm->mode_num - 1);
687 if (gv->mode_num == 0)
688 return (EINVAL);
689
690 memcpy(vm, gv, sizeof(struct grfvideo_mode));
691 }
692
693 /* adjust internal values to pixel values */
694
695 vm->hblank_start *= 8;
696 vm->hsync_start *= 8;
697 vm->hsync_stop *= 8;
698 vm->htotal *= 8;
699
700 return (0);
701 }
702
703
704 int
705 cl_setvmode(struct grf_softc *gp, unsigned mode)
706 {
707 if (!mode || (mode > monitor_def_max) ||
708 monitor_def[mode - 1].mode_num == 0)
709 return (EINVAL);
710
711 monitor_current = monitor_def + (mode - 1);
712
713 return (0);
714 }
715
716 #ifndef CL5426CONSOLE
717 void
718 cl_off(struct grf_softc *gp)
719 {
720 char *ba = gp->g_regkva;
721
722 /*
723 * we'll put the pass-through on for cc ite and set Full Bandwidth bit
724 * on just in case it didn't work...but then it doesn't matter does
725 * it? =)
726 */
727 RegOnpass(ba);
728 vgaw(ba, SEQ_ADDRESS, SEQ_ID_CLOCKING_MODE);
729 vgaw(ba, SEQ_ADDRESS_W, vgar(ba, SEQ_ADDRESS_W) | 0x20);
730 cl_blanked = 1;
731 }
732 #endif
733
734 int
735 cl_blank(struct grf_softc *gp, int on)
736 {
737
738 WSeq(gp->g_regkva, SEQ_ID_CLOCKING_MODE, on ? 0x01 : 0x21);
739 cl_blanked = !on;
740 return 0;
741 }
742
743 int
744 cl_isblank(struct grf_softc *gp)
745 {
746
747 return cl_blanked;
748 }
749
750 /*
751 * Change the mode of the display.
752 * Return a UNIX error number or 0 for success.
753 */
754 int
755 cl_mode(register struct grf_softc *gp, u_long cmd, void *arg, u_long a2, int a3)
756 {
757 int error;
758
759 switch (cmd) {
760 case GM_GRFON:
761 error = cl_load_mon(gp,
762 (struct grfcltext_mode *) monitor_current) ? 0 : EINVAL;
763 return (error);
764
765 case GM_GRFOFF:
766 #ifndef CL5426CONSOLE
767 cl_off(gp);
768 #else
769 cl_load_mon(gp, &clconsole_mode);
770 #endif
771 return (0);
772
773 case GM_GRFCONFIG:
774 return (0);
775
776 case GM_GRFGETVMODE:
777 return (cl_getvmode(gp, (struct grfvideo_mode *) arg));
778
779 case GM_GRFSETVMODE:
780 error = cl_setvmode(gp, *(unsigned *) arg);
781 if (!error && (gp->g_flags & GF_GRFON))
782 cl_load_mon(gp,
783 (struct grfcltext_mode *) monitor_current);
784 return (error);
785
786 case GM_GRFGETNUMVM:
787 *(int *) arg = monitor_def_max;
788 return (0);
789
790 case GM_GRFIOCTL:
791 return (cl_ioctl(gp, a2, arg));
792
793 default:
794 break;
795 }
796
797 return (EPASSTHROUGH);
798 }
799
800 int
801 cl_ioctl(register struct grf_softc *gp, u_long cmd, void *data)
802 {
803 switch (cmd) {
804 case GRFIOCGSPRITEPOS:
805 return (cl_getmousepos(gp, (struct grf_position *) data));
806
807 case GRFIOCSSPRITEPOS:
808 return (cl_setmousepos(gp, (struct grf_position *) data));
809
810 case GRFIOCSSPRITEINF:
811 return (cl_setspriteinfo(gp, (struct grf_spriteinfo *) data));
812
813 case GRFIOCGSPRITEINF:
814 return (cl_getspriteinfo(gp, (struct grf_spriteinfo *) data));
815
816 case GRFIOCGSPRITEMAX:
817 return (cl_getspritemax(gp, (struct grf_position *) data));
818
819 case GRFIOCGETCMAP:
820 return (cl_getcmap(gp, (struct grf_colormap *) data));
821
822 case GRFIOCPUTCMAP:
823 return (cl_putcmap(gp, (struct grf_colormap *) data));
824
825 case GRFIOCBITBLT:
826 break;
827
828 case GRFTOGGLE:
829 return (cl_toggle(gp, 0));
830
831 case GRFIOCSETMON:
832 return (cl_setmonitor(gp, (struct grfvideo_mode *) data));
833
834 case GRFIOCBLANK:
835 return (cl_blank(gp, *(int *)data));
836
837 }
838 return (EPASSTHROUGH);
839 }
840
841 int
842 cl_getmousepos(struct grf_softc *gp, struct grf_position *data)
843 {
844 data->x = cl_cursprite.pos.x;
845 data->y = cl_cursprite.pos.y;
846 return (0);
847 }
848
849 void
850 cl_writesprpos(volatile char *ba, short x, short y)
851 {
852 /* we want to use a 16-bit write to 3c4 so no macros used */
853 volatile unsigned char *cwp;
854 volatile unsigned short *wp;
855
856 cwp = ba + 0x3c4;
857 wp = (volatile unsigned short *)cwp;
858
859 /*
860 * don't ask me why, but apparently you can't do a 16-bit write with
861 * x-position like with y-position below (dagge)
862 */
863 cwp[0] = 0x10 | ((x << 5) & 0xff);
864 cwp[1] = (x >> 3) & 0xff;
865
866 *wp = 0x1100 | ((y & 7) << 13) | ((y >> 3) & 0xff);
867 }
868
869 void
870 writeshifted(volatile char *to, signed char shiftx, signed char shifty)
871 {
872 int y;
873 unsigned long long *tptr, *iptr, *mptr, line;
874
875 tptr = (unsigned long long *) __UNVOLATILE(to);
876 iptr = (unsigned long long *) cl_cursprite.image;
877 mptr = (unsigned long long *) cl_cursprite.mask;
878
879 shiftx = shiftx < 0 ? 0 : shiftx;
880 shifty = shifty < 0 ? 0 : shifty;
881
882 /* start reading shifty lines down, and
883 * shift each line in by shiftx
884 */
885 for (y = shifty; y < 64; y++) {
886
887 /* image */
888 line = iptr[y];
889 *tptr++ = line << shiftx;
890
891 /* mask */
892 line = mptr[y];
893 *tptr++ = line << shiftx;
894 }
895
896 /* clear the remainder */
897 for (y = shifty; y > 0; y--) {
898 *tptr++ = 0;
899 *tptr++ = 0;
900 }
901 }
902
903 int
904 cl_setmousepos(struct grf_softc *gp, struct grf_position *data)
905 {
906 volatile char *ba = gp->g_regkva;
907 short rx, ry;
908 #ifdef CL_SHIFTSPRITE
909 volatile char *fb = gp->g_fbkva;
910 volatile char *sprite = fb + (cl_fbsize - 1024);
911 #endif
912
913 /* no movement */
914 if (cl_cursprite.pos.x == data->x && cl_cursprite.pos.y == data->y)
915 return (0);
916
917 /* current and previous real coordinates */
918 rx = data->x - cl_cursprite.hot.x;
919 ry = data->y - cl_cursprite.hot.y;
920
921 /*
922 * if we are/were on an edge, create (un)shifted bitmap --
923 * ripped out optimization (not extremely worthwhile,
924 * and kind of buggy anyhow).
925 */
926 #ifdef CL_SHIFTSPRITE
927 if (rx < 0 || ry < 0 || prx < 0 || pry < 0) {
928 writeshifted(sprite, rx < 0 ? -rx : 0, ry < 0 ? -ry : 0);
929 }
930 #endif
931
932 /* do movement, save position */
933 cl_writesprpos(ba, rx < 0 ? 0 : rx, ry < 0 ? 0 : ry);
934 cl_cursprite.pos.x = data->x;
935 cl_cursprite.pos.y = data->y;
936
937 return (0);
938 }
939
940 int
941 cl_getspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data)
942 {
943 copyout(&cl_cursprite, data, sizeof(struct grf_spriteinfo));
944 copyout(cl_cursprite.image, data->image, 64 * 8);
945 copyout(cl_cursprite.mask, data->mask, 64 * 8);
946 return (0);
947 }
948
949 static int
950 cl_setspriteinfo(struct grf_softc *gp, struct grf_spriteinfo *data)
951 {
952 volatile unsigned char *ba = gp->g_regkva, *fb = gp->g_fbkva;
953 volatile char *sprite = fb + (cl_fbsize - 1024);
954
955 if (data->set & GRFSPRSET_SHAPE) {
956
957 unsigned short dsx, dsy, i;
958 unsigned long *di, *dm, *si, *sm;
959 unsigned long ssi[128], ssm[128];
960 struct grf_position gpos;
961
962
963 /* check for a too large sprite (no clipping!) */
964 dsy = data->size.y;
965 dsx = data->size.x;
966 if (dsy > 64 || dsx > 64)
967 return(EINVAL);
968
969 /* prepare destination */
970 di = (unsigned long *)cl_cursprite.image;
971 dm = (unsigned long *)cl_cursprite.mask;
972 cl_memset((unsigned char *)di, 0, 8*64);
973 cl_memset((unsigned char *)dm, 0, 8*64);
974
975 /* two alternatives: 64 across, then it's
976 * the same format we use, just copy. Otherwise,
977 * copy into tmp buf and recopy skipping the
978 * unused 32 bits.
979 */
980 if ((dsx - 1) / 32) {
981 copyin(data->image, di, 8 * dsy);
982 copyin(data->mask, dm, 8 * dsy);
983 } else {
984 si = ssi; sm = ssm;
985 copyin(data->image, si, 4 * dsy);
986 copyin(data->mask, sm, 4 * dsy);
987 for (i = 0; i < dsy; i++) {
988 *di = *si++;
989 *dm = *sm++;
990 di += 2;
991 dm += 2;
992 }
993 }
994
995 /* set size */
996 cl_cursprite.size.x = data->size.x;
997 cl_cursprite.size.y = data->size.y;
998
999 /* forcably load into board */
1000 gpos.x = cl_cursprite.pos.x;
1001 gpos.y = cl_cursprite.pos.y;
1002 cl_cursprite.pos.x = -1;
1003 cl_cursprite.pos.y = -1;
1004 writeshifted(sprite, 0, 0);
1005 cl_setmousepos(gp, &gpos);
1006
1007 }
1008 if (data->set & GRFSPRSET_HOT) {
1009
1010 cl_cursprite.hot = data->hot;
1011
1012 }
1013 if (data->set & GRFSPRSET_CMAP) {
1014
1015 u_char red[2], green[2], blue[2];
1016
1017 copyin(data->cmap.red, red, 2);
1018 copyin(data->cmap.green, green, 2);
1019 copyin(data->cmap.blue, blue, 2);
1020 memcpy(cl_cursprite.cmap.red, red, 2);
1021 memcpy(cl_cursprite.cmap.green, green, 2);
1022 memcpy(cl_cursprite.cmap.blue, blue, 2);
1023
1024 /* enable and load colors 256 & 257 */
1025 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x06);
1026
1027 /* 256 */
1028 vgaw(ba, VDAC_ADDRESS_W, 0x00);
1029 if (cltype == PICASSO) {
1030 vgaw(ba, VDAC_DATA, (u_char) (red[0] >> 2));
1031 vgaw(ba, VDAC_DATA, (u_char) (green[0] >> 2));
1032 vgaw(ba, VDAC_DATA, (u_char) (blue[0] >> 2));
1033 } else {
1034 vgaw(ba, VDAC_DATA, (u_char) (blue[0] >> 2));
1035 vgaw(ba, VDAC_DATA, (u_char) (green[0] >> 2));
1036 vgaw(ba, VDAC_DATA, (u_char) (red[0] >> 2));
1037 }
1038
1039 /* 257 */
1040 vgaw(ba, VDAC_ADDRESS_W, 0x0f);
1041 if (cltype == PICASSO) {
1042 vgaw(ba, VDAC_DATA, (u_char) (red[1] >> 2));
1043 vgaw(ba, VDAC_DATA, (u_char) (green[1] >> 2));
1044 vgaw(ba, VDAC_DATA, (u_char) (blue[1] >> 2));
1045 } else {
1046 vgaw(ba, VDAC_DATA, (u_char) (blue[1] >> 2));
1047 vgaw(ba, VDAC_DATA, (u_char) (green[1] >> 2));
1048 vgaw(ba, VDAC_DATA, (u_char) (red[1] >> 2));
1049 }
1050
1051 /* turn on/off sprite */
1052 if (cl_cursprite.enable) {
1053 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x05);
1054 } else {
1055 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
1056 }
1057
1058 }
1059 if (data->set & GRFSPRSET_ENABLE) {
1060
1061 if (data->enable == 1) {
1062 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x05);
1063 cl_cursprite.enable = 1;
1064 } else {
1065 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x04);
1066 cl_cursprite.enable = 0;
1067 }
1068
1069 }
1070 if (data->set & GRFSPRSET_POS) {
1071
1072 /* force placement */
1073 cl_cursprite.pos.x = -1;
1074 cl_cursprite.pos.y = -1;
1075
1076 /* do it */
1077 cl_setmousepos(gp, &data->pos);
1078
1079 }
1080 return (0);
1081 }
1082
1083 static int
1084 cl_getspritemax(struct grf_softc *gp, struct grf_position *data)
1085 {
1086 if (gp->g_display.gd_planes == 24)
1087 return (EINVAL);
1088 data->x = 64;
1089 data->y = 64;
1090 return (0);
1091 }
1092
1093 int
1094 cl_setmonitor(struct grf_softc *gp, struct grfvideo_mode *gv)
1095 {
1096 struct grfvideo_mode *md;
1097
1098 if (!cl_mondefok(gv))
1099 return(EINVAL);
1100
1101 #ifdef CL5426CONSOLE
1102 /* handle interactive setting of console mode */
1103 if (gv->mode_num == 255) {
1104 memcpy(&clconsole_mode.gv, gv, sizeof(struct grfvideo_mode));
1105 clconsole_mode.gv.hblank_start /= 8;
1106 clconsole_mode.gv.hsync_start /= 8;
1107 clconsole_mode.gv.hsync_stop /= 8;
1108 clconsole_mode.gv.htotal /= 8;
1109 clconsole_mode.rows = gv->disp_height / clconsole_mode.fy;
1110 clconsole_mode.cols = gv->disp_width / clconsole_mode.fx;
1111 if (!(gp->g_flags & GF_GRFON))
1112 cl_load_mon(gp, &clconsole_mode);
1113 #if NITE > 0
1114 ite_reinit(gp->g_itedev);
1115 #endif
1116 return (0);
1117 }
1118 #endif
1119
1120 md = monitor_def + (gv->mode_num - 1);
1121 memcpy(md, gv, sizeof(struct grfvideo_mode));
1122
1123 /* adjust pixel oriented values to internal rep. */
1124
1125 md->hblank_start /= 8;
1126 md->hsync_start /= 8;
1127 md->hsync_stop /= 8;
1128 md->htotal /= 8;
1129
1130 return (0);
1131 }
1132
1133 int
1134 cl_getcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
1135 {
1136 volatile unsigned char *ba;
1137 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1138 short x;
1139 int error;
1140
1141 if (cmap->count == 0 || cmap->index >= 256)
1142 return 0;
1143
1144 if (cmap->count > 256 - cmap->index)
1145 cmap->count = 256 - cmap->index;
1146
1147 ba = gfp->g_regkva;
1148 /* first read colors out of the chip, then copyout to userspace */
1149 vgaw(ba, VDAC_ADDRESS_R, cmap->index);
1150 x = cmap->count - 1;
1151
1152 /*
1153 * Some sort 'o Magic. Spectrum has some changes on the board to speed
1154 * up 15 and 16Bit modes. They can access these modes with easy-to-programm
1155 * rgbrgbrgb instead of rrrgggbbb. Side effect: when in 8Bit mode, rgb
1156 * is swapped to bgr. I wonder if we need to check for 8Bit though, ill
1157 */
1158
1159 /*
1160 * The source for the above comment is somewhat unknow to me.
1161 * The Spectrum, Piccolo and PiccoloSD64 have the analog Red and Blue
1162 * lines swapped. In 24BPP this provides RGB instead of BGR as it would
1163 * be native to the chipset. This requires special programming for the
1164 * CLUT in 8BPP to compensate and avoid false colors.
1165 * I didn't find any special stuff for 15 and 16BPP though, crest.
1166 */
1167
1168 switch (cltype) {
1169 case SPECTRUM:
1170 case PICCOLO:
1171 rp = blue + cmap->index;
1172 gp = green + cmap->index;
1173 bp = red + cmap->index;
1174 break;
1175 case PICASSO:
1176 rp = red + cmap->index;
1177 gp = green + cmap->index;
1178 bp = blue + cmap->index;
1179 break;
1180 default:
1181 rp = gp = bp = 0;
1182 break;
1183 }
1184
1185 do {
1186 *rp++ = vgar(ba, VDAC_DATA) << 2;
1187 *gp++ = vgar(ba, VDAC_DATA) << 2;
1188 *bp++ = vgar(ba, VDAC_DATA) << 2;
1189 } while (x-- > 0);
1190
1191 if (!(error = copyout(red + cmap->index, cmap->red, cmap->count))
1192 && !(error = copyout(green + cmap->index, cmap->green, cmap->count))
1193 && !(error = copyout(blue + cmap->index, cmap->blue, cmap->count)))
1194 return (0);
1195
1196 return (error);
1197 }
1198
1199 int
1200 cl_putcmap(struct grf_softc *gfp, struct grf_colormap *cmap)
1201 {
1202 volatile unsigned char *ba;
1203 u_char red[256], green[256], blue[256], *rp, *gp, *bp;
1204 short x;
1205 int error;
1206
1207 if (cmap->count == 0 || cmap->index >= 256)
1208 return (0);
1209
1210 if (cmap->count > 256 - cmap->index)
1211 cmap->count = 256 - cmap->index;
1212
1213 /* first copy the colors into kernelspace */
1214 if (!(error = copyin(cmap->red, red + cmap->index, cmap->count))
1215 && !(error = copyin(cmap->green, green + cmap->index, cmap->count))
1216 && !(error = copyin(cmap->blue, blue + cmap->index, cmap->count))) {
1217 ba = gfp->g_regkva;
1218 vgaw(ba, VDAC_ADDRESS_W, cmap->index);
1219 x = cmap->count - 1;
1220
1221 switch (cltype) {
1222 case SPECTRUM:
1223 case PICCOLO:
1224 rp = blue + cmap->index;
1225 gp = green + cmap->index;
1226 bp = red + cmap->index;
1227 break;
1228 case PICASSO:
1229 rp = red + cmap->index;
1230 gp = green + cmap->index;
1231 bp = blue + cmap->index;
1232 break;
1233 default:
1234 rp = gp = bp = 0;
1235 break;
1236 }
1237
1238 do {
1239 vgaw(ba, VDAC_DATA, *rp++ >> 2);
1240 vgaw(ba, VDAC_DATA, *gp++ >> 2);
1241 vgaw(ba, VDAC_DATA, *bp++ >> 2);
1242 } while (x-- > 0);
1243 return (0);
1244 } else
1245 return (error);
1246 }
1247
1248
1249 int
1250 cl_toggle(struct grf_softc *gp, unsigned short wopp)
1251 /* wopp: don't need that one yet, ill */
1252 {
1253 volatile void *ba;
1254
1255 ba = gp->g_regkva;
1256
1257 if (cl_pass_toggle) {
1258 RegOffpass(ba);
1259 } else {
1260 RegOnpass(ba);
1261 }
1262 return (0);
1263 }
1264
1265 static void
1266 cl_CompFQ(u_int fq, u_char *num, u_char *denom, u_char *clkdoub)
1267 {
1268 #define OSC 14318180
1269 /* OK, here's what we're doing here:
1270 *
1271 * OSC * NUMERATOR
1272 * VCLK = ------------------- Hz
1273 * DENOMINATOR * (1+P)
1274 *
1275 * so we're given VCLK and we should give out some useful
1276 * values....
1277 *
1278 * NUMERATOR is 7 bits wide
1279 * DENOMINATOR is 5 bits wide with bit P in the same char as bit 0.
1280 *
1281 * We run through all the possible combinations and
1282 * return the values which deviate the least from the chosen frequency.
1283 *
1284 */
1285 #define OSC 14318180
1286 #define count(n,d,p) ((OSC * n)/(d * (1+p)))
1287
1288 unsigned char n, d, p, minn, mind, minp = 0;
1289 unsigned long err, minerr;
1290
1291 /*
1292 numer = 0x00 - 0x7f
1293 denom = 0x00 - 0x1f (1) 0x20 - 0x3e (even)
1294 */
1295
1296 /* find lowest error in 6144 iterations. */
1297 minerr = fq;
1298 minn = 0;
1299 mind = 0;
1300 p = 0;
1301
1302 if ((cl_64bit == 1) && (fq >= 86000000))
1303 {
1304 for (d = 1; d < 0x20; d++) {
1305 for (n = 1; n < 0x80; n++) {
1306 err = abs(count(n, d, 0) - fq);
1307 if (err < minerr) {
1308 minerr = err;
1309 minn = n;
1310 mind = d;
1311 minp = 1;
1312 }
1313 }
1314 }
1315 *clkdoub = 1;
1316 }
1317 else {
1318 for (d = 1; d < 0x20; d++) {
1319 for (n = 1; n < 0x80; n++) {
1320 err = abs(count(n, d, p) - fq);
1321 if (err < minerr) {
1322 minerr = err;
1323 minn = n;
1324 mind = d;
1325 minp = p;
1326 }
1327 }
1328 if (d == 0x1f && p == 0) {
1329 p = 1;
1330 d = 0x0f;
1331 }
1332 }
1333 *clkdoub = 0;
1334 }
1335
1336 *num = minn;
1337 *denom = (mind << 1) | minp;
1338 if (minerr > 500000)
1339 printf("Warning: CompFQ minimum error = %ld\n", minerr);
1340 return;
1341 }
1342
1343 int
1344 cl_mondefok(struct grfvideo_mode *gv)
1345 {
1346 unsigned long maxpix;
1347
1348 if (gv->mode_num < 1 || gv->mode_num > monitor_def_max)
1349 if (gv->mode_num != 255 || gv->depth != 4)
1350 return(0);
1351
1352 switch (gv->depth) {
1353 case 4:
1354 if (gv->mode_num != 255)
1355 return(0);
1356 case 1:
1357 case 8:
1358 maxpix = cl_maxpixelclock;
1359 if (cl_64bit == 1)
1360 {
1361 if (cltype == PICASSO) /* Picasso IV */
1362 maxpix = 135000000;
1363 else /* Piccolo SD64 */
1364 maxpix = 110000000;
1365 }
1366 break;
1367 case 15:
1368 case 16:
1369 if (cl_64bit == 1)
1370 maxpix = 85000000;
1371 else
1372 maxpix = cl_maxpixelclock - (cl_maxpixelclock / 3);
1373 break;
1374 case 24:
1375 if ((cltype == PICASSO) && (cl_64bit == 1))
1376 maxpix = 85000000;
1377 else
1378 maxpix = cl_maxpixelclock / 3;
1379 break;
1380 case 32:
1381 if ((cltype == PICCOLO) && (cl_64bit == 1))
1382 maxpix = 50000000;
1383 else
1384 maxpix = 0;
1385 break;
1386 default:
1387 printf("grfcl: Illegal depth in mode %d\n",
1388 (int) gv->mode_num);
1389 return (0);
1390 }
1391
1392 if (gv->pixel_clock > maxpix) {
1393 printf("grfcl: Pixelclock too high in mode %d\n",
1394 (int) gv->mode_num);
1395 return (0);
1396 }
1397
1398 if (gv->disp_flags & GRF_FLAGS_SYNC_ON_GREEN) {
1399 printf("grfcl: sync-on-green is not supported\n");
1400 return (0);
1401 }
1402
1403 return (1);
1404 }
1405
1406 int
1407 cl_load_mon(struct grf_softc *gp, struct grfcltext_mode *md)
1408 {
1409 struct grfvideo_mode *gv;
1410 struct grfinfo *gi;
1411 volatile void *ba, *fb;
1412 unsigned char num0, denom0, clkdoub;
1413 unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS,
1414 VSE, VT;
1415 int clkmul, clkmode;
1416 int vmul;
1417 int sr15;
1418 unsigned char hvsync_pulse;
1419 char TEXT;
1420
1421 /* identity */
1422 gv = &md->gv;
1423 TEXT = (gv->depth == 4);
1424
1425 if (!cl_mondefok(gv)) {
1426 printf("grfcl: Monitor definition not ok\n");
1427 return (0);
1428 }
1429
1430 ba = gp->g_regkva;
1431 fb = gp->g_fbkva;
1432
1433 /* provide all needed information in grf device-independent locations */
1434 gp->g_data = (void *) gv;
1435 gi = &gp->g_display;
1436 gi->gd_regaddr = (void *) kvtop(__UNVOLATILE(ba));
1437 gi->gd_regsize = 64 * 1024;
1438 gi->gd_fbaddr = (void *) kvtop(__UNVOLATILE(fb));
1439 gi->gd_fbsize = cl_fbsize;
1440 gi->gd_colors = 1 << gv->depth;
1441 gi->gd_planes = gv->depth;
1442 gi->gd_fbwidth = gv->disp_width;
1443 gi->gd_fbheight = gv->disp_height;
1444 gi->gd_fbx = 0;
1445 gi->gd_fby = 0;
1446 if (TEXT) {
1447 gi->gd_dwidth = md->fx * md->cols;
1448 gi->gd_dheight = md->fy * md->rows;
1449 } else {
1450 gi->gd_dwidth = gv->disp_width;
1451 gi->gd_dheight = gv->disp_height;
1452 }
1453 gi->gd_dx = 0;
1454 gi->gd_dy = 0;
1455
1456 /* get display mode parameters */
1457
1458 HBS = gv->hblank_start;
1459 HSS = gv->hsync_start;
1460 HSE = gv->hsync_stop;
1461 HBE = gv->htotal - 1;
1462 HT = gv->htotal;
1463 VBS = gv->vblank_start;
1464 VSS = gv->vsync_start;
1465 VSE = gv->vsync_stop;
1466 VBE = gv->vtotal - 1;
1467 VT = gv->vtotal;
1468
1469 if (TEXT)
1470 HDE = ((gv->disp_width + md->fx - 1) / md->fx) - 1;
1471 else
1472 HDE = (gv->disp_width + 3) / 8 - 1; /* HBS; */
1473 VDE = gv->disp_height - 1;
1474
1475 /* adjustments */
1476 switch (gv->depth) {
1477 case 8:
1478 clkmul = 1;
1479 clkmode = 0x0;
1480 break;
1481 case 15:
1482 case 16:
1483 clkmul = 1;
1484 clkmode = 0x6;
1485 break;
1486 case 24:
1487 if ((cltype == PICASSO) && (cl_64bit == 1)) /* Picasso IV */
1488 clkmul = 1;
1489 else
1490 clkmul = 3;
1491 clkmode = 0x4;
1492 break;
1493 case 32:
1494 clkmul = 1;
1495 clkmode = 0x8;
1496 break;
1497 default:
1498 clkmul = 1;
1499 clkmode = 0x0;
1500 break;
1501 }
1502
1503 if ((VT > 1023) && (!(gv->disp_flags & GRF_FLAGS_LACE))) {
1504 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe7);
1505 } else
1506 WCrt(ba, CRT_ID_MODE_CONTROL, 0xe3);
1507
1508 vmul = 2;
1509 if ((VT > 1023) || (gv->disp_flags & GRF_FLAGS_LACE))
1510 vmul = 1;
1511 if (gv->disp_flags & GRF_FLAGS_DBLSCAN)
1512 vmul = 4;
1513
1514 VDE = VDE * vmul / 2;
1515 VBS = VBS * vmul / 2;
1516 VSS = VSS * vmul / 2;
1517 VSE = VSE * vmul / 2;
1518 VBE = VBE * vmul / 2;
1519 VT = VT * vmul / 2;
1520
1521 WSeq(ba, SEQ_ID_MEMORY_MODE, (TEXT || (gv->depth == 1)) ? 0x06 : 0x0e);
1522 if (cl_64bit == 1) {
1523 if (TEXT || (gv->depth == 1))
1524 sr15 = 0xd0;
1525 else
1526 sr15 = ((cl_fbsize / 0x100000 == 2) ? 0x38 : 0xb8);
1527 WSeq(ba, SEQ_ID_CONF_RBACK, 0x00);
1528 } else {
1529 sr15 = (TEXT || (gv->depth == 1)) ? 0xd0 : 0xb0;
1530 sr15 &= ((cl_fbsize / 0x100000) == 2) ? 0xff : 0x7f;
1531 }
1532 WSeq(ba, SEQ_ID_DRAM_CNTL, sr15);
1533 WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x00);
1534 WSeq(ba, SEQ_ID_MAP_MASK, (gv->depth == 1) ? 0x01 : 0xff);
1535 WSeq(ba, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1536
1537 /* Set clock */
1538
1539 cl_CompFQ(gv->pixel_clock * clkmul, &num0, &denom0, &clkdoub);
1540
1541 /* Horizontal/Vertical Sync Pulse */
1542 hvsync_pulse = vgar(ba, GREG_MISC_OUTPUT_R);
1543 if (gv->disp_flags & GRF_FLAGS_PHSYNC)
1544 hvsync_pulse &= ~0x40;
1545 else
1546 hvsync_pulse |= 0x40;
1547 if (gv->disp_flags & GRF_FLAGS_PVSYNC)
1548 hvsync_pulse &= ~0x80;
1549 else
1550 hvsync_pulse |= 0x80;
1551 vgaw(ba, GREG_MISC_OUTPUT_W, hvsync_pulse);
1552
1553 if (clkdoub) {
1554 HDE /= 2;
1555 HBS /= 2;
1556 HSS /= 2;
1557 HSE /= 2;
1558 HBE /= 2;
1559 HT /= 2;
1560 clkmode = 0x6;
1561 }
1562
1563 WSeq(ba, SEQ_ID_VCLK_3_NUM, num0);
1564 WSeq(ba, SEQ_ID_VCLK_3_DENOM, denom0);
1565
1566 /* load display parameters into board */
1567
1568 WCrt(ba, CRT_ID_HOR_TOTAL, HT);
1569 WCrt(ba, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? HBS - 1 : HDE));
1570 WCrt(ba, CRT_ID_START_HOR_BLANK, HBS);
1571 WCrt(ba, CRT_ID_END_HOR_BLANK, (HBE & 0x1f) | 0x80); /* | 0x80? */
1572 WCrt(ba, CRT_ID_START_HOR_RETR, HSS);
1573 WCrt(ba, CRT_ID_END_HOR_RETR,
1574 (HSE & 0x1f) |
1575 ((HBE & 0x20) ? 0x80 : 0x00));
1576 WCrt(ba, CRT_ID_VER_TOTAL, VT);
1577 WCrt(ba, CRT_ID_OVERFLOW,
1578 0x10 |
1579 ((VT & 0x100) ? 0x01 : 0x00) |
1580 ((VDE & 0x100) ? 0x02 : 0x00) |
1581 ((VSS & 0x100) ? 0x04 : 0x00) |
1582 ((VBS & 0x100) ? 0x08 : 0x00) |
1583 ((VT & 0x200) ? 0x20 : 0x00) |
1584 ((VDE & 0x200) ? 0x40 : 0x00) |
1585 ((VSS & 0x200) ? 0x80 : 0x00));
1586
1587 WCrt(ba, CRT_ID_CHAR_HEIGHT,
1588 0x40 | /* TEXT ? 0x00 ??? */
1589 ((gv->disp_flags & GRF_FLAGS_DBLSCAN) ? 0x80 : 0x00) |
1590 ((VBS & 0x200) ? 0x20 : 0x00) |
1591 (TEXT ? ((md->fy - 1) & 0x1f) : 0x00));
1592
1593 /* text cursor */
1594
1595 if (TEXT) {
1596 #if CL_ULCURSOR
1597 WCrt(ba, CRT_ID_CURSOR_START, (md->fy & 0x1f) - 2);
1598 WCrt(ba, CRT_ID_CURSOR_END, (md->fy & 0x1f) - 1);
1599 #else
1600 WCrt(ba, CRT_ID_CURSOR_START, 0x00);
1601 WCrt(ba, CRT_ID_CURSOR_END, md->fy & 0x1f);
1602 #endif
1603 WCrt(ba, CRT_ID_UNDERLINE_LOC, (md->fy - 1) & 0x1f);
1604
1605 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1606 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, 0x00);
1607 }
1608 WCrt(ba, CRT_ID_START_ADDR_HIGH, 0x00);
1609 WCrt(ba, CRT_ID_START_ADDR_LOW, 0x00);
1610
1611 WCrt(ba, CRT_ID_START_VER_RETR, VSS);
1612 WCrt(ba, CRT_ID_END_VER_RETR, (VSE & 0x0f) | 0x20);
1613 WCrt(ba, CRT_ID_VER_DISP_ENA_END, VDE);
1614 WCrt(ba, CRT_ID_START_VER_BLANK, VBS);
1615 WCrt(ba, CRT_ID_END_VER_BLANK, VBE);
1616
1617 WCrt(ba, CRT_ID_LINE_COMPARE, 0xff);
1618 WCrt(ba, CRT_ID_LACE_END, HT / 2); /* MW/16 */
1619 WCrt(ba, CRT_ID_LACE_CNTL,
1620 ((gv->disp_flags & GRF_FLAGS_LACE) ? 0x01 : 0x00) |
1621 ((HBE & 0x40) ? 0x10 : 0x00) |
1622 ((HBE & 0x80) ? 0x20 : 0x00) |
1623 ((VBE & 0x100) ? 0x40 : 0x00) |
1624 ((VBE & 0x200) ? 0x80 : 0x00));
1625
1626 WGfx(ba, GCT_ID_GRAPHICS_MODE,
1627 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x40));
1628 WGfx(ba, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
1629
1630 WSeq(ba, SEQ_ID_EXT_SEQ_MODE,
1631 ((TEXT || (gv->depth == 1)) ? 0x00 : 0x01) |
1632 ((cltype == PICASSO) ? 0x20 : 0x80) | clkmode);
1633
1634 /* write 0x00 to VDAC_MASK before accessing HDR this helps
1635 sometimes, out of "secret" application note (crest) */
1636 vgaw(ba, VDAC_MASK, 0);
1637 /* reset HDR "magic" access counter (crest) */
1638 vgar(ba, VDAC_ADDRESS);
1639
1640 delay(200000);
1641 vgar(ba, VDAC_MASK);
1642 delay(200000);
1643 vgar(ba, VDAC_MASK);
1644 delay(200000);
1645 vgar(ba, VDAC_MASK);
1646 delay(200000);
1647 vgar(ba, VDAC_MASK);
1648 delay(200000);
1649 switch (gv->depth) {
1650 case 1:
1651 case 4: /* text */
1652 vgaw(ba, VDAC_MASK, 0);
1653 HDE = gv->disp_width / 16;
1654 break;
1655 case 8:
1656 if (clkdoub)
1657 vgaw(ba, VDAC_MASK, 0x4a); /* Clockdouble Magic */
1658 else
1659 vgaw(ba, VDAC_MASK, 0);
1660 HDE = gv->disp_width / 8;
1661 break;
1662 case 15:
1663 vgaw(ba, VDAC_MASK, 0xd0);
1664 HDE = gv->disp_width / 4;
1665 break;
1666 case 16:
1667 vgaw(ba, VDAC_MASK, 0xc1);
1668 HDE = gv->disp_width / 4;
1669 break;
1670 case 24:
1671 vgaw(ba, VDAC_MASK, 0xc5);
1672 HDE = (gv->disp_width / 8) * 3;
1673 break;
1674 case 32:
1675 vgaw(ba, VDAC_MASK, 0xc5);
1676 HDE = (gv->disp_width / 4);
1677 break;
1678 }
1679
1680 /* reset HDR "magic" access counter (crest) */
1681 vgar(ba, VDAC_ADDRESS);
1682 /* then enable all bit in VDAC_MASK afterwards (crest) */
1683 vgaw(ba, VDAC_MASK, 0xff);
1684
1685 WCrt(ba, CRT_ID_OFFSET, HDE);
1686 if (cl_64bit == 1) {
1687 WCrt(ba, CRT_ID_SYNC_ADJ_GENLOCK, 0x00);
1688 WCrt(ba, CRT_ID_OVERLAY_EXT_CTRL_REG, 0x40);
1689 }
1690 WCrt(ba, CRT_ID_EXT_DISP_CNTL,
1691 ((TEXT && gv->pixel_clock > 29000000) ? 0x40 : 0x00) |
1692 0x22 |
1693 ((HDE > 0xff) ? 0x10 : 0x00));
1694
1695 WAttr(ba, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x0a : 0x01));
1696 WAttr(ba, 0x20 | ACT_ID_COLOR_PLANE_ENA,
1697 (gv->depth == 1) ? 0x01 : 0x0f);
1698
1699 /* text initialization */
1700
1701 if (TEXT) {
1702 cl_inittextmode(gp);
1703 }
1704 WSeq(ba, SEQ_ID_CURSOR_ATTR, 0x14);
1705 WSeq(ba, SEQ_ID_CLOCKING_MODE, 0x01);
1706 cl_blanked = 0;
1707
1708 /* Pass-through */
1709
1710 RegOffpass(ba);
1711
1712 return (1);
1713 }
1714
1715 void
1716 cl_inittextmode(struct grf_softc *gp)
1717 {
1718 struct grfcltext_mode *tm = (struct grfcltext_mode *) gp->g_data;
1719 volatile unsigned char *ba = gp->g_regkva;
1720 unsigned char *fb = __UNVOLATILE(gp->g_fbkva);
1721 unsigned char *c, *f, y;
1722 unsigned short z;
1723
1724
1725 /* load text font into beginning of display memory. Each character
1726 * cell is 32 bytes long (enough for 4 planes) */
1727
1728 SetTextPlane(ba, 0x02);
1729 cl_memset(fb, 0, 256 * 32);
1730 c = (unsigned char *) (fb) + (32 * tm->fdstart);
1731 f = tm->fdata;
1732 for (z = tm->fdstart; z <= tm->fdend; z++, c += (32 - tm->fy))
1733 for (y = 0; y < tm->fy; y++)
1734 *c++ = *f++;
1735
1736 /* clear out text/attr planes (three screens worth) */
1737
1738 SetTextPlane(ba, 0x01);
1739 cl_memset(fb, 0x07, tm->cols * tm->rows * 3);
1740 SetTextPlane(ba, 0x00);
1741 cl_memset(fb, 0x20, tm->cols * tm->rows * 3);
1742
1743 /* print out a little init msg */
1744
1745 c = (unsigned char *) (fb) + (tm->cols - 16);
1746 strcpy(c, "CIRRUS");
1747 c[6] = 0x20;
1748
1749 /* set colors (B&W) */
1750
1751 vgaw(ba, VDAC_ADDRESS_W, 0);
1752 for (z = 0; z < 256; z++) {
1753 unsigned char r, g, b;
1754
1755 y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
1756
1757 if (cltype == PICASSO) {
1758 r = clconscolors[y][0];
1759 g = clconscolors[y][1];
1760 b = clconscolors[y][2];
1761 } else {
1762 b = clconscolors[y][0];
1763 g = clconscolors[y][1];
1764 r = clconscolors[y][2];
1765 }
1766 vgaw(ba, VDAC_DATA, r >> 2);
1767 vgaw(ba, VDAC_DATA, g >> 2);
1768 vgaw(ba, VDAC_DATA, b >> 2);
1769 }
1770 }
1771
1772 void
1773 cl_memset(unsigned char *d, unsigned char c, int l)
1774 {
1775 for (; l > 0; l--)
1776 *d++ = c;
1777 }
1778
1779 /*
1780 * Special wakeup/passthrough registers on graphics boards
1781 *
1782 * The methods have diverged a bit for each board, so
1783 * WPass(P) has been converted into a set of specific
1784 * inline functions.
1785 */
1786 static void
1787 RegWakeup(volatile void *ba)
1788 {
1789
1790 switch (cltype) {
1791 case SPECTRUM:
1792 vgaw(ba, PASS_ADDRESS_W, 0x1f);
1793 break;
1794 case PICASSO:
1795 /* Picasso needs no wakeup */
1796 break;
1797 case PICCOLO:
1798 if (cl_64bit == 1)
1799 vgaw(ba, PASS_ADDRESS_W, 0x1f);
1800 else
1801 vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) | 0x10);
1802 break;
1803 }
1804 delay(200000);
1805 }
1806
1807 static void
1808 RegOnpass(volatile void *ba)
1809 {
1810
1811 switch (cltype) {
1812 case SPECTRUM:
1813 vgaw(ba, PASS_ADDRESS_W, 0x4f);
1814 break;
1815 case PICASSO:
1816 if (cl_64bit == 0)
1817 vgaw(ba, PASS_ADDRESS_WP, 0x01);
1818 break;
1819 case PICCOLO:
1820 if (cl_64bit == 1)
1821 vgaw(ba, PASS_ADDRESS_W, 0x4f);
1822 else
1823 vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) & 0xdf);
1824 break;
1825 }
1826 cl_pass_toggle = 1;
1827 delay(200000);
1828 }
1829
1830 static void
1831 RegOffpass(volatile void *ba)
1832 {
1833
1834 switch (cltype) {
1835 case SPECTRUM:
1836 vgaw(ba, PASS_ADDRESS_W, 0x6f);
1837 break;
1838 case PICASSO:
1839 if (cl_64bit == 0)
1840 vgaw(ba, PASS_ADDRESS_W, 0xff);
1841 break;
1842 case PICCOLO:
1843 if (cl_64bit == 1)
1844 vgaw(ba, PASS_ADDRESS_W, 0x6f);
1845 else
1846 vgaw(ba, PASS_ADDRESS_W, vgar(ba, PASS_ADDRESS) | 0x20);
1847 break;
1848 }
1849 cl_pass_toggle = 0;
1850 delay(200000);
1851 }
1852
1853 #if NWSDISPLAY > 0
1854 static void
1855 cl_wscursor(void *c, int on, int row, int col)
1856 {
1857 struct rasops_info *ri;
1858 struct vcons_screen *scr;
1859 struct grf_softc *gp;
1860 volatile void *ba;
1861 int offs;
1862
1863 ri = c;
1864 scr = ri->ri_hw;
1865 gp = scr->scr_cookie;
1866 ba = gp->g_regkva;
1867
1868 if ((ri->ri_flg & RI_CURSOR) && !on) {
1869 /* cursor was visible, but we want to remove it */
1870 /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/
1871 ri->ri_flg &= ~RI_CURSOR;
1872 }
1873
1874 ri->ri_crow = row;
1875 ri->ri_ccol = col;
1876
1877 if (on) {
1878 /* move cursor to new location */
1879 if (!(ri->ri_flg & RI_CURSOR)) {
1880 /*WCrt(ba, CRT_ID_CURSOR_START, | 0x20);*/
1881 ri->ri_flg |= RI_CURSOR;
1882 }
1883 offs = gp->g_rowoffset[row] + col;
1884 WCrt(ba, CRT_ID_CURSOR_LOC_LOW, offs & 0xff);
1885 WCrt(ba, CRT_ID_CURSOR_LOC_HIGH, offs >> 8);
1886 }
1887 }
1888
1889 static void
1890 cl_wsputchar(void *c, int row, int col, u_int ch, long attr)
1891 {
1892 struct rasops_info *ri;
1893 struct vcons_screen *scr;
1894 struct grf_softc *gp;
1895 volatile unsigned char *ba, *cp;
1896
1897 ri = c;
1898 scr = ri->ri_hw;
1899 gp = scr->scr_cookie;
1900 ba = gp->g_regkva;
1901 cp = gp->g_fbkva;
1902
1903 cp += gp->g_rowoffset[row] + col;
1904 SetTextPlane(ba, 0x00);
1905 *cp = ch;
1906 SetTextPlane(ba, 0x01);
1907 *cp = attr;
1908 }
1909
1910 static void
1911 cl_wscopycols(void *c, int row, int srccol, int dstcol, int ncols)
1912 {
1913 volatile unsigned char *ba, *dst, *src;
1914 struct rasops_info *ri;
1915 struct vcons_screen *scr;
1916 struct grf_softc *gp;
1917 int i;
1918
1919 KASSERT(ncols > 0);
1920 ri = c;
1921 scr = ri->ri_hw;
1922 gp = scr->scr_cookie;
1923 ba = gp->g_regkva;
1924 src = gp->g_fbkva;
1925
1926 src += gp->g_rowoffset[row];
1927 dst = src;
1928 src += srccol;
1929 dst += dstcol;
1930 if (srccol < dstcol) {
1931 /* need to copy backwards */
1932 src += ncols;
1933 dst += ncols;
1934 SetTextPlane(ba, 0x00);
1935 for (i = 0; i < ncols; i++)
1936 *(--dst) = *(--src);
1937 src += ncols;
1938 dst += ncols;
1939 SetTextPlane(ba, 0x01);
1940 for (i = 0; i < ncols; i++)
1941 *(--dst) = *(--src);
1942 } else {
1943 SetTextPlane(ba, 0x00);
1944 for (i = 0; i < ncols; i++)
1945 *dst++ = *src++;
1946 src -= ncols;
1947 dst -= ncols;
1948 SetTextPlane(ba, 0x01);
1949 for (i = 0; i < ncols; i++)
1950 *dst++ = *src++;
1951 }
1952 }
1953
1954 static void
1955 cl_wserasecols(void *c, int row, int startcol, int ncols, long fillattr)
1956 {
1957 volatile unsigned char *ba, *cp;
1958 struct rasops_info *ri;
1959 struct vcons_screen *scr;
1960 struct grf_softc *gp;
1961 int i;
1962
1963 ri = c;
1964 scr = ri->ri_hw;
1965 gp = scr->scr_cookie;
1966 ba = gp->g_regkva;
1967 cp = gp->g_fbkva;
1968
1969 cp += gp->g_rowoffset[row] + startcol;
1970 SetTextPlane(ba, 0x00);
1971 for (i = 0; i < ncols; i++)
1972 *cp++ = 0x20;
1973 cp -= ncols;
1974 SetTextPlane(ba, 0x01);
1975 for (i = 0; i < ncols; i++)
1976 *cp++ = 0x07;
1977 }
1978
1979 static void
1980 cl_wscopyrows(void *c, int srcrow, int dstrow, int nrows)
1981 {
1982 volatile unsigned char *ba, *dst, *src;
1983 struct rasops_info *ri;
1984 struct vcons_screen *scr;
1985 struct grf_softc *gp;
1986 int i, n;
1987
1988 KASSERT(nrows > 0);
1989 ri = c;
1990 scr = ri->ri_hw;
1991 gp = scr->scr_cookie;
1992 ba = gp->g_regkva;
1993 src = dst = gp->g_fbkva;
1994 n = ri->ri_cols * nrows;
1995
1996 if (srcrow < dstrow) {
1997 /* need to copy backwards */
1998 src += gp->g_rowoffset[srcrow + nrows];
1999 dst += gp->g_rowoffset[dstrow + nrows];
2000 SetTextPlane(ba, 0x00);
2001 for (i = 0; i < n; i++)
2002 *(--dst) = *(--src);
2003 src += n;
2004 dst += n;
2005 SetTextPlane(ba, 0x01);
2006 for (i = 0; i < n; i++)
2007 *(--dst) = *(--src);
2008 } else {
2009 src += gp->g_rowoffset[srcrow];
2010 dst += gp->g_rowoffset[dstrow];
2011 SetTextPlane(ba, 0x00);
2012 for (i = 0; i < n; i++)
2013 *dst++ = *src++;
2014 src -= n;
2015 dst -= n;
2016 SetTextPlane(ba, 0x01);
2017 for (i = 0; i < n; i++)
2018 *dst++ = *src++;
2019 }
2020 }
2021
2022 static void
2023 cl_wseraserows(void *c, int row, int nrows, long fillattr)
2024 {
2025 volatile unsigned char *ba, *cp;
2026 struct rasops_info *ri;
2027 struct vcons_screen *scr;
2028 struct grf_softc *gp;
2029 int i, n;
2030
2031 ri = c;
2032 scr = ri->ri_hw;
2033 gp = scr->scr_cookie;
2034 ba = gp->g_regkva;
2035 cp = gp->g_fbkva;
2036
2037 cp += gp->g_rowoffset[row];
2038 n = ri->ri_cols * nrows;
2039 SetTextPlane(ba, 0x00);
2040 for (i = 0; i < n; i++)
2041 *cp++ = 0x20;
2042 cp -= n;
2043 SetTextPlane(ba, 0x01);
2044 for (i = 0; i < n; i++)
2045 *cp++ = 0x07;
2046 }
2047
2048 static int
2049 cl_wsallocattr(void *c, int fg, int bg, int flg, long *attr)
2050 {
2051
2052 /* XXX color support? */
2053 *attr = (flg & WSATTR_REVERSE) ? 0x70 : 0x07;
2054 if (flg & WSATTR_UNDERLINE) *attr = 0x01;
2055 if (flg & WSATTR_HILIT) *attr |= 0x08;
2056 if (flg & WSATTR_BLINK) *attr |= 0x80;
2057 return 0;
2058 }
2059
2060 /* our font does not support unicode extensions */
2061 static int
2062 cl_wsmapchar(void *c, int ch, unsigned int *cp)
2063 {
2064
2065 if (ch > 0 && ch < 256) {
2066 *cp = ch;
2067 return 5;
2068 }
2069 *cp = ' ';
2070 return 0;
2071 }
2072
2073 static int
2074 cl_wsioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
2075 {
2076 struct vcons_data *vd;
2077 struct grf_softc *gp;
2078
2079 vd = v;
2080 gp = vd->cookie;
2081
2082 switch (cmd) {
2083 case WSDISPLAYIO_GETCMAP:
2084 /* Note: wsdisplay_cmap and grf_colormap have same format */
2085 if (gp->g_display.gd_planes == 8)
2086 return cl_getcmap(gp, (struct grf_colormap *)data);
2087 return EINVAL;
2088
2089 case WSDISPLAYIO_PUTCMAP:
2090 /* Note: wsdisplay_cmap and grf_colormap have same format */
2091 if (gp->g_display.gd_planes == 8)
2092 return cl_putcmap(gp, (struct grf_colormap *)data);
2093 return EINVAL;
2094
2095 case WSDISPLAYIO_GVIDEO:
2096 if (cl_isblank(gp))
2097 *(u_int *)data = WSDISPLAYIO_VIDEO_OFF;
2098 else
2099 *(u_int *)data = WSDISPLAYIO_VIDEO_ON;
2100 return 0;
2101
2102 case WSDISPLAYIO_SVIDEO:
2103 return cl_blank(gp, *(u_int *)data == WSDISPLAYIO_VIDEO_ON);
2104
2105 case WSDISPLAYIO_SMODE:
2106 if ((*(int *)data) != gp->g_wsmode) {
2107 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
2108 /* load console text mode, redraw screen */
2109 (void)cl_load_mon(gp, &clconsole_mode);
2110 if (vd->active != NULL)
2111 vcons_redraw_screen(vd->active);
2112 } else {
2113 /* switch to current graphics mode */
2114 if (!cl_load_mon(gp,
2115 (struct grfcltext_mode *)monitor_current))
2116 return EINVAL;
2117 }
2118 gp->g_wsmode = *(int *)data;
2119 }
2120 return 0;
2121
2122 case WSDISPLAYIO_GET_FBINFO:
2123 return cl_get_fbinfo(gp, data);
2124 }
2125
2126 /* handle this command hw-independant in grf(4) */
2127 return grf_wsioctl(v, vs, cmd, data, flag, l);
2128 }
2129
2130 /*
2131 * Fill the wsdisplayio_fbinfo structure with information from the current
2132 * graphics mode. Even when text mode is active.
2133 */
2134 static int
2135 cl_get_fbinfo(struct grf_softc *gp, struct wsdisplayio_fbinfo *fbi)
2136 {
2137 struct grfvideo_mode *md;
2138 uint32_t rbits, gbits, bbits;
2139
2140 md = monitor_current;
2141
2142 switch (md->depth) {
2143 case 8:
2144 fbi->fbi_bitsperpixel = 8;
2145 rbits = gbits = bbits = 6; /* keep gcc happy */
2146 break;
2147 case 15:
2148 fbi->fbi_bitsperpixel = 16;
2149 rbits = gbits = bbits = 5;
2150 break;
2151 case 16:
2152 fbi->fbi_bitsperpixel = 16;
2153 rbits = bbits = 5;
2154 gbits = 6;
2155 break;
2156 case 24:
2157 fbi->fbi_bitsperpixel = 24;
2158 rbits = gbits = bbits = 8;
2159 break;
2160 default:
2161 return EINVAL;
2162 }
2163
2164 fbi->fbi_stride = (fbi->fbi_bitsperpixel / 8) * md->disp_width;
2165 fbi->fbi_width = md->disp_width;
2166 fbi->fbi_height = md->disp_height;
2167
2168 if (md->depth > 8) {
2169 fbi->fbi_pixeltype = WSFB_RGB;
2170 fbi->fbi_subtype.fbi_rgbmasks.red_offset = bbits + gbits;
2171 fbi->fbi_subtype.fbi_rgbmasks.red_size = rbits;
2172 fbi->fbi_subtype.fbi_rgbmasks.green_offset = bbits;
2173 fbi->fbi_subtype.fbi_rgbmasks.green_size = gbits;
2174 fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 0;
2175 fbi->fbi_subtype.fbi_rgbmasks.blue_size = bbits;
2176 fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0;
2177 fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0;
2178 } else {
2179 fbi->fbi_pixeltype = WSFB_CI;
2180 fbi->fbi_subtype.fbi_cmapinfo.cmap_entries = 1 << md->depth;
2181 }
2182
2183 fbi->fbi_flags = 0;
2184 fbi->fbi_fbsize = fbi->fbi_stride * fbi->fbi_height;
2185 fbi->fbi_fboffset = 0;
2186 return 0;
2187 }
2188 #endif /* NWSDISPLAY > 0 */
2189
2190 #endif /* NGRFCL */
2191