121826Sjoerg/*-
221826Sjoerg * Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com>
321826Sjoerg * All rights reserved.
421826Sjoerg *
521826Sjoerg * Redistribution and use in source and binary forms, with or without
621826Sjoerg * modification, are permitted provided that the following conditions
721826Sjoerg * are met:
821826Sjoerg * 1. Redistributions of source code must retain the above copyright
921826Sjoerg *    notice, this list of conditions and the following disclaimer.
1021826Sjoerg * 2. The name of the author may not be used to endorse or promote products
1197748Sschweikh *    derived from this software without specific prior written permission
1221826Sjoerg *
1321826Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1421826Sjoerg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1521826Sjoerg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1621826Sjoerg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1721826Sjoerg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1821826Sjoerg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1921826Sjoerg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2021826Sjoerg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2121826Sjoerg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2221826Sjoerg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2321826Sjoerg *
2421826Sjoerg *
2521826Sjoerg */
2621826Sjoerg
27119418Sobrien#include <sys/cdefs.h>
28119418Sobrien__FBSDID("$FreeBSD$");
29119418Sobrien
3021826Sjoerg/*
3121826Sjoerg * DEC PDQ FDDI Controller; code for BSD derived operating systems
3221826Sjoerg *
3321826Sjoerg *   This module supports the DEC DEFPA PCI FDDI Controller
3421826Sjoerg */
3521826Sjoerg
3621826Sjoerg#include <sys/param.h>
3793383Smdodd#include <sys/systm.h>
3821826Sjoerg#include <sys/kernel.h>
3921826Sjoerg#include <sys/socket.h>
4021826Sjoerg
4193383Smdodd#include <sys/module.h>
4293383Smdodd#include <sys/bus.h>
4321826Sjoerg
4470594Speter#include <machine/bus.h>
4570594Speter#include <machine/resource.h>
4693383Smdodd#include <sys/rman.h>
4721826Sjoerg
4893383Smdodd#include <net/if.h>
4993383Smdodd#include <net/if_media.h>
5093383Smdodd#include <net/fddi.h>
5121826Sjoerg
5293383Smdodd#include <dev/pci/pcivar.h>
5393383Smdodd#include <dev/pci/pcireg.h>
5493383Smdodd
5593383Smdodd#include <dev/pdq/pdq_freebsd.h>
5693383Smdodd#include <dev/pdq/pdqreg.h>
5793383Smdodd
5821826Sjoerg#define	DEC_VENDORID		0x1011
5921826Sjoerg#define	DEFPA_CHIPID		0x000F
6021826Sjoerg
6121826Sjoerg#define	DEFPA_LATENCY	0x88
6221826Sjoerg
6321826Sjoerg#define	PCI_CFLT	0x0C	/* Configuration Latency */
6421826Sjoerg#define	PCI_CBMA	0x10	/* Configuration Base Memory Address */
6521826Sjoerg#define	PCI_CBIO	0x14	/* Configuration Base I/O Address */
6621826Sjoerg
6793383Smdoddstatic int	pdq_pci_probe		(device_t);
6893383Smdoddstatic int	pdq_pci_attach		(device_t);
6993383Smdoddstatic int	pdq_pci_detach		(device_t);
70194023Savgstatic int	pdq_pci_shutdown	(device_t);
7193383Smdoddstatic void	pdq_pci_ifintr		(void *);
7293383Smdodd
7370594Speterstatic void
7470594Speterpdq_pci_ifintr(void *arg)
7521826Sjoerg{
7670594Speter    pdq_softc_t *sc;
7721826Sjoerg
78199542Sjhb    sc = arg;
7993383Smdodd
8093383Smdodd    PDQ_LOCK(sc);
8121826Sjoerg    (void) pdq_interrupt(sc->sc_pdq);
8293383Smdodd    PDQ_UNLOCK(sc);
8393383Smdodd
8493383Smdodd    return;
8521826Sjoerg}
8621826Sjoerg
8721826Sjoerg/*
8870594Speter * This is the PCI configuration support.
8921826Sjoerg */
9070594Speterstatic int
9170594Speterpdq_pci_probe(device_t dev)
9221826Sjoerg{
9370594Speter    if (pci_get_vendor(dev) == DEC_VENDORID &&
9470594Speter	    pci_get_device(dev) == DEFPA_CHIPID) {
9570594Speter	device_set_desc(dev, "Digital DEFPA PCI FDDI Controller");
96143158Simp	return (BUS_PROBE_DEFAULT);
9721826Sjoerg    }
9893383Smdodd
9993383Smdodd    return (ENXIO);
10021826Sjoerg}
10121826Sjoerg
10221826Sjoergstatic int
10370594Speterpdq_pci_attach(device_t dev)
10421826Sjoerg{
10570594Speter    pdq_softc_t *sc;
10693383Smdodd    u_int32_t command;
10793383Smdodd    int error;
10821826Sjoerg
10970594Speter    sc = device_get_softc(dev);
11021826Sjoerg
11193383Smdodd    sc->dev = dev;
11293383Smdodd
11393383Smdodd    /*
11493383Smdodd     * Map control/status registers.
11593383Smdodd     */
11693383Smdodd    pci_enable_busmaster(dev);
11793383Smdodd
11893383Smdodd    command = pci_read_config(dev, PCIR_LATTIMER, 1);
11993383Smdodd    if (command < DEFPA_LATENCY) {
12093383Smdodd	command = DEFPA_LATENCY;
12193383Smdodd	pci_write_config(dev, PCIR_LATTIMER, command, 1);
12293383Smdodd    }
12393383Smdodd
12493383Smdodd    sc->mem_rid = PCI_CBMA;
12593383Smdodd    sc->mem_type = SYS_RES_MEMORY;
126127135Snjl    sc->mem = bus_alloc_resource_any(dev, sc->mem_type, &sc->mem_rid,
127127135Snjl				     RF_ACTIVE);
12893383Smdodd    if (!sc->mem) {
12993383Smdodd	device_printf(dev, "Unable to allocate I/O space resource.\n");
13093383Smdodd	error = ENXIO;
13170594Speter	goto bad;
13293383Smdodd    }
13393383Smdodd    sc->mem_bsh = rman_get_bushandle(sc->mem);
13493383Smdodd    sc->mem_bst = rman_get_bustag(sc->mem);
13593383Smdodd
13693383Smdodd    sc->irq_rid = 0;
137127135Snjl    sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
138127135Snjl				     RF_SHAREABLE | RF_ACTIVE);
13993383Smdodd    if (!sc->irq) {
14093383Smdodd	device_printf(dev, "Unable to allocate interrupt resource.\n");
14193383Smdodd	error = ENXIO;
14270594Speter	goto bad;
14393383Smdodd    }
14493383Smdodd
145199542Sjhb    error = pdq_ifattach(sc, sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, PDQ_DEFPA);
146199542Sjhb    if (error)
14770594Speter	goto bad;
148199542Sjhb
149199542Sjhb    error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, NULL,
150199542Sjhb			   pdq_pci_ifintr, sc, &sc->irq_ih);
15193383Smdodd    if (error) {
15293383Smdodd	device_printf(dev, "Failed to setup interrupt handler.\n");
153199542Sjhb	pdq_ifdetach(sc);
154199542Sjhb	return (error);
15593383Smdodd    }
15693383Smdodd
15793383Smdodd
15893383Smdodd    return (0);
15970594Speterbad:
16093383Smdodd    pdq_free(dev);
16193383Smdodd    return (error);
16221826Sjoerg}
16321826Sjoerg
16493383Smdoddstatic int
16593383Smdoddpdq_pci_detach (dev)
16693383Smdodd    device_t	dev;
16793383Smdodd{
16893383Smdodd    pdq_softc_t *sc;
16993383Smdodd
17093383Smdodd    sc = device_get_softc(dev);
17193383Smdodd    pdq_ifdetach(sc);
17293383Smdodd
17393383Smdodd    return (0);
17493383Smdodd}
17593383Smdodd
176194023Savgstatic int
17770594Speterpdq_pci_shutdown(device_t dev)
17821826Sjoerg{
17970594Speter    pdq_softc_t *sc;
18021826Sjoerg
18170594Speter    sc = device_get_softc(dev);
182199542Sjhb    PDQ_LOCK(sc);
18370594Speter    pdq_hwreset(sc->sc_pdq);
184199542Sjhb    PDQ_UNLOCK(sc);
18593383Smdodd
186194023Savg    return (0);
18721826Sjoerg}
18821826Sjoerg
18970594Speterstatic device_method_t pdq_pci_methods[] = {
19070594Speter    /* Device interface */
19170594Speter    DEVMETHOD(device_probe,	pdq_pci_probe),
19270594Speter    DEVMETHOD(device_attach,	pdq_pci_attach),
19393383Smdodd    DEVMETHOD(device_detach,	pdq_pci_detach),
19470594Speter    DEVMETHOD(device_shutdown,	pdq_pci_shutdown),
19593383Smdodd
19670594Speter    { 0, 0 }
19721826Sjoerg};
19893383Smdodd
19970594Speterstatic driver_t pdq_pci_driver = {
20070594Speter    "fpa",
20170594Speter    pdq_pci_methods,
20270594Speter    sizeof(pdq_softc_t),
20321826Sjoerg};
20493383Smdodd
205113506SmdoddDRIVER_MODULE(fpa, pci, pdq_pci_driver, pdq_devclass, 0, 0);
206113506SmdoddMODULE_DEPEND(fpa, pci, 1, 1, 1);
207113506SmdoddMODULE_DEPEND(fpa, fddi, 1, 1, 1);
208