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 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 *
|
170 /*boundary*/0, 171 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 172 /*highaddr*/BUS_SPACE_MAXADDR, 173 /*filter*/NULL, /*filterarg*/NULL, 174 /*maxsize*/MAXBSIZE, 175 /*nsegments*/AHC_NSEG, 176 /*maxsegsz*/AHC_MAXTRANSFER_SIZE, 177 /*flags*/BUS_DMA_ALLOCNOW, &parent_dmat); 178 179 if (error != 0) { 180 printf("ahc_eisa_attach: Could not allocate DMA tag " 181 "- error %d\n", error); 182 goto bad; 183 } 184 185 io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 186 0, ~0, 1, RF_ACTIVE); 187 if (!io) { 188 device_printf(dev, "No I/O space?!\n"); 189 return ENOMEM; 190 } 191 192 if (!(ahc = ahc_alloc(dev, io, SYS_RES_IOPORT, rid, 193 parent_dmat, chip, AHC_AIC7770_FE, AHC_FNONE, 194 NULL))) 195 goto bad; 196 197 io = NULL; 198 199 ahc->channel = 'A'; 200 ahc->channel_b = 'B'; 201 if (ahc_reset(ahc) != 0) { 202 goto bad; 203 } 204 205 /* 206 * The IRQMS bit enables level sensitive interrupts. Only allow 207 * IRQ sharing if it's set. 208 */ 209 rid = 0; 210 ahc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 211 0, ~0, 1, RF_ACTIVE); 212 if (ahc->irq == NULL) { 213 device_printf(dev, "Can't allocate interrupt\n"); 214 goto bad; 215 } 216 ahc->irq_res_type = SYS_RES_IRQ; 217 218 /* 219 * Tell the user what type of interrupts we're using. 220 * usefull for debugging irq problems 221 */ 222 if (bootverbose) { 223 printf("%s: Using %s Interrupts\n", 224 ahc_name(ahc), 225 ahc->pause & IRQMS ? 226 "Level Sensitive" : "Edge Triggered"); 227 } 228 229 /* 230 * Now that we know we own the resources we need, do the 231 * card initialization. 232 * 233 * First, the aic7770 card specific setup. 234 */ 235 switch (chip & (AHC_EISA|AHC_VL)) { 236 case AHC_EISA: 237 { 238 u_int biosctrl; 239 u_int scsiconf; 240 u_int scsiconf1; 241#if DEBUG 242 int i; 243#endif 244 245 biosctrl = ahc_inb(ahc, HA_274_BIOSCTRL); 246 scsiconf = ahc_inb(ahc, SCSICONF); 247 scsiconf1 = ahc_inb(ahc, SCSICONF + 1); 248 249#if DEBUG 250 for (i = TARG_SCSIRATE; i <= HA_274_BIOSCTRL; i+=8) { 251 printf("0x%x, 0x%x, 0x%x, 0x%x, " 252 "0x%x, 0x%x, 0x%x, 0x%x\n", 253 ahc_inb(ahc, i), 254 ahc_inb(ahc, i+1), 255 ahc_inb(ahc, i+2), 256 ahc_inb(ahc, i+3), 257 ahc_inb(ahc, i+4), 258 ahc_inb(ahc, i+5), 259 ahc_inb(ahc, i+6), 260 ahc_inb(ahc, i+7)); 261 } 262#endif 263 264 /* Get the primary channel information */ 265 if ((biosctrl & CHANNEL_B_PRIMARY) != 0) 266 ahc->flags |= AHC_CHANNEL_B_PRIMARY; 267 268 if ((biosctrl & BIOSMODE) == BIOSDISABLED) { 269 ahc->flags |= AHC_USEDEFAULTS; 270 } else { 271 if ((ahc->features & AHC_WIDE) != 0) { 272 ahc->our_id = scsiconf1 & HWSCSIID; 273 if (scsiconf & TERM_ENB) 274 ahc->flags |= AHC_TERM_ENB_A; 275 } else { 276 ahc->our_id = scsiconf & HSCSIID; 277 ahc->our_id_b = scsiconf1 & HSCSIID; 278 if (scsiconf & TERM_ENB) 279 ahc->flags |= AHC_TERM_ENB_A; 280 if (scsiconf1 & TERM_ENB) 281 ahc->flags |= AHC_TERM_ENB_B; 282 } 283 } 284 /* 285 * We have no way to tell, so assume extended 286 * translation is enabled. 287 */ 288 ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B; 289 break; 290 } 291 case AHC_VL: 292 { 293 aha2840_load_seeprom(ahc); 294 break; 295 } 296 default: 297 break; 298 } 299 300 /* 301 * See if we have a Rev E or higher aic7770. Anything below a 302 * Rev E will have a R/O autoflush disable configuration bit. 303 */ 304 { 305 char *id_string; 306 u_int8_t sblkctl; 307 u_int8_t sblkctl_orig; 308 309 sblkctl_orig = ahc_inb(ahc, SBLKCTL); 310 sblkctl = sblkctl_orig ^ AUTOFLUSHDIS; 311 ahc_outb(ahc, SBLKCTL, sblkctl); 312 sblkctl = ahc_inb(ahc, SBLKCTL); 313 if (sblkctl != sblkctl_orig) { 314 id_string = "aic7770 >= Rev E, "; 315 /* 316 * Ensure autoflush is enabled 317 */ 318 sblkctl &= ~AUTOFLUSHDIS; 319 ahc_outb(ahc, SBLKCTL, sblkctl); 320 321 } else 322 id_string = "aic7770 <= Rev C, "; 323 324 printf("%s: %s", ahc_name(ahc), id_string); 325 } 326 327 /* Setup the FIFO threshold and the bus off time */ 328 { 329 u_int8_t hostconf = ahc_inb(ahc, HOSTCONF); 330 ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH); 331 ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF); 332 } 333 334 /* 335 * Generic aic7xxx initialization. 336 */ 337 if (ahc_init(ahc)) { 338 /* 339 * The board's IRQ line is not yet enabled so it's safe 340 * to release the irq. 341 */ 342 goto bad; 343 } 344 345 /* 346 * Enable the board's BUS drivers 347 */ 348 ahc_outb(ahc, BCTL, ENABLE); 349 350 /* Attach sub-devices - always succeeds */ 351 ahc_attach(ahc); 352 353 return 0; 354 355 bad: 356 if (ahc != NULL) 357 ahc_free(ahc); 358 359 if (io != NULL) 360 bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 361 362 return -1; 363} 364 365/* 366 * Read the 284x SEEPROM. 367 */ 368static void 369aha2840_load_seeprom(struct ahc_softc *ahc) 370{ 371 struct seeprom_descriptor sd; 372 struct seeprom_config sc; 373 u_int16_t checksum = 0; 374 u_int8_t scsi_conf; 375 int have_seeprom; 376 377 sd.sd_tag = ahc->tag; 378 sd.sd_bsh = ahc->bsh; 379 sd.sd_control_offset = SEECTL_2840; 380 sd.sd_status_offset = STATUS_2840; 381 sd.sd_dataout_offset = STATUS_2840; 382 sd.sd_chip = C46; 383 sd.sd_MS = 0; 384 sd.sd_RDY = EEPROM_TF; 385 sd.sd_CS = CS_2840; 386 sd.sd_CK = CK_2840; 387 sd.sd_DO = DO_2840; 388 sd.sd_DI = DI_2840; 389 390 if (bootverbose) 391 printf("%s: Reading SEEPROM...", ahc_name(ahc)); 392 have_seeprom = read_seeprom(&sd, 393 (u_int16_t *)&sc, 394 /*start_addr*/0, 395 sizeof(sc)/2); 396 397 if (have_seeprom) { 398 /* Check checksum */ 399 int i; 400 int maxaddr = (sizeof(sc)/2) - 1; 401 u_int16_t *scarray = (u_int16_t *)≻ 402 403 for (i = 0; i < maxaddr; i++) 404 checksum = checksum + scarray[i]; 405 if (checksum != sc.checksum) { 406 if(bootverbose) 407 printf ("checksum error\n"); 408 have_seeprom = 0; 409 } else if (bootverbose) { 410 printf("done.\n"); 411 } 412 } 413 414 if (!have_seeprom) { 415 if (bootverbose) 416 printf("%s: No SEEPROM available\n", ahc_name(ahc)); 417 ahc->flags |= AHC_USEDEFAULTS; 418 } else { 419 /* 420 * Put the data we've collected down into SRAM 421 * where ahc_init will find it. 422 */ 423 int i; 424 int max_targ = (ahc->features & AHC_WIDE) != 0 ? 16 : 8; 425 u_int16_t discenable; 426 427 discenable = 0; 428 for (i = 0; i < max_targ; i++){ 429 u_int8_t target_settings; 430 target_settings = (sc.device_flags[i] & CFXFER) << 4; 431 if (sc.device_flags[i] & CFSYNCH) 432 target_settings |= SOFS; 433 if (sc.device_flags[i] & CFWIDEB) 434 target_settings |= WIDEXFER; 435 if (sc.device_flags[i] & CFDISC) 436 discenable |= (0x01 << i); 437 ahc_outb(ahc, TARG_SCSIRATE + i, target_settings); 438 } 439 ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff)); 440 ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff)); 441 442 ahc->our_id = sc.brtime_id & CFSCSIID; 443 444 scsi_conf = (ahc->our_id & 0x7); 445 if (sc.adapter_control & CFSPARITY) 446 scsi_conf |= ENSPCHK; 447 if (sc.adapter_control & CFRESETB) 448 scsi_conf |= RESET_SCSI; 449 450 if (sc.bios_control & CF284XEXTEND) 451 ahc->flags |= AHC_EXTENDED_TRANS_A; 452 /* Set SCSICONF info */ 453 ahc_outb(ahc, SCSICONF, scsi_conf); 454 455 if (sc.adapter_control & CF284XSTERM) 456 ahc->flags |= AHC_TERM_ENB_A; 457 } 458} 459 460static device_method_t ahc_eisa_methods[] = { 461 /* Device interface */ 462 DEVMETHOD(device_probe, aic7770_probe), 463 DEVMETHOD(device_attach, aic7770_attach), 464 465 { 0, 0 } 466}; 467 468static driver_t ahc_eisa_driver = { 469 "ahc", 470 ahc_eisa_methods, 471 1, /* unused */ 472}; 473 474static devclass_t ahc_devclass; 475 476DRIVER_MODULE(ahc, eisa, ahc_eisa_driver, ahc_devclass, 0, 0); 477 478#endif /* NEISA > 0 */
|