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