Deleted Added
sdiff udiff text old ( 47640 ) new ( 48104 )
full compact
1/*-
2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
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

--- 11 unchanged lines hidden (view full) ---

20 * IN NO EVENT SHALL THE AUTHORS 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 * $Id: fb.c,v 1.5 1999/05/31 11:24:38 phk Exp $
29 */
30
31#include "fb.h"
32#include "opt_fb.h"
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/conf.h>
37#include <sys/bus.h>
38#include <sys/kernel.h>
39#include <sys/malloc.h>
40#include <sys/uio.h>
41#include <sys/fbio.h>
42
43#include <vm/vm.h>
44#include <vm/pmap.h>
45
46#include <dev/fb/fbreg.h>
47
48/* local arrays */
49
50/*
51 * We need at least one entry each in order to initialize a video card
52 * for the kernel console. The arrays will be increased dynamically
53 * when necessary.
54 */
55
56static int vid_malloc;
57static int adapters = 1;
58static video_adapter_t *adp_ini;
59static video_adapter_t **adapter = &adp_ini;
60static video_switch_t *vidsw_ini;
61 video_switch_t **vidsw = &vidsw_ini;
62
63#ifdef FB_INSTALL_CDEV
64static struct cdevsw *vidcdevsw_ini;
65static struct cdevsw **vidcdevsw = &vidcdevsw_ini;
66#endif
67
68#define ARRAY_DELTA 4
69
70static int
71vid_realloc_array(void)
72{
73 video_adapter_t **new_adp;
74 video_switch_t **new_vidsw;
75#ifdef FB_INSTALL_CDEV
76 struct cdevsw **new_cdevsw;
77#endif
78 int newsize;
79 int s;
80
81 if (!vid_malloc)
82 return ENOMEM;
83
84 s = spltty();
85 newsize = ((adapters + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA;
86 new_adp = malloc(sizeof(*new_adp)*newsize, M_DEVBUF, M_WAITOK);
87 new_vidsw = malloc(sizeof(*new_vidsw)*newsize, M_DEVBUF, M_WAITOK);
88#ifdef FB_INSTALL_CDEV
89 new_cdevsw = malloc(sizeof(*new_cdevsw)*newsize, M_DEVBUF, M_WAITOK);
90#endif
91 bzero(new_adp, sizeof(*new_adp)*newsize);
92 bzero(new_vidsw, sizeof(*new_vidsw)*newsize);
93 bcopy(adapter, new_adp, sizeof(*adapter)*adapters);
94 bcopy(vidsw, new_vidsw, sizeof(*vidsw)*adapters);
95#ifdef FB_INSTALL_CDEV
96 bzero(new_cdevsw, sizeof(*new_cdevsw)*newsize);
97 bcopy(vidcdevsw, new_cdevsw, sizeof(*vidcdevsw)*adapters);
98#endif
99 if (adapters > 1) {
100 free(adapter, M_DEVBUF);
101 free(vidsw, M_DEVBUF);
102#ifdef FB_INSTALL_CDEV
103 free(vidcdevsw, M_DEVBUF);
104#endif
105 }
106 adapter = new_adp;
107 vidsw = new_vidsw;
108#ifdef FB_INSTALL_CDEV
109 vidcdevsw = new_cdevsw;
110#endif
111 adapters = newsize;
112 splx(s);
113
114 if (bootverbose)
115 printf("fb: new array size %d\n", adapters);
116
117 return 0;
118}
119
120static void
121vid_malloc_init(void *arg)
122{
123 vid_malloc = TRUE;
124}
125
126SYSINIT(vid_mem, SI_SUB_KMEM, SI_ORDER_ANY, vid_malloc_init, NULL);
127
128/*
129 * Low-level frame buffer driver functions
130 * frame buffer subdrivers, such as the VGA driver, call these functions
131 * to initialize the video_adapter structure and register it to the virtual
132 * frame buffer driver `fb'.
133 */
134
135/* initialize the video_adapter_t structure */

--- 5 unchanged lines hidden (view full) ---

141 adp->va_type = type;
142 adp->va_unit = unit;
143}
144
145/* Register a video adapter */
146int
147vid_register(video_adapter_t *adp)
148{
149 const video_driver_t **list;
150 const video_driver_t *p;
151 int index;
152
153 for (index = 0; index < adapters; ++index) {
154 if (adapter[index] == NULL)
155 break;
156 }
157 if (index >= adapters) {
158 if (vid_realloc_array())
159 return -1;
160 }
161
162 adp->va_index = index;
163 adp->va_token = NULL;
164 list = (const video_driver_t **)videodriver_set.ls_items;
165 while ((p = *list++) != NULL) {
166 if (strcmp(p->name, adp->va_name) == 0) {
167 adapter[index] = adp;
168 vidsw[index] = p->vidsw;
169 return index;
170 }
171 }
172

--- 12 unchanged lines hidden (view full) ---

185 vidsw[adp->va_index] = NULL;
186 return 0;
187}
188
189/* Get video I/O function table */
190video_switch_t
191*vid_get_switch(char *name)
192{
193 const video_driver_t **list;
194 const video_driver_t *p;
195
196 list = (const video_driver_t **)videodriver_set.ls_items;
197 while ((p = *list++) != NULL) {
198 if (strcmp(p->name, name) == 0)
199 return p->vidsw;
200 }
201
202 return NULL;
203}
204

--- 69 unchanged lines hidden (view full) ---

274 return NULL;
275 return adapter[index];
276}
277
278/* Configure drivers: this is a backdoor for the console driver XXX */
279int
280vid_configure(int flags)
281{
282 const video_driver_t **list;
283 const video_driver_t *p;
284
285 list = (const video_driver_t **)videodriver_set.ls_items;
286 while ((p = *list++) != NULL) {
287 if (p->configure != NULL)
288 (*p->configure)(flags);
289 }
290
291 return 0;
292}
293
294/*
295 * Virtual frame buffer cdev driver functions
296 * The virtual frame buffer driver dispatches driver functions to
297 * appropriate subdrivers.
298 */
299
300#define FB_DRIVER_NAME "fb"
301
302#ifdef FB_INSTALL_CDEV
303
304#if experimental
305
306static devclass_t fb_devclass;
307
308static int fbprobe(device_t dev);
309static int fbattach(device_t dev);
310
311static device_method_t fb_methods[] = {
312 DEVMETHOD(device_probe, fbprobe),
313 DEVMETHOD(device_attach, fbattach),
314
315 DEVMETHOD(bus_print_child, bus_generic_print_child),
316 { 0, 0 }
317};
318
319static driver_t fb_driver = {
320 FB_DRIVER_NAME,
321 fb_methods,
322 0,
323};
324
325static int
326fbprobe(device_t dev)
327{
328 int unit;
329
330 unit = device_get_unit(dev);
331 if (unit >= adapters)
332 return ENXIO;
333 if (adapter[unit] == NULL)
334 return ENXIO;
335
336 device_set_desc(dev, "generic frame buffer");
337 return 0;
338}
339
340static int
341fbattach(device_t dev)
342{
343 printf("fbattach: about to attach children\n");
344 bus_generic_attach(dev);
345 return 0;
346}
347
348#endif /* experimental */
349
350#define FB_UNIT(dev) minor(dev)
351#define FB_MKMINOR(unit) (u)
352
353static d_open_t fbopen;
354static d_close_t fbclose;
355static d_read_t fbread;
356static d_write_t fbwrite;
357static d_ioctl_t fbioctl;
358static d_mmap_t fbmmap;
359
360#define CDEV_MAJOR 123 /* XXX */
361
362static struct cdevsw fb_cdevsw = {
363 /* open */ fbopen,
364 /* close */ fbclose,
365 /* read */ fbread,
366 /* write */ fbwrite,
367 /* ioctl */ fbioctl,
368 /* stop */ nostop,
369 /* reset */ noreset,
370 /* devtotty */ nodevtotty,
371 /* poll */ nopoll,
372 /* mmap */ fbmmap,
373 /* strategy */ nostrategy,
374 /* name */ FB_DRIVER_NAME,
375 /* parms */ noparms,
376 /* maj */ CDEV_MAJOR,
377 /* dump */ nodump,
378 /* psize */ nopsize,
379 /* flags */ 0,
380 /* maxio */ 0,
381 /* bmaj */ -1
382};

