FreeBSD/Linux Kernel Cross Reference
sys/pc98/cbus/gdc.c
1 /*-
2 * Copyright (c) 1999 FreeBSD(98) port team.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer as
10 * the first lines of this file unmodified.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD$
29 */
30
31 #include "opt_gdc.h"
32 #include "opt_fb.h"
33 #include "opt_syscons.h"
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/conf.h>
40 #include <sys/bus.h>
41 #include <machine/bus.h>
42 #include <sys/rman.h>
43 #include <machine/resource.h>
44
45 #include <sys/fbio.h>
46 #include <sys/fcntl.h>
47
48 #include <vm/vm.h>
49 #include <vm/pmap.h>
50 #include <vm/vm_param.h>
51
52 #include <machine/md_var.h>
53 #include <machine/pc/bios.h>
54
55 #include <dev/fb/fbreg.h>
56
57 #ifdef LINE30
58 #include <pc98/cbus/cbus.h>
59 #endif
60 #include <pc98/pc98/pc98_machdep.h>
61 #include <isa/isavar.h>
62
63 #define TEXT_GDC 0x60
64 #define GRAPHIC_GDC 0xa0
65 #define ROW 25
66 #define COL 80
67
68 #define DRIVER_NAME "gdc"
69
70 /* cdev driver declaration */
71
72 #define GDC_UNIT(dev) dev2unit(dev)
73 #define GDC_MKMINOR(unit) (unit)
74
75 typedef struct gdc_softc {
76 video_adapter_t *adp;
77 struct resource *res_tgdc, *res_ggdc;
78 struct resource *res_egc, *res_pegc, *res_grcg, *res_kcg;
79 struct resource *res_tmem, *res_gmem1, *res_gmem2;
80 #ifdef FB_INSTALL_CDEV
81 genfb_softc_t gensc;
82 #endif
83 } gdc_softc_t;
84
85 #define GDC_SOFTC(unit) \
86 ((gdc_softc_t *)devclass_get_softc(gdc_devclass, unit))
87
88 static bus_addr_t gdc_iat[] = {0, 2, 4, 6, 8, 10, 12, 14};
89
90 static devclass_t gdc_devclass;
91
92 static int gdc_probe_unit(int unit, gdc_softc_t *sc, int flags);
93 static int gdc_attach_unit(int unit, gdc_softc_t *sc, int flags);
94 static int gdc_alloc_resource(device_t dev);
95 static int gdc_release_resource(device_t dev);
96
97 #ifdef FB_INSTALL_CDEV
98
99 static d_open_t gdcopen;
100 static d_close_t gdcclose;
101 static d_read_t gdcread;
102 static d_write_t gdcwrite;
103 static d_ioctl_t gdcioctl;
104 static d_mmap_t gdcmmap;
105
106 static struct cdevsw gdc_cdevsw = {
107 .d_version = D_VERSION,
108 .d_flags = D_NEEDGIANT,
109 .d_open = gdcopen,
110 .d_close = gdcclose,
111 .d_read = gdcread,
112 .d_write = gdcwrite,
113 .d_ioctl = gdcioctl,
114 .d_mmap = gdcmmap,
115 .d_name = DRIVER_NAME,
116 };
117
118 #endif /* FB_INSTALL_CDEV */
119
120 static void
121 gdc_identify(driver_t *driver, device_t parent)
122 {
123 BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, DRIVER_NAME, 0);
124 }
125
126 static int
127 gdcprobe(device_t dev)
128 {
129 int error;
130
131 /* Check isapnp ids */
132 if (isa_get_vendorid(dev))
133 return (ENXIO);
134
135 device_set_desc(dev, "Generic GDC");
136
137 error = gdc_alloc_resource(dev);
138 if (error)
139 return (error);
140
141 error = gdc_probe_unit(device_get_unit(dev),
142 device_get_softc(dev),
143 device_get_flags(dev));
144
145 gdc_release_resource(dev);
146
147 return (error);
148 }
149
150 static int
151 gdc_attach(device_t dev)
152 {
153 gdc_softc_t *sc;
154 int error;
155
156 error = gdc_alloc_resource(dev);
157 if (error)
158 return (error);
159
160 sc = device_get_softc(dev);
161 error = gdc_attach_unit(device_get_unit(dev),
162 sc,
163 device_get_flags(dev));
164 if (error) {
165 gdc_release_resource(dev);
166 return error;
167 }
168
169 #ifdef FB_INSTALL_CDEV
170 /* attach a virtual frame buffer device */
171 error = fb_attach(GDC_MKMINOR(device_get_unit(dev)),
172 sc->adp, &gdc_cdevsw);
173 if (error) {
174 gdc_release_resource(dev);
175 return error;
176 }
177 #endif /* FB_INSTALL_CDEV */
178
179 if (bootverbose)
180 vidd_diag(sc->adp, bootverbose);
181
182 return 0;
183 }
184
185 static int
186 gdc_probe_unit(int unit, gdc_softc_t *sc, int flags)
187 {
188 video_switch_t *sw;
189
190 sw = vid_get_switch(DRIVER_NAME);
191 if (sw == NULL)
192 return ENXIO;
193 return (*sw->probe)(unit, &sc->adp, NULL, flags);
194 }
195
196 static int
197 gdc_attach_unit(int unit, gdc_softc_t *sc, int flags)
198 {
199 video_switch_t *sw;
200
201 sw = vid_get_switch(DRIVER_NAME);
202 if (sw == NULL)
203 return ENXIO;
204 return (*sw->init)(unit, sc->adp, flags);
205 }
206
207
208 static int
209 gdc_alloc_resource(device_t dev)
210 {
211 int rid;
212 gdc_softc_t *sc;
213
214 sc = device_get_softc(dev);
215
216 /* TEXT GDC */
217 rid = 0;
218 bus_set_resource(dev, SYS_RES_IOPORT, rid, TEXT_GDC, 1);
219 sc->res_tgdc = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
220 gdc_iat, 8, RF_ACTIVE);
221 if (sc->res_tgdc == NULL) {
222 gdc_release_resource(dev);
223 return (ENXIO);
224 }
225 isa_load_resourcev(sc->res_tgdc, gdc_iat, 8);
226
227 /* GRAPHIC GDC */
228 rid = 8;
229 bus_set_resource(dev, SYS_RES_IOPORT, rid, GRAPHIC_GDC, 1);
230 sc->res_ggdc = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
231 gdc_iat, 8, RF_ACTIVE);
232 if (sc->res_ggdc == NULL) {
233 gdc_release_resource(dev);
234 return (ENXIO);
235 }
236 isa_load_resourcev(sc->res_ggdc, gdc_iat, 8);
237
238 /* EGC */
239 rid = 16;
240 bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x4a0, 1);
241 sc->res_egc = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
242 gdc_iat, 8, RF_ACTIVE);
243 if (sc->res_egc == NULL) {
244 gdc_release_resource(dev);
245 return (ENXIO);
246 }
247 isa_load_resourcev(sc->res_egc, gdc_iat, 8);
248
249 /* PEGC */
250 rid = 24;
251 bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x9a0, 1);
252 sc->res_pegc = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
253 gdc_iat, 8, RF_ACTIVE);
254 if (sc->res_pegc == NULL) {
255 gdc_release_resource(dev);
256 return (ENXIO);
257 }
258 isa_load_resourcev(sc->res_pegc, gdc_iat, 8);
259
260 /* CRTC/GRCG */
261 rid = 32;
262 bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x70, 1);
263 sc->res_grcg = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
264 gdc_iat, 8, RF_ACTIVE);
265 if (sc->res_grcg == NULL) {
266 gdc_release_resource(dev);
267 return (ENXIO);
268 }
269 isa_load_resourcev(sc->res_grcg, gdc_iat, 8);
270
271 /* KCG */
272 rid = 40;
273 bus_set_resource(dev, SYS_RES_IOPORT, rid, 0xa1, 1);
274 sc->res_kcg = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
275 gdc_iat, 8, RF_ACTIVE);
276 if (sc->res_kcg == NULL) {
277 gdc_release_resource(dev);
278 return (ENXIO);
279 }
280 isa_load_resourcev(sc->res_kcg, gdc_iat, 8);
281
282
283 /* TEXT Memory */
284 rid = 0;
285 sc->res_tmem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
286 0xa0000, 0xa4fff, 0x5000, RF_ACTIVE);
287 if (sc->res_tmem == NULL) {
288 gdc_release_resource(dev);
289 return (ENXIO);
290 }
291
292 /* GRAPHIC Memory */
293 rid = 1;
294 sc->res_gmem1 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
295 0xa8000, 0xbffff, 0x18000,
296 RF_ACTIVE);
297 if (sc->res_gmem1 == NULL) {
298 gdc_release_resource(dev);
299 return (ENXIO);
300 }
301 rid = 2;
302 sc->res_gmem2 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
303 0xe0000, 0xe7fff, 0x8000,
304 RF_ACTIVE);
305 if (sc->res_gmem2 == NULL) {
306 gdc_release_resource(dev);
307 return (ENXIO);
308 }
309
310 return (0);
311 }
312
313 static int
314 gdc_release_resource(device_t dev)
315 {
316 gdc_softc_t *sc;
317
318 sc = device_get_softc(dev);
319
320 if (sc->res_tgdc)
321 bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->res_tgdc);
322 if (sc->res_ggdc)
323 bus_release_resource(dev, SYS_RES_IOPORT, 8, sc->res_ggdc);
324 if (sc->res_egc)
325 bus_release_resource(dev, SYS_RES_IOPORT, 16, sc->res_egc);
326 if (sc->res_pegc)
327 bus_release_resource(dev, SYS_RES_IOPORT, 24, sc->res_pegc);
328 if (sc->res_grcg)
329 bus_release_resource(dev, SYS_RES_IOPORT, 32, sc->res_grcg);
330 if (sc->res_kcg)
331 bus_release_resource(dev, SYS_RES_IOPORT, 40, sc->res_kcg);
332
333 if (sc->res_tmem)
334 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res_tmem);
335 if (sc->res_gmem1)
336 bus_release_resource(dev, SYS_RES_MEMORY, 1, sc->res_gmem1);
337 if (sc->res_gmem2)
338 bus_release_resource(dev, SYS_RES_MEMORY, 2, sc->res_gmem2);
339
340 return (0);
341 }
342
343 /* cdev driver functions */
344
345 #ifdef FB_INSTALL_CDEV
346
347 static int
348 gdcopen(struct cdev *dev, int flag, int mode, struct thread *td)
349 {
350 gdc_softc_t *sc;
351
352 sc = GDC_SOFTC(GDC_UNIT(dev));
353 if (sc == NULL)
354 return ENXIO;
355 if (mode & (O_CREAT | O_APPEND | O_TRUNC))
356 return ENODEV;
357
358 return genfbopen(&sc->gensc, sc->adp, flag, mode, td);
359 }
360
361 static int
362 gdcclose(struct cdev *dev, int flag, int mode, struct thread *td)
363 {
364 gdc_softc_t *sc;
365
366 sc = GDC_SOFTC(GDC_UNIT(dev));
367 return genfbclose(&sc->gensc, sc->adp, flag, mode, td);
368 }
369
370 static int
371 gdcread(struct cdev *dev, struct uio *uio, int flag)
372 {
373 gdc_softc_t *sc;
374
375 sc = GDC_SOFTC(GDC_UNIT(dev));
376 return genfbread(&sc->gensc, sc->adp, uio, flag);
377 }
378
379 static int
380 gdcwrite(struct cdev *dev, struct uio *uio, int flag)
381 {
382 gdc_softc_t *sc;
383
384 sc = GDC_SOFTC(GDC_UNIT(dev));
385 return genfbread(&sc->gensc, sc->adp, uio, flag);
386 }
387
388 static int
389 gdcioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
390 {
391 gdc_softc_t *sc;
392
393 sc = GDC_SOFTC(GDC_UNIT(dev));
394 return genfbioctl(&sc->gensc, sc->adp, cmd, arg, flag, td);
395 }
396
397 static int
398 gdcmmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
399 int prot, vm_memattr_t *memattr)
400 {
401 gdc_softc_t *sc;
402
403 sc = GDC_SOFTC(GDC_UNIT(dev));
404 return genfbmmap(&sc->gensc, sc->adp, offset, paddr, prot, memattr);
405 }
406
407 #endif /* FB_INSTALL_CDEV */
408
409 static device_method_t gdc_methods[] = {
410 DEVMETHOD(device_identify, gdc_identify),
411 DEVMETHOD(device_probe, gdcprobe),
412 DEVMETHOD(device_attach, gdc_attach),
413 { 0, 0 }
414 };
415
416 static driver_t gdcdriver = {
417 DRIVER_NAME,
418 gdc_methods,
419 sizeof(gdc_softc_t),
420 };
421
422 DRIVER_MODULE(gdc, isa, gdcdriver, gdc_devclass, 0, 0);
423
424 /* LOW-LEVEL */
425
426
427 #include <pc98/cbus/30line.h>
428
429 #define TEXT_BUF_BASE 0x000a0000
430 #define TEXT_BUF_SIZE 0x00008000
431 #define GRAPHICS_BUF_BASE 0x000a8000
432 #define GRAPHICS_BUF_SIZE 0x00040000
433 #define VIDEO_BUF_BASE 0x000a0000
434 #define VIDEO_BUF_SIZE 0x00048000
435
436 #define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED)
437 #define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED)
438 #define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED)
439
440 /*
441 * NOTE: `va_window' should have a virtual address, but is initialized
442 * with a physical address in the following table, they will be
443 * converted at run-time.
444 */
445 static video_adapter_t adapter_init_value[] = {
446 { 0,
447 KD_PC98, "gdc", /* va_type, va_name */
448 0, 0, /* va_unit, va_minor */
449 V_ADP_COLOR | V_ADP_MODECHANGE | V_ADP_BORDER,
450 TEXT_GDC, 16, TEXT_GDC, /* va_io*, XXX */
451 VIDEO_BUF_BASE, VIDEO_BUF_SIZE, /* va_mem* */
452 TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, /* va_window* */
453 0, 0, /* va_buffer, va_buffer_size */
454 0, M_PC98_80x25, 0, /* va_*mode* */
455 },
456 };
457
458 static video_adapter_t biosadapter[1];
459
460 /* video driver declarations */
461 static int gdc_configure(int flags);
462 static int gdc_err(video_adapter_t *adp, ...);
463 static vi_probe_t gdc_probe;
464 static vi_init_t gdc_init;
465 static vi_get_info_t gdc_get_info;
466 static vi_query_mode_t gdc_query_mode;
467 static vi_set_mode_t gdc_set_mode;
468 static vi_set_border_t gdc_set_border;
469 static vi_save_state_t gdc_save_state;
470 static vi_load_state_t gdc_load_state;
471 static vi_read_hw_cursor_t gdc_read_hw_cursor;
472 static vi_set_hw_cursor_t gdc_set_hw_cursor;
473 static vi_set_hw_cursor_shape_t gdc_set_hw_cursor_shape;
474 static vi_blank_display_t gdc_blank_display;
475 static vi_mmap_t gdc_mmap_buf;
476 static vi_ioctl_t gdc_dev_ioctl;
477 static vi_clear_t gdc_clear;
478 static vi_fill_rect_t gdc_fill_rect;
479 static vi_bitblt_t gdc_bitblt;
480 static vi_diag_t gdc_diag;
481 static vi_save_palette_t gdc_save_palette;
482 static vi_load_palette_t gdc_load_palette;
483 static vi_set_win_org_t gdc_set_origin;
484
485 static video_switch_t gdcvidsw = {
486 gdc_probe,
487 gdc_init,
488 gdc_get_info,
489 gdc_query_mode,
490 gdc_set_mode,
491 (vi_save_font_t *)gdc_err,
492 (vi_load_font_t *)gdc_err,
493 (vi_show_font_t *)gdc_err,
494 gdc_save_palette,
495 gdc_load_palette,
496 gdc_set_border,
497 gdc_save_state,
498 gdc_load_state,
499 gdc_set_origin,
500 gdc_read_hw_cursor,
501 gdc_set_hw_cursor,
502 gdc_set_hw_cursor_shape,
503 gdc_blank_display,
504 gdc_mmap_buf,
505 gdc_dev_ioctl,
506 gdc_clear,
507 gdc_fill_rect,
508 gdc_bitblt,
509 (int (*)(void))gdc_err,
510 (int (*)(void))gdc_err,
511 gdc_diag,
512 };
513
514 VIDEO_DRIVER(gdc, gdcvidsw, gdc_configure);
515
516 /* GDC BIOS standard video modes */
517 #define EOT (-1)
518 #define NA (-2)
519
520 static video_info_t bios_vmode[] = {
521 { M_PC98_80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1,
522 TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
523 #ifdef LINE30
524 { M_PC98_80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1,
525 TEXT_BUF_BASE, TEXT_BUF_SIZE, TEXT_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
526 #endif
527 #ifndef GDC_NOGRAPHICS
528 { M_PC98_EGC640x400, V_INFO_COLOR | V_INFO_GRAPHICS,
529 640, 400, 8, 16, 4, 4,
530 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0,
531 V_INFO_MM_PLANAR },
532 { M_PC98_PEGC640x400, V_INFO_COLOR | V_INFO_GRAPHICS | V_INFO_VESA,
533 640, 400, 8, 16, 8, 1,
534 GRAPHICS_BUF_BASE, 0x00008000, 0x00008000, 0, 0,
535 V_INFO_MM_PACKED, 1 },
536 #ifdef LINE30
537 { M_PC98_PEGC640x480, V_INFO_COLOR | V_INFO_GRAPHICS | V_INFO_VESA,
538 640, 480, 8, 16, 8, 1,
539 GRAPHICS_BUF_BASE, 0x00008000, 0x00008000, 0, 0,
540 V_INFO_MM_PACKED, 1 },
541 #endif
542 #endif
543 { EOT },
544 };
545
546 static int gdc_init_done = FALSE;
547
548 /* local functions */
549 static int map_gen_mode_num(int type, int color, int mode);
550 static int probe_adapters(void);
551
552 #define prologue(adp, flag, err) \
553 if (!gdc_init_done || !((adp)->va_flags & (flag))) \
554 return (err)
555
556 /* a backdoor for the console driver */
557 static int
558 gdc_configure(int flags)
559 {
560 probe_adapters();
561 biosadapter[0].va_flags |= V_ADP_INITIALIZED;
562 if (!config_done(&biosadapter[0])) {
563 if (vid_register(&biosadapter[0]) < 0)
564 return 1;
565 biosadapter[0].va_flags |= V_ADP_REGISTERED;
566 }
567
568 return 1;
569 }
570
571 /* local subroutines */
572
573 /* map a generic video mode to a known mode number */
574 static int
575 map_gen_mode_num(int type, int color, int mode)
576 {
577 static struct {
578 int from;
579 int to;
580 } mode_map[] = {
581 { M_TEXT_80x25, M_PC98_80x25, },
582 #ifdef LINE30
583 { M_TEXT_80x30, M_PC98_80x30, },
584 #endif
585 };
586 int i;
587
588 for (i = 0; i < nitems(mode_map); ++i) {
589 if (mode_map[i].from == mode)
590 return mode_map[i].to;
591 }
592 return mode;
593 }
594
595 static int
596 verify_adapter(video_adapter_t *adp)
597 {
598 #ifndef GDC_NOGRAPHICS
599 int i;
600
601 if (PC98_SYSTEM_PARAMETER(0x45c) & 0x40) { /* PEGC exists */
602 adp->va_flags |= V_ADP_VESA; /* XXX */
603 } else {
604 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
605 if (bios_vmode[i].vi_flags & V_INFO_VESA)
606 bios_vmode[i].vi_mode = NA;
607 }
608 }
609 #endif
610 return 0;
611 }
612
613 /* probe video adapters and return the number of detected adapters */
614 static int
615 probe_adapters(void)
616 {
617 video_info_t info;
618
619 /* do this test only once */
620 if (gdc_init_done)
621 return 1;
622 gdc_init_done = TRUE;
623
624 biosadapter[0] = adapter_init_value[0];
625 biosadapter[0].va_flags |= V_ADP_PROBED;
626 biosadapter[0].va_mode =
627 biosadapter[0].va_initial_mode = biosadapter[0].va_initial_bios_mode;
628
629 if ((PC98_SYSTEM_PARAMETER(0x597) & 0x80) ||
630 (PC98_SYSTEM_PARAMETER(0x458) & 0x80)) {
631 gdc_FH = (inb(0x9a8) & 1) ? _31KHZ : _24KHZ;
632 } else {
633 gdc_FH = _24KHZ;
634 }
635
636 gdc_get_info(&biosadapter[0], biosadapter[0].va_initial_mode, &info);
637 initialize_gdc(T25_G400, info.vi_flags & V_INFO_GRAPHICS);
638
639 biosadapter[0].va_window = BIOS_PADDRTOVADDR(info.vi_window);
640 biosadapter[0].va_window_size = info.vi_window_size;
641 biosadapter[0].va_window_gran = info.vi_window_gran;
642 biosadapter[0].va_buffer = 0;
643 biosadapter[0].va_buffer_size = 0;
644 if (info.vi_flags & V_INFO_GRAPHICS) {
645 switch (info.vi_depth/info.vi_planes) {
646 case 1:
647 biosadapter[0].va_line_width = info.vi_width/8;
648 break;
649 case 2:
650 biosadapter[0].va_line_width = info.vi_width/4;
651 break;
652 case 4:
653 biosadapter[0].va_line_width = info.vi_width/2;
654 break;
655 case 8:
656 default: /* shouldn't happen */
657 biosadapter[0].va_line_width = info.vi_width;
658 break;
659 }
660 } else {
661 biosadapter[0].va_line_width = info.vi_width;
662 }
663 bcopy(&info, &biosadapter[0].va_info, sizeof(info));
664
665 verify_adapter(&biosadapter[0]);
666
667 return 1;
668 }
669
670 static void master_gdc_cmd(unsigned int cmd)
671 {
672 while ( (inb(TEXT_GDC) & 2) != 0);
673 outb(TEXT_GDC+2, cmd);
674 }
675
676 static void master_gdc_prm(unsigned int pmtr)
677 {
678 while ( (inb(TEXT_GDC) & 2) != 0);
679 outb(TEXT_GDC, pmtr);
680 }
681
682 static void master_gdc_word_prm(unsigned int wpmtr)
683 {
684 master_gdc_prm(wpmtr & 0x00ff);
685 master_gdc_prm((wpmtr >> 8) & 0x00ff);
686 }
687
688 #ifdef LINE30
689 static void master_gdc_fifo_empty(void)
690 {
691 while ( (inb(TEXT_GDC) & 4) == 0);
692 }
693 #endif
694
695 static void master_gdc_wait_vsync(void)
696 {
697 while ( (inb(TEXT_GDC) & 0x20) != 0);
698 while ( (inb(TEXT_GDC) & 0x20) == 0);
699 }
700
701 static void gdc_cmd(unsigned int cmd)
702 {
703 while ( (inb(GRAPHIC_GDC) & 2) != 0);
704 outb( GRAPHIC_GDC+2, cmd);
705 }
706
707 #ifdef LINE30
708 static void gdc_prm(unsigned int pmtr)
709 {
710 while ( (inb(GRAPHIC_GDC) & 2) != 0);
711 outb( GRAPHIC_GDC, pmtr);
712 }
713
714 static void gdc_word_prm(unsigned int wpmtr)
715 {
716 gdc_prm(wpmtr & 0x00ff);
717 gdc_prm((wpmtr >> 8) & 0x00ff);
718 }
719
720 static void gdc_fifo_empty(void)
721 {
722 while ( (inb(GRAPHIC_GDC) & 0x04) == 0);
723 }
724 #endif
725
726 static void gdc_wait_vsync(void)
727 {
728 while ( (inb(GRAPHIC_GDC) & 0x20) != 0);
729 while ( (inb(GRAPHIC_GDC) & 0x20) == 0);
730 }
731
732 #ifdef LINE30
733 static int check_gdc_clock(void)
734 {
735 if ((inb(IO_SYSPORT) & 0x80) == 0){
736 return _5MHZ;
737 } else {
738 return _2_5MHZ;
739 }
740 }
741 #endif
742
743 static void initialize_gdc(unsigned int mode, int isGraph)
744 {
745 #ifdef LINE30
746 /* start 30line initialize */
747 int m_mode, s_mode, gdc_clock, hsync_clock;
748
749 gdc_clock = check_gdc_clock();
750 m_mode = (mode == T25_G400) ? _25L : _30L;
751 s_mode = 2*mode+gdc_clock;
752 gdc_INFO = m_mode;
753
754 master_gdc_wait_vsync();
755
756 if ((PC98_SYSTEM_PARAMETER(0x597) & 0x80) ||
757 (PC98_SYSTEM_PARAMETER(0x458) & 0x80)) {
758 if (PC98_SYSTEM_PARAMETER(0x481) & 0x08) {
759 hsync_clock = (m_mode == _25L) ? gdc_FH : _31KHZ;
760 outb(0x9a8, (hsync_clock == _31KHZ) ? 1 : 0);
761 } else {
762 hsync_clock = gdc_FH;
763 }
764 } else {
765 hsync_clock = _24KHZ;
766 }
767
768 if ((gdc_clock == _2_5MHZ) &&
769 (slave_param[hsync_clock][s_mode][GDC_LF] > 400)) {
770 outb(0x6a, 0x83);
771 outb(0x6a, 0x85);
772 gdc_clock = _5MHZ;
773 s_mode = 2*mode+gdc_clock;
774 }
775
776 master_gdc_cmd(_GDC_RESET);
777 master_gdc_cmd(_GDC_MASTER);
778 gdc_cmd(_GDC_RESET);
779 gdc_cmd(_GDC_SLAVE);
780
781 /* GDC Master */
782 master_gdc_cmd(_GDC_SYNC);
783 master_gdc_prm(0x00); /* flush less */ /* text & graph */
784 master_gdc_prm(master_param[hsync_clock][m_mode][GDC_CR]);
785 master_gdc_word_prm(((master_param[hsync_clock][m_mode][GDC_HFP] << 10)
786 + (master_param[hsync_clock][m_mode][GDC_VS] << 5)
787 + master_param[hsync_clock][m_mode][GDC_HS]));
788 master_gdc_prm(master_param[hsync_clock][m_mode][GDC_HBP]);
789 master_gdc_prm(master_param[hsync_clock][m_mode][GDC_VFP]);
790 master_gdc_word_prm(((master_param[hsync_clock][m_mode][GDC_VBP] << 10)
791 + (master_param[hsync_clock][m_mode][GDC_LF])));
792 master_gdc_fifo_empty();
793 master_gdc_cmd(_GDC_PITCH);
794 master_gdc_prm(MasterPCH);
795 master_gdc_fifo_empty();
796
797 /* GDC slave */
798 gdc_cmd(_GDC_SYNC);
799 gdc_prm(0x06);
800 gdc_prm(slave_param[hsync_clock][s_mode][GDC_CR]);
801 gdc_word_prm((slave_param[hsync_clock][s_mode][GDC_HFP] << 10)
802 + (slave_param[hsync_clock][s_mode][GDC_VS] << 5)
803 + (slave_param[hsync_clock][s_mode][GDC_HS]));
804 gdc_prm(slave_param[hsync_clock][s_mode][GDC_HBP]);
805 gdc_prm(slave_param[hsync_clock][s_mode][GDC_VFP]);
806 gdc_word_prm((slave_param[hsync_clock][s_mode][GDC_VBP] << 10)
807 + (slave_param[hsync_clock][s_mode][GDC_LF]));
808 gdc_fifo_empty();
809 gdc_cmd(_GDC_PITCH);
810 gdc_prm(SlavePCH[gdc_clock]);
811 gdc_fifo_empty();
812
813 /* set Master GDC scroll param */
814 master_gdc_wait_vsync();
815 master_gdc_wait_vsync();
816 master_gdc_wait_vsync();
817 master_gdc_cmd(_GDC_SCROLL);
818 master_gdc_word_prm(0);
819 master_gdc_word_prm((master_param[hsync_clock][m_mode][GDC_LF] << 4)
820 | 0x0000);
821 master_gdc_fifo_empty();
822
823 /* set Slave GDC scroll param */
824 gdc_wait_vsync();
825 gdc_cmd(_GDC_SCROLL);
826 gdc_word_prm(0);
827 if (gdc_clock == _5MHZ) {
828 gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000);
829 } else {
830 gdc_word_prm(SlaveScrlLF[mode] << 4);
831 }
832 gdc_fifo_empty();
833
834 gdc_word_prm(0);
835 if (gdc_clock == _5MHZ) {
836 gdc_word_prm((SlaveScrlLF[mode] << 4) | 0x4000);
837 } else {
838 gdc_word_prm(SlaveScrlLF[mode] << 4);
839 }
840 gdc_fifo_empty();
841
842 /* sync start */
843 gdc_cmd(isGraph ? _GDC_START : _GDC_STOP);
844
845 gdc_wait_vsync();
846 gdc_wait_vsync();
847 gdc_wait_vsync();
848
849 master_gdc_cmd(isGraph ? _GDC_STOP : _GDC_START);
850 #else
851 master_gdc_wait_vsync();
852 master_gdc_cmd(isGraph ? _GDC_STOP : _GDC_START); /* text */
853 gdc_wait_vsync();
854 gdc_cmd(isGraph ? _GDC_START : _GDC_STOP); /* graphics */
855 #endif
856 }
857
858 #ifndef GDC_NOGRAPHICS
859 static u_char b_palette[] = {
860 /* R G B */
861 0x00, 0x00, 0x00, /* 0 */
862 0x00, 0x00, 0x7f, /* 1 */
863 0x7f, 0x00, 0x00, /* 2 */
864 0x7f, 0x00, 0x7f, /* 3 */
865 0x00, 0x7f, 0x00, /* 4 */
866 0x00, 0x7f, 0x7f, /* 5 */
867 0x7f, 0x7f, 0x00, /* 6 */
868 0x7f, 0x7f, 0x7f, /* 7 */
869 0x40, 0x40, 0x40, /* 8 */
870 0x00, 0x00, 0xff, /* 9 */
871 0xff, 0x00, 0x00, /* 10 */
872 0xff, 0x00, 0xff, /* 11 */
873 0x00, 0xff, 0x00, /* 12 */
874 0x00, 0xff, 0xff, /* 13 */
875 0xff, 0xff, 0x00, /* 14 */
876 0xff, 0xff, 0xff, /* 15 */
877 };
878 #endif
879
880 static int
881 gdc_load_palette(video_adapter_t *adp, u_char *palette)
882 {
883 #ifndef GDC_NOGRAPHICS
884 int i;
885
886 if (adp->va_info.vi_flags & V_INFO_VESA) {
887 gdc_wait_vsync();
888 for (i = 0; i < 256; ++i) {
889 outb(0xa8, i);
890 outb(0xac, *palette++); /* R */
891 outb(0xaa, *palette++); /* G */
892 outb(0xae, *palette++); /* B */
893 }
894 } else {
895 /*
896 * XXX - Even though PC-98 text color is independent of palette,
897 * we should set palette in text mode.
898 * Because the background color of text mode is palette 0's one.
899 */
900 outb(0x6a, 1); /* 16 colors mode */
901 bcopy(palette, b_palette, sizeof(b_palette));
902
903 gdc_wait_vsync();
904 for (i = 0; i < 16; ++i) {
905 outb(0xa8, i);
906 outb(0xac, *palette++ >> 4); /* R */
907 outb(0xaa, *palette++ >> 4); /* G */
908 outb(0xae, *palette++ >> 4); /* B */
909 }
910 }
911 #endif
912 return 0;
913 }
914
915 static int
916 gdc_save_palette(video_adapter_t *adp, u_char *palette)
917 {
918 #ifndef GDC_NOGRAPHICS
919 int i;
920
921 if (adp->va_info.vi_flags & V_INFO_VESA) {
922 for (i = 0; i < 256; ++i) {
923 outb(0xa8, i);
924 *palette++ = inb(0xac); /* R */
925 *palette++ = inb(0xaa); /* G */
926 *palette++ = inb(0xae); /* B */
927 }
928 } else {
929 bcopy(b_palette, palette, sizeof(b_palette));
930 }
931 #endif
932 return 0;
933 }
934
935 static int
936 gdc_set_origin(video_adapter_t *adp, off_t offset)
937 {
938 #ifndef GDC_NOGRAPHICS
939 if (adp->va_info.vi_flags & V_INFO_VESA) {
940 writew(BIOS_PADDRTOVADDR(0x000e0004), offset >> 15);
941 }
942 #endif
943 return 0;
944 }
945
946 /* entry points */
947
948 static int
949 gdc_err(video_adapter_t *adp, ...)
950 {
951 return ENODEV;
952 }
953
954 static int
955 gdc_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
956 {
957 probe_adapters();
958 if (unit >= 1)
959 return ENXIO;
960
961 *adpp = &biosadapter[unit];
962
963 return 0;
964 }
965
966 static int
967 gdc_init(int unit, video_adapter_t *adp, int flags)
968 {
969 if ((unit >= 1) || (adp == NULL) || !probe_done(adp))
970 return ENXIO;
971
972 if (!init_done(adp)) {
973 /* nothing to do really... */
974 adp->va_flags |= V_ADP_INITIALIZED;
975 }
976
977 if (!config_done(adp)) {
978 if (vid_register(adp) < 0)
979 return ENXIO;
980 adp->va_flags |= V_ADP_REGISTERED;
981 }
982
983 return 0;
984 }
985
986 /*
987 * get_info():
988 * Return the video_info structure of the requested video mode.
989 */
990 static int
991 gdc_get_info(video_adapter_t *adp, int mode, video_info_t *info)
992 {
993 int i;
994
995 if (!gdc_init_done)
996 return ENXIO;
997
998 mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode);
999 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
1000 if (bios_vmode[i].vi_mode == NA)
1001 continue;
1002 if (mode == bios_vmode[i].vi_mode) {
1003 *info = bios_vmode[i];
1004 info->vi_buffer_size = info->vi_window_size*info->vi_planes;
1005 return 0;
1006 }
1007 }
1008 return EINVAL;
1009 }
1010
1011 /*
1012 * query_mode():
1013 * Find a video mode matching the requested parameters.
1014 * Fields filled with 0 are considered "don't care" fields and
1015 * match any modes.
1016 */
1017 static int
1018 gdc_query_mode(video_adapter_t *adp, video_info_t *info)
1019 {
1020 int i;
1021
1022 if (!gdc_init_done)
1023 return ENXIO;
1024
1025 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
1026 if (bios_vmode[i].vi_mode == NA)
1027 continue;
1028
1029 if ((info->vi_width != 0)
1030 && (info->vi_width != bios_vmode[i].vi_width))
1031 continue;
1032 if ((info->vi_height != 0)
1033 && (info->vi_height != bios_vmode[i].vi_height))
1034 continue;
1035 if ((info->vi_cwidth != 0)
1036 && (info->vi_cwidth != bios_vmode[i].vi_cwidth))
1037 continue;
1038 if ((info->vi_cheight != 0)
1039 && (info->vi_cheight != bios_vmode[i].vi_cheight))
1040 continue;
1041 if ((info->vi_depth != 0)
1042 && (info->vi_depth != bios_vmode[i].vi_depth))
1043 continue;
1044 if ((info->vi_planes != 0)
1045 && (info->vi_planes != bios_vmode[i].vi_planes))
1046 continue;
1047 /* XXX: should check pixel format, memory model */
1048 if ((info->vi_flags != 0)
1049 && (info->vi_flags != bios_vmode[i].vi_flags))
1050 continue;
1051
1052 /* verify if this mode is supported on this adapter */
1053 if (gdc_get_info(adp, bios_vmode[i].vi_mode, info))
1054 continue;
1055 return 0;
1056 }
1057 return ENODEV;
1058 }
1059
1060 /*
1061 * set_mode():
1062 * Change the video mode.
1063 */
1064 static int
1065 gdc_set_mode(video_adapter_t *adp, int mode)
1066 {
1067 video_info_t info;
1068
1069 prologue(adp, V_ADP_MODECHANGE, ENODEV);
1070
1071 mode = map_gen_mode_num(adp->va_type,
1072 adp->va_flags & V_ADP_COLOR, mode);
1073 if (gdc_get_info(adp, mode, &info))
1074 return EINVAL;
1075
1076 switch (info.vi_mode) {
1077 #ifndef GDC_NOGRAPHICS
1078 case M_PC98_PEGC640x480: /* PEGC 640x480 */
1079 initialize_gdc(T30_G480, info.vi_flags & V_INFO_GRAPHICS);
1080 break;
1081 case M_PC98_PEGC640x400: /* PEGC 640x400 */
1082 case M_PC98_EGC640x400: /* EGC GRAPHICS */
1083 #endif
1084 case M_PC98_80x25: /* VGA TEXT */
1085 initialize_gdc(T25_G400, info.vi_flags & V_INFO_GRAPHICS);
1086 break;
1087 case M_PC98_80x30: /* VGA TEXT */
1088 initialize_gdc(T30_G400, info.vi_flags & V_INFO_GRAPHICS);
1089 break;
1090 default:
1091 break;
1092 }
1093
1094 #ifndef GDC_NOGRAPHICS
1095 if (info.vi_flags & V_INFO_VESA) {
1096 outb(0x6a, 0x07); /* enable mode F/F change */
1097 outb(0x6a, 0x21); /* enhanced graphics */
1098 if (info.vi_height > 400)
1099 outb(0x6a, 0x69); /* 800 lines */
1100 writeb(BIOS_PADDRTOVADDR(0x000e0100), 0); /* packed pixel */
1101 } else {
1102 if (adp->va_flags & V_ADP_VESA) {
1103 outb(0x6a, 0x07); /* enable mode F/F change */
1104 outb(0x6a, 0x20); /* normal graphics */
1105 outb(0x6a, 0x68); /* 400 lines */
1106 }
1107 outb(0x6a, 1); /* 16 colors */
1108 }
1109 #endif
1110
1111 adp->va_mode = mode;
1112 adp->va_flags &= ~V_ADP_COLOR;
1113 adp->va_flags |=
1114 (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
1115 #if 0
1116 adp->va_crtc_addr =
1117 (adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
1118 #endif
1119 adp->va_window = BIOS_PADDRTOVADDR(info.vi_window);
1120 adp->va_window_size = info.vi_window_size;
1121 adp->va_window_gran = info.vi_window_gran;
1122 if (info.vi_buffer_size == 0) {
1123 adp->va_buffer = 0;
1124 adp->va_buffer_size = 0;
1125 } else {
1126 adp->va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer);
1127 adp->va_buffer_size = info.vi_buffer_size;
1128 }
1129 if (info.vi_flags & V_INFO_GRAPHICS) {
1130 switch (info.vi_depth/info.vi_planes) {
1131 case 1:
1132 adp->va_line_width = info.vi_width/8;
1133 break;
1134 case 2:
1135 adp->va_line_width = info.vi_width/4;
1136 break;
1137 case 4:
1138 adp->va_line_width = info.vi_width/2;
1139 break;
1140 case 8:
1141 default: /* shouldn't happen */
1142 adp->va_line_width = info.vi_width;
1143 break;
1144 }
1145 } else {
1146 adp->va_line_width = info.vi_width;
1147 }
1148 bcopy(&info, &adp->va_info, sizeof(info));
1149
1150 /* move hardware cursor out of the way */
1151 vidd_set_hw_cursor(adp, -1, -1);
1152
1153 return 0;
1154 }
1155
1156 /*
1157 * set_border():
1158 * Change the border color.
1159 */
1160 static int
1161 gdc_set_border(video_adapter_t *adp, int color)
1162 {
1163 outb(0x6c, color << 4);
1164 return 0;
1165 }
1166
1167 /*
1168 * save_state():
1169 * Read video card register values.
1170 */
1171 static int
1172 gdc_save_state(video_adapter_t *adp, void *p, size_t size)
1173 {
1174 return ENODEV;
1175 }
1176
1177 /*
1178 * load_state():
1179 * Set video card registers at once.
1180 */
1181 static int
1182 gdc_load_state(video_adapter_t *adp, void *p)
1183 {
1184 return ENODEV;
1185 }
1186
1187 /*
1188 * read_hw_cursor():
1189 * Read the position of the hardware text cursor.
1190 */
1191 static int
1192 gdc_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
1193 {
1194 u_int16_t off;
1195 int s;
1196
1197 if (!gdc_init_done)
1198 return ENXIO;
1199
1200 if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
1201 return ENODEV;
1202
1203 s = spltty();
1204 master_gdc_cmd(0xe0); /* _GDC_CSRR */
1205 while((inb(TEXT_GDC + 0) & 0x1) == 0) {} /* GDC wait */
1206 off = inb(TEXT_GDC + 2); /* EADl */
1207 off |= (inb(TEXT_GDC + 2) << 8); /* EADh */
1208 inb(TEXT_GDC + 2); /* dummy */
1209 inb(TEXT_GDC + 2); /* dummy */
1210 inb(TEXT_GDC + 2); /* dummy */
1211 splx(s);
1212
1213 if (off >= ROW*COL)
1214 off = 0;
1215 *row = off / adp->va_info.vi_width;
1216 *col = off % adp->va_info.vi_width;
1217
1218 return 0;
1219 }
1220
1221 /*
1222 * set_hw_cursor():
1223 * Move the hardware text cursor. If col and row are both -1,
1224 * the cursor won't be shown.
1225 */
1226 static int
1227 gdc_set_hw_cursor(video_adapter_t *adp, int col, int row)
1228 {
1229 u_int16_t off;
1230 int s;
1231
1232 if (!gdc_init_done)
1233 return ENXIO;
1234
1235 if ((col == -1) && (row == -1)) {
1236 off = -1;
1237 } else {
1238 if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
1239 return ENODEV;
1240 off = row*adp->va_info.vi_width + col;
1241 }
1242
1243 s = spltty();
1244 master_gdc_cmd(0x49); /* _GDC_CSRW */
1245 master_gdc_word_prm(off);
1246 splx(s);
1247
1248 return 0;
1249 }
1250
1251 /*
1252 * set_hw_cursor_shape():
1253 * Change the shape of the hardware text cursor. If the height is zero
1254 * or negative, the cursor won't be shown.
1255 */
1256 static int
1257 gdc_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
1258 int celsize, int blink)
1259 {
1260 int start;
1261 int end;
1262 int s;
1263
1264 if (!gdc_init_done)
1265 return ENXIO;
1266
1267 start = celsize - (base + height);
1268 end = celsize - base - 1;
1269
1270 #if 0
1271 /*
1272 * muPD7220 GDC has anomaly that if end == celsize - 1 then start
1273 * must be 0, otherwise the cursor won't be correctly shown
1274 * in the first row in the screen. We shall set end to celsize - 2;
1275 * if end == celsize -1 && start > 0. XXX
1276 */
1277 if ((end == celsize - 1) && (start > 0) && (start < end))
1278 --end;
1279 #endif
1280
1281 s = spltty();
1282 master_gdc_cmd(0x4b); /* _GDC_CSRFORM */
1283 master_gdc_prm(((height > 0) ? 0x80 : 0) /* cursor on/off */
1284 | ((celsize - 1) & 0x1f)); /* cel size */
1285 master_gdc_word_prm(((end & 0x1f) << 11) /* end line */
1286 | (12 << 6) /* blink rate */
1287 | (blink ? 0 : 0x20) /* blink on/off */
1288 | (start & 0x1f)); /* start line */
1289 splx(s);
1290
1291 return 0;
1292 }
1293
1294 /*
1295 * blank_display()
1296 * Put the display in power save/power off mode.
1297 */
1298 static int
1299 gdc_blank_display(video_adapter_t *adp, int mode)
1300 {
1301 int s;
1302 static int standby = 0;
1303
1304 if (!gdc_init_done)
1305 return ENXIO;
1306
1307 s = splhigh();
1308 switch (mode) {
1309 case V_DISPLAY_SUSPEND:
1310 case V_DISPLAY_STAND_BY:
1311 outb(0x09a2, 0x80 | 0x40); /* V/H-SYNC mask */
1312 if (inb(0x09a2) == (0x80 | 0x40))
1313 standby = 1;
1314 /* FALLTHROUGH */
1315
1316 case V_DISPLAY_BLANK:
1317 while (!(inb(TEXT_GDC) & 0x20)) /* V-SYNC wait */
1318 ;
1319 outb(TEXT_GDC + 8, 0x0e); /* DISP off */
1320 break;
1321
1322 case V_DISPLAY_ON:
1323 while (!(inb(TEXT_GDC) & 0x20)) /* V-SYNC wait */
1324 ;
1325 outb(TEXT_GDC + 8, 0x0f); /* DISP on */
1326 if (standby) {
1327 outb(0x09a2, 0x00); /* V/H-SYNC unmask */
1328 standby = 0;
1329 }
1330 break;
1331 }
1332 splx(s);
1333 return 0;
1334 }
1335
1336 /*
1337 * mmap():
1338 * Mmap frame buffer.
1339 */
1340 static int
1341 gdc_mmap_buf(video_adapter_t *adp, vm_ooffset_t offset, vm_offset_t *paddr,
1342 int prot, vm_memattr_t *memattr)
1343 {
1344 /* FIXME: is this correct? XXX */
1345 if (offset > VIDEO_BUF_SIZE - PAGE_SIZE)
1346 return -1;
1347 *paddr = adp->va_info.vi_window + offset;
1348 return 0;
1349 }
1350
1351 #ifndef GDC_NOGRAPHICS
1352 static void
1353 planar_fill(video_adapter_t *adp, int val)
1354 {
1355
1356 outb(0x7c, 0x80); /* GRCG on & TDW mode */
1357 outb(0x7e, 0); /* tile B */
1358 outb(0x7e, 0); /* tile R */
1359 outb(0x7e, 0); /* tile G */
1360 outb(0x7e, 0); /* tile I */
1361
1362 fillw_io(0, adp->va_window, 0x8000 / 2); /* XXX */
1363
1364 outb(0x7c, 0); /* GRCG off */
1365 }
1366
1367 static void
1368 packed_fill(video_adapter_t *adp, int val)
1369 {
1370 int length;
1371 int at; /* position in the frame buffer */
1372 int l;
1373
1374 at = 0;
1375 length = adp->va_line_width*adp->va_info.vi_height;
1376 while (length > 0) {
1377 l = imin(length, adp->va_window_size);
1378 vidd_set_win_org(adp, at);
1379 bzero_io(adp->va_window, l);
1380 length -= l;
1381 at += l;
1382 }
1383 }
1384
1385 static int
1386 gdc_clear(video_adapter_t *adp)
1387 {
1388
1389 switch (adp->va_info.vi_mem_model) {
1390 case V_INFO_MM_TEXT:
1391 /* do nothing? XXX */
1392 break;
1393 case V_INFO_MM_PLANAR:
1394 planar_fill(adp, 0);
1395 break;
1396 case V_INFO_MM_PACKED:
1397 packed_fill(adp, 0);
1398 break;
1399 }
1400
1401 return 0;
1402 }
1403 #else /* GDC_NOGRAPHICS */
1404 static int
1405 gdc_clear(video_adapter_t *adp)
1406 {
1407
1408 return 0;
1409 }
1410 #endif /* GDC_NOGRAPHICS */
1411
1412 static int
1413 gdc_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
1414 {
1415 return ENODEV;
1416 }
1417
1418 static int
1419 gdc_bitblt(video_adapter_t *adp,...)
1420 {
1421 /* FIXME */
1422 return ENODEV;
1423 }
1424
1425 static int
1426 gdc_dev_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
1427 {
1428 switch (cmd) {
1429 case FBIO_GETWINORG: /* get frame buffer window origin */
1430 *(u_int *)arg = 0;
1431 return 0;
1432
1433 case FBIO_SETWINORG: /* set frame buffer window origin */
1434 case FBIO_SETDISPSTART: /* set display start address */
1435 case FBIO_SETLINEWIDTH: /* set scan line length in pixel */
1436 case FBIO_GETPALETTE: /* get color palette */
1437 case FBIO_SETPALETTE: /* set color palette */
1438 case FBIOGETCMAP: /* get color palette */
1439 case FBIOPUTCMAP: /* set color palette */
1440 return ENODEV;
1441
1442 case FBIOGTYPE: /* get frame buffer type info. */
1443 ((struct fbtype *)arg)->fb_type = fb_type(adp->va_type);
1444 ((struct fbtype *)arg)->fb_height = adp->va_info.vi_height;
1445 ((struct fbtype *)arg)->fb_width = adp->va_info.vi_width;
1446 ((struct fbtype *)arg)->fb_depth = adp->va_info.vi_depth;
1447 if ((adp->va_info.vi_depth <= 1) || (adp->va_info.vi_depth > 8))
1448 ((struct fbtype *)arg)->fb_cmsize = 0;
1449 else
1450 ((struct fbtype *)arg)->fb_cmsize = 1 << adp->va_info.vi_depth;
1451 ((struct fbtype *)arg)->fb_size = adp->va_buffer_size;
1452 return 0;
1453
1454 default:
1455 return fb_commonioctl(adp, cmd, arg);
1456 }
1457 }
1458
1459 /*
1460 * diag():
1461 * Print some information about the video adapter and video modes,
1462 * with requested level of details.
1463 */
1464 static int
1465 gdc_diag(video_adapter_t *adp, int level)
1466 {
1467 #if defined(FB_DEBUG) && FB_DEBUG > 1
1468 int i;
1469 #endif
1470
1471 if (!gdc_init_done)
1472 return ENXIO;
1473
1474 fb_dump_adp_info(DRIVER_NAME, adp, level);
1475
1476 #if defined(FB_DEBUG) && FB_DEBUG > 1
1477 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
1478 if (bios_vmode[i].vi_mode == NA)
1479 continue;
1480 if (get_mode_param(bios_vmode[i].vi_mode) == NULL)
1481 continue;
1482 fb_dump_mode_info(DRIVER_NAME, adp, &bios_vmode[i], level);
1483 }
1484 #endif
1485
1486 return 0;
1487 }
Cache object: e9801698e58e80609da38c2068b9fbcb
|