Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 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; } |