if_ep_eisa.c revision 119418
1/* 2 * Product specific probe and attach routines for: 3 * 3COM 3C579 and 3C509(in eisa config mode) ethernet controllers 4 * 5 * Copyright (c) 1996 Justin T. Gibbs 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice immediately at the beginning of the file, without modification, 13 * this list of conditions, and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Absolutely no warranty of function or purpose is made by the author 18 * Justin T. Gibbs. 19 * 4. Modifications may be freely made to this file if the above conditions 20 * are met. 21 */ 22 23#include <sys/cdefs.h> 24__FBSDID("$FreeBSD: head/sys/dev/ep/if_ep_eisa.c 119418 2003-08-24 17:55:58Z obrien $"); 25 26#include <sys/cdefs.h> 27__FBSDID("$FreeBSD: head/sys/dev/ep/if_ep_eisa.c 119418 2003-08-24 17:55:58Z obrien $"); 28 29#include <sys/param.h> 30#include <sys/systm.h> 31#include <sys/kernel.h> 32#include <sys/socket.h> 33#include <sys/module.h> 34#include <sys/bus.h> 35 36#include <machine/bus.h> 37#include <machine/resource.h> 38#include <sys/rman.h> 39 40#include <net/if.h> 41#include <net/if_arp.h> 42#include <net/if_media.h> 43 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(dev, SYS_RES_IOPORT, &rid, 186 0, ~0, 1, RF_ACTIVE); 187 if (!eisa_io) { 188 device_printf(dev, "No I/O space?!\n"); 189 error = ENXIO; 190 goto bad; 191 } 192 eisa_iobase = rman_get_start(eisa_io); 193 194 /* Reset and Enable the card */ 195 outb(eisa_iobase + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER); 196 DELAY(1000); /* we must wait at least 1 ms */ 197 outb(eisa_iobase + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER); 198 /* Now the registers are availible through the lower ioport */ 199 200 if ((error = ep_alloc(dev))) { 201 device_printf(dev, "ep_alloc() failed! (%d)\n", error); 202 goto bad; 203 } 204 switch (eisa_get_id(dev)) { 205 case EISA_DEVICE_ID_3COM_3C579_BNC: 206 case EISA_DEVICE_ID_3COM_3C579_TP: 207 sc->stat = F_ACCESS_32_BITS; 208 break; 209 } 210 211 ep_get_media(sc); 212 213 irq = rman_get_start(sc->irq); 214 if (irq == 9) 215 irq = 2; 216 217 GO_WINDOW(0); 218 SET_IRQ(BASE, irq); 219 220 if ((error = ep_attach(sc))) { 221 device_printf(dev, "ep_attach() failed! (%d)\n", error); 222 goto bad; 223 } 224 if ((error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, ep_intr, 225 sc, &sc->ep_intrhand))) { 226 device_printf(dev, "bus_setup_intr() failed! (%d)\n", error); 227 goto bad; 228 } 229 return (0); 230 231bad: 232 if (eisa_io) 233 bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io); 234 235 ep_free(dev); 236 return (error); 237} 238 239static device_method_t ep_eisa_methods[] = { 240 /* Device interface */ 241 DEVMETHOD(device_probe, ep_eisa_probe), 242 DEVMETHOD(device_attach, ep_eisa_attach), 243 DEVMETHOD(device_detach, ep_detach), 244 245 {0, 0} 246}; 247 248static driver_t ep_eisa_driver = { 249 "ep", 250 ep_eisa_methods, 251 sizeof(struct ep_softc), 252}; 253 254extern devclass_t ep_devclass; 255 256DRIVER_MODULE(ep, eisa, ep_eisa_driver, ep_devclass, 0, 0); 257