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