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