vidcvideo.c revision 1.9 1 /* $NetBSD: vidcvideo.c,v 1.9 2002/03/23 21:27:41 reinoud Exp $ */
2
3 /*
4 * Copyright (c) 2001 Reinoud Zandijk
5 * Copyright (c) 1998, 1999 Tohru Nishimura. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Tohru Nishimura
18 * and Reinoud Zandijk for the NetBSD Project.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Created vidcvideo.c from /dev/tc/cfb.c to fit the Acorn/ARM VIDC1 and VIDC20 chips
34 *
35 */
36
37 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
38
39 __KERNEL_RCSID(0, "$NetBSD: vidcvideo.c,v 1.9 2002/03/23 21:27:41 reinoud Exp $");
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/device.h>
45 #include <sys/malloc.h>
46 #include <sys/buf.h>
47 #include <sys/ioctl.h>
48
49 #include <arm/mainbus/mainbus.h>
50 #include <machine/bus.h>
51 #include <machine/intr.h>
52
53 #include <dev/wscons/wsconsio.h>
54 #include <dev/wscons/wsdisplayvar.h>
55
56 #include <dev/rasops/rasops.h>
57 #include <dev/wsfont/wsfont.h>
58
59 #include <uvm/uvm_extern.h>
60 #include <arm/arm32/pmap.h>
61 #include <arm/cpufunc.h>
62 #include <machine/intr.h>
63
64 /* for vidc_mode ... needs to be MI indepenent one day */
65 #include <arm/iomd/vidc.h>
66 #include <arm/iomd/vidc20config.h>
67 #include <arm/iomd/vidcvideo.h>
68 #include <machine/bootconfig.h>
69
70 extern videomemory_t videomemory;
71
72 #define machine_btop(x) arm_byte_to_page(x)
73 #define MACHINE_KSEG0_TO_PHYS(x) vtophys(x)
74
75 /* FOR DEBUG */
76 extern videomemory_t videomemory;
77
78
79 struct hwcmap256 {
80 #define CMAP_SIZE 256 /* 256 R/G/B entries */
81 u_int8_t r[CMAP_SIZE];
82 u_int8_t g[CMAP_SIZE];
83 u_int8_t b[CMAP_SIZE];
84 };
85
86
87 /* XXX for CURSOR_MAX_WIDTH = 32 */
88 struct hwcursor32 {
89 struct wsdisplay_curpos cc_pos;
90 struct wsdisplay_curpos cc_hot;
91 struct wsdisplay_curpos cc_size;
92 struct wsdisplay_curpos cc_magic;
93 u_int8_t cc_color[6]; /* how many? */
94 u_int32_t cc_image[(CURSOR_MAX_WIDTH/4) * CURSOR_MAX_HEIGHT];
95 u_int32_t cc_mask[(CURSOR_MAX_WIDTH/4) * CURSOR_MAX_HEIGHT];
96 };
97
98
99 struct fb_devconfig {
100 vaddr_t dc_vaddr; /* memory space virtual base address */
101 paddr_t dc_paddr; /* memory space physical base address */
102 vsize_t dc_size; /* size of slot memory */
103 int dc_wid; /* width of frame buffer */
104 int dc_ht; /* height of frame buffer */
105 int dc_log2_depth; /* log2 of bits per pixel */
106 int dc_depth; /* depth, bits per pixel */
107 int dc_rowbytes; /* bytes in a FB scan line */
108 vaddr_t dc_videobase; /* base of flat frame buffer */
109 int dc_blanked; /* currently has video disabled */
110 void *dc_hwscroll_cookie; /* cookie for hardware scroll */
111
112 int dc_curenb; /* is cursor sprite enabled ? */
113 int dc_changed; /* need update of hardware */
114 int dc_writeback_delay; /* Screenarea write back vsync counter */
115 #define WSDISPLAY_CMAP_DOLUT 0x20
116 #define WSDISPLAY_VIDEO_ONOFF 0x40
117 #define WSDISPLAY_WB_COUNTER 0x80
118
119 struct hwcmap256 dc_cmap; /* software copy of colormap */
120 struct hwcursor32 dc_cursor; /* software copy of cursor */
121
122 struct vidc_mode mode_info;
123 struct rasops_info rinfo;
124
125 struct wsdisplay_emulops orig_ri_ops; /* Rasops functions for deligation */
126 };
127
128
129 struct vidcvideo_softc {
130 struct device sc_dev;
131 struct fb_devconfig *sc_dc; /* device configuration */
132 int nscreens; /* number of screens configured */
133 };
134
135
136 /* XXX has to go XXX */
137 #define CX_MAGIC_X 220
138 #define CX_MAGIC_Y 35
139 #define CX_FB_OFFSET 0x000000
140 #define CX_FB_SIZE 0x100000
141 #define CX_BT459_OFFSET 0x200000
142 #define CX_OFFSET_IREQ 0x300000 /* Interrupt req. control */
143 /* XXX till here XXX */
144
145
146 /* Function prototypes for glue */
147 static int vidcvideo_match __P((struct device *, struct cfdata *, void *));
148 static void vidcvideo_attach __P((struct device *, struct device *, void *));
149
150
151 /* config glue */
152 const struct cfattach vidcvideo_ca = {
153 sizeof(struct vidcvideo_softc), vidcvideo_match, vidcvideo_attach,
154 };
155
156
157 static struct fb_devconfig vidcvideo_console_dc;
158 static int vidcvideo_is_console;
159
160
161 static struct wsscreen_descr vidcvideo_stdscreen = {
162 "std", 0, 0,
163 0, /* textops */
164 0, 0,
165 WSSCREEN_REVERSE
166 };
167
168 static const struct wsscreen_descr *_vidcvideo_scrlist[] = {
169 &vidcvideo_stdscreen,
170 };
171
172 static const struct wsscreen_list vidcvideo_screenlist = {
173 sizeof(_vidcvideo_scrlist) / sizeof(struct wsscreen_descr *), _vidcvideo_scrlist
174 };
175
176 static int vidcvideoioctl __P((void *, u_long, caddr_t, int, struct proc *));
177 static paddr_t vidcvideommap __P((void *, off_t, int));
178
179 static int vidcvideo_alloc_screen __P((void *, const struct wsscreen_descr *,
180 void **, int *, int *, long *));
181 static void vidcvideo_free_screen __P((void *, void *));
182 static int vidcvideo_show_screen __P((void *, void *, int,
183 void (*) (void *, int, int), void *));
184
185 static const struct wsdisplay_accessops vidcvideo_accessops = {
186 vidcvideoioctl,
187 vidcvideommap,
188 vidcvideo_alloc_screen,
189 vidcvideo_free_screen,
190 vidcvideo_show_screen,
191 0 /* load_font */
192 };
193
194
195 /* Function prototypes */
196 int vidcvideo_cnattach __P((vaddr_t));
197 static void vidcvideo_colourmap_and_cursor_init __P((struct fb_devconfig *));
198
199 static int get_cmap __P((struct vidcvideo_softc *, struct wsdisplay_cmap *));
200 static int set_cmap __P((struct vidcvideo_softc *, struct wsdisplay_cmap *));
201 static int set_cursor __P((struct vidcvideo_softc *, struct wsdisplay_cursor *));
202 static int get_cursor __P((struct vidcvideo_softc *, struct wsdisplay_cursor *));
203 static void set_curpos __P((struct vidcvideo_softc *, struct wsdisplay_curpos *));
204 static void vidcvideo_getdevconfig __P((vaddr_t, struct fb_devconfig *));
205
206 static int vidcvideointr __P((void *));
207 static void vidcvideo_config_wscons __P((struct fb_devconfig *));
208
209
210 /* Acceleration function prototypes */
211 static void vv_copyrows __P((void *, int, int, int));
212 static void vv_eraserows __P((void *, int, int, long));
213 static void vv_putchar __P((void *c, int row, int col, u_int uc, long attr));
214
215
216 static int
217 vidcvideo_match(parent, match, aux)
218 struct device *parent;
219 struct cfdata *match;
220 void *aux;
221 {
222 /* Can't probe AFAIK ; how ? */
223 return (1);
224 }
225
226
227 static void
228 vidcvideo_getdevconfig(dense_addr, dc)
229 vaddr_t dense_addr;
230 struct fb_devconfig *dc;
231 {
232 dc->dc_vaddr = dense_addr;
233 dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr);
234
235 vidcvideo_getmode(&dc->mode_info);
236
237 dc->dc_wid = dc->mode_info.hder;
238 dc->dc_ht = dc->mode_info.vder;
239 dc->dc_log2_depth = dc->mode_info.log2_bpp;
240 dc->dc_depth = 1 << dc->dc_log2_depth;
241 dc->dc_videobase = dc->dc_vaddr;
242 dc->dc_blanked = 0;
243
244 /* this should/could be done somewhat more elegant! */
245 switch (dc->dc_depth) {
246 case 1:
247 dc->dc_rowbytes = dc->dc_wid / 8;
248 break;
249 case 2:
250 dc->dc_rowbytes = dc->dc_wid / 4;
251 break;
252 case 4:
253 dc->dc_rowbytes = dc->dc_wid / 2;
254 break;
255 case 8:
256 dc->dc_rowbytes = dc->dc_wid;
257 break;
258 case 16:
259 dc->dc_rowbytes = dc->dc_wid * 2;
260 break;
261 case 32:
262 dc->dc_rowbytes = dc->dc_wid * 4;
263 break;
264 default:
265 printf("Unknown colour depth %d ... what to do ?", dc->dc_depth);
266 break;
267 };
268
269 /* euhm... correct ? i.e. not complete VIDC memory */
270 dc->dc_size = dc->mode_info.vder * dc->dc_rowbytes;
271
272 /* initialize colormap and cursor resource */
273 vidcvideo_colourmap_and_cursor_init(dc);
274
275 dc->rinfo.ri_flg = 0; /* RI_CENTER; */
276 dc->rinfo.ri_depth = dc->dc_depth;
277 dc->rinfo.ri_bits = (void *) dc->dc_videobase;
278 dc->rinfo.ri_width = dc->dc_wid;
279 dc->rinfo.ri_height = dc->dc_ht;
280 dc->rinfo.ri_stride = dc->dc_rowbytes;
281 dc->rinfo.ri_hw = dc; /* link back */
282
283 /* intitialise miscelanious */
284 dc->dc_writeback_delay = 0;
285 }
286
287
288 static void
289 vidcvideo_config_wscons(dc)
290 struct fb_devconfig *dc;
291 {
292 int i, cookie, font_not_locked;
293
294 /* clear the screen ; why not a memset ? - it was this way so keep it for now */
295 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
296 *(u_int32_t *)(dc->dc_videobase + i) = 0x0;
297
298 wsfont_init();
299
300 /* prefer 8 pixel wide font */
301 cookie = wsfont_find(NULL, 8, 0, 0, WSDISPLAY_FONTORDER_L2R,
302 WSDISPLAY_FONTORDER_L2R);
303 if (cookie <= 0)
304 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
305 WSDISPLAY_FONTORDER_L2R);
306
307 if (cookie < 0) {
308 /* Can I even print here ? */
309 printf("Font table empty! exiting\n");
310 return;
311 };
312
313 font_not_locked = wsfont_lock(cookie, &dc->rinfo.ri_font);
314
315 dc->rinfo.ri_wsfcookie = cookie;
316
317 rasops_init(&dc->rinfo,
318 dc->rinfo.ri_height / dc->rinfo.ri_font->fontheight,
319 dc->rinfo.ri_width / dc->rinfo.ri_font->fontwidth
320 );
321
322 /*
323 * Provide a hook for the acceleration functions and make a copy of the
324 * original rasops functions for passing on calls
325 */
326 dc->rinfo.ri_hw = dc;
327 memcpy(&(dc->orig_ri_ops), &(dc->rinfo.ri_ops), sizeof(struct wsdisplay_emulops));
328
329 /* add our accelerated functions */
330 dc->rinfo.ri_ops.eraserows = vv_eraserows;
331 dc->rinfo.ri_ops.copyrows = vv_copyrows;
332
333 /* add the extra activity measuring functions; they just delegate on */
334 dc->rinfo.ri_ops.putchar = vv_putchar;
335
336 /* XXX shouldn't be global */
337 vidcvideo_stdscreen.nrows = dc->rinfo.ri_rows;
338 vidcvideo_stdscreen.ncols = dc->rinfo.ri_cols;
339 vidcvideo_stdscreen.textops = &dc->rinfo.ri_ops;
340 vidcvideo_stdscreen.capabilities = dc->rinfo.ri_caps;
341
342 if (font_not_locked) {
343 printf(" warning ... couldn't lock font! ");
344 };
345 }
346
347
348 static void
349 vidcvideo_attach(parent, self, aux)
350 struct device *parent, *self;
351 void *aux;
352 {
353 struct vidcvideo_softc *sc = (struct vidcvideo_softc *)self;
354 struct fb_devconfig *dc;
355 struct wsemuldisplaydev_attach_args waa;
356 struct hwcmap256 *cm;
357 const u_int8_t *p;
358 long defattr;
359 int index;
360
361 vidcvideo_init();
362 if (sc->nscreens == 0) {
363 sc->sc_dc = &vidcvideo_console_dc;
364 if (!vidcvideo_is_console) {
365 printf(" : non console (no kbd yet) ");
366 vidcvideo_getdevconfig(videomemory.vidm_vbase, sc->sc_dc);
367 vidcvideo_config_wscons(sc->sc_dc);
368 (*sc->sc_dc->rinfo.ri_ops.alloc_attr)(&sc->sc_dc->rinfo, 0, 0, 0, &defattr);
369 };
370 sc->nscreens = 1;
371 } else {
372 printf(": allready attached ... can't cope with this\n");
373 return;
374 };
375
376 dc = sc->sc_dc;
377
378 vidcvideo_printdetails();
379 printf(": using %d x %d, %dbpp\n", dc->dc_wid, dc->dc_ht,
380 dc->dc_depth);
381
382 /* initialise rasops */
383 cm = &dc->dc_cmap;
384 p = rasops_cmap;
385 for (index = 0; index < CMAP_SIZE; index++, p += 3) {
386 cm->r[index] = p[0];
387 cm->g[index] = p[1];
388 cm->b[index] = p[2];
389 }
390
391 /* what does these do ? */
392 dc->dc_cursor.cc_magic.x = CX_MAGIC_X;
393 dc->dc_cursor.cc_magic.y = CX_MAGIC_Y;
394
395 /* set up interrupt flags */
396 dc->dc_changed |= WSDISPLAY_CMAP_DOLUT;
397
398 /*
399 * Set up a link in the rasops structure to our device config
400 * for acceleration stuff
401 */
402 dc->rinfo.ri_hw = sc->sc_dc;
403
404 /* Establish an interrupt handler, and clear any pending interrupts */
405 intr_claim(IRQ_FLYBACK, IPL_TTY, "vblank", vidcvideointr, dc);
406
407 waa.console = (vidcvideo_is_console ? 1 : 0);
408 waa.scrdata = &vidcvideo_screenlist;
409 waa.accessops = &vidcvideo_accessops;
410 waa.accesscookie = sc;
411
412 config_found(self, &waa, wsemuldisplaydevprint);
413 }
414
415
416 static int
417 vidcvideoioctl(v, cmd, data, flag, p)
418 void *v;
419 u_long cmd;
420 caddr_t data;
421 int flag;
422 struct proc *p;
423 {
424 struct vidcvideo_softc *sc = v;
425 struct fb_devconfig *dc = sc->sc_dc;
426 int state;
427
428 switch (cmd) {
429 case WSDISPLAYIO_GTYPE:
430 *(u_int *)data = WSDISPLAY_TYPE_VIDC;
431 return (0);
432
433 case WSDISPLAYIO_GINFO:
434 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
435 wsd_fbip->height = dc->dc_ht;
436 wsd_fbip->width = dc->dc_wid;
437 wsd_fbip->depth = dc->dc_depth;
438 wsd_fbip->cmsize = CMAP_SIZE;
439 #undef fbt
440 return (0);
441
442 case WSDISPLAYIO_GETCMAP:
443 return get_cmap(sc, (struct wsdisplay_cmap *)data);
444
445 case WSDISPLAYIO_PUTCMAP:
446 return set_cmap(sc, (struct wsdisplay_cmap *)data);
447
448 case WSDISPLAYIO_SVIDEO:
449 state = *(int *)data;
450 dc->dc_blanked = (state == WSDISPLAYIO_VIDEO_OFF);
451 dc->dc_changed |= WSDISPLAY_VIDEO_ONOFF;
452 /* done on video blank */
453 return (0);
454
455 case WSDISPLAYIO_GVIDEO:
456 *(u_int *)data = dc->dc_blanked ?
457 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
458 return (0);
459
460 case WSDISPLAYIO_GCURPOS:
461 *(struct wsdisplay_curpos *)data = dc->dc_cursor.cc_pos;
462 return (0);
463
464 case WSDISPLAYIO_SCURPOS:
465 set_curpos(sc, (struct wsdisplay_curpos *)data);
466 dc->dc_changed |= WSDISPLAY_CURSOR_DOPOS;
467 return (0);
468
469 case WSDISPLAYIO_GCURMAX:
470 ((struct wsdisplay_curpos *)data)->x = CURSOR_MAX_WIDTH;
471 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_HEIGHT;
472 return (0);
473
474 case WSDISPLAYIO_GCURSOR:
475 return get_cursor(sc, (struct wsdisplay_cursor *)data);
476
477 case WSDISPLAYIO_SCURSOR:
478 return set_cursor(sc, (struct wsdisplay_cursor *)data);
479
480 case WSDISPLAYIO_SMODE:
481 state = *(int *)data;
482 if (state == WSDISPLAYIO_MODE_MAPPED) {
483 dc->dc_hwscroll_cookie = vidcvideo_hwscroll_reset();
484 };
485 if (state == WSDISPLAYIO_MODE_EMUL) {
486 vidcvideo_hwscroll_back(dc->dc_hwscroll_cookie);
487 };
488 vidcvideo_progr_scroll();
489 return (0);
490 }
491 return EPASSTHROUGH;
492 }
493
494
495 paddr_t
496 vidcvideommap(v, offset, prot)
497 void *v;
498 off_t offset;
499 int prot;
500 {
501 struct vidcvideo_softc *sc = v;
502
503 if (offset >= sc->sc_dc->dc_size || offset < 0)
504 return (-1);
505 return machine_btop(sc->sc_dc->dc_paddr + offset);
506 }
507
508
509 static int
510 vidcvideo_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
511 void *v;
512 const struct wsscreen_descr *type;
513 void **cookiep;
514 int *curxp, *curyp;
515 long *attrp;
516 {
517 struct vidcvideo_softc *sc = v;
518 struct fb_devconfig *dc = sc->sc_dc;
519 long defattr;
520
521 /*
522 * One and just only one for now :( ... if the vidcconsole is not the
523 * console then this makes one wsconsole screen free for use !
524 */
525 if ((sc->nscreens > 1) || vidcvideo_is_console)
526 return (ENOMEM);
527
528 /* Add the screen to wscons to control */
529 *cookiep = &dc->rinfo;
530 *curxp = 0;
531 *curyp = 0;
532 vidcvideo_getdevconfig(videomemory.vidm_vbase, dc);
533 vidcvideo_config_wscons(dc);
534 (*dc->rinfo.ri_ops.alloc_attr)(&dc->rinfo, 0, 0, 0, &defattr);
535 *attrp = defattr;
536 sc->nscreens++;
537
538 return (0);
539 }
540
541
542 static void
543 vidcvideo_free_screen(v, cookie)
544 void *v;
545 void *cookie;
546 {
547 struct vidcvideo_softc *sc = v;
548
549 if (sc->sc_dc == &vidcvideo_console_dc)
550 panic("vidcvideo_free_screen: console");
551
552 sc->nscreens--;
553 }
554
555
556 static int
557 vidcvideo_show_screen(v, cookie, waitok, cb, cbarg)
558 void *v;
559 void *cookie;
560 int waitok;
561 void (*cb) __P((void *, int, int));
562 void *cbarg;
563 {
564
565 return (0);
566 }
567
568
569 /* EXPORT */ int
570 vidcvideo_cnattach(addr)
571 vaddr_t addr;
572 {
573 struct fb_devconfig *dcp = &vidcvideo_console_dc;
574 long defattr;
575
576 vidcvideo_init();
577 vidcvideo_getdevconfig(addr, dcp);
578 vidcvideo_config_wscons(dcp);
579 (*dcp->rinfo.ri_ops.alloc_attr)(&dcp->rinfo, 0, 0, 0, &defattr);
580 wsdisplay_cnattach(&vidcvideo_stdscreen, &dcp->rinfo, 0, 0, defattr);
581
582 vidcvideo_is_console = 1;
583 return(0);
584 }
585
586
587 static int
588 vidcvideointr(arg)
589 void *arg;
590 {
591 struct fb_devconfig *dc = arg;
592 int v, cleared = 0;
593
594 v = dc->dc_changed;
595 if (v == 0)
596 return (1);
597
598 if (v & WSDISPLAY_WB_COUNTER) {
599 dc->dc_writeback_delay--;
600 if (dc->dc_writeback_delay == 0) {
601 cpu_dcache_wb_range(dc->dc_vaddr, dc->dc_size);
602 cleared |= WSDISPLAY_WB_COUNTER;
603 };
604 }
605
606 if (v & WSDISPLAY_CMAP_DOLUT) {
607 struct hwcmap256 *cm = &dc->dc_cmap;
608 int index;
609
610 if (dc->dc_depth == 4) {
611 /* palette for 4 bpp is different from 8bpp */
612 vidcvideo_write(VIDC_PALREG, 0x00000000);
613 for (index=0; index < (1 << dc->dc_depth); index++)
614 vidcvideo_write(VIDC_PALETTE,
615 VIDC_COL(cm->r[index],
616 cm->g[index],
617 cm->b[index]));
618 ;
619 };
620
621 if (dc->dc_depth == 8) {
622 /* dunno what to do in more than 8bpp */
623 /* palettes only make sense in 8bpp and less modes on VIDC */
624 vidcvideo_write(VIDC_PALREG, 0x00000000);
625 for (index = 0; index < CMAP_SIZE; index++) {
626 vidcvideo_write(VIDC_PALETTE,
627 VIDC_COL(cm->r[index], cm->g[index], cm->b[index])
628 );
629 };
630 };
631 cleared |= WSDISPLAY_CMAP_DOLUT;
632 }
633
634 if (v & WSDISPLAY_VIDEO_ONOFF) {
635 vidcvideo_blank(dc->dc_blanked);
636 cleared |= WSDISPLAY_VIDEO_ONOFF;
637 };
638
639 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
640 int x, y;
641 x = dc->dc_cursor.cc_pos.x - dc->dc_cursor.cc_hot.x;
642 y = dc->dc_cursor.cc_pos.y - dc->dc_cursor.cc_hot.y;
643
644 vidcvideo_updatecursor(x, y);
645 cleared |= WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT;
646 };
647
648 if (v & WSDISPLAY_CURSOR_DOCUR) {
649 vidcvideo_enablecursor(dc->dc_curenb);
650 cleared |= WSDISPLAY_CURSOR_DOCUR;
651 };
652
653
654 #if 0 /* XXX snip XXX */
655 /* XXX kept here as an archive for now XXX */
656
657 vdac = vidcvideobase + CX_BT459_OFFSET;
658 v = sc->sc_changed;
659 if (v & WSDISPLAY_CURSOR_DOCUR) {
660 SELECT(vdac, BT459_IREG_CCR);
661 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
662 }
663 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
664 int x, y;
665
666 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
667 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
668
669 x += sc->sc_cursor.cc_magic.x;
670 y += sc->sc_cursor.cc_magic.y;
671
672 SELECT(vdac, BT459_IREG_CURSOR_X_LOW);
673 REG(vdac, bt_reg) = x; tc_wmb();
674 REG(vdac, bt_reg) = x >> 8; tc_wmb();
675 REG(vdac, bt_reg) = y; tc_wmb();
676 REG(vdac, bt_reg) = y >> 8; tc_wmb();
677 }
678 if (v & WSDISPLAY_CURSOR_DOCMAP) {
679 u_int8_t *cp = sc->sc_cursor.cc_color;
680
681 SELECT(vdac, BT459_IREG_CCOLOR_2);
682 REG(vdac, bt_reg) = cp[1]; tc_wmb();
683 REG(vdac, bt_reg) = cp[3]; tc_wmb();
684 REG(vdac, bt_reg) = cp[5]; tc_wmb();
685
686 REG(vdac, bt_reg) = cp[0]; tc_wmb();
687 REG(vdac, bt_reg) = cp[2]; tc_wmb();
688 REG(vdac, bt_reg) = cp[4]; tc_wmb();
689 }
690 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
691 u_int8_t *ip, *mp, img, msk;
692 u_int8_t u;
693 int bcnt;
694
695 ip = (u_int8_t *)sc->sc_cursor.cc_image;
696 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_HEIGHT);
697
698 bcnt = 0;
699 SELECT(vdac, BT459_IREG_CRAM_BASE+0);
700 /* 64 pixel scan line is consisted with 16 byte cursor ram */
701 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
702 /* pad right half 32 pixel when smaller than 33 */
703 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
704 REG(vdac, bt_reg) = 0; tc_wmb();
705 REG(vdac, bt_reg) = 0; tc_wmb();
706 }
707 else {
708 img = *ip++;
709 msk = *mp++;
710 img &= msk; /* cookie off image */
711 u = (msk & 0x0f) << 4 | (img & 0x0f);
712 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
713 u = (msk & 0xf0) | (img & 0xf0) >> 4;
714 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
715 }
716 bcnt += 2;
717 }
718 /* pad unoccupied scan lines */
719 while (bcnt < CURSOR_MAX_HEIGHT * 16) {
720 REG(vdac, bt_reg) = 0; tc_wmb();
721 REG(vdac, bt_reg) = 0; tc_wmb();
722 bcnt += 2;
723 }
724 }
725 #endif /* XXX snip XXX */
726
727 dc->dc_changed ^= cleared;
728
729 return (1);
730 }
731
732
733 static u_char ri_col_data[6][6] = {
734 { 0, 0, 0, 0, 0, 0}, /* 1 bpp */
735 { 0, 0, 0, 0, 0, 0}, /* 2 bpp */
736 { 0, 0, 0, 0, 0, 0}, /* 4 bpp */
737 { 0, 0, 0, 0, 0, 0}, /* 8 bpp */
738 { 5, 5, 5, 0, 5, 10}, /* 16 bpp */
739 { 8, 8, 8, 0, 8, 16}, /* 32 bpp */
740 };
741
742 static void
743 vidcvideo_colourmap_and_cursor_init(dc)
744 struct fb_devconfig *dc;
745 {
746 struct rasops_info *ri = &dc->rinfo;
747 u_char *rgbdat;
748
749 /* Whatever we do later... just make sure we have a
750 * sane palette to start with
751 */
752 vidcvideo_stdpalette();
753
754 /* set up rgb bit pattern values for rasops_init */
755 rgbdat = ri_col_data[dc->dc_log2_depth];
756 ri->ri_rnum = rgbdat[0];
757 ri->ri_gnum = rgbdat[1];
758 ri->ri_bnum = rgbdat[2];
759 ri->ri_rpos = rgbdat[3];
760 ri->ri_gpos = rgbdat[4];
761 ri->ri_bpos = rgbdat[5];
762
763 }
764
765
766 static int
767 get_cmap(sc, p)
768 struct vidcvideo_softc *sc;
769 struct wsdisplay_cmap *p;
770 {
771 u_int index = p->index, count = p->count;
772
773 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
774 return (EINVAL);
775
776 if (!uvm_useracc(p->red, count, B_WRITE) ||
777 !uvm_useracc(p->green, count, B_WRITE) ||
778 !uvm_useracc(p->blue, count, B_WRITE))
779 return (EFAULT);
780
781 copyout(&sc->sc_dc->dc_cmap.r[index], p->red, count);
782 copyout(&sc->sc_dc->dc_cmap.g[index], p->green, count);
783 copyout(&sc->sc_dc->dc_cmap.b[index], p->blue, count);
784
785 return (0);
786 }
787
788
789 static int
790 set_cmap(sc, p)
791 struct vidcvideo_softc *sc;
792 struct wsdisplay_cmap *p;
793 {
794 struct fb_devconfig *dc = sc->sc_dc;
795 u_int index = p->index, count = p->count;
796
797 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
798 return (EINVAL);
799
800 if (!uvm_useracc(p->red, count, B_READ) ||
801 !uvm_useracc(p->green, count, B_READ) ||
802 !uvm_useracc(p->blue, count, B_READ))
803 return (EFAULT);
804
805 copyin(p->red, &dc->dc_cmap.r[index], count);
806 copyin(p->green, &dc->dc_cmap.g[index], count);
807 copyin(p->blue, &dc->dc_cmap.b[index], count);
808 dc->dc_changed |= WSDISPLAY_CMAP_DOLUT;
809 return (0);
810 }
811
812
813 static int
814 set_cursor(sc, p)
815 struct vidcvideo_softc *sc;
816 struct wsdisplay_cursor *p;
817 {
818 #define cc (&dc->dc_cursor)
819 struct fb_devconfig *dc = sc->sc_dc;
820 u_int v, index, count, icount;
821
822 v = p->which;
823 if (v & WSDISPLAY_CURSOR_DOCMAP) {
824 index = p->cmap.index;
825 count = p->cmap.count;
826 if (index >= CURSOR_MAX_COLOURS || (index + count) > CURSOR_MAX_COLOURS)
827 return (EINVAL);
828 if (!uvm_useracc(p->cmap.red, count, B_READ) ||
829 !uvm_useracc(p->cmap.green, count, B_READ) ||
830 !uvm_useracc(p->cmap.blue, count, B_READ))
831 return (EFAULT);
832 }
833 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
834 if (p->size.x > CURSOR_MAX_WIDTH || p->size.y > CURSOR_MAX_HEIGHT)
835 return (EINVAL);
836 icount = sizeof(u_int32_t) * p->size.y;
837 if (!uvm_useracc(p->image, icount, B_READ) ||
838 !uvm_useracc(p->mask, icount, B_READ))
839 return (EFAULT);
840 }
841
842 if (v & WSDISPLAY_CURSOR_DOCUR)
843 dc->dc_curenb = p->enable;
844 if (v & WSDISPLAY_CURSOR_DOPOS)
845 set_curpos(sc, &p->pos);
846 if (v & WSDISPLAY_CURSOR_DOHOT)
847 cc->cc_hot = p->hot;
848 if (v & WSDISPLAY_CURSOR_DOCMAP) {
849 copyin(p->cmap.red, &cc->cc_color[index], count);
850 copyin(p->cmap.green, &cc->cc_color[index + 2], count);
851 copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
852 }
853 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
854 cc->cc_size = p->size;
855 memset(cc->cc_image, 0, sizeof cc->cc_image);
856 memset(cc->cc_mask, 0, sizeof cc->cc_mask);
857 copyin(p->image, cc->cc_image, icount);
858 copyin(p->mask, cc->cc_mask, icount);
859 }
860 dc->dc_changed |= v;
861
862 return (0);
863 #undef cc
864 }
865
866
867 static int
868 get_cursor(sc, p)
869 struct vidcvideo_softc *sc;
870 struct wsdisplay_cursor *p;
871 {
872 return (EPASSTHROUGH); /* XXX */
873 }
874
875
876 static void
877 set_curpos(sc, curpos)
878 struct vidcvideo_softc *sc;
879 struct wsdisplay_curpos *curpos;
880 {
881 struct fb_devconfig *dc = sc->sc_dc;
882 int x = curpos->x, y = curpos->y;
883
884 if (y < 0)
885 y = 0;
886 else if (y > dc->dc_ht)
887 y = dc->dc_ht;
888 if (x < 0)
889 x = 0;
890 else if (x > dc->dc_wid)
891 x = dc->dc_wid;
892 dc->dc_cursor.cc_pos.x = x;
893 dc->dc_cursor.cc_pos.y = y;
894 }
895
896
897 static void vv_copyrows(id, srcrow, dstrow, nrows)
898 void *id;
899 int srcrow, dstrow, nrows;
900 {
901 struct rasops_info *ri = id;
902 int height, offset, size;
903 int scrollup, scrolldown;
904 unsigned char *src, *dst;
905
906 /* All movements are done in multiples of character heigths */
907 height = ri->ri_font->fontheight * nrows;
908 offset = (srcrow - dstrow) * ri->ri_yscale;
909 size = height * ri->ri_stride;
910
911 /* check if we are full screen scrolling */
912 scrollup = (srcrow + nrows >= ri->ri_rows);
913 scrolldown = (dstrow + nrows >= ri->ri_rows);
914
915 if ((scrollup || scrolldown) && (videomemory.vidm_type == VIDEOMEM_TYPE_VRAM)) {
916 ri->ri_bits = vidcvideo_hwscroll(offset);
917 vidcvideo_progr_scroll(); /* sadistic ; shouldnt this be on vsync? */
918
919 /* wipe out remains of the screen if nessisary */
920 if (ri->ri_emuheight != ri->ri_height) vv_eraserows(id, ri->ri_rows, 1, NULL);
921 return;
922 };
923
924 /* Else we just copy the area : we're braindead for now
925 * Note: we can't use hardware scrolling when the softc isnt known yet...
926 * if its not known we dont have interrupts and we can't change the display
927 * address reliable other than in a Vsync
928 */
929
930 src = ri->ri_bits + srcrow * ri->ri_font->fontheight * ri->ri_stride;
931 dst = ri->ri_bits + dstrow * ri->ri_font->fontheight * ri->ri_stride;
932
933 bcopy(src, dst, size);
934 }
935
936
937 static void vv_eraserows(id, startrow, nrows, attr)
938 void *id;
939 int startrow, nrows;
940 long attr;
941 {
942 struct rasops_info *ri = id;
943 int height;
944 unsigned char *src;
945
946 /* we're braindead for now */
947 height = ri->ri_font->fontheight * nrows * ri->ri_stride;
948
949 src = ri->ri_bits + startrow * ri->ri_font->fontheight * ri->ri_stride;
950
951 bzero(src, height);
952 }
953
954
955 static void vv_putchar(id, row, col, uc, attr)
956 void *id;
957 int row, col;
958 u_int uc;
959 long attr;
960 {
961 struct rasops_info *ri = id;
962 struct fb_devconfig *dc = (struct fb_devconfig *) (ri->ri_hw);
963
964 /* delay the write back operation of the screen area */
965 dc->dc_writeback_delay = SCREEN_WRITE_BACK_DELAY;
966 dc->dc_changed |= WSDISPLAY_WB_COUNTER;
967
968 /* just delegate */
969 dc->orig_ri_ops.putchar(id, row, col, uc, attr);
970 }
971
972