^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/drivers/acorn/net/ether1.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1996-2000 Russell King
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Acorn ether1 driver (82586 chip) for Acorn machines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * We basically keep two queues in the cards memory - one for transmit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * and one for receive. Each has a head and a tail. The head is where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * we/the chip adds packets to be transmitted/received, and the tail
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * is where the transmitter has got to/where the receiver will stop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Both of these queues are circular, and since the chip is running
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * all the time, we have to be careful when we modify the pointers etc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * so that the buffer memory contents is valid all the time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Change log:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * 1.00 RMK Released
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * 1.01 RMK 19/03/1996 Transfers the last odd byte onto/off of the card now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * 1.02 RMK 25/05/1997 Added code to restart RU if it goes not ready
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * 1.03 RMK 14/09/1997 Cleaned up the handling of a reset during the TX interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Should prevent lockup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * 1.04 RMK 17/09/1997 Added more info when initialsation of chip goes wrong.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * TDR now only reports failure when chip reports non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * TDR time-distance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * 1.05 RMK 31/12/1997 Removed calls to dev_tint for 2.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * 1.06 RMK 10/02/2000 Updated for 2.3.43
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * 1.07 RMK 13/05/2000 Updated for 2.3.99-pre8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/in.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <asm/dma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <asm/ecard.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define __ETHER1_C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include "ether1.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static unsigned int net_debug = NET_DEBUG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define BUFFER_SIZE 0x10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define TX_AREA_START 0x00100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define TX_AREA_END 0x05000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define RX_AREA_START 0x05000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define RX_AREA_END 0x0fc00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static int ether1_open(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static netdev_tx_t ether1_sendpacket(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static irqreturn_t ether1_interrupt(int irq, void *dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static int ether1_close(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static void ether1_setmulticastlist(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static void ether1_timeout(struct net_device *dev, unsigned int txqueue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static char version[] = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define BUS_16 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define BUS_8 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define DISABLEIRQS 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define NORMALIRQS 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define ether1_readw(dev, addr, type, offset, svflgs) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset), svflgs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define ether1_writew(dev, val, addr, type, offset, svflgs) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset), svflgs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static inline unsigned short
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ether1_inw_p (struct net_device *dev, int addr, int svflgs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) unsigned short ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (svflgs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) local_irq_save (flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) writeb(addr >> 12, REG_PAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ret = readw(ETHER1_RAM + ((addr & 4095) << 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (svflgs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) local_irq_restore (flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ether1_outw_p (struct net_device *dev, unsigned short val, int addr, int svflgs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (svflgs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) local_irq_save (flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) writeb(addr >> 12, REG_PAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) writew(val, ETHER1_RAM + ((addr & 4095) << 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (svflgs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) local_irq_restore (flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * Some inline assembler to allow fast transfers on to/off of the card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * Since this driver depends on some features presented by the ARM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * specific architecture, and that you can't configure this driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * without specifiing ARM mode, this is not a problem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * This routine is essentially an optimised memcpy from the card's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * onboard RAM to kernel memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) ether1_writebuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) unsigned int page, thislen, offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) void __iomem *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) offset = start & 4095;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) page = start >> 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) addr = ETHER1_RAM + (offset << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (offset + length > 4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) thislen = 4096 - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) thislen = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int used;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) writeb(page, REG_PAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) length -= thislen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) "subs %3, %3, #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) bmi 2f\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 1: ldr %0, [%1], #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) mov %0, %0, lsl #16\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) orr %0, %0, %0, lsr #16\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) str %0, [%2], #4\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) subs %3, %3, #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) bmi 2f\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ldr %0, [%1], #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) mov %0, %0, lsl #16\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) orr %0, %0, %0, lsr #16\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) str %0, [%2], #4\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) subs %3, %3, #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) bmi 2f\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) ldr %0, [%1], #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) mov %0, %0, lsl #16\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) orr %0, %0, %0, lsr #16\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) str %0, [%2], #4\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) subs %3, %3, #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) bmi 2f\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ldr %0, [%1], #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) mov %0, %0, lsl #16\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) orr %0, %0, %0, lsr #16\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) str %0, [%2], #4\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) subs %3, %3, #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) bpl 1b\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 2: adds %3, %3, #1\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ldreqb %0, [%1]\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) streqb %0, [%2]"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) : "=&r" (used), "=&r" (data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) : "r" (addr), "r" (thislen), "1" (data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) addr = ETHER1_RAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) thislen = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (thislen > 4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) thislen = 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) page++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) } while (thislen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned int page, thislen, offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) void __iomem *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) offset = start & 4095;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) page = start >> 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) addr = ETHER1_RAM + (offset << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (offset + length > 4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) thislen = 4096 - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) thislen = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int used;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) writeb(page, REG_PAGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) length -= thislen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) __asm__ __volatile__(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) "subs %3, %3, #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) bmi 2f\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 1: ldr %0, [%2], #4\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) strb %0, [%1], #1\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) mov %0, %0, lsr #8\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) strb %0, [%1], #1\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) subs %3, %3, #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) bmi 2f\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ldr %0, [%2], #4\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) strb %0, [%1], #1\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) mov %0, %0, lsr #8\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) strb %0, [%1], #1\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) subs %3, %3, #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) bmi 2f\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ldr %0, [%2], #4\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) strb %0, [%1], #1\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) mov %0, %0, lsr #8\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) strb %0, [%1], #1\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) subs %3, %3, #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) bmi 2f\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ldr %0, [%2], #4\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) strb %0, [%1], #1\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) mov %0, %0, lsr #8\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) strb %0, [%1], #1\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) subs %3, %3, #2\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) bpl 1b\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 2: adds %3, %3, #1\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ldreqb %0, [%2]\n\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) streqb %0, [%1]"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) : "=&r" (used), "=&r" (data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) : "r" (addr), "r" (thislen), "1" (data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) addr = ETHER1_RAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) thislen = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (thislen > 4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) thislen = 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) page++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) } while (thislen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) ether1_ramtest(struct net_device *dev, unsigned char byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) int i, ret = BUFFER_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) int max_errors = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int bad = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int bad_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) memset (buffer, byte, BUFFER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) ether1_writebuffer (dev, buffer, 0, BUFFER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) memset (buffer, byte ^ 0xff, BUFFER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ether1_readbuffer (dev, buffer, 0, BUFFER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) for (i = 0; i < BUFFER_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (buffer[i] != byte) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (max_errors >= 0 && bad != buffer[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (bad != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) printk ("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) printk (KERN_CRIT "%s: RAM failed with (%02X instead of %02X) at 0x%04X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) dev->name, buffer[i], byte, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) max_errors --;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) bad = buffer[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) bad_start = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (bad != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (bad_start == i - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) printk ("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) printk (" - 0x%04X\n", i - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) bad = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (bad != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) printk (" - 0x%04X\n", BUFFER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) kfree (buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ether1_reset (struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) writeb(CTRL_RST|CTRL_ACK, REG_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return BUS_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ether1_init_2(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) dev->mem_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) i = ether1_ramtest (dev, 0x5a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (i > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) i = ether1_ramtest (dev, 0x1e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (i <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) dev->mem_end = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * These are the structures that are loaded into the ether RAM card to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) * initialise the 82586
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /* at 0x0100 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) #define NOP_ADDR (TX_AREA_START)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) #define NOP_SIZE (0x06)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static nop_t init_nop = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) CMD_NOP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) NOP_ADDR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* at 0x003a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) #define TDR_ADDR (0x003a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) #define TDR_SIZE (0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static tdr_t init_tdr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) CMD_TDR | CMD_INTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) NOP_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* at 0x002e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) #define MC_ADDR (0x002e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) #define MC_SIZE (0x0c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static mc_t init_mc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) CMD_SETMULTICAST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) TDR_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) { { 0, } }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* at 0x0022 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) #define SA_ADDR (0x0022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) #define SA_SIZE (0x0c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) static sa_t init_sa = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) CMD_SETADDRESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) MC_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) { 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* at 0x0010 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) #define CFG_ADDR (0x0010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) #define CFG_SIZE (0x12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) static cfg_t init_cfg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) CMD_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) SA_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) CFG8_SRDY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) CFG9_PREAMB8 | CFG9_ADDRLENBUF | CFG9_ADDRLEN(6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 0x60,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) CFG13_RETRY(15) | CFG13_SLOTH(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* at 0x0000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) #define SCB_ADDR (0x0000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) #define SCB_SIZE (0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static scb_t init_scb = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) SCB_CMDACKRNR | SCB_CMDACKCNA | SCB_CMDACKFR | SCB_CMDACKCX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) CFG_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) RX_AREA_START,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /* at 0xffee */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) #define ISCP_ADDR (0xffee)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) #define ISCP_SIZE (0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static iscp_t init_iscp = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) SCB_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /* at 0xfff6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) #define SCP_ADDR (0xfff6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) #define SCP_SIZE (0x0a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) static scp_t init_scp = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) SCP_SY_16BBUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) { 0, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) ISCP_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) #define RFD_SIZE (0x16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static rfd_t init_rfd = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) { 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) { 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) #define RBD_SIZE (0x0a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) static rbd_t init_rbd = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) ETH_FRAME_LEN + 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) #define TX_SIZE (0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) #define TBD_SIZE (0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) ether1_init_for_open (struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) int i, status, addr, next, next2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) int failures = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) writeb(CTRL_RST|CTRL_ACK, REG_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) for (i = 0; i < 6; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) init_sa.sa_addr[i] = dev->dev_addr[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* load data structures into ether1 RAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ether1_writebuffer (dev, &init_scp, SCP_ADDR, SCP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) ether1_writebuffer (dev, &init_iscp, ISCP_ADDR, ISCP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) ether1_writebuffer (dev, &init_scb, SCB_ADDR, SCB_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) ether1_writebuffer (dev, &init_cfg, CFG_ADDR, CFG_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ether1_writebuffer (dev, &init_sa, SA_ADDR, SA_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) ether1_writebuffer (dev, &init_mc, MC_ADDR, MC_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) ether1_writebuffer (dev, &init_tdr, TDR_ADDR, TDR_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) ether1_writebuffer (dev, &init_nop, NOP_ADDR, NOP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (ether1_readw(dev, CFG_ADDR, cfg_t, cfg_command, NORMALIRQS) != CMD_CONFIG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) printk (KERN_ERR "%s: detected either RAM fault or compiler bug\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * setup circularly linked list of { rfd, rbd, buffer }, with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * all rfds circularly linked, rbds circularly linked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * First rfd is linked to scp, first rbd is linked to first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * rfd. Last rbd has a suspend command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) addr = RX_AREA_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) next = addr + RFD_SIZE + RBD_SIZE + ETH_FRAME_LEN + 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) next2 = next + RFD_SIZE + RBD_SIZE + ETH_FRAME_LEN + 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (next2 >= RX_AREA_END) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) next = RX_AREA_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) init_rfd.rfd_command = RFD_CMDEL | RFD_CMDSUSPEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) priv(dev)->rx_tail = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) init_rfd.rfd_command = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (addr == RX_AREA_START)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) init_rfd.rfd_rbdoffset = addr + RFD_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) init_rfd.rfd_rbdoffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) init_rfd.rfd_link = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) init_rbd.rbd_link = next + RFD_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) init_rbd.rbd_bufl = addr + RFD_SIZE + RBD_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) ether1_writebuffer (dev, &init_rfd, addr, RFD_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) ether1_writebuffer (dev, &init_rbd, addr + RFD_SIZE, RBD_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) addr = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) } while (next2 < RX_AREA_END);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) priv(dev)->tx_link = NOP_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) priv(dev)->tx_head = NOP_ADDR + NOP_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) priv(dev)->tx_tail = TDR_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) priv(dev)->rx_head = RX_AREA_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) /* release reset & give 586 a prod */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) priv(dev)->resetting = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) priv(dev)->initialising = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) writeb(CTRL_RST, REG_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) writeb(0, REG_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) writeb(CTRL_CA, REG_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /* 586 should now unset iscp.busy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) timeout = jiffies + HZ/2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) while (ether1_readw(dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (time_after(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) printk (KERN_WARNING "%s: can't initialise 82586: iscp is busy\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* check status of commands that we issued */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) timeout += HZ/10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) while (((status = ether1_readw(dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) & STAT_COMPLETE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (time_after(jiffies, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) printk (KERN_WARNING "%s: can't initialise 82586: config status %04X\n", dev->name, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) failures += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) timeout += HZ/10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) while (((status = ether1_readw(dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) & STAT_COMPLETE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (time_after(jiffies, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) printk (KERN_WARNING "%s: can't initialise 82586: set address status %04X\n", dev->name, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) failures += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) timeout += HZ/10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) while (((status = ether1_readw(dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) & STAT_COMPLETE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (time_after(jiffies, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) printk (KERN_WARNING "%s: can't initialise 82586: set multicast status %04X\n", dev->name, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) failures += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) timeout += HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) while (((status = ether1_readw(dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) & STAT_COMPLETE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (time_after(jiffies, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) printk (KERN_WARNING "%s: can't tdr (ignored)\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) status = ether1_readw(dev, TDR_ADDR, tdr_t, tdr_result, DISABLEIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (status & TDR_XCVRPROB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) printk (KERN_WARNING "%s: i/f failed tdr: transceiver problem\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) else if ((status & (TDR_SHORT|TDR_OPEN)) && (status & TDR_TIME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) #ifdef FANCY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) printk (KERN_WARNING "%s: i/f failed tdr: cable %s %d.%d us away\n", dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) status & TDR_SHORT ? "short" : "open", (status & TDR_TIME) / 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) (status & TDR_TIME) % 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) printk (KERN_WARNING "%s: i/f failed tdr: cable %s %d clks away\n", dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) status & TDR_SHORT ? "short" : "open", (status & TDR_TIME));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (failures)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) ether1_reset (dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return failures ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) ether1_txalloc (struct net_device *dev, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) int start, tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) size = (size + 1) & ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) tail = priv(dev)->tx_tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (priv(dev)->tx_head + size > TX_AREA_END) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (tail > priv(dev)->tx_head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) start = TX_AREA_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (start + size > tail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) priv(dev)->tx_head = start + size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (priv(dev)->tx_head < tail && (priv(dev)->tx_head + size) > tail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) start = priv(dev)->tx_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) priv(dev)->tx_head += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) ether1_open (struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (ether1_init_for_open (dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) free_irq (dev->irq, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) netif_start_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) ether1_timeout(struct net_device *dev, unsigned int txqueue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) printk(KERN_WARNING "%s: transmit timeout, network cable problem?\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) printk(KERN_WARNING "%s: resetting device\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) ether1_reset (dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (ether1_init_for_open (dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) printk (KERN_ERR "%s: unable to restart interface\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) dev->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static netdev_tx_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) tx_t tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) tbd_t tbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) nop_t nop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (priv(dev)->restart) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) printk(KERN_WARNING "%s: resetting device\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) ether1_reset(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (ether1_init_for_open(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) printk(KERN_ERR "%s: unable to restart interface\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) priv(dev)->restart = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (skb->len < ETH_ZLEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (skb_padto(skb, ETH_ZLEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * insert packet followed by a nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) txaddr = ether1_txalloc (dev, TX_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) tbdaddr = ether1_txalloc (dev, TBD_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) dataddr = ether1_txalloc (dev, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) nopaddr = ether1_txalloc (dev, NOP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) tx.tx_status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) tx.tx_command = CMD_TX | CMD_INTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) tx.tx_link = nopaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) tx.tx_tbdoffset = tbdaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) tbd.tbd_opts = TBD_EOL | skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) tbd.tbd_link = I82586_NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) tbd.tbd_bufl = dataddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) tbd.tbd_bufh = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) nop.nop_status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) nop.nop_command = CMD_NOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) nop.nop_link = nopaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) ether1_writebuffer (dev, &tx, txaddr, TX_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) ether1_writebuffer (dev, &tbd, tbdaddr, TBD_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) ether1_writebuffer (dev, skb->data, dataddr, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) ether1_writebuffer (dev, &nop, nopaddr, NOP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) tmp = priv(dev)->tx_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) priv(dev)->tx_link = nopaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) /* now reset the previous nop pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) ether1_writew(dev, txaddr, tmp, nop_t, nop_link, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /* handle transmit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) /* check to see if we have room for a full sized ether frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) tmp = priv(dev)->tx_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) priv(dev)->tx_head = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) dev_kfree_skb (skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (tst == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) ether1_xmit_done (struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) nop_t nop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) int caddr, tst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) caddr = priv(dev)->tx_tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) switch (nop.nop_command & CMD_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) case CMD_TDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /* special case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) != (unsigned short)I82586_NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) ether1_writew(dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) scb_command, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) writeb(CTRL_CA, REG_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) priv(dev)->tx_tail = NOP_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) case CMD_NOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (nop.nop_link == caddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (priv(dev)->initialising == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) printk (KERN_WARNING "%s: strange command complete with no tx command!\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) priv(dev)->initialising = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (caddr == nop.nop_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) caddr = nop.nop_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) case CMD_TX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (nop.nop_status & STAT_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) printk (KERN_ERR "%s: strange command complete without completed command\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) priv(dev)->restart = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) printk (KERN_WARNING "%s: strange command %d complete! (offset %04X)", dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) nop.nop_command & CMD_MASK, caddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) priv(dev)->restart = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) while (nop.nop_status & STAT_COMPLETE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (nop.nop_status & STAT_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) dev->stats.tx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) dev->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) dev->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (nop.nop_status & STAT_COLLAFTERTX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) dev->stats.collisions++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (nop.nop_status & STAT_NOCARRIER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) dev->stats.tx_carrier_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (nop.nop_status & STAT_TXLOSTCTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) printk (KERN_WARNING "%s: cts lost\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (nop.nop_status & STAT_TXSLOWDMA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) dev->stats.tx_fifo_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (nop.nop_status & STAT_COLLEXCESSIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) dev->stats.collisions += 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (nop.nop_link == caddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) printk (KERN_ERR "%s: tx buffer chaining error: tx command points to itself\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) caddr = nop.nop_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if ((nop.nop_command & CMD_MASK) != CMD_NOP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) printk (KERN_ERR "%s: tx buffer chaining error: no nop after tx command\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (caddr == nop.nop_link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) caddr = nop.nop_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if ((nop.nop_command & CMD_MASK) != CMD_TX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) printk (KERN_ERR "%s: tx buffer chaining error: no tx command after nop\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) priv(dev)->tx_tail = caddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) caddr = priv(dev)->tx_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) priv(dev)->tx_head = caddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (tst != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) netif_wake_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) ether1_recv_done (struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) int nexttail, rbdaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) rbd_t rbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) status = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_status, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if ((status & RFD_COMPLETE) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) rbdaddr = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_rbdoffset, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) ether1_readbuffer (dev, &rbd, rbdaddr, RBD_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if ((rbd.rbd_status & (RBD_EOF | RBD_ACNTVALID)) == (RBD_EOF | RBD_ACNTVALID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) int length = rbd.rbd_status & RBD_ACNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) length = (length + 1) & ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) skb = netdev_alloc_skb(dev, length + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) skb_reserve (skb, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) ether1_readbuffer (dev, skb_put (skb, length), rbd.rbd_bufl, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) skb->protocol = eth_type_trans (skb, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) netif_rx (skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) dev->stats.rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) dev->stats.rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) printk(KERN_WARNING "%s: %s\n", dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) (rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) dev->stats.rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) nexttail = ether1_readw(dev, priv(dev)->rx_tail, rfd_t, rfd_link, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) /* nexttail should be rx_head */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (nexttail != priv(dev)->rx_head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) printk(KERN_ERR "%s: receiver buffer chaining error (%04X != %04X)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) dev->name, nexttail, priv(dev)->rx_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) ether1_writew(dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_command, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_status, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_rbdoffset, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) priv(dev)->rx_tail = nexttail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) priv(dev)->rx_head = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_link, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) } while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) static irqreturn_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) ether1_interrupt (int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) struct net_device *dev = (struct net_device *)dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) status = ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) ether1_writew(dev, status & (SCB_STRNR | SCB_STCNA | SCB_STFR | SCB_STCX),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) SCB_ADDR, scb_t, scb_command, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) writeb(CTRL_CA | CTRL_ACK, REG_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (status & SCB_STCX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) ether1_xmit_done (dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (status & SCB_STCNA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (priv(dev)->resetting == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) printk (KERN_WARNING "%s: CU went not ready ???\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) priv(dev)->resetting += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) != (unsigned short)I82586_NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) ether1_writew(dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) writeb(CTRL_CA, REG_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (priv(dev)->resetting == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) priv(dev)->resetting = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (status & SCB_STFR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) ether1_recv_done (dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (status & SCB_STRNR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS) & SCB_STRXSUSP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) printk (KERN_WARNING "%s: RU went not ready: RU suspended\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) ether1_writew(dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) writeb(CTRL_CA, REG_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) dev->stats.rx_dropped++; /* we suspended due to lack of buffer space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) printk(KERN_WARNING "%s: RU went not ready: %04X\n", dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) printk (KERN_WARNING "RU ptr = %04X\n", ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) NORMALIRQS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) writeb(CTRL_ACK, REG_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) ether1_close (struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) ether1_reset (dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) free_irq(dev->irq, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) * Set or clear the multicast filter for this adaptor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) * num_addrs == -1 Promiscuous mode, receive all packets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * num_addrs == 0 Normal mode, clear multicast list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) * num_addrs > 0 Multicast mode, receive normal and MC packets, and do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) * best-effort filtering.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) ether1_setmulticastlist (struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) /* ------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) static void ether1_banner(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) static unsigned int version_printed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (net_debug && version_printed++ == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) printk(KERN_INFO "%s", version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) static const struct net_device_ops ether1_netdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) .ndo_open = ether1_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) .ndo_stop = ether1_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) .ndo_start_xmit = ether1_sendpacket,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) .ndo_set_rx_mode = ether1_setmulticastlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) .ndo_tx_timeout = ether1_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) .ndo_validate_addr = eth_validate_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) .ndo_set_mac_address = eth_mac_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) ether1_banner();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) ret = ecard_request_resources(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) dev = alloc_etherdev(sizeof(struct ether1_priv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) goto release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) SET_NETDEV_DEV(dev, &ec->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) dev->irq = ec->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) priv(dev)->base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (!priv(dev)->base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) goto free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) if ((priv(dev)->bus_type = ether1_reset(dev)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) goto free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) for (i = 0; i < 6; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) dev->dev_addr[i] = readb(IDPROM_ADDRESS + (i << 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (ether1_init_2(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) goto free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) dev->netdev_ops = ðer1_netdev_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) dev->watchdog_timeo = 5 * HZ / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) ret = register_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) goto free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) printk(KERN_INFO "%s: ether1 in slot %d, %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) dev->name, ec->slot_no, dev->dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) ecard_set_drvdata(ec, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) ecard_release_resources(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) static void ether1_remove(struct expansion_card *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) struct net_device *dev = ecard_get_drvdata(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) ecard_set_drvdata(ec, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) unregister_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) ecard_release_resources(ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) static const struct ecard_id ether1_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) { MANU_ACORN, PROD_ACORN_ETHER1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) { 0xffff, 0xffff }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) static struct ecard_driver ether1_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) .probe = ether1_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) .remove = ether1_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) .id_table = ether1_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) .drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) .name = "ether1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) static int __init ether1_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) return ecard_register_driver(ðer1_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) static void __exit ether1_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) ecard_remove_driver(ðer1_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) module_init(ether1_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) module_exit(ether1_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) MODULE_LICENSE("GPL");