if_vx_eisa.c revision 115548
160484Sobrien/*
292828Sobrien * Copyright (C) 1996 Naoki Hamada <nao@tom-yam.or.jp>
392828Sobrien * All rights reserved.
460484Sobrien *
560484Sobrien * Redistribution and use in source and binary forms, with or without
660484Sobrien * modification, are permitted provided that the following conditions
760484Sobrien * are met:
860484Sobrien * 1. Redistributions of source code must retain the above copyright
960484Sobrien *    notice, this list of conditions and the following disclaimer.
1060484Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1160484Sobrien *    notice, this list of conditions and the following disclaimer in the
1260484Sobrien *    documentation and/or other materials provided with the distribution.
1360484Sobrien * 3. Neither the name of the author nor the names of any co-contributors
1460484Sobrien *    may be used to endorse or promote products derived from this software
1560484Sobrien *    without specific prior written permission.
1660484Sobrien *
1760484Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1860484Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1960484Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2060484Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2160484Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2260484Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2360484Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2460484Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2560484Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2660484Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2760484Sobrien * SUCH DAMAGE.
2860484Sobrien *
2960484Sobrien * $FreeBSD: head/sys/dev/vx/if_vx_eisa.c 115548 2003-05-31 20:28:21Z phk $
3060484Sobrien */
3160484Sobrien
3260484Sobrien#include <sys/param.h>
3360484Sobrien#include <sys/systm.h>
3460484Sobrien#include <sys/kernel.h>
3560484Sobrien#include <sys/socket.h>
3660484Sobrien#include <sys/module.h>
3760484Sobrien#include <sys/bus.h>
3860484Sobrien
3960484Sobrien#include <machine/bus.h>
4060484Sobrien#include <machine/resource.h>
4160484Sobrien#include <sys/rman.h>
4260484Sobrien
4360484Sobrien#include <net/if.h>
4460484Sobrien#include <net/if_arp.h>
4560484Sobrien
4660484Sobrien#include <dev/eisa/eisaconf.h>
4760484Sobrien
4860484Sobrien#include <dev/vx/if_vxreg.h>
4960484Sobrien
5060484Sobrien#define EISA_DEVICE_ID_3COM_3C592	0x506d5920
5160484Sobrien#define EISA_DEVICE_ID_3COM_3C597_TX	0x506d5970
5260484Sobrien#define EISA_DEVICE_ID_3COM_3C597_T4	0x506d5971
5360484Sobrien#define EISA_DEVICE_ID_3COM_3C597_MII	0x506d5972
5460484Sobrien
5560484Sobrien
5660484Sobrien#define	VX_EISA_SLOT_OFFSET		0x0c80
5760484Sobrien#define	VX_EISA_IOSIZE			0x000a
5860484Sobrien#define VX_RESOURCE_CONFIG		0x0008
5960484Sobrien
6060484Sobrien
6160484Sobrienstatic const char *vx_match(eisa_id_t type);
6260484Sobrien
6360484Sobrienstatic const char*
6460484Sobrienvx_match(eisa_id_t type)
6560484Sobrien{
6660484Sobrien    switch (type) {
6760484Sobrien      case EISA_DEVICE_ID_3COM_3C592:
6860484Sobrien	return "3Com 3C592 Network Adapter";
6960484Sobrien      case EISA_DEVICE_ID_3COM_3C597_TX:
7060484Sobrien	return "3Com 3C597-TX Network Adapter";
7160484Sobrien      case EISA_DEVICE_ID_3COM_3C597_T4:
7260484Sobrien	return "3Com 3C597-T4 Network Adapter";
7360484Sobrien      case EISA_DEVICE_ID_3COM_3C597_MII:
7460484Sobrien	return "3Com 3C597-MII Network Adapter";
7560484Sobrien      default:
7660484Sobrien	break;
7760484Sobrien    }
7860484Sobrien    return (NULL);
7960484Sobrien}
8060484Sobrien
8160484Sobrienstatic int
8260484Sobrienvx_eisa_probe(device_t dev)
8360484Sobrien{
8460484Sobrien    const char	   *desc;
8560484Sobrien    u_long          iobase;
8660484Sobrien    u_long          port;
8760484Sobrien
8860484Sobrien    desc = vx_match(eisa_get_id(dev));
8960484Sobrien    if (!desc)
9060484Sobrien	return (ENXIO);
9160484Sobrien    device_set_desc(dev, desc);
9277298Sobrien
9389857Sobrien    port = eisa_get_slot(dev) * EISA_SLOT_SIZE;
9477298Sobrien    iobase = port + VX_EISA_SLOT_OFFSET;
9589857Sobrien
9689857Sobrien    eisa_add_iospace(dev, iobase, VX_EISA_IOSIZE, RESVADDR_NONE);
9789857Sobrien    eisa_add_iospace(dev, port, VX_IOSIZE, RESVADDR_NONE);
9889857Sobrien
9989857Sobrien    /* Set irq */
10089857Sobrien    eisa_add_intr(dev, inw(iobase + VX_RESOURCE_CONFIG) >> 12,
10189857Sobrien		  EISA_TRIGGER_EDGE);
10289857Sobrien
10389857Sobrien    return (0);
10492828Sobrien}
10592828Sobrien
10692828Sobrienstatic int
10792828Sobrienvx_eisa_attach(device_t dev)
10892828Sobrien{
10992828Sobrien    struct vx_softc *sc;
11060484Sobrien    struct resource *io = 0;
11160484Sobrien    struct resource *eisa_io = 0;
11260484Sobrien    struct resource *irq = 0;
11360484Sobrien    int		    rid;
11460484Sobrien    void	    *ih;
11560484Sobrien
11660484Sobrien    /*
11760484Sobrien     * The addresses are sorted in increasing order
11860484Sobrien     * so we know the port to pass to the core ep
11960484Sobrien     * driver comes first.
12060484Sobrien     */
12160484Sobrien    rid = 0;
12260484Sobrien    io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
12360484Sobrien			    0, ~0, 1, RF_ACTIVE);
12460484Sobrien    if (!io) {
12560484Sobrien	device_printf(dev, "No I/O space?!\n");
12660484Sobrien	goto bad;
12760484Sobrien    }
12860484Sobrien
12960484Sobrien    rid = 1;
13060484Sobrien    eisa_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
13160484Sobrien				 0, ~0, 1, RF_ACTIVE);
13260484Sobrien    if (!eisa_io) {
13360484Sobrien	device_printf(dev, "No I/O space?!\n");
13460484Sobrien	goto bad;
13560484Sobrien    }
13660484Sobrien
13760484Sobrien    sc = device_get_softc(dev);
13860484Sobrien
13960484Sobrien    sc->vx_res = io;
14089857Sobrien    sc->vx_bhandle = rman_get_bushandle(io);
14160484Sobrien    sc->vx_btag = rman_get_bustag(io);
14260484Sobrien
14360484Sobrien    rid = 0;
14460484Sobrien    irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
14560484Sobrien			     0, ~0, 1, RF_ACTIVE);
14660484Sobrien    if (!irq) {
14760484Sobrien	device_printf(dev, "No irq?!\n");
14860484Sobrien	goto bad;
14960484Sobrien    }
15060484Sobrien
15160484Sobrien    sc->vx_irq = irq;
15260484Sobrien
15360484Sobrien    /* Now the registers are availible through the lower ioport */
15460484Sobrien
15560484Sobrien    vxattach(sc);
15660484Sobrien
15760484Sobrien    if (bus_setup_intr(dev, irq, INTR_TYPE_NET, vxintr, sc, &ih)) {
15860484Sobrien	goto bad;
15960484Sobrien    }
16089857Sobrien
16189857Sobrien    sc->vx_intrhand = ih;
16260484Sobrien
16360484Sobrien    return 0;
16460484Sobrien
16560484Sobrien bad:
16660484Sobrien    if (io)
16760484Sobrien	bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
16860484Sobrien    if (eisa_io)
16960484Sobrien	bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io);
17060484Sobrien    if (irq)
17160484Sobrien	bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
17260484Sobrien    return -1;
17360484Sobrien}
17460484Sobrien
17560484Sobrienstatic device_method_t vx_eisa_methods[] = {
17660484Sobrien	/* Device interface */
17760484Sobrien	DEVMETHOD(device_probe,		vx_eisa_probe),
17860484Sobrien	DEVMETHOD(device_attach,	vx_eisa_attach),
17960484Sobrien
18060484Sobrien	{ 0, 0 }
18160484Sobrien};
18260484Sobrien
18360484Sobrienstatic driver_t vx_eisa_driver = {
18460484Sobrien	"vx",
18560484Sobrien	vx_eisa_methods,
18660484Sobrien	1,			/* unused */
18760484Sobrien};
18860484Sobrien
18960484Sobrienstatic devclass_t vx_devclass;
19060484Sobrien
19160484SobrienDRIVER_MODULE(vx, eisa, vx_eisa_driver, vx_devclass, 0, 0);
19260484Sobrien