--- 6 unchanged lines hidden (view full) ---

389 if (!fb_devsw_installed) {
390 cdevsw_add(&fb_cdevsw);
391 fb_devsw_installed = TRUE;
392 }
393}
394
395PSEUDO_SET(vfbattach, fb);
396
397int
398fb_attach(dev_t dev, video_adapter_t *adp, struct cdevsw *cdevsw)
399{
400 int s;
401
402 if (adp->va_index >= adapters)
403 return EINVAL;
404 if (adapter[adp->va_index] != adp)
405 return EINVAL;
406
407 s = spltty();
408 adp->va_minor = minor(dev);
409 vidcdevsw[adp->va_index] = cdevsw;
410 splx(s);
411
412 /* XXX: DEVFS? */
413
414 printf("fb%d at %s%d\n", adp->va_index, adp->va_name, adp->va_unit);
415 return 0;
416}
417
418int
419fb_detach(dev_t dev, video_adapter_t *adp, struct cdevsw *cdevsw)
420{
421 int s;
422
423 if (adp->va_index >= adapters)
424 return EINVAL;
425 if (adapter[adp->va_index] != adp)
426 return EINVAL;
427 if (vidcdevsw[adp->va_index] != cdevsw)
428 return EINVAL;
429
430 s = spltty();
431 vidcdevsw[adp->va_index] = NULL;
432 splx(s);
433 return 0;
434}
435
436static int
437fbopen(dev_t dev, int flag, int mode, struct proc *p)
438{
439 int unit;
440
441 unit = FB_UNIT(dev);
442 if (unit >= adapters)
443 return ENXIO;
444 if (vidcdevsw[unit] == NULL)
445 return ENXIO;
446 return (*vidcdevsw[unit]->d_open)(makedev(0, adapter[unit]->va_minor),
447 flag, mode, p);
448}
449
450static int
451fbclose(dev_t dev, int flag, int mode, struct proc *p)
452{
453 int unit;
454
455 unit = FB_UNIT(dev);
456 if (vidcdevsw[unit] == NULL)
457 return ENXIO;
458 return (*vidcdevsw[unit]->d_close)(makedev(0, adapter[unit]->va_minor),
459 flag, mode, p);
460}
461
462static int
463fbread(dev_t dev, struct uio *uio, int flag)
464{
465 int unit;
466
467 unit = FB_UNIT(dev);
468 if (vidcdevsw[unit] == NULL)
469 return ENXIO;
470 return (*vidcdevsw[unit]->d_read)(makedev(0, adapter[unit]->va_minor),
471 uio, flag);
472}
473
474static int
475fbwrite(dev_t dev, struct uio *uio, int flag)
476{
477 int unit;
478
479 unit = FB_UNIT(dev);
480 if (vidcdevsw[unit] == NULL)
481 return ENXIO;
482 return (*vidcdevsw[unit]->d_write)(makedev(0, adapter[unit]->va_minor),
483 uio, flag);
484}
485
486static int
487fbioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
488{
489 int unit;
490
491 unit = FB_UNIT(dev);
492 if (vidcdevsw[unit] == NULL)
493 return ENXIO;
494 return (*vidcdevsw[unit]->d_ioctl)(makedev(0, adapter[unit]->va_minor),
495 cmd, arg, flag, p);
496}
497
498static int
499fbmmap(dev_t dev, vm_offset_t offset, int nprot)
500{
501 int unit;
502
503 unit = FB_UNIT(dev);
504 if (vidcdevsw[unit] == NULL)
505 return ENXIO;
506 return (*vidcdevsw[unit]->d_mmap)(makedev(0, adapter[unit]->va_minor),
507 offset, nprot);
508}
509
510#if experimental
511DEV_DRIVER_MODULE(fb, ???, fb_driver, fb_devclass,
512 CDEV_MAJOR, NOMAJ, fb_cdevsw, 0, 0);
513#endif
514
515/*
516 * Generic frame buffer cdev driver functions
517 * Frame buffer subdrivers may call these functions to implement common
518 * driver functions.
519 */
520
521int genfbopen(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
522 struct proc *p)
523{
524 int s;
525
526 s = spltty();
527 if (!(sc->gfb_flags & FB_OPEN))
528 sc->gfb_flags |= FB_OPEN;
529 splx(s);
530 return 0;
531}
532
533int genfbclose(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
534 struct proc *p)
535{
536 int s;
537
538 s = spltty();
539 sc->gfb_flags &= ~FB_OPEN;
540 splx(s);
541 return 0;
542}
543
544int genfbread(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
545 int flag)
546{
547 int size;
548 int offset;
549 int error;
550 int len;
551
552 error = 0;
553 size = adp->va_buffer_size/adp->va_info.vi_planes;
554 while (uio->uio_resid > 0) {
555 if (uio->uio_offset >= size)
556 break;
557 offset = uio->uio_offset%adp->va_window_size;
558 len = imin(uio->uio_resid, size - uio->uio_offset);
559 len = imin(len, adp->va_window_size - offset);
560 if (len <= 0)
561 break;
562 (*vidsw[adp->va_index]->set_win_org)(adp, uio->uio_offset);
563 error = uiomove((caddr_t)(adp->va_window + offset), len, uio);
564 if (error)
565 break;
566 }
567 return error;
568}
569
570int genfbwrite(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
571 int flag)
572{
573 return ENODEV;
574}
575
576int genfbioctl(genfb_softc_t *sc, video_adapter_t *adp, u_long cmd,
577 caddr_t arg, int flag, struct proc *p)
578{
579 int error;
580
581 if (adp == NULL) /* XXX */
582 return ENXIO;
583 error = (*vidsw[adp->va_index]->ioctl)(adp, cmd, arg);
584 if (error == ENOIOCTL)
585 error = ENODEV;
586 return error;
587}
588
589int genfbmmap(genfb_softc_t *sc, video_adapter_t *adp, vm_offset_t offset,
590 int prot)
591{
592 return (*vidsw[adp->va_index]->mmap)(adp, offset, prot);
593}
594
595#endif /* FB_INSTALL_CDEV */
596
597static char
598*adapter_name(int type)
599{
600 static struct {
601 int type;
602 char *name;
603 } names[] = {
604 { KD_MONO, "MDA" },
605 { KD_HERCULES, "Hercules" },
606 { KD_CGA, "CGA" },
607 { KD_EGA, "EGA" },
608 { KD_VGA, "VGA" },
609 { KD_PC98, "PC-98x1" },
610 { KD_TGA, "TGA" },
611 { -1, "Unknown" },
612 };
613 int i;
614
615 for (i = 0; names[i].type != -1; ++i)
616 if (names[i].type == type)
617 break;
618 return names[i].name;
619}
620
621/*
622 * Generic low-level frame buffer functions
623 * The low-level functions in the frame buffer subdriver may use these
624 * functions.
625 */
626
627void
628fb_dump_adp_info(char *driver, video_adapter_t *adp, int level)
629{
630 if (level <= 0)
631 return;
632
633 printf("%s%d: %s%d, %s, type:%s (%d), flags:0x%x\n",
634 FB_DRIVER_NAME, adp->va_index, driver, adp->va_unit, adp->va_name,
635 adapter_name(adp->va_type), adp->va_type, adp->va_flags);
636 printf("%s%d: port:0x%x-0x%x, crtc:0x%x, mem:0x%x 0x%x\n",
637 FB_DRIVER_NAME, adp->va_index,
638 adp->va_io_base, adp->va_io_base + adp->va_io_size - 1,
639 adp->va_crtc_addr, adp->va_mem_base, adp->va_mem_size);
640 printf("%s%d: init mode:%d, bios mode:%d, current mode:%d\n",
641 FB_DRIVER_NAME, adp->va_index,
642 adp->va_initial_mode, adp->va_initial_bios_mode, adp->va_mode);
643 printf("%s%d: window:%p size:%dk gran:%dk, buf:%p size:%dk\n",
644 FB_DRIVER_NAME, adp->va_index,
645 (void *)adp->va_window, (int)adp->va_window_size/1024,
646 (int)adp->va_window_gran/1024, (void *)adp->va_buffer,
647 (int)adp->va_buffer_size/1024);
648}
649
650void
651fb_dump_mode_info(char *driver, video_adapter_t *adp, video_info_t *info,
652 int level)
653{
654 if (level <= 0)

--- 7 unchanged lines hidden (view full) ---

662 info->vi_depth, info->vi_planes,
663 info->vi_cwidth, info->vi_cheight);
664 else
665 printf("T %dx%d, font:%dx%d, ",
666 info->vi_width, info->vi_height,
667 info->vi_cwidth, info->vi_cheight);
668 printf("win:0x%x\n", info->vi_window);
669}
670
671int
672fb_type(int adp_type)
673{
674 static struct {
675 int fb_type;
676 int va_type;
677 } types[] = {
678 { FBTYPE_MDA, KD_MONO },
679 { FBTYPE_HERCULES, KD_HERCULES },
680 { FBTYPE_CGA, KD_CGA },
681 { FBTYPE_EGA, KD_EGA },
682 { FBTYPE_VGA, KD_VGA },
683 { FBTYPE_PC98, KD_PC98 },
684 { FBTYPE_TGA, KD_TGA },
685 };
686 int i;
687
688 for (i = 0; i < sizeof(types)/sizeof(types[0]); ++i) {
689 if (types[i].va_type == adp_type)
690 return types[i].fb_type;
691 }
692 return -1;
693}
694
695int
696fb_commonioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
697{
698 int error;
699 int s;
700
701 /* assert(adp != NULL) */
702
703 error = 0;
704 s = spltty();
705
706 switch (cmd) {
707
708 case FBIO_ADAPTER: /* get video adapter index */
709 *(int *)arg = adp->va_index;
710 break;
711
712 case FBIO_ADPTYPE: /* get video adapter type */
713 *(int *)arg = adp->va_type;
714 break;
715
716 case FBIO_ADPINFO: /* get video adapter info */
717 ((video_adapter_info_t *)arg)->va_index = adp->va_index;
718 ((video_adapter_info_t *)arg)->va_type = adp->va_type;
719 bcopy(adp->va_name, ((video_adapter_info_t *)arg)->va_name,
720 imin(strlen(adp->va_name) + 1,
721 sizeof(((video_adapter_info_t *)arg)->va_name)));
722 ((video_adapter_info_t *)arg)->va_unit = adp->va_unit;
723 ((video_adapter_info_t *)arg)->va_flags = adp->va_flags;
724 ((video_adapter_info_t *)arg)->va_io_base = adp->va_io_base;
725 ((video_adapter_info_t *)arg)->va_io_size = adp->va_io_size;
726 ((video_adapter_info_t *)arg)->va_crtc_addr = adp->va_crtc_addr;
727 ((video_adapter_info_t *)arg)->va_mem_base = adp->va_mem_base;
728 ((video_adapter_info_t *)arg)->va_mem_size = adp->va_mem_size;
729 ((video_adapter_info_t *)arg)->va_window
730 = vtophys(adp->va_window);
731 ((video_adapter_info_t *)arg)->va_window_size
732 = adp->va_window_size;
733 ((video_adapter_info_t *)arg)->va_window_gran
734 = adp->va_window_gran;
735 ((video_adapter_info_t *)arg)->va_window_orig
736 = adp->va_window_orig;
737 ((video_adapter_info_t *)arg)->va_unused0
738 = (adp->va_buffer) ? vtophys(adp->va_buffer) : 0;
739 ((video_adapter_info_t *)arg)->va_buffer_size
740 = adp->va_buffer_size;
741 ((video_adapter_info_t *)arg)->va_mode = adp->va_mode;
742 ((video_adapter_info_t *)arg)->va_initial_mode
743 = adp->va_initial_mode;
744 ((video_adapter_info_t *)arg)->va_initial_bios_mode
745 = adp->va_initial_bios_mode;
746 ((video_adapter_info_t *)arg)->va_line_width
747 = adp->va_line_width;
748 ((video_adapter_info_t *)arg)->va_disp_start.x
749 = adp->va_disp_start.x;
750 ((video_adapter_info_t *)arg)->va_disp_start.y
751 = adp->va_disp_start.y;
752 break;
753
754 case FBIO_MODEINFO: /* get mode information */
755 error = (*vidsw[adp->va_index]->get_info)(adp,
756 ((video_info_t *)arg)->vi_mode,
757 (video_info_t *)arg);
758 if (error)
759 error = ENODEV;
760 break;
761
762 case FBIO_FINDMODE: /* find a matching video mode */
763 error = (*vidsw[adp->va_index]->query_mode)(adp,
764 (video_info_t *)arg);
765 if (error < 0) {
766 error = EINVAL;
767 } else {
768 error = (*vidsw[adp->va_index]->get_info)(adp,
769 error, (video_info_t *)arg);
770 if (error)
771 error = ENODEV; /* shouldn't happen */
772 }
773 break;
774
775 case FBIO_GETMODE: /* get video mode */
776 *(int *)arg = adp->va_mode;
777 break;
778
779 case FBIO_SETMODE: /* set video mode */
780 error = (*vidsw[adp->va_index]->set_mode)(adp, *(int *)arg);
781 if (error)
782 error = ENODEV; /* EINVAL? */
783 break;
784
785 case FBIO_GETWINORG: /* get frame buffer window origin */
786 *(u_int *)arg = adp->va_window_orig;
787 break;
788
789 case FBIO_GETDISPSTART: /* get display start address */
790 ((video_display_start_t *)arg)->x = adp->va_disp_start.x;
791 ((video_display_start_t *)arg)->y = adp->va_disp_start.y;
792 break;
793
794 case FBIO_GETLINEWIDTH: /* get scan line width in bytes */
795 *(u_int *)arg = adp->va_line_width;
796 break;
797
798 case FBIO_GETPALETTE: /* get color palette */
799 case FBIO_SETPALETTE: /* set color palette */
800 /* XXX */
801
802 case FBIOPUTCMAP:
803 case FBIOGETCMAP:
804 /* XXX */
805
806 case FBIO_SETWINORG: /* set frame buffer window origin */
807 case FBIO_SETDISPSTART: /* set display start address */
808 case FBIO_SETLINEWIDTH: /* set scan line width in pixel */
809
810 case FBIOGTYPE:
811 case FBIOGATTR:
812 case FBIOSVIDEO:
813 case FBIOGVIDEO:
814 case FBIOSCURSOR:
815 case FBIOGCURSOR:
816 case FBIOSCURPOS:
817 case FBIOGCURPOS:
818 case FBIOGCURMAX:
819
820 default:
821 error = ENODEV;
822 break;
823 }
824
825 splx(s);
826 return error;
827}