grf.c revision 1.60 1 /* $NetBSD: grf.c,v 1.60 2014/03/16 05:20:22 dholland Exp $ */
2
3 /*
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1990 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * the Systems Programming Group of the University of Utah Computer
10 * Science Department.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: Utah $Hdr: grf.c 1.31 91/01/21$
37 *
38 * @(#)grf.c 7.8 (Berkeley) 5/7/91
39 */
40
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: grf.c,v 1.60 2014/03/16 05:20:22 dholland Exp $");
43
44 /*
45 * Graphics display driver for the Amiga
46 * This is the hardware-independent portion of the driver.
47 * Hardware access is through the grf_softc->g_mode routine.
48 */
49
50 #include "view.h"
51 #include "grf.h"
52 #include "kbd.h"
53 #include "wsdisplay.h"
54
55 #include <sys/param.h>
56 #include <sys/proc.h>
57 #include <sys/ioctl.h>
58 #include <sys/device.h>
59 #include <sys/file.h>
60 #include <sys/malloc.h>
61 #include <sys/systm.h>
62 #include <sys/vnode.h>
63 #include <sys/mman.h>
64 #include <sys/bus.h>
65 #include <sys/kauth.h>
66
67 #include <machine/cpu.h>
68
69 #include <dev/cons.h>
70 #include <dev/sun/fbio.h>
71 #include <dev/wscons/wsconsio.h>
72 #include <dev/wscons/wsdisplayvar.h>
73 #include <dev/rasops/rasops.h>
74 #include <dev/wscons/wsdisplay_vconsvar.h>
75
76 #include <amiga/amiga/color.h> /* DEBUG */
77 #include <amiga/amiga/device.h>
78 #include <amiga/dev/grfioctl.h>
79 #include <amiga/dev/grfws.h>
80 #include <amiga/dev/grfvar.h>
81 #include <amiga/dev/itevar.h>
82 #include <amiga/dev/kbdvar.h>
83 #include <amiga/dev/viewioctl.h>
84
85 #include <sys/conf.h>
86
87 #if NGRF > 0
88 #include "ite.h"
89 #if NITE == 0
90 #define ite_on(u,f)
91 #define ite_off(u,f)
92 #define ite_reinit(d)
93 #endif
94
95 int grfon(dev_t);
96 int grfoff(dev_t);
97 int grfsinfo(dev_t, struct grfdyninfo *);
98
99 void grfattach(device_t, device_t, void *);
100 int grfmatch(device_t, cfdata_t, void *);
101 int grfprint(void *, const char *);
102 #ifdef DEBUG
103 void grfdebug(struct grf_softc *, const char *, ...);
104 #endif
105 /*
106 * pointers to grf drivers device structs
107 */
108 struct grf_softc *grfsp[NGRF];
109
110 CFATTACH_DECL_NEW(grf, 0,
111 grfmatch, grfattach, NULL, NULL);
112
113 dev_type_open(grfopen);
114 dev_type_close(grfclose);
115 dev_type_ioctl(grfioctl);
116 dev_type_mmap(grfmmap);
117
118 const struct cdevsw grf_cdevsw = {
119 .d_open = grfopen,
120 .d_close = grfclose,
121 .d_read = nullread,
122 .d_write = nullwrite,
123 .d_ioctl = grfioctl,
124 .d_stop = nostop,
125 .d_tty = notty,
126 .d_poll = nopoll,
127 .d_mmap = grfmmap,
128 .d_kqfilter = nokqfilter,
129 .d_flag = 0
130 };
131
132 /*
133 * only used in console init.
134 */
135 static cfdata_t cfdata;
136
137 #if NWSDISPLAY > 0
138 static struct vcons_screen console_vcons;
139
140 static void grf_init_screen(void *, struct vcons_screen *, int, long *);
141 static struct rasops_info *grf_setup_rasops(struct grf_softc *,
142 struct vcons_screen *);
143 static paddr_t grf_wsmmap_md(off_t off);
144
145 cons_decl(grf);
146 #endif
147
148 /*
149 * match if the unit of grf matches its perspective
150 * low level board driver.
151 */
152 int
153 grfmatch(device_t parent, cfdata_t cf, void *aux)
154 {
155 struct grf_softc *psc;
156
157 psc = device_private(parent);
158 if (cf->cf_unit != psc->g_unit)
159 return(0);
160 cfdata = cf;
161 return(1);
162 }
163
164 /*
165 * Attach.. plug pointer in and print some info.
166 * Then try and attach a wsdisplay or ite to us.
167 * Note: self is NULL durring console init.
168 */
169 void
170 grfattach(device_t parent, device_t self, void *aux)
171 {
172 #if NWSDISPLAY > 0
173 struct wsemuldisplaydev_attach_args wa;
174 long defattr;
175 #endif
176 struct grf_softc *gp;
177 int maj;
178
179 gp = device_private(parent);
180 gp->g_device = self;
181 grfsp[gp->g_unit] = gp;
182
183 /*
184 * find our major device number
185 */
186 maj = cdevsw_lookup_major(&grf_cdevsw);
187
188 gp->g_grfdev = makedev(maj, gp->g_unit);
189 if (self != NULL) {
190 printf(": width %d height %d", gp->g_display.gd_dwidth,
191 gp->g_display.gd_dheight);
192 if (gp->g_display.gd_colors == 2)
193 printf(" monochrome\n");
194 else
195 printf(" colors %d\n", gp->g_display.gd_colors);
196 #if NWSDISPLAY > 0
197 vcons_init(&gp->g_vd, gp, gp->g_screens[0], gp->g_accessops);
198 gp->g_vd.init_screen = grf_init_screen;
199 if (gp->g_flags & GF_CONSOLE) {
200 console_vcons.scr_flags |= VCONS_SCREEN_IS_STATIC;
201 vcons_init_screen(&gp->g_vd,
202 &console_vcons, 1, &defattr);
203 gp->g_screens[0]->textops =
204 &console_vcons.scr_ri.ri_ops;
205 wsdisplay_cnattach(gp->g_screens[0],
206 &console_vcons.scr_ri, 0, 0, defattr);
207 vcons_replay_msgbuf(&console_vcons);
208 }
209
210 /* attach wsdisplay */
211 wa.console = (gp->g_flags & GF_CONSOLE) != 0;
212 wa.scrdata = &gp->g_screenlist;
213 wa.accessops = gp->g_accessops;
214 wa.accesscookie = &gp->g_vd;
215 config_found(self, &wa, wsemuldisplaydevprint);
216 #endif /* NWSDISPLAY > 0 */
217 }
218
219 #if NWSDISPLAY == 0
220 /*
221 * try and attach an ite
222 */
223 amiga_config_found(cfdata, self, gp, grfprint);
224 #endif
225 }
226
227 int
228 grfprint(void *aux, const char *pnp)
229 {
230 if (pnp)
231 aprint_normal("ite at %s", pnp);
232 return(UNCONF);
233 }
234
235 /*ARGSUSED*/
236 int
237 grfopen(dev_t dev, int flags, int devtype, struct lwp *l)
238 {
239 struct grf_softc *gp;
240
241 if (GRFUNIT(dev) >= NGRF || (gp = grfsp[GRFUNIT(dev)]) == NULL)
242 return(ENXIO);
243
244 if ((gp->g_flags & GF_ALIVE) == 0)
245 return(ENXIO);
246
247 if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE))
248 return(EBUSY);
249
250 return(0);
251 }
252
253 /*ARGSUSED*/
254 int
255 grfclose(dev_t dev, int flags, int mode, struct lwp *l)
256 {
257 struct grf_softc *gp;
258
259 gp = grfsp[GRFUNIT(dev)];
260 (void)grfoff(dev);
261 gp->g_flags &= GF_ALIVE;
262 return(0);
263 }
264
265 /*ARGSUSED*/
266 int
267 grfioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
268 {
269 struct grf_softc *gp;
270 int error;
271
272 gp = grfsp[GRFUNIT(dev)];
273 error = 0;
274
275 switch (cmd) {
276 case OGRFIOCGINFO:
277 /* argl.. no bank-member.. */
278 memcpy(data, (void *)&gp->g_display, sizeof(struct grfinfo)-4);
279 break;
280 case GRFIOCGINFO:
281 memcpy(data, (void *)&gp->g_display, sizeof(struct grfinfo));
282 break;
283 case GRFIOCON:
284 error = grfon(dev);
285 break;
286 case GRFIOCOFF:
287 error = grfoff(dev);
288 break;
289 case GRFIOCSINFO:
290 error = grfsinfo(dev, (struct grfdyninfo *) data);
291 break;
292 case GRFGETVMODE:
293 return(gp->g_mode(gp, GM_GRFGETVMODE, data, 0, 0));
294 case GRFSETVMODE:
295 error = gp->g_mode(gp, GM_GRFSETVMODE, data, 0, 0);
296 if (error == 0 && gp->g_itedev && !(gp->g_flags & GF_GRFON))
297 ite_reinit(gp->g_itedev);
298 break;
299 case GRFGETNUMVM:
300 return(gp->g_mode(gp, GM_GRFGETNUMVM, data, 0, 0));
301 /*
302 * these are all hardware dependent, and have to be resolved
303 * in the respective driver.
304 */
305 case GRFIOCPUTCMAP:
306 case GRFIOCGETCMAP:
307 case GRFIOCSSPRITEPOS:
308 case GRFIOCGSPRITEPOS:
309 case GRFIOCSSPRITEINF:
310 case GRFIOCGSPRITEINF:
311 case GRFIOCGSPRITEMAX:
312 case GRFIOCBITBLT:
313 case GRFIOCSETMON:
314 case GRFTOGGLE: /* Toggles between Cirrus boards and native ECS on
315 Amiga. 15/11/94 ill */
316 /*
317 * We need the minor dev number to get the overlay/image
318 * information for grf_ul.
319 */
320 return(gp->g_mode(gp, GM_GRFIOCTL, data, cmd, dev));
321
322 case GRFIOCBLANK: /* blank ioctl, IOCON/OFF will turn ite on */
323 case FBIOSVIDEO:
324 error = gp->g_mode(gp, GM_GRFIOCTL, data, GRFIOCBLANK, dev);
325 if (!error)
326 gp->g_blank = *(int *)data;
327 return (error);
328
329 case FBIOGVIDEO:
330 *(int *)data = gp->g_blank;
331 return (0);
332
333 default:
334 #if NVIEW > 0
335 /*
336 * check to see whether it's a command recognized by the
337 * view code if the unit is 0
338 * XXX
339 */
340 if (GRFUNIT(dev) == 0) {
341 extern const struct cdevsw view_cdevsw;
342
343 return((*view_cdevsw.d_ioctl)(dev, cmd, data, flag, l));
344 }
345 #endif
346 error = EPASSTHROUGH;
347 break;
348
349 }
350 return(error);
351 }
352
353 /*
354 * map the contents of a graphics display card into process'
355 * memory space.
356 */
357 paddr_t
358 grfmmap(dev_t dev, off_t off, int prot)
359 {
360 struct grf_softc *gp;
361 struct grfinfo *gi;
362
363 gp = grfsp[GRFUNIT(dev)];
364 gi = &gp->g_display;
365
366 /*
367 * control registers
368 */
369 if (off >= 0 && off < gi->gd_regsize)
370 return(((paddr_t)gi->gd_regaddr + off) >> PGSHIFT);
371
372 /*
373 * frame buffer
374 */
375 if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) {
376 off -= gi->gd_regsize;
377 return(((paddr_t)gi->gd_fbaddr + off) >> PGSHIFT);
378 }
379 /* bogus */
380 return(-1);
381 }
382
383 int
384 grfon(dev_t dev)
385 {
386 struct grf_softc *gp;
387
388 gp = grfsp[GRFUNIT(dev)];
389
390 if (gp->g_flags & GF_GRFON)
391 return(0);
392
393 gp->g_flags |= GF_GRFON;
394 if (gp->g_itedev != NODEV)
395 ite_off(gp->g_itedev, 3);
396
397 return(gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVON : GM_GRFON,
398 NULL, 0, 0));
399 }
400
401 int
402 grfoff(dev_t dev)
403 {
404 struct grf_softc *gp;
405 int error;
406
407 gp = grfsp[GRFUNIT(dev)];
408
409 if ((gp->g_flags & GF_GRFON) == 0)
410 return(0);
411
412 gp->g_flags &= ~GF_GRFON;
413 error = gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF,
414 NULL, 0, 0);
415
416 /*
417 * Closely tied together no X's
418 */
419 if (gp->g_itedev != NODEV)
420 ite_on(gp->g_itedev, 2);
421
422 return(error);
423 }
424
425 int
426 grfsinfo(dev_t dev, struct grfdyninfo *dyninfo)
427 {
428 struct grf_softc *gp;
429 int error;
430
431 gp = grfsp[GRFUNIT(dev)];
432 error = gp->g_mode(gp, GM_GRFCONFIG, dyninfo, 0, 0);
433
434 /*
435 * Closely tied together no X's
436 */
437 if (gp->g_itedev != NODEV)
438 ite_reinit(gp->g_itedev);
439 return(error);
440 }
441
442 #if NWSDISPLAY > 0
443 void
444 grfcnprobe(struct consdev *cd)
445 {
446 struct grf_softc *gp;
447 int unit;
448
449 /*
450 * Find the first working grf device for being console.
451 * Ignore unit 0 (grfcc), which should use amidisplaycc instead.
452 */
453 for (unit = 1; unit < NGRF; unit++) {
454 gp = grfsp[unit];
455 if (gp != NULL && (gp->g_flags & GF_ALIVE)) {
456 cd->cn_pri = CN_INTERNAL;
457 cd->cn_dev = NODEV; /* initialized later by wscons */
458 return;
459 }
460 }
461
462 /* no grf console alive */
463 cd->cn_pri = CN_DEAD;
464 }
465
466 void
467 grfcninit(struct consdev *cd)
468 {
469 struct grf_softc *gp;
470 struct rasops_info *ri;
471 long defattr;
472 int unit;
473
474 /* find console grf and set up wsdisplay for it */
475 for (unit = 1; unit < NGRF; unit++) {
476 gp = grfsp[unit];
477 if (gp != NULL && (gp->g_flags & GF_ALIVE)) {
478 gp->g_flags |= GF_CONSOLE; /* we are console! */
479 gp->g_screens[0]->ncols = gp->g_display.gd_fbwidth /
480 gp->g_screens[0]->fontwidth;
481 gp->g_screens[0]->nrows = gp->g_display.gd_fbheight /
482 gp->g_screens[0]->fontheight;
483
484 ri = grf_setup_rasops(gp, &console_vcons);
485 console_vcons.scr_cookie = gp;
486 defattr = 0; /* XXX */
487
488 wsdisplay_preattach(gp->g_screens[0], ri, 0, 0,
489 defattr);
490 #if NKBD > 0
491 /* tell kbd device it is used as console keyboard */
492 kbd_cnattach();
493 #endif
494 return;
495 }
496 }
497 panic("grfcninit: lost console");
498 }
499
500 static void
501 grf_init_screen(void *cookie, struct vcons_screen *scr, int existing,
502 long *defattr)
503 {
504 struct grf_softc *gp;
505 struct rasops_info *ri;
506
507 gp = cookie;
508 ri = grf_setup_rasops(gp, scr);
509 }
510
511 static struct rasops_info *
512 grf_setup_rasops(struct grf_softc *gp, struct vcons_screen *scr)
513 {
514 struct rasops_info *ri;
515 int i;
516
517 ri = &scr->scr_ri;
518 scr->scr_flags |= VCONS_DONT_READ;
519 memset(ri, 0, sizeof(struct rasops_info));
520
521 ri->ri_rows = gp->g_screens[0]->nrows;
522 ri->ri_cols = gp->g_screens[0]->ncols;
523 ri->ri_hw = scr;
524 ri->ri_ops.cursor = gp->g_emulops->cursor;
525 ri->ri_ops.mapchar = gp->g_emulops->mapchar;
526 ri->ri_ops.copyrows = gp->g_emulops->copyrows;
527 ri->ri_ops.eraserows = gp->g_emulops->eraserows;
528 ri->ri_ops.copycols = gp->g_emulops->copycols;
529 ri->ri_ops.erasecols = gp->g_emulops->erasecols;
530 ri->ri_ops.putchar = gp->g_emulops->putchar;
531 ri->ri_ops.allocattr = gp->g_emulops->allocattr;
532
533 /* multiplication table for row-offsets */
534 for (i = 0; i < ri->ri_rows; i++)
535 gp->g_rowoffset[i] = i * ri->ri_cols;
536
537 return ri;
538 }
539
540 paddr_t
541 grf_wsmmap(void *v, void *vs, off_t off, int prot)
542 {
543 struct vcons_data *vd;
544 struct grf_softc *gp;
545 struct grfinfo *gi;
546
547 vd = v;
548 gp = vd->cookie;
549 gi = &gp->g_display;
550
551 /* Normal fb mapping */
552 if (off < gi->gd_fbsize)
553 return grf_wsmmap_md(((bus_addr_t)gp->g_fbkva) + off);
554
555 if (kauth_authorize_machdep(kauth_cred_get(), KAUTH_MACHDEP_UNMANAGEDMEM,
556 NULL, NULL, NULL, NULL) != 0) {
557 aprint_normal("%s: permission to mmap denied.\n",
558 device_xname(gp->g_device));
559 return -1;
560 }
561
562 if ((off >= (bus_addr_t)gp->g_fbkva ) &&
563 (off < ( (bus_addr_t)gp->g_fbkva + (size_t)gi->gd_fbsize)))
564 return grf_wsmmap_md(off);
565
566 /* Handle register mapping */
567 if ((off >= (bus_addr_t)gi->gd_regaddr) &&
568 (off < ((bus_addr_t)gi->gd_regaddr + (size_t)gi->gd_regsize)))
569 return grf_wsmmap_md(off);
570
571 return -1;
572 }
573
574 static paddr_t
575 grf_wsmmap_md(off_t off)
576 {
577 #if defined(__m68k__)
578 return (paddr_t) m68k_btop(off);
579 #else
580 return -1; /* FIXME */
581 #endif
582 }
583
584 int
585 grf_wsioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
586 {
587 struct vcons_data *vd;
588 struct grf_softc *gp;
589
590 vd = v;
591 gp = vd->cookie;
592
593 switch (cmd) {
594 /* XXX: check if ptr to implementation is not null */
595 case WSDISPLAYIO_GINFO:
596 return gp->g_wsioctl->ginfo(gp, data);
597 case WSDISPLAYIO_SMODE:
598 return gp->g_wsioctl->smode(gp, data);
599 case WSDISPLAYIO_GMODE:
600 return gp->g_wsioctl->gmode(gp, data);
601 case WSDISPLAYIO_GTYPE:
602 return gp->g_wsioctl->gtype(gp, data);
603 case WSDISPLAYIO_SVIDEO:
604 return gp->g_wsioctl->svideo(gp, data);
605 case WSDISPLAYIO_GVIDEO:
606 return gp->g_wsioctl->gvideo(gp, data);
607 case WSDISPLAYIO_GETCMAP:
608 return gp->g_wsioctl->getcmap(gp, data);
609 case WSDISPLAYIO_PUTCMAP:
610 return gp->g_wsioctl->putcmap(gp, data);
611 }
612
613 return EPASSTHROUGH;
614 }
615
616 /* wsdisplay_accessops ioctls */
617
618 int
619 grf_wsaogetcmap(void *c, void *data)
620 {
621 u_int index, count;
622 struct grf_softc *gp;
623 struct wsdisplay_cmap *cm;
624
625 cm = (struct wsdisplay_cmap*) data;
626 gp = c;
627 index = 0;
628 count = 0;
629
630 if (gp->g_wsmode == WSDISPLAYIO_MODE_EMUL)
631 return EINVAL;
632
633 if (index >= 255 || count > 256 || index + count > 256)
634 return EINVAL;
635
636 /*
637 * TODO: copyout values for r, g, b. This function should be
638 * driver-specific...
639 */
640
641 return 0;
642 }
643
644 int
645 grf_wsaoputcmap(void *c, void *data)
646 {
647 /*
648 * We probably couldn't care less about color map in MODE_EMUL,
649 * I don't know about X11 yet. Also, these ioctls could be used by
650 * fullscreen console programs (think wsdisplay picture viewer, or
651 * the wsimgshow tool written by Yasushi Oshima).
652 */
653 struct grf_softc *gp;
654
655 gp = c;
656
657 if (gp->g_wsmode == WSDISPLAYIO_MODE_EMUL)
658 return EINVAL;
659 /* ... */
660
661 return 0;
662 }
663
664 int
665 grf_wsaosvideo(void *c, void *data)
666 {
667 #if 0
668 struct grf_softc *gp;
669 dev_t dev;
670 int rv;
671
672 gp = c;
673 dev = (dev_t) &gp->g_grfdev;
674
675 if (*(u_int *)data == WSDISPLAYIO_VIDEO_OFF) {
676 if ((gp->g_flags & GF_GRFON) == 0)
677 rv = 0;
678 else {
679 gp->g_flags &= ~GF_GRFON;
680 rv = gp->g_mode(gp, (dev & GRFOVDEV) ?
681 GM_GRFOVOFF : GM_GRFOFF, NULL, 0, 0);
682 }
683
684 } else {
685 if ((gp->g_flags & GF_GRFON))
686 rv = 0;
687 else
688 gp->g_flags |= GF_GRFON;
689 rv = gp->g_mode(gp, (dev & GRFOVDEV) ?
690 GM_GRFOVON : GM_GRFON, NULL, 0, 0);
691 }
692
693 return rv;
694 #endif
695 return 0;
696 }
697
698 int
699 grf_wsaogvideo(void *c, void *data)
700 {
701 struct grf_softc *gp;
702
703 gp = c;
704
705 if(gp->g_flags & GF_GRFON)
706 *(u_int *)data = WSDISPLAYIO_VIDEO_ON;
707 else
708 *(u_int *)data = WSDISPLAYIO_VIDEO_OFF;
709
710 return 0;
711 }
712
713 int
714 grf_wsaogtype(void *c, void *data)
715 {
716 struct grf_softc *gp;
717
718 gp = c;
719
720 *(u_int *)data = WSDISPLAY_TYPE_GRF;
721 return 0;
722 }
723
724 int
725 grf_wsaogmode(void *c, void *data)
726 {
727 struct grf_softc *gp;
728
729 gp = c;
730
731 *(u_int *)data = gp->g_wsmode;
732 return 0;
733 }
734
735 int
736 grf_wsaosmode(void *c, void *data)
737 {
738 /* XXX: should provide hw-dependent impl of this in grf_xxx driver? */
739 struct grf_softc *gp;
740
741 gp = c;
742
743 if ((*(int*) data) != gp->g_wsmode) {
744 gp->g_wsmode = (*(int*) data);
745 if ((*(int*) data) == WSDISPLAYIO_MODE_EMUL) {
746 //vcons_redraw_screen( active vcons screen );
747 }
748 }
749 return 0;
750 }
751
752 int
753 grf_wsaoginfo(void *c, void *data)
754 {
755 struct wsdisplay_fbinfo *fbinfo;
756 struct grf_softc *gp;
757 struct grfinfo *gi;
758
759 gp = c;
760
761 fbinfo = (struct wsdisplay_fbinfo *)data;
762 gi = &gp->g_display;
763
764 /*
765 * TODO: better sanity checking, it is possible that
766 * wsdisplay is initialized, but no screen is opened
767 * (for example, device is not used).
768 */
769
770 /*
771 * We shold return truth about current mode here because
772 * X11 wsfb driver denepds on this!
773 */
774 fbinfo->height = gi->gd_fbheight;
775 fbinfo->width = gi->gd_fbwidth;
776 fbinfo->depth = gi->gd_planes;
777 fbinfo->cmsize = gi->gd_colors;
778
779 return 0;
780 }
781
782 #endif /* NWSDISPLAY > 0 */
783
784 #ifdef DEBUG
785 void
786 grfdebug(struct grf_softc *gp, const char *fmt, ...)
787 {
788 static int ccol = 0, crow = 1;
789 volatile char *cp;
790 char buf[256];
791 va_list ap;
792 int ncols;
793 char *bp;
794
795 va_start(ap, fmt);
796 vsnprintf(buf, 256, fmt, ap);
797 va_end(ap);
798
799 cp = gp->g_fbkva;
800 ncols = gp->g_display.gd_fbwidth / 8;
801 cp += (crow * ncols + ccol) << 2;
802 for (bp = buf; *bp != '\0'; bp++) {
803 if (*bp == '\n') {
804 ccol = 0;
805 crow++;
806 continue;
807 }
808 *cp++ = *bp;
809 *cp = 0x0a;
810 cp += 3;
811 ccol++;
812 }
813 }
814 #endif /* DEBUG */
815
816 #endif /* NGRF > 0 */
817