The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/pc98/cbus/gdc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.