pcii.c revision 202870
1251881Speter/*-
2251881Speter * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org>
3251881Speter * Copyright (c) 2010 Joerg Wunsch <joerg@FreeBSD.org>
4251881Speter * All rights reserved.
5251881Speter *
6251881Speter * Redistribution and use in source and binary forms, with or without
7251881Speter * modification, are permitted provided that the following conditions
8251881Speter * are met:
9251881Speter * 1. Redistributions of source code must retain the above copyright
10251881Speter *    notice, this list of conditions and the following disclaimer.
11251881Speter * 2. Redistributions in binary form must reproduce the above copyright
12251881Speter *    notice, this list of conditions and the following disclaimer in the
13251881Speter *    documentation and/or other materials provided with the distribution.
14251881Speter *
15251881Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16251881Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17251881Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18251881Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19251881Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20251881Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21251881Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22251881Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23251881Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24251881Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25251881Speter * SUCH DAMAGE.
26251881Speter *
27251881Speter * Driver for GPIB cards based on NEC �PD7210 and compatibles.
28251881Speter *
29251881Speter * This driver just hooks up to the hardware and leaves all the interesting
30251881Speter * stuff to upd7210.c.
31251881Speter *
32251881Speter * Supported hardware:
33251881Speter *    PCIIA compatible cards.
34251881Speter *
35251881Speter *    Tested and known working:
36251881Speter *	"B&C Microsystems PC488A-0"
37251881Speter *	"National Instruments GPIB-PCII/PCIIA" (in PCIIa mode)
38251881Speter *	"Axiom AX5488"
39251881Speter *
40251881Speter */
41251881Speter
42251881Speter#include <sys/cdefs.h>
43251881Speter__FBSDID("$FreeBSD: head/sys/dev/ieee488/pcii.c 202870 2010-01-23 07:54:06Z joerg $");
44251881Speter
45251881Speter#include <sys/param.h>
46251881Speter#include <sys/systm.h>
47251881Speter#include <sys/lock.h>
48251881Speter#include <sys/mutex.h>
49251881Speter#include <sys/kernel.h>
50251881Speter#include <sys/module.h>
51251881Speter#include <sys/bus.h>
52251881Speter#include <machine/bus.h>
53251881Speter#include <machine/resource.h>
54251881Speter#include <sys/rman.h>
55251881Speter#include <isa/isavar.h>
56251881Speter
57251881Speter#define UPD7210_HW_DRIVER
58251881Speter#include <dev/ieee488/upd7210.h>
59251881Speter
60251881Speterstruct pcii_softc {
61251881Speter	int foo;
62251881Speter	struct resource	*res[11];
63251881Speter	void *intr_handler;
64251881Speter	struct upd7210	upd7210;
65251881Speter};
66251881Speter
67251881Speterstatic devclass_t pcii_devclass;
68251881Speter
69251881Speterstatic int	pcii_probe(device_t dev);
70251881Speterstatic int	pcii_attach(device_t dev);
71251881Speter
72251881Speterstatic device_method_t pcii_methods[] = {
73251881Speter	DEVMETHOD(device_probe,		pcii_probe),
74251881Speter	DEVMETHOD(device_attach,	pcii_attach),
75251881Speter	DEVMETHOD(device_suspend,	bus_generic_suspend),
76251881Speter	DEVMETHOD(device_resume,	bus_generic_resume),
77251881Speter
78251881Speter	{ 0, 0 }
79251881Speter};
80251881Speter
81251881Speterstatic struct resource_spec pcii_res_spec[] = {
82251881Speter	{ SYS_RES_IRQ,		0, RF_ACTIVE | RF_SHAREABLE},
83251881Speter	{ SYS_RES_DRQ,		0, RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL},
84251881Speter	{ SYS_RES_IOPORT,	0, RF_ACTIVE},
85251881Speter	{ SYS_RES_IOPORT,	1, RF_ACTIVE},
86251881Speter	{ SYS_RES_IOPORT,	2, RF_ACTIVE},
87251881Speter	{ SYS_RES_IOPORT,	3, RF_ACTIVE},
88251881Speter	{ SYS_RES_IOPORT,	4, RF_ACTIVE},
89251881Speter	{ SYS_RES_IOPORT,	5, RF_ACTIVE},
90251881Speter	{ SYS_RES_IOPORT,	6, RF_ACTIVE},
91251881Speter	{ SYS_RES_IOPORT,	7, RF_ACTIVE},
92251881Speter	{ SYS_RES_IOPORT,	8, RF_ACTIVE | RF_SHAREABLE},
93251881Speter	{ -1, 0, 0 }
94251881Speter};
95251881Speter
96251881Speterstatic driver_t pcii_driver = {
97251881Speter	"pcii",
98251881Speter	pcii_methods,
99251881Speter	sizeof(struct pcii_softc),
100251881Speter};
101251881Speter
102251881Speterstatic int
103251881Speterpcii_probe(device_t dev)
104251881Speter{
105251881Speter	int rid, i, j;
106251881Speter	u_long start, count, addr;
107251881Speter	int error = 0;
108251881Speter	struct pcii_softc *sc;
109251881Speter
110251881Speter	device_set_desc(dev, "PCII IEEE-4888 controller");
111251881Speter	sc = device_get_softc(dev);
112251881Speter
113251881Speter	rid = 0;
114251881Speter	if (bus_get_resource(dev, SYS_RES_IOPORT, rid, &start, &count) != 0)
115251881Speter		return ENXIO;
116251881Speter	/*
117251881Speter	 * The PCIIA decodes a fixed pattern of 0x2e1 for the lower 10
118251881Speter	 * address bits A0 ... A9.  Bits A10 through A12 are used by
119251881Speter	 * the �PD7210 register select lines.  This makes the
120251881Speter	 * individual 7210 register being 0x400 bytes apart in the ISA
121251881Speter	 * bus address space.  Address bits A13 and A14 are compared
122251881Speter	 * to a DIP switch setting on the card, allowing for up to 4
123251881Speter	 * different cards being installed (at base addresses 0x2e1,
124251881Speter	 * 0x22e1, 0x42e1, and 0x62e1, respectively).  A15 has been
125251881Speter	 * used to select an optional on-board time-of-day clock chip
126251881Speter	 * (MM58167A) on the original PCIIA rather than the �PD7210
127251881Speter	 * (which is not implemented on later boards).  The
128251881Speter	 * documentation states the respective addresses for that chip
129251881Speter	 * should be handled as reserved addresses, which we don't do
130251881Speter	 * (right now).  Finally, the IO addresses 0x2f0 ... 0x2f7 for
131251881Speter	 * a "special interrupt handling feature" (re-enable
132	 * interrupts so the IRQ can be shared).
133	 *
134	 * Usually, the user will only set the base address in the
135	 * device hints, so we handle the rest here.
136	 *
137	 * (Source: GPIB-PCIIA Technical Reference Manual, September
138	 * 1989 Edition, National Instruments.)
139	 */
140	if ((start & 0x3ff) != 0x2e1) {
141		printf("pcii_probe: PCIIA base address 0x%lx not "
142		       "0x2e1/0x22e1/0x42e1/0x62e1\n",
143		       start);
144		return (ENXIO);
145	}
146
147	for (rid = 0, addr = start; rid < 8; rid++, addr += 0x400) {
148		if (bus_set_resource(dev, SYS_RES_IOPORT, rid, addr, 1) != 0) {
149			printf("pcii_probe: could not set IO port 0x%lx\n",
150			       addr);
151			return (ENXIO);
152		}
153	}
154	if (bus_get_resource(dev, SYS_RES_IRQ, 0, &start, &count) != 0) {
155		printf("pcii_probe: cannot obtain IRQ level\n");
156		return ENXIO;
157	}
158	if (start > 7) {
159		printf("pcii_probe: IRQ level %lu too high\n", start);
160		return ENXIO;
161	}
162
163	if (bus_set_resource(dev, SYS_RES_IOPORT, 8, 0x2f0 + start, 1) != 0) {
164		printf("pcii_probe: could not set IO port 0x%3lx\n",
165		       0x2f0 + start);
166		return (ENXIO);
167	}
168
169	error = bus_alloc_resources(dev, pcii_res_spec, sc->res);
170	if (error) {
171		printf("pcii_probe: Could not allocate resources\n");
172		return (error);
173	}
174	error = ENXIO;
175	/*
176	 * Perform some basic tests on the �PD7210 registers.  At
177	 * least *some* register must read different from 0x00 or
178	 * 0xff.
179	 */
180	for (i = 0; i < 8; i++) {
181		j = bus_read_1(sc->res[2 + i], 0);
182		if (j != 0x00 && j != 0xff)
183			error = 0;
184	}
185	/* SPSR/SPMR read/write test */
186	if (!error) {
187		bus_write_1(sc->res[2 + 3], 0, 0x55);
188		if (bus_read_1(sc->res[2 + 3], 0) != 0x55)
189			error = ENXIO;
190	}
191	if (!error) {
192		bus_write_1(sc->res[2 + 3], 0, 0xaa);
193		if (bus_read_1(sc->res[2 + 3], 0) != 0xaa)
194			error = ENXIO;
195	}
196	if (error)
197		printf("pcii_probe: probe failure\n");
198
199	bus_release_resources(dev, pcii_res_spec, sc->res);
200	return (error);
201}
202
203static int
204pcii_attach(device_t dev)
205{
206	struct pcii_softc *sc;
207	u_long		start, count;
208	int		unit;
209	int		rid;
210	int		error = 0;
211
212	unit = device_get_unit(dev);
213	sc = device_get_softc(dev);
214	memset(sc, 0, sizeof *sc);
215
216	device_set_desc(dev, "PCII IEEE-4888 controller");
217
218	if (bus_get_resource(dev, SYS_RES_IRQ, 0, &start, &count) != 0) {
219		printf("pcii_attach: cannot obtain IRQ number\n");
220		return ENXIO;
221	}
222
223	error = bus_alloc_resources(dev, pcii_res_spec, sc->res);
224	if (error)
225		return (error);
226
227	error = bus_setup_intr(dev, sc->res[0],
228	    INTR_TYPE_MISC | INTR_MPSAFE, NULL,
229	    upd7210intr, &sc->upd7210, &sc->intr_handler);
230	if (error) {
231		bus_release_resources(dev, pcii_res_spec, sc->res);
232		return (error);
233	}
234
235	for (rid = 0; rid < 8; rid++) {
236		sc->upd7210.reg_res[rid] = sc->res[2 + rid];
237	}
238	sc->upd7210.irq_clear_res = sc->res[10];
239
240	if (sc->res[1] == NULL)
241		sc->upd7210.dmachan = -1;
242	else
243		sc->upd7210.dmachan = rman_get_start(sc->res[1]);
244
245	upd7210attach(&sc->upd7210);
246	return (error);
247}
248
249DRIVER_MODULE(pcii, isa, pcii_driver, pcii_devclass, 0, 0);
250DRIVER_MODULE(pcii, acpi, pcii_driver, pcii_devclass, 0, 0);
251