| 1 |
199 |
simons |
/* 8390.c: A general NS8390 ethernet driver core for linux. */
|
| 2 |
|
|
/*
|
| 3 |
|
|
Written 1992-94 by Donald Becker.
|
| 4 |
|
|
|
| 5 |
|
|
Copyright 1993 United States Government as represented by the
|
| 6 |
|
|
Director, National Security Agency.
|
| 7 |
|
|
|
| 8 |
|
|
This software may be used and distributed according to the terms
|
| 9 |
|
|
of the GNU Public License, incorporated herein by reference.
|
| 10 |
|
|
|
| 11 |
|
|
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
|
| 12 |
|
|
Center of Excellence in Space Data and Information Sciences
|
| 13 |
|
|
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
|
| 14 |
|
|
|
| 15 |
|
|
This is the chip-specific code for many 8390-based ethernet adaptors.
|
| 16 |
|
|
This is not a complete driver, it must be combined with board-specific
|
| 17 |
|
|
code such as ne.c, wd.c, 3c503.c, etc.
|
| 18 |
|
|
|
| 19 |
|
|
Seeing how at least eight drivers use this code, (not counting the
|
| 20 |
|
|
PCMCIA ones either) it is easy to break some card by what seems like
|
| 21 |
|
|
a simple innocent change. Please contact me or Donald if you think
|
| 22 |
|
|
you have found something that needs changing. -- PG
|
| 23 |
|
|
|
| 24 |
|
|
|
| 25 |
|
|
Changelog:
|
| 26 |
|
|
|
| 27 |
|
|
Paul Gortmaker : remove set_bit lock, other cleanups.
|
| 28 |
|
|
Paul Gortmaker : add ei_get_8390_hdr() so we can pass skb's to
|
| 29 |
|
|
ei_block_input() for eth_io_copy_and_sum().
|
| 30 |
|
|
Paul Gortmaker : exchange static int ei_pingpong for a #define,
|
| 31 |
|
|
also add better Tx error handling.
|
| 32 |
|
|
Paul Gortmaker : rewrite Rx overrun handling as per NS specs.
|
| 33 |
|
|
|
| 34 |
|
|
Greg Ungerer : added some coldfire addressing code.
|
| 35 |
|
|
|
| 36 |
|
|
|
| 37 |
|
|
Sources:
|
| 38 |
|
|
The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
|
| 39 |
|
|
|
| 40 |
|
|
*/
|
| 41 |
|
|
|
| 42 |
|
|
static const char *version =
|
| 43 |
|
|
"8390.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
|
| 44 |
|
|
|
| 45 |
|
|
#include <linux/module.h>
|
| 46 |
|
|
#include <linux/kernel.h>
|
| 47 |
|
|
#include <linux/sched.h>
|
| 48 |
|
|
#include <linux/fs.h>
|
| 49 |
|
|
#include <linux/types.h>
|
| 50 |
|
|
#include <linux/ptrace.h>
|
| 51 |
|
|
#include <linux/string.h>
|
| 52 |
|
|
#include <asm/system.h>
|
| 53 |
|
|
#include <asm/segment.h>
|
| 54 |
|
|
#include <asm/bitops.h>
|
| 55 |
|
|
#include <asm/io.h>
|
| 56 |
|
|
#include <linux/errno.h>
|
| 57 |
|
|
#include <linux/fcntl.h>
|
| 58 |
|
|
#include <linux/in.h>
|
| 59 |
|
|
#include <linux/interrupt.h>
|
| 60 |
|
|
|
| 61 |
|
|
#include <linux/netdevice.h>
|
| 62 |
|
|
#include <linux/etherdevice.h>
|
| 63 |
|
|
|
| 64 |
|
|
#include "8390.h"
|
| 65 |
|
|
|
| 66 |
|
|
#ifdef CONFIG_COLDFIRE
|
| 67 |
|
|
#ifdef CONFIG_NETtel
|
| 68 |
|
|
#include <asm/nettel.h>
|
| 69 |
|
|
int ethernet_tick = 0;
|
| 70 |
|
|
#endif
|
| 71 |
|
|
#include <asm/mcfne.h>
|
| 72 |
|
|
#endif /* CONFIG_COLDFIRE */
|
| 73 |
|
|
|
| 74 |
|
|
#ifdef CONFIG_MCF_MPEGBOARD
|
| 75 |
|
|
#include <board/pport.h>
|
| 76 |
|
|
#include <asm/coldfire.h>
|
| 77 |
|
|
#endif
|
| 78 |
|
|
|
| 79 |
|
|
/* These are the operational function interfaces to board-specific
|
| 80 |
|
|
routines.
|
| 81 |
|
|
void reset_8390(struct device *dev)
|
| 82 |
|
|
Resets the board associated with DEV, including a hardware reset of
|
| 83 |
|
|
the 8390. This is only called when there is a transmit timeout, and
|
| 84 |
|
|
it is always followed by 8390_init().
|
| 85 |
|
|
void block_output(struct device *dev, int count, const unsigned char *buf,
|
| 86 |
|
|
int start_page)
|
| 87 |
|
|
Write the COUNT bytes of BUF to the packet buffer at START_PAGE. The
|
| 88 |
|
|
"page" value uses the 8390's 256-byte pages.
|
| 89 |
|
|
void get_8390_hdr(struct device *dev, struct e8390_hdr *hdr, int ring_page)
|
| 90 |
|
|
Read the 4 byte, page aligned 8390 header. *If* there is a
|
| 91 |
|
|
subsequent read, it will be of the rest of the packet.
|
| 92 |
|
|
void block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
|
| 93 |
|
|
Read COUNT bytes from the packet buffer into the skb data area. Start
|
| 94 |
|
|
reading from RING_OFFSET, the address as the 8390 sees it. This will always
|
| 95 |
|
|
follow the read of the 8390 header.
|
| 96 |
|
|
*/
|
| 97 |
|
|
#define ei_reset_8390 (ei_local->reset_8390)
|
| 98 |
|
|
#define ei_block_output (ei_local->block_output)
|
| 99 |
|
|
#define ei_block_input (ei_local->block_input)
|
| 100 |
|
|
#define ei_get_8390_hdr (ei_local->get_8390_hdr)
|
| 101 |
|
|
|
| 102 |
|
|
/* use 0 for production, 1 for verification, >2 for debug */
|
| 103 |
|
|
#ifdef EI_DEBUG
|
| 104 |
|
|
int ei_debug = EI_DEBUG;
|
| 105 |
|
|
#else
|
| 106 |
|
|
int ei_debug = 1;
|
| 107 |
|
|
#endif
|
| 108 |
|
|
|
| 109 |
|
|
/* Index to functions. */
|
| 110 |
|
|
static void ei_tx_intr(struct device *dev);
|
| 111 |
|
|
static void ei_tx_err(struct device *dev);
|
| 112 |
|
|
static void ei_receive(struct device *dev);
|
| 113 |
|
|
static void ei_rx_overrun(struct device *dev);
|
| 114 |
|
|
|
| 115 |
|
|
/* Routines generic to NS8390-based boards. */
|
| 116 |
|
|
static void NS8390_trigger_send(struct device *dev, unsigned int length,
|
| 117 |
|
|
int start_page);
|
| 118 |
|
|
static void set_multicast_list(struct device *dev);
|
| 119 |
|
|
|
| 120 |
|
|
|
| 121 |
|
|
/* Open/initialize the board. This routine goes all-out, setting everything
|
| 122 |
|
|
up anew at each open, even though many of these registers should only
|
| 123 |
|
|
need to be set once at boot.
|
| 124 |
|
|
*/
|
| 125 |
|
|
int ei_open(struct device *dev)
|
| 126 |
|
|
{
|
| 127 |
|
|
struct ei_device *ei_local = (struct ei_device *) dev->priv;
|
| 128 |
|
|
|
| 129 |
|
|
/* This can't happen unless somebody forgot to call ethdev_init(). */
|
| 130 |
|
|
if (ei_local == NULL) {
|
| 131 |
|
|
printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
|
| 132 |
|
|
return -ENXIO;
|
| 133 |
|
|
}
|
| 134 |
|
|
|
| 135 |
|
|
irq2dev_map[dev->irq] = dev;
|
| 136 |
|
|
NS8390_init(dev, 1);
|
| 137 |
|
|
dev->start = 1;
|
| 138 |
|
|
ei_local->irqlock = 0;
|
| 139 |
|
|
return 0;
|
| 140 |
|
|
}
|
| 141 |
|
|
|
| 142 |
|
|
/* Opposite of above. Only used when "ifconfig <devname> down" is done. */
|
| 143 |
|
|
int ei_close(struct device *dev)
|
| 144 |
|
|
{
|
| 145 |
|
|
NS8390_init(dev, 0);
|
| 146 |
|
|
dev->start = 0;
|
| 147 |
|
|
return 0;
|
| 148 |
|
|
}
|
| 149 |
|
|
|
| 150 |
|
|
static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
|
| 151 |
|
|
{
|
| 152 |
|
|
int e8390_base = dev->base_addr;
|
| 153 |
|
|
struct ei_device *ei_local = (struct ei_device *) dev->priv;
|
| 154 |
|
|
int length, send_length, output_page;
|
| 155 |
|
|
int i;
|
| 156 |
|
|
int flags;
|
| 157 |
|
|
/*
|
| 158 |
|
|
* We normally shouldn't be called if dev->tbusy is set, but the
|
| 159 |
|
|
* existing code does anyway. If it has been too long since the
|
| 160 |
|
|
* last Tx, we assume the board has died and kick it.
|
| 161 |
|
|
*/
|
| 162 |
|
|
|
| 163 |
|
|
if (dev->tbusy) { /* Do timeouts, just like the 8003 driver. */
|
| 164 |
|
|
int txsr = inb(e8390_base+EN0_TSR), isr;
|
| 165 |
|
|
int tickssofar = jiffies - dev->trans_start;
|
| 166 |
|
|
if (tickssofar < TX_TIMEOUT || (tickssofar < (TX_TIMEOUT+5) && ! (txsr & ENTSR_PTX))) {
|
| 167 |
|
|
return 1;
|
| 168 |
|
|
}
|
| 169 |
|
|
isr = inb(e8390_base+EN0_ISR);
|
| 170 |
|
|
if (dev->start == 0) {
|
| 171 |
|
|
printk("%s: xmit on stopped card\n", dev->name);
|
| 172 |
|
|
return 1;
|
| 173 |
|
|
}
|
| 174 |
|
|
|
| 175 |
|
|
/*
|
| 176 |
|
|
* Note that if the Tx posted a TX_ERR interrupt, then the
|
| 177 |
|
|
* error will have been handled from the interrupt handler.
|
| 178 |
|
|
* and not here.
|
| 179 |
|
|
*/
|
| 180 |
|
|
|
| 181 |
|
|
printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
|
| 182 |
|
|
dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
|
| 183 |
|
|
(isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
|
| 184 |
|
|
|
| 185 |
|
|
if (!isr && !ei_local->stat.tx_packets) {
|
| 186 |
|
|
/* The 8390 probably hasn't gotten on the cable yet. */
|
| 187 |
|
|
ei_local->interface_num ^= 1; /* Try a different xcvr. */
|
| 188 |
|
|
}
|
| 189 |
|
|
|
| 190 |
|
|
/* Try to restart the card. Perhaps the user has fixed something. */
|
| 191 |
|
|
ei_reset_8390(dev);
|
| 192 |
|
|
NS8390_init(dev, 1);
|
| 193 |
|
|
dev->trans_start = jiffies;
|
| 194 |
|
|
}
|
| 195 |
|
|
|
| 196 |
|
|
/* Sending a NULL skb means some higher layer thinks we've missed an
|
| 197 |
|
|
tx-done interrupt. Caution: dev_tint() handles the cli()/sti()
|
| 198 |
|
|
itself. */
|
| 199 |
|
|
if (skb == NULL) {
|
| 200 |
|
|
dev_tint(dev);
|
| 201 |
|
|
return 0;
|
| 202 |
|
|
}
|
| 203 |
|
|
|
| 204 |
|
|
length = skb->len;
|
| 205 |
|
|
if (skb->len <= 0)
|
| 206 |
|
|
return 0;
|
| 207 |
|
|
|
| 208 |
|
|
/* Mask interrupts from the ethercard. */
|
| 209 |
|
|
save_flags(flags);
|
| 210 |
|
|
cli();
|
| 211 |
|
|
outb_p(0x00, e8390_base + EN0_IMR);
|
| 212 |
|
|
restore_flags(flags);
|
| 213 |
|
|
if (dev->interrupt) {
|
| 214 |
|
|
printk("%s: Tx request while isr active.\n",dev->name);
|
| 215 |
|
|
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
|
| 216 |
|
|
return 1;
|
| 217 |
|
|
}
|
| 218 |
|
|
ei_local->irqlock = 1;
|
| 219 |
|
|
|
| 220 |
|
|
send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
|
| 221 |
|
|
|
| 222 |
|
|
#ifdef EI_PINGPONG
|
| 223 |
|
|
|
| 224 |
|
|
/*
|
| 225 |
|
|
* We have two Tx slots available for use. Find the first free
|
| 226 |
|
|
* slot, and then perform some sanity checks. With two Tx bufs,
|
| 227 |
|
|
* you get very close to transmitting back-to-back packets. With
|
| 228 |
|
|
* only one Tx buf, the transmitter sits idle while you reload the
|
| 229 |
|
|
* card, leaving a substantial gap between each transmitted packet.
|
| 230 |
|
|
*/
|
| 231 |
|
|
|
| 232 |
|
|
if (ei_local->tx1 == 0) {
|
| 233 |
|
|
output_page = ei_local->tx_start_page;
|
| 234 |
|
|
ei_local->tx1 = send_length;
|
| 235 |
|
|
if (ei_debug && ei_local->tx2 > 0)
|
| 236 |
|
|
printk("%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n",
|
| 237 |
|
|
dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing);
|
| 238 |
|
|
} else if (ei_local->tx2 == 0) {
|
| 239 |
|
|
output_page = ei_local->tx_start_page + TX_1X_PAGES;
|
| 240 |
|
|
ei_local->tx2 = send_length;
|
| 241 |
|
|
if (ei_debug && ei_local->tx1 > 0)
|
| 242 |
|
|
printk("%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
|
| 243 |
|
|
dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing);
|
| 244 |
|
|
} else { /* We should never get here. */
|
| 245 |
|
|
if (ei_debug)
|
| 246 |
|
|
printk("%s: No Tx buffers free! irq=%d tx1=%d tx2=%d last=%d\n",
|
| 247 |
|
|
dev->name, dev->interrupt, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
|
| 248 |
|
|
ei_local->irqlock = 0;
|
| 249 |
|
|
dev->tbusy = 1;
|
| 250 |
|
|
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
|
| 251 |
|
|
return 1;
|
| 252 |
|
|
}
|
| 253 |
|
|
|
| 254 |
|
|
/*
|
| 255 |
|
|
* Okay, now upload the packet and trigger a send if the transmitter
|
| 256 |
|
|
* isn't already sending. If it is busy, the interrupt handler will
|
| 257 |
|
|
* trigger the send later, upon receiving a Tx done interrupt.
|
| 258 |
|
|
*/
|
| 259 |
|
|
|
| 260 |
|
|
ei_block_output(dev, length, skb->data, output_page);
|
| 261 |
|
|
if (! ei_local->txing) {
|
| 262 |
|
|
ei_local->txing = 1;
|
| 263 |
|
|
NS8390_trigger_send(dev, send_length, output_page);
|
| 264 |
|
|
dev->trans_start = jiffies;
|
| 265 |
|
|
if (output_page == ei_local->tx_start_page) {
|
| 266 |
|
|
ei_local->tx1 = -1;
|
| 267 |
|
|
ei_local->lasttx = -1;
|
| 268 |
|
|
} else {
|
| 269 |
|
|
ei_local->tx2 = -1;
|
| 270 |
|
|
ei_local->lasttx = -2;
|
| 271 |
|
|
}
|
| 272 |
|
|
} else
|
| 273 |
|
|
ei_local->txqueue++;
|
| 274 |
|
|
|
| 275 |
|
|
dev->tbusy = (ei_local->tx1 && ei_local->tx2);
|
| 276 |
|
|
|
| 277 |
|
|
#else /* EI_PINGPONG */
|
| 278 |
|
|
|
| 279 |
|
|
/*
|
| 280 |
|
|
* Only one Tx buffer in use. You need two Tx bufs to come close to
|
| 281 |
|
|
* back-to-back transmits. Expect a 20 -> 25% performance hit on
|
| 282 |
|
|
* reasonable hardware if you only use one Tx buffer.
|
| 283 |
|
|
*/
|
| 284 |
|
|
|
| 285 |
|
|
ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
|
| 286 |
|
|
ei_local->txing = 1;
|
| 287 |
|
|
NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
|
| 288 |
|
|
dev->trans_start = jiffies;
|
| 289 |
|
|
dev->tbusy = 1;
|
| 290 |
|
|
|
| 291 |
|
|
#endif /* EI_PINGPONG */
|
| 292 |
|
|
|
| 293 |
|
|
/* Turn 8390 interrupts back on. */
|
| 294 |
|
|
ei_local->irqlock = 0;
|
| 295 |
|
|
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
|
| 296 |
|
|
#ifdef CONFIG_MCF_MPEGBOARD
|
| 297 |
|
|
if(!skb->send_control)
|
| 298 |
|
|
dev_kfree_skb (skb, FREE_WRITE);
|
| 299 |
|
|
else
|
| 300 |
|
|
skb_device_unlock(skb);
|
| 301 |
|
|
#else
|
| 302 |
|
|
dev_kfree_skb (skb, FREE_WRITE);
|
| 303 |
|
|
#endif
|
| 304 |
|
|
return 0;
|
| 305 |
|
|
}
|
| 306 |
|
|
|
| 307 |
|
|
/* The typical workload of the driver:
|
| 308 |
|
|
Handle the ether interface interrupts. */
|
| 309 |
|
|
void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
|
| 310 |
|
|
{
|
| 311 |
|
|
struct device *dev;
|
| 312 |
|
|
int e8390_base;
|
| 313 |
|
|
int interrupts, nr_serviced = 0;
|
| 314 |
|
|
struct ei_device *ei_local;
|
| 315 |
|
|
|
| 316 |
|
|
#ifdef CONFIG_COLDFIRE
|
| 317 |
|
|
dev = (struct device *)(irq2dev_map[NE2000_ISA_IRQ]);
|
| 318 |
|
|
#ifdef NETtel_LEDETH
|
| 319 |
|
|
setled(NETtel_LEDETH);
|
| 320 |
|
|
ethernet_tick = 4;
|
| 321 |
|
|
#endif
|
| 322 |
|
|
#else
|
| 323 |
|
|
dev = (struct device *)(irq2dev_map[irq]);
|
| 324 |
|
|
#endif
|
| 325 |
|
|
|
| 326 |
|
|
if (dev == NULL) {
|
| 327 |
|
|
printk ("net_interrupt(): irq %d for unknown device.\n", irq);
|
| 328 |
|
|
return;
|
| 329 |
|
|
}
|
| 330 |
|
|
e8390_base = dev->base_addr;
|
| 331 |
|
|
ei_local = (struct ei_device *) dev->priv;
|
| 332 |
|
|
if (dev->interrupt || ei_local->irqlock) {
|
| 333 |
|
|
/* The "irqlock" check is only for testing. */
|
| 334 |
|
|
printk(ei_local->irqlock
|
| 335 |
|
|
? "%s: Interrupted while interrupts are masked! isr=%#2x imr=%#2x.\n"
|
| 336 |
|
|
: "%s: Reentering the interrupt handler! isr=%#2x imr=%#2x.\n",
|
| 337 |
|
|
dev->name, inb_p(e8390_base + EN0_ISR),
|
| 338 |
|
|
inb_p(e8390_base + EN0_IMR));
|
| 339 |
|
|
return;
|
| 340 |
|
|
}
|
| 341 |
|
|
|
| 342 |
|
|
dev->interrupt = 1;
|
| 343 |
|
|
|
| 344 |
|
|
/* Change to page 0 and read the intr status reg. */
|
| 345 |
|
|
outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
|
| 346 |
|
|
if (ei_debug > 3)
|
| 347 |
|
|
printk("%s: interrupt(isr=%#2.2x).\n", dev->name,
|
| 348 |
|
|
inb_p(e8390_base + EN0_ISR));
|
| 349 |
|
|
|
| 350 |
|
|
/* !!Assumption!! -- we stay in page 0. Don't break this. */
|
| 351 |
|
|
while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0
|
| 352 |
|
|
&& ++nr_serviced < MAX_SERVICE) {
|
| 353 |
|
|
if (dev->start == 0) {
|
| 354 |
|
|
printk("%s: interrupt from stopped card\n", dev->name);
|
| 355 |
|
|
interrupts = 0;
|
| 356 |
|
|
break;
|
| 357 |
|
|
}
|
| 358 |
|
|
if (interrupts & ENISR_OVER) {
|
| 359 |
|
|
ei_rx_overrun(dev);
|
| 360 |
|
|
} else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) {
|
| 361 |
|
|
/* Got a good (?) packet. */
|
| 362 |
|
|
ei_receive(dev);
|
| 363 |
|
|
}
|
| 364 |
|
|
/* Push the next to-transmit packet through. */
|
| 365 |
|
|
if (interrupts & ENISR_TX) {
|
| 366 |
|
|
ei_tx_intr(dev);
|
| 367 |
|
|
} else if (interrupts & ENISR_TX_ERR) {
|
| 368 |
|
|
ei_tx_err(dev);
|
| 369 |
|
|
}
|
| 370 |
|
|
|
| 371 |
|
|
if (interrupts & ENISR_COUNTERS) {
|
| 372 |
|
|
ei_local->stat.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0);
|
| 373 |
|
|
ei_local->stat.rx_crc_errors += inb_p(e8390_base + EN0_COUNTER1);
|
| 374 |
|
|
ei_local->stat.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2);
|
| 375 |
|
|
outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */
|
| 376 |
|
|
}
|
| 377 |
|
|
|
| 378 |
|
|
/* Ignore any RDC interrupts that make it back to here. */
|
| 379 |
|
|
if (interrupts & ENISR_RDC) {
|
| 380 |
|
|
outb_p(ENISR_RDC, e8390_base + EN0_ISR);
|
| 381 |
|
|
}
|
| 382 |
|
|
|
| 383 |
|
|
outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
|
| 384 |
|
|
}
|
| 385 |
|
|
|
| 386 |
|
|
if (interrupts && ei_debug) {
|
| 387 |
|
|
outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
|
| 388 |
|
|
if (nr_serviced >= MAX_SERVICE) {
|
| 389 |
|
|
printk("%s: Too much work at interrupt, status %#2.2x\n",
|
| 390 |
|
|
dev->name, interrupts);
|
| 391 |
|
|
outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
|
| 392 |
|
|
} else {
|
| 393 |
|
|
printk("%s: unknown interrupt %#2x\n", dev->name, interrupts);
|
| 394 |
|
|
outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
|
| 395 |
|
|
}
|
| 396 |
|
|
}
|
| 397 |
|
|
dev->interrupt = 0;
|
| 398 |
|
|
return;
|
| 399 |
|
|
}
|
| 400 |
|
|
|
| 401 |
|
|
/*
|
| 402 |
|
|
* A transmitter error has happened. Most likely excess collisions (which
|
| 403 |
|
|
* is a fairly normal condition). If the error is one where the Tx will
|
| 404 |
|
|
* have been aborted, we try and send another one right away, instead of
|
| 405 |
|
|
* letting the failed packet sit and collect dust in the Tx buffer. This
|
| 406 |
|
|
* is a much better solution as it avoids kernel based Tx timeouts, and
|
| 407 |
|
|
* an unnecessary card reset.
|
| 408 |
|
|
*/
|
| 409 |
|
|
|
| 410 |
|
|
static void ei_tx_err(struct device *dev)
|
| 411 |
|
|
{
|
| 412 |
|
|
int e8390_base = dev->base_addr;
|
| 413 |
|
|
unsigned char txsr = inb_p(e8390_base+EN0_TSR);
|
| 414 |
|
|
unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
|
| 415 |
|
|
struct ei_device *ei_local = (struct ei_device *) dev->priv;
|
| 416 |
|
|
|
| 417 |
|
|
#ifdef VERBOSE_ERROR_DUMP
|
| 418 |
|
|
printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr);
|
| 419 |
|
|
if (txsr & ENTSR_ABT)
|
| 420 |
|
|
printk("excess-collisions ");
|
| 421 |
|
|
if (txsr & ENTSR_ND)
|
| 422 |
|
|
printk("non-deferral ");
|
| 423 |
|
|
if (txsr & ENTSR_CRS)
|
| 424 |
|
|
printk("lost-carrier ");
|
| 425 |
|
|
if (txsr & ENTSR_FU)
|
| 426 |
|
|
printk("FIFO-underrun ");
|
| 427 |
|
|
if (txsr & ENTSR_CDH)
|
| 428 |
|
|
printk("lost-heartbeat ");
|
| 429 |
|
|
printk("\n");
|
| 430 |
|
|
#endif
|
| 431 |
|
|
|
| 432 |
|
|
outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */
|
| 433 |
|
|
|
| 434 |
|
|
if (tx_was_aborted)
|
| 435 |
|
|
ei_tx_intr(dev);
|
| 436 |
|
|
|
| 437 |
|
|
/*
|
| 438 |
|
|
* Note: NCR reads zero on 16 collisions so we add them
|
| 439 |
|
|
* in by hand. Somebody might care...
|
| 440 |
|
|
*/
|
| 441 |
|
|
if (txsr & ENTSR_ABT)
|
| 442 |
|
|
ei_local->stat.collisions += 16;
|
| 443 |
|
|
|
| 444 |
|
|
}
|
| 445 |
|
|
|
| 446 |
|
|
/* We have finished a transmit: check for errors and then trigger the next
|
| 447 |
|
|
packet to be sent. */
|
| 448 |
|
|
static void ei_tx_intr(struct device *dev)
|
| 449 |
|
|
{
|
| 450 |
|
|
int e8390_base = dev->base_addr;
|
| 451 |
|
|
int status = inb(e8390_base + EN0_TSR);
|
| 452 |
|
|
struct ei_device *ei_local = (struct ei_device *) dev->priv;
|
| 453 |
|
|
|
| 454 |
|
|
outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */
|
| 455 |
|
|
|
| 456 |
|
|
#ifdef EI_PINGPONG
|
| 457 |
|
|
|
| 458 |
|
|
/*
|
| 459 |
|
|
* There are two Tx buffers, see which one finished, and trigger
|
| 460 |
|
|
* the send of another one if it exists.
|
| 461 |
|
|
*/
|
| 462 |
|
|
ei_local->txqueue--;
|
| 463 |
|
|
if (ei_local->tx1 < 0) {
|
| 464 |
|
|
if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
|
| 465 |
|
|
printk("%s: bogus last_tx_buffer %d, tx1=%d.\n",
|
| 466 |
|
|
ei_local->name, ei_local->lasttx, ei_local->tx1);
|
| 467 |
|
|
ei_local->tx1 = 0;
|
| 468 |
|
|
dev->tbusy = 0;
|
| 469 |
|
|
if (ei_local->tx2 > 0) {
|
| 470 |
|
|
ei_local->txing = 1;
|
| 471 |
|
|
NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
|
| 472 |
|
|
dev->trans_start = jiffies;
|
| 473 |
|
|
ei_local->tx2 = -1,
|
| 474 |
|
|
ei_local->lasttx = 2;
|
| 475 |
|
|
} else
|
| 476 |
|
|
ei_local->lasttx = 20, ei_local->txing = 0;
|
| 477 |
|
|
} else if (ei_local->tx2 < 0) {
|
| 478 |
|
|
if (ei_local->lasttx != 2 && ei_local->lasttx != -2)
|
| 479 |
|
|
printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
|
| 480 |
|
|
ei_local->name, ei_local->lasttx, ei_local->tx2);
|
| 481 |
|
|
ei_local->tx2 = 0;
|
| 482 |
|
|
dev->tbusy = 0;
|
| 483 |
|
|
if (ei_local->tx1 > 0) {
|
| 484 |
|
|
ei_local->txing = 1;
|
| 485 |
|
|
NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
|
| 486 |
|
|
dev->trans_start = jiffies;
|
| 487 |
|
|
ei_local->tx1 = -1;
|
| 488 |
|
|
ei_local->lasttx = 1;
|
| 489 |
|
|
} else
|
| 490 |
|
|
ei_local->lasttx = 10, ei_local->txing = 0;
|
| 491 |
|
|
} else
|
| 492 |
|
|
printk("%s: unexpected TX-done interrupt, lasttx=%d.\n",
|
| 493 |
|
|
dev->name, ei_local->lasttx);
|
| 494 |
|
|
|
| 495 |
|
|
#else /* EI_PINGPONG */
|
| 496 |
|
|
/*
|
| 497 |
|
|
* Single Tx buffer: mark it free so another packet can be loaded.
|
| 498 |
|
|
*/
|
| 499 |
|
|
ei_local->txing = 0;
|
| 500 |
|
|
dev->tbusy = 0;
|
| 501 |
|
|
#endif
|
| 502 |
|
|
|
| 503 |
|
|
/* Minimize Tx latency: update the statistics after we restart TXing. */
|
| 504 |
|
|
if (status & ENTSR_COL)
|
| 505 |
|
|
ei_local->stat.collisions++;
|
| 506 |
|
|
if (status & ENTSR_PTX)
|
| 507 |
|
|
ei_local->stat.tx_packets++;
|
| 508 |
|
|
else {
|
| 509 |
|
|
ei_local->stat.tx_errors++;
|
| 510 |
|
|
if (status & ENTSR_ABT) ei_local->stat.tx_aborted_errors++;
|
| 511 |
|
|
if (status & ENTSR_CRS) ei_local->stat.tx_carrier_errors++;
|
| 512 |
|
|
if (status & ENTSR_FU) ei_local->stat.tx_fifo_errors++;
|
| 513 |
|
|
if (status & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++;
|
| 514 |
|
|
if (status & ENTSR_OWC) ei_local->stat.tx_window_errors++;
|
| 515 |
|
|
}
|
| 516 |
|
|
|
| 517 |
|
|
mark_bh (NET_BH);
|
| 518 |
|
|
}
|
| 519 |
|
|
|
| 520 |
|
|
/* We have a good packet(s), get it/them out of the buffers. */
|
| 521 |
|
|
|
| 522 |
|
|
static void ei_receive(struct device *dev)
|
| 523 |
|
|
{
|
| 524 |
|
|
int e8390_base = dev->base_addr;
|
| 525 |
|
|
struct ei_device *ei_local = (struct ei_device *) dev->priv;
|
| 526 |
|
|
unsigned char rxing_page, this_frame, next_frame;
|
| 527 |
|
|
unsigned short current_offset;
|
| 528 |
|
|
int rx_pkt_count = 0;
|
| 529 |
|
|
struct e8390_pkt_hdr rx_frame;
|
| 530 |
|
|
int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
|
| 531 |
|
|
|
| 532 |
|
|
while (++rx_pkt_count < 10) {
|
| 533 |
|
|
int pkt_len;
|
| 534 |
|
|
|
| 535 |
|
|
/* Get the rx page (incoming packet pointer). */
|
| 536 |
|
|
outb_p(E8390_NODMA+E8390_PAGE1, e8390_base + E8390_CMD);
|
| 537 |
|
|
rxing_page = inb_p(e8390_base + EN1_CURPAG);
|
| 538 |
|
|
outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
|
| 539 |
|
|
|
| 540 |
|
|
/* Remove one frame from the ring. Boundary is always a page behind. */
|
| 541 |
|
|
this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1;
|
| 542 |
|
|
if (this_frame >= ei_local->stop_page)
|
| 543 |
|
|
this_frame = ei_local->rx_start_page;
|
| 544 |
|
|
|
| 545 |
|
|
/* Someday we'll omit the previous, iff we never get this message.
|
| 546 |
|
|
(There is at least one clone claimed to have a problem.) */
|
| 547 |
|
|
if (ei_debug > 0 && this_frame != ei_local->current_page)
|
| 548 |
|
|
printk("%s: mismatched read page pointers %2x vs %2x.\n",
|
| 549 |
|
|
dev->name, this_frame, ei_local->current_page);
|
| 550 |
|
|
|
| 551 |
|
|
if (this_frame == rxing_page) /* Read all the frames? */
|
| 552 |
|
|
break; /* Done for now */
|
| 553 |
|
|
|
| 554 |
|
|
current_offset = this_frame << 8;
|
| 555 |
|
|
ei_get_8390_hdr(dev, &rx_frame, this_frame);
|
| 556 |
|
|
|
| 557 |
|
|
pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);
|
| 558 |
|
|
|
| 559 |
|
|
next_frame = this_frame + 1 + ((pkt_len+4)>>8);
|
| 560 |
|
|
|
| 561 |
|
|
/* Check for bogosity warned by 3c503 book: the status byte is never
|
| 562 |
|
|
written. This happened a lot during testing! This code should be
|
| 563 |
|
|
cleaned up someday. */
|
| 564 |
|
|
if (rx_frame.next != next_frame
|
| 565 |
|
|
&& rx_frame.next != next_frame + 1
|
| 566 |
|
|
&& rx_frame.next != next_frame - num_rx_pages
|
| 567 |
|
|
&& rx_frame.next != next_frame + 1 - num_rx_pages) {
|
| 568 |
|
|
ei_local->current_page = rxing_page;
|
| 569 |
|
|
outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY);
|
| 570 |
|
|
#if 1
|
| 571 |
|
|
printk("%s(%d): ERROR -> rx_frame.next=%x "
|
| 572 |
|
|
"next_frame=%x num_rx_pages=%x\n",
|
| 573 |
|
|
__FILE__, __LINE__, rx_frame.next,
|
| 574 |
|
|
next_frame, num_rx_pages);
|
| 575 |
|
|
#endif
|
| 576 |
|
|
ei_local->stat.rx_errors++;
|
| 577 |
|
|
continue;
|
| 578 |
|
|
}
|
| 579 |
|
|
|
| 580 |
|
|
if (pkt_len < 60 || pkt_len > 1518) {
|
| 581 |
|
|
if (ei_debug)
|
| 582 |
|
|
printk("%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n",
|
| 583 |
|
|
dev->name, rx_frame.count, rx_frame.status,
|
| 584 |
|
|
rx_frame.next);
|
| 585 |
|
|
ei_local->stat.rx_errors++;
|
| 586 |
|
|
} else if ((rx_frame.status & 0x0F) == ENRSR_RXOK) {
|
| 587 |
|
|
struct sk_buff *skb;
|
| 588 |
|
|
|
| 589 |
|
|
skb = dev_alloc_skb(pkt_len+2);
|
| 590 |
|
|
if (skb == NULL) {
|
| 591 |
|
|
if (ei_debug > 1)
|
| 592 |
|
|
printk("%s: Couldn't allocate a sk_buff of size %d.\n",
|
| 593 |
|
|
dev->name, pkt_len);
|
| 594 |
|
|
ei_local->stat.rx_dropped++;
|
| 595 |
|
|
break;
|
| 596 |
|
|
} else {
|
| 597 |
|
|
skb_reserve(skb,2); /* IP headers on 16 byte boundaries */
|
| 598 |
|
|
skb->dev = dev;
|
| 599 |
|
|
skb_put(skb, pkt_len); /* Make room */
|
| 600 |
|
|
ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
|
| 601 |
|
|
skb->protocol=eth_type_trans(skb,dev);
|
| 602 |
|
|
netif_rx(skb);
|
| 603 |
|
|
ei_local->stat.rx_packets++;
|
| 604 |
|
|
}
|
| 605 |
|
|
} else {
|
| 606 |
|
|
int errs = rx_frame.status;
|
| 607 |
|
|
if (ei_debug)
|
| 608 |
|
|
printk("%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n",
|
| 609 |
|
|
dev->name, rx_frame.status, rx_frame.next,
|
| 610 |
|
|
rx_frame.count);
|
| 611 |
|
|
if (errs & ENRSR_FO)
|
| 612 |
|
|
ei_local->stat.rx_fifo_errors++;
|
| 613 |
|
|
}
|
| 614 |
|
|
next_frame = rx_frame.next;
|
| 615 |
|
|
|
| 616 |
|
|
/* This _should_ never happen: it's here for avoiding bad clones. */
|
| 617 |
|
|
if (next_frame >= ei_local->stop_page) {
|
| 618 |
|
|
printk("%s: next frame inconsistency, %#2x\n", dev->name,
|
| 619 |
|
|
next_frame);
|
| 620 |
|
|
next_frame = ei_local->rx_start_page;
|
| 621 |
|
|
}
|
| 622 |
|
|
ei_local->current_page = next_frame;
|
| 623 |
|
|
outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
|
| 624 |
|
|
}
|
| 625 |
|
|
|
| 626 |
|
|
/* We used to also ack ENISR_OVER here, but that would sometimes mask
|
| 627 |
|
|
a real overrun, leaving the 8390 in a stopped state with rec'vr off. */
|
| 628 |
|
|
outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR);
|
| 629 |
|
|
return;
|
| 630 |
|
|
}
|
| 631 |
|
|
|
| 632 |
|
|
/*
|
| 633 |
|
|
* We have a receiver overrun: we have to kick the 8390 to get it started
|
| 634 |
|
|
* again. Problem is that you have to kick it exactly as NS prescribes in
|
| 635 |
|
|
* the updated datasheets, or "the NIC may act in an unpredictable manner."
|
| 636 |
|
|
* This includes causing "the NIC to defer indefinitely when it is stopped
|
| 637 |
|
|
* on a busy network." Ugh.
|
| 638 |
|
|
*/
|
| 639 |
|
|
static void ei_rx_overrun(struct device *dev)
|
| 640 |
|
|
{
|
| 641 |
|
|
int e8390_base = dev->base_addr;
|
| 642 |
|
|
unsigned long wait_start_time;
|
| 643 |
|
|
unsigned char was_txing, must_resend = 0;
|
| 644 |
|
|
struct ei_device *ei_local = (struct ei_device *) dev->priv;
|
| 645 |
|
|
|
| 646 |
|
|
/*
|
| 647 |
|
|
* Record whether a Tx was in progress and then issue the
|
| 648 |
|
|
* stop command.
|
| 649 |
|
|
*/
|
| 650 |
|
|
was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
|
| 651 |
|
|
outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
|
| 652 |
|
|
|
| 653 |
|
|
if (ei_debug > 1)
|
| 654 |
|
|
printk("%s: Receiver overrun.\n", dev->name);
|
| 655 |
|
|
ei_local->stat.rx_over_errors++;
|
| 656 |
|
|
|
| 657 |
|
|
/*
|
| 658 |
|
|
* Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
|
| 659 |
|
|
* Early datasheets said to poll the reset bit, but now they say that
|
| 660 |
|
|
* it "is not a reliable indicator and subsequently should be ignored."
|
| 661 |
|
|
* We wait at least 10ms.
|
| 662 |
|
|
*/
|
| 663 |
|
|
wait_start_time = jiffies;
|
| 664 |
|
|
#ifdef CONFIG_COLDFIRE
|
| 665 |
|
|
/*
|
| 666 |
|
|
* I don't see how the following can work eithout enabling
|
| 667 |
|
|
* interrupts again?
|
| 668 |
|
|
*/
|
| 669 |
|
|
sti();
|
| 670 |
|
|
#endif
|
| 671 |
|
|
while (jiffies - wait_start_time <= 1*HZ/100)
|
| 672 |
|
|
barrier();
|
| 673 |
|
|
#ifdef CONFIG_COLDFIRE
|
| 674 |
|
|
cli();
|
| 675 |
|
|
#endif
|
| 676 |
|
|
|
| 677 |
|
|
/*
|
| 678 |
|
|
* Reset RBCR[01] back to zero as per magic incantation.
|
| 679 |
|
|
*/
|
| 680 |
|
|
outb_p(0x00, e8390_base+EN0_RCNTLO);
|
| 681 |
|
|
outb_p(0x00, e8390_base+EN0_RCNTHI);
|
| 682 |
|
|
|
| 683 |
|
|
/*
|
| 684 |
|
|
* See if any Tx was interrupted or not. According to NS, this
|
| 685 |
|
|
* step is vital, and skipping it will cause no end of havoc.
|
| 686 |
|
|
*/
|
| 687 |
|
|
if (was_txing) {
|
| 688 |
|
|
unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
|
| 689 |
|
|
if (!tx_completed) must_resend = 1;
|
| 690 |
|
|
}
|
| 691 |
|
|
|
| 692 |
|
|
/*
|
| 693 |
|
|
* Have to enter loopback mode and then restart the NIC before
|
| 694 |
|
|
* you are allowed to slurp packets up off the ring.
|
| 695 |
|
|
*/
|
| 696 |
|
|
outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
|
| 697 |
|
|
outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
|
| 698 |
|
|
|
| 699 |
|
|
/*
|
| 700 |
|
|
* Clear the Rx ring of all the debris, and ack the interrupt.
|
| 701 |
|
|
*/
|
| 702 |
|
|
ei_receive(dev);
|
| 703 |
|
|
outb_p(ENISR_OVER, e8390_base+EN0_ISR);
|
| 704 |
|
|
|
| 705 |
|
|
/*
|
| 706 |
|
|
* Leave loopback mode, and resend any packet that got stopped.
|
| 707 |
|
|
*/
|
| 708 |
|
|
outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR);
|
| 709 |
|
|
if (must_resend)
|
| 710 |
|
|
outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
|
| 711 |
|
|
|
| 712 |
|
|
}
|
| 713 |
|
|
|
| 714 |
|
|
static struct enet_statistics *get_stats(struct device *dev)
|
| 715 |
|
|
{
|
| 716 |
|
|
short ioaddr = dev->base_addr;
|
| 717 |
|
|
struct ei_device *ei_local = (struct ei_device *) dev->priv;
|
| 718 |
|
|
|
| 719 |
|
|
/* If the card is stopped, just return the present stats. */
|
| 720 |
|
|
if (dev->start == 0) return &ei_local->stat;
|
| 721 |
|
|
|
| 722 |
|
|
/* Read the counter registers, assuming we are in page 0. */
|
| 723 |
|
|
ei_local->stat.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0);
|
| 724 |
|
|
ei_local->stat.rx_crc_errors += inb_p(ioaddr + EN0_COUNTER1);
|
| 725 |
|
|
ei_local->stat.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2);
|
| 726 |
|
|
|
| 727 |
|
|
return &ei_local->stat;
|
| 728 |
|
|
}
|
| 729 |
|
|
|
| 730 |
|
|
/*
|
| 731 |
|
|
* Set or clear the multicast filter for this adaptor.
|
| 732 |
|
|
*/
|
| 733 |
|
|
|
| 734 |
|
|
static void set_multicast_list(struct device *dev)
|
| 735 |
|
|
{
|
| 736 |
|
|
short ioaddr = dev->base_addr;
|
| 737 |
|
|
|
| 738 |
|
|
if(dev->flags&IFF_PROMISC)
|
| 739 |
|
|
{
|
| 740 |
|
|
outb_p(E8390_RXCONFIG | 0x18, ioaddr + EN0_RXCR);
|
| 741 |
|
|
}
|
| 742 |
|
|
else if((dev->flags&IFF_ALLMULTI)||dev->mc_list)
|
| 743 |
|
|
{
|
| 744 |
|
|
/* The multicast-accept list is initialized to accept-all, and we
|
| 745 |
|
|
rely on higher-level filtering for now. */
|
| 746 |
|
|
outb_p(E8390_RXCONFIG | 0x08, ioaddr + EN0_RXCR);
|
| 747 |
|
|
}
|
| 748 |
|
|
else
|
| 749 |
|
|
outb_p(E8390_RXCONFIG, ioaddr + EN0_RXCR);
|
| 750 |
|
|
}
|
| 751 |
|
|
|
| 752 |
|
|
/* Initialize the rest of the 8390 device structure. */
|
| 753 |
|
|
int ethdev_init(struct device *dev)
|
| 754 |
|
|
{
|
| 755 |
|
|
if (ei_debug > 1)
|
| 756 |
|
|
printk(version);
|
| 757 |
|
|
|
| 758 |
|
|
if (dev->priv == NULL) {
|
| 759 |
|
|
struct ei_device *ei_local;
|
| 760 |
|
|
|
| 761 |
|
|
dev->priv = kmalloc(sizeof(struct ei_device), GFP_KERNEL);
|
| 762 |
|
|
if (dev->priv == NULL)
|
| 763 |
|
|
return -ENOMEM;
|
| 764 |
|
|
memset(dev->priv, 0, sizeof(struct ei_device));
|
| 765 |
|
|
ei_local = (struct ei_device *)dev->priv;
|
| 766 |
|
|
}
|
| 767 |
|
|
|
| 768 |
|
|
dev->hard_start_xmit = &ei_start_xmit;
|
| 769 |
|
|
dev->get_stats = get_stats;
|
| 770 |
|
|
dev->set_multicast_list = &set_multicast_list;
|
| 771 |
|
|
|
| 772 |
|
|
ether_setup(dev);
|
| 773 |
|
|
|
| 774 |
|
|
return 0;
|
| 775 |
|
|
}
|
| 776 |
|
|
|
| 777 |
|
|
|
| 778 |
|
|
/* This page of functions should be 8390 generic */
|
| 779 |
|
|
/* Follow National Semi's recommendations for initializing the "NIC". */
|
| 780 |
|
|
void NS8390_init(struct device *dev, int startp)
|
| 781 |
|
|
{
|
| 782 |
|
|
int e8390_base = dev->base_addr;
|
| 783 |
|
|
struct ei_device *ei_local = (struct ei_device *) dev->priv;
|
| 784 |
|
|
int i;
|
| 785 |
|
|
int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48;
|
| 786 |
|
|
unsigned long flags;
|
| 787 |
|
|
|
| 788 |
|
|
/* Follow National Semi's recommendations for initing the DP83902. */
|
| 789 |
|
|
outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base); /* 0x21 */
|
| 790 |
|
|
outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */
|
| 791 |
|
|
/* Clear the remote byte count registers. */
|
| 792 |
|
|
outb_p(0x00, e8390_base + EN0_RCNTLO);
|
| 793 |
|
|
outb_p(0x00, e8390_base + EN0_RCNTHI);
|
| 794 |
|
|
/* Set to monitor and loopback mode -- this is vital!. */
|
| 795 |
|
|
outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */
|
| 796 |
|
|
outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
|
| 797 |
|
|
/* Set the transmit page and receive ring. */
|
| 798 |
|
|
outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
|
| 799 |
|
|
ei_local->tx1 = ei_local->tx2 = 0;
|
| 800 |
|
|
outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG);
|
| 801 |
|
|
outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/
|
| 802 |
|
|
ei_local->current_page = ei_local->rx_start_page; /* assert boundary+1 */
|
| 803 |
|
|
outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG);
|
| 804 |
|
|
/* Clear the pending interrupts and mask. */
|
| 805 |
|
|
outb_p(0xFF, e8390_base + EN0_ISR);
|
| 806 |
|
|
outb_p(0x00, e8390_base + EN0_IMR);
|
| 807 |
|
|
|
| 808 |
|
|
/* Copy the station address into the DS8390 registers,
|
| 809 |
|
|
and set the multicast hash bitmap to receive all multicasts. */
|
| 810 |
|
|
save_flags(flags);
|
| 811 |
|
|
cli();
|
| 812 |
|
|
outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base); /* 0x61 */
|
| 813 |
|
|
for(i = 0; i < 6; i++) {
|
| 814 |
|
|
outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS + i);
|
| 815 |
|
|
}
|
| 816 |
|
|
/* Initialize the multicast list to accept-all. If we enable multicast
|
| 817 |
|
|
the higher levels can do the filtering. */
|
| 818 |
|
|
for(i = 0; i < 8; i++)
|
| 819 |
|
|
outb_p(0xff, e8390_base + EN1_MULT + i);
|
| 820 |
|
|
|
| 821 |
|
|
outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
|
| 822 |
|
|
outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base);
|
| 823 |
|
|
restore_flags(flags);
|
| 824 |
|
|
dev->tbusy = 0;
|
| 825 |
|
|
dev->interrupt = 0;
|
| 826 |
|
|
ei_local->tx1 = ei_local->tx2 = 0;
|
| 827 |
|
|
ei_local->txing = 0;
|
| 828 |
|
|
if (startp) {
|
| 829 |
|
|
outb_p(0xff, e8390_base + EN0_ISR);
|
| 830 |
|
|
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
|
| 831 |
|
|
outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base);
|
| 832 |
|
|
outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */
|
| 833 |
|
|
/* 3c503 TechMan says rxconfig only after the NIC is started. */
|
| 834 |
|
|
outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */
|
| 835 |
|
|
dev->set_multicast_list(dev); /* Get the multicast status right if this
|
| 836 |
|
|
was a reset. */
|
| 837 |
|
|
}
|
| 838 |
|
|
return;
|
| 839 |
|
|
}
|
| 840 |
|
|
|
| 841 |
|
|
/* Trigger a transmit start, assuming the length is valid. */
|
| 842 |
|
|
static void NS8390_trigger_send(struct device *dev, unsigned int length,
|
| 843 |
|
|
int start_page)
|
| 844 |
|
|
{
|
| 845 |
|
|
int e8390_base = dev->base_addr;
|
| 846 |
|
|
|
| 847 |
|
|
outb_p(E8390_NODMA+E8390_PAGE0, e8390_base);
|
| 848 |
|
|
|
| 849 |
|
|
if (inb_p(e8390_base) & E8390_TRANS) {
|
| 850 |
|
|
printk("%s: trigger_send() called with the transmitter busy.\n",
|
| 851 |
|
|
dev->name);
|
| 852 |
|
|
return;
|
| 853 |
|
|
}
|
| 854 |
|
|
outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
|
| 855 |
|
|
outb_p(length >> 8, e8390_base + EN0_TCNTHI);
|
| 856 |
|
|
outb_p(start_page, e8390_base + EN0_TPSR);
|
| 857 |
|
|
outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base);
|
| 858 |
|
|
return;
|
| 859 |
|
|
}
|
| 860 |
|
|
|
| 861 |
|
|
#ifdef MODULE
|
| 862 |
|
|
|
| 863 |
|
|
int init_module(void)
|
| 864 |
|
|
{
|
| 865 |
|
|
return 0;
|
| 866 |
|
|
}
|
| 867 |
|
|
|
| 868 |
|
|
void
|
| 869 |
|
|
cleanup_module(void)
|
| 870 |
|
|
{
|
| 871 |
|
|
}
|
| 872 |
|
|
#endif /* MODULE */
|
| 873 |
|
|
|
| 874 |
|
|
/*
|
| 875 |
|
|
* Local variables:
|
| 876 |
|
|
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 8390.c"
|
| 877 |
|
|
* version-control: t
|
| 878 |
|
|
* kept-new-versions: 5
|
| 879 |
|
|
* c-indent-level: 4
|
| 880 |
|
|
* tab-width: 4
|
| 881 |
|
|
* End:
|
| 882 |
|
|
*/
|