if_hme_pci.c revision 119696
1119418Sobrien/*-
291396Stmm * Copyright (c) 2000 Matthew R. Green
391396Stmm * All rights reserved.
491396Stmm *
591396Stmm * Redistribution and use in source and binary forms, with or without
691396Stmm * modification, are permitted provided that the following conditions
791396Stmm * are met:
891396Stmm * 1. Redistributions of source code must retain the above copyright
991396Stmm *    notice, this list of conditions and the following disclaimer.
1091396Stmm * 2. Redistributions in binary form must reproduce the above copyright
1191396Stmm *    notice, this list of conditions and the following disclaimer in the
1291396Stmm *    documentation and/or other materials provided with the distribution.
1391396Stmm * 3. The name of the author may not be used to endorse or promote products
1491396Stmm *    derived from this software without specific prior written permission.
1591396Stmm *
1691396Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1791396Stmm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1891396Stmm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1991396Stmm * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2091396Stmm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2191396Stmm * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2291396Stmm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2391396Stmm * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2491396Stmm * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2591396Stmm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2691396Stmm * SUCH DAMAGE.
2791396Stmm *
2891396Stmm *	from: NetBSD: if_hme_pci.c,v 1.4 2001/08/27 22:18:49 augustss Exp
2991396Stmm */
3091396Stmm
31119418Sobrien#include <sys/cdefs.h>
32119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/hme/if_hme_pci.c 119696 2003-09-02 20:24:42Z marcel $");
33119418Sobrien
3491396Stmm/*
3591396Stmm * PCI front-end device driver for the HME ethernet device.
3691396Stmm */
3791396Stmm
3891396Stmm#include <sys/param.h>
3991396Stmm#include <sys/systm.h>
4091396Stmm#include <sys/bus.h>
4191396Stmm#include <sys/kernel.h>
4291396Stmm#include <sys/resource.h>
4391396Stmm#include <sys/socket.h>
4491396Stmm
4591396Stmm#include <machine/bus.h>
46119696Smarcel#include <dev/ofw/openfirm.h>
4791396Stmm#include <machine/ofw_machdep.h>
4891396Stmm#include <machine/resource.h>
4991396Stmm
5091396Stmm#include <sys/rman.h>
5191396Stmm
5291396Stmm#include <net/ethernet.h>
5391396Stmm#include <net/if.h>
5491396Stmm#include <net/if_arp.h>
5591396Stmm#include <net/if_dl.h>
5691396Stmm#include <net/if_media.h>
5791396Stmm
58119351Smarcel#include <dev/mii/mii.h>
59119351Smarcel#include <dev/mii/miivar.h>
6091396Stmm
61119280Simp#include <dev/pci/pcivar.h>
62119280Simp#include <dev/pci/pcireg.h>
6391396Stmm
64119351Smarcel#include <dev/hme/if_hmereg.h>
65119351Smarcel#include <dev/hme/if_hmevar.h>
6691396Stmm
6791396Stmm#include "miibus_if.h"
6891396Stmm
6991396Stmmstruct hme_pci_softc {
7091396Stmm	struct	hme_softc	hsc_hme;	/* HME device */
7191396Stmm	struct	resource	*hsc_sres;
7291396Stmm	int			hsc_srid;
7391396Stmm	struct	resource	*hsc_ires;
7491396Stmm	int			hsc_irid;
7591396Stmm	bus_space_tag_t		hsc_memt;
7691396Stmm	bus_space_handle_t	hsc_memh;
7791396Stmm	void			*hsc_ih;
7891396Stmm};
7991396Stmm
8091396Stmmstatic int hme_pci_probe(device_t);
8191396Stmmstatic int hme_pci_attach(device_t);
82108976Stmmstatic int hme_pci_detach(device_t);
83108976Stmmstatic int hme_pci_suspend(device_t);
84108976Stmmstatic int hme_pci_resume(device_t);
8591396Stmm
8691396Stmmstatic device_method_t hme_pci_methods[] = {
8791396Stmm	/* Device interface */
8891396Stmm	DEVMETHOD(device_probe,		hme_pci_probe),
8991396Stmm	DEVMETHOD(device_attach,	hme_pci_attach),
90108976Stmm	DEVMETHOD(device_detach,	hme_pci_detach),
91108976Stmm	DEVMETHOD(device_suspend,	hme_pci_suspend),
92108976Stmm	DEVMETHOD(device_resume,	hme_pci_resume),
93108976Stmm	/* Can just use the suspend method here. */
94108976Stmm	DEVMETHOD(device_shutdown,	hme_pci_suspend),
9591396Stmm
9691396Stmm	/* bus interface */
9791396Stmm	DEVMETHOD(bus_print_child,	bus_generic_print_child),
9891396Stmm	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
9991396Stmm
10091396Stmm	/* MII interface */
10191396Stmm	DEVMETHOD(miibus_readreg,	hme_mii_readreg),
10291396Stmm	DEVMETHOD(miibus_writereg,	hme_mii_writereg),
10391396Stmm	DEVMETHOD(miibus_statchg,	hme_mii_statchg),
10491396Stmm
10591396Stmm	{ 0, 0 }
10691396Stmm};
10791396Stmm
10891396Stmmstatic driver_t hme_pci_driver = {
10991396Stmm	"hme",
11091396Stmm	hme_pci_methods,
11191396Stmm	sizeof(struct hme_pci_softc)
11291396Stmm};
11391396Stmm
114113506SmdoddDRIVER_MODULE(hme, pci, hme_pci_driver, hme_devclass, 0, 0);
115113506SmdoddMODULE_DEPEND(hme, pci, 1, 1, 1);
116113506SmdoddMODULE_DEPEND(hme, ether, 1, 1, 1);
11791396Stmm
11891396Stmmint
11991396Stmmhme_pci_probe(device_t dev)
12091396Stmm{
12191396Stmm
12291396Stmm	if (pci_get_vendor(dev) == 0x108e &&
12391396Stmm	    pci_get_device(dev) ==  0x1001) {
12491396Stmm		device_set_desc(dev, "Sun HME 10/100 Ethernet");
12591396Stmm		return (0);
12691396Stmm	}
12791396Stmm	return (ENXIO);
12891396Stmm}
12991396Stmm
13091396Stmmint
13191396Stmmhme_pci_attach(device_t dev)
13291396Stmm{
13391396Stmm	struct hme_pci_softc *hsc = device_get_softc(dev);
13491396Stmm	struct hme_softc *sc = &hsc->hsc_hme;
13591396Stmm	int error;
13691396Stmm
137117116Stmm	pci_enable_busmaster(dev);
13891396Stmm	/*
139117116Stmm	 * Some Sun HMEs do have their intpin register bogusly set to 0,
140117116Stmm	 * although it should be 1. correct that.
14191396Stmm	 */
142117116Stmm	if (pci_get_intpin(dev) == 0)
143117116Stmm		pci_set_intpin(dev, 1);
14491396Stmm
145117116Stmm	sc->sc_pci = 1;
14691396Stmm	sc->sc_dev = dev;
14791396Stmm
14891396Stmm	/*
14991396Stmm	 * Map five register banks:
15091396Stmm	 *
15191396Stmm	 *	bank 0: HME SEB registers:	+0x0000
15291396Stmm	 *	bank 1: HME ETX registers:	+0x2000
15391396Stmm	 *	bank 2: HME ERX registers:	+0x4000
15491396Stmm	 *	bank 3: HME MAC registers:	+0x6000
15591396Stmm	 *	bank 4: HME MIF registers:	+0x7000
15691396Stmm	 *
15791396Stmm	 */
15891396Stmm	hsc->hsc_srid = PCI_HME_BASEADDR;
15991396Stmm	hsc->hsc_sres = bus_alloc_resource(dev, SYS_RES_MEMORY, &hsc->hsc_srid,
16091396Stmm	    0, ~0, 1, RF_ACTIVE);
16191396Stmm	if (hsc->hsc_sres == NULL) {
16291396Stmm		device_printf(dev, "could not map device registers\n");
16391396Stmm		return (ENXIO);
16491396Stmm	}
16591396Stmm	hsc->hsc_irid = 0;
16691396Stmm	hsc->hsc_ires = bus_alloc_resource(dev, SYS_RES_IRQ, &hsc->hsc_irid, 0,
16793043Stmm	    ~0, 1, RF_SHAREABLE | RF_ACTIVE);
16891396Stmm	if (hsc->hsc_ires == NULL) {
16991396Stmm		device_printf(dev, "could not allocate interrupt\n");
17091396Stmm		error = ENXIO;
17191396Stmm		goto fail_sres;
17291396Stmm	}
17391396Stmm	sc->sc_sebt = sc->sc_etxt = sc->sc_erxt = sc->sc_mact = sc->sc_mift =
17491396Stmm	    rman_get_bustag(hsc->hsc_sres);
17591396Stmm	sc->sc_sebh = sc->sc_etxh = sc->sc_erxh = sc->sc_mach = sc->sc_mifh =
17691396Stmm	    rman_get_bushandle(hsc->hsc_sres);
17791396Stmm	sc->sc_sebo = 0;
17891396Stmm	sc->sc_etxo = 0x2000;
17991396Stmm	sc->sc_erxo = 0x4000;
18091396Stmm	sc->sc_maco = 0x6000;
18191396Stmm	sc->sc_mifo = 0x7000;
18291396Stmm
18391396Stmm	OF_getetheraddr(dev, sc->sc_arpcom.ac_enaddr);
18491396Stmm
18591396Stmm	sc->sc_burst = 64;	/* XXX */
18691396Stmm
18791396Stmm	/*
18891396Stmm	 * call the main configure
18991396Stmm	 */
19091396Stmm	if ((error = hme_config(sc)) != 0) {
19191396Stmm		device_printf(dev, "could not be configured\n");
19291396Stmm		goto fail_ires;
19391396Stmm	}
19491396Stmm
19591396Stmm	if ((error = bus_setup_intr(dev, hsc->hsc_ires, INTR_TYPE_NET, hme_intr,
19691396Stmm	     sc, &hsc->hsc_ih)) != 0) {
19791396Stmm		device_printf(dev, "couldn't establish interrupt\n");
198108976Stmm		hme_detach(sc);
19991396Stmm		goto fail_ires;
20091396Stmm	}
20191396Stmm	return (0);
20291396Stmm
20391396Stmmfail_ires:
20491396Stmm	bus_release_resource(dev, SYS_RES_IRQ, hsc->hsc_irid, hsc->hsc_ires);
20591396Stmmfail_sres:
20691396Stmm	bus_release_resource(dev, SYS_RES_MEMORY, hsc->hsc_srid, hsc->hsc_sres);
20791396Stmm	return (ENXIO);
20891396Stmm}
209108976Stmm
210108976Stmmstatic int
211108976Stmmhme_pci_detach(device_t dev)
212108976Stmm{
213108976Stmm	struct hme_pci_softc *hsc = device_get_softc(dev);
214108976Stmm	struct hme_softc *sc = &hsc->hsc_hme;
215108976Stmm
216108976Stmm	hme_detach(sc);
217108976Stmm
218108976Stmm	bus_teardown_intr(dev, hsc->hsc_ires, hsc->hsc_ih);
219108976Stmm	bus_release_resource(dev, SYS_RES_IRQ, hsc->hsc_irid, hsc->hsc_ires);
220108976Stmm	bus_release_resource(dev, SYS_RES_MEMORY, hsc->hsc_srid, hsc->hsc_sres);
221108976Stmm	return (0);
222108976Stmm}
223108976Stmm
224108976Stmmstatic int
225108976Stmmhme_pci_suspend(device_t dev)
226108976Stmm{
227108976Stmm	struct hme_pci_softc *hsc = device_get_softc(dev);
228108976Stmm	struct hme_softc *sc = &hsc->hsc_hme;
229108976Stmm
230108976Stmm	hme_suspend(sc);
231108976Stmm	return (0);
232108976Stmm}
233108976Stmm
234108976Stmmstatic int
235108976Stmmhme_pci_resume(device_t dev)
236108976Stmm{
237108976Stmm	struct hme_pci_softc *hsc = device_get_softc(dev);
238108976Stmm	struct hme_softc *sc = &hsc->hsc_hme;
239108976Stmm
240108976Stmm	hme_resume(sc);
241108976Stmm	return (0);
242108976Stmm}
243