]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/ieee488/tnt4882.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / dev / ieee488 / tnt4882.c
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$
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);