1 /* 2 * Product specific probe and attach routines for: 3 * 27/284X and aic7770 motherboard SCSI controllers 4 * 5 * Copyright (c) 1994, 1995, 1996, 1997, 1998, 2000 Justin T. Gibbs. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice immediately at the beginning of the file, without modification, 13 * this list of conditions, and the following disclaimer. 14 * 2. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $Id$ 30 * 31 * $FreeBSD$ 32 */ 33 34 #ifdef __linux__ 35 #include "aic7xxx_linux.h" 36 #include "aic7xxx_inline.h" 37 #include "aic7xxx_93cx6.h" 38 #endif 39 40 #ifdef __FreeBSD__ 41 #include <dev/aic7xxx/aic7xxx_freebsd.h> 42 #include <dev/aic7xxx/aic7xxx_inline.h> 43 #include <dev/aic7xxx/aic7xxx_93cx6.h> 44 #endif 45 46 #define ID_AIC7770 0x04907770 47 #define ID_AHA_274x 0x04907771 48 #define ID_AHA_284xB 0x04907756 /* BIOS enabled */ 49 #define ID_AHA_284x 0x04907757 /* BIOS disabled*/ 50 51 static void aha2840_load_seeprom(struct ahc_softc *ahc); 52 static ahc_device_setup_t ahc_aic7770_VL_setup; 53 static ahc_device_setup_t ahc_aic7770_EISA_setup;; 54 static ahc_device_setup_t ahc_aic7770_setup; 55 56 57 struct aic7770_identity aic7770_ident_table [] = 58 { 59 { 60 ID_AHA_274x, 61 0xFFFFFFFF, 62 "Adaptec 274X SCSI adapter", 63 ahc_aic7770_EISA_setup 64 }, 65 { 66 ID_AHA_284xB, 67 0xFFFFFFFE, 68 "Adaptec 284X SCSI adapter", 69 ahc_aic7770_VL_setup 70 }, 71 /* Generic chip probes for devices we don't know 'exactly' */ 72 { 73 ID_AIC7770, 74 0xFFFFFFFF, 75 "Adaptec aic7770 SCSI adapter", 76 ahc_aic7770_EISA_setup 77 } 78 }; 79 const int ahc_num_aic7770_devs = NUM_ELEMENTS(aic7770_ident_table); 80 81 struct aic7770_identity * 82 aic7770_find_device(uint32_t id) 83 { 84 struct aic7770_identity *entry; 85 int i; 86 87 for (i = 0; i < ahc_num_aic7770_devs; i++) { 88 entry = &aic7770_ident_table[i]; 89 if (entry->full_id == (id & entry->id_mask)) 90 return (entry); 91 } 92 return (NULL); 93 } 94 95 int 96 aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry) 97 { 98 struct ahc_probe_config probe_config; 99 int error; 100 u_int hostconf; 101 102 ahc_init_probe_config(&probe_config); 103 error = entry->setup(ahc->dev_softc, &probe_config); 104 if (error != 0) 105 return (error); 106 107 error = aic7770_map_registers(ahc); 108 if (error != 0) 109 return (error); 110 111 probe_config.description = entry->name; 112 error = ahc_softc_init(ahc, &probe_config); 113 114 error = aic7770_map_int(ahc); 115 if (error != 0) 116 return (error); 117 118 error = ahc_reset(ahc); 119 if (error != 0) 120 return (error); 121 122 switch (probe_config.chip & (AHC_EISA|AHC_VL)) { 123 case AHC_EISA: 124 { 125 u_int biosctrl; 126 u_int scsiconf; 127 u_int scsiconf1; 128 129 biosctrl = ahc_inb(ahc, HA_274_BIOSCTRL); 130 scsiconf = ahc_inb(ahc, SCSICONF); 131 scsiconf1 = ahc_inb(ahc, SCSICONF + 1); 132 133 /* Get the primary channel information */ 134 if ((biosctrl & CHANNEL_B_PRIMARY) != 0) 135 ahc->flags |= AHC_CHANNEL_B_PRIMARY; 136 137 if ((biosctrl & BIOSMODE) == BIOSDISABLED) { 138 ahc->flags |= AHC_USEDEFAULTS; 139 } else { 140 if ((ahc->features & AHC_WIDE) != 0) { 141 ahc->our_id = scsiconf1 & HWSCSIID; 142 if (scsiconf & TERM_ENB) 143 ahc->flags |= AHC_TERM_ENB_A; 144 } else { 145 ahc->our_id = scsiconf & HSCSIID; 146 ahc->our_id_b = scsiconf1 & HSCSIID; 147 if (scsiconf & TERM_ENB) 148 ahc->flags |= AHC_TERM_ENB_A; 149 if (scsiconf1 & TERM_ENB) 150 ahc->flags |= AHC_TERM_ENB_B; 151 } 152 } 153 /* 154 * We have no way to tell, so assume extended 155 * translation is enabled. 156 */ 157 ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B; 158 break; 159 } 160 case AHC_VL: 161 { 162 aha2840_load_seeprom(ahc); 163 break; 164 } 165 default: 166 break; 167 } 168 169 /* 170 * Ensure autoflush is enabled 171 */ 172 ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~AUTOFLUSHDIS); 173 174 /* Setup the FIFO threshold and the bus off time */ 175 hostconf = ahc_inb(ahc, HOSTCONF); 176 ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH); 177 ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF); 178 179 /* 180 * Generic aic7xxx initialization. 181 */ 182 error = ahc_init(ahc); 183 if (error != 0) 184 return (error); 185 186 /* 187 * Enable the board's BUS drivers 188 */ 189 ahc_outb(ahc, BCTL, ENABLE); 190 191 return (0); 192 } 193 194 /* 195 * Read the 284x SEEPROM. 196 */ 197 static void 198 aha2840_load_seeprom(struct ahc_softc *ahc) 199 { 200 struct seeprom_descriptor sd; 201 struct seeprom_config sc; 202 uint16_t checksum = 0; 203 uint8_t scsi_conf; 204 int have_seeprom; 205 206 sd.sd_ahc = ahc; 207 sd.sd_control_offset = SEECTL_2840; 208 sd.sd_status_offset = STATUS_2840; 209 sd.sd_dataout_offset = STATUS_2840; 210 sd.sd_chip = C46; 211 sd.sd_MS = 0; 212 sd.sd_RDY = EEPROM_TF; 213 sd.sd_CS = CS_2840; 214 sd.sd_CK = CK_2840; 215 sd.sd_DO = DO_2840; 216 sd.sd_DI = DI_2840; 217 218 if (bootverbose) 219 printf("%s: Reading SEEPROM...", ahc_name(ahc)); 220 have_seeprom = read_seeprom(&sd, 221 (uint16_t *)&sc, 222 /*start_addr*/0, 223 sizeof(sc)/2); 224 225 if (have_seeprom) { 226 /* Check checksum */ 227 int i; 228 int maxaddr = (sizeof(sc)/2) - 1; 229 uint16_t *scarray = (uint16_t *)≻ 230 231 for (i = 0; i < maxaddr; i++) 232 checksum = checksum + scarray[i]; 233 if (checksum != sc.checksum) { 234 if(bootverbose) 235 printf ("checksum error\n"); 236 have_seeprom = 0; 237 } else if (bootverbose) { 238 printf("done.\n"); 239 } 240 } 241 242 if (!have_seeprom) { 243 if (bootverbose) 244 printf("%s: No SEEPROM available\n", ahc_name(ahc)); 245 ahc->flags |= AHC_USEDEFAULTS; 246 } else { 247 /* 248 * Put the data we've collected down into SRAM 249 * where ahc_init will find it. 250 */ 251 int i; 252 int max_targ = (ahc->features & AHC_WIDE) != 0 ? 16 : 8; 253 uint16_t discenable; 254 255 discenable = 0; 256 for (i = 0; i < max_targ; i++){ 257 uint8_t target_settings; 258 target_settings = (sc.device_flags[i] & CFXFER) << 4; 259 if (sc.device_flags[i] & CFSYNCH) 260 target_settings |= SOFS; 261 if (sc.device_flags[i] & CFWIDEB) 262 target_settings |= WIDEXFER; 263 if (sc.device_flags[i] & CFDISC) 264 discenable |= (0x01 << i); 265 ahc_outb(ahc, TARG_SCSIRATE + i, target_settings); 266 } 267 ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff)); 268 ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff)); 269 270 ahc->our_id = sc.brtime_id & CFSCSIID; 271 272 scsi_conf = (ahc->our_id & 0x7); 273 if (sc.adapter_control & CFSPARITY) 274 scsi_conf |= ENSPCHK; 275 if (sc.adapter_control & CFRESETB) 276 scsi_conf |= RESET_SCSI; 277 278 if (sc.bios_control & CF284XEXTEND) 279 ahc->flags |= AHC_EXTENDED_TRANS_A; 280 /* Set SCSICONF info */ 281 ahc_outb(ahc, SCSICONF, scsi_conf); 282 283 if (sc.adapter_control & CF284XSTERM) 284 ahc->flags |= AHC_TERM_ENB_A; 285 } 286 } 287 288 static int 289 ahc_aic7770_VL_setup(ahc_dev_softc_t dev, struct ahc_probe_config *probe_config) 290 { 291 int error; 292 293 error = ahc_aic7770_setup(dev, probe_config); 294 probe_config->chip |= AHC_VL; 295 return (error); 296 } 297 298 static int 299 ahc_aic7770_EISA_setup(ahc_dev_softc_t dev, 300 struct ahc_probe_config *probe_config) 301 { 302 int error; 303 304 error = ahc_aic7770_setup(dev, probe_config); 305 probe_config->chip |= AHC_EISA; 306 return (error); 307 } 308 309 static int 310 ahc_aic7770_setup(ahc_dev_softc_t dev, struct ahc_probe_config *probe_config) 311 { 312 probe_config->channel = 'A'; 313 probe_config->channel_b = 'B'; 314 probe_config->chip = AHC_AIC7770; 315 probe_config->features = AHC_AIC7770_FE; 316 probe_config->bugs |= AHC_TMODE_WIDEODD_BUG; 317 probe_config->flags |= AHC_PAGESCBS; 318 return (0); 319 } 320