if_ep_eisa.c revision 127135
1153838Sdfr/* 2153838Sdfr * Product specific probe and attach routines for: 3153838Sdfr * 3COM 3C579 and 3C509(in eisa config mode) ethernet controllers 4153838Sdfr * 5153838Sdfr * Copyright (c) 1996 Justin T. Gibbs 6153838Sdfr * All rights reserved. 7153838Sdfr * 8153838Sdfr * Redistribution and use in source and binary forms, with or without 9153838Sdfr * modification, are permitted provided that the following conditions 10153838Sdfr * are met: 11153838Sdfr * 1. Redistributions of source code must retain the above copyright 12153838Sdfr * notice immediately at the beginning of the file, without modification, 13153838Sdfr * this list of conditions, and the following disclaimer. 14153838Sdfr * 2. Redistributions in binary form must reproduce the above copyright 15153838Sdfr * notice, this list of conditions and the following disclaimer in the 16153838Sdfr * documentation and/or other materials provided with the distribution. 17153838Sdfr * 3. Absolutely no warranty of function or purpose is made by the author 18153838Sdfr * Justin T. Gibbs. 19153838Sdfr * 4. Modifications may be freely made to this file if the above conditions 20153838Sdfr * are met. 21153838Sdfr */ 22153838Sdfr 23153838Sdfr#include <sys/cdefs.h> 24153838Sdfr__FBSDID("$FreeBSD: head/sys/dev/ep/if_ep_eisa.c 127135 2004-03-17 17:50:55Z njl $"); 25153838Sdfr 26153838Sdfr#include <sys/cdefs.h> 27153838Sdfr__FBSDID("$FreeBSD: head/sys/dev/ep/if_ep_eisa.c 127135 2004-03-17 17:50:55Z njl $"); 28153838Sdfr 29153838Sdfr#include <sys/param.h> 30153838Sdfr#include <sys/systm.h> 31153838Sdfr#include <sys/kernel.h> 32153838Sdfr#include <sys/socket.h> 33153838Sdfr#include <sys/module.h> 34153838Sdfr#include <sys/bus.h> 35153838Sdfr 36153838Sdfr#include <machine/bus.h> 37153838Sdfr#include <machine/resource.h> 38153838Sdfr#include <sys/rman.h> 39153838Sdfr 40153838Sdfr#include <net/if.h> 41153838Sdfr#include <net/if_arp.h> 42153838Sdfr#include <net/if_media.h> 43153838Sdfr 44#include <dev/eisa/eisaconf.h> 45 46#include <dev/ep/if_epreg.h> 47#include <dev/ep/if_epvar.h> 48 49#define EISA_DEVICE_ID_3COM_3C509_TP 0x506d5090 50#define EISA_DEVICE_ID_3COM_3C509_BNC 0x506d5091 51#define EISA_DEVICE_ID_3COM_3C579_TP 0x506d5092 52#define EISA_DEVICE_ID_3COM_3C579_BNC 0x506d5093 53#define EISA_DEVICE_ID_3COM_3C509_COMBO 0x506d5094 54#define EISA_DEVICE_ID_3COM_3C509_TPO 0x506d5095 55 56#define EP_EISA_SLOT_OFFSET 0x0c80 57#define EP_EISA_IOSIZE 0x000a 58 59#define EISA_IOCONF 0x0008 60#define IRQ_CHANNEL 0xf000 61#define INT_3 0x3000 62#define INT_5 0x5000 63#define INT_7 0x7000 64#define INT_9 0x9000 65#define INT_10 0xa000 66#define INT_11 0xb000 67#define INT_12 0xc000 68#define INT_15 0xf000 69#define EISA_BPROM_MEDIA_CONF 0x0006 70#define TRANS_TYPE 0xc000 71#define TRANS_TP 0x0000 72#define TRANS_AUI 0x4000 73#define TRANS_BNC 0xc000 74 75static const char *ep_match(eisa_id_t type); 76 77static const char * 78ep_match(eisa_id_t type) 79{ 80 switch (type) { 81 case EISA_DEVICE_ID_3COM_3C509_TP: 82 return ("3Com 3C509-TP Network Adapter"); 83 case EISA_DEVICE_ID_3COM_3C509_BNC: 84 return ("3Com 3C509-BNC Network Adapter"); 85 case EISA_DEVICE_ID_3COM_3C579_TP: 86 return ("3Com 3C579-TP EISA Network Adapter"); 87 case EISA_DEVICE_ID_3COM_3C579_BNC: 88 return ("3Com 3C579-BNC EISA Network Adapter"); 89 case EISA_DEVICE_ID_3COM_3C509_COMBO: 90 return ("3Com 3C509-Combo Network Adapter"); 91 case EISA_DEVICE_ID_3COM_3C509_TPO: 92 return ("3Com 3C509-TPO Network Adapter"); 93 default: 94 return (NULL); 95 } 96} 97 98static int 99ep_eisa_probe(device_t dev) 100{ 101 const char *desc; 102 u_long iobase; 103 u_short conf; 104 u_long port; 105 int irq; 106 int int_trig; 107 108 desc = ep_match(eisa_get_id(dev)); 109 if (!desc) 110 return (ENXIO); 111 device_set_desc(dev, desc); 112 113 port = (eisa_get_slot(dev) * EISA_SLOT_SIZE); 114 iobase = port + EP_EISA_SLOT_OFFSET; 115 116 /* We must be in EISA configuration mode */ 117 if ((inw(iobase + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f) 118 return ENXIO; 119 120 eisa_add_iospace(dev, iobase, EP_EISA_IOSIZE, RESVADDR_NONE); 121 eisa_add_iospace(dev, port, EP_IOSIZE, RESVADDR_NONE); 122 123 conf = inw(iobase + EISA_IOCONF); 124 /* Determine our IRQ */ 125 switch (conf & IRQ_CHANNEL) { 126 case INT_3: 127 irq = 3; 128 break; 129 case INT_5: 130 irq = 5; 131 break; 132 case INT_7: 133 irq = 7; 134 break; 135 case INT_9: 136 irq = 9; 137 break; 138 case INT_10: 139 irq = 10; 140 break; 141 case INT_11: 142 irq = 11; 143 break; 144 case INT_12: 145 irq = 12; 146 break; 147 case INT_15: 148 irq = 15; 149 break; 150 default: 151 /* Disabled */ 152 printf("ep: 3COM Network Adapter at " 153 "slot %d has its IRQ disabled. " 154 "Probe failed.\n", 155 eisa_get_slot(dev)); 156 return (ENXIO); 157 } 158 159 switch (eisa_get_id(dev)) { 160 case EISA_DEVICE_ID_3COM_3C579_BNC: 161 case EISA_DEVICE_ID_3COM_3C579_TP: 162 int_trig = EISA_TRIGGER_LEVEL; 163 break; 164 default: 165 int_trig = EISA_TRIGGER_EDGE; 166 break; 167 } 168 169 eisa_add_intr(dev, irq, int_trig); 170 171 return (0); 172} 173 174static int 175ep_eisa_attach(device_t dev) 176{ 177 struct ep_softc *sc = device_get_softc(dev); 178 struct resource *eisa_io = NULL; 179 u_int32_t eisa_iobase; 180 int irq; 181 int error = 0; 182 int rid; 183 184 rid = 1; 185 eisa_io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 186 if (!eisa_io) { 187 device_printf(dev, "No I/O space?!\n"); 188 error = ENXIO; 189 goto bad; 190 } 191 eisa_iobase = rman_get_start(eisa_io); 192 193 /* Reset and Enable the card */ 194 outb(eisa_iobase + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER); 195 DELAY(1000); /* we must wait at least 1 ms */ 196 outb(eisa_iobase + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER); 197 /* Now the registers are availible through the lower ioport */ 198 199 if ((error = ep_alloc(dev))) { 200 device_printf(dev, "ep_alloc() failed! (%d)\n", error); 201 goto bad; 202 } 203 switch (eisa_get_id(dev)) { 204 case EISA_DEVICE_ID_3COM_3C579_BNC: 205 case EISA_DEVICE_ID_3COM_3C579_TP: 206 sc->stat = F_ACCESS_32_BITS; 207 break; 208 } 209 210 ep_get_media(sc); 211 212 irq = rman_get_start(sc->irq); 213 if (irq == 9) 214 irq = 2; 215 216 GO_WINDOW(sc, 0); 217 SET_IRQ(sc, irq); 218 219 if ((error = ep_attach(sc))) { 220 device_printf(dev, "ep_attach() failed! (%d)\n", error); 221 goto bad; 222 } 223 if ((error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, ep_intr, 224 sc, &sc->ep_intrhand))) { 225 device_printf(dev, "bus_setup_intr() failed! (%d)\n", error); 226 goto bad; 227 } 228 return (0); 229 230bad: 231 if (eisa_io) 232 bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io); 233 234 ep_free(dev); 235 return (error); 236} 237 238static device_method_t ep_eisa_methods[] = { 239 /* Device interface */ 240 DEVMETHOD(device_probe, ep_eisa_probe), 241 DEVMETHOD(device_attach, ep_eisa_attach), 242 DEVMETHOD(device_detach, ep_detach), 243 244 {0, 0} 245}; 246 247static driver_t ep_eisa_driver = { 248 "ep", 249 ep_eisa_methods, 250 sizeof(struct ep_softc), 251}; 252 253extern devclass_t ep_devclass; 254 255DRIVER_MODULE(ep, eisa, ep_eisa_driver, ep_devclass, 0, 0); 256