patch-2.3.15 linux/drivers/net/fc/iph5526_novram.c

Next file: linux/drivers/net/fc/iph5526_scsi.h
Previous file: linux/drivers/net/fc/iph5526_ip.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.14/linux/drivers/net/fc/iph5526_novram.c linux/drivers/net/fc/iph5526_novram.c
@@ -0,0 +1,278 @@
+/********************************************************************** 
+ * Reading the NVRAM on the Interphase 5526 PCI Fibre Channel Card. 
+ * All contents in this file : courtesy Interphase Corporation.
+ * Special thanks to Kevin Quick, kquick@iphase.com.
+ **********************************************************************/
+
+#define FF_MAGIC        0x4646
+#define DB_MAGIC        0x4442
+#define DL_MAGIC        0x444d
+
+
+#define CMD_LEN         9
+
+/***********
+ *
+ *      Switches and defines for header files.
+ *
+ *      The following defines are used to turn on and off
+ *      various options in the header files. Primarily useful
+ *      for debugging.
+ *
+ ***********/
+
+static const unsigned short novram_default[4] = {
+    FF_MAGIC,
+    DB_MAGIC,
+    DL_MAGIC,
+    0 };
+
+
+/*
+ * a list of the commands that can be sent to the NOVRAM
+ */
+
+#define NR_EXTEND  0x100
+#define NR_WRITE   0x140
+#define NR_READ    0x180
+#define NR_ERASE   0x1c0
+
+#define EWDS    0x00
+#define WRAL    0x10
+#define ERAL    0x20
+#define EWEN    0x30
+
+/*
+ * Defines for the pins on the NOVRAM
+ */
+
+#define BIT(x)          (1 << (x))
+
+#define NVDI_B          31
+#define NVDI            BIT(NVDI_B)
+#define NVDO            BIT(9)
+#define NVCE            BIT(30)
+#define NVSK            BIT(29)
+#define NV_MANUAL       BIT(28)
+
+/***********
+ *
+ *      Include files.
+ *
+ ***********/
+
+#define KeStallExecutionProcessor(x)    {volatile int d, p;\
+		  for (d=0; d<x; d++) for (p=0; p<10; p++);\
+				     }
+
+
+/***********************
+ *
+ * This define ands the value and the current config register and puts
+ * the result in the config register
+ *
+ ***********************/
+
+#define CFG_AND(val) { volatile int t; \
+			   t = readl(fi->n_r.ptr_novram_hw_control_reg);   \
+			   t &= (val);                                  \
+			   writel(t, fi->n_r.ptr_novram_hw_control_reg);   \
+		   }
+
+/***********************
+ *
+ * This define ors the value and the current config register and puts
+ * the result in the config register
+ *
+ ***********************/
+
+#define CFG_OR(val) { volatile int t; \
+			   t = readl(fi->n_r.ptr_novram_hw_control_reg);   \
+			   t |= (val);                                  \
+			   writel(t, fi->n_r.ptr_novram_hw_control_reg);   \
+		   }
+
+/***********************
+ *
+ * Send a command to the NOVRAM, the command is in cmd.
+ *
+ * clear CE and SK. Then assert CE.
+ * Clock each of the command bits out in the correct order with SK
+ * exit with CE still asserted
+ *
+ ***********************/
+
+#define NVRAM_CMD(cmd) { int i; \
+			 int c = cmd; \
+			 CFG_AND(~(NVCE|NVSK)); \
+			 CFG_OR(NVCE); \
+			 for (i=0; i<CMD_LEN; i++) { \
+			     NVRAM_CLKOUT((c & (1 << (CMD_LEN - 1))) ? 1 : 0);\
+			     c <<= 1; } }
+
+/***********************
+ *
+ * clear the CE, this must be used after each command is complete
+ *
+ ***********************/
+
+#define NVRAM_CLR_CE    CFG_AND(~NVCE)
+
+/***********************
+ *
+ * clock the data bit in bitval out to the NOVRAM.  The bitval must be
+ * a 1 or 0, or the clockout operation is undefined
+ *
+ ***********************/
+
+#define NVRAM_CLKOUT(bitval) {\
+			   CFG_AND(~NVDI); \
+			   CFG_OR((bitval) << NVDI_B); \
+			   KeStallExecutionProcessor(5);\
+			   CFG_OR(NVSK); \
+			   KeStallExecutionProcessor(5);\
+			   CFG_AND( ~NVSK); \
+			   }
+
+/***********************
+ *
+ * clock the data bit in and return a 1 or 0, depending on the value
+ * that was received from the NOVRAM
+ *
+ ***********************/
+
+#define NVRAM_CLKIN(val)        {\
+		       CFG_OR(NVSK); \
+			   KeStallExecutionProcessor(5);\
+		       CFG_AND(~NVSK); \
+			   KeStallExecutionProcessor(5);\
+		       val = (readl(fi->n_r.ptr_novram_hw_status_reg) & NVDO) ? 1 : 0; \
+		       }
+
+/***********
+ *
+ *      Function Prototypes
+ *
+ ***********/
+
+static int iph5526_nr_get(struct fc_info *fi, int addr);
+static void iph5526_nr_do_init(struct fc_info *fi);
+static void iph5526_nr_checksum(struct fc_info *fi);
+
+
+/*******************************************************************
+ *
+ *      Local routine:  iph5526_nr_do_init
+ *      Purpose:        initialize novram server
+ *      Description:
+ *
+ *      iph5526_nr_do_init reads the novram into the temporary holding place.
+ *      A checksum is done on the area and the Magic Cookies are checked.
+ *      If any of them are bad, the NOVRAM is initialized with the 
+ *      default values and a warning message is displayed.
+ *
+ *******************************************************************/
+
+static void iph5526_nr_do_init(struct fc_info *fi)
+{
+    int i;
+    unsigned short chksum = 0;
+    int bad = 0;
+
+    for (i=0; i<IPH5526_NOVRAM_SIZE; i++) {
+	fi->n_r.data[i] = iph5526_nr_get(fi, i);
+	chksum += fi->n_r.data[i];
+    }
+
+    if (chksum) 
+	bad = 1;
+
+    if (fi->n_r.data[IPH5526_NOVRAM_SIZE - 4] != FF_MAGIC)
+	bad = 1;
+    if (fi->n_r.data[IPH5526_NOVRAM_SIZE - 3] != DB_MAGIC)
+	bad = 1;                 
+	if (fi->n_r.data[IPH5526_NOVRAM_SIZE - 2] != DL_MAGIC)
+	bad = 1;
+
+    if (bad) {
+	for (i=0; i<IPH5526_NOVRAM_SIZE; i++) {
+	    if (i < (IPH5526_NOVRAM_SIZE - 4)) {
+		fi->n_r.data[i] = 0xffff;
+	    } else {
+		fi->n_r.data[i] = novram_default[i - (IPH5526_NOVRAM_SIZE - 4)];
+	    }
+	}
+	iph5526_nr_checksum(fi);
+    }
+}
+
+
+/*******************************************************************
+ *
+ *      Local routine:  iph5526_nr_get
+ *      Purpose:        read a single word of NOVRAM
+ *      Description:
+ *
+ *      read the 16 bits that make up a word addr of the novram.  
+ *      The 16 bits of data that are read are returned as the return value
+ *
+ *******************************************************************/
+
+static int iph5526_nr_get(struct fc_info *fi, int addr)
+{
+    int i;
+    int t;
+    int val = 0;
+
+    CFG_OR(NV_MANUAL);
+
+    /*
+     * read the first bit that was clocked with the falling edge of the
+     * the last command data clock
+     */
+
+    NVRAM_CMD(NR_READ + addr);
+
+    /*
+     * Now read the rest of the bits, the next bit read is D1, then D2,
+     * and so on
+     */
+
+    val = 0;
+    for (i=0; i<16; i++) {
+	NVRAM_CLKIN(t);
+	val <<= 1;
+	val |= t;
+    }
+    NVRAM_CLR_CE;
+
+    CFG_OR(NVDI);
+    CFG_AND(~NV_MANUAL);
+
+    return(val);
+}
+
+
+
+
+/*******************************************************************
+ *
+ *      Local routine:  iph5526_nr_checksum
+ *      Purpose:        calculate novram checksum on fi->n_r.data
+ *      Description:
+ *
+ *      calculate a checksum for the novram on the image that is
+ *      currently in fi->n_r.data
+ *
+ *******************************************************************/
+
+static void iph5526_nr_checksum(struct fc_info *fi)
+{
+    int i;
+    unsigned short chksum = 0;
+
+    for (i=0; i<(IPH5526_NOVRAM_SIZE - 1); i++)
+	chksum += fi->n_r.data[i];
+
+    fi->n_r.data[i] = -chksum;
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)