1 /*----------------------------------------------------------------*/
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.
7 Copyright 1994, Tom Zerucha.
10 Additional Code, and much appreciated help by
14 Thanks to Eric Youngdale and Dave Hinds for loadable module and PCMCIA
15 help respectively, and for suffering through my foolishness during the
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)
21 Version 0.46 1/30/97 - kernel 1.2.0+
23 Functions as standalone, loadable, and PCMCIA driver, the latter from
24 Dave Hinds' PCMCIA package.
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
29 - Non terminating hardware waits
30 - Some layering violations with its pcmcia stub
32 Redistributable under terms of the GNU General Public License
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.
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>
59 #include <scsi/scsi_host.h>
60 #include "qlogicfas408.h"
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);
70 /*----------------------------------------------------------------*/
72 /*----------------------------------------------------------------*/
74 /*----------------------------------------------------------------*/
76 /* error recovery - reset everything */
78 static void ql_zap(struct qlogicfas408_priv *priv)
81 int qbase = priv->qbase;
82 int int_type = priv->int_type;
86 outb(3, qbase + 3); /* reset SCSI */
87 outb(2, qbase + 3); /* reset chip */
93 * Do a pseudo-dma tranfer
96 static int ql_pdma(struct qlogicfas408_priv *priv, int phase, char *request,
100 int qbase = priv->qbase;
102 if (phase & 1) { /* in */
105 /* empty fifo in large chunks */
106 if (reqlen >= 128 && (inb(qbase + 8) & 2)) { /* full */
107 insl(qbase + 4, request, 32);
111 while (reqlen >= 84 && !(j & 0xc0)) /* 2/3 */
112 if ((j = inb(qbase + 8)) & 4)
114 insl(qbase + 4, request, 21);
118 if (reqlen >= 44 && (inb(qbase + 8) & 8)) { /* 1/3 */
119 insl(qbase + 4, request, 11);
124 /* until both empty and int (or until reclen is 0) */
127 while (reqlen && !((j & 0x10) && (j & 0xc0)))
129 /* while bytes to receive and not empty */
131 while (reqlen && !((j = inb(qbase + 8)) & 0x10))
133 *request++ = inb(qbase + 4);
143 if (reqlen >= 128 && inb(qbase + 8) & 0x10) { /* empty */
144 outsl(qbase + 4, request, 32);
148 while (reqlen >= 84 && !(j & 0xc0)) /* 1/3 */
149 if (!((j = inb(qbase + 8)) & 8)) {
150 outsl(qbase + 4, request, 21);
154 if (reqlen >= 40 && !(inb(qbase + 8) & 4)) { /* 2/3 */
155 outsl(qbase + 4, request, 10);
160 /* until full and int (or until reclen is 0) */
163 while (reqlen && !((j & 2) && (j & 0xc0))) {
164 /* while bytes to send and not full */
165 while (reqlen && !((j = inb(qbase + 8)) & 2))
167 outb(*request++, qbase + 4);
174 /* maybe return reqlen */
175 return inb(qbase + 8) & 0xc0;
179 * Wait for interrupt flag (polled - not real hardware interrupt)
182 static int ql_wai(struct qlogicfas408_priv *priv)
185 int qbase = priv->qbase;
189 i = jiffies + WATCHDOG;
190 while (time_before(jiffies, i) && !priv->qabort &&
191 !((k = inb(qbase + 4)) & 0xe0)) {
195 if (time_after_eq(jiffies, i))
196 return (DID_TIME_OUT);
198 return (priv->qabort == 1 ? DID_ABORT : DID_RESET);
209 * Initiate scsi command - queueing handler
210 * caller must hold host lock
213 static void ql_icmd(struct scsi_cmnd *cmd)
215 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
216 int qbase = priv->qbase;
217 int int_type = priv->int_type;
223 /* clearing of interrupts and the fifo is needed */
225 inb(qbase + 5); /* clear interrupts */
226 if (inb(qbase + 5)) /* if still interrupting */
227 outb(2, qbase + 3); /* reset chip */
228 else if (inb(qbase + 7) & 0x1f)
229 outb(1, qbase + 3); /* clear fifo */
230 while (inb(qbase + 5)); /* clear ints */
232 outb(1, qbase + 8); /* set for PIO pseudo DMA */
233 outb(0, qbase + 0xb); /* disable ints */
234 inb(qbase + 8); /* clear int bits */
236 outb(0x40, qbase + 0xb); /* enable features */
239 outb(qlcfgc, qbase + 0xc);
240 /* config: no reset interrupt, (initiator) bus id */
241 outb(0x40 | qlcfg8 | priv->qinitid, qbase + 8);
242 outb(qlcfg7, qbase + 7);
243 outb(qlcfg6, qbase + 6);
244 outb(qlcfg5, qbase + 5); /* select timer */
245 outb(qlcfg9 & 7, qbase + 9); /* prescaler */
246 /* outb(0x99, qbase + 5); */
247 outb(scmd_id(cmd), qbase + 4);
249 for (i = 0; i < cmd->cmd_len; i++)
250 outb(cmd->cmnd[i], qbase + 2);
253 outb(0x41, qbase + 3); /* select and send command */
257 * Process scsi command - usually after interrupt
260 static void ql_pcmd(struct scsi_cmnd *cmd)
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 */
269 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
270 int qbase = priv->qbase;
271 int int_type = priv->int_type;
277 set_host_byte(cmd, DID_NO_CONNECT);
280 i |= inb(qbase + 5); /* the 0x10 bit can be set after the 0x08 */
282 printk(KERN_ERR "Ql:Bad Interrupt status:%02x\n", i);
284 set_host_byte(cmd, DID_BAD_INTR);
287 j &= 7; /* j = inb( qbase + 7 ) >> 5; */
289 /* correct status is supposed to be step 4 */
290 /* it sometimes returns step 3 but with 0 bytes left to send */
291 /* We can try stuffing the FIFO with the max each time, but we will get a
292 sequence of 3 if any bytes are left (but we do flush the FIFO anyway */
294 if (j != 3 && j != 4) {
295 printk(KERN_ERR "Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n",
296 j, i, inb(qbase + 7) & 0x1f);
298 set_host_byte(cmd, DID_ERROR);
302 if (inb(qbase + 7) & 0x1f) /* if some bytes in fifo */
303 outb(1, qbase + 3); /* clear fifo */
304 /* note that request_bufflen is the total xfer size when sg is used */
305 reqlen = scsi_bufflen(cmd);
306 /* note that it won't work if transfers > 16M are requested */
307 if (reqlen && !((phase = inb(qbase + 4)) & 6)) { /* data phase */
308 struct scatterlist *sg;
310 outb(reqlen, qbase); /* low-mid xfer cnt */
311 outb(reqlen >> 8, qbase + 1); /* low-mid xfer cnt */
312 outb(reqlen >> 16, qbase + 0xe); /* high xfer cnt */
313 outb(0x90, qbase + 3); /* command do xfer */
314 /* PIO pseudo DMA to buffer or sglist */
317 scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) {
322 DID_ABORT : DID_RESET);
325 if (ql_pdma(priv, phase, buf, sg->length))
331 * Wait for irq (split into second state of irq handler
332 * if this can take time)
334 if ((k = ql_wai(priv))) {
335 set_host_byte(cmd, k);
338 k = inb(qbase + 5); /* should be 0x10, bus service */
342 * Enter Status (and Message In) Phase
345 k = jiffies + WATCHDOG;
347 while (time_before(jiffies, k) && !priv->qabort &&
348 !(inb(qbase + 4) & 6))
349 cpu_relax(); /* wait for status phase */
351 if (time_after_eq(jiffies, k)) {
353 set_host_byte(cmd, DID_TIME_OUT);
357 /* FIXME: timeout ?? */
358 while (inb(qbase + 5))
359 cpu_relax(); /* clear pending ints */
363 priv->qabort == 1 ? DID_ABORT : DID_RESET);
367 outb(0x11, qbase + 3); /* get status and message */
368 if ((k = ql_wai(priv))) {
369 set_host_byte(cmd, k);
372 i = inb(qbase + 5); /* get chip irq stat */
373 j = inb(qbase + 7) & 0x1f; /* and bytes rec'd */
374 status = inb(qbase + 2);
375 message = inb(qbase + 2);
378 * Should get function complete int if Status and message, else
379 * bus serv if only status
381 if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) {
382 printk(KERN_ERR "Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j);
383 set_host_byte(cmd, DID_ERROR);
385 outb(0x12, qbase + 3); /* done, disconnect */
387 if ((k = ql_wai(priv))) {
388 set_host_byte(cmd, k);
393 * Should get bus service interrupt and disconnect interrupt
396 i = inb(qbase + 5); /* should be bus service */
397 while (!priv->qabort && ((i & 0x20) != 0x20)) {
406 priv->qabort == 1 ? DID_ABORT : DID_RESET);
410 set_host_byte(cmd, DID_OK);
411 if (message != COMMAND_COMPLETE)
412 scsi_msg_to_host_byte(cmd, message);
413 set_status_byte(cmd, status);
421 static void ql_ihandl(void *dev_id)
423 struct scsi_cmnd *icmd;
424 struct Scsi_Host *host = dev_id;
425 struct qlogicfas408_priv *priv = get_priv_by_host(host);
426 int qbase = priv->qbase;
429 if (!(inb(qbase + 4) & 0x80)) /* false alarm? */
432 if (priv->qlcmd == NULL) { /* no command to process? */
435 while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */
442 * If result is CHECK CONDITION done calls qcommand to request
445 (icmd->scsi_done) (icmd);
448 irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id)
451 struct Scsi_Host *host = dev_id;
453 spin_lock_irqsave(host->host_lock, flags);
455 spin_unlock_irqrestore(host->host_lock, flags);
463 static int qlogicfas408_queuecommand_lck(struct scsi_cmnd *cmd,
464 void (*done) (struct scsi_cmnd *))
466 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
468 set_host_byte(cmd, DID_OK);
469 set_status_byte(cmd, SAM_STAT_GOOD);
470 if (scmd_id(cmd) == priv->qinitid) {
471 set_host_byte(cmd, DID_BAD_TARGET);
476 cmd->scsi_done = done;
477 /* wait for the last command's interrupt to finish */
478 while (priv->qlcmd != NULL) {
486 DEF_SCSI_QCMD(qlogicfas408_queuecommand)
489 * Return bios parameters
492 int qlogicfas408_biosparam(struct scsi_device *disk, struct block_device *dev,
493 sector_t capacity, int ip[])
495 /* This should mimic the DOS Qlogic driver's behavior exactly */
498 ip[2] = (unsigned long) capacity / (ip[0] * ip[1]);
502 ip[2] = (unsigned long) capacity / (ip[0] * ip[1]);
512 * Abort a command in progress
515 int qlogicfas408_abort(struct scsi_cmnd *cmd)
517 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
525 * FIXME: This function is invoked with cmd = NULL directly by
526 * the PCMCIA qlogic_stub code. This wants fixing
529 int qlogicfas408_host_reset(struct scsi_cmnd *cmd)
531 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
536 spin_lock_irqsave(cmd->device->host->host_lock, flags);
538 spin_unlock_irqrestore(cmd->device->host->host_lock, flags);
547 const char *qlogicfas408_info(struct Scsi_Host *host)
549 struct qlogicfas408_priv *priv = get_priv_by_host(host);
557 int qlogicfas408_get_chip_type(int qbase, int int_type)
560 return inb(qbase + 0xe) & 0xf8;
564 * Perform initialization tasks
567 void qlogicfas408_setup(int qbase, int id, int int_type)
569 outb(1, qbase + 8); /* set for PIO pseudo DMA */
571 outb(0x40 | qlcfg8 | id, qbase + 8); /* (ini) bus id, disable scsi rst */
572 outb(qlcfg5, qbase + 5); /* select timer */
573 outb(qlcfg9, qbase + 9); /* prescaler */
575 #if QL_RESET_AT_START
580 while (inb(qbase + 0xf) & 4)
588 * Checks if this is a QLogic FAS 408
591 int qlogicfas408_detect(int qbase, int int_type)
594 return (((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7) &&
595 ((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7));
602 void qlogicfas408_disable_ints(struct qlogicfas408_priv *priv)
604 int qbase = priv->qbase;
605 int int_type = priv->int_type;
608 outb(0, qbase + 0xb); /* disable ints */
612 * Init and exit functions
615 static int __init qlogicfas408_init(void)
620 static void __exit qlogicfas408_exit(void)
625 MODULE_AUTHOR("Tom Zerucha, Michael Griffith");
626 MODULE_DESCRIPTION("Driver for the Qlogic FAS SCSI controllers");
627 MODULE_LICENSE("GPL");
628 module_init(qlogicfas408_init);
629 module_exit(qlogicfas408_exit);
631 EXPORT_SYMBOL(qlogicfas408_info);
632 EXPORT_SYMBOL(qlogicfas408_queuecommand);
633 EXPORT_SYMBOL(qlogicfas408_abort);
634 EXPORT_SYMBOL(qlogicfas408_host_reset);
635 EXPORT_SYMBOL(qlogicfas408_biosparam);
636 EXPORT_SYMBOL(qlogicfas408_ihandl);
637 EXPORT_SYMBOL(qlogicfas408_get_chip_type);
638 EXPORT_SYMBOL(qlogicfas408_setup);
639 EXPORT_SYMBOL(qlogicfas408_detect);
640 EXPORT_SYMBOL(qlogicfas408_disable_ints);