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 #include "aic7xxx_osm.h"
0046 #include "aic7xxx_inline.h"
0047 #include "aic7xxx_93cx6.h"
0048
0049 #define ID_AIC7770 0x04907770
0050 #define ID_AHA_274x 0x04907771
0051 #define ID_AHA_284xB 0x04907756
0052 #define ID_AHA_284x 0x04907757
0053 #define ID_OLV_274x 0x04907782
0054 #define ID_OLV_274xD 0x04907783
0055
0056 static int aic7770_chip_init(struct ahc_softc *ahc);
0057 static int aha2840_load_seeprom(struct ahc_softc *ahc);
0058 static ahc_device_setup_t ahc_aic7770_VL_setup;
0059 static ahc_device_setup_t ahc_aic7770_EISA_setup;
0060 static ahc_device_setup_t ahc_aic7770_setup;
0061
0062 struct aic7770_identity aic7770_ident_table[] =
0063 {
0064 {
0065 ID_AHA_274x,
0066 0xFFFFFFFF,
0067 "Adaptec 274X SCSI adapter",
0068 ahc_aic7770_EISA_setup
0069 },
0070 {
0071 ID_AHA_284xB,
0072 0xFFFFFFFE,
0073 "Adaptec 284X SCSI adapter",
0074 ahc_aic7770_VL_setup
0075 },
0076 {
0077 ID_AHA_284x,
0078 0xFFFFFFFE,
0079 "Adaptec 284X SCSI adapter (BIOS Disabled)",
0080 ahc_aic7770_VL_setup
0081 },
0082 {
0083 ID_OLV_274x,
0084 0xFFFFFFFF,
0085 "Adaptec (Olivetti OEM) 274X SCSI adapter",
0086 ahc_aic7770_EISA_setup
0087 },
0088 {
0089 ID_OLV_274xD,
0090 0xFFFFFFFF,
0091 "Adaptec (Olivetti OEM) 274X Differential SCSI adapter",
0092 ahc_aic7770_EISA_setup
0093 },
0094
0095 {
0096 ID_AIC7770,
0097 0xFFFFFFFF,
0098 "Adaptec aic7770 SCSI adapter",
0099 ahc_aic7770_EISA_setup
0100 }
0101 };
0102 const int ahc_num_aic7770_devs = ARRAY_SIZE(aic7770_ident_table);
0103
0104 struct aic7770_identity *
0105 aic7770_find_device(uint32_t id)
0106 {
0107 struct aic7770_identity *entry;
0108 int i;
0109
0110 for (i = 0; i < ahc_num_aic7770_devs; i++) {
0111 entry = &aic7770_ident_table[i];
0112 if (entry->full_id == (id & entry->id_mask))
0113 return (entry);
0114 }
0115 return (NULL);
0116 }
0117
0118 int
0119 aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
0120 {
0121 int error;
0122 int have_seeprom;
0123 u_int hostconf;
0124 u_int irq;
0125 u_int intdef;
0126
0127 error = entry->setup(ahc);
0128 have_seeprom = 0;
0129 if (error != 0)
0130 return (error);
0131
0132 error = aic7770_map_registers(ahc, io);
0133 if (error != 0)
0134 return (error);
0135
0136
0137
0138
0139
0140
0141
0142 ahc_intr_enable(ahc, FALSE);
0143
0144 ahc->description = entry->name;
0145 error = ahc_softc_init(ahc);
0146 if (error != 0)
0147 return (error);
0148
0149 ahc->bus_chip_init = aic7770_chip_init;
0150
0151 error = ahc_reset(ahc, FALSE);
0152 if (error != 0)
0153 return (error);
0154
0155
0156 intdef = ahc_inb(ahc, INTDEF);
0157 irq = intdef & VECTOR;
0158 switch (irq) {
0159 case 9:
0160 case 10:
0161 case 11:
0162 case 12:
0163 case 14:
0164 case 15:
0165 break;
0166 default:
0167 printk("aic7770_config: invalid irq setting %d\n", intdef);
0168 return (ENXIO);
0169 }
0170
0171 if ((intdef & EDGE_TRIG) != 0)
0172 ahc->flags |= AHC_EDGE_INTERRUPT;
0173
0174 switch (ahc->chip & (AHC_EISA|AHC_VL)) {
0175 case AHC_EISA:
0176 {
0177 u_int biosctrl;
0178 u_int scsiconf;
0179 u_int scsiconf1;
0180
0181 biosctrl = ahc_inb(ahc, HA_274_BIOSCTRL);
0182 scsiconf = ahc_inb(ahc, SCSICONF);
0183 scsiconf1 = ahc_inb(ahc, SCSICONF + 1);
0184
0185
0186 if ((biosctrl & CHANNEL_B_PRIMARY) != 0)
0187 ahc->flags |= 1;
0188
0189 if ((biosctrl & BIOSMODE) == BIOSDISABLED) {
0190 ahc->flags |= AHC_USEDEFAULTS;
0191 } else {
0192 if ((ahc->features & AHC_WIDE) != 0) {
0193 ahc->our_id = scsiconf1 & HWSCSIID;
0194 if (scsiconf & TERM_ENB)
0195 ahc->flags |= AHC_TERM_ENB_A;
0196 } else {
0197 ahc->our_id = scsiconf & HSCSIID;
0198 ahc->our_id_b = scsiconf1 & HSCSIID;
0199 if (scsiconf & TERM_ENB)
0200 ahc->flags |= AHC_TERM_ENB_A;
0201 if (scsiconf1 & TERM_ENB)
0202 ahc->flags |= AHC_TERM_ENB_B;
0203 }
0204 }
0205 if ((ahc_inb(ahc, HA_274_BIOSGLOBAL) & HA_274_EXTENDED_TRANS))
0206 ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B;
0207 break;
0208 }
0209 case AHC_VL:
0210 {
0211 have_seeprom = aha2840_load_seeprom(ahc);
0212 break;
0213 }
0214 default:
0215 break;
0216 }
0217 if (have_seeprom == 0) {
0218 kfree(ahc->seep_config);
0219 ahc->seep_config = NULL;
0220 }
0221
0222
0223
0224
0225 ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~AUTOFLUSHDIS);
0226
0227
0228 hostconf = ahc_inb(ahc, HOSTCONF);
0229 ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH);
0230 ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF);
0231
0232 ahc->bus_softc.aic7770_softc.busspd = hostconf & DFTHRSH;
0233 ahc->bus_softc.aic7770_softc.bustime = (hostconf << 2) & BOFF;
0234
0235
0236
0237
0238 error = ahc_init(ahc);
0239 if (error != 0)
0240 return (error);
0241
0242 error = aic7770_map_int(ahc, irq);
0243 if (error != 0)
0244 return (error);
0245
0246 ahc->init_level++;
0247
0248
0249
0250
0251 ahc_outb(ahc, BCTL, ENABLE);
0252 return (0);
0253 }
0254
0255 static int
0256 aic7770_chip_init(struct ahc_softc *ahc)
0257 {
0258 ahc_outb(ahc, BUSSPD, ahc->bus_softc.aic7770_softc.busspd);
0259 ahc_outb(ahc, BUSTIME, ahc->bus_softc.aic7770_softc.bustime);
0260 ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~AUTOFLUSHDIS);
0261 ahc_outb(ahc, BCTL, ENABLE);
0262 return (ahc_chip_init(ahc));
0263 }
0264
0265
0266
0267
0268 static int
0269 aha2840_load_seeprom(struct ahc_softc *ahc)
0270 {
0271 struct seeprom_descriptor sd;
0272 struct seeprom_config *sc;
0273 int have_seeprom;
0274 uint8_t scsi_conf;
0275
0276 sd.sd_ahc = ahc;
0277 sd.sd_control_offset = SEECTL_2840;
0278 sd.sd_status_offset = STATUS_2840;
0279 sd.sd_dataout_offset = STATUS_2840;
0280 sd.sd_chip = C46;
0281 sd.sd_MS = 0;
0282 sd.sd_RDY = EEPROM_TF;
0283 sd.sd_CS = CS_2840;
0284 sd.sd_CK = CK_2840;
0285 sd.sd_DO = DO_2840;
0286 sd.sd_DI = DI_2840;
0287 sc = ahc->seep_config;
0288
0289 if (bootverbose)
0290 printk("%s: Reading SEEPROM...", ahc_name(ahc));
0291 have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc,
0292 0, sizeof(*sc)/2);
0293
0294 if (have_seeprom) {
0295
0296 if (ahc_verify_cksum(sc) == 0) {
0297 if(bootverbose)
0298 printk ("checksum error\n");
0299 have_seeprom = 0;
0300 } else if (bootverbose) {
0301 printk("done.\n");
0302 }
0303 }
0304
0305 if (!have_seeprom) {
0306 if (bootverbose)
0307 printk("%s: No SEEPROM available\n", ahc_name(ahc));
0308 ahc->flags |= AHC_USEDEFAULTS;
0309 } else {
0310
0311
0312
0313
0314 int i;
0315 int max_targ;
0316 uint16_t discenable;
0317
0318 max_targ = (ahc->features & AHC_WIDE) != 0 ? 16 : 8;
0319 discenable = 0;
0320 for (i = 0; i < max_targ; i++){
0321 uint8_t target_settings;
0322
0323 target_settings = (sc->device_flags[i] & CFXFER) << 4;
0324 if (sc->device_flags[i] & CFSYNCH)
0325 target_settings |= SOFS;
0326 if (sc->device_flags[i] & CFWIDEB)
0327 target_settings |= WIDEXFER;
0328 if (sc->device_flags[i] & CFDISC)
0329 discenable |= (0x01 << i);
0330 ahc_outb(ahc, TARG_SCSIRATE + i, target_settings);
0331 }
0332 ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));
0333 ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));
0334
0335 ahc->our_id = sc->brtime_id & CFSCSIID;
0336
0337 scsi_conf = (ahc->our_id & 0x7);
0338 if (sc->adapter_control & CFSPARITY)
0339 scsi_conf |= ENSPCHK;
0340 if (sc->adapter_control & CFRESETB)
0341 scsi_conf |= RESET_SCSI;
0342
0343 if (sc->bios_control & CF284XEXTEND)
0344 ahc->flags |= AHC_EXTENDED_TRANS_A;
0345
0346 ahc_outb(ahc, SCSICONF, scsi_conf);
0347
0348 if (sc->adapter_control & CF284XSTERM)
0349 ahc->flags |= AHC_TERM_ENB_A;
0350 }
0351 return (have_seeprom);
0352 }
0353
0354 static int
0355 ahc_aic7770_VL_setup(struct ahc_softc *ahc)
0356 {
0357 int error;
0358
0359 error = ahc_aic7770_setup(ahc);
0360 ahc->chip |= AHC_VL;
0361 return (error);
0362 }
0363
0364 static int
0365 ahc_aic7770_EISA_setup(struct ahc_softc *ahc)
0366 {
0367 int error;
0368
0369 error = ahc_aic7770_setup(ahc);
0370 ahc->chip |= AHC_EISA;
0371 return (error);
0372 }
0373
0374 static int
0375 ahc_aic7770_setup(struct ahc_softc *ahc)
0376 {
0377 ahc->channel = 'A';
0378 ahc->channel_b = 'B';
0379 ahc->chip = AHC_AIC7770;
0380 ahc->features = AHC_AIC7770_FE;
0381 ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
0382 ahc->flags |= AHC_PAGESCBS;
0383 ahc->instruction_ram_size = 448;
0384 return (0);
0385 }