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

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)