1/* 2 * Copyright (c) 1995, David Greenman 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * |
27 * $Id: if_ed.c,v 1.97 1996/04/23 18:36:54 nate Exp $ |
28 */ 29 30/* 31 * Device driver for National Semiconductor DS8390/WD83C690 based ethernet 32 * adapters. By David Greenman, 29-April-1993 33 * 34 * Currently supports the Western Digital/SMC 8003 and 8013 series, 35 * the SMC Elite Ultra (8216), the 3Com 3c503, the NE1000 and NE2000, --- 89 unchanged lines hidden (view full) --- 125 u_char rec_page_start; /* first page of RX ring-buffer */ 126 u_char rec_page_stop; /* last page of RX ring-buffer */ 127 u_char next_packet; /* pointer to next unread RX packet */ 128 struct kern_devconf kdc; /* kernel configuration database info */ 129}; 130 131static struct ed_softc ed_softc[NED]; 132 |
133static int ed_attach __P((struct ed_softc *, int, int)); 134static int ed_attach_isa __P((struct isa_device *)); 135 |
136static void ed_init __P((struct ifnet *)); 137static int ed_ioctl __P((struct ifnet *, int, caddr_t)); 138static int ed_probe __P((struct isa_device *)); 139static void ed_start __P((struct ifnet *)); 140static void ed_reset __P((struct ifnet *)); 141static void ed_watchdog __P((struct ifnet *)); 142 143static void ed_stop __P((struct ed_softc *)); 144static int ed_probe_generic8390 __P((struct ed_softc *)); 145static int ed_probe_WD80x3 __P((struct isa_device *)); 146static int ed_probe_3Com __P((struct isa_device *)); 147static int ed_probe_Novell __P((struct isa_device *)); |
148static int ed_probe_Novell_generic __P((struct ed_softc *, int, int, int)); 149 150#include "pci.h" 151#if NPCI > 0 152void *ed_attach_NE2000_pci __P((int, int)); 153#endif 154 155#include "crd.h" 156#if NCRD > 0 |
157static int ed_probe_pccard __P((struct isa_device *, u_char *)); |
158#endif |
159 160static void ds_getmcaf __P((struct ed_softc *, u_long *)); 161 162static void ed_get_packet(struct ed_softc *, char *, /* u_short */ int, int); 163 164static void ed_rint __P((struct ed_softc *)); 165static void ed_xmit __P((struct ed_softc *)); 166static char * ed_ring_copy __P((struct ed_softc *, char *, char *, --- 4 unchanged lines hidden (view full) --- 171static void ed_pio_writemem __P((struct ed_softc *, char *, 172 /* u_short */ int, /* u_short */ int)); 173static u_short ed_pio_write_mbufs __P((struct ed_softc *, struct mbuf *, 174 int)); 175 176static void ed_setrcr(struct ed_softc *); 177static u_long ds_crc(u_char *ep); 178 |
179#if NCRD > 0 180#include <sys/select.h> 181#include <pccard/card.h> 182#include <pccard/driver.h> 183#include <pccard/slot.h> 184 185/* 186 * PC-Card (PCMCIA) specific code. --- 44 unchanged lines hidden (view full) --- 231 return(ENODEV); 232 /* 233 * Probe the device. If a value is returned, the 234 * device was found at the location. 235 */ 236 sc->gone = 0; 237 if (ed_probe_pccard(&dp->isahd,dp->misc)==0) 238 return(ENXIO); |
239 if (ed_attach_isa(&dp->isahd)==0) |
240 return(ENXIO); 241 } 242 /* 243 * XXX TODO: 244 * If it was initialized before, the device structure 245 * should also be initialized. We should 246 * reset (and possibly restart) the hardware, but 247 * I am not sure of the best way to do this... --- 29 unchanged lines hidden (view full) --- 277 278/* 279 * card_intr - Shared interrupt called from 280 * front end of PC-Card handler. 281 */ 282static int 283card_intr(struct pccard_dev *dp) 284{ |
285 edintr_sc(&ed_softc[dp->isahd.id_unit]); |
286 return(1); 287} 288#endif /* NCRD > 0 */ 289 290struct isa_driver eddriver = { 291 ed_probe, |
292 ed_attach_isa, |
293 "ed", 294 1 /* We are ultra sensitive */ 295}; 296 297/* 298 * Interrupt conversion table for WD/SMC ASIC/83C584 299 * (IRQ* are defined in icu.h) 300 */ --- 788 unchanged lines hidden (view full) --- 1089 isa_dev->id_msize = memsize; 1090 return (ED_3COM_IO_PORTS); 1091} 1092 1093/* 1094 * Probe and vendor-specific initialization routine for NE1000/2000 boards 1095 */ 1096static int |
1097ed_probe_Novell_generic(sc, port, unit, flags) 1098 struct ed_softc *sc; 1099 int port; 1100 int unit; 1101 int flags; |
1102{ |
1103 u_int memsize, n; 1104 u_char romdata[16], tmp; 1105 static char test_pattern[32] = "THIS is A memory TEST pattern"; 1106 char test_buffer[32]; 1107 |
1108 sc->asic_addr = port + ED_NOVELL_ASIC_OFFSET; 1109 sc->nic_addr = port + ED_NOVELL_NIC_OFFSET; |
1110 1111 /* XXX - do Novell-specific probe here */ 1112 1113 /* Reset the board */ 1114#ifdef GWETHER 1115 outb(sc->asic_addr + ED_NOVELL_RESET, 0); 1116 DELAY(200); 1117#endif /* GWETHER */ --- 22 unchanged lines hidden (view full) --- 1140 1141 /* Make sure that we really have an 8390 based board */ 1142 if (!ed_probe_generic8390(sc)) 1143 return (0); 1144 1145 sc->vendor = ED_VENDOR_NOVELL; 1146 sc->mem_shared = 0; 1147 sc->cr_proto = ED_CR_RD2; |
1148 1149 /* 1150 * Test the ability to read and write to the NIC memory. This has the 1151 * side affect of determining if this is an NE1000 or an NE2000. 1152 */ 1153 1154 /* 1155 * This prevents packets from being stored in the NIC memory when the --- 86 unchanged lines hidden (view full) --- 1242 mstart = x * ED_PAGE_SIZE; 1243 msize = ED_PAGE_SIZE; 1244 break; 1245 } 1246 } 1247 } 1248 1249 if (mstart == 0) { |
1250 printf("ed%d: Cannot find start of RAM.\n", unit); |
1251 return 0; 1252 } 1253 /* Search for the start of RAM. */ 1254 for (x = (mstart / ED_PAGE_SIZE) + 1; x < 256; x++) { 1255 ed_pio_readmem(sc, x * 256, tbuf, ED_PAGE_SIZE); 1256 if (bcmp(pbuf0, tbuf, ED_PAGE_SIZE) == 0) { 1257 for (i = 0; i < ED_PAGE_SIZE; i++) 1258 pbuf[i] = 255 - x; --- 5 unchanged lines hidden (view full) --- 1264 break; 1265 } 1266 } else { 1267 break; 1268 } 1269 } 1270 1271 if (msize == 0) { |
1272 printf("ed%d: Cannot find any RAM, start : %d, x = %d.\n", unit, mstart, x); |
1273 return 0; 1274 } |
1275 printf("ed%d: RAM start at %d, size : %d.\n", unit, mstart, msize); |
1276 1277 sc->mem_size = msize; 1278 sc->mem_start = (char *) mstart; 1279 sc->mem_end = (char *) (msize + mstart); 1280 sc->tx_page_start = mstart / ED_PAGE_SIZE; 1281 } 1282#endif /* GWETHER */ 1283 1284 /* 1285 * Use one xmit buffer if < 16k, two buffers otherwise (if not told 1286 * otherwise). 1287 */ |
1288 if ((memsize < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) |
1289 sc->txb_cnt = 1; 1290 else 1291 sc->txb_cnt = 2; 1292 1293 sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE; 1294 sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE; 1295 1296 sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE; --- 10 unchanged lines hidden (view full) --- 1307#endif /* GWETHER */ 1308 1309 /* clear any pending interrupts that might have occurred above */ 1310 outb(sc->nic_addr + ED_P0_ISR, 0xff); 1311 1312 return (ED_NOVELL_IO_PORTS); 1313} 1314 |
1315static int 1316ed_probe_Novell(isa_dev) 1317 struct isa_device *isa_dev; 1318{ 1319 struct ed_softc *sc = &ed_softc[isa_dev->id_unit]; |
1320 |
1321 isa_dev->id_maddr = 0; 1322 return ed_probe_Novell_generic(sc, isa_dev->id_iobase, 1323 isa_dev->id_unit, isa_dev->id_flags); 1324} 1325 1326#if NCRD > 0 1327 |
1328/* 1329 * Probe and vendor-specific initialization routine for PCCARDs 1330 */ 1331static int 1332ed_probe_pccard(isa_dev, ether) 1333 struct isa_device *isa_dev; 1334 u_char *ether; 1335{ --- 92 unchanged lines hidden (view full) --- 1428 } 1429 1430 /* clear any pending interupts that we may have caused */ 1431 outb(sc->nic_addr + ED_P0_ISR, 0xff); 1432 1433 return (ED_PC_IO_PORTS); 1434} 1435 |
1436#endif /* NCRD > 0 */ 1437 |
1438/* 1439 * Install interface into kernel networking data structures 1440 */ 1441static int |
1442ed_attach(sc, unit, flags) 1443 struct ed_softc *sc; 1444 int unit; 1445 int flags; |
1446{ |
1447 struct ifnet *ifp = &sc->arpcom.ac_if; 1448 1449 /* 1450 * Set interface to stopped condition (reset) 1451 */ 1452 ed_stop(sc); 1453 1454 if (!ifp->if_name) { 1455 /* 1456 * Initialize ifnet structure 1457 */ 1458 ifp->if_softc = sc; |
1459 ifp->if_unit = unit; |
1460 ifp->if_name = "ed"; 1461 ifp->if_output = ether_output; 1462 ifp->if_start = ed_start; 1463 ifp->if_ioctl = ed_ioctl; 1464 ifp->if_watchdog = ed_watchdog; 1465 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 1466 1467 /* 1468 * Set default state for ALTPHYS flag (used to disable the 1469 * tranceiver for AUI operation), based on compile-time 1470 * config option. 1471 */ |
1472 if (flags & ED_FLAGS_DISABLE_TRANCEIVER) |
1473 ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | 1474 IFF_MULTICAST | IFF_ALTPHYS); 1475 else 1476 ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | 1477 IFF_MULTICAST); 1478 1479 /* 1480 * Attach the interface 1481 */ 1482 if_attach(ifp); 1483 ether_ifattach(ifp); 1484 } 1485 /* device attach does transition from UNCONFIGURED to IDLE state */ 1486 sc->kdc.kdc_state = DC_IDLE; 1487 1488 /* 1489 * Print additional info when attached 1490 */ |
1491 printf("%s%d: address %6D, ", ifp->if_name, ifp->if_unit, |
1492 sc->arpcom.ac_enaddr, ":"); 1493 1494 if (sc->type_str && (*sc->type_str != 0)) 1495 printf("type %s ", sc->type_str); 1496 else 1497 printf("type unknown (0x%x) ", sc->type); 1498 1499 printf("%s ", sc->isa16bit ? "(16 bit)" : "(8 bit)"); --- 5 unchanged lines hidden (view full) --- 1505 * If BPF is in the kernel, call the attach for it 1506 */ 1507#if NBPFILTER > 0 1508 bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); 1509#endif 1510 return 1; 1511} 1512 |
1513static int 1514ed_attach_isa(isa_dev) 1515 struct isa_device *isa_dev; 1516{ 1517 int unit = isa_dev->id_unit; 1518 struct ed_softc *sc = &ed_softc[unit]; 1519 int flags = isa_dev->id_flags; 1520 1521 return ed_attach(sc, unit, flags); 1522} 1523 1524#if NPCI > 0 1525void * 1526ed_attach_NE2000_pci(unit, port) 1527 int unit; 1528 int port; 1529{ 1530 struct ed_softc *sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); 1531 int isa_flags = 0; 1532 1533 if (!sc) 1534 return sc; 1535 1536 if (ed_probe_Novell_generic(sc, port, unit, isa_flags) == 0 1537 || ed_attach(sc, unit, isa_flags) == 0) { 1538 free(sc, M_DEVBUF); 1539 return NULL; 1540 } 1541 return sc; 1542} 1543#endif 1544 |
1545/* 1546 * Reset interface. 1547 */ 1548static void 1549ed_reset(ifp) 1550 struct ifnet *ifp; 1551{ 1552 struct ed_softc *sc = ifp->if_softc; --- 541 unchanged lines hidden (view full) --- 2094 outb(sc->nic_addr + ED_P0_CR, sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STA); 2095 } 2096} 2097 2098/* 2099 * Ethernet interface interrupt processor 2100 */ 2101void |
2102edintr_sc(sc) 2103 struct ed_softc *sc; |
2104{ |
2105 struct ifnet *ifp = (struct ifnet *)sc; 2106 u_char isr; 2107 2108 if (sc->gone) 2109 return; 2110 /* 2111 * Set NIC to page 0 registers 2112 */ --- 189 unchanged lines hidden (view full) --- 2302 if (isr & ED_ISR_CNT) { 2303 (void) inb(sc->nic_addr + ED_P0_CNTR0); 2304 (void) inb(sc->nic_addr + ED_P0_CNTR1); 2305 (void) inb(sc->nic_addr + ED_P0_CNTR2); 2306 } 2307 } 2308} 2309 |
2310void 2311edintr(unit) 2312 int unit; 2313{ 2314 edintr_sc (&ed_softc[unit]); 2315} 2316 |
2317/* 2318 * Process an ioctl request. This code needs some work - it looks 2319 * pretty ugly. 2320 */ 2321static int 2322ed_ioctl(ifp, command, data) 2323 register struct ifnet *ifp; 2324 int command; --- 618 unchanged lines hidden --- |