1139749Simp/*- 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 */ 2214258Sgibbs 23117700Smarkm#include <sys/cdefs.h> 24117700Smarkm__FBSDID("$FreeBSD$"); 25117700Smarkm 2614258Sgibbs#include <sys/param.h> 2714258Sgibbs#include <sys/systm.h> 2814258Sgibbs#include <sys/kernel.h> 2918892Sbde#include <sys/socket.h> 3045791Speter#include <sys/module.h> 3145791Speter#include <sys/bus.h> 3214258Sgibbs 3345791Speter#include <machine/bus.h> 3445791Speter#include <machine/resource.h> 35117700Smarkm#include <sys/rman.h> 3614258Sgibbs 3714258Sgibbs#include <net/if.h> 3852549Smdodd#include <net/if_arp.h> 39117700Smarkm#include <net/if_media.h> 4014258Sgibbs 41112845Smdodd#include <dev/eisa/eisaconf.h> 42112845Smdodd 4351879Smdodd#include <dev/ep/if_epreg.h> 4451879Smdodd#include <dev/ep/if_epvar.h> 4551879Smdodd 4614258Sgibbs#define EISA_DEVICE_ID_3COM_3C509_TP 0x506d5090 4714258Sgibbs#define EISA_DEVICE_ID_3COM_3C509_BNC 0x506d5091 4814258Sgibbs#define EISA_DEVICE_ID_3COM_3C579_TP 0x506d5092 4914258Sgibbs#define EISA_DEVICE_ID_3COM_3C579_BNC 0x506d5093 5014258Sgibbs#define EISA_DEVICE_ID_3COM_3C509_COMBO 0x506d5094 5114258Sgibbs#define EISA_DEVICE_ID_3COM_3C509_TPO 0x506d5095 5214258Sgibbs 5314258Sgibbs#define EP_EISA_SLOT_OFFSET 0x0c80 5414258Sgibbs#define EP_EISA_IOSIZE 0x000a 5514258Sgibbs 5614258Sgibbs#define EISA_IOCONF 0x0008 5714258Sgibbs#define IRQ_CHANNEL 0xf000 5814258Sgibbs#define INT_3 0x3000 5914258Sgibbs#define INT_5 0x5000 6014258Sgibbs#define INT_7 0x7000 6114258Sgibbs#define INT_9 0x9000 6214258Sgibbs#define INT_10 0xa000 6314258Sgibbs#define INT_11 0xb000 6414258Sgibbs#define INT_12 0xc000 6514258Sgibbs#define INT_15 0xf000 6614258Sgibbs#define EISA_BPROM_MEDIA_CONF 0x0006 6714258Sgibbs#define TRANS_TYPE 0xc000 6814258Sgibbs#define TRANS_TP 0x0000 6914258Sgibbs#define TRANS_AUI 0x4000 7014258Sgibbs#define TRANS_BNC 0xc000 7114258Sgibbs 7292739Salfredstatic const char *ep_match(eisa_id_t type); 7314258Sgibbs 74117700Smarkmstatic const char * 7545791Speterep_match(eisa_id_t type) 7614258Sgibbs{ 77117700Smarkm switch (type) { 78117700Smarkm case EISA_DEVICE_ID_3COM_3C509_TP: 79149559Simp return ("3Com 3C509-TP"); 80117700Smarkm case EISA_DEVICE_ID_3COM_3C509_BNC: 81149559Simp return ("3Com 3C509-BNC"); 82117700Smarkm case EISA_DEVICE_ID_3COM_3C579_TP: 83149559Simp return ("3Com 3C579-TP"); 84117700Smarkm case EISA_DEVICE_ID_3COM_3C579_BNC: 85149559Simp return ("3Com 3C579-BNC"); 86117700Smarkm case EISA_DEVICE_ID_3COM_3C509_COMBO: 87149559Simp return ("3Com 3C509-Combo"); 88117700Smarkm case EISA_DEVICE_ID_3COM_3C509_TPO: 89149559Simp return ("3Com 3C509-TPO"); 90117700Smarkm default: 91117700Smarkm return (NULL); 9214258Sgibbs } 9314258Sgibbs} 9414258Sgibbs 9514258Sgibbsstatic int 9645791Speterep_eisa_probe(device_t dev) 9714258Sgibbs{ 9845791Speter const char *desc; 9914258Sgibbs u_long iobase; 10045791Speter u_short conf; 10145791Speter u_long port; 10245791Speter int irq; 10352549Smdodd int int_trig; 10414258Sgibbs 10545791Speter desc = ep_match(eisa_get_id(dev)); 10645791Speter if (!desc) 10745791Speter return (ENXIO); 10845791Speter device_set_desc(dev, desc); 10914258Sgibbs 11045791Speter port = (eisa_get_slot(dev) * EISA_SLOT_SIZE); 11145791Speter iobase = port + EP_EISA_SLOT_OFFSET; 11214258Sgibbs 11345791Speter /* We must be in EISA configuration mode */ 11445791Speter if ((inw(iobase + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f) 115132518Simp return (ENXIO); 11614258Sgibbs 117112845Smdodd eisa_add_iospace(dev, iobase, EP_EISA_IOSIZE, RESVADDR_NONE); 118112845Smdodd eisa_add_iospace(dev, port, EP_IOSIZE, RESVADDR_NONE); 11914258Sgibbs 12045791Speter conf = inw(iobase + EISA_IOCONF); 12145791Speter /* Determine our IRQ */ 12245791Speter switch (conf & IRQ_CHANNEL) { 12345791Speter case INT_3: 124117700Smarkm irq = 3; 125117700Smarkm break; 12645791Speter case INT_5: 127117700Smarkm irq = 5; 128117700Smarkm break; 12945791Speter case INT_7: 130117700Smarkm irq = 7; 131117700Smarkm break; 13245791Speter case INT_9: 133117700Smarkm irq = 9; 134117700Smarkm break; 13545791Speter case INT_10: 136117700Smarkm irq = 10; 137117700Smarkm break; 13845791Speter case INT_11: 139117700Smarkm irq = 11; 140117700Smarkm break; 14145791Speter case INT_12: 142117700Smarkm irq = 12; 143117700Smarkm break; 14445791Speter case INT_15: 145117700Smarkm irq = 15; 146117700Smarkm break; 14745791Speter default: 148117700Smarkm /* Disabled */ 149117700Smarkm printf("ep: 3COM Network Adapter at " 150117700Smarkm "slot %d has its IRQ disabled. " 151117700Smarkm "Probe failed.\n", 152117700Smarkm eisa_get_slot(dev)); 153117700Smarkm return (ENXIO); 15414258Sgibbs } 15545791Speter 156117700Smarkm switch (eisa_get_id(dev)) { 157117700Smarkm case EISA_DEVICE_ID_3COM_3C579_BNC: 158117700Smarkm case EISA_DEVICE_ID_3COM_3C579_TP: 159117700Smarkm int_trig = EISA_TRIGGER_LEVEL; 160117700Smarkm break; 161117700Smarkm default: 162117700Smarkm int_trig = EISA_TRIGGER_EDGE; 163117700Smarkm break; 16452549Smdodd } 165117700Smarkm 166112845Smdodd eisa_add_intr(dev, irq, int_trig); 16752549Smdodd 168117700Smarkm return (0); 16914258Sgibbs} 17014258Sgibbs 17114258Sgibbsstatic int 17245791Speterep_eisa_attach(device_t dev) 17314258Sgibbs{ 174117700Smarkm struct ep_softc *sc = device_get_softc(dev); 175117700Smarkm struct resource *eisa_io = NULL; 176140523Simp uint32_t eisa_iobase; 177117700Smarkm int irq; 178117700Smarkm int error = 0; 179117700Smarkm int rid; 18014258Sgibbs 18145791Speter rid = 1; 182127135Snjl eisa_io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 18345791Speter if (!eisa_io) { 18445791Speter device_printf(dev, "No I/O space?!\n"); 18552549Smdodd error = ENXIO; 18645791Speter goto bad; 18745791Speter } 18852549Smdodd eisa_iobase = rman_get_start(eisa_io); 18914258Sgibbs 19052549Smdodd /* Reset and Enable the card */ 19152549Smdodd outb(eisa_iobase + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER); 192117700Smarkm DELAY(1000); /* we must wait at least 1 ms */ 19352549Smdodd outb(eisa_iobase + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER); 19452549Smdodd /* Now the registers are availible through the lower ioport */ 19514258Sgibbs 19652549Smdodd if ((error = ep_alloc(dev))) { 19752549Smdodd device_printf(dev, "ep_alloc() failed! (%d)\n", error); 19845791Speter goto bad; 19952549Smdodd } 200117700Smarkm switch (eisa_get_id(dev)) { 201117700Smarkm case EISA_DEVICE_ID_3COM_3C579_BNC: 202117700Smarkm case EISA_DEVICE_ID_3COM_3C579_TP: 203117700Smarkm sc->stat = F_ACCESS_32_BITS; 204117700Smarkm break; 20514258Sgibbs } 20614258Sgibbs 20752549Smdodd ep_get_media(sc); 20814258Sgibbs 20952549Smdodd irq = rman_get_start(sc->irq); 21052549Smdodd if (irq == 9) 21152549Smdodd irq = 2; 21214258Sgibbs 213121588Simp GO_WINDOW(sc, 0); 214121225Sbms SET_IRQ(sc, irq); 21514258Sgibbs 21652549Smdodd if ((error = ep_attach(sc))) { 21752549Smdodd device_printf(dev, "ep_attach() failed! (%d)\n", error); 21852549Smdodd goto bad; 21952549Smdodd } 220166901Spiso if ((error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, 221166901Spiso NULL, ep_intr, sc, &sc->ep_intrhand))) { 22252549Smdodd device_printf(dev, "bus_setup_intr() failed! (%d)\n", error); 22352549Smdodd goto bad; 22452549Smdodd } 22552549Smdodd return (0); 22614258Sgibbs 227117700Smarkmbad: 22845791Speter if (eisa_io) 22945791Speter bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io); 23052549Smdodd 23152549Smdodd ep_free(dev); 23252549Smdodd return (error); 23314258Sgibbs} 23414258Sgibbs 23545791Speterstatic device_method_t ep_eisa_methods[] = { 23645791Speter /* Device interface */ 237117700Smarkm DEVMETHOD(device_probe, ep_eisa_probe), 238117700Smarkm DEVMETHOD(device_attach, ep_eisa_attach), 239117700Smarkm DEVMETHOD(device_detach, ep_detach), 24045791Speter 241117700Smarkm {0, 0} 24245791Speter}; 24345791Speter 24445791Speterstatic driver_t ep_eisa_driver = { 24545791Speter "ep", 24645791Speter ep_eisa_methods, 24752549Smdodd sizeof(struct ep_softc), 24845791Speter}; 24945791Speter 25052472Simpextern devclass_t ep_devclass; 25145791Speter 25245791SpeterDRIVER_MODULE(ep, eisa, ep_eisa_driver, ep_devclass, 0, 0); 253