digi_pci.c revision 91445
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 * $FreeBSD: head/sys/dev/digi/digi_pci.c 91445 2002-02-27 23:47:45Z peter $
3076195Sbrian */
3176195Sbrian
3276195Sbrian#include <sys/param.h>
3376195Sbrian
3476195Sbrian#include <sys/systm.h>
3576195Sbrian#include <sys/kernel.h>
3676195Sbrian#include <sys/tty.h>
3776195Sbrian#include <sys/bus.h>
3876195Sbrian#include <machine/bus.h>
3976195Sbrian#include <sys/rman.h>
4076195Sbrian#include <machine/resource.h>
4176195Sbrian#include <vm/vm.h>
4276195Sbrian#include <vm/pmap.h>
4376195Sbrian#include <pci/pcivar.h>
4476195Sbrian
4576848Sbrian#include <sys/digiio.h>
4676853Sbrian#include <dev/digi/digireg.h>
4776853Sbrian#include <dev/digi/digi.h>
4876853Sbrian#include <dev/digi/digi_pci.h>
4976195Sbrian
5076195Sbrianstatic u_char *
5176195Sbriandigi_pci_setwin(struct digi_softc *sc, unsigned int addr)
5276195Sbrian{
5376195Sbrian	return (sc->vmem + addr);
5476195Sbrian}
5576195Sbrian
5676195Sbrianstatic void
5776195Sbriandigi_pci_hidewin(struct digi_softc *sc)
5876195Sbrian{
5976195Sbrian	return;
6076195Sbrian}
6176195Sbrian
6276195Sbrianstatic void
6376195Sbriandigi_pci_towin(struct digi_softc *sc, int win)
6476195Sbrian{
6576195Sbrian	return;
6676195Sbrian}
6776195Sbrian
6876195Sbrianstatic int
6976195Sbriandigi_pci_probe(device_t dev)
7076195Sbrian{
7176195Sbrian	unsigned int device_id = pci_get_devid(dev);
7276195Sbrian
7376195Sbrian	if (device_get_unit(dev) >= 16) {
7476195Sbrian		/* Don't overflow our control mask */
7576195Sbrian		device_printf(dev, "At most 16 digiboards may be used\n");
7676195Sbrian		return (ENXIO);
7776195Sbrian	}
7876195Sbrian
7976195Sbrian	if ((device_id & 0xffff) != PCI_VENDOR_DIGI)
8076195Sbrian		return (ENXIO);
8176195Sbrian
8276195Sbrian	switch (device_id >> 16) {
8376195Sbrian	case PCI_DEVICE_EPC:
8476195Sbrian	case PCI_DEVICE_XEM:
8576195Sbrian	case PCI_DEVICE_XR:
8676195Sbrian	case PCI_DEVICE_CX:
8776195Sbrian	case PCI_DEVICE_XRJ:
8876195Sbrian	case PCI_DEVICE_EPCJ:
8976195Sbrian	case PCI_DEVICE_920_4:
9076195Sbrian	case PCI_DEVICE_920_8:
9176195Sbrian	case PCI_DEVICE_920_2:
9276358Sbrian		return (0);
9376195Sbrian	}
9476195Sbrian
9576358Sbrian	return (ENXIO);
9676195Sbrian}
9776195Sbrian
9876195Sbrianstatic int
9976195Sbriandigi_pci_attach(device_t dev)
10076195Sbrian{
10176195Sbrian	struct digi_softc *sc;
10276195Sbrian	u_int32_t device_id;
10376195Sbrian#ifdef DIGI_INTERRUPT
10476195Sbrian	int retVal = 0;
10576195Sbrian#endif
10676195Sbrian
10776195Sbrian	sc = device_get_softc(dev);
10876195Sbrian	KASSERT(sc, ("digi%d: softc not allocated in digi_pci_attach\n",
10976195Sbrian	    device_get_unit(dev)));
11076195Sbrian
11176195Sbrian	bzero(sc, sizeof(*sc));
11276195Sbrian	sc->dev = dev;
11376195Sbrian	sc->res.unit = device_get_unit(dev);
11476195Sbrian
11576195Sbrian	device_id = pci_get_devid(dev);
11676195Sbrian	switch (device_id >> 16) {
11776195Sbrian	case PCI_DEVICE_EPC:
11876195Sbrian		sc->name = "Digiboard PCI EPC/X ASIC";
11976195Sbrian		sc->res.mrid = 0x10;
12076195Sbrian		sc->model = PCIEPCX;
12176195Sbrian		sc->module = "EPCX_PCI";
12276195Sbrian		break;
12376195Sbrian	case PCI_DEVICE_XEM:
12476195Sbrian		sc->name = "Digiboard PCI PC/Xem ASIC";
12576195Sbrian		sc->res.mrid = 0x10;
12676195Sbrian		sc->model = PCXEM;
12776195Sbrian		sc->module = "Xem";
12876195Sbrian		break;
12976195Sbrian	case PCI_DEVICE_XR:
13076195Sbrian		sc->name = "Digiboard PCI PC/Xr ASIC";
13176195Sbrian		sc->res.mrid = 0x10;
13276195Sbrian		sc->model = PCIXR;
13376195Sbrian		sc->module = "Xr";
13476195Sbrian		break;
13576195Sbrian	case PCI_DEVICE_CX:
13676195Sbrian		sc->name = "Digiboard PCI C/X ASIC";
13776195Sbrian		sc->res.mrid = 0x10;
13876195Sbrian		sc->model = PCCX;
13976195Sbrian		sc->module = "CX_PCI";
14076195Sbrian		break;
14176195Sbrian	case PCI_DEVICE_XRJ:
14276195Sbrian		sc->name = "Digiboard PCI PC/Xr PLX";
14376195Sbrian		sc->res.mrid = 0x18;
14476195Sbrian		sc->model = PCIXR;
14576195Sbrian		sc->module = "Xr";
14676195Sbrian		break;
14776195Sbrian	case PCI_DEVICE_EPCJ:
14876195Sbrian		sc->name = "Digiboard PCI EPC/X PLX";
14976195Sbrian		sc->res.mrid = 0x18;
15076195Sbrian		sc->model = PCIEPCX;
15176195Sbrian		sc->module = "EPCX_PCI";
15276195Sbrian		break;
15376195Sbrian	case PCI_DEVICE_920_4:			/* Digi PCI4r 920 */
15476195Sbrian		sc->name = "Digiboard PCI4r 920";
15576195Sbrian		sc->res.mrid = 0x10;
15676195Sbrian		sc->model = PCIXR;
15776195Sbrian		sc->module = "Xr";
15876195Sbrian		break;
15976195Sbrian	case PCI_DEVICE_920_8:			/* Digi PCI8r 920 */
16076195Sbrian		sc->name = "Digiboard PCI8r 920";
16176195Sbrian		sc->res.mrid = 0x10;
16276195Sbrian		sc->model = PCIXR;
16376195Sbrian		sc->module = "Xr";
16476195Sbrian		break;
16576195Sbrian	case PCI_DEVICE_920_2:			/* Digi PCI2r 920 */
16676195Sbrian		sc->name = "Digiboard PCI2r 920";
16776195Sbrian		sc->res.mrid = 0x10;
16876195Sbrian		sc->model = PCIXR;
16976195Sbrian		sc->module = "Xr";
17076195Sbrian		break;
17176195Sbrian	default:
17276195Sbrian		device_printf(dev, "Unknown device id = %08x\n", device_id);
17376195Sbrian		return (ENXIO);
17476195Sbrian	}
17576195Sbrian
17676195Sbrian	pci_write_config(dev, 0x40, 0, 4);
17776195Sbrian	pci_write_config(dev, 0x46, 0, 4);
17876195Sbrian
17976195Sbrian	sc->res.mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->res.mrid,
18076195Sbrian	    0, ~0, 1, RF_ACTIVE);
18176195Sbrian
18276195Sbrian#ifdef DIGI_INTERRUPT
18376195Sbrian	sc->res.irqrid = 0;
18476195Sbrian	sc->res.irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->res.irqrid,
18576195Sbrian	    0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
18676195Sbrian	if (sc->res.irq == NULL) {
18776195Sbrian		device_printf(dev, "couldn't map interrupt\n");
18876358Sbrian		return (ENXIO);
18976195Sbrian	}
19076195Sbrian	retVal = bus_setup_intr(dev, sc->res.irq, INTR_TYPE_TTY,
19176195Sbrian	    digiintr, sc, &sc->res.irqHandler);
19276195Sbrian#else
19376195Sbrian	DLOG(DIGIDB_IRQ, (sc->dev, "Interrupt support compiled out\n"));
19476195Sbrian#endif
19576195Sbrian
19676195Sbrian	sc->vmem = rman_get_virtual(sc->res.mem);
19776195Sbrian	sc->pmem = vtophys(sc->vmem);
19876195Sbrian	sc->pcibus = 1;
19976195Sbrian	sc->win_size = 0x200000;
20076195Sbrian	sc->win_bits = 21;
20176195Sbrian	sc->csigs = &digi_normal_signals;
20276195Sbrian	sc->status = DIGI_STATUS_NOTINIT;
20376195Sbrian	callout_handle_init(&sc->callout);
20476195Sbrian	callout_handle_init(&sc->inttest);
20576195Sbrian	sc->setwin = digi_pci_setwin;
20676195Sbrian	sc->hidewin = digi_pci_hidewin;
20776195Sbrian	sc->towin = digi_pci_towin;
20876195Sbrian
20976195Sbrian	PCIPORT = FEPRST;
21076195Sbrian
21176195Sbrian	return (digi_attach(sc));
21276195Sbrian}
21376195Sbrian
21476195Sbrianstatic device_method_t digi_pci_methods[] = {
21576195Sbrian	/* Device interface */
21676195Sbrian	DEVMETHOD(device_probe, digi_pci_probe),
21776195Sbrian	DEVMETHOD(device_attach, digi_pci_attach),
21876195Sbrian	DEVMETHOD(device_detach, digi_detach),
21976195Sbrian	DEVMETHOD(device_shutdown, digi_shutdown),
22076195Sbrian	{0, 0}
22176195Sbrian};
22276195Sbrian
22376195Sbrianstatic driver_t digi_pci_drv = {
22476195Sbrian	"digi",
22576195Sbrian	digi_pci_methods,
22676195Sbrian	sizeof(struct digi_softc),
22776195Sbrian};
22891445SpeterDRIVER_MODULE(digi, pci, digi_pci_drv, digi_devclass, 0, 0);
229