digi_pci.c revision 143161
122347Spst/*-
222347Spst * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
329967Sache *   based on work by Slawa Olhovchenkov
492914Smarkm *                    John Prince <johnp@knight-trosoft.com>
522347Spst *                    Eric Hernes
622347Spst * All rights reserved.
722347Spst *
822347Spst * Redistribution and use in source and binary forms, with or without
922347Spst * modification, are permitted provided that the following conditions
1022347Spst * are met:
1122347Spst * 1. Redistributions of source code must retain the above copyright
1222347Spst *    notice, this list of conditions and the following disclaimer.
1322347Spst * 2. Redistributions in binary form must reproduce the above copyright
1422347Spst *    notice, this list of conditions and the following disclaimer in the
1522347Spst *    documentation and/or other materials provided with the distribution.
1622347Spst *
1722347Spst * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1822347Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1922347Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2022347Spst * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2122347Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2259121Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2322347Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2422347Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2522347Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2622347Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2722347Spst * SUCH DAMAGE.
2822347Spst */
2922347Spst
3022347Spst#include <sys/cdefs.h>
3122347Spst__FBSDID("$FreeBSD: head/sys/dev/digi/digi_pci.c 143161 2005-03-05 18:30:12Z imp $");
3222347Spst
3322347Spst#include <sys/param.h>
3422347Spst
3522347Spst#include <sys/systm.h>
3622347Spst#include <sys/kernel.h>
3722347Spst#include <sys/module.h>
3822347Spst#include <sys/tty.h>
3922347Spst#include <sys/bus.h>
4022347Spst#include <machine/bus.h>
4122347Spst#include <sys/rman.h>
4222347Spst#include <machine/resource.h>
4322347Spst#include <vm/vm.h>
4422347Spst#include <vm/pmap.h>
4522347Spst#include <dev/pci/pcivar.h>
4622347Spst
4722347Spst#include <sys/digiio.h>
4822347Spst#include <dev/digi/digireg.h>
4922347Spst#include <dev/digi/digi.h>
5022347Spst#include <dev/digi/digi_pci.h>
5122347Spst
5222347Spststatic u_char *
5322347Spstdigi_pci_setwin(struct digi_softc *sc, unsigned int addr)
5422347Spst{
5522347Spst	return (sc->vmem + addr);
5622347Spst}
5722347Spst
5822347Spststatic void
5922347Spstdigi_pci_hidewin(struct digi_softc *sc)
6022347Spst{
6122347Spst	return;
6222347Spst}
6322347Spst
6422347Spststatic void
6522347Spstdigi_pci_towin(struct digi_softc *sc, int win)
6622347Spst{
6722347Spst	return;
6822347Spst}
6922347Spst
7022347Spststatic int
7122347Spstdigi_pci_probe(device_t dev)
7222347Spst{
7322347Spst	unsigned int device_id = pci_get_devid(dev);
7422347Spst
7522347Spst	if (device_get_unit(dev) >= 16) {
7622347Spst		/* Don't overflow our control mask */
7722347Spst		device_printf(dev, "At most 16 digiboards may be used\n");
7822347Spst		return (ENXIO);
7922347Spst	}
8022347Spst
8122347Spst	if ((device_id & 0xffff) != PCI_VENDOR_DIGI)
8222347Spst		return (ENXIO);
8322372Spst
8422372Spst	switch (device_id >> 16) {
8522372Spst	case PCI_DEVICE_EPC:
8622347Spst	case PCI_DEVICE_XEM:
8722347Spst	case PCI_DEVICE_XR:
8822347Spst	case PCI_DEVICE_CX:
8922347Spst	case PCI_DEVICE_XRJ:
9022347Spst	case PCI_DEVICE_EPCJ:
9122347Spst	case PCI_DEVICE_920_4:
9222347Spst	case PCI_DEVICE_920_8:
9322347Spst	case PCI_DEVICE_920_2:
9422347Spst		return (BUS_PROBE_DEFAULT);
9522347Spst	}
9622347Spst
9722347Spst	return (ENXIO);
9822347Spst}
9922347Spst
10022347Spststatic int
101digi_pci_attach(device_t dev)
102{
103	struct digi_softc *sc;
104	u_int32_t device_id;
105#ifdef DIGI_INTERRUPT
106	int retVal = 0;
107#endif
108
109	sc = device_get_softc(dev);
110	KASSERT(sc, ("digi%d: softc not allocated in digi_pci_attach\n",
111	    device_get_unit(dev)));
112
113	bzero(sc, sizeof(*sc));
114	sc->dev = dev;
115	sc->res.unit = device_get_unit(dev);
116
117	device_id = pci_get_devid(dev);
118	switch (device_id >> 16) {
119	case PCI_DEVICE_EPC:
120		sc->name = "Digiboard PCI EPC/X ASIC";
121		sc->res.mrid = 0x10;
122		sc->model = PCIEPCX;
123		sc->module = "EPCX_PCI";
124		break;
125	case PCI_DEVICE_XEM:
126		sc->name = "Digiboard PCI PC/Xem ASIC";
127		sc->res.mrid = 0x10;
128		sc->model = PCXEM;
129		sc->module = "Xem";
130		break;
131	case PCI_DEVICE_XR:
132		sc->name = "Digiboard PCI PC/Xr ASIC";
133		sc->res.mrid = 0x10;
134		sc->model = PCIXR;
135		sc->module = "Xr";
136		break;
137	case PCI_DEVICE_CX:
138		sc->name = "Digiboard PCI C/X ASIC";
139		sc->res.mrid = 0x10;
140		sc->model = PCCX;
141		sc->module = "CX_PCI";
142		break;
143	case PCI_DEVICE_XRJ:
144		sc->name = "Digiboard PCI PC/Xr PLX";
145		sc->res.mrid = 0x18;
146		sc->model = PCIXR;
147		sc->module = "Xr";
148		break;
149	case PCI_DEVICE_EPCJ:
150		sc->name = "Digiboard PCI EPC/X PLX";
151		sc->res.mrid = 0x18;
152		sc->model = PCIEPCX;
153		sc->module = "EPCX_PCI";
154		break;
155	case PCI_DEVICE_920_4:			/* Digi PCI4r 920 */
156		sc->name = "Digiboard PCI4r 920";
157		sc->res.mrid = 0x10;
158		sc->model = PCIXR;
159		sc->module = "Xr";
160		break;
161	case PCI_DEVICE_920_8:			/* Digi PCI8r 920 */
162		sc->name = "Digiboard PCI8r 920";
163		sc->res.mrid = 0x10;
164		sc->model = PCIXR;
165		sc->module = "Xr";
166		break;
167	case PCI_DEVICE_920_2:			/* Digi PCI2r 920 */
168		sc->name = "Digiboard PCI2r 920";
169		sc->res.mrid = 0x10;
170		sc->model = PCIXR;
171		sc->module = "Xr";
172		break;
173	default:
174		device_printf(dev, "Unknown device id = %08x\n", device_id);
175		return (ENXIO);
176	}
177
178	pci_write_config(dev, 0x40, 0, 4);
179	pci_write_config(dev, 0x46, 0, 4);
180
181	sc->res.mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->res.mrid,
182	    RF_ACTIVE);
183
184#ifdef DIGI_INTERRUPT
185	sc->res.irqrid = 0;
186	sc->res.irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->res.irqrid,
187	    RF_SHAREABLE | RF_ACTIVE);
188	if (sc->res.irq == NULL) {
189		device_printf(dev, "couldn't map interrupt\n");
190		return (ENXIO);
191	}
192	retVal = bus_setup_intr(dev, sc->res.irq, INTR_TYPE_TTY,
193	    digiintr, sc, &sc->res.irqHandler);
194#else
195	DLOG(DIGIDB_IRQ, (sc->dev, "Interrupt support compiled out\n"));
196#endif
197
198	sc->vmem = rman_get_virtual(sc->res.mem);
199	sc->pmem = vtophys(sc->vmem);
200	sc->pcibus = 1;
201	sc->win_size = 0x200000;
202	sc->win_bits = 21;
203	sc->csigs = &digi_normal_signals;
204	sc->status = DIGI_STATUS_NOTINIT;
205	callout_handle_init(&sc->callout);
206	callout_handle_init(&sc->inttest);
207	sc->setwin = digi_pci_setwin;
208	sc->hidewin = digi_pci_hidewin;
209	sc->towin = digi_pci_towin;
210
211	PCIPORT = FEPRST;
212
213	return (digi_attach(sc));
214}
215
216static device_method_t digi_pci_methods[] = {
217	/* Device interface */
218	DEVMETHOD(device_probe, digi_pci_probe),
219	DEVMETHOD(device_attach, digi_pci_attach),
220	DEVMETHOD(device_detach, digi_detach),
221	DEVMETHOD(device_shutdown, digi_shutdown),
222	{0, 0}
223};
224
225static driver_t digi_pci_drv = {
226	"digi",
227	digi_pci_methods,
228	sizeof(struct digi_softc),
229};
230DRIVER_MODULE(digi, pci, digi_pci_drv, digi_devclass, 0, 0);
231