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$");
33119418Sobrien
3419410Sguido#include <sys/param.h>
3519410Sguido#include <sys/systm.h>
36257324Sglebius#include <sys/lock.h>
3719410Sguido#include <sys/kernel.h>
38257324Sglebius#include <sys/mutex.h>
3919410Sguido#include <sys/socket.h>
4045791Speter#include <sys/module.h>
4145791Speter#include <sys/bus.h>
4219410Sguido
4345791Speter#include <machine/bus.h>
4445791Speter#include <machine/resource.h>
4545791Speter#include <sys/rman.h>
4645791Speter
47151017Sjhb#include <net/ethernet.h>
4819410Sguido#include <net/if.h>
49257324Sglebius#include <net/if_var.h>
5019410Sguido
5155953Speter#include <dev/eisa/eisaconf.h>
5219410Sguido
5319410Sguido#include <dev/vx/if_vxreg.h>
54121491Simp#include <dev/vx/if_vxvar.h>
5519410Sguido
5619410Sguido#define EISA_DEVICE_ID_3COM_3C592	0x506d5920
5719410Sguido#define EISA_DEVICE_ID_3COM_3C597_TX	0x506d5970
5819410Sguido#define EISA_DEVICE_ID_3COM_3C597_T4	0x506d5971
5919410Sguido#define EISA_DEVICE_ID_3COM_3C597_MII	0x506d5972
6019410Sguido
6119410Sguido
6219410Sguido#define	VX_EISA_SLOT_OFFSET		0x0c80
6319410Sguido#define	VX_EISA_IOSIZE			0x000a
6419410Sguido#define VX_RESOURCE_CONFIG		0x0008
6519410Sguido
6619410Sguido
6792739Salfredstatic const char *vx_match(eisa_id_t type);
6819410Sguido
69133980Sgibbsstatic const char *
7045791Spetervx_match(eisa_id_t type)
7119410Sguido{
72133980Sgibbs	switch (type) {
73133980Sgibbs	case EISA_DEVICE_ID_3COM_3C592:
74182143Simp		return "3Com 3C592";
75133980Sgibbs	case EISA_DEVICE_ID_3COM_3C597_TX:
76182143Simp		return "3Com 3C597-TX";
77133980Sgibbs	case EISA_DEVICE_ID_3COM_3C597_T4:
78182143Simp		return "3Com 3C597-T4";
79133980Sgibbs	case EISA_DEVICE_ID_3COM_3C597_MII:
80182143Simp		return "3Com 3C597-MII";
81133980Sgibbs	default:
82133980Sgibbs		break;
83133980Sgibbs	}
84133980Sgibbs	return (NULL);
8519410Sguido}
8619410Sguido
8719410Sguidostatic int
8845791Spetervx_eisa_probe(device_t dev)
8919410Sguido{
90133980Sgibbs	const char *desc;
91133980Sgibbs	u_long iobase;
92133980Sgibbs	u_long port;
9319410Sguido
94133980Sgibbs	desc = vx_match(eisa_get_id(dev));
95133980Sgibbs	if (!desc)
96133980Sgibbs		return (ENXIO);
97133980Sgibbs	device_set_desc(dev, desc);
9819410Sguido
99133980Sgibbs	port = eisa_get_slot(dev) * EISA_SLOT_SIZE;
100133980Sgibbs	iobase = port + VX_EISA_SLOT_OFFSET;
10119410Sguido
102133980Sgibbs	eisa_add_iospace(dev, iobase, VX_EISA_IOSIZE, RESVADDR_NONE);
103133980Sgibbs	eisa_add_iospace(dev, port, VX_IOSIZE, RESVADDR_NONE);
10419410Sguido
105133980Sgibbs	/* Set irq */
106133980Sgibbs	eisa_add_intr(dev, inw(iobase + VX_RESOURCE_CONFIG) >> 12,
107133980Sgibbs	    EISA_TRIGGER_EDGE);
10845791Speter
109133980Sgibbs	return (0);
11019410Sguido}
11119410Sguido
11219410Sguidostatic int
11345791Spetervx_eisa_attach(device_t dev)
11419410Sguido{
115133980Sgibbs	struct vx_softc *sc;
116133980Sgibbs	struct resource *io = 0;
117133980Sgibbs	struct resource *eisa_io = 0;
118133980Sgibbs	struct resource *irq = 0;
119133980Sgibbs	int rid;
12019410Sguido
121133980Sgibbs	/*
122133980Sgibbs         * The addresses are sorted in increasing order
123133980Sgibbs         * so we know the port to pass to the core ep
124133980Sgibbs         * driver comes first.
125133980Sgibbs         */
126133980Sgibbs	rid = 0;
127133980Sgibbs	io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
128133980Sgibbs	if (!io) {
129133980Sgibbs		device_printf(dev, "No I/O space?!\n");
130133980Sgibbs		goto bad;
131133980Sgibbs	}
132133980Sgibbs	rid = 1;
133133980Sgibbs	eisa_io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
134133980Sgibbs	if (!eisa_io) {
135133980Sgibbs		device_printf(dev, "No I/O space?!\n");
136133980Sgibbs		goto bad;
137133980Sgibbs	}
138133980Sgibbs	sc = device_get_softc(dev);
13929674Sgibbs
140133980Sgibbs	sc->vx_res = io;
141151014Sjhb	sc->vx_bst = rman_get_bustag(io);
142151014Sjhb	sc->vx_bsh = rman_get_bushandle(io);
14329674Sgibbs
144133980Sgibbs	rid = 0;
145133980Sgibbs	irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
146133980Sgibbs	if (!irq) {
147133980Sgibbs		device_printf(dev, "No irq?!\n");
148133980Sgibbs		goto bad;
149133980Sgibbs	}
150133980Sgibbs	sc->vx_irq = irq;
15119410Sguido
152298955Spfg	/* Now the registers are available through the lower ioport */
15319410Sguido
154151014Sjhb	if (vx_attach(dev) == 0)
155133980Sgibbs		goto bad;
15668417Swpaul
157166901Spiso	if (bus_setup_intr(dev, irq, INTR_TYPE_NET | INTR_MPSAFE, NULL,
158166901Spiso		  vx_intr, sc, &sc->vx_intrhand))
159151014Sjhb		goto bad_mtx;
16019410Sguido
161151014Sjhb	return (0);
16219410Sguido
163151014Sjhbbad_mtx:
164151014Sjhb	mtx_destroy(&sc->vx_mtx);
165151017Sjhb	ether_ifdetach(sc->vx_ifp);
166151017Sjhb	if_free(sc->vx_ifp);
167133980Sgibbsbad:
168133980Sgibbs	if (io)
169133980Sgibbs		bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
170133980Sgibbs	if (eisa_io)
171133980Sgibbs		bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io);
172133980Sgibbs	if (irq)
173133980Sgibbs		bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
174151014Sjhb	return (ENXIO);
17519410Sguido}
17619410Sguido
17745791Speterstatic device_method_t vx_eisa_methods[] = {
17845791Speter	/* Device interface */
179133980Sgibbs	DEVMETHOD(device_probe, vx_eisa_probe),
180133980Sgibbs	DEVMETHOD(device_attach, vx_eisa_attach),
18145791Speter
182246128Ssbz	DEVMETHOD_END
18345791Speter};
18445791Speter
18545791Speterstatic driver_t vx_eisa_driver = {
18645791Speter	"vx",
18745791Speter	vx_eisa_methods,
188133518Sgibbs	sizeof(struct vx_softc)
18945791Speter};
19045791Speter
19145791Speterstatic devclass_t vx_devclass;
19245791Speter
19345791SpeterDRIVER_MODULE(vx, eisa, vx_eisa_driver, vx_devclass, 0, 0);
194