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/ieee488/tnt4882.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) 2005 Poul-Henning Kamp
    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.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD: releng/7.3/sys/dev/ieee488/tnt4882.c 166914 2007-02-23 19:34:52Z imp $
   27  */
   28 
   29 #include <sys/param.h>
   30 #include <sys/kernel.h>
   31 #include <sys/systm.h>
   32 #include <sys/module.h>
   33 #include <sys/bus.h>
   34 #include <dev/pci/pcireg.h>
   35 #include <dev/pci/pcivar.h>
   36 
   37 #include <machine/bus.h>
   38 #include <machine/resource.h>
   39 #include <machine/stdarg.h>
   40 #include <sys/rman.h>
   41 
   42 /* vtophys */
   43 #include <vm/vm.h>
   44 #include <vm/pmap.h>
   45 #include <machine/pmap.h>
   46 
   47 #define UPD7210_HW_DRIVER 1
   48 #include <dev/ieee488/upd7210.h>
   49 
   50 struct tnt_softc {
   51         int foo;
   52         struct upd7210          upd7210;
   53 
   54         struct resource         *res[3];
   55         void                    *intr_handler;
   56 };
   57 
   58 static struct resource_spec tnt_res_spec[] = {
   59         { SYS_RES_MEMORY,       PCIR_BAR(0),    RF_ACTIVE},
   60         { SYS_RES_MEMORY,       PCIR_BAR(1),    RF_ACTIVE},
   61         { SYS_RES_IRQ,          0,              RF_ACTIVE | RF_SHAREABLE},
   62         { -1, 0 }
   63 };
   64 
   65 enum tnt4882reg {
   66         dir = 0x00,
   67         cdor = 0x00,
   68         isr1 = 0x02,
   69         imr1 = 0x02,
   70         isr2 = 0x04,
   71         imr2 = 0x04,
   72         accwr = 0x05,
   73         spsr = 0x06,
   74         spmr = 0x06,
   75         intr = 0x07,
   76         adsr = 0x08,
   77         admr = 0x08,
   78         cnt2 = 0x09,
   79         cptr = 0x0a,
   80         auxmr = 0x0a,
   81         tauxcr = 0x0a,  /* 9914 mode register */
   82         cnt3 = 0x0b,
   83         adr0 = 0x0c,
   84         adr = 0x0c,
   85         hssel = 0x0d,
   86         adr1 = 0x0e,
   87         eosr = 0x0e,
   88         sts1 = 0x10,
   89         cfg = 0x10,
   90         dsr = 0x11,
   91         sh_cnt = 0x11,
   92         imr3 = 0x12,
   93         hier = 0x13,
   94         cnt0 = 0x14,
   95         misc = 0x15,
   96         cnt1 = 0x16,
   97         csr = 0x17,
   98         keyreg = 0x17,
   99         fifob = 0x18,
  100         fifoa = 0x19,
  101         isr3 = 0x1a,
  102         ccr = 0x1a,
  103         sasr = 0x1b,
  104         dcr = 0x1b,
  105         sts2 = 0x1c,
  106         cmdr = 0x1c,
  107         isr0 = 0x1d,
  108         imr0 = 0x1d,
  109         timer = 0x1e,
  110         bsr = 0x1f,
  111         bcr = 0x1f
  112 };
  113 
  114 struct tst {
  115         enum {RD, WT, xDELAY, END}
  116                                 action;
  117         enum tnt4882reg         reg;
  118         uint8_t                 val;
  119 };
  120 
  121 /*
  122  * From NI Application note 095:
  123  *   Writing Functional Self-Tests for the TNT4882 GPIB Interface Chip
  124  * XXX: fill in the rest ?
  125  */
  126 static struct tst tst_reset[] = {
  127         {WT, tauxcr, 0x80},     /* chip reset if in 9914 mode */
  128         {WT, auxmr, 0x80},      /* swrst if swapped */ 
  129         {WT, tauxcr, 0x99},     /* switch to 7210 mode */
  130         {WT, auxmr, 0x99},      /* switch to 7210 mode if swapped */ 
  131         {WT, auxmr, 0x02},      /* execute chip reset */
  132         {WT, keyreg, 0x00},     /* important! clear the swap bit */
  133         {WT, eosr, 0x00},       /* clear EOS register */
  134         {WT, cdor, 0x00},       /* clear data lines */
  135         {WT, imr1, 0x00},       /* disable all interrupts */
  136         {WT, imr2, 0x00},
  137         {WT, imr0, 0x80},
  138         {WT, adr, 0x80},
  139         {WT, adr, 0x00},
  140         {WT, admr, 0x00},       /* clear addressing modes */
  141         {WT, auxmr, 0x00},      /* release from idle state with pon */
  142         {WT, auxmr, 0x60},      /* reset ppr */
  143         {WT, bcr, 0x00},        /* reset bcr */
  144         {WT, misc, 0x04},       /* set wrap plug bit */
  145         {WT, cmdr, 0xB2},       /* issue soft reset */
  146         {WT, hssel, 0x00},      /* select two-chip mode */
  147         {END, 0, 0}
  148 };
  149 
  150 static struct tst tst_read_reg[] = {
  151         {RD, isr1, 0x00},       /* Verify mask registers are clear */
  152         {RD, isr2, 0x00},
  153         {RD, adsr, 0x40},       /* Verify ATN is not asserted */
  154         {RD, adr0, 0x00},       /* Verify Primary address not set */
  155         {RD, adr1, 0x00},       /* Verify Secondary address not set */
  156         {RD, sts1, 0x8B},       /* Verify DONE, STOP, HALT, and GSYNC set */
  157         {RD, isr3, 0x19},       /* Verify STOP, Not Full FIFO, & DONE set */
  158         {RD, sts2, 0x9A},       /* Verify FIFO A/B is empty */
  159         {RD, sasr, 0x00},       /* Verify clear */
  160         {RD, isr0, 0x01},       /* Verify SYNC bit is set */
  161         {END, 0, 0}
  162 };
  163 
  164 static struct tst tst_bsr_dcr[] = {
  165         {WT, bcr, 0x55},        /* Set DAV, NRFD, SRQ, and REN */
  166         {WT, dcr, 0xAA},        /* Write pattern to GPIB data lines */
  167         {RD, bsr, 0x55},        /* Verify DAV, NRFD, SRQ, and REN are set */
  168         {RD, dsr, 0xAA},        /* Verify data pattern written previously */
  169         {WT, bcr, 0xAA},        /* Set ATN, NDAC, EOI, & IFC */
  170         {WT, dcr, 0x55},        /* Write pattern to GPIB data lines */
  171         {RD, bsr, 0xAA},        /* Verify ATN, NDAC, EOI, & IFC are set */
  172         {RD, dsr, 0x55},        /* Verify data pattern written previously */
  173         {WT, bcr, 0x00},        /* Clear control lines */
  174         {WT, dcr, 0x00},        /* Clear data lines */
  175         {RD, bsr, 0x00},        /* Verify control lines are clear */
  176         {RD, dsr, 0x00},        /* Verify data lines are clear */
  177         {END, 0, 0}
  178 };
  179 
  180 static struct tst tst_adr0_1[] = {
  181         {WT, adr, 0x55},        /* Set Primary talk address */
  182         {WT, adr, 0xAA},        /* Set Secondary listen address */
  183         {RD, adr0, 0x55},       /* Read Primary address */
  184         {RD, adr1, 0x2A},       /* Read Secondary address */
  185         {WT, adr, 0x2A},        /* Set Primay listen address */
  186         {WT, adr, 0xD5},        /* Set Secondary talk address */
  187         {RD, adr0, 0x2A},       /* Read Primary address */
  188         {RD, adr1, 0x55},       /* Read Secondary address */
  189         {END, 0, 0}
  190 };
  191 
  192 static struct tst tst_cdor_dir[] = {
  193         {WT, admr, 0xF0},       /* program AT-GPIB as talker only and
  194                                  * listener only */
  195         {RD, isr1, 0x02},       /* check DO bit set */
  196         {RD, adsr, 0x46},       /* check AT-GPIB is both talker active
  197                                  * and listener active */
  198         {WT, cdor, 0xAA},       /* write out data byte */
  199         {xDELAY, 0, 1},         /* One ISA I/O Cycle (500-ns) */
  200         {RD, isr1, 0x03},       /* check DO and DI bits set */
  201         {RD, dir, 0xAA},        /* verify data received */
  202         {WT, cdor, 0x55},       /* write out data byte */
  203         {xDELAY, 0, 1},         /* One ISA I/O Cycle (500-ns) */
  204         {RD, dir, 0x55},        /* verify data received */
  205         {END, 0, 0}
  206 };
  207 
  208 static struct tst tst_spmr_spsr[] = {
  209         {WT, spsr, 0x00},       /* Write pattern to SPSR register */
  210         {RD, spmr, 0x00},       /* Read back previously written pattern */
  211         {WT, spsr, 0xBF},       /* Write pattern to SPSR register */
  212         {RD, spmr, 0xBF},       /* Read back previously written pattern */
  213         {END, 0, 0}
  214 };
  215 
  216 static struct tst tst_count0_1[] = {
  217         {WT, cnt0, 0x55},       /* Verify every other bit can be set */
  218         {WT, cnt1, 0xAA},
  219         {RD, cnt0, 0x55},       /* Read back previously written pattern */
  220         {RD, cnt1, 0xAA},
  221         {WT, cnt0, 0xAA},       /* Verify every other bit can be set */
  222         {WT, cnt1, 0x55},
  223         {RD, cnt0, 0xAA},       /* Read back previously written pattern */
  224         {RD, cnt1, 0x55},
  225         {END, 0, 0}
  226 };
  227 
  228 static int
  229 tst_exec(struct tnt_softc *sc, struct tst *tp, const char *name)
  230 {
  231         uint8_t u;
  232         int step;
  233 
  234         for (step = 0; tp->action != END; tp++, step++) {
  235                 switch (tp->action) {
  236                 case WT:
  237                         bus_write_1(sc->res[1], tp->reg, tp->val);
  238                         break;
  239                 case RD:
  240                         u = bus_read_1(sc->res[1], tp->reg);
  241                         if (u != tp->val) {
  242                                 printf(
  243                                     "Test %s, step %d: reg(%02x) = %02x",
  244                                     name, step, tp->reg, u);
  245                                 printf( "should have been %02x\n", tp->val);
  246                                 return (1);
  247                         }
  248                         break;
  249                 case xDELAY:
  250                         DELAY(tp->val);
  251                         break;
  252                 default:
  253                         printf("Unknown action in test %s, step %d: %d\n",
  254                         name, step, tp->action);
  255                         return (1);
  256                 }
  257         }
  258         if (bootverbose)
  259                 printf("Test %s passed\n", name);
  260         return (0);
  261 }
  262 
  263 static int
  264 tnt_probe(device_t dev)
  265 {
  266 
  267         if (pci_get_vendor(dev) == 0x1093 && pci_get_device(dev) == 0xc801) {
  268                 device_set_desc(dev, "NI PCI-GPIB");
  269                 return (BUS_PROBE_DEFAULT);
  270         }
  271         return (ENXIO);
  272 }
  273 
  274 static int
  275 tnt_attach(device_t dev)
  276 {
  277         struct tnt_softc *sc;
  278         int error, i;
  279 
  280         sc = device_get_softc(dev);
  281 
  282         error = bus_alloc_resources(dev, tnt_res_spec, sc->res);
  283         if (error)
  284                 return (error);
  285 
  286         error = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE,
  287             NULL, upd7210intr, &sc->upd7210, &sc->intr_handler);
  288 
  289         /* Necessary magic for MITE */
  290         bus_write_4(sc->res[0], 0xc0, rman_get_start(sc->res[1]) | 0x80);
  291 
  292         tst_exec(sc, tst_reset, "Reset");
  293         tst_exec(sc, tst_read_reg, "Read registers");
  294         tst_exec(sc, tst_bsr_dcr, "BSR & DCR");
  295         tst_exec(sc, tst_adr0_1, "ADR0,1");
  296         tst_exec(sc, tst_cdor_dir, "CDOR/DIR");
  297         tst_exec(sc, tst_spmr_spsr, "CPMR/SPSR");
  298         tst_exec(sc, tst_count0_1, "COUNT0:1");
  299         tst_exec(sc, tst_reset, "Reset");
  300 
  301         /* pass 7210 interrupts through */
  302         bus_write_1(sc->res[1], imr3, 0x02);
  303 
  304         for (i = 0; i < 8; i++) {
  305                 sc->upd7210.reg_res[i] = sc->res[1];
  306                 sc->upd7210.reg_offset[i] = i * 2;
  307         }
  308 
  309         /* No DMA help */
  310         sc->upd7210.dmachan = -1;
  311 
  312         upd7210attach(&sc->upd7210);
  313 
  314         return (0);
  315 }
  316 
  317 static int
  318 tnt_detach(device_t dev)
  319 {
  320         struct tnt_softc *sc;
  321 
  322         sc = device_get_softc(dev);
  323         bus_teardown_intr(dev, sc->res[2], sc->intr_handler);
  324         upd7210detach(&sc->upd7210);
  325 
  326         bus_release_resources(dev, tnt_res_spec, sc->res);
  327 
  328         return (0);
  329 }
  330 
  331 static device_method_t  tnt4882_methods[] = {
  332         DEVMETHOD(device_probe,         tnt_probe),
  333         DEVMETHOD(device_attach,        tnt_attach),
  334         DEVMETHOD(device_detach,        tnt_detach),
  335         { 0, 0 }
  336 };
  337 
  338 static driver_t pci_gpib_driver = {
  339         "tnt4882",
  340         tnt4882_methods,
  341         sizeof(struct tnt_softc)
  342 };
  343 
  344 static devclass_t pci_gpib_devclass;
  345 
  346 DRIVER_MODULE(pci_gpib, pci, pci_gpib_driver, pci_gpib_devclass, 0, 0);

Cache object: 0760d4176394eefb6b5278730a42984a


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