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/dev/digi/digi_isa.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) 2001 Brian Somers <brian@Awfulhak.org>
    3  *   based on work by Slawa Olhovchenkov
    4  *                    John Prince <johnp@knight-trosoft.com>
    5  *                    Eric Hernes
    6  * 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 AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD: releng/8.4/sys/dev/digi/digi_isa.c 129879 2004-05-30 20:08:47Z phk $");
   33 
   34 /*-
   35  * TODO:
   36  *      Figure out how to make the non-Xi boards use memory addresses other
   37  *      than 0xd0000 !!!
   38  */
   39 
   40 #include <sys/param.h>
   41 
   42 #include <sys/systm.h>
   43 #include <sys/kernel.h>
   44 #include <sys/module.h>
   45 #include <sys/tty.h>
   46 #include <sys/bus.h>
   47 #include <machine/bus.h>
   48 #include <sys/rman.h>
   49 #include <machine/resource.h>
   50 #include <vm/vm.h>
   51 #include <vm/pmap.h>
   52 
   53 #include <sys/digiio.h>
   54 #include <dev/digi/digireg.h>
   55 #include <dev/digi/digi.h>
   56 
   57 /* Valid i/o addresses are any of these with either 0 or 4 added */
   58 static u_long digi_validio[] = {
   59         0x100, 0x110, 0x120, 0x200, 0x220, 0x300, 0x320
   60 };
   61 #define DIGI_NVALIDIO   (sizeof(digi_validio) / sizeof(digi_validio[0]))
   62 #define IO_SIZE         0x04
   63 
   64 static u_long digi_validmem[] = {
   65         0x80000, 0x88000, 0x90000, 0x98000, 0xa0000, 0xa8000, 0xb0000, 0xb8000,
   66         0xc0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000, 0xe8000, 0xf0000, 0xf8000,
   67         0xf0000000, 0xf1000000, 0xf2000000, 0xf3000000, 0xf4000000, 0xf5000000,
   68         0xf6000000, 0xf7000000, 0xf8000000, 0xf9000000, 0xfa000000, 0xfb000000,
   69         0xfc000000, 0xfd000000, 0xfe000000, 0xff000000
   70 };
   71 #define DIGI_NVALIDMEM  (sizeof(digi_validmem) / sizeof(digi_validmem[0]))
   72 
   73 static u_char *
   74 digi_isa_setwin(struct digi_softc *sc, unsigned int addr)
   75 {
   76         outb(sc->wport, sc->window = FEPWIN | (addr >> sc->win_bits));
   77         return (sc->vmem + (addr % sc->win_size));
   78 }
   79 
   80 static u_char *
   81 digi_xi_setwin(struct digi_softc *sc, unsigned int addr)
   82 {
   83         outb(sc->wport, sc->window = FEPMEM);
   84         return (sc->vmem + addr);
   85 }
   86 
   87 static void
   88 digi_isa_hidewin(struct digi_softc *sc)
   89 {
   90         outb(sc->wport, sc->window = 0);
   91         /* outb(sc->port, 0); */
   92 }
   93 
   94 static void
   95 digi_isa_towin(struct digi_softc *sc, int win)
   96 {
   97         outb(sc->wport, sc->window = win);
   98 }
   99 
  100 static void
  101 digi_xi_towin(struct digi_softc *sc, int win)
  102 {
  103         outb(sc->wport, sc->window = FEPMEM);
  104 }
  105 
  106 /*
  107  * sc->port should be set and its resource allocated.
  108  */
  109 static int
  110 digi_isa_check(struct digi_softc *sc)
  111 {
  112         int i, ident;
  113 
  114         sc->name = NULL;
  115 
  116         /* Invasive probe - reset the card */
  117         outb(sc->port, FEPRST);
  118         for (i = 0; (inb(sc->port) & FEPMASK) != FEPRST; i++) {
  119                 if (i == hz / 10)
  120                         return (0);
  121                 digi_delay(sc, "digirst", 1);
  122         }
  123         DLOG(DIGIDB_INIT, (sc->dev, "got reset after %d iterations\n", i));
  124 
  125         ident = inb(sc->port);
  126 
  127         /*
  128          * NOTE, this probe is all wrong.  I haven't got the data sheets !
  129          */
  130 
  131         DLOG(DIGIDB_INIT, (sc->dev, "board type is 0x%x\n", ident));
  132         if (ident & 0x1) {
  133                 switch (ident) {
  134                 case 0x05:
  135                 case 0x15:
  136                 case 0x25:
  137                 case 0x35:
  138                         sc->model = PCXI;
  139                         sc->csigs = &digi_xixe_signals;
  140                         switch (ident & 0x30) {
  141                         case 0:
  142                                 sc->name = "Digiboard PC/Xi 64K";
  143                                 sc->mem_seg = 0xf000;
  144                                 sc->win_size = 0x10000;
  145                                 sc->win_bits = 16;
  146                                 break;
  147                         case 0x10:
  148                                 sc->name = "Digiboard PC/Xi 128K";
  149                                 sc->mem_seg = 0xE000;
  150                                 sc->win_size = 0x20000;
  151                                 sc->win_bits = 17;
  152                                 break;
  153                         case 0x20:
  154                                 sc->name = "Digiboard PC/Xi 256K";
  155                                 sc->mem_seg = 0xC000;
  156                                 sc->win_size = 0x40000;
  157                                 sc->win_bits = 18;
  158                                 break;
  159                         case 0x30:
  160                                 sc->name = "Digiboard PC/Xi 512K";
  161                                 sc->mem_seg = 0x8000;
  162                                 sc->win_size = 0x80000;
  163                                 sc->win_bits = 19;
  164                                 break;
  165                         }
  166                         sc->wport = sc->port;
  167                         sc->module = "Xe";
  168 
  169                         sc->setwin = digi_xi_setwin;
  170                         sc->hidewin = digi_isa_hidewin;
  171                         sc->towin = digi_xi_towin;
  172                         break;
  173 
  174                 case 0xf5:
  175                         sc->name = "Digiboard PC/Xem";
  176                         sc->model = PCXEM;
  177                         sc->csigs = &digi_normal_signals;
  178                         sc->win_size = 0x8000;
  179                         sc->win_bits = 15;
  180                         sc->wport = sc->port + 1;
  181                         sc->module = "Xem";
  182 
  183                         sc->setwin = digi_isa_setwin;
  184                         sc->hidewin = digi_isa_hidewin;
  185                         sc->towin = digi_isa_towin;
  186                         break;
  187                 }
  188         } else {
  189                 outb(sc->port, 1);
  190                 ident = inb(sc->port);
  191 
  192                 if (ident & 0x1) {
  193                         device_printf(sc->dev, "PC/Xm is unsupported\n");
  194                         return (0);
  195                 }
  196 
  197                 sc->mem_seg = 0xf000;
  198 
  199                 if (!(ident & 0xc0)) {
  200                         sc->name = "Digiboard PC/Xe 64K";
  201                         sc->model = PCXE;
  202                         sc->csigs = &digi_xixe_signals;
  203                         sc->win_size = 0x10000;
  204                         sc->win_bits = 16;
  205                         sc->wport = sc->port;
  206                 } else {
  207                         sc->name = "Digiboard PC/Xe 64/8K (windowed)";
  208                         sc->model = PCXEVE;
  209                         sc->csigs = &digi_normal_signals;
  210                         sc->win_size = 0x2000;
  211                         sc->win_bits = 13;
  212                         sc->wport = sc->port + 1;
  213                 }
  214                 sc->module = "Xe";
  215 
  216                 sc->setwin = digi_isa_setwin;
  217                 sc->hidewin = digi_isa_hidewin;
  218                 sc->towin = digi_isa_towin;
  219         }
  220 
  221         return (sc->name != NULL);
  222 }
  223 
  224 static int
  225 digi_isa_probe(device_t dev)
  226 {
  227         struct digi_softc *sc = device_get_softc(dev);
  228         int i;
  229 
  230         KASSERT(sc, ("digi%d: softc not allocated in digi_isa_probe\n",
  231             device_get_unit(dev)));
  232 
  233         bzero(sc, sizeof(*sc));
  234         sc->status = DIGI_STATUS_NOTINIT;
  235         sc->dev = dev;
  236         sc->res.unit = device_get_unit(dev);
  237         if (sc->res.unit >= 16) {
  238                 /* Don't overflow our control mask */
  239                 device_printf(dev, "At most 16 digiboards may be used\n");
  240                 return (ENXIO);
  241         }
  242         DLOG(DIGIDB_INIT, (sc->dev, "probing on isa bus\n"));
  243 
  244         /* Check that we've got a valid i/o address */
  245         if ((sc->port = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0) {
  246                 DLOG(DIGIDB_INIT, (sc->dev, "io address not given\n"));
  247                 return (ENXIO);
  248         }
  249         for (i = 0; i < DIGI_NVALIDIO; i++)
  250                 if (sc->port == digi_validio[i] ||
  251                     sc->port == digi_validio[i] + 4)
  252                         break;
  253         if (i == DIGI_NVALIDIO) {
  254                 device_printf(dev, "0x%03x: Invalid i/o address\n", sc->port);
  255                 return (ENXIO);
  256         }
  257 
  258         /* Ditto for our memory address */
  259         if ((sc->pmem = bus_get_resource_start(dev, SYS_RES_MEMORY, 0)) == 0)
  260                 return (ENXIO);
  261         for (i = 0; i < DIGI_NVALIDMEM; i++)
  262                 if (sc->pmem == digi_validmem[i])
  263                         break;
  264         if (i == DIGI_NVALIDMEM) {
  265                 device_printf(dev, "0x%lx: Invalid memory address\n", sc->pmem);
  266                 return (ENXIO);
  267         }
  268         if ((sc->pmem & 0xfffffful) != sc->pmem) {
  269                 device_printf(dev, "0x%lx: Memory address not supported\n",
  270                     sc->pmem);
  271                 return (ENXIO);
  272         }
  273         sc->vmem = (u_char *)sc->pmem;
  274 
  275         DLOG(DIGIDB_INIT, (sc->dev, "isa? port 0x%03x mem 0x%lx\n",
  276             sc->port, sc->pmem));
  277 
  278         /* Temporarily map our io ports */
  279         sc->res.iorid = 0;
  280         sc->res.io = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->res.iorid,
  281             0ul, ~0ul, IO_SIZE, RF_ACTIVE);
  282         if (sc->res.io == NULL)
  283                 return (ENXIO);
  284 
  285         /* Check the type of card and get internal memory characteristics */
  286         if (!digi_isa_check(sc)) {
  287                 bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid,
  288                     sc->res.io);
  289                 return (ENXIO);
  290         }
  291 
  292         /* Temporarily map our memory */
  293         sc->res.mrid = 0;
  294         sc->res.mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->res.mrid,
  295             0ul, ~0ul, sc->win_size, RF_ALLOCATED);
  296         if (sc->res.mem == NULL) {
  297                 device_printf(dev, "0x%lx: Memory range is in use\n", sc->pmem);
  298                 bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid,
  299                     sc->res.io);
  300                 return (ENXIO);
  301         }
  302 
  303         outb(sc->port, FEPCLR);         /* drop RESET */
  304         sc->hidewin(sc);        /* set initial sc->window */
  305 
  306         bus_release_resource(dev, SYS_RES_MEMORY, sc->res.mrid, sc->res.mem);
  307         bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid, sc->res.io);
  308 
  309         /* Let digi_isa_attach() know what we've found */
  310         bus_set_resource(dev, SYS_RES_IOPORT, 0, sc->port, IO_SIZE);
  311         bus_set_resource(dev, SYS_RES_MEMORY, 0, sc->pmem, sc->win_size);
  312 
  313         DLOG(DIGIDB_INIT, (sc->dev, "Probe returns -10\n"));
  314 
  315         return (-10);           /* Other drivers are preferred for now */
  316 }
  317 
  318 static int
  319 digi_isa_attach(device_t dev)
  320 {
  321         struct digi_softc *sc = device_get_softc(dev);
  322         int i, t, res;
  323         u_char *ptr;
  324         int reset;
  325         u_long msize, iosize;
  326         long scport;
  327 
  328         KASSERT(sc, ("digi%d: softc not allocated in digi_isa_attach\n",
  329             device_get_unit(dev)));
  330 
  331         res = ENXIO;
  332         bzero(sc, sizeof(*sc));
  333         sc->status = DIGI_STATUS_NOTINIT;
  334         sc->dev = dev;
  335         sc->res.unit = device_get_unit(dev);
  336         DLOG(DIGIDB_INIT, (sc->dev, "attaching\n"));
  337 
  338         bus_get_resource(dev, SYS_RES_IOPORT, 0, &scport, &iosize);
  339         bus_get_resource(dev, SYS_RES_MEMORY, 0, &sc->pmem, &msize);
  340         sc->port = scport;
  341         /* sc->altpin = !!(device_get_flags(dev) & DGBFLAG_ALTPIN); */
  342 
  343         /* Allocate resources (verified in digi_isa_probe()) */
  344         sc->res.iorid = 0;
  345         sc->res.io = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->res.iorid,
  346             0ul, ~0ul, iosize, RF_ACTIVE);
  347         if (sc->res.io == NULL)
  348                 return (ENXIO);
  349 
  350         /* Check the type of card and get internal memory characteristics */
  351         DLOG(DIGIDB_INIT, (sc->dev, "Checking card type\n"));
  352         if (!digi_isa_check(sc))
  353                 goto failed;
  354 
  355         callout_handle_init(&sc->callout);
  356         callout_handle_init(&sc->inttest);
  357 
  358         sc->res.mrid = 0;
  359         sc->res.mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->res.mrid,
  360             0ul, ~0ul, msize, RF_ACTIVE);
  361         if (sc->res.mem == NULL) {
  362                 device_printf(dev, "0x%lx: Memory range is in use\n", sc->pmem);
  363                 sc->hidewin(sc);
  364                 goto failed;
  365         }
  366 
  367         /* map memory */
  368         sc->vmem = pmap_mapdev(sc->pmem, msize);
  369 
  370         DLOG(DIGIDB_INIT, (sc->dev, "internal memory segment 0x%x\n",
  371             sc->mem_seg));
  372 
  373         /* Start by resetting the card */
  374         reset = FEPRST;
  375         if (sc->model == PCXI)
  376                 reset |= FEPMEM;
  377 
  378         outb(sc->port, reset);
  379         for (i = 0; (inb(sc->port) & FEPMASK) != reset; i++) {
  380                 if (i == hz / 10) {
  381                         device_printf(dev, "1st reset failed\n");
  382                         sc->hidewin(sc);
  383                         goto failed;
  384                 }
  385                 digi_delay(sc, "digirst1", 1);
  386         }
  387         DLOG(DIGIDB_INIT, (sc->dev, "got reset after %d iterations\n", i));
  388 
  389         if (sc->model != PCXI) {
  390                 t = (sc->pmem >> 8) & 0xffe0;
  391                 if (sc->model == PCXEVE)
  392                         t |= 0x10;              /* enable windowing */
  393                 outb(sc->port + 2, t & 0xff);
  394                 outb(sc->port + 3, t >> 8);
  395         }
  396 
  397         if (sc->model == PCXI || sc->model == PCXE) {
  398                 outb(sc->port, FEPRST | FEPMEM);
  399                 for (i = 0; (inb(sc->port) & FEPMASK) != FEPRST; i++) {
  400                         if (i == hz / 10) {
  401                                 device_printf(dev,
  402                                     "memory reservation failed (0x%02x)\n",
  403                                     inb(sc->port));
  404                                 sc->hidewin(sc);
  405                                 goto failed;
  406                         }
  407                         digi_delay(sc, "digirst2", 1);
  408                 }
  409                 DLOG(DIGIDB_INIT, (sc->dev, "got memory after %d iterations\n",
  410                     i));
  411         }
  412 
  413         DLOG(DIGIDB_INIT, (sc->dev, "short memory test\n"));
  414         ptr = sc->setwin(sc, BOTWIN);
  415         vD(ptr) = 0xA55A3CC3;
  416         if (vD(ptr) != 0xA55A3CC3) {
  417                 device_printf(dev, "1st memory test failed\n");
  418                 sc->hidewin(sc);
  419                 goto failed;
  420         }
  421         DLOG(DIGIDB_INIT, (sc->dev, "1st memory test ok\n"));
  422 
  423         ptr = sc->setwin(sc, TOPWIN);
  424         vD(ptr) = 0x5AA5C33C;
  425         if (vD(ptr) != 0x5AA5C33C) {
  426                 device_printf(dev, "2nd memory test failed\n");
  427                 sc->hidewin(sc);
  428                 goto failed;
  429         }
  430         DLOG(DIGIDB_INIT, (sc->dev, "2nd memory test ok\n"));
  431 
  432         ptr = sc->setwin(sc, BIOSCODE + ((0xf000 - sc->mem_seg) << 4));
  433         vD(ptr) = 0x5AA5C33C;
  434         if (vD(ptr) != 0x5AA5C33C) {
  435                 device_printf(dev, "3rd (BIOS) memory test failed\n");
  436                 sc->hidewin(sc);
  437                 goto failed;
  438         }
  439         DLOG(DIGIDB_INIT, (sc->dev, "3rd memory test ok\n"));
  440 
  441         if ((res = digi_attach(sc)) == 0)
  442                 return (0);
  443 
  444 failed:
  445         if (sc->res.mem != NULL) {
  446                 bus_release_resource(dev, SYS_RES_MEMORY, sc->res.mrid,
  447                     sc->res.mem);
  448                 sc->res.mem = NULL;
  449         }
  450         if (sc->res.io != NULL) {
  451                 bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid,
  452                     sc->res.io);
  453                 sc->res.io = NULL;
  454         }
  455 
  456         return (res);
  457 }
  458 
  459 static device_method_t digi_isa_methods[] = {
  460         /* Device interface */
  461         DEVMETHOD(device_probe, digi_isa_probe),
  462         DEVMETHOD(device_attach, digi_isa_attach),
  463         DEVMETHOD(device_detach, digi_detach),
  464         DEVMETHOD(device_shutdown, digi_shutdown),
  465         {0, 0}
  466 };
  467 
  468 static driver_t digi_isa_drv = {
  469         "digi",
  470         digi_isa_methods,
  471         sizeof(struct digi_softc),
  472 };
  473 DRIVER_MODULE(digi, isa, digi_isa_drv, digi_devclass, 0, 0);

Cache object: 920e5fdc7e4416daa95ccdb74f3ce02e


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