digi_pci.c revision 119277
1195878Skib/*-
2195636Skib * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
3195636Skib *   based on work by Slawa Olhovchenkov
4195636Skib *                    John Prince <johnp@knight-trosoft.com>
5195636Skib *                    Eric Hernes
6196554Sjilles * All rights reserved.
7195636Skib *
8195636Skib * Redistribution and use in source and binary forms, with or without
9195636Skib * modification, are permitted provided that the following conditions
10195636Skib * are met:
11195636Skib * 1. Redistributions of source code must retain the above copyright
12196554Sjilles *    notice, this list of conditions and the following disclaimer.
13195636Skib * 2. Redistributions in binary form must reproduce the above copyright
14196554Sjilles *    notice, this list of conditions and the following disclaimer in the
15195636Skib *    documentation and/or other materials provided with the distribution.
16195636Skib *
17195636Skib * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18195636Skib * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19195636Skib * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20195636Skib * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21195636Skib * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22195636Skib * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23195636Skib * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24195636Skib * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25195636Skib * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26195636Skib * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27195636Skib * SUCH DAMAGE.
28195636Skib *
29195636Skib * $FreeBSD: head/sys/dev/digi/digi_pci.c 119277 2003-08-22 05:54:52Z imp $
30195636Skib */
31195636Skib
32195636Skib#include <sys/param.h>
33195636Skib
34195636Skib#include <sys/systm.h>
35195636Skib#include <sys/kernel.h>
36195636Skib#include <sys/tty.h>
37#include <sys/bus.h>
38#include <machine/bus.h>
39#include <sys/rman.h>
40#include <machine/resource.h>
41#include <vm/vm.h>
42#include <vm/pmap.h>
43#include <dev/pci/pcivar.h>
44
45#include <sys/digiio.h>
46#include <dev/digi/digireg.h>
47#include <dev/digi/digi.h>
48#include <dev/digi/digi_pci.h>
49
50static u_char *
51digi_pci_setwin(struct digi_softc *sc, unsigned int addr)
52{
53	return (sc->vmem + addr);
54}
55
56static void
57digi_pci_hidewin(struct digi_softc *sc)
58{
59	return;
60}
61
62static void
63digi_pci_towin(struct digi_softc *sc, int win)
64{
65	return;
66}
67
68static int
69digi_pci_probe(device_t dev)
70{
71	unsigned int device_id = pci_get_devid(dev);
72
73	if (device_get_unit(dev) >= 16) {
74		/* Don't overflow our control mask */
75		device_printf(dev, "At most 16 digiboards may be used\n");
76		return (ENXIO);
77	}
78
79	if ((device_id & 0xffff) != PCI_VENDOR_DIGI)
80		return (ENXIO);
81
82	switch (device_id >> 16) {
83	case PCI_DEVICE_EPC:
84	case PCI_DEVICE_XEM:
85	case PCI_DEVICE_XR:
86	case PCI_DEVICE_CX:
87	case PCI_DEVICE_XRJ:
88	case PCI_DEVICE_EPCJ:
89	case PCI_DEVICE_920_4:
90	case PCI_DEVICE_920_8:
91	case PCI_DEVICE_920_2:
92		return (0);
93	}
94
95	return (ENXIO);
96}
97
98static int
99digi_pci_attach(device_t dev)
100{
101	struct digi_softc *sc;
102	u_int32_t device_id;
103#ifdef DIGI_INTERRUPT
104	int retVal = 0;
105#endif
106
107	sc = device_get_softc(dev);
108	KASSERT(sc, ("digi%d: softc not allocated in digi_pci_attach\n",
109	    device_get_unit(dev)));
110
111	bzero(sc, sizeof(*sc));
112	sc->dev = dev;
113	sc->res.unit = device_get_unit(dev);
114
115	device_id = pci_get_devid(dev);
116	switch (device_id >> 16) {
117	case PCI_DEVICE_EPC:
118		sc->name = "Digiboard PCI EPC/X ASIC";
119		sc->res.mrid = 0x10;
120		sc->model = PCIEPCX;
121		sc->module = "EPCX_PCI";
122		break;
123	case PCI_DEVICE_XEM:
124		sc->name = "Digiboard PCI PC/Xem ASIC";
125		sc->res.mrid = 0x10;
126		sc->model = PCXEM;
127		sc->module = "Xem";
128		break;
129	case PCI_DEVICE_XR:
130		sc->name = "Digiboard PCI PC/Xr ASIC";
131		sc->res.mrid = 0x10;
132		sc->model = PCIXR;
133		sc->module = "Xr";
134		break;
135	case PCI_DEVICE_CX:
136		sc->name = "Digiboard PCI C/X ASIC";
137		sc->res.mrid = 0x10;
138		sc->model = PCCX;
139		sc->module = "CX_PCI";
140		break;
141	case PCI_DEVICE_XRJ:
142		sc->name = "Digiboard PCI PC/Xr PLX";
143		sc->res.mrid = 0x18;
144		sc->model = PCIXR;
145		sc->module = "Xr";
146		break;
147	case PCI_DEVICE_EPCJ:
148		sc->name = "Digiboard PCI EPC/X PLX";
149		sc->res.mrid = 0x18;
150		sc->model = PCIEPCX;
151		sc->module = "EPCX_PCI";
152		break;
153	case PCI_DEVICE_920_4:			/* Digi PCI4r 920 */
154		sc->name = "Digiboard PCI4r 920";
155		sc->res.mrid = 0x10;
156		sc->model = PCIXR;
157		sc->module = "Xr";
158		break;
159	case PCI_DEVICE_920_8:			/* Digi PCI8r 920 */
160		sc->name = "Digiboard PCI8r 920";
161		sc->res.mrid = 0x10;
162		sc->model = PCIXR;
163		sc->module = "Xr";
164		break;
165	case PCI_DEVICE_920_2:			/* Digi PCI2r 920 */
166		sc->name = "Digiboard PCI2r 920";
167		sc->res.mrid = 0x10;
168		sc->model = PCIXR;
169		sc->module = "Xr";
170		break;
171	default:
172		device_printf(dev, "Unknown device id = %08x\n", device_id);
173		return (ENXIO);
174	}
175
176	pci_write_config(dev, 0x40, 0, 4);
177	pci_write_config(dev, 0x46, 0, 4);
178
179	sc->res.mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->res.mrid,
180	    0, ~0, 1, RF_ACTIVE);
181
182#ifdef DIGI_INTERRUPT
183	sc->res.irqrid = 0;
184	sc->res.irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->res.irqrid,
185	    0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
186	if (sc->res.irq == NULL) {
187		device_printf(dev, "couldn't map interrupt\n");
188		return (ENXIO);
189	}
190	retVal = bus_setup_intr(dev, sc->res.irq, INTR_TYPE_TTY,
191	    digiintr, sc, &sc->res.irqHandler);
192#else
193	DLOG(DIGIDB_IRQ, (sc->dev, "Interrupt support compiled out\n"));
194#endif
195
196	sc->vmem = rman_get_virtual(sc->res.mem);
197	sc->pmem = vtophys(sc->vmem);
198	sc->pcibus = 1;
199	sc->win_size = 0x200000;
200	sc->win_bits = 21;
201	sc->csigs = &digi_normal_signals;
202	sc->status = DIGI_STATUS_NOTINIT;
203	callout_handle_init(&sc->callout);
204	callout_handle_init(&sc->inttest);
205	sc->setwin = digi_pci_setwin;
206	sc->hidewin = digi_pci_hidewin;
207	sc->towin = digi_pci_towin;
208
209	PCIPORT = FEPRST;
210
211	return (digi_attach(sc));
212}
213
214static device_method_t digi_pci_methods[] = {
215	/* Device interface */
216	DEVMETHOD(device_probe, digi_pci_probe),
217	DEVMETHOD(device_attach, digi_pci_attach),
218	DEVMETHOD(device_detach, digi_detach),
219	DEVMETHOD(device_shutdown, digi_shutdown),
220	{0, 0}
221};
222
223static driver_t digi_pci_drv = {
224	"digi",
225	digi_pci_methods,
226	sizeof(struct digi_softc),
227};
228DRIVER_MODULE(digi, pci, digi_pci_drv, digi_devclass, 0, 0);
229