1139749Simp/*-
219410Sguido * Copyright (C) 1996 Naoki Hamada <nao@tom-yam.or.jp>
319410Sguido * All rights reserved.
419410Sguido *
519410Sguido * Redistribution and use in source and binary forms, with or without
619410Sguido * modification, are permitted provided that the following conditions
719410Sguido * are met:
819410Sguido * 1. Redistributions of source code must retain the above copyright
919410Sguido *    notice, this list of conditions and the following disclaimer.
1019410Sguido * 2. Redistributions in binary form must reproduce the above copyright
1119410Sguido *    notice, this list of conditions and the following disclaimer in the
1219410Sguido *    documentation and/or other materials provided with the distribution.
1319410Sguido * 3. Neither the name of the author nor the names of any co-contributors
1419410Sguido *    may be used to endorse or promote products derived from this software
1519410Sguido *    without specific prior written permission.
1619410Sguido *
1719410Sguido * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1819410Sguido * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1919410Sguido * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2019410Sguido * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2119410Sguido * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2219410Sguido * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2319410Sguido * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2419410Sguido * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2519410Sguido * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2619410Sguido * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2719410Sguido * SUCH DAMAGE.
2819410Sguido *
2919410Sguido */
3019410Sguido
31119418Sobrien#include <sys/cdefs.h>
32119418Sobrien__FBSDID("$FreeBSD: releng/10.2/sys/dev/vx/if_vx_eisa.c 246128 2013-01-30 18:01:20Z sbz $");
33119418Sobrien
3419410Sguido#include <sys/param.h>
3519410Sguido#include <sys/systm.h>
3619410Sguido#include <sys/kernel.h>
3719410Sguido#include <sys/socket.h>
3845791Speter#include <sys/module.h>
3945791Speter#include <sys/bus.h>
4019410Sguido
4145791Speter#include <machine/bus.h>
4245791Speter#include <machine/resource.h>
4345791Speter#include <sys/rman.h>
4445791Speter
45151017Sjhb#include <net/ethernet.h>
4619410Sguido#include <net/if.h>
4732350Seivind#include <net/if_arp.h>
4819410Sguido
4955953Speter#include <dev/eisa/eisaconf.h>
5019410Sguido
5119410Sguido#include <dev/vx/if_vxreg.h>
52121491Simp#include <dev/vx/if_vxvar.h>
5319410Sguido
5419410Sguido#define EISA_DEVICE_ID_3COM_3C592	0x506d5920
5519410Sguido#define EISA_DEVICE_ID_3COM_3C597_TX	0x506d5970
5619410Sguido#define EISA_DEVICE_ID_3COM_3C597_T4	0x506d5971
5719410Sguido#define EISA_DEVICE_ID_3COM_3C597_MII	0x506d5972
5819410Sguido
5919410Sguido
6019410Sguido#define	VX_EISA_SLOT_OFFSET		0x0c80
6119410Sguido#define	VX_EISA_IOSIZE			0x000a
6219410Sguido#define VX_RESOURCE_CONFIG		0x0008
6319410Sguido
6419410Sguido
6592739Salfredstatic const char *vx_match(eisa_id_t type);
6619410Sguido
67133980Sgibbsstatic const char *
6845791Spetervx_match(eisa_id_t type)
6919410Sguido{
70133980Sgibbs	switch (type) {
71133980Sgibbs	case EISA_DEVICE_ID_3COM_3C592:
72182143Simp		return "3Com 3C592";
73133980Sgibbs	case EISA_DEVICE_ID_3COM_3C597_TX:
74182143Simp		return "3Com 3C597-TX";
75133980Sgibbs	case EISA_DEVICE_ID_3COM_3C597_T4:
76182143Simp		return "3Com 3C597-T4";
77133980Sgibbs	case EISA_DEVICE_ID_3COM_3C597_MII:
78182143Simp		return "3Com 3C597-MII";
79133980Sgibbs	default:
80133980Sgibbs		break;
81133980Sgibbs	}
82133980Sgibbs	return (NULL);
8319410Sguido}
8419410Sguido
8519410Sguidostatic int
8645791Spetervx_eisa_probe(device_t dev)
8719410Sguido{
88133980Sgibbs	const char *desc;
89133980Sgibbs	u_long iobase;
90133980Sgibbs	u_long port;
9119410Sguido
92133980Sgibbs	desc = vx_match(eisa_get_id(dev));
93133980Sgibbs	if (!desc)
94133980Sgibbs		return (ENXIO);
95133980Sgibbs	device_set_desc(dev, desc);
9619410Sguido
97133980Sgibbs	port = eisa_get_slot(dev) * EISA_SLOT_SIZE;
98133980Sgibbs	iobase = port + VX_EISA_SLOT_OFFSET;
9919410Sguido
100133980Sgibbs	eisa_add_iospace(dev, iobase, VX_EISA_IOSIZE, RESVADDR_NONE);
101133980Sgibbs	eisa_add_iospace(dev, port, VX_IOSIZE, RESVADDR_NONE);
10219410Sguido
103133980Sgibbs	/* Set irq */
104133980Sgibbs	eisa_add_intr(dev, inw(iobase + VX_RESOURCE_CONFIG) >> 12,
105133980Sgibbs	    EISA_TRIGGER_EDGE);
10645791Speter
107133980Sgibbs	return (0);
10819410Sguido}
10919410Sguido
11019410Sguidostatic int
11145791Spetervx_eisa_attach(device_t dev)
11219410Sguido{
113133980Sgibbs	struct vx_softc *sc;
114133980Sgibbs	struct resource *io = 0;
115133980Sgibbs	struct resource *eisa_io = 0;
116133980Sgibbs	struct resource *irq = 0;
117133980Sgibbs	int rid;
11819410Sguido
119133980Sgibbs	/*
120133980Sgibbs         * The addresses are sorted in increasing order
121133980Sgibbs         * so we know the port to pass to the core ep
122133980Sgibbs         * driver comes first.
123133980Sgibbs         */
124133980Sgibbs	rid = 0;
125133980Sgibbs	io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
126133980Sgibbs	if (!io) {
127133980Sgibbs		device_printf(dev, "No I/O space?!\n");
128133980Sgibbs		goto bad;
129133980Sgibbs	}
130133980Sgibbs	rid = 1;
131133980Sgibbs	eisa_io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
132133980Sgibbs	if (!eisa_io) {
133133980Sgibbs		device_printf(dev, "No I/O space?!\n");
134133980Sgibbs		goto bad;
135133980Sgibbs	}
136133980Sgibbs	sc = device_get_softc(dev);
13729674Sgibbs
138133980Sgibbs	sc->vx_res = io;
139151014Sjhb	sc->vx_bst = rman_get_bustag(io);
140151014Sjhb	sc->vx_bsh = rman_get_bushandle(io);
14129674Sgibbs
142133980Sgibbs	rid = 0;
143133980Sgibbs	irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
144133980Sgibbs	if (!irq) {
145133980Sgibbs		device_printf(dev, "No irq?!\n");
146133980Sgibbs		goto bad;
147133980Sgibbs	}
148133980Sgibbs	sc->vx_irq = irq;
14919410Sguido
150133980Sgibbs	/* Now the registers are availible through the lower ioport */
15119410Sguido
152151014Sjhb	if (vx_attach(dev) == 0)
153133980Sgibbs		goto bad;
15468417Swpaul
155166901Spiso	if (bus_setup_intr(dev, irq, INTR_TYPE_NET | INTR_MPSAFE, NULL,
156166901Spiso		  vx_intr, sc, &sc->vx_intrhand))
157151014Sjhb		goto bad_mtx;
15819410Sguido
159151014Sjhb	return (0);
16019410Sguido
161151014Sjhbbad_mtx:
162151014Sjhb	mtx_destroy(&sc->vx_mtx);
163151017Sjhb	ether_ifdetach(sc->vx_ifp);
164151017Sjhb	if_free(sc->vx_ifp);
165133980Sgibbsbad:
166133980Sgibbs	if (io)
167133980Sgibbs		bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
168133980Sgibbs	if (eisa_io)
169133980Sgibbs		bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io);
170133980Sgibbs	if (irq)
171133980Sgibbs		bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
172151014Sjhb	return (ENXIO);
17319410Sguido}
17419410Sguido
17545791Speterstatic device_method_t vx_eisa_methods[] = {
17645791Speter	/* Device interface */
177133980Sgibbs	DEVMETHOD(device_probe, vx_eisa_probe),
178133980Sgibbs	DEVMETHOD(device_attach, vx_eisa_attach),
17945791Speter
180246128Ssbz	DEVMETHOD_END
18145791Speter};
18245791Speter
18345791Speterstatic driver_t vx_eisa_driver = {
18445791Speter	"vx",
18545791Speter	vx_eisa_methods,
186133518Sgibbs	sizeof(struct vx_softc)
18745791Speter};
18845791Speter
18945791Speterstatic devclass_t vx_devclass;
19045791Speter
19145791SpeterDRIVER_MODULE(vx, eisa, vx_eisa_driver, vx_devclass, 0, 0);
192