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>
58 #include <scsi/scsi.h>
59 #include <scsi/scsi_cmnd.h>
60 #include <scsi/scsi_device.h>
61 #include <scsi/scsi_eh.h>
62 #include <scsi/scsi_host.h>
63 #include <scsi/scsi_tcq.h>
64 #include "qlogicfas408.h"
66 /*----------------------------------------------------------------*/
67 static int qlcfg5 = (XTALFREQ << 5); /* 15625/512 */
68 static int qlcfg6 = SYNCXFRPD;
69 static int qlcfg7 = SYNCOFFST;
70 static int qlcfg8 = (SLOWCABLE << 7) | (QL_ENABLE_PARITY << 4);
71 static int qlcfg9 = ((XTALFREQ + 4) / 5);
72 static int qlcfgc = (FASTCLK << 3) | (FASTSCSI << 4);
74 /*----------------------------------------------------------------*/
76 /*----------------------------------------------------------------*/
78 /*----------------------------------------------------------------*/
80 /* error recovery - reset everything */
82 static void ql_zap(struct qlogicfas408_priv *priv)
85 int qbase = priv->qbase;
86 int int_type = priv->int_type;
90 outb(3, qbase + 3); /* reset SCSI */
91 outb(2, qbase + 3); /* reset chip */
97 * Do a pseudo-dma tranfer
100 static int ql_pdma(struct qlogicfas408_priv *priv, int phase, char *request,
104 int qbase = priv->qbase;
106 if (phase & 1) { /* in */
109 /* empty fifo in large chunks */
110 if (reqlen >= 128 && (inb(qbase + 8) & 2)) { /* full */
111 insl(qbase + 4, request, 32);
115 while (reqlen >= 84 && !(j & 0xc0)) /* 2/3 */
116 if ((j = inb(qbase + 8)) & 4)
118 insl(qbase + 4, request, 21);
122 if (reqlen >= 44 && (inb(qbase + 8) & 8)) { /* 1/3 */
123 insl(qbase + 4, request, 11);
128 /* until both empty and int (or until reclen is 0) */
131 while (reqlen && !((j & 0x10) && (j & 0xc0)))
133 /* while bytes to receive and not empty */
135 while (reqlen && !((j = inb(qbase + 8)) & 0x10))
137 *request++ = inb(qbase + 4);
147 if (reqlen >= 128 && inb(qbase + 8) & 0x10) { /* empty */
148 outsl(qbase + 4, request, 32);
152 while (reqlen >= 84 && !(j & 0xc0)) /* 1/3 */
153 if (!((j = inb(qbase + 8)) & 8)) {
154 outsl(qbase + 4, request, 21);
158 if (reqlen >= 40 && !(inb(qbase + 8) & 4)) { /* 2/3 */
159 outsl(qbase + 4, request, 10);
164 /* until full and int (or until reclen is 0) */
167 while (reqlen && !((j & 2) && (j & 0xc0))) {
168 /* while bytes to send and not full */
169 while (reqlen && !((j = inb(qbase + 8)) & 2))
171 outb(*request++, qbase + 4);
178 /* maybe return reqlen */
179 return inb(qbase + 8) & 0xc0;
183 * Wait for interrupt flag (polled - not real hardware interrupt)
186 static int ql_wai(struct qlogicfas408_priv *priv)
189 int qbase = priv->qbase;
193 i = jiffies + WATCHDOG;
194 while (time_before(jiffies, i) && !priv->qabort &&
195 !((k = inb(qbase + 4)) & 0xe0)) {
199 if (time_after_eq(jiffies, i))
200 return (DID_TIME_OUT);
202 return (priv->qabort == 1 ? DID_ABORT : DID_RESET);
213 * Initiate scsi command - queueing handler
214 * caller must hold host lock
217 static void ql_icmd(struct scsi_cmnd *cmd)
219 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
220 int qbase = priv->qbase;
221 int int_type = priv->int_type;
227 /* clearing of interrupts and the fifo is needed */
229 inb(qbase + 5); /* clear interrupts */
230 if (inb(qbase + 5)) /* if still interrupting */
231 outb(2, qbase + 3); /* reset chip */
232 else if (inb(qbase + 7) & 0x1f)
233 outb(1, qbase + 3); /* clear fifo */
234 while (inb(qbase + 5)); /* clear ints */
236 outb(1, qbase + 8); /* set for PIO pseudo DMA */
237 outb(0, qbase + 0xb); /* disable ints */
238 inb(qbase + 8); /* clear int bits */
240 outb(0x40, qbase + 0xb); /* enable features */
243 outb(qlcfgc, qbase + 0xc);
244 /* config: no reset interrupt, (initiator) bus id */
245 outb(0x40 | qlcfg8 | priv->qinitid, qbase + 8);
246 outb(qlcfg7, qbase + 7);
247 outb(qlcfg6, qbase + 6);
248 outb(qlcfg5, qbase + 5); /* select timer */
249 outb(qlcfg9 & 7, qbase + 9); /* prescaler */
250 /* outb(0x99, qbase + 5); */
251 outb(scmd_id(cmd), qbase + 4);
253 for (i = 0; i < cmd->cmd_len; i++)
254 outb(cmd->cmnd[i], qbase + 2);
257 outb(0x41, qbase + 3); /* select and send command */
261 * Process scsi command - usually after interrupt
264 static void ql_pcmd(struct scsi_cmnd *cmd)
268 unsigned int status; /* scsi returned status */
269 unsigned int message; /* scsi returned message */
270 unsigned int phase; /* recorded scsi phase */
271 unsigned int reqlen; /* total length of transfer */
273 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
274 int qbase = priv->qbase;
275 int int_type = priv->int_type;
281 set_host_byte(cmd, DID_NO_CONNECT);
284 i |= inb(qbase + 5); /* the 0x10 bit can be set after the 0x08 */
286 printk(KERN_ERR "Ql:Bad Interrupt status:%02x\n", i);
288 set_host_byte(cmd, DID_BAD_INTR);
291 j &= 7; /* j = inb( qbase + 7 ) >> 5; */
293 /* correct status is supposed to be step 4 */
294 /* it sometimes returns step 3 but with 0 bytes left to send */
295 /* We can try stuffing the FIFO with the max each time, but we will get a
296 sequence of 3 if any bytes are left (but we do flush the FIFO anyway */
298 if (j != 3 && j != 4) {
299 printk(KERN_ERR "Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n",
300 j, i, inb(qbase + 7) & 0x1f);
302 set_host_byte(cmd, DID_ERROR);
306 if (inb(qbase + 7) & 0x1f) /* if some bytes in fifo */
307 outb(1, qbase + 3); /* clear fifo */
308 /* note that request_bufflen is the total xfer size when sg is used */
309 reqlen = scsi_bufflen(cmd);
310 /* note that it won't work if transfers > 16M are requested */
311 if (reqlen && !((phase = inb(qbase + 4)) & 6)) { /* data phase */
312 struct scatterlist *sg;
314 outb(reqlen, qbase); /* low-mid xfer cnt */
315 outb(reqlen >> 8, qbase + 1); /* low-mid xfer cnt */
316 outb(reqlen >> 16, qbase + 0xe); /* high xfer cnt */
317 outb(0x90, qbase + 3); /* command do xfer */
318 /* PIO pseudo DMA to buffer or sglist */
321 scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) {
326 DID_ABORT : DID_RESET);
329 if (ql_pdma(priv, phase, buf, sg->length))
335 * Wait for irq (split into second state of irq handler
336 * if this can take time)
338 if ((k = ql_wai(priv))) {
339 set_host_byte(cmd, k);
342 k = inb(qbase + 5); /* should be 0x10, bus service */
346 * Enter Status (and Message In) Phase
349 k = jiffies + WATCHDOG;
351 while (time_before(jiffies, k) && !priv->qabort &&
352 !(inb(qbase + 4) & 6))
353 cpu_relax(); /* wait for status phase */
355 if (time_after_eq(jiffies, k)) {
357 set_host_byte(cmd, DID_TIME_OUT);
361 /* FIXME: timeout ?? */
362 while (inb(qbase + 5))
363 cpu_relax(); /* clear pending ints */
367 priv->qabort == 1 ? DID_ABORT : DID_RESET);
371 outb(0x11, qbase + 3); /* get status and message */
372 if ((k = ql_wai(priv))) {
373 set_host_byte(cmd, k);
376 i = inb(qbase + 5); /* get chip irq stat */
377 j = inb(qbase + 7) & 0x1f; /* and bytes rec'd */
378 status = inb(qbase + 2);
379 message = inb(qbase + 2);
382 * Should get function complete int if Status and message, else
383 * bus serv if only status
385 if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) {
386 printk(KERN_ERR "Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j);
387 set_host_byte(cmd, DID_ERROR);
389 outb(0x12, qbase + 3); /* done, disconnect */
391 if ((k = ql_wai(priv))) {
392 set_host_byte(cmd, k);
397 * Should get bus service interrupt and disconnect interrupt
400 i = inb(qbase + 5); /* should be bus service */
401 while (!priv->qabort && ((i & 0x20) != 0x20)) {
410 priv->qabort == 1 ? DID_ABORT : DID_RESET);
414 set_host_byte(cmd, DID_OK);
415 if (message != COMMAND_COMPLETE)
416 scsi_msg_to_host_byte(cmd, message);
417 set_status_byte(cmd, status);
425 static void ql_ihandl(void *dev_id)
427 struct scsi_cmnd *icmd;
428 struct Scsi_Host *host = dev_id;
429 struct qlogicfas408_priv *priv = get_priv_by_host(host);
430 int qbase = priv->qbase;
433 if (!(inb(qbase + 4) & 0x80)) /* false alarm? */
436 if (priv->qlcmd == NULL) { /* no command to process? */
439 while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */
446 * If result is CHECK CONDITION done calls qcommand to request
452 irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id)
455 struct Scsi_Host *host = dev_id;
457 spin_lock_irqsave(host->host_lock, flags);
459 spin_unlock_irqrestore(host->host_lock, flags);
467 static int qlogicfas408_queuecommand_lck(struct scsi_cmnd *cmd)
469 void (*done)(struct scsi_cmnd *) = scsi_done;
470 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
472 set_host_byte(cmd, DID_OK);
473 set_status_byte(cmd, SAM_STAT_GOOD);
474 if (scmd_id(cmd) == priv->qinitid) {
475 set_host_byte(cmd, DID_BAD_TARGET);
480 /* wait for the last command's interrupt to finish */
481 while (priv->qlcmd != NULL) {
489 DEF_SCSI_QCMD(qlogicfas408_queuecommand)
492 * Return bios parameters
495 int qlogicfas408_biosparam(struct scsi_device *disk, struct block_device *dev,
496 sector_t capacity, int ip[])
498 /* This should mimic the DOS Qlogic driver's behavior exactly */
501 ip[2] = (unsigned long) capacity / (ip[0] * ip[1]);
505 ip[2] = (unsigned long) capacity / (ip[0] * ip[1]);
515 * Abort a command in progress
518 int qlogicfas408_abort(struct scsi_cmnd *cmd)
520 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
528 * FIXME: This function is invoked with cmd = NULL directly by
529 * the PCMCIA qlogic_stub code. This wants fixing
532 int qlogicfas408_host_reset(struct scsi_cmnd *cmd)
534 struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
539 spin_lock_irqsave(cmd->device->host->host_lock, flags);
541 spin_unlock_irqrestore(cmd->device->host->host_lock, flags);
550 const char *qlogicfas408_info(struct Scsi_Host *host)
552 struct qlogicfas408_priv *priv = get_priv_by_host(host);
560 int qlogicfas408_get_chip_type(int qbase, int int_type)
563 return inb(qbase + 0xe) & 0xf8;
567 * Perform initialization tasks
570 void qlogicfas408_setup(int qbase, int id, int int_type)
572 outb(1, qbase + 8); /* set for PIO pseudo DMA */
574 outb(0x40 | qlcfg8 | id, qbase + 8); /* (ini) bus id, disable scsi rst */
575 outb(qlcfg5, qbase + 5); /* select timer */
576 outb(qlcfg9, qbase + 9); /* prescaler */
578 #if QL_RESET_AT_START
583 while (inb(qbase + 0xf) & 4)
591 * Checks if this is a QLogic FAS 408
594 int qlogicfas408_detect(int qbase, int int_type)
597 return (((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7) &&
598 ((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7));
605 void qlogicfas408_disable_ints(struct qlogicfas408_priv *priv)
607 int qbase = priv->qbase;
608 int int_type = priv->int_type;
611 outb(0, qbase + 0xb); /* disable ints */
615 * Init and exit functions
618 static int __init qlogicfas408_init(void)
623 static void __exit qlogicfas408_exit(void)
628 MODULE_AUTHOR("Tom Zerucha, Michael Griffith");
629 MODULE_DESCRIPTION("Driver for the Qlogic FAS SCSI controllers");
630 MODULE_LICENSE("GPL");
631 module_init(qlogicfas408_init);
632 module_exit(qlogicfas408_exit);
634 EXPORT_SYMBOL(qlogicfas408_info);
635 EXPORT_SYMBOL(qlogicfas408_queuecommand);
636 EXPORT_SYMBOL(qlogicfas408_abort);
637 EXPORT_SYMBOL(qlogicfas408_host_reset);
638 EXPORT_SYMBOL(qlogicfas408_biosparam);
639 EXPORT_SYMBOL(qlogicfas408_ihandl);
640 EXPORT_SYMBOL(qlogicfas408_get_chip_type);
641 EXPORT_SYMBOL(qlogicfas408_setup);
642 EXPORT_SYMBOL(qlogicfas408_detect);
643 EXPORT_SYMBOL(qlogicfas408_disable_ints);