if_ep_eisa.c revision 18892
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 * $Id: 3c5x9.c,v 1.6 1996/10/12 17:34:25 bde Exp $ 23 */ 24 25#include "eisa.h" 26#if NEISA > 0 27 28#include <sys/param.h> 29#include <sys/systm.h> 30#include <sys/kernel.h> 31#include <sys/socket.h> 32 33#include <machine/clock.h> 34 35#include <net/if.h> 36 37#include <netinet/in.h> 38#include <netinet/if_ether.h> 39 40#include <i386/isa/if_epreg.h> 41#include <i386/eisa/eisaconf.h> 42 43#define EISA_DEVICE_ID_3COM_3C509_TP 0x506d5090 44#define EISA_DEVICE_ID_3COM_3C509_BNC 0x506d5091 45#define EISA_DEVICE_ID_3COM_3C579_TP 0x506d5092 46#define EISA_DEVICE_ID_3COM_3C579_BNC 0x506d5093 47#define EISA_DEVICE_ID_3COM_3C509_COMBO 0x506d5094 48#define EISA_DEVICE_ID_3COM_3C509_TPO 0x506d5095 49 50#define EP_EISA_SLOT_OFFSET 0x0c80 51#define EP_EISA_IOSIZE 0x000a 52 53#define EISA_IOCONF 0x0008 54#define IRQ_CHANNEL 0xf000 55#define INT_3 0x3000 56#define INT_5 0x5000 57#define INT_7 0x7000 58#define INT_9 0x9000 59#define INT_10 0xa000 60#define INT_11 0xb000 61#define INT_12 0xc000 62#define INT_15 0xf000 63#define EISA_BPROM_MEDIA_CONF 0x0006 64#define TRANS_TYPE 0xc000 65#define TRANS_TP 0x0000 66#define TRANS_AUI 0x4000 67#define TRANS_BNC 0xc000 68 69static int ep_eisa_probe __P((void)); 70static int ep_eisa_attach __P((struct eisa_device *e_dev)); 71 72static struct eisa_driver ep_eisa_driver = { 73 "ep", 74 ep_eisa_probe, 75 ep_eisa_attach, 76 /*shutdown*/NULL, 77 &ep_unit 78 }; 79 80DATA_SET (eisadriver_set, ep_eisa_driver); 81 82static char *ep_match __P((eisa_id_t type)); 83 84static char* 85ep_match(type) 86 eisa_id_t type; 87{ 88 switch(type) { 89 case EISA_DEVICE_ID_3COM_3C509_TP: 90 return "3Com 3C509-TP Network Adapter"; 91 break; 92 case EISA_DEVICE_ID_3COM_3C509_BNC: 93 return "3Com 3C509-BNC Network Adapter"; 94 break; 95 case EISA_DEVICE_ID_3COM_3C579_TP: 96 return "3Com 3C579-TP EISA Network Adapter"; 97 break; 98 case EISA_DEVICE_ID_3COM_3C579_BNC: 99 return "3Com 3C579-BNC EISA Network Adapter"; 100 break; 101 case EISA_DEVICE_ID_3COM_3C509_COMBO: 102 return "3Com 3C509-Combo Network Adapter"; 103 break; 104 case EISA_DEVICE_ID_3COM_3C509_TPO: 105 return "3Com 3C509-TPO Network Adapter"; 106 break; 107 default: 108 break; 109 } 110 return (NULL); 111} 112 113static int 114ep_eisa_probe(void) 115{ 116 u_long iobase; 117 struct eisa_device *e_dev = NULL; 118 int count; 119 120 count = 0; 121 while ((e_dev = eisa_match_dev(e_dev, ep_match))) { 122 u_short conf; 123 u_long port; 124 int irq; 125 126 port = (e_dev->ioconf.slot * EISA_SLOT_SIZE); 127 iobase = port + EP_EISA_SLOT_OFFSET; 128 129 /* We must be in EISA configuration mode */ 130 if ((inw(iobase + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f) 131 continue; 132 133 eisa_add_iospace(e_dev, iobase, EP_EISA_IOSIZE, RESVADDR_NONE); 134 eisa_add_iospace(e_dev, port, EP_IOSIZE, RESVADDR_NONE); 135 136 conf = inw(iobase + EISA_IOCONF); 137 /* Determine our IRQ */ 138 switch (conf & IRQ_CHANNEL) { 139 case INT_3: 140 irq = 3; 141 break; 142 case INT_5: 143 irq = 5; 144 break; 145 case INT_7: 146 irq = 7; 147 break; 148 case INT_9: 149 irq = 9; 150 break; 151 case INT_10: 152 irq = 10; 153 break; 154 case INT_11: 155 irq = 11; 156 break; 157 case INT_12: 158 irq = 12; 159 break; 160 case INT_15: 161 irq = 15; 162 break; 163 default: 164 /* Disabled */ 165 printf("ep: 3COM Network Adapter at " 166 "slot %d has its IRQ disabled. " 167 "Probe failed.\n", 168 e_dev->ioconf.slot); 169 continue; 170 } 171 eisa_add_intr(e_dev, irq); 172 eisa_registerdev(e_dev, &ep_eisa_driver); 173 count++; 174 } 175 return count; 176} 177 178static int 179ep_eisa_attach(e_dev) 180 struct eisa_device *e_dev; 181{ 182 struct ep_softc *sc; 183 struct ep_board *epb; 184 int unit = e_dev->unit; 185 int irq = ffs(e_dev->ioconf.irq) - 1; 186 resvaddr_t *ioport; 187 resvaddr_t *eisa_ioport; 188 u_char level_intr; 189 int i; 190 191 /* 192 * The addresses are sorted in increasing order 193 * so we know the port to pass to the core ep 194 * driver comes first. 195 */ 196 ioport = e_dev->ioconf.ioaddrs.lh_first; 197 198 if(!ioport) 199 return -1; 200 201 eisa_ioport = ioport->links.le_next; 202 203 if(!eisa_ioport) 204 return -1; 205 206 eisa_reg_start(e_dev); 207 if(eisa_reg_iospace(e_dev, ioport)) 208 return -1; 209 210 if(eisa_reg_iospace(e_dev, eisa_ioport)) 211 return -1; 212 213 epb = &ep_board[ep_boards]; 214 215 epb->epb_addr = ioport->addr; 216 epb->epb_used = 1; 217 218 if(!(sc = ep_alloc(unit, epb))) 219 return -1; 220 221 ep_boards++; 222 223 sc->stat = 0; 224 level_intr = FALSE; 225 switch(e_dev->id) { 226 case EISA_DEVICE_ID_3COM_3C509_TP: 227 sc->ep_connectors = UTP|AUI; 228 break; 229 case EISA_DEVICE_ID_3COM_3C509_BNC: 230 sc->ep_connectors = BNC|AUI; 231 break; 232 case EISA_DEVICE_ID_3COM_3C579_TP: 233 sc->ep_connectors = UTP|AUI; 234 sc->stat = F_ACCESS_32_BITS; 235 level_intr = TRUE; 236 break; 237 case EISA_DEVICE_ID_3COM_3C579_BNC: 238 sc->ep_connectors = BNC|AUI; 239 sc->stat = F_ACCESS_32_BITS; 240 level_intr = TRUE; 241 break; 242 case EISA_DEVICE_ID_3COM_3C509_COMBO: 243 sc->ep_connectors = UTP|BNC|AUI; 244 break; 245 case EISA_DEVICE_ID_3COM_3C509_TPO: 246 sc->ep_connectors = UTP; 247 break; 248 default: 249 break; 250 } 251 /* 252 * Set the eisa config selected media type 253 */ 254 sc->ep_connector = inw(eisa_ioport->addr + EISA_BPROM_MEDIA_CONF) 255 >> ACF_CONNECTOR_BITS; 256 257 if(eisa_reg_intr(e_dev, irq, ep_intr, (void *)sc, &net_imask, 258 /*shared ==*/level_intr)) { 259 ep_free(sc); 260 return -1; 261 } 262 eisa_reg_end(e_dev); 263 264 /* Reset and Enable the card */ 265 outb(eisa_ioport->addr + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER); 266 DELAY(1000); /* we must wait at least 1 ms */ 267 outb(eisa_ioport->addr + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER); 268 269 /* Now the registers are availible through the lower ioport */ 270 271 /* 272 * Retrieve our ethernet address 273 */ 274 GO_WINDOW(0); 275 for(i = 0; i < 3; i++) 276 sc->epb->eth_addr[i] = get_e(sc, i); 277 278 /* Even we get irq number from board, we should tell him.. 279 Otherwise we never get a H/W interrupt anymore...*/ 280 if ( irq == 9 ) 281 irq = 2; 282 SET_IRQ(eisa_ioport->addr, irq); 283 284 ep_attach(sc); 285 286 if(eisa_enable_intr(e_dev, irq)) { 287 ep_free(sc); 288 eisa_release_intr(e_dev, irq, ep_intr); 289 return -1; 290 } 291 292 return 0; 293} 294 295#endif /* NEISA > 0 */ 296