patch-2.4.19 linux-2.4.19/drivers/net/ioc3-eth.c
Next file: linux-2.4.19/drivers/net/irda/Config.in
Previous file: linux-2.4.19/drivers/net/hydra.c
Back to the patch index
Back to the overall index
- Lines: 277
- Date:
Fri Aug 2 17:39:44 2002
- Orig file:
linux-2.4.18/drivers/net/ioc3-eth.c
- Orig date:
Fri Dec 21 09:41:54 2001
diff -urN linux-2.4.18/drivers/net/ioc3-eth.c linux-2.4.19/drivers/net/ioc3-eth.c
@@ -26,6 +26,7 @@
* which workarounds are required for them? Do we ever have Lucent's?
* o For the 2.5 branch kill the mii-tool ioctls.
*/
+#include <linux/config.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/kernel.h>
@@ -33,6 +34,7 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/crc32.h>
#ifdef CONFIG_SERIAL
#include <linux/serial.h>
@@ -340,14 +342,15 @@
}
/*
- * Read the NIC (Number-In-a-Can) device.
+ * Read the NIC (Number-In-a-Can) device used to store the MAC address on
+ * SN0 / SN00 nodeboards and PCI cards.
*/
-static void ioc3_get_eaddr(struct ioc3_private *ip)
+static void ioc3_get_eaddr_nic(struct ioc3_private *ip)
{
struct ioc3 *ioc3 = ip->regs;
u8 nic[14];
- int i;
int tries = 2; /* There may be some problem with the battery? */
+ int i;
ioc3_w(gpcr_s, (1 << 21));
@@ -370,16 +373,123 @@
for (i = 13; i >= 0; i--)
nic[i] = nic_read_byte(ioc3);
- printk("Ethernet address is ");
- for (i = 2; i < 8; i++) {
+ for (i = 2; i < 8; i++)
ip->dev->dev_addr[i - 2] = nic[i];
- printk("%02x", nic[i]);
+}
+
+#if defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_SGI_SN2)
+/*
+ * Get the ether-address on SN1 nodes
+ */
+static void ioc3_get_eaddr_sn(struct ioc3_private *ip)
+{
+ int ibrick_mac_addr_get(nasid_t, char *);
+ struct ioc3 *ioc3 = ip->regs;
+ nasid_t nasid_of_ioc3;
+ char io7eaddr[20];
+ long mac;
+ int err_val;
+
+ /*
+ * err_val = ibrick_mac_addr_get(get_nasid(), io7eaddr );
+ *
+ * BAD!! The above call uses get_nasid() and assumes that
+ * the ioc3 pointed to by struct ioc3 is hooked up to the
+ * cbrick that we're running on. The proper way to make this call
+ * is to figure out which nasid the ioc3 is connected to
+ * and use that to call ibrick_mac_addr_get. Below is
+ * a hack to do just that.
+ */
+
+ /*
+ * Get the nasid of the ioc3 from the ioc3's base addr.
+ * FIXME: the 8 at the end assumes we're in memory mode,
+ * not node mode (for that, we'd change it to a 9).
+ * Is there a call to extract this info from a physical
+ * addr somewhere in an sn header file already? If so,
+ * we should probably use that, or restructure this routine
+ * to use pci_dev and generic numa nodeid getting stuff.
+ */
+ nasid_of_ioc3 = (((unsigned long)ioc3 >> 33) & ~(-1 << 8));
+ err_val = ibrick_mac_addr_get(nasid_of_ioc3, io7eaddr );
+
+
+ if (err_val) {
+ /* Couldn't read the eeprom; try OSLoadOptions. */
+ printk("WARNING: ibrick_mac_addr_get failed: %d\n", err_val);
+
+ /* this is where we hardwire the mac address
+ * 1st ibrick had 08:00:69:11:34:75
+ * 2nd ibrick had 08:00:69:11:35:35
+ *
+ * Eagan Machines:
+ * mankato1 08:00:69:11:BE:95
+ * warroad 08:00:69:11:bd:60
+ * duron 08:00:69:11:34:60
+ *
+ * an easy way to get the mac address is to hook
+ * up an ip35, then from L1 do 'cti serial'
+ * and then look for MAC line XXX THIS DOESN"T QUITE WORK!!
+ */
+ printk("ioc3_get_eaddr: setting ethernet address to:\n -----> ");
+ ip->dev->dev_addr[0] = 0x8;
+ ip->dev->dev_addr[1] = 0x0;
+ ip->dev->dev_addr[2] = 0x69;
+ ip->dev->dev_addr[3] = 0x11;
+ ip->dev->dev_addr[4] = 0x34;
+ ip->dev->dev_addr[5] = 0x60;
+ }
+ else {
+ long simple_strtol(const char *,char **,unsigned int);
+
+ mac = simple_strtol(io7eaddr, (char **)0, 16);
+ ip->dev->dev_addr[0] = (mac >> 40) & 0xff;
+ ip->dev->dev_addr[1] = (mac >> 32) & 0xff;
+ ip->dev->dev_addr[2] = (mac >> 24) & 0xff;
+ ip->dev->dev_addr[3] = (mac >> 16) & 0xff;
+ ip->dev->dev_addr[4] = (mac >> 8) & 0xff;
+ ip->dev->dev_addr[5] = mac & 0xff;
+ }
+}
+#endif
+
+/*
+ * Ok, this is hosed by design. It's necessary to know what machine the
+ * NIC is in in order to know how to read the NIC address. We also have
+ * to know if it's a PCI card or a NIC in on the node board ...
+ */
+static void ioc3_get_eaddr(struct ioc3_private *ip)
+{
+ void (*do_get_eaddr)(struct ioc3_private *ip) = NULL;
+ int i;
+
+ /*
+ * We should also use this code for PCI cards, no matter what host
+ * machine but how to know that we're a PCI card?
+ */
+#ifdef CONFIG_SGI_IP27
+ do_get_eaddr = ioc3_get_eaddr_nic;
+#endif
+#if defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_SGI_SN2)
+ do_get_eaddr = ioc3_get_eaddr_sn;
+#endif
+
+ if (!do_get_eaddr) {
+ printk(KERN_ERR "Don't know how to read MAC address of this "
+ "IOC3 NIC\n");
+ return;
+ }
+
+ printk("Ethernet address is ");
+ for (i = 0; i < 6; i++) {
+ printk("%02x", ip->dev->dev_addr[i]);
if (i < 7)
printk(":");
}
printk(".\n");
}
+
/*
* Caller must hold the ioc3_lock ever for MII readers. This is also
* used to protect the transmitter side but it's low contention.
@@ -434,10 +544,10 @@
skb = ip->rx_skbs[rx_entry];
rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET);
- w0 = rxb->w0;
+ w0 = be32_to_cpu(rxb->w0);
while (w0 & ERXBUF_V) {
- err = rxb->err; /* It's valid ... */
+ err = be32_to_cpu(rxb->err); /* It's valid ... */
if (err & ERXBUF_GOODPKT) {
len = ((w0 >> ERXBUF_BYTECNT_SHIFT) & 0x7ff) - 4;
skb_trim(skb, len);
@@ -478,8 +588,8 @@
ip->stats.rx_frame_errors++;
next:
ip->rx_skbs[n_entry] = new_skb;
- rxr[n_entry] = (0xa5UL << 56) |
- ((unsigned long) rxb & TO_PHYS_MASK);
+ rxr[n_entry] = cpu_to_be32((0xa5UL << 56) |
+ ((unsigned long) rxb & TO_PHYS_MASK));
rxb->w0 = 0; /* Clear valid flag */
n_entry = (n_entry + 1) & 511; /* Update erpir */
@@ -487,7 +597,7 @@
rx_entry = (rx_entry + 1) & 511;
skb = ip->rx_skbs[rx_entry];
rxb = (struct ioc3_erxbuf *) (skb->data - RX_OFFSET);
- w0 = rxb->w0;
+ w0 = be32_to_cpu(rxb->w0);
}
ioc3->erpir = (n_entry << 3) | ERPIR_ARM;
ip->rx_pi = n_entry;
@@ -1189,8 +1299,8 @@
/* Because we reserve afterwards. */
skb_put(skb, (1664 + RX_OFFSET));
rxb = (struct ioc3_erxbuf *) skb->data;
- rxr[i] = (0xa5UL << 56)
- | ((unsigned long) rxb & TO_PHYS_MASK);
+ rxr[i] = cpu_to_be64((0xa5UL << 56) |
+ ((unsigned long) rxb & TO_PHYS_MASK));
skb_reserve(skb, RX_OFFSET);
}
ip->rx_ci = 0;
@@ -1554,8 +1664,8 @@
memset(desc->data + len, 0, ETH_ZLEN - len);
len = ETH_ZLEN;
}
- desc->cmd = len | ETXD_INTWHENDONE | ETXD_D0V;
- desc->bufcnt = len;
+ desc->cmd = cpu_to_be32(len | ETXD_INTWHENDONE | ETXD_D0V);
+ desc->bufcnt = cpu_to_be32(len);
} else if ((data ^ (data + len)) & 0x4000) {
unsigned long b2, s1, s2;
@@ -1563,16 +1673,20 @@
s1 = b2 - data;
s2 = data + len - b2;
- desc->cmd = len | ETXD_INTWHENDONE | ETXD_B1V | ETXD_B2V;
- desc->bufcnt = (s1 << ETXD_B1CNT_SHIFT) |
- (s2 << ETXD_B2CNT_SHIFT);
- desc->p1 = (0xa5UL << 56) | (data & TO_PHYS_MASK);
- desc->p2 = (0xa5UL << 56) | (data & TO_PHYS_MASK);
+ desc->cmd = cpu_to_be32(len | ETXD_INTWHENDONE |
+ ETXD_B1V | ETXD_B2V);
+ desc->bufcnt = cpu_to_be32((s1 << ETXD_B1CNT_SHIFT)
+ | (s2 << ETXD_B2CNT_SHIFT));
+ desc->p1 = cpu_to_be64((0xa5UL << 56) |
+ (data & TO_PHYS_MASK));
+ desc->p2 = cpu_to_be64((0xa5UL << 56) |
+ (data & TO_PHYS_MASK));
} else {
/* Normal sized packet that doesn't cross a page boundary. */
- desc->cmd = len | ETXD_INTWHENDONE | ETXD_B1V;
- desc->bufcnt = len << ETXD_B1CNT_SHIFT;
- desc->p1 = (0xa5UL << 56) | (data & TO_PHYS_MASK);
+ desc->cmd = cpu_to_be32(len | ETXD_INTWHENDONE | ETXD_B1V);
+ desc->bufcnt = cpu_to_be32(len << ETXD_B1CNT_SHIFT);
+ desc->p1 = cpu_to_be64((0xa5UL << 56) |
+ (data & TO_PHYS_MASK));
}
BARRIER();
@@ -1611,27 +1725,16 @@
* Given a multicast ethernet address, this routine calculates the
* address's bit index in the logical address filter mask
*/
-#define CRC_MASK 0xedb88320
static inline unsigned int
ioc3_hash(const unsigned char *addr)
{
unsigned int temp = 0;
unsigned char byte;
- unsigned int crc;
- int bits, len;
+ u32 crc;
+ int bits;
- len = ETH_ALEN;
- for (crc = ~0; --len >= 0; addr++) {
- byte = *addr;
- for (bits = 8; --bits >= 0; ) {
- if ((byte ^ crc) & 1)
- crc = (crc >> 1) ^ CRC_MASK;
- else
- crc >>= 1;
- byte >>= 1;
- }
- }
+ crc = ether_crc_le(ETH_ALEN, addr);
crc &= 0x3f; /* bit reverse lowest 6 bits for hash index */
for (bits = 6; --bits >= 0; ) {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)