if_fpa.c revision 113506
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 *
2450477Speter * $FreeBSD: head/sys/dev/pdq/if_fpa.c 113506 2003-04-15 06:37:30Z mdodd $
2521826Sjoerg *
2621826Sjoerg */
2721826Sjoerg
2821826Sjoerg/*
2921826Sjoerg * DEC PDQ FDDI Controller; code for BSD derived operating systems
3021826Sjoerg *
3121826Sjoerg *   This module supports the DEC DEFPA PCI FDDI Controller
3221826Sjoerg */
3321826Sjoerg
3421826Sjoerg#include <sys/param.h>
3593383Smdodd#include <sys/systm.h>
3621826Sjoerg#include <sys/kernel.h>
3721826Sjoerg#include <sys/socket.h>
3821826Sjoerg
3993383Smdodd#include <sys/module.h>
4093383Smdodd#include <sys/bus.h>
4121826Sjoerg
4293383Smdodd#include <machine/bus_memio.h>
4393383Smdodd#include <machine/bus_pio.h>
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_arp.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);
7193383Smdoddstatic void	pdq_pci_shutdown	(device_t);
7293383Smdoddstatic void	pdq_pci_ifintr		(void *);
7393383Smdodd
7470594Speterstatic void
7570594Speterpdq_pci_ifintr(void *arg)
7621826Sjoerg{
7793383Smdodd    device_t dev;
7870594Speter    pdq_softc_t *sc;
7921826Sjoerg
8093383Smdodd    dev = (device_t)arg;
8193383Smdodd    sc = device_get_softc(dev);
8293383Smdodd
8393383Smdodd    PDQ_LOCK(sc);
8421826Sjoerg    (void) pdq_interrupt(sc->sc_pdq);
8593383Smdodd    PDQ_UNLOCK(sc);
8693383Smdodd
8793383Smdodd    return;
8821826Sjoerg}
8921826Sjoerg
9021826Sjoerg/*
9170594Speter * This is the PCI configuration support.
9221826Sjoerg */
9370594Speterstatic int
9470594Speterpdq_pci_probe(device_t dev)
9521826Sjoerg{
9670594Speter    if (pci_get_vendor(dev) == DEC_VENDORID &&
9770594Speter	    pci_get_device(dev) == DEFPA_CHIPID) {
9870594Speter	device_set_desc(dev, "Digital DEFPA PCI FDDI Controller");
9993383Smdodd	return (0);
10021826Sjoerg    }
10193383Smdodd
10293383Smdodd    return (ENXIO);
10321826Sjoerg}
10421826Sjoerg
10521826Sjoergstatic int
10670594Speterpdq_pci_attach(device_t dev)
10721826Sjoerg{
10870594Speter    pdq_softc_t *sc;
10993383Smdodd    struct ifnet *ifp;
11093383Smdodd    u_int32_t command;
11193383Smdodd    int error;
11221826Sjoerg
11370594Speter    sc = device_get_softc(dev);
11493383Smdodd    ifp = &sc->arpcom.ac_if;
11521826Sjoerg
11693383Smdodd    sc->dev = dev;
11793383Smdodd
11893383Smdodd    /*
11993383Smdodd     * Map control/status registers.
12093383Smdodd     */
12193383Smdodd    pci_enable_busmaster(dev);
12293383Smdodd    pci_enable_io(dev, SYS_RES_IOPORT);
12393383Smdodd    pci_enable_io(dev, SYS_RES_MEMORY);
12493383Smdodd    command = pci_read_config(dev, PCIR_COMMAND, 4);
12593383Smdodd
12693383Smdodd    if (!(command & PCIM_CMD_PORTEN)) {
12793383Smdodd	device_printf(dev, "Failed to enable PCI I/O ports.\n");
12893383Smdodd	error = ENXIO;
12993383Smdodd	goto bad;
13021826Sjoerg    }
13121826Sjoerg
13293383Smdodd    if (!(command & PCIM_CMD_MEMEN)) {
13393383Smdodd	device_printf(dev, "Failed to enable PCI memory mapping.\n");
13493383Smdodd	error = ENXIO;
13570594Speter	goto bad;
13693383Smdodd    }
13721826Sjoerg
13893383Smdodd    command = pci_read_config(dev, PCIR_LATTIMER, 1);
13993383Smdodd    if (command < DEFPA_LATENCY) {
14093383Smdodd	command = DEFPA_LATENCY;
14193383Smdodd	pci_write_config(dev, PCIR_LATTIMER, command, 1);
14293383Smdodd    }
14393383Smdodd
14493383Smdodd    sc->mem_rid = PCI_CBMA;
14593383Smdodd    sc->mem_type = SYS_RES_MEMORY;
14693383Smdodd    sc->mem = bus_alloc_resource(dev, sc->mem_type, &sc->mem_rid,
14793383Smdodd				 0, ~0, 1, RF_ACTIVE);
14893383Smdodd    if (!sc->mem) {
14993383Smdodd	device_printf(dev, "Unable to allocate I/O space resource.\n");
15093383Smdodd	error = ENXIO;
15170594Speter	goto bad;
15293383Smdodd    }
15393383Smdodd    sc->mem_bsh = rman_get_bushandle(sc->mem);
15493383Smdodd    sc->mem_bst = rman_get_bustag(sc->mem);
15593383Smdodd
15693383Smdodd    sc->irq_rid = 0;
15793383Smdodd    sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
15893383Smdodd				 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
15993383Smdodd    if (!sc->irq) {
16093383Smdodd	device_printf(dev, "Unable to allocate interrupt resource.\n");
16193383Smdodd	error = ENXIO;
16270594Speter	goto bad;
16393383Smdodd    }
16493383Smdodd
16593383Smdodd    ifp->if_name = "fpa";
16693383Smdodd    ifp->if_unit = device_get_unit(dev);
16793383Smdodd
16893383Smdodd    sc->sc_pdq = pdq_initialize(sc->mem_bst, sc->mem_bsh,
16993383Smdodd				ifp->if_name, ifp->if_unit,
17093383Smdodd				(void *)sc, PDQ_DEFPA);
17193383Smdodd    if (sc->sc_pdq == NULL) {
17293383Smdodd	device_printf(dev, "Initialization failed.\n");
17393383Smdodd	error = ENXIO;
17470594Speter	goto bad;
17593383Smdodd    }
17621826Sjoerg
17793383Smdodd    error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
17893383Smdodd			   pdq_pci_ifintr, dev, &sc->irq_ih);
17993383Smdodd    if (error) {
18093383Smdodd	device_printf(dev, "Failed to setup interrupt handler.\n");
18193383Smdodd	error = ENXIO;
18293383Smdodd	goto bad;
18393383Smdodd    }
18493383Smdodd
18593383Smdodd    bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes,
18693383Smdodd	  (caddr_t) sc->arpcom.ac_enaddr, FDDI_ADDR_LEN);
18793383Smdodd    pdq_ifattach(sc);
18893383Smdodd
18993383Smdodd    return (0);
19070594Speterbad:
19193383Smdodd    pdq_free(dev);
19293383Smdodd    return (error);
19321826Sjoerg}
19421826Sjoerg
19593383Smdoddstatic int
19693383Smdoddpdq_pci_detach (dev)
19793383Smdodd    device_t	dev;
19893383Smdodd{
19993383Smdodd    pdq_softc_t *sc;
20093383Smdodd
20193383Smdodd    sc = device_get_softc(dev);
20293383Smdodd    pdq_ifdetach(sc);
20393383Smdodd
20493383Smdodd    return (0);
20593383Smdodd}
20693383Smdodd
20721826Sjoergstatic void
20870594Speterpdq_pci_shutdown(device_t dev)
20921826Sjoerg{
21070594Speter    pdq_softc_t *sc;
21121826Sjoerg
21270594Speter    sc = device_get_softc(dev);
21370594Speter    pdq_hwreset(sc->sc_pdq);
21493383Smdodd
21593383Smdodd    return;
21621826Sjoerg}
21721826Sjoerg
21870594Speterstatic device_method_t pdq_pci_methods[] = {
21970594Speter    /* Device interface */
22070594Speter    DEVMETHOD(device_probe,	pdq_pci_probe),
22170594Speter    DEVMETHOD(device_attach,	pdq_pci_attach),
22293383Smdodd    DEVMETHOD(device_detach,	pdq_pci_detach),
22370594Speter    DEVMETHOD(device_shutdown,	pdq_pci_shutdown),
22493383Smdodd
22570594Speter    { 0, 0 }
22621826Sjoerg};
22793383Smdodd
22870594Speterstatic driver_t pdq_pci_driver = {
22970594Speter    "fpa",
23070594Speter    pdq_pci_methods,
23170594Speter    sizeof(pdq_softc_t),
23221826Sjoerg};
23393383Smdodd
234113506SmdoddDRIVER_MODULE(fpa, pci, pdq_pci_driver, pdq_devclass, 0, 0);
235113506SmdoddMODULE_DEPEND(fpa, pci, 1, 1, 1);
236113506SmdoddMODULE_DEPEND(fpa, fddi, 1, 1, 1);
237