digi_pci.c revision 76195
1/*-
2 * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
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/digi/digi_pci.c 76195 2001-05-02 01:08:09Z brian $
27 */
28
29#include <sys/param.h>
30
31#include <sys/systm.h>
32#include <sys/kernel.h>
33#include <sys/tty.h>
34#include <sys/syslog.h>
35#include <sys/bus.h>
36#include <machine/bus.h>
37#include <sys/rman.h>
38#include <machine/resource.h>
39#include <vm/vm.h>
40#include <vm/pmap.h>
41#include <pci/pcivar.h>
42
43#include <digi/digireg.h>
44#include <digi/digiio.h>
45#include <digi/digi.h>
46#include <digi/digi_pci.h>
47
48static u_char *
49digi_pci_setwin(struct digi_softc *sc, unsigned int addr)
50{
51	return (sc->vmem + addr);
52}
53
54static void
55digi_pci_hidewin(struct digi_softc *sc)
56{
57	return;
58}
59
60static void
61digi_pci_towin(struct digi_softc *sc, int win)
62{
63	return;
64}
65
66static int
67digi_pci_probe(device_t dev)
68{
69	unsigned int device_id = pci_get_devid(dev);
70
71	if (device_get_unit(dev) >= 16) {
72		/* Don't overflow our control mask */
73		device_printf(dev, "At most 16 digiboards may be used\n");
74		return (ENXIO);
75	}
76
77	if ((device_id & 0xffff) != PCI_VENDOR_DIGI)
78		return (ENXIO);
79
80	switch (device_id >> 16) {
81	case PCI_DEVICE_EPC:
82	case PCI_DEVICE_XEM:
83	case PCI_DEVICE_XR:
84	case PCI_DEVICE_CX:
85	case PCI_DEVICE_XRJ:
86	case PCI_DEVICE_EPCJ:
87	case PCI_DEVICE_920_4:
88	case PCI_DEVICE_920_8:
89	case PCI_DEVICE_920_2:
90		return 0;
91	}
92
93	return ENXIO;
94}
95
96static int
97digi_pci_attach(device_t dev)
98{
99	struct digi_softc *sc;
100	u_int32_t device_id;
101#ifdef DIGI_INTERRUPT
102	int retVal = 0;
103#endif
104
105	sc = device_get_softc(dev);
106	KASSERT(sc, ("digi%d: softc not allocated in digi_pci_attach\n",
107	    device_get_unit(dev)));
108
109	bzero(sc, sizeof(*sc));
110	sc->dev = dev;
111	sc->res.unit = device_get_unit(dev);
112
113	device_id = pci_get_devid(dev);
114	switch (device_id >> 16) {
115	case PCI_DEVICE_EPC:
116		sc->name = "Digiboard PCI EPC/X ASIC";
117		sc->res.mrid = 0x10;
118		sc->model = PCIEPCX;
119		sc->module = "EPCX_PCI";
120		break;
121	case PCI_DEVICE_XEM:
122		sc->name = "Digiboard PCI PC/Xem ASIC";
123		sc->res.mrid = 0x10;
124		sc->model = PCXEM;
125		sc->module = "Xem";
126		break;
127	case PCI_DEVICE_XR:
128		sc->name = "Digiboard PCI PC/Xr ASIC";
129		sc->res.mrid = 0x10;
130		sc->model = PCIXR;
131		sc->module = "Xr";
132		break;
133	case PCI_DEVICE_CX:
134		sc->name = "Digiboard PCI C/X ASIC";
135		sc->res.mrid = 0x10;
136		sc->model = PCCX;
137		sc->module = "CX_PCI";
138		break;
139	case PCI_DEVICE_XRJ:
140		sc->name = "Digiboard PCI PC/Xr PLX";
141		sc->res.mrid = 0x18;
142		sc->model = PCIXR;
143		sc->module = "Xr";
144		break;
145	case PCI_DEVICE_EPCJ:
146		sc->name = "Digiboard PCI EPC/X PLX";
147		sc->res.mrid = 0x18;
148		sc->model = PCIEPCX;
149		sc->module = "EPCX_PCI";
150		break;
151	case PCI_DEVICE_920_4:			/* Digi PCI4r 920 */
152		sc->name = "Digiboard PCI4r 920";
153		sc->res.mrid = 0x10;
154		sc->model = PCIXR;
155		sc->module = "Xr";
156		break;
157	case PCI_DEVICE_920_8:			/* Digi PCI8r 920 */
158		sc->name = "Digiboard PCI8r 920";
159		sc->res.mrid = 0x10;
160		sc->model = PCIXR;
161		sc->module = "Xr";
162		break;
163	case PCI_DEVICE_920_2:			/* Digi PCI2r 920 */
164		sc->name = "Digiboard PCI2r 920";
165		sc->res.mrid = 0x10;
166		sc->model = PCIXR;
167		sc->module = "Xr";
168		break;
169	default:
170		device_printf(dev, "Unknown device id = %08x\n", device_id);
171		return (ENXIO);
172	}
173
174	pci_write_config(dev, 0x40, 0, 4);
175	pci_write_config(dev, 0x46, 0, 4);
176
177	sc->res.mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->res.mrid,
178	    0, ~0, 1, RF_ACTIVE);
179
180#ifdef DIGI_INTERRUPT
181	sc->res.irqrid = 0;
182	sc->res.irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->res.irqrid,
183	    0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
184	if (sc->res.irq == NULL) {
185		device_printf(dev, "couldn't map interrupt\n");
186		return ENXIO;
187	}
188	retVal = bus_setup_intr(dev, sc->res.irq, INTR_TYPE_TTY,
189	    digiintr, sc, &sc->res.irqHandler);
190#else
191	DLOG(DIGIDB_IRQ, (sc->dev, "Interrupt support compiled out\n"));
192#endif
193
194	sc->vmem = rman_get_virtual(sc->res.mem);
195	sc->pmem = vtophys(sc->vmem);
196	sc->pcibus = 1;
197	sc->win_size = 0x200000;
198	sc->win_bits = 21;
199	sc->csigs = &digi_normal_signals;
200	sc->status = DIGI_STATUS_NOTINIT;
201	callout_handle_init(&sc->callout);
202	callout_handle_init(&sc->inttest);
203	sc->setwin = digi_pci_setwin;
204	sc->hidewin = digi_pci_hidewin;
205	sc->towin = digi_pci_towin;
206
207	PCIPORT = FEPRST;
208
209	return (digi_attach(sc));
210}
211
212static device_method_t digi_pci_methods[] = {
213	/* Device interface */
214	DEVMETHOD(device_probe, digi_pci_probe),
215	DEVMETHOD(device_attach, digi_pci_attach),
216	DEVMETHOD(device_detach, digi_detach),
217	DEVMETHOD(device_shutdown, digi_shutdown),
218	{0, 0}
219};
220
221static driver_t digi_pci_drv = {
222	"digi",
223	digi_pci_methods,
224	sizeof(struct digi_softc),
225};
226
227
228DRIVER_MODULE(digi, pci, digi_pci_drv, digi_devclass, digi_modhandler, 0);
229