1 /*----------------------------------------------------------------*/ 2 /* 3 Qlogic linux driver - work in progress. No Warranty express or implied. 4 Use at your own risk. Support Tort Reform so you won't have to read all 5 these silly disclaimers. 6 7 Copyright 1994, Tom Zerucha. 8 tz@execpc.com 9 10 Additional Code, and much appreciated help by 11 Michael A. Griffith 12 grif@cs.ucr.edu 13 14 Thanks to Eric Youngdale and Dave Hinds for loadable module and PCMCIA 15 help respectively, and for suffering through my foolishness during the 16 debugging process. 17 18 Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994 19 (you can reference it, but it is incomplete and inaccurate in places) 20 21 Version 0.46 1/30/97 - kernel 1.2.0+ 22 23 Functions as standalone, loadable, and PCMCIA driver, the latter from 24 Dave Hinds' PCMCIA package. 25 26 Cleaned up 26/10/2002 by Alan Cox <alan@lxorguk.ukuu.org.uk> as part of the 2.5 27 SCSI driver cleanup and audit. This driver still needs work on the 28 following 29 - Non terminating hardware waits 30 - Some layering violations with its pcmcia stub 31 32 Redistributable under terms of the GNU General Public License 33 34 For the avoidance of doubt the "preferred form" of this code is one which 35 is in an open non patent encumbered format. Where cryptographic key signing 36 forms part of the process of creating an executable the information 37 including keys needed to generate an equivalently functional executable 38 are deemed to be part of the source code. 39 40 */ 41 42 #include <linux/module.h> 43 #include <linux/blkdev.h> /* to get disk capacity */ 44 #include <linux/kernel.h> 45 #include <linux/string.h> 46 #include <linux/init.h> 47 #include <linux/interrupt.h> 48 #include <linux/ioport.h> 49 #include <linux/proc_fs.h> 50 #include <linux/unistd.h> 51 #include <linux/spinlock.h> 52 #include <linux/stat.h> 53 54 #include <asm/io.h> 55 #include <asm/irq.h> 56 #include <asm/dma.h> 57 58 #include "scsi.h" 59 #include <scsi/scsi_host.h> 60 #include "qlogicfas408.h" 61 62 /*----------------------------------------------------------------*/ 63 static int qlcfg5 = (XTALFREQ << 5); /* 15625/512 */ 64 static int qlcfg6 = SYNCXFRPD; 65 static int qlcfg7 = SYNCOFFST; 66 static int qlcfg8 = (SLOWCABLE << 7) | (QL_ENABLE_PARITY << 4); 67 static int qlcfg9 = ((XTALFREQ + 4) / 5); 68 static int qlcfgc = (FASTCLK << 3) | (FASTSCSI << 4); 69 70 /*----------------------------------------------------------------*/ 71 72 /*----------------------------------------------------------------*/ 73 /* local functions */ 74 /*----------------------------------------------------------------*/ 75 76 /* error recovery - reset everything */ 77 78 static void ql_zap(struct qlogicfas408_priv *priv) 79 { 80 int x; 81 int qbase = priv->qbase; 82 int int_type = priv->int_type; 83 84 x = inb(qbase + 0xd); 85 REG0; 86 outb(3, qbase + 3); /* reset SCSI */ 87 outb(2, qbase + 3); /* reset chip */ 88 if (x & 0x80) 89 REG1; 90 } 91 92 /* 93 * Do a pseudo-dma tranfer 94 */ 95 96 static int ql_pdma(struct qlogicfas408_priv *priv, int phase, char *request, int reqlen) 97 { 98 int j; 99 int qbase = priv->qbase; 100 j = 0; 101 if (phase & 1) { /* in */ 102 #if QL_TURBO_PDMA 103 rtrc(4) 104 /* empty fifo in large chunks */ 105 if (reqlen >= 128 && (inb(qbase + 8) & 2)) { /* full */ 106 insl(qbase + 4, request, 32); 107 reqlen -= 128; 108 request += 128; 109 } 110 while (reqlen >= 84 && !(j & 0xc0)) /* 2/3 */ 111 if ((j = inb(qbase + 8)) & 4) 112 { 113 insl(qbase + 4, request, 21); 114 reqlen -= 84; 115 request += 84; 116 } 117 if (reqlen >= 44 && (inb(qbase + 8) & 8)) { /* 1/3 */ 118 insl(qbase + 4, request, 11); 119 reqlen -= 44; 120 request += 44; 121 } 122 #endif 123 /* until both empty and int (or until reclen is 0) */ 124 rtrc(7) 125 j = 0; 126 while (reqlen && !((j & 0x10) && (j & 0xc0))) 127 { 128 /* while bytes to receive and not empty */ 129 j &= 0xc0; 130 while (reqlen && !((j = inb(qbase + 8)) & 0x10)) 131 { 132 *request++ = inb(qbase + 4); 133 reqlen--; 134 } 135 if (j & 0x10) 136 j = inb(qbase + 8); 137 138 } 139 } else { /* out */ 140 #if QL_TURBO_PDMA 141 rtrc(4) 142 if (reqlen >= 128 && inb(qbase + 8) & 0x10) { /* empty */ 143 outsl(qbase + 4, request, 32); 144 reqlen -= 128; 145 request += 128; 146 } 147 while (reqlen >= 84 && !(j & 0xc0)) /* 1/3 */ 148 if (!((j = inb(qbase + 8)) & 8)) { 149 outsl(qbase + 4, request, 21); 150 reqlen -= 84; 151 request += 84; 152 } 153 if (reqlen >= 40 && !(inb(qbase + 8) & 4)) { /* 2/3 */ 154 outsl(qbase + 4, request, 10); 155 reqlen -= 40; 156 request += 40; 157 } 158 #endif 159 /* until full and int (or until reclen is 0) */ 160 rtrc(7) 161 j = 0; 162 while (reqlen && !((j & 2) && (j & 0xc0))) { 163 /* while bytes to send and not full */ 164 while (reqlen && !((j = inb(qbase + 8)) & 2)) 165 { 166 outb(*request++, qbase + 4); 167 reqlen--; 168 } 169 if (j & 2) 170 j = inb(qbase + 8); 171 } 172 } 173 /* maybe return reqlen */ 174 return inb(qbase + 8) & 0xc0; 175 } 176 177 /* 178 * Wait for interrupt flag (polled - not real hardware interrupt) 179 */ 180 181 static int ql_wai(struct qlogicfas408_priv *priv) 182 { 183 int k; 184 int qbase = priv->qbase; 185 unsigned long i; 186 187 k = 0; 188 i = jiffies + WATCHDOG; 189 while (time_before(jiffies, i) && !priv->qabort && 190 !((k = inb(qbase + 4)) & 0xe0)) { 191 barrier(); 192 cpu_relax(); 193 } 194 if (time_after_eq(jiffies, i)) 195 return (DID_TIME_OUT); 196 if (priv->qabort) 197 return (priv->qabort == 1 ? DID_ABORT : DID_RESET); 198 if (k & 0x60) 199 ql_zap(priv); 200 if (k & 0x20) 201 return (DID_PARITY); 202 if (k & 0x40) 203 return (DID_ERROR); 204 return 0; 205 } 206 207 /* 208 * Initiate scsi command - queueing handler 209 * caller must hold host lock 210 */ 211 212 static void ql_icmd(struct scsi_cmnd *cmd) 213 { 214 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); 215 int qbase = priv->qbase; 216 int int_type = priv->int_type; 217 unsigned int i; 218 219 priv->qabort = 0; 220 221 REG0; 222 /* clearing of interrupts and the fifo is needed */ 223 224 inb(qbase + 5); /* clear interrupts */ 225 if (inb(qbase + 5)) /* if still interrupting */ 226 outb(2, qbase + 3); /* reset chip */ 227 else if (inb(qbase + 7) & 0x1f) 228 outb(1, qbase + 3); /* clear fifo */ 229 while (inb(qbase + 5)); /* clear ints */ 230 REG1; 231 outb(1, qbase + 8); /* set for PIO pseudo DMA */ 232 outb(0, qbase + 0xb); /* disable ints */ 233 inb(qbase + 8); /* clear int bits */ 234 REG0; 235 outb(0x40, qbase + 0xb); /* enable features */ 236 237 /* configurables */ 238 outb(qlcfgc, qbase + 0xc); 239 /* config: no reset interrupt, (initiator) bus id */ 240 outb(0x40 | qlcfg8 | priv->qinitid, qbase + 8); 241 outb(qlcfg7, qbase + 7); 242 outb(qlcfg6, qbase + 6); 243 /**/ outb(qlcfg5, qbase + 5); /* select timer */ 244 outb(qlcfg9 & 7, qbase + 9); /* prescaler */ 245 /* outb(0x99, qbase + 5); */ 246 outb(scmd_id(cmd), qbase + 4); 247 248 for (i = 0; i < cmd->cmd_len; i++) 249 outb(cmd->cmnd[i], qbase + 2); 250 251 priv->qlcmd = cmd; 252 outb(0x41, qbase + 3); /* select and send command */ 253 } 254 255 /* 256 * Process scsi command - usually after interrupt 257 */ 258 259 static unsigned int ql_pcmd(struct scsi_cmnd *cmd) 260 { 261 unsigned int i, j; 262 unsigned long k; 263 unsigned int result; /* ultimate return result */ 264 unsigned int status; /* scsi returned status */ 265 unsigned int message; /* scsi returned message */ 266 unsigned int phase; /* recorded scsi phase */ 267 unsigned int reqlen; /* total length of transfer */ 268 char *buf; 269 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); 270 int qbase = priv->qbase; 271 int int_type = priv->int_type; 272 273 rtrc(1) 274 j = inb(qbase + 6); 275 i = inb(qbase + 5); 276 if (i == 0x20) { 277 return (DID_NO_CONNECT << 16); 278 } 279 i |= inb(qbase + 5); /* the 0x10 bit can be set after the 0x08 */ 280 if (i != 0x18) { 281 printk(KERN_ERR "Ql:Bad Interrupt status:%02x\n", i); 282 ql_zap(priv); 283 return (DID_BAD_INTR << 16); 284 } 285 j &= 7; /* j = inb( qbase + 7 ) >> 5; */ 286 287 /* correct status is supposed to be step 4 */ 288 /* it sometimes returns step 3 but with 0 bytes left to send */ 289 /* We can try stuffing the FIFO with the max each time, but we will get a 290 sequence of 3 if any bytes are left (but we do flush the FIFO anyway */ 291 292 if (j != 3 && j != 4) { 293 printk(KERN_ERR "Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", 294 j, i, inb(qbase + 7) & 0x1f); 295 ql_zap(priv); 296 return (DID_ERROR << 16); 297 } 298 result = DID_OK; 299 if (inb(qbase + 7) & 0x1f) /* if some bytes in fifo */ 300 outb(1, qbase + 3); /* clear fifo */ 301 /* note that request_bufflen is the total xfer size when sg is used */ 302 reqlen = scsi_bufflen(cmd); 303 /* note that it won't work if transfers > 16M are requested */ 304 if (reqlen && !((phase = inb(qbase + 4)) & 6)) { /* data phase */ 305 struct scatterlist *sg; 306 rtrc(2) 307 outb(reqlen, qbase); /* low-mid xfer cnt */ 308 outb(reqlen >> 8, qbase + 1); /* low-mid xfer cnt */ 309 outb(reqlen >> 16, qbase + 0xe); /* high xfer cnt */ 310 outb(0x90, qbase + 3); /* command do xfer */ 311 /* PIO pseudo DMA to buffer or sglist */ 312 REG1; 313 314 scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) { 315 if (priv->qabort) { 316 REG0; 317 return ((priv->qabort == 1 ? 318 DID_ABORT : DID_RESET) << 16); 319 } 320 buf = sg_virt(sg); 321 if (ql_pdma(priv, phase, buf, sg->length)) 322 break; 323 } 324 REG0; 325 rtrc(2) 326 /* 327 * Wait for irq (split into second state of irq handler 328 * if this can take time) 329 */ 330 if ((k = ql_wai(priv))) 331 return (k << 16); 332 k = inb(qbase + 5); /* should be 0x10, bus service */ 333 } 334 335 /* 336 * Enter Status (and Message In) Phase 337 */ 338 339 k = jiffies + WATCHDOG; 340 341 while (time_before(jiffies, k) && !priv->qabort && 342 !(inb(qbase + 4) & 6)) 343 cpu_relax(); /* wait for status phase */ 344 345 if (time_after_eq(jiffies, k)) { 346 ql_zap(priv); 347 return (DID_TIME_OUT << 16); 348 } 349 350 /* FIXME: timeout ?? */ 351 while (inb(qbase + 5)) 352 cpu_relax(); /* clear pending ints */ 353 354 if (priv->qabort) 355 return ((priv->qabort == 1 ? DID_ABORT : DID_RESET) << 16); 356 357 outb(0x11, qbase + 3); /* get status and message */ 358 if ((k = ql_wai(priv))) 359 return (k << 16); 360 i = inb(qbase + 5); /* get chip irq stat */ 361 j = inb(qbase + 7) & 0x1f; /* and bytes rec'd */ 362 status = inb(qbase + 2); 363 message = inb(qbase + 2); 364 365 /* 366 * Should get function complete int if Status and message, else 367 * bus serv if only status 368 */ 369 if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) { 370 printk(KERN_ERR "Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j); 371 result = DID_ERROR; 372 } 373 outb(0x12, qbase + 3); /* done, disconnect */ 374 rtrc(1) 375 if ((k = ql_wai(priv))) 376 return (k << 16); 377 378 /* 379 * Should get bus service interrupt and disconnect interrupt 380 */ 381 382 i = inb(qbase + 5); /* should be bus service */ 383 while (!priv->qabort && ((i & 0x20) != 0x20)) { 384 barrier(); 385 cpu_relax(); 386 i |= inb(qbase + 5); 387 } 388 rtrc(0) 389 390 if (priv->qabort) 391 return ((priv->qabort == 1 ? DID_ABORT : DID_RESET) << 16); 392 393 return (result << 16) | (message << 8) | (status & STATUS_MASK); 394 } 395 396 /* 397 * Interrupt handler 398 */ 399 400 static void ql_ihandl(void *dev_id) 401 { 402 struct scsi_cmnd *icmd; 403 struct Scsi_Host *host = dev_id; 404 struct qlogicfas408_priv *priv = get_priv_by_host(host); 405 int qbase = priv->qbase; 406 REG0; 407 408 if (!(inb(qbase + 4) & 0x80)) /* false alarm? */ 409 return; 410 411 if (priv->qlcmd == NULL) { /* no command to process? */ 412 int i; 413 i = 16; 414 while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */ 415 return; 416 } 417 icmd = priv->qlcmd; 418 icmd->result = ql_pcmd(icmd); 419 priv->qlcmd = NULL; 420 /* 421 * If result is CHECK CONDITION done calls qcommand to request 422 * sense 423 */ 424 (icmd->scsi_done) (icmd); 425 } 426 427 irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id) 428 { 429 unsigned long flags; 430 struct Scsi_Host *host = dev_id; 431 432 spin_lock_irqsave(host->host_lock, flags); 433 ql_ihandl(dev_id); 434 spin_unlock_irqrestore(host->host_lock, flags); 435 return IRQ_HANDLED; 436 } 437 438 /* 439 * Queued command 440 */ 441 442 static int qlogicfas408_queuecommand_lck(struct scsi_cmnd *cmd, 443 void (*done) (struct scsi_cmnd *)) 444 { 445 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); 446 if (scmd_id(cmd) == priv->qinitid) { 447 cmd->result = DID_BAD_TARGET << 16; 448 done(cmd); 449 return 0; 450 } 451 452 cmd->scsi_done = done; 453 /* wait for the last command's interrupt to finish */ 454 while (priv->qlcmd != NULL) { 455 barrier(); 456 cpu_relax(); 457 } 458 ql_icmd(cmd); 459 return 0; 460 } 461 462 DEF_SCSI_QCMD(qlogicfas408_queuecommand) 463 464 /* 465 * Return bios parameters 466 */ 467 468 int qlogicfas408_biosparam(struct scsi_device *disk, struct block_device *dev, 469 sector_t capacity, int ip[]) 470 { 471 /* This should mimic the DOS Qlogic driver's behavior exactly */ 472 ip[0] = 0x40; 473 ip[1] = 0x20; 474 ip[2] = (unsigned long) capacity / (ip[0] * ip[1]); 475 if (ip[2] > 1024) { 476 ip[0] = 0xff; 477 ip[1] = 0x3f; 478 ip[2] = (unsigned long) capacity / (ip[0] * ip[1]); 479 #if 0 480 if (ip[2] > 1023) 481 ip[2] = 1023; 482 #endif 483 } 484 return 0; 485 } 486 487 /* 488 * Abort a command in progress 489 */ 490 491 int qlogicfas408_abort(struct scsi_cmnd *cmd) 492 { 493 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); 494 priv->qabort = 1; 495 ql_zap(priv); 496 return SUCCESS; 497 } 498 499 /* 500 * Reset SCSI bus 501 * FIXME: This function is invoked with cmd = NULL directly by 502 * the PCMCIA qlogic_stub code. This wants fixing 503 */ 504 505 int qlogicfas408_host_reset(struct scsi_cmnd *cmd) 506 { 507 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); 508 unsigned long flags; 509 510 priv->qabort = 2; 511 512 spin_lock_irqsave(cmd->device->host->host_lock, flags); 513 ql_zap(priv); 514 spin_unlock_irqrestore(cmd->device->host->host_lock, flags); 515 516 return SUCCESS; 517 } 518 519 /* 520 * Return info string 521 */ 522 523 const char *qlogicfas408_info(struct Scsi_Host *host) 524 { 525 struct qlogicfas408_priv *priv = get_priv_by_host(host); 526 return priv->qinfo; 527 } 528 529 /* 530 * Get type of chip 531 */ 532 533 int qlogicfas408_get_chip_type(int qbase, int int_type) 534 { 535 REG1; 536 return inb(qbase + 0xe) & 0xf8; 537 } 538 539 /* 540 * Perform initialization tasks 541 */ 542 543 void qlogicfas408_setup(int qbase, int id, int int_type) 544 { 545 outb(1, qbase + 8); /* set for PIO pseudo DMA */ 546 REG0; 547 outb(0x40 | qlcfg8 | id, qbase + 8); /* (ini) bus id, disable scsi rst */ 548 outb(qlcfg5, qbase + 5); /* select timer */ 549 outb(qlcfg9, qbase + 9); /* prescaler */ 550 551 #if QL_RESET_AT_START 552 outb(3, qbase + 3); 553 554 REG1; 555 /* FIXME: timeout */ 556 while (inb(qbase + 0xf) & 4) 557 cpu_relax(); 558 559 REG0; 560 #endif 561 } 562 563 /* 564 * Checks if this is a QLogic FAS 408 565 */ 566 567 int qlogicfas408_detect(int qbase, int int_type) 568 { 569 REG1; 570 return (((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7) && 571 ((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7)); 572 } 573 574 /* 575 * Disable interrupts 576 */ 577 578 void qlogicfas408_disable_ints(struct qlogicfas408_priv *priv) 579 { 580 int qbase = priv->qbase; 581 int int_type = priv->int_type; 582 583 REG1; 584 outb(0, qbase + 0xb); /* disable ints */ 585 } 586 587 /* 588 * Init and exit functions 589 */ 590 591 static int __init qlogicfas408_init(void) 592 { 593 return 0; 594 } 595 596 static void __exit qlogicfas408_exit(void) 597 { 598 599 } 600 601 MODULE_AUTHOR("Tom Zerucha, Michael Griffith"); 602 MODULE_DESCRIPTION("Driver for the Qlogic FAS SCSI controllers"); 603 MODULE_LICENSE("GPL"); 604 module_init(qlogicfas408_init); 605 module_exit(qlogicfas408_exit); 606 607 EXPORT_SYMBOL(qlogicfas408_info); 608 EXPORT_SYMBOL(qlogicfas408_queuecommand); 609 EXPORT_SYMBOL(qlogicfas408_abort); 610 EXPORT_SYMBOL(qlogicfas408_host_reset); 611 EXPORT_SYMBOL(qlogicfas408_biosparam); 612 EXPORT_SYMBOL(qlogicfas408_ihandl); 613 EXPORT_SYMBOL(qlogicfas408_get_chip_type); 614 EXPORT_SYMBOL(qlogicfas408_setup); 615 EXPORT_SYMBOL(qlogicfas408_detect); 616 EXPORT_SYMBOL(qlogicfas408_disable_ints); 617 618