dpt_eisa.c revision 36129
1/** 2 * Copyright (c) 1997 by Matthew N. Dodd <winter@jurai.net> 3 * All Rights Reserved 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions, and the following disclaimer, 10 * without modification, immediately at the beginning of the file. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. 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 30/* Credits: Based on and part of the DPT driver for FreeBSD written and 31 * maintained by Simon Shapiro <shimon@simon-shapiro.org> 32 */ 33 34/* 35 * $Id: dpt_eisa.c,v 1.1 1998/03/11 00:30:12 julian Exp $ 36 */ 37 38#include "eisa.h" 39#if NEISA > 0 40#include "opt_dpt.h" 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/malloc.h> 45#include <sys/buf.h> 46#include <sys/proc.h> 47#include <sys/kernel.h> 48 49#include <scsi/scsi_all.h> 50#include <scsi/scsi_message.h> 51#include <scsi/scsiconf.h> 52 53#include <i386/eisa/eisaconf.h> 54 55#include <sys/dpt.h> 56#include <i386/eisa/dpt_eisa.h> 57 58#include <machine/clock.h> 59 60#include <vm/vm.h> 61#include <vm/vm_param.h> 62#include <vm/pmap.h> 63 64/* Function Prototypes */ 65 66int dpt_eisa_probe(void); 67int dpt_eisa_attach(struct eisa_device*); 68int dpt_eisa_shutdown(int); 69 70static const char *dpt_eisa_match(eisa_id_t); 71 72static struct eisa_driver dpt_eisa_driver = 73{ 74 "dpt", 75 dpt_eisa_probe, 76 dpt_eisa_attach, 77 dpt_eisa_shutdown, 78 &dpt_unit 79}; 80 81DATA_SET (eisadriver_set, dpt_eisa_driver); 82 83int 84dpt_eisa_probe(void) 85{ 86 static int already_announced = 0; 87 u_int32_t io_base; 88 u_int32_t irq; 89 struct eisa_device *e_dev = NULL; 90 dpt_conf_t *config; 91 dpt_softc_t *dpt; 92 int count = 0; 93 94 if ( !already_announced ) { 95 printf("DPT: EISA SCSI HBA Driver, version %d.%d.%d\n", 96 DPT_RELEASE, DPT_VERSION, DPT_PATCH); 97 ++already_announced; 98 } 99 100 if ((dpt = (dpt_softc_t *) malloc(sizeof(dpt_softc_t), 101 M_DEVBUF, M_NOWAIT)) == NULL) { 102 printf("dpt_eisa_probe() : Failed to allocate %d bytes for a DPT softc\n", sizeof(dpt_softc_t)); 103 return -1; 104 } 105 106 bzero(dpt, sizeof(dpt_softc_t)); 107 108 TAILQ_INIT(&dpt->free_ccbs); 109 TAILQ_INIT(&dpt->waiting_ccbs); 110 TAILQ_INIT(&dpt->submitted_ccbs); 111 TAILQ_INIT(&dpt->completed_ccbs); 112 113 dpt->queue_status = DPT_QUEUES_NONE_ACTIVE; 114 dpt->commands_processed = 0; 115 dpt->handle_interrupts = 0; 116 dpt->v_membase = NULL; 117 dpt->p_membase = NULL; 118 119 dpt->unit = -1; 120 121 while ((e_dev = eisa_match_dev(e_dev, dpt_eisa_match))) { 122 io_base = (e_dev->ioconf.slot * EISA_SLOT_SIZE) 123 + DPT_EISA_SLOT_OFFSET; 124 125 eisa_add_iospace(e_dev, io_base, 126 DPT_EISA_IOSIZE, RESVADDR_NONE); 127 128 dpt->io_base = io_base; 129 130 if ((config = dpt_get_conf(dpt, 0xc1, 7, 131 sizeof(dpt_conf_t), 1)) == NULL) { 132#ifdef DPT_DEBUG_ERROR 133 printf("eisa0:%d dpt_eisa_probe() : Failed to get board configuration.\n", 134 e_dev->ioconf.slot); 135#endif 136 continue; 137 } 138 139 irq = config->IRQ; 140 141 eisa_add_intr(e_dev, irq); 142 eisa_registerdev(e_dev, &dpt_eisa_driver); 143 144 count++; 145 146 } 147 148 free(dpt, M_DEVBUF); 149 return count; 150} 151 152int 153dpt_eisa_attach(e_dev) 154 struct eisa_device *e_dev; 155{ 156 int result; 157 int ndx; 158 159 dpt_conf_t *config; 160 dpt_softc_t *dpt; 161 162 int unit = e_dev->unit; 163 int irq; 164 resvaddr_t *io_space; 165 166 if (TAILQ_FIRST(&e_dev->ioconf.irqs) == NULL) { 167#ifdef DPT_DEBUG_ERROR 168 printf("dpt%d: Can't retrieve irq from EISA config struct.\n", 169 unit); 170#endif 171 return -1; 172 } 173 174 irq = TAILQ_FIRST(&e_dev->ioconf.irqs)->irq_no; 175 io_space = e_dev->ioconf.ioaddrs.lh_first; 176 177 if (!io_space) { 178#ifdef DPT_DEBUG_ERROR 179 printf("dpt%d: No I/O space?!\n", unit); 180#endif 181 return -1; 182 } 183 184 if ( dpt_controllers_present >= DPT_MAX_ADAPTERS ){ 185 printf("dpt%d: More than %d Adapters found! Adapter rejected\n", 186 unit, DPT_MAX_ADAPTERS); 187 return -1; 188 } 189 190 if ((dpt = (dpt_softc_t *) malloc(sizeof(dpt_softc_t), 191 M_DEVBUF, M_NOWAIT)) == NULL) { 192 printf("dpt%d: Failed to allocate %d bytes for a DPT softc\n", 193 unit, sizeof(dpt_softc_t)); 194 return -1; 195 } 196 197 /* 198 * Initialize the queues. See dpt.h for details. We do this here, 199 * as we may get hit with interrupts at any moment and we want to 200 * have a minimal structure in place to handle them. We also want to 201 * register interrupts correctly. To do so, we need a valid dpt 202 * structure. To have that, we need this minimal setup here. 203 */ 204 205 bzero(dpt, sizeof(dpt_softc_t)); 206 207 TAILQ_INIT(&dpt->free_ccbs); 208 TAILQ_INIT(&dpt->waiting_ccbs); 209 TAILQ_INIT(&dpt->submitted_ccbs); 210 TAILQ_INIT(&dpt->completed_ccbs); 211 212 if (TAILQ_EMPTY(&dpt_softc_list)) { 213 TAILQ_INIT(&dpt_softc_list); 214 } 215 216 TAILQ_INSERT_TAIL(&dpt_softc_list, dpt, links); 217 dpt->queue_status = DPT_QUEUES_NONE_ACTIVE; 218 dpt->commands_processed = 0; 219 220#ifdef DPT_MEASURE_PERFORMANCE 221 /* Zero out all command counters */ 222 bzero((void *)&dpt->performance, sizeof(dpt_perf_t)); 223#endif /* DPT_MEASURE_PERFORMANCE */ 224 225 dpt->handle_interrupts = 0; /* 226 * Do not set to 1 until all 227 * initialization is done 228 */ 229 dpt->v_membase = NULL; 230 dpt->p_membase = NULL; 231 232 dpt->unit = unit; 233 dpt->io_base = (e_dev->ioconf.slot * EISA_SLOT_SIZE) 234 + DPT_EISA_SLOT_OFFSET; 235 236 eisa_reg_start(e_dev); 237 238 if (eisa_reg_iospace(e_dev, io_space)) { 239#ifdef DPT_DEBUG_ERROR 240 printf("dpt%d: eisa_reg_iospace() failed.\n", unit); 241#endif 242 free(dpt, M_DEVBUF); 243 return -1; 244 } 245 246 /* reset the card? */ 247 248 /* If the DPT is mapped as an IDE controller, let it be IDE controller */ 249 if (dpt->io_base == ISA_PRIMARY_WD_ADDRESS) { 250#ifdef DPT_DEBUG_WARN 251 printf("dpt%d: Mapped as an IDE controller. " 252 "Disabling SCSI setup\n", unit); 253#endif 254 free(dpt, M_DEVBUF); 255 return -1; 256 } else { 257 if ((config = dpt_get_conf(dpt, 0xc1, 7, 258 sizeof(dpt_conf_t), 1)) == NULL) { 259#ifdef DPT_DEBUG_ERROR 260 printf("dpt%d: Failed to get board configuration (%x)\n", 261 unit, BaseRegister(dpt)); 262#endif 263 free(dpt, M_DEVBUF); 264 return -1; 265 } 266 } 267 268 if(eisa_reg_intr(e_dev, irq, dpt_intr, (void *)dpt, &cam_imask, 269 /* shared == */ config->IRQ_TR)) { 270#ifdef DPT_DEBUG_ERROR 271 printf("dpt%d: eisa_reg_intr() failed.\n", unit); 272#endif 273 free(dpt, M_DEVBUF); 274 return -1; 275 } 276 eisa_reg_end(e_dev); 277 278 /* Enable our interrupt handler. */ 279 if (eisa_enable_intr(e_dev, irq)) { 280#ifdef DPT_DEBUG_ERROR 281 printf("dpt%d: eisa_enable_intr() failed.\n", unit); 282#endif 283 free(dpt, M_DEVBUF); 284 eisa_release_intr(e_dev, irq, dpt_intr); 285 return -1; 286 } 287 288 dpt->max_id = config->MAX_ID; 289 dpt->max_lun = config->MAX_LUN; 290 dpt->irq = config->IRQ; 291 dpt->channels = config->MAX_CHAN; 292 dpt->dma_channel = (8 - config->DMA_channel) & 7; 293 294#ifdef DPT_DEBUG_SETUP 295 printf("dpt%d: max_id = %d, max_chan = %d, max_lun = %d\n", 296 dpt->unit, dpt->max_id, dpt->channels, dpt->max_lun); 297#endif 298 299 if (result = dpt_setup(dpt, config)) { 300 free(config, M_TEMP); 301 free(dpt, M_DEVBUF); 302 printf("dpt%d: dpt_setup failed (%d). Driver Disabled :-(\n", 303 dpt->unit, result); 304 } else { 305 /* clean up the informational data, and display */ 306 char clean_vendor[9]; 307 char clean_model[17]; 308 char clean_firmware[5]; 309 char clean_protocol[5]; 310 char clean_other[7]; 311 312 int ndx; 313 314 strncpy(clean_other, dpt->board_data.otherData, 8); 315 clean_other[6] = '\0'; 316 for (ndx = 5; ndx >= 0; ndx--) { 317 if (clean_other[ndx] == ' ') { 318 clean_other[ndx] = '\0'; 319 } else { 320 break; 321 } 322 } 323 324 strncpy(dpt->board_data.otherData, clean_other, 6); 325 326 strncpy(clean_vendor, dpt->board_data.vendor, 8); 327 clean_vendor[8] = '\0'; 328 329 for (ndx = 7; ndx >= 0; ndx--) { 330 if (clean_vendor[ndx] == ' ') { 331 clean_vendor[ndx] = '\0'; 332 } else { 333 break; 334 } 335 } 336 337 strncpy(dpt->board_data.vendor, clean_vendor, 8); 338 339 strncpy(clean_model, dpt->board_data.modelNum, 16); 340 clean_model[16] = '\0'; 341 342 for (ndx = 15; ndx >= 0; ndx--) { 343 if (clean_model[ndx] == ' ') { 344 clean_model[ndx] = '\0'; 345 } else { 346 break; 347 } 348 } 349 350 strncpy(dpt->board_data.modelNum, clean_model, 16); 351 352 strncpy(clean_firmware, dpt->board_data.firmware, 4); 353 clean_firmware[4] = '\0'; 354 355 for (ndx = 3; ndx >= 0; ndx--) { 356 if (clean_firmware[ndx] == ' ') 357 clean_firmware[ndx] = '\0'; 358 else 359 break; 360 } 361 362 strncpy(dpt->board_data.firmware, clean_firmware, 4); 363 364 strncpy(clean_protocol, dpt->board_data.protocol, 4); 365 clean_protocol[4] = '\0'; 366 367 for (ndx = 3; ndx >= 0; ndx--) { 368 if (clean_protocol[ndx] == ' ') 369 clean_protocol[ndx] = '\0'; 370 else 371 break; 372 } 373 374 strncpy(dpt->board_data.protocol, clean_protocol, 4); 375 376 dpt_detect_cache(dpt); 377 378 printf("dpt%d: %s type %x, model %s firmware %s, Protocol %s \n" 379 " on port %x with %dMB %s cache. LED = %s\n", 380 dpt->unit, clean_vendor, dpt->board_data.deviceType, 381 clean_model, clean_firmware, clean_protocol, dpt->io_base, 382 dpt->cache_size, 383 (dpt->cache_type == DPT_NO_CACHE) 384 ? "Disabled" 385 : (dpt->cache_type == DPT_CACHE_WRITETHROUGH) 386 ? "Write-Through" 387 : "Write-Back", 388 i2bin(dpt_blinking_led(dpt), 8)); 389 390 printf("dpt%d: Enabled Options:\n", dpt->unit); 391 392#ifdef DPT_VERIFY_HINTR 393 printf(" Verify Lost Transactions\n"); 394#endif 395#ifdef DPT_RESTRICTED_FREELIST 396 printf(" Restrict the Freelist Size\n"); 397#endif 398#ifdef DPT_TRACK_CCB_STATES 399 printf(" Precisely Track State Transitions\n"); 400#endif 401#ifdef DPT_MEASURE_PERFORMANCE 402 printf(" Collect Metrics\n"); 403#endif 404#ifdef DPT_FREELIST_IS_STACK 405 printf(" Optimize CPU Cache\n"); 406#endif 407#ifdef DPT_HANDLE_TIMEOUTS 408 printf(" Handle Timeouts\n"); 409#endif 410#ifdef DPT_ALLOW_MEMIO 411 printf(" Allow I/O to be Memeory Mapped\n"); 412#endif 413#ifdef DPT_HINTR_CHECK_SOFTC 414 printf(" Validate SoftC at Interrupt\n"); 415#endif 416 417 /* register shutdown handlers */ 418 result = at_shutdown((bootlist_fn)dpt_shutdown, (void *)dpt, 419 SHUTDOWN_POST_SYNC); 420 switch ( result ) { 421 case 0: 422#ifdef DPT_DEBUG_SHUTDOWN 423 printf("dpt%d: Shutdown handler registered\n", dpt->unit); 424#endif 425 break; 426 default: 427#ifdef DPT_DEBUG_WARN 428 printf("dpt%d: Failed to register shutdown handler (%d)\n", 429 dpt->unit, result); 430#endif 431 break; 432 } 433 434 dpt_attach(dpt); 435 } 436 437 ++dpt_controllers_present; 438 439 return 0; 440} 441 442int 443dpt_eisa_shutdown(foo) 444 int foo; 445{ 446#ifdef DPT_DEBUG_WARN 447 printf("dpt_pci_shutdown(%x)\n", foo); 448#endif 449 return (0); 450} 451 452static const char * 453dpt_eisa_match(type) 454 eisa_id_t type; 455{ 456 switch (type) { 457 case DPT_EISA_DPT2402 : 458 return ("DPT PM2012A/9X"); 459 break; 460 case DPT_EISA_DPTA401 : 461 return ("DPT PM2012B/9X"); 462 break; 463 case DPT_EISA_DPTA402 : 464 return ("DPT PM2012B2/9X"); 465 break; 466 case DPT_EISA_DPTA410 : 467 return ("DPT PM2x22A/9X"); 468 break; 469 case DPT_EISA_DPTA411 : 470 return ("DPT Spectre"); 471 break; 472 case DPT_EISA_DPTA412 : 473 return ("DPT PM2021A/9X"); 474 break; 475 case DPT_EISA_DPTA420 : 476 return ("DPT Smart Cache IV (PM2042)"); 477 break; 478 case DPT_EISA_DPTA501 : 479 return ("DPT PM2012B1/9X"); 480 break; 481 case DPT_EISA_DPTA502 : 482 return ("DPT PM2012Bx/9X"); 483 break; 484 case DPT_EISA_DPTA701 : 485 return ("DPT PM2011B1/9X"); 486 break; 487 case DPT_EISA_DPTBC01 : 488 return ("DPT PM3011/7X ESDI"); 489 break; 490 case DPT_EISA_NEC8200 : 491 return ("NEC EATA SCSI"); 492 break; 493 case DPT_EISA_ATT2408 : 494 return ("ATT EATA SCSI"); 495 break; 496 default: 497 break; 498 } 499 500 return (NULL); 501} 502 503#endif /* NEISA > 0 */ 504