iph5526_novram.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:7k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /********************************************************************** 
  2.  * Reading the NVRAM on the Interphase 5526 PCI Fibre Channel Card. 
  3.  * All contents in this file : courtesy Interphase Corporation.
  4.  * Special thanks to Kevin Quick, kquick@iphase.com.
  5.  **********************************************************************/
  6. #define FF_MAGIC        0x4646
  7. #define DB_MAGIC        0x4442
  8. #define DL_MAGIC        0x444d
  9. #define CMD_LEN         9
  10. /***********
  11.  *
  12.  *      Switches and defines for header files.
  13.  *
  14.  *      The following defines are used to turn on and off
  15.  *      various options in the header files. Primarily useful
  16.  *      for debugging.
  17.  *
  18.  ***********/
  19. static const unsigned short novram_default[4] = {
  20.     FF_MAGIC,
  21.     DB_MAGIC,
  22.     DL_MAGIC,
  23.     0 };
  24. /*
  25.  * a list of the commands that can be sent to the NOVRAM
  26.  */
  27. #define NR_EXTEND  0x100
  28. #define NR_WRITE   0x140
  29. #define NR_READ    0x180
  30. #define NR_ERASE   0x1c0
  31. #define EWDS    0x00
  32. #define WRAL    0x10
  33. #define ERAL    0x20
  34. #define EWEN    0x30
  35. /*
  36.  * Defines for the pins on the NOVRAM
  37.  */
  38. #define BIT(x)          (1 << (x))
  39. #define NVDI_B          31
  40. #define NVDI            BIT(NVDI_B)
  41. #define NVDO            BIT(9)
  42. #define NVCE            BIT(30)
  43. #define NVSK            BIT(29)
  44. #define NV_MANUAL       BIT(28)
  45. /***********
  46.  *
  47.  *      Include files.
  48.  *
  49.  ***********/
  50. #define KeStallExecutionProcessor(x)    {volatile int d, p;
  51.   for (d=0; d<x; d++) for (p=0; p<10; p++);
  52.      }
  53. /***********************
  54.  *
  55.  * This define ands the value and the current config register and puts
  56.  * the result in the config register
  57.  *
  58.  ***********************/
  59. #define CFG_AND(val) { volatile int t; 
  60.    t = readl(fi->n_r.ptr_novram_hw_control_reg);   
  61.    t &= (val);                                  
  62.    writel(t, fi->n_r.ptr_novram_hw_control_reg);   
  63.    }
  64. /***********************
  65.  *
  66.  * This define ors the value and the current config register and puts
  67.  * the result in the config register
  68.  *
  69.  ***********************/
  70. #define CFG_OR(val) { volatile int t; 
  71.    t = readl(fi->n_r.ptr_novram_hw_control_reg);   
  72.    t |= (val);                                  
  73.    writel(t, fi->n_r.ptr_novram_hw_control_reg);   
  74.    }
  75. /***********************
  76.  *
  77.  * Send a command to the NOVRAM, the command is in cmd.
  78.  *
  79.  * clear CE and SK. Then assert CE.
  80.  * Clock each of the command bits out in the correct order with SK
  81.  * exit with CE still asserted
  82.  *
  83.  ***********************/
  84. #define NVRAM_CMD(cmd) { int i; 
  85.  int c = cmd; 
  86.  CFG_AND(~(NVCE|NVSK)); 
  87.  CFG_OR(NVCE); 
  88.  for (i=0; i<CMD_LEN; i++) { 
  89.      NVRAM_CLKOUT((c & (1 << (CMD_LEN - 1))) ? 1 : 0);
  90.      c <<= 1; } }
  91. /***********************
  92.  *
  93.  * clear the CE, this must be used after each command is complete
  94.  *
  95.  ***********************/
  96. #define NVRAM_CLR_CE    CFG_AND(~NVCE)
  97. /***********************
  98.  *
  99.  * clock the data bit in bitval out to the NOVRAM.  The bitval must be
  100.  * a 1 or 0, or the clockout operation is undefined
  101.  *
  102.  ***********************/
  103. #define NVRAM_CLKOUT(bitval) {
  104.    CFG_AND(~NVDI); 
  105.    CFG_OR((bitval) << NVDI_B); 
  106.    KeStallExecutionProcessor(5);
  107.    CFG_OR(NVSK); 
  108.    KeStallExecutionProcessor(5);
  109.    CFG_AND( ~NVSK); 
  110.    }
  111. /***********************
  112.  *
  113.  * clock the data bit in and return a 1 or 0, depending on the value
  114.  * that was received from the NOVRAM
  115.  *
  116.  ***********************/
  117. #define NVRAM_CLKIN(val)        {
  118.        CFG_OR(NVSK); 
  119.    KeStallExecutionProcessor(5);
  120.        CFG_AND(~NVSK); 
  121.    KeStallExecutionProcessor(5);
  122.        val = (readl(fi->n_r.ptr_novram_hw_status_reg) & NVDO) ? 1 : 0; 
  123.        }
  124. /***********
  125.  *
  126.  *      Function Prototypes
  127.  *
  128.  ***********/
  129. static int iph5526_nr_get(struct fc_info *fi, int addr);
  130. static void iph5526_nr_do_init(struct fc_info *fi);
  131. static void iph5526_nr_checksum(struct fc_info *fi);
  132. /*******************************************************************
  133.  *
  134.  *      Local routine:  iph5526_nr_do_init
  135.  *      Purpose:        initialize novram server
  136.  *      Description:
  137.  *
  138.  *      iph5526_nr_do_init reads the novram into the temporary holding place.
  139.  *      A checksum is done on the area and the Magic Cookies are checked.
  140.  *      If any of them are bad, the NOVRAM is initialized with the 
  141.  *      default values and a warning message is displayed.
  142.  *
  143.  *******************************************************************/
  144. static void iph5526_nr_do_init(struct fc_info *fi)
  145. {
  146.     int i;
  147.     unsigned short chksum = 0;
  148.     int bad = 0;
  149.     for (i=0; i<IPH5526_NOVRAM_SIZE; i++) {
  150. fi->n_r.data[i] = iph5526_nr_get(fi, i);
  151. chksum += fi->n_r.data[i];
  152.     }
  153.     if (chksum) 
  154. bad = 1;
  155.     if (fi->n_r.data[IPH5526_NOVRAM_SIZE - 4] != FF_MAGIC)
  156. bad = 1;
  157.     if (fi->n_r.data[IPH5526_NOVRAM_SIZE - 3] != DB_MAGIC)
  158. bad = 1;                 
  159. if (fi->n_r.data[IPH5526_NOVRAM_SIZE - 2] != DL_MAGIC)
  160. bad = 1;
  161.     if (bad) {
  162. for (i=0; i<IPH5526_NOVRAM_SIZE; i++) {
  163.     if (i < (IPH5526_NOVRAM_SIZE - 4)) {
  164. fi->n_r.data[i] = 0xffff;
  165.     } else {
  166. fi->n_r.data[i] = novram_default[i - (IPH5526_NOVRAM_SIZE - 4)];
  167.     }
  168. }
  169. iph5526_nr_checksum(fi);
  170.     }
  171. }
  172. /*******************************************************************
  173.  *
  174.  *      Local routine:  iph5526_nr_get
  175.  *      Purpose:        read a single word of NOVRAM
  176.  *      Description:
  177.  *
  178.  *      read the 16 bits that make up a word addr of the novram.  
  179.  *      The 16 bits of data that are read are returned as the return value
  180.  *
  181.  *******************************************************************/
  182. static int iph5526_nr_get(struct fc_info *fi, int addr)
  183. {
  184.     int i;
  185.     int t;
  186.     int val = 0;
  187.     CFG_OR(NV_MANUAL);
  188.     /*
  189.      * read the first bit that was clocked with the falling edge of the
  190.      * the last command data clock
  191.      */
  192.     NVRAM_CMD(NR_READ + addr);
  193.     /*
  194.      * Now read the rest of the bits, the next bit read is D1, then D2,
  195.      * and so on
  196.      */
  197.     val = 0;
  198.     for (i=0; i<16; i++) {
  199. NVRAM_CLKIN(t);
  200. val <<= 1;
  201. val |= t;
  202.     }
  203.     NVRAM_CLR_CE;
  204.     CFG_OR(NVDI);
  205.     CFG_AND(~NV_MANUAL);
  206.     return(val);
  207. }
  208. /*******************************************************************
  209.  *
  210.  *      Local routine:  iph5526_nr_checksum
  211.  *      Purpose:        calculate novram checksum on fi->n_r.data
  212.  *      Description:
  213.  *
  214.  *      calculate a checksum for the novram on the image that is
  215.  *      currently in fi->n_r.data
  216.  *
  217.  *******************************************************************/
  218. static void iph5526_nr_checksum(struct fc_info *fi)
  219. {
  220.     int i;
  221.     unsigned short chksum = 0;
  222.     for (i=0; i<(IPH5526_NOVRAM_SIZE - 1); i++)
  223. chksum += fi->n_r.data[i];
  224.     fi->n_r.data[i] = -chksum;
  225. }