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: stable/11/sys/dev/pdq/if_fpa.c 331882 2018-04-02 16:11:49Z brooks $");
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>
49257176Sglebius#include <net/if_var.h>
5093383Smdodd#include <net/if_media.h>
5193383Smdodd#include <net/fddi.h>
5221826Sjoerg
5393383Smdodd#include <dev/pci/pcivar.h>
5493383Smdodd#include <dev/pci/pcireg.h>
5593383Smdodd
5693383Smdodd#include <dev/pdq/pdq_freebsd.h>
5793383Smdodd#include <dev/pdq/pdqreg.h>
5893383Smdodd
5921826Sjoerg#define	DEC_VENDORID		0x1011
6021826Sjoerg#define	DEFPA_CHIPID		0x000F
6121826Sjoerg
6221826Sjoerg#define	DEFPA_LATENCY	0x88
6321826Sjoerg
6421826Sjoerg#define	PCI_CFLT	0x0C	/* Configuration Latency */
6521826Sjoerg#define	PCI_CBMA	0x10	/* Configuration Base Memory Address */
6621826Sjoerg#define	PCI_CBIO	0x14	/* Configuration Base I/O Address */
6721826Sjoerg
6893383Smdoddstatic int	pdq_pci_probe		(device_t);
6993383Smdoddstatic int	pdq_pci_attach		(device_t);
7093383Smdoddstatic int	pdq_pci_detach		(device_t);
71194023Savgstatic int	pdq_pci_shutdown	(device_t);
7293383Smdoddstatic void	pdq_pci_ifintr		(void *);
7393383Smdodd
7470594Speterstatic void
7570594Speterpdq_pci_ifintr(void *arg)
7621826Sjoerg{
7770594Speter    pdq_softc_t *sc;
7821826Sjoerg
79199542Sjhb    sc = arg;
8093383Smdodd
8193383Smdodd    PDQ_LOCK(sc);
8221826Sjoerg    (void) pdq_interrupt(sc->sc_pdq);
8393383Smdodd    PDQ_UNLOCK(sc);
8493383Smdodd
8593383Smdodd    return;
8621826Sjoerg}
8721826Sjoerg
8821826Sjoerg/*
8970594Speter * This is the PCI configuration support.
9021826Sjoerg */
9170594Speterstatic int
9270594Speterpdq_pci_probe(device_t dev)
9321826Sjoerg{
9470594Speter    if (pci_get_vendor(dev) == DEC_VENDORID &&
9570594Speter	    pci_get_device(dev) == DEFPA_CHIPID) {
9670594Speter	device_set_desc(dev, "Digital DEFPA PCI FDDI Controller");
97143158Simp	return (BUS_PROBE_DEFAULT);
9821826Sjoerg    }
9993383Smdodd
10093383Smdodd    return (ENXIO);
10121826Sjoerg}
10221826Sjoerg
10321826Sjoergstatic int
10470594Speterpdq_pci_attach(device_t dev)
10521826Sjoerg{
10670594Speter    pdq_softc_t *sc;
10793383Smdodd    u_int32_t command;
10893383Smdodd    int error;
10921826Sjoerg
11070594Speter    sc = device_get_softc(dev);
11121826Sjoerg
11293383Smdodd    sc->dev = dev;
11393383Smdodd
11493383Smdodd    /*
11593383Smdodd     * Map control/status registers.
11693383Smdodd     */
11793383Smdodd    pci_enable_busmaster(dev);
11893383Smdodd
11993383Smdodd    command = pci_read_config(dev, PCIR_LATTIMER, 1);
12093383Smdodd    if (command < DEFPA_LATENCY) {
12193383Smdodd	command = DEFPA_LATENCY;
12293383Smdodd	pci_write_config(dev, PCIR_LATTIMER, command, 1);
12393383Smdodd    }
12493383Smdodd
12593383Smdodd    sc->mem_rid = PCI_CBMA;
12693383Smdodd    sc->mem_type = SYS_RES_MEMORY;
127127135Snjl    sc->mem = bus_alloc_resource_any(dev, sc->mem_type, &sc->mem_rid,
128127135Snjl				     RF_ACTIVE);
12993383Smdodd    if (!sc->mem) {
13093383Smdodd	device_printf(dev, "Unable to allocate I/O space resource.\n");
13193383Smdodd	error = ENXIO;
13270594Speter	goto bad;
13393383Smdodd    }
13493383Smdodd    sc->mem_bsh = rman_get_bushandle(sc->mem);
13593383Smdodd    sc->mem_bst = rman_get_bustag(sc->mem);
13693383Smdodd
13793383Smdodd    sc->irq_rid = 0;
138127135Snjl    sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
139127135Snjl				     RF_SHAREABLE | RF_ACTIVE);
14093383Smdodd    if (!sc->irq) {
14193383Smdodd	device_printf(dev, "Unable to allocate interrupt resource.\n");
14293383Smdodd	error = ENXIO;
14370594Speter	goto bad;
14493383Smdodd    }
14593383Smdodd
146199542Sjhb    error = pdq_ifattach(sc, sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, PDQ_DEFPA);
147199542Sjhb    if (error)
14870594Speter	goto bad;
149199542Sjhb
150199542Sjhb    error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, NULL,
151199542Sjhb			   pdq_pci_ifintr, sc, &sc->irq_ih);
15293383Smdodd    if (error) {
15393383Smdodd	device_printf(dev, "Failed to setup interrupt handler.\n");
154199542Sjhb	pdq_ifdetach(sc);
155199542Sjhb	return (error);
15693383Smdodd    }
15793383Smdodd
15893383Smdodd
159331882Sbrooks    gone_in_dev(dev, 12, "fpa(4) driver");
16093383Smdodd    return (0);
16170594Speterbad:
16293383Smdodd    pdq_free(dev);
16393383Smdodd    return (error);
16421826Sjoerg}
16521826Sjoerg
16693383Smdoddstatic int
16793383Smdoddpdq_pci_detach (dev)
16893383Smdodd    device_t	dev;
16993383Smdodd{
17093383Smdodd    pdq_softc_t *sc;
17193383Smdodd
17293383Smdodd    sc = device_get_softc(dev);
17393383Smdodd    pdq_ifdetach(sc);
17493383Smdodd
17593383Smdodd    return (0);
17693383Smdodd}
17793383Smdodd
178194023Savgstatic int
17970594Speterpdq_pci_shutdown(device_t dev)
18021826Sjoerg{
18170594Speter    pdq_softc_t *sc;
18221826Sjoerg
18370594Speter    sc = device_get_softc(dev);
184199542Sjhb    PDQ_LOCK(sc);
18570594Speter    pdq_hwreset(sc->sc_pdq);
186199542Sjhb    PDQ_UNLOCK(sc);
18793383Smdodd
188194023Savg    return (0);
18921826Sjoerg}
19021826Sjoerg
19170594Speterstatic device_method_t pdq_pci_methods[] = {
19270594Speter    /* Device interface */
19370594Speter    DEVMETHOD(device_probe,	pdq_pci_probe),
19470594Speter    DEVMETHOD(device_attach,	pdq_pci_attach),
19593383Smdodd    DEVMETHOD(device_detach,	pdq_pci_detach),
19670594Speter    DEVMETHOD(device_shutdown,	pdq_pci_shutdown),
19793383Smdodd
19870594Speter    { 0, 0 }
19921826Sjoerg};
20093383Smdodd
20170594Speterstatic driver_t pdq_pci_driver = {
20270594Speter    "fpa",
20370594Speter    pdq_pci_methods,
20470594Speter    sizeof(pdq_softc_t),
20521826Sjoerg};
20693383Smdodd
207113506SmdoddDRIVER_MODULE(fpa, pci, pdq_pci_driver, pdq_devclass, 0, 0);
208113506SmdoddMODULE_DEPEND(fpa, pci, 1, 1, 1);
209113506SmdoddMODULE_DEPEND(fpa, fddi, 1, 1, 1);
210