digi_pci.c revision 127135
176195Sbrian/*-
276195Sbrian * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
376358Sbrian *   based on work by Slawa Olhovchenkov
476358Sbrian *                    John Prince <johnp@knight-trosoft.com>
576358Sbrian *                    Eric Hernes
676195Sbrian * All rights reserved.
776195Sbrian *
876195Sbrian * Redistribution and use in source and binary forms, with or without
976195Sbrian * modification, are permitted provided that the following conditions
1076195Sbrian * are met:
1176195Sbrian * 1. Redistributions of source code must retain the above copyright
1276195Sbrian *    notice, this list of conditions and the following disclaimer.
1376195Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1476195Sbrian *    notice, this list of conditions and the following disclaimer in the
1576195Sbrian *    documentation and/or other materials provided with the distribution.
1676195Sbrian *
1776195Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1876195Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1976195Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2076195Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2176195Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2276195Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2376195Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2476195Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2576195Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2676195Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2776195Sbrian * SUCH DAMAGE.
2876195Sbrian */
2976195Sbrian
30119418Sobrien#include <sys/cdefs.h>
31119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/digi/digi_pci.c 127135 2004-03-17 17:50:55Z njl $");
32119418Sobrien
3376195Sbrian#include <sys/param.h>
3476195Sbrian
3576195Sbrian#include <sys/systm.h>
3676195Sbrian#include <sys/kernel.h>
3776195Sbrian#include <sys/tty.h>
3876195Sbrian#include <sys/bus.h>
3976195Sbrian#include <machine/bus.h>
4076195Sbrian#include <sys/rman.h>
4176195Sbrian#include <machine/resource.h>
4276195Sbrian#include <vm/vm.h>
4376195Sbrian#include <vm/pmap.h>
44119277Simp#include <dev/pci/pcivar.h>
4576195Sbrian
4676848Sbrian#include <sys/digiio.h>
4776853Sbrian#include <dev/digi/digireg.h>
4876853Sbrian#include <dev/digi/digi.h>
4976853Sbrian#include <dev/digi/digi_pci.h>
5076195Sbrian
5176195Sbrianstatic u_char *
5276195Sbriandigi_pci_setwin(struct digi_softc *sc, unsigned int addr)
5376195Sbrian{
5476195Sbrian	return (sc->vmem + addr);
5576195Sbrian}
5676195Sbrian
5776195Sbrianstatic void
5876195Sbriandigi_pci_hidewin(struct digi_softc *sc)
5976195Sbrian{
6076195Sbrian	return;
6176195Sbrian}
6276195Sbrian
6376195Sbrianstatic void
6476195Sbriandigi_pci_towin(struct digi_softc *sc, int win)
6576195Sbrian{
6676195Sbrian	return;
6776195Sbrian}
6876195Sbrian
6976195Sbrianstatic int
7076195Sbriandigi_pci_probe(device_t dev)
7176195Sbrian{
7276195Sbrian	unsigned int device_id = pci_get_devid(dev);
7376195Sbrian
7476195Sbrian	if (device_get_unit(dev) >= 16) {
7576195Sbrian		/* Don't overflow our control mask */
7676195Sbrian		device_printf(dev, "At most 16 digiboards may be used\n");
7776195Sbrian		return (ENXIO);
7876195Sbrian	}
7976195Sbrian
8076195Sbrian	if ((device_id & 0xffff) != PCI_VENDOR_DIGI)
8176195Sbrian		return (ENXIO);
8276195Sbrian
8376195Sbrian	switch (device_id >> 16) {
8476195Sbrian	case PCI_DEVICE_EPC:
8576195Sbrian	case PCI_DEVICE_XEM:
8676195Sbrian	case PCI_DEVICE_XR:
8776195Sbrian	case PCI_DEVICE_CX:
8876195Sbrian	case PCI_DEVICE_XRJ:
8976195Sbrian	case PCI_DEVICE_EPCJ:
9076195Sbrian	case PCI_DEVICE_920_4:
9176195Sbrian	case PCI_DEVICE_920_8:
9276195Sbrian	case PCI_DEVICE_920_2:
9376358Sbrian		return (0);
9476195Sbrian	}
9576195Sbrian
9676358Sbrian	return (ENXIO);
9776195Sbrian}
9876195Sbrian
9976195Sbrianstatic int
10076195Sbriandigi_pci_attach(device_t dev)
10176195Sbrian{
10276195Sbrian	struct digi_softc *sc;
10376195Sbrian	u_int32_t device_id;
10476195Sbrian#ifdef DIGI_INTERRUPT
10576195Sbrian	int retVal = 0;
10676195Sbrian#endif
10776195Sbrian
10876195Sbrian	sc = device_get_softc(dev);
10976195Sbrian	KASSERT(sc, ("digi%d: softc not allocated in digi_pci_attach\n",
11076195Sbrian	    device_get_unit(dev)));
11176195Sbrian
11276195Sbrian	bzero(sc, sizeof(*sc));
11376195Sbrian	sc->dev = dev;
11476195Sbrian	sc->res.unit = device_get_unit(dev);
11576195Sbrian
11676195Sbrian	device_id = pci_get_devid(dev);
11776195Sbrian	switch (device_id >> 16) {
11876195Sbrian	case PCI_DEVICE_EPC:
11976195Sbrian		sc->name = "Digiboard PCI EPC/X ASIC";
12076195Sbrian		sc->res.mrid = 0x10;
12176195Sbrian		sc->model = PCIEPCX;
12276195Sbrian		sc->module = "EPCX_PCI";
12376195Sbrian		break;
12476195Sbrian	case PCI_DEVICE_XEM:
12576195Sbrian		sc->name = "Digiboard PCI PC/Xem ASIC";
12676195Sbrian		sc->res.mrid = 0x10;
12776195Sbrian		sc->model = PCXEM;
12876195Sbrian		sc->module = "Xem";
12976195Sbrian		break;
13076195Sbrian	case PCI_DEVICE_XR:
13176195Sbrian		sc->name = "Digiboard PCI PC/Xr ASIC";
13276195Sbrian		sc->res.mrid = 0x10;
13376195Sbrian		sc->model = PCIXR;
13476195Sbrian		sc->module = "Xr";
13576195Sbrian		break;
13676195Sbrian	case PCI_DEVICE_CX:
13776195Sbrian		sc->name = "Digiboard PCI C/X ASIC";
13876195Sbrian		sc->res.mrid = 0x10;
13976195Sbrian		sc->model = PCCX;
14076195Sbrian		sc->module = "CX_PCI";
14176195Sbrian		break;
14276195Sbrian	case PCI_DEVICE_XRJ:
14376195Sbrian		sc->name = "Digiboard PCI PC/Xr PLX";
14476195Sbrian		sc->res.mrid = 0x18;
14576195Sbrian		sc->model = PCIXR;
14676195Sbrian		sc->module = "Xr";
14776195Sbrian		break;
14876195Sbrian	case PCI_DEVICE_EPCJ:
14976195Sbrian		sc->name = "Digiboard PCI EPC/X PLX";
15076195Sbrian		sc->res.mrid = 0x18;
15176195Sbrian		sc->model = PCIEPCX;
15276195Sbrian		sc->module = "EPCX_PCI";
15376195Sbrian		break;
15476195Sbrian	case PCI_DEVICE_920_4:			/* Digi PCI4r 920 */
15576195Sbrian		sc->name = "Digiboard PCI4r 920";
15676195Sbrian		sc->res.mrid = 0x10;
15776195Sbrian		sc->model = PCIXR;
15876195Sbrian		sc->module = "Xr";
15976195Sbrian		break;
16076195Sbrian	case PCI_DEVICE_920_8:			/* Digi PCI8r 920 */
16176195Sbrian		sc->name = "Digiboard PCI8r 920";
16276195Sbrian		sc->res.mrid = 0x10;
16376195Sbrian		sc->model = PCIXR;
16476195Sbrian		sc->module = "Xr";
16576195Sbrian		break;
16676195Sbrian	case PCI_DEVICE_920_2:			/* Digi PCI2r 920 */
16776195Sbrian		sc->name = "Digiboard PCI2r 920";
16876195Sbrian		sc->res.mrid = 0x10;
16976195Sbrian		sc->model = PCIXR;
17076195Sbrian		sc->module = "Xr";
17176195Sbrian		break;
17276195Sbrian	default:
17376195Sbrian		device_printf(dev, "Unknown device id = %08x\n", device_id);
17476195Sbrian		return (ENXIO);
17576195Sbrian	}
17676195Sbrian
17776195Sbrian	pci_write_config(dev, 0x40, 0, 4);
17876195Sbrian	pci_write_config(dev, 0x46, 0, 4);
17976195Sbrian
180127135Snjl	sc->res.mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->res.mrid,
181127135Snjl	    RF_ACTIVE);
18276195Sbrian
18376195Sbrian#ifdef DIGI_INTERRUPT
18476195Sbrian	sc->res.irqrid = 0;
185127135Snjl	sc->res.irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->res.irqrid,
186127135Snjl	    RF_SHAREABLE | RF_ACTIVE);
18776195Sbrian	if (sc->res.irq == NULL) {
18876195Sbrian		device_printf(dev, "couldn't map interrupt\n");
18976358Sbrian		return (ENXIO);
19076195Sbrian	}
19176195Sbrian	retVal = bus_setup_intr(dev, sc->res.irq, INTR_TYPE_TTY,
19276195Sbrian	    digiintr, sc, &sc->res.irqHandler);
19376195Sbrian#else
19476195Sbrian	DLOG(DIGIDB_IRQ, (sc->dev, "Interrupt support compiled out\n"));
19576195Sbrian#endif
19676195Sbrian
19776195Sbrian	sc->vmem = rman_get_virtual(sc->res.mem);
19876195Sbrian	sc->pmem = vtophys(sc->vmem);
19976195Sbrian	sc->pcibus = 1;
20076195Sbrian	sc->win_size = 0x200000;
20176195Sbrian	sc->win_bits = 21;
20276195Sbrian	sc->csigs = &digi_normal_signals;
20376195Sbrian	sc->status = DIGI_STATUS_NOTINIT;
20476195Sbrian	callout_handle_init(&sc->callout);
20576195Sbrian	callout_handle_init(&sc->inttest);
20676195Sbrian	sc->setwin = digi_pci_setwin;
20776195Sbrian	sc->hidewin = digi_pci_hidewin;
20876195Sbrian	sc->towin = digi_pci_towin;
20976195Sbrian
21076195Sbrian	PCIPORT = FEPRST;
21176195Sbrian
21276195Sbrian	return (digi_attach(sc));
21376195Sbrian}
21476195Sbrian
21576195Sbrianstatic device_method_t digi_pci_methods[] = {
21676195Sbrian	/* Device interface */
21776195Sbrian	DEVMETHOD(device_probe, digi_pci_probe),
21876195Sbrian	DEVMETHOD(device_attach, digi_pci_attach),
21976195Sbrian	DEVMETHOD(device_detach, digi_detach),
22076195Sbrian	DEVMETHOD(device_shutdown, digi_shutdown),
22176195Sbrian	{0, 0}
22276195Sbrian};
22376195Sbrian
22476195Sbrianstatic driver_t digi_pci_drv = {
22576195Sbrian	"digi",
22676195Sbrian	digi_pci_methods,
22776195Sbrian	sizeof(struct digi_softc),
22876195Sbrian};
22991445SpeterDRIVER_MODULE(digi, pci, digi_pci_drv, digi_devclass, 0, 0);
230