if_ep_eisa.c revision 92739
114258Sgibbs/*
214258Sgibbs * Product specific probe and attach routines for:
314258Sgibbs * 	3COM 3C579 and 3C509(in eisa config mode) ethernet controllers
414258Sgibbs *
514258Sgibbs * Copyright (c) 1996 Justin T. Gibbs
614258Sgibbs * All rights reserved.
714258Sgibbs *
814258Sgibbs * Redistribution and use in source and binary forms, with or without
914258Sgibbs * modification, are permitted provided that the following conditions
1014258Sgibbs * are met:
1114258Sgibbs * 1. Redistributions of source code must retain the above copyright
1214258Sgibbs *    notice immediately at the beginning of the file, without modification,
1314258Sgibbs *    this list of conditions, and the following disclaimer.
1414258Sgibbs * 2. Redistributions in binary form must reproduce the above copyright
1514258Sgibbs *    notice, this list of conditions and the following disclaimer in the
1614258Sgibbs *    documentation and/or other materials provided with the distribution.
1714258Sgibbs * 3. Absolutely no warranty of function or purpose is made by the author
1814258Sgibbs *    Justin T. Gibbs.
1914258Sgibbs * 4. Modifications may be freely made to this file if the above conditions
2014258Sgibbs *    are met.
2114258Sgibbs *
2250477Speter * $FreeBSD: head/sys/dev/ep/if_ep_eisa.c 92739 2002-03-20 02:08:01Z alfred $
2314258Sgibbs */
2414258Sgibbs
2514258Sgibbs#include <sys/param.h>
2614258Sgibbs#include <sys/systm.h>
2714258Sgibbs#include <sys/kernel.h>
2818892Sbde#include <sys/socket.h>
2952549Smdodd
3045791Speter#include <sys/module.h>
3145791Speter#include <sys/bus.h>
3214258Sgibbs
3345791Speter#include <machine/bus.h>
3445791Speter#include <machine/resource.h>
3552549Smdodd#include <sys/rman.h>
3614258Sgibbs
3714258Sgibbs#include <net/if.h>
3852549Smdodd#include <net/if_arp.h>
3952549Smdodd#include <net/if_media.h>
4014258Sgibbs
4114258Sgibbs
4255953Speter#include <dev/eisa/eisaconf.h>
4314258Sgibbs
4451879Smdodd#include <dev/ep/if_epreg.h>
4551879Smdodd#include <dev/ep/if_epvar.h>
4651879Smdodd
4714258Sgibbs#define EISA_DEVICE_ID_3COM_3C509_TP	0x506d5090
4814258Sgibbs#define EISA_DEVICE_ID_3COM_3C509_BNC	0x506d5091
4914258Sgibbs#define EISA_DEVICE_ID_3COM_3C579_TP	0x506d5092
5014258Sgibbs#define EISA_DEVICE_ID_3COM_3C579_BNC	0x506d5093
5114258Sgibbs#define EISA_DEVICE_ID_3COM_3C509_COMBO	0x506d5094
5214258Sgibbs#define EISA_DEVICE_ID_3COM_3C509_TPO	0x506d5095
5314258Sgibbs
5414258Sgibbs#define	EP_EISA_SLOT_OFFSET		0x0c80
5514258Sgibbs#define	EP_EISA_IOSIZE			0x000a
5614258Sgibbs
5714258Sgibbs#define EISA_IOCONF			0x0008
5814258Sgibbs#define		IRQ_CHANNEL		0xf000
5914258Sgibbs#define			INT_3		0x3000
6014258Sgibbs#define			INT_5		0x5000
6114258Sgibbs#define			INT_7		0x7000
6214258Sgibbs#define			INT_9		0x9000
6314258Sgibbs#define			INT_10		0xa000
6414258Sgibbs#define			INT_11		0xb000
6514258Sgibbs#define			INT_12		0xc000
6614258Sgibbs#define			INT_15		0xf000
6714258Sgibbs#define EISA_BPROM_MEDIA_CONF		0x0006
6814258Sgibbs#define		TRANS_TYPE		0xc000
6914258Sgibbs#define			TRANS_TP	0x0000
7014258Sgibbs#define			TRANS_AUI	0x4000
7114258Sgibbs#define			TRANS_BNC	0xc000
7214258Sgibbs
7392739Salfredstatic const char *ep_match(eisa_id_t type);
7414258Sgibbs
7529674Sgibbsstatic const char*
7645791Speterep_match(eisa_id_t type)
7714258Sgibbs{
7814258Sgibbs	switch(type) {
7914258Sgibbs		case EISA_DEVICE_ID_3COM_3C509_TP:
8014258Sgibbs			return "3Com 3C509-TP Network Adapter";
8114258Sgibbs			break;
8214258Sgibbs		case EISA_DEVICE_ID_3COM_3C509_BNC:
8314258Sgibbs			return "3Com 3C509-BNC Network Adapter";
8414258Sgibbs			break;
8514258Sgibbs		case EISA_DEVICE_ID_3COM_3C579_TP:
8614258Sgibbs			return "3Com 3C579-TP EISA Network Adapter";
8714258Sgibbs			break;
8814258Sgibbs		case EISA_DEVICE_ID_3COM_3C579_BNC:
8914258Sgibbs			return "3Com 3C579-BNC EISA Network Adapter";
9014258Sgibbs			break;
9114258Sgibbs		case EISA_DEVICE_ID_3COM_3C509_COMBO:
9214258Sgibbs			return "3Com 3C509-Combo Network Adapter";
9314258Sgibbs			break;
9414258Sgibbs		case EISA_DEVICE_ID_3COM_3C509_TPO:
9514258Sgibbs			return "3Com 3C509-TPO Network Adapter";
9614258Sgibbs			break;
9714258Sgibbs		default:
9814258Sgibbs			break;
9914258Sgibbs	}
10014258Sgibbs	return (NULL);
10114258Sgibbs}
10214258Sgibbs
10314258Sgibbsstatic int
10445791Speterep_eisa_probe(device_t dev)
10514258Sgibbs{
10645791Speter	const char *desc;
10714258Sgibbs	u_long iobase;
10845791Speter	u_short conf;
10945791Speter	u_long port;
11045791Speter	int irq;
11152549Smdodd	int int_trig;
11214258Sgibbs
11345791Speter	desc = ep_match(eisa_get_id(dev));
11445791Speter	if (!desc)
11545791Speter		return (ENXIO);
11645791Speter	device_set_desc(dev, desc);
11714258Sgibbs
11845791Speter	port = (eisa_get_slot(dev) * EISA_SLOT_SIZE);
11945791Speter	iobase = port + EP_EISA_SLOT_OFFSET;
12014258Sgibbs
12145791Speter	/* We must be in EISA configuration mode */
12245791Speter	if ((inw(iobase + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f)
12345791Speter	    return ENXIO;
12414258Sgibbs
12545791Speter	eisa_add_iospace(dev, iobase, EP_EISA_IOSIZE, RESVADDR_NONE);
12645791Speter	eisa_add_iospace(dev, port, EP_IOSIZE, RESVADDR_NONE);
12714258Sgibbs
12845791Speter	conf = inw(iobase + EISA_IOCONF);
12945791Speter	/* Determine our IRQ */
13045791Speter	switch (conf & IRQ_CHANNEL) {
13145791Speter	case INT_3:
13245791Speter	    irq = 3;
13345791Speter	    break;
13445791Speter	case INT_5:
13545791Speter	    irq = 5;
13645791Speter	    break;
13745791Speter	case INT_7:
13845791Speter	    irq = 7;
13945791Speter	    break;
14045791Speter	case INT_9:
14145791Speter	    irq = 9;
14245791Speter	    break;
14345791Speter	case INT_10:
14445791Speter	    irq = 10;
14545791Speter	    break;
14645791Speter	case INT_11:
14745791Speter	    irq = 11;
14845791Speter	    break;
14945791Speter	case INT_12:
15045791Speter	    irq = 12;
15145791Speter	    break;
15245791Speter	case INT_15:
15345791Speter	    irq = 15;
15445791Speter	    break;
15545791Speter	default:
15614258Sgibbs				/* Disabled */
15745791Speter	    printf("ep: 3COM Network Adapter at "
15845791Speter		   "slot %d has its IRQ disabled. "
15945791Speter		   "Probe failed.\n",
16045791Speter		   eisa_get_slot(dev));
16145791Speter	    return ENXIO;
16214258Sgibbs	}
16345791Speter
16452549Smdodd	switch(eisa_get_id(dev)) {
16552549Smdodd		case EISA_DEVICE_ID_3COM_3C579_BNC:
16652549Smdodd		case EISA_DEVICE_ID_3COM_3C579_TP:
16752549Smdodd			int_trig = EISA_TRIGGER_LEVEL;
16852549Smdodd			break;
16952549Smdodd		default:
17052549Smdodd			int_trig = EISA_TRIGGER_EDGE;
17152549Smdodd			break;
17252549Smdodd	}
17352549Smdodd
17452549Smdodd	eisa_add_intr(dev, irq, int_trig);
17552549Smdodd
17645791Speter	return 0;
17714258Sgibbs}
17814258Sgibbs
17914258Sgibbsstatic int
18045791Speterep_eisa_attach(device_t dev)
18114258Sgibbs{
18252549Smdodd	struct ep_softc *	sc = device_get_softc(dev);
18352549Smdodd	struct resource *	eisa_io = NULL;
18452549Smdodd	u_int32_t		eisa_iobase;
18552549Smdodd	int			irq;
18652549Smdodd	int			error = 0;
18752549Smdodd	int			rid;
18814258Sgibbs
18945791Speter	rid = 1;
19045791Speter	eisa_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
19145791Speter				     0, ~0, 1, RF_ACTIVE);
19245791Speter	if (!eisa_io) {
19345791Speter		device_printf(dev, "No I/O space?!\n");
19452549Smdodd		error = ENXIO;
19545791Speter		goto bad;
19645791Speter	}
19752549Smdodd	eisa_iobase = rman_get_start(eisa_io);
19814258Sgibbs
19952549Smdodd	/* Reset and Enable the card */
20052549Smdodd	outb(eisa_iobase + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER);
20152549Smdodd	DELAY(1000); /* we must wait at least 1 ms */
20252549Smdodd	outb(eisa_iobase + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER);
20352549Smdodd	/* Now the registers are availible through the lower ioport */
20414258Sgibbs
20552549Smdodd	if ((error = ep_alloc(dev))) {
20652549Smdodd		device_printf(dev, "ep_alloc() failed! (%d)\n", error);
20745791Speter		goto bad;
20852549Smdodd	}
20914258Sgibbs
21045791Speter	switch(eisa_get_id(dev)) {
21152549Smdodd		case EISA_DEVICE_ID_3COM_3C579_BNC:
21214258Sgibbs		case EISA_DEVICE_ID_3COM_3C579_TP:
21314258Sgibbs			sc->stat = F_ACCESS_32_BITS;
21414258Sgibbs			break;
21514258Sgibbs		default:
21614258Sgibbs			break;
21714258Sgibbs	}
21814258Sgibbs
21952549Smdodd	ep_get_media(sc);
22014258Sgibbs
22152549Smdodd	irq = rman_get_start(sc->irq);
22252549Smdodd	if (irq == 9)
22352549Smdodd		irq = 2;
22414258Sgibbs
22545791Speter	GO_WINDOW(0);
22652549Smdodd	SET_IRQ(BASE, irq);
22714258Sgibbs
22852549Smdodd	if ((error = ep_attach(sc))) {
22952549Smdodd		device_printf(dev, "ep_attach() failed! (%d)\n", error);
23052549Smdodd		goto bad;
23152549Smdodd	}
23217223Samurai
23352549Smdodd	if ((error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, ep_intr,
23452549Smdodd				   sc, &sc->ep_intrhand))) {
23552549Smdodd		device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
23652549Smdodd		goto bad;
23752549Smdodd	}
23814258Sgibbs
23952549Smdodd	return (0);
24014258Sgibbs
24145791Speter bad:
24245791Speter	if (eisa_io)
24345791Speter		bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io);
24452549Smdodd
24552549Smdodd	ep_free(dev);
24652549Smdodd	return (error);
24714258Sgibbs}
24814258Sgibbs
24945791Speterstatic device_method_t ep_eisa_methods[] = {
25045791Speter	/* Device interface */
25145791Speter	DEVMETHOD(device_probe,		ep_eisa_probe),
25245791Speter	DEVMETHOD(device_attach,	ep_eisa_attach),
25345791Speter
25445791Speter	{ 0, 0 }
25545791Speter};
25645791Speter
25745791Speterstatic driver_t ep_eisa_driver = {
25845791Speter	"ep",
25945791Speter	ep_eisa_methods,
26052549Smdodd	sizeof(struct ep_softc),
26145791Speter};
26245791Speter
26352472Simpextern devclass_t ep_devclass;
26445791Speter
26545791SpeterDRIVER_MODULE(ep, eisa, ep_eisa_driver, ep_devclass, 0, 0);
266