0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 #include "aic7xxx_osm.h"
0068 #include "aic7xxx_inline.h"
0069 #include "aic7xxx_93cx6.h"
0070
0071
0072
0073
0074
0075 struct seeprom_cmd {
0076 uint8_t len;
0077 uint8_t bits[11];
0078 };
0079
0080
0081 static const struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
0082 static const struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
0083
0084
0085 static const struct seeprom_cmd seeprom_long_ewen = {11, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
0086 static const struct seeprom_cmd seeprom_long_ewds = {11, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
0087
0088
0089 static const struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
0090 static const struct seeprom_cmd seeprom_read = {3, {1, 1, 0}};
0091
0092
0093
0094
0095 #define CLOCK_PULSE(sd, rdy) \
0096 while ((SEEPROM_STATUS_INB(sd) & rdy) == 0) { \
0097 ; \
0098 } \
0099 (void)SEEPROM_INB(sd);
0100
0101
0102
0103
0104 static void
0105 send_seeprom_cmd(struct seeprom_descriptor *sd, const struct seeprom_cmd *cmd)
0106 {
0107 uint8_t temp;
0108 int i = 0;
0109
0110
0111 temp = sd->sd_MS ^ sd->sd_CS;
0112 SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
0113 CLOCK_PULSE(sd, sd->sd_RDY);
0114
0115 for (i = 0; i < cmd->len; i++) {
0116 if (cmd->bits[i] != 0)
0117 temp ^= sd->sd_DO;
0118 SEEPROM_OUTB(sd, temp);
0119 CLOCK_PULSE(sd, sd->sd_RDY);
0120 SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
0121 CLOCK_PULSE(sd, sd->sd_RDY);
0122 if (cmd->bits[i] != 0)
0123 temp ^= sd->sd_DO;
0124 }
0125 }
0126
0127
0128
0129
0130 static void
0131 reset_seeprom(struct seeprom_descriptor *sd)
0132 {
0133 uint8_t temp;
0134
0135 temp = sd->sd_MS;
0136 SEEPROM_OUTB(sd, temp);
0137 CLOCK_PULSE(sd, sd->sd_RDY);
0138 SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
0139 CLOCK_PULSE(sd, sd->sd_RDY);
0140 SEEPROM_OUTB(sd, temp);
0141 CLOCK_PULSE(sd, sd->sd_RDY);
0142 }
0143
0144
0145
0146
0147
0148 int
0149 ahc_read_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
0150 u_int start_addr, u_int count)
0151 {
0152 int i = 0;
0153 u_int k = 0;
0154 uint16_t v;
0155 uint8_t temp;
0156
0157
0158
0159
0160
0161 for (k = start_addr; k < count + start_addr; k++) {
0162
0163
0164
0165
0166 send_seeprom_cmd(sd, &seeprom_read);
0167
0168
0169 temp = sd->sd_MS ^ sd->sd_CS;
0170 for (i = (sd->sd_chip - 1); i >= 0; i--) {
0171 if ((k & (1 << i)) != 0)
0172 temp ^= sd->sd_DO;
0173 SEEPROM_OUTB(sd, temp);
0174 CLOCK_PULSE(sd, sd->sd_RDY);
0175 SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
0176 CLOCK_PULSE(sd, sd->sd_RDY);
0177 if ((k & (1 << i)) != 0)
0178 temp ^= sd->sd_DO;
0179 }
0180
0181
0182
0183
0184
0185
0186
0187 v = 0;
0188 for (i = 16; i >= 0; i--) {
0189 SEEPROM_OUTB(sd, temp);
0190 CLOCK_PULSE(sd, sd->sd_RDY);
0191 v <<= 1;
0192 if (SEEPROM_DATA_INB(sd) & sd->sd_DI)
0193 v |= 1;
0194 SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
0195 CLOCK_PULSE(sd, sd->sd_RDY);
0196 }
0197
0198 buf[k - start_addr] = v;
0199
0200
0201 reset_seeprom(sd);
0202 }
0203 #ifdef AHC_DUMP_EEPROM
0204 printk("\nSerial EEPROM:\n\t");
0205 for (k = 0; k < count; k = k + 1) {
0206 if (((k % 8) == 0) && (k != 0)) {
0207 printk(KERN_CONT "\n\t");
0208 }
0209 printk(KERN_CONT " 0x%x", buf[k]);
0210 }
0211 printk(KERN_CONT "\n");
0212 #endif
0213 return (1);
0214 }
0215
0216
0217
0218
0219
0220 int
0221 ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
0222 u_int start_addr, u_int count)
0223 {
0224 const struct seeprom_cmd *ewen, *ewds;
0225 uint16_t v;
0226 uint8_t temp;
0227 int i, k;
0228
0229
0230 if (sd->sd_chip == C46) {
0231 ewen = &seeprom_ewen;
0232 ewds = &seeprom_ewds;
0233 } else if (sd->sd_chip == C56_66) {
0234 ewen = &seeprom_long_ewen;
0235 ewds = &seeprom_long_ewds;
0236 } else {
0237 printk("ahc_write_seeprom: unsupported seeprom type %d\n",
0238 sd->sd_chip);
0239 return (0);
0240 }
0241
0242 send_seeprom_cmd(sd, ewen);
0243 reset_seeprom(sd);
0244
0245
0246 temp = sd->sd_MS ^ sd->sd_CS;
0247 for (k = start_addr; k < count + start_addr; k++) {
0248
0249 send_seeprom_cmd(sd, &seeprom_write);
0250
0251
0252 for (i = (sd->sd_chip - 1); i >= 0; i--) {
0253 if ((k & (1 << i)) != 0)
0254 temp ^= sd->sd_DO;
0255 SEEPROM_OUTB(sd, temp);
0256 CLOCK_PULSE(sd, sd->sd_RDY);
0257 SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
0258 CLOCK_PULSE(sd, sd->sd_RDY);
0259 if ((k & (1 << i)) != 0)
0260 temp ^= sd->sd_DO;
0261 }
0262
0263
0264 v = buf[k - start_addr];
0265 for (i = 15; i >= 0; i--) {
0266 if ((v & (1 << i)) != 0)
0267 temp ^= sd->sd_DO;
0268 SEEPROM_OUTB(sd, temp);
0269 CLOCK_PULSE(sd, sd->sd_RDY);
0270 SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
0271 CLOCK_PULSE(sd, sd->sd_RDY);
0272 if ((v & (1 << i)) != 0)
0273 temp ^= sd->sd_DO;
0274 }
0275
0276
0277 temp = sd->sd_MS;
0278 SEEPROM_OUTB(sd, temp);
0279 CLOCK_PULSE(sd, sd->sd_RDY);
0280 temp = sd->sd_MS ^ sd->sd_CS;
0281 do {
0282 SEEPROM_OUTB(sd, temp);
0283 CLOCK_PULSE(sd, sd->sd_RDY);
0284 SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
0285 CLOCK_PULSE(sd, sd->sd_RDY);
0286 } while ((SEEPROM_DATA_INB(sd) & sd->sd_DI) == 0);
0287
0288 reset_seeprom(sd);
0289 }
0290
0291
0292 send_seeprom_cmd(sd, ewds);
0293 reset_seeprom(sd);
0294
0295 return (1);
0296 }
0297
0298 int
0299 ahc_verify_cksum(struct seeprom_config *sc)
0300 {
0301 int i;
0302 int maxaddr;
0303 uint32_t checksum;
0304 uint16_t *scarray;
0305
0306 maxaddr = (sizeof(*sc)/2) - 1;
0307 checksum = 0;
0308 scarray = (uint16_t *)sc;
0309
0310 for (i = 0; i < maxaddr; i++)
0311 checksum = checksum + scarray[i];
0312 if (checksum == 0
0313 || (checksum & 0xFFFF) != sc->checksum) {
0314 return (0);
0315 } else {
0316 return(1);
0317 }
0318 }