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

Cache object: e77e4d98cea0de4845e4ca036e908c93


[ 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.