tnt4882.c revision 166914
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: head/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
50struct tnt_softc {
51	int foo;
52	struct upd7210		upd7210;
53
54	struct resource		*res[3];
55	void			*intr_handler;
56};
57
58static 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
65enum 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
114struct 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 */
126static 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
150static 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
164static 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
180static 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
192static 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
208static 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
216static 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
228static int
229tst_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
263static int
264tnt_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
274static int
275tnt_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
317static int
318tnt_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
331static 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
338static driver_t pci_gpib_driver = {
339	"tnt4882",
340	tnt4882_methods,
341	sizeof(struct tnt_softc)
342};
343
344static devclass_t pci_gpib_devclass;
345
346DRIVER_MODULE(pci_gpib, pci, pci_gpib_driver, pci_gpib_devclass, 0, 0);
347