root/dev/isa/pcdisplay.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pcdisplay_probe_col
  2. pcdisplay_probe_mono
  3. pcdisplay_init
  4. pcdisplay_match
  5. pcdisplay_attach
  6. pcdisplay_cnattach
  7. pcdisplay_is_console
  8. pcdisplay_ioctl
  9. pcdisplay_mmap
  10. pcdisplay_alloc_screen
  11. pcdisplay_free_screen
  12. pcdisplay_show_screen
  13. pcdisplay_alloc_attr
  14. pcdisplay_unpack_attr

    1 /* $OpenBSD: pcdisplay.c,v 1.9 2006/11/29 19:08:22 miod Exp $ */
    2 /* $NetBSD: pcdisplay.c,v 1.9.4.1 2000/06/30 16:27:48 simonb Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1998
    6  *      Matthias Drochner.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   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  */
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/kernel.h>
   33 #include <sys/device.h>
   34 #include <sys/malloc.h>
   35 #include <machine/bus.h>
   36 
   37 #include <dev/isa/isavar.h>
   38 #include <dev/isa/isareg.h>
   39 
   40 #include <dev/ic/mc6845reg.h>
   41 #include <dev/ic/pcdisplayvar.h>
   42 #include <dev/isa/pcdisplayvar.h>
   43 
   44 #include <dev/ic/pcdisplay.h>
   45 
   46 #include <dev/wscons/wsconsio.h>
   47 #include <dev/wscons/wsdisplayvar.h>
   48 
   49 struct pcdisplay_config {
   50         struct pcdisplayscreen pcs;
   51         struct pcdisplay_handle dc_ph;
   52         int mono;
   53 };
   54 
   55 struct pcdisplay_softc {
   56         struct device sc_dev;
   57         struct pcdisplay_config *sc_dc;
   58         int nscreens;
   59 };
   60 
   61 static int pcdisplayconsole, pcdisplay_console_attached;
   62 static struct pcdisplay_config pcdisplay_console_dc;
   63 
   64 int     pcdisplay_match(struct device *, void *, void *);
   65 void    pcdisplay_attach(struct device *, struct device *, void *);
   66 
   67 static int pcdisplay_is_console(bus_space_tag_t);
   68 static int pcdisplay_probe_col(bus_space_tag_t, bus_space_tag_t);
   69 static int pcdisplay_probe_mono(bus_space_tag_t, bus_space_tag_t);
   70 static void pcdisplay_init(struct pcdisplay_config *,
   71                              bus_space_tag_t, bus_space_tag_t,
   72                              int);
   73 static int pcdisplay_alloc_attr(void *, int, int, int, long *);
   74 static void pcdisplay_unpack_attr(void *, long, int *, int *, int *);
   75 
   76 struct cfattach pcdisplay_ca = {
   77         sizeof(struct pcdisplay_softc), pcdisplay_match, pcdisplay_attach,
   78 };
   79 
   80 const struct wsdisplay_emulops pcdisplay_emulops = {
   81         pcdisplay_cursor,
   82         pcdisplay_mapchar,
   83         pcdisplay_putchar,
   84         pcdisplay_copycols,
   85         pcdisplay_erasecols,
   86         pcdisplay_copyrows,
   87         pcdisplay_eraserows,
   88         pcdisplay_alloc_attr,
   89         pcdisplay_unpack_attr
   90 };
   91 
   92 const struct wsscreen_descr pcdisplay_scr = {
   93         "80x25", 80, 25,
   94         &pcdisplay_emulops,
   95         0, 0, /* no font support */
   96         WSSCREEN_REVERSE /* that's minimal... */
   97 };
   98 
   99 const struct wsscreen_descr *_pcdisplay_scrlist[] = {
  100         &pcdisplay_scr,
  101 };
  102 
  103 const struct wsscreen_list pcdisplay_screenlist = {
  104         sizeof(_pcdisplay_scrlist) / sizeof(struct wsscreen_descr *),
  105         _pcdisplay_scrlist
  106 };
  107 
  108 static int pcdisplay_ioctl(void *, u_long, caddr_t, int, struct proc *);
  109 static paddr_t pcdisplay_mmap(void *, off_t, int);
  110 static int pcdisplay_alloc_screen(void *, const struct wsscreen_descr *,
  111                                        void **, int *, int *, long *);
  112 static void pcdisplay_free_screen(void *, void *);
  113 static int pcdisplay_show_screen(void *, void *, int,
  114                                  void (*) (void *, int, int), void *);
  115 
  116 const struct wsdisplay_accessops pcdisplay_accessops = {
  117         pcdisplay_ioctl,
  118         pcdisplay_mmap,
  119         pcdisplay_alloc_screen,
  120         pcdisplay_free_screen,
  121         pcdisplay_show_screen,
  122         0 /* load_font */
  123 };
  124 
  125 static int
  126 pcdisplay_probe_col(iot, memt)
  127         bus_space_tag_t iot, memt;
  128 {
  129         bus_space_handle_t memh, ioh_6845;
  130         u_int16_t oldval, val;
  131 
  132         if (bus_space_map(memt, 0xb8000, 0x8000, 0, &memh))
  133                 return (0);
  134         oldval = bus_space_read_2(memt, memh, 0);
  135         bus_space_write_2(memt, memh, 0, 0xa55a);
  136         val = bus_space_read_2(memt, memh, 0);
  137         bus_space_write_2(memt, memh, 0, oldval);
  138         bus_space_unmap(memt, memh, 0x8000);
  139         if (val != 0xa55a)
  140                 return (0);
  141 
  142         if (bus_space_map(iot, 0x3d0, 0x10, 0, &ioh_6845))
  143                 return (0);
  144         bus_space_unmap(iot, ioh_6845, 0x10);
  145 
  146         return (1);
  147 }
  148 
  149 static int
  150 pcdisplay_probe_mono(iot, memt)
  151         bus_space_tag_t iot, memt;
  152 {
  153         bus_space_handle_t memh, ioh_6845;
  154         u_int16_t oldval, val;
  155 
  156         if (bus_space_map(memt, 0xb0000, 0x8000, 0, &memh))
  157                 return (0);
  158         oldval = bus_space_read_2(memt, memh, 0);
  159         bus_space_write_2(memt, memh, 0, 0xa55a);
  160         val = bus_space_read_2(memt, memh, 0);
  161         bus_space_write_2(memt, memh, 0, oldval);
  162         bus_space_unmap(memt, memh, 0x8000);
  163         if (val != 0xa55a)
  164                 return (0);
  165 
  166         if (bus_space_map(iot, 0x3b0, 0x10, 0, &ioh_6845))
  167                 return (0);
  168         bus_space_unmap(iot, ioh_6845, 0x10);
  169 
  170         return (1);
  171 }
  172 
  173 static void
  174 pcdisplay_init(dc, iot, memt, mono)
  175         struct pcdisplay_config *dc;
  176         bus_space_tag_t iot, memt;
  177         int mono;
  178 {
  179         struct pcdisplay_handle *ph = &dc->dc_ph;
  180         int cpos;
  181 
  182         ph->ph_iot = iot;
  183         ph->ph_memt = memt;
  184         dc->mono = mono;
  185 
  186         if (bus_space_map(memt, mono ? 0xb0000 : 0xb8000, 0x8000,
  187                           0, &ph->ph_memh))
  188                 panic("pcdisplay_init: cannot map memory");
  189         if (bus_space_map(iot, mono ? 0x3b0 : 0x3d0, 0x10,
  190                           0, &ph->ph_ioh_6845))
  191                 panic("pcdisplay_init: cannot map io");
  192 
  193         /*
  194          * initialize the only screen
  195          */
  196         dc->pcs.hdl = ph;
  197         dc->pcs.type = &pcdisplay_scr;
  198         dc->pcs.active = 1;
  199         dc->pcs.mem = NULL;
  200 
  201         cpos = pcdisplay_6845_read(ph, cursorh) << 8;
  202         cpos |= pcdisplay_6845_read(ph, cursorl);
  203 
  204         /* make sure we have a valid cursor position */
  205         if (cpos < 0 || cpos >= pcdisplay_scr.nrows * pcdisplay_scr.ncols)
  206                 cpos = 0;
  207 
  208         dc->pcs.dispoffset = 0;
  209         dc->pcs.visibleoffset = 0;
  210 
  211         dc->pcs.vc_crow = cpos / pcdisplay_scr.ncols;
  212         dc->pcs.vc_ccol = cpos % pcdisplay_scr.ncols;
  213         pcdisplay_cursor_init(&dc->pcs, 1);
  214 }
  215 
  216 int
  217 pcdisplay_match(parent, match, aux)
  218         struct device *parent;
  219         void *match;
  220         void *aux;
  221 {
  222         struct isa_attach_args *ia = aux;
  223         int mono;
  224 
  225         /* If values are hardwired to something that they can't be, punt. */
  226         if ((ia->ia_iobase != IOBASEUNK &&
  227              ia->ia_iobase != 0x3d0 &&
  228              ia->ia_iobase != 0x3b0) ||
  229             /* ia->ia_iosize != 0 || XXX isa.c */
  230             (ia->ia_maddr != MADDRUNK &&
  231              ia->ia_maddr != 0xb8000 &&
  232              ia->ia_maddr != 0xb0000) ||
  233             (ia->ia_msize != 0 && ia->ia_msize != 0x8000) ||
  234             ia->ia_irq != IRQUNK || ia->ia_drq != DRQUNK)
  235                 return (0);
  236 
  237         if (pcdisplay_is_console(ia->ia_iot))
  238                 mono = pcdisplay_console_dc.mono;
  239         else if (ia->ia_iobase != 0x3b0 && ia->ia_maddr != 0xb0000 &&
  240                  pcdisplay_probe_col(ia->ia_iot, ia->ia_memt))
  241                 mono = 0;
  242         else if (ia->ia_iobase != 0x3d0 && ia->ia_maddr != 0xb8000 &&
  243                  pcdisplay_probe_mono(ia->ia_iot, ia->ia_memt))
  244                 mono = 1;
  245         else
  246                 return (0);
  247 
  248         ia->ia_iobase = mono ? 0x3b0 : 0x3d0;
  249         ia->ia_iosize = 0x10;
  250         ia->ia_maddr = mono ? 0xb0000 : 0xb8000;
  251         ia->ia_msize = 0x8000;
  252         return (1);
  253 }
  254 
  255 void
  256 pcdisplay_attach(parent, self, aux)
  257         struct device *parent, *self;
  258         void *aux;
  259 {
  260         struct isa_attach_args *ia = aux;
  261         struct pcdisplay_softc *sc = (struct pcdisplay_softc *)self;
  262         int console;
  263         struct pcdisplay_config *dc;
  264         struct wsemuldisplaydev_attach_args aa;
  265 
  266         printf("\n");
  267 
  268         console = pcdisplay_is_console(ia->ia_iot);
  269 
  270         if (console) {
  271                 dc = &pcdisplay_console_dc;
  272                 sc->nscreens = 1;
  273                 pcdisplay_console_attached = 1;
  274         } else {
  275                 dc = malloc(sizeof(struct pcdisplay_config),
  276                             M_DEVBUF, M_WAITOK);
  277                 if (ia->ia_iobase != 0x3b0 && ia->ia_maddr != 0xb0000 &&
  278                     pcdisplay_probe_col(ia->ia_iot, ia->ia_memt))
  279                         pcdisplay_init(dc, ia->ia_iot, ia->ia_memt, 0);
  280                 else if (ia->ia_iobase != 0x3d0 && ia->ia_maddr != 0xb8000 &&
  281                          pcdisplay_probe_mono(ia->ia_iot, ia->ia_memt))
  282                         pcdisplay_init(dc, ia->ia_iot, ia->ia_memt, 1);
  283                 else
  284                         panic("pcdisplay_attach: display disappeared");
  285         }
  286         sc->sc_dc = dc;
  287 
  288         aa.console = console;
  289         aa.scrdata = &pcdisplay_screenlist;
  290         aa.accessops = &pcdisplay_accessops;
  291         aa.accesscookie = sc;
  292         aa.defaultscreens = 0;
  293 
  294         config_found(self, &aa, wsemuldisplaydevprint);
  295 }
  296 
  297 
  298 int
  299 pcdisplay_cnattach(iot, memt)
  300         bus_space_tag_t iot, memt;
  301 {
  302         int mono;
  303 
  304         if (pcdisplay_probe_col(iot, memt))
  305                 mono = 0;
  306         else if (pcdisplay_probe_mono(iot, memt))
  307                 mono = 1;
  308         else
  309                 return (ENXIO);
  310 
  311         pcdisplay_init(&pcdisplay_console_dc, iot, memt, mono);
  312 
  313         wsdisplay_cnattach(&pcdisplay_scr, &pcdisplay_console_dc,
  314                            pcdisplay_console_dc.pcs.vc_ccol,
  315                            pcdisplay_console_dc.pcs.vc_crow,
  316                            FG_LIGHTGREY | BG_BLACK);
  317 
  318         pcdisplayconsole = 1;
  319         return (0);
  320 }
  321 
  322 static int
  323 pcdisplay_is_console(iot)
  324         bus_space_tag_t iot;
  325 {
  326         if (pcdisplayconsole &&
  327             !pcdisplay_console_attached &&
  328             iot == pcdisplay_console_dc.dc_ph.ph_iot)
  329                 return (1);
  330         return (0);
  331 }
  332 
  333 static int
  334 pcdisplay_ioctl(v, cmd, data, flag, p)
  335         void *v;
  336         u_long cmd;
  337         caddr_t data;
  338         int flag;
  339         struct proc *p;
  340 {
  341         /*
  342          * XXX "do something!"
  343          */
  344         return (-1);
  345 }
  346 
  347 static paddr_t
  348 pcdisplay_mmap(v, offset, prot)
  349         void *v;
  350         off_t offset;
  351         int prot;
  352 {
  353         return (-1);
  354 }
  355 
  356 static int
  357 pcdisplay_alloc_screen(v, type, cookiep, curxp, curyp, defattrp)
  358         void *v;
  359         const struct wsscreen_descr *type;
  360         void **cookiep;
  361         int *curxp, *curyp;
  362         long *defattrp;
  363 {
  364         struct pcdisplay_softc *sc = v;
  365 
  366         if (sc->nscreens > 0)
  367                 return (ENOMEM);
  368 
  369         *cookiep = sc->sc_dc;
  370         *curxp = 0;
  371         *curyp = 0;
  372         *defattrp = FG_LIGHTGREY | BG_BLACK;
  373         sc->nscreens++;
  374         return (0);
  375 }
  376 
  377 static void
  378 pcdisplay_free_screen(v, cookie)
  379         void *v;
  380         void *cookie;
  381 {
  382         struct pcdisplay_softc *sc = v;
  383 
  384         if (sc->sc_dc == &pcdisplay_console_dc)
  385                 panic("pcdisplay_free_screen: console");
  386 
  387         sc->nscreens--;
  388 }
  389 
  390 static int
  391 pcdisplay_show_screen(v, cookie, waitok, cb, cbarg)
  392         void *v;
  393         void *cookie;
  394         int waitok;
  395         void (*cb)(void *, int, int);
  396         void *cbarg;
  397 {
  398 #ifdef DIAGNOSTIC
  399         struct pcdisplay_softc *sc = v;
  400 
  401         if (cookie != sc->sc_dc)
  402                 panic("pcdisplay_show_screen: bad screen");
  403 #endif
  404         return (0);
  405 }
  406 
  407 static int
  408 pcdisplay_alloc_attr(id, fg, bg, flags, attrp)
  409         void *id;
  410         int fg, bg;
  411         int flags;
  412         long *attrp;
  413 {
  414         if (flags & WSATTR_REVERSE)
  415                 *attrp = FG_BLACK | BG_LIGHTGREY;
  416         else
  417                 *attrp = FG_LIGHTGREY | BG_BLACK;
  418         return (0);
  419 }
  420 
  421 static void
  422 pcdisplay_unpack_attr(id, attr, fg, bg, ul)
  423         void *id;
  424         long attr;
  425         int *fg, *bg, *ul;
  426 {
  427         if (attr == (FG_BLACK | BG_LIGHTGREY)) {
  428                 *fg = WSCOL_BLACK;
  429                 *bg = WSCOL_WHITE;
  430         } else {
  431                 *fg = WSCOL_WHITE;
  432                 *bg = WSCOL_BLACK;
  433         }
  434         if (ul != NULL)
  435                 *ul = 0;
  436 }
  437 
  438 struct cfdriver pcdisplay_cd = {
  439         NULL, "pcdisplay", DV_DULL
  440 };

/* [<][>][^][v][top][bottom][index][help] */