if_fpa.c revision 119418
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: head/sys/dev/pdq/if_fpa.c 119418 2003-08-24 17:55:58Z obrien $");
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
4493383Smdodd#include <machine/bus_memio.h>
4593383Smdodd#include <machine/bus_pio.h>
4670594Speter#include <machine/bus.h>
4770594Speter#include <machine/resource.h>
4893383Smdodd#include <sys/rman.h>
4921826Sjoerg
5093383Smdodd#include <net/if.h>
5193383Smdodd#include <net/if_arp.h>
5293383Smdodd#include <net/if_media.h>
5393383Smdodd#include <net/fddi.h>
5421826Sjoerg
5593383Smdodd#include <dev/pci/pcivar.h>
5693383Smdodd#include <dev/pci/pcireg.h>
5793383Smdodd
5893383Smdodd#include <dev/pdq/pdq_freebsd.h>
5993383Smdodd#include <dev/pdq/pdqreg.h>
6093383Smdodd
6121826Sjoerg#define	DEC_VENDORID		0x1011
6221826Sjoerg#define	DEFPA_CHIPID		0x000F
6321826Sjoerg
6421826Sjoerg#define	DEFPA_LATENCY	0x88
6521826Sjoerg
6621826Sjoerg#define	PCI_CFLT	0x0C	/* Configuration Latency */
6721826Sjoerg#define	PCI_CBMA	0x10	/* Configuration Base Memory Address */
6821826Sjoerg#define	PCI_CBIO	0x14	/* Configuration Base I/O Address */
6921826Sjoerg
7093383Smdoddstatic int	pdq_pci_probe		(device_t);
7193383Smdoddstatic int	pdq_pci_attach		(device_t);
7293383Smdoddstatic int	pdq_pci_detach		(device_t);
7393383Smdoddstatic void	pdq_pci_shutdown	(device_t);
7493383Smdoddstatic void	pdq_pci_ifintr		(void *);
7593383Smdodd
7670594Speterstatic void
7770594Speterpdq_pci_ifintr(void *arg)
7821826Sjoerg{
7993383Smdodd    device_t dev;
8070594Speter    pdq_softc_t *sc;
8121826Sjoerg
8293383Smdodd    dev = (device_t)arg;
8393383Smdodd    sc = device_get_softc(dev);
8493383Smdodd
8593383Smdodd    PDQ_LOCK(sc);
8621826Sjoerg    (void) pdq_interrupt(sc->sc_pdq);
8793383Smdodd    PDQ_UNLOCK(sc);
8893383Smdodd
8993383Smdodd    return;
9021826Sjoerg}
9121826Sjoerg
9221826Sjoerg/*
9370594Speter * This is the PCI configuration support.
9421826Sjoerg */
9570594Speterstatic int
9670594Speterpdq_pci_probe(device_t dev)
9721826Sjoerg{
9870594Speter    if (pci_get_vendor(dev) == DEC_VENDORID &&
9970594Speter	    pci_get_device(dev) == DEFPA_CHIPID) {
10070594Speter	device_set_desc(dev, "Digital DEFPA PCI FDDI Controller");
10193383Smdodd	return (0);
10221826Sjoerg    }
10393383Smdodd
10493383Smdodd    return (ENXIO);
10521826Sjoerg}
10621826Sjoerg
10721826Sjoergstatic int
10870594Speterpdq_pci_attach(device_t dev)
10921826Sjoerg{
11070594Speter    pdq_softc_t *sc;
11193383Smdodd    struct ifnet *ifp;
11293383Smdodd    u_int32_t command;
11393383Smdodd    int error;
11421826Sjoerg
11570594Speter    sc = device_get_softc(dev);
11693383Smdodd    ifp = &sc->arpcom.ac_if;
11721826Sjoerg
11893383Smdodd    sc->dev = dev;
11993383Smdodd
12093383Smdodd    /*
12193383Smdodd     * Map control/status registers.
12293383Smdodd     */
12393383Smdodd    pci_enable_busmaster(dev);
12493383Smdodd
12593383Smdodd    command = pci_read_config(dev, PCIR_LATTIMER, 1);
12693383Smdodd    if (command < DEFPA_LATENCY) {
12793383Smdodd	command = DEFPA_LATENCY;
12893383Smdodd	pci_write_config(dev, PCIR_LATTIMER, command, 1);
12993383Smdodd    }
13093383Smdodd
13193383Smdodd    sc->mem_rid = PCI_CBMA;
13293383Smdodd    sc->mem_type = SYS_RES_MEMORY;
13393383Smdodd    sc->mem = bus_alloc_resource(dev, sc->mem_type, &sc->mem_rid,
13493383Smdodd				 0, ~0, 1, RF_ACTIVE);
13593383Smdodd    if (!sc->mem) {
13693383Smdodd	device_printf(dev, "Unable to allocate I/O space resource.\n");
13793383Smdodd	error = ENXIO;
13870594Speter	goto bad;
13993383Smdodd    }
14093383Smdodd    sc->mem_bsh = rman_get_bushandle(sc->mem);
14193383Smdodd    sc->mem_bst = rman_get_bustag(sc->mem);
14293383Smdodd
14393383Smdodd    sc->irq_rid = 0;
14493383Smdodd    sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
14593383Smdodd				 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
14693383Smdodd    if (!sc->irq) {
14793383Smdodd	device_printf(dev, "Unable to allocate interrupt resource.\n");
14893383Smdodd	error = ENXIO;
14970594Speter	goto bad;
15093383Smdodd    }
15193383Smdodd
15293383Smdodd    ifp->if_name = "fpa";
15393383Smdodd    ifp->if_unit = device_get_unit(dev);
15493383Smdodd
15593383Smdodd    sc->sc_pdq = pdq_initialize(sc->mem_bst, sc->mem_bsh,
15693383Smdodd				ifp->if_name, ifp->if_unit,
15793383Smdodd				(void *)sc, PDQ_DEFPA);
15893383Smdodd    if (sc->sc_pdq == NULL) {
15993383Smdodd	device_printf(dev, "Initialization failed.\n");
16093383Smdodd	error = ENXIO;
16170594Speter	goto bad;
16293383Smdodd    }
16321826Sjoerg
16493383Smdodd    error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
16593383Smdodd			   pdq_pci_ifintr, dev, &sc->irq_ih);
16693383Smdodd    if (error) {
16793383Smdodd	device_printf(dev, "Failed to setup interrupt handler.\n");
16893383Smdodd	error = ENXIO;
16993383Smdodd	goto bad;
17093383Smdodd    }
17193383Smdodd
17293383Smdodd    bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes,
17393383Smdodd	  (caddr_t) sc->arpcom.ac_enaddr, FDDI_ADDR_LEN);
17493383Smdodd    pdq_ifattach(sc);
17593383Smdodd
17693383Smdodd    return (0);
17770594Speterbad:
17893383Smdodd    pdq_free(dev);
17993383Smdodd    return (error);
18021826Sjoerg}
18121826Sjoerg
18293383Smdoddstatic int
18393383Smdoddpdq_pci_detach (dev)
18493383Smdodd    device_t	dev;
18593383Smdodd{
18693383Smdodd    pdq_softc_t *sc;
18793383Smdodd
18893383Smdodd    sc = device_get_softc(dev);
18993383Smdodd    pdq_ifdetach(sc);
19093383Smdodd
19193383Smdodd    return (0);
19293383Smdodd}
19393383Smdodd
19421826Sjoergstatic void
19570594Speterpdq_pci_shutdown(device_t dev)
19621826Sjoerg{
19770594Speter    pdq_softc_t *sc;
19821826Sjoerg
19970594Speter    sc = device_get_softc(dev);
20070594Speter    pdq_hwreset(sc->sc_pdq);
20193383Smdodd
20293383Smdodd    return;
20321826Sjoerg}
20421826Sjoerg
20570594Speterstatic device_method_t pdq_pci_methods[] = {
20670594Speter    /* Device interface */
20770594Speter    DEVMETHOD(device_probe,	pdq_pci_probe),
20870594Speter    DEVMETHOD(device_attach,	pdq_pci_attach),
20993383Smdodd    DEVMETHOD(device_detach,	pdq_pci_detach),
21070594Speter    DEVMETHOD(device_shutdown,	pdq_pci_shutdown),
21193383Smdodd
21270594Speter    { 0, 0 }
21321826Sjoerg};
21493383Smdodd
21570594Speterstatic driver_t pdq_pci_driver = {
21670594Speter    "fpa",
21770594Speter    pdq_pci_methods,
21870594Speter    sizeof(pdq_softc_t),
21921826Sjoerg};
22093383Smdodd
221113506SmdoddDRIVER_MODULE(fpa, pci, pdq_pci_driver, pdq_devclass, 0, 0);
222113506SmdoddMODULE_DEPEND(fpa, pci, 1, 1, 1);
223113506SmdoddMODULE_DEPEND(fpa, fddi, 1, 1, 1);
224