xref: /openbmc/linux/drivers/scsi/qlogicfas408.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
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@redhat.com> 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(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(cmd->device->id, 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(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 	struct scatterlist *sglist;	/* scatter-gather list pointer */
269 	unsigned int sgcount;	/* sg counter */
270 	char *buf;
271 	struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
272 	int qbase = priv->qbase;
273 	int int_type = priv->int_type;
274 
275 	rtrc(1)
276 	j = inb(qbase + 6);
277 	i = inb(qbase + 5);
278 	if (i == 0x20) {
279 		return (DID_NO_CONNECT << 16);
280 	}
281 	i |= inb(qbase + 5);	/* the 0x10 bit can be set after the 0x08 */
282 	if (i != 0x18) {
283 		printk(KERN_ERR "Ql:Bad Interrupt status:%02x\n", i);
284 		ql_zap(priv);
285 		return (DID_BAD_INTR << 16);
286 	}
287 	j &= 7;			/* j = inb( qbase + 7 ) >> 5; */
288 
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 */
293 
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);
297 		ql_zap(priv);
298 		return (DID_ERROR << 16);
299 	}
300 	result = DID_OK;
301 	if (inb(qbase + 7) & 0x1f)	/* if some bytes in fifo */
302 		outb(1, qbase + 3);	/* clear fifo */
303 	/* note that request_bufflen is the total xfer size when sg is used */
304 	reqlen = cmd->request_bufflen;
305 	/* note that it won't work if transfers > 16M are requested */
306 	if (reqlen && !((phase = inb(qbase + 4)) & 6)) {	/* data phase */
307 		rtrc(2)
308 		outb(reqlen, qbase);	/* low-mid xfer cnt */
309 		outb(reqlen >> 8, qbase + 1);	/* low-mid xfer cnt */
310 		outb(reqlen >> 16, qbase + 0xe);	/* high xfer cnt */
311 		outb(0x90, qbase + 3);	/* command do xfer */
312 		/* PIO pseudo DMA to buffer or sglist */
313 		REG1;
314 		if (!cmd->use_sg)
315 			ql_pdma(priv, phase, cmd->request_buffer,
316 				cmd->request_bufflen);
317 		else {
318 			sgcount = cmd->use_sg;
319 			sglist = cmd->request_buffer;
320 			while (sgcount--) {
321 				if (priv->qabort) {
322 					REG0;
323 					return ((priv->qabort == 1 ?
324 						DID_ABORT : DID_RESET) << 16);
325 				}
326 				buf = page_address(sglist->page) + sglist->offset;
327 				if (ql_pdma(priv, phase, buf, sglist->length))
328 					break;
329 				sglist++;
330 			}
331 		}
332 		REG0;
333 		rtrc(2)
334 		/*
335 		 *	Wait for irq (split into second state of irq handler
336 		 *	if this can take time)
337 		 */
338 		if ((k = ql_wai(priv)))
339 			return (k << 16);
340 		k = inb(qbase + 5);	/* should be 0x10, bus service */
341 	}
342 
343 	/*
344 	 *	Enter Status (and Message In) Phase
345 	 */
346 
347 	k = jiffies + WATCHDOG;
348 
349 	while (time_before(jiffies, k) && !priv->qabort &&
350 						!(inb(qbase + 4) & 6))
351 		cpu_relax();	/* wait for status phase */
352 
353 	if (time_after_eq(jiffies, k)) {
354 		ql_zap(priv);
355 		return (DID_TIME_OUT << 16);
356 	}
357 
358 	/* FIXME: timeout ?? */
359 	while (inb(qbase + 5))
360 		cpu_relax();	/* clear pending ints */
361 
362 	if (priv->qabort)
363 		return ((priv->qabort == 1 ? DID_ABORT : DID_RESET) << 16);
364 
365 	outb(0x11, qbase + 3);	/* get status and message */
366 	if ((k = ql_wai(priv)))
367 		return (k << 16);
368 	i = inb(qbase + 5);	/* get chip irq stat */
369 	j = inb(qbase + 7) & 0x1f;	/* and bytes rec'd */
370 	status = inb(qbase + 2);
371 	message = inb(qbase + 2);
372 
373 	/*
374 	 *	Should get function complete int if Status and message, else
375 	 *	bus serv if only status
376 	 */
377 	if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) {
378 		printk(KERN_ERR "Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j);
379 		result = DID_ERROR;
380 	}
381 	outb(0x12, qbase + 3);	/* done, disconnect */
382 	rtrc(1)
383 	if ((k = ql_wai(priv)))
384 		return (k << 16);
385 
386 	/*
387 	 *	Should get bus service interrupt and disconnect interrupt
388 	 */
389 
390 	i = inb(qbase + 5);	/* should be bus service */
391 	while (!priv->qabort && ((i & 0x20) != 0x20)) {
392 		barrier();
393 		cpu_relax();
394 		i |= inb(qbase + 5);
395 	}
396 	rtrc(0)
397 
398 	if (priv->qabort)
399 		return ((priv->qabort == 1 ? DID_ABORT : DID_RESET) << 16);
400 
401 	return (result << 16) | (message << 8) | (status & STATUS_MASK);
402 }
403 
404 /*
405  *	Interrupt handler
406  */
407 
408 static void ql_ihandl(int irq, void *dev_id, struct pt_regs *regs)
409 {
410 	Scsi_Cmnd *icmd;
411 	struct Scsi_Host *host = (struct Scsi_Host *)dev_id;
412 	struct qlogicfas408_priv *priv = get_priv_by_host(host);
413 	int qbase = priv->qbase;
414 	REG0;
415 
416 	if (!(inb(qbase + 4) & 0x80))	/* false alarm? */
417 		return;
418 
419 	if (priv->qlcmd == NULL) {	/* no command to process? */
420 		int i;
421 		i = 16;
422 		while (i-- && inb(qbase + 5));	/* maybe also ql_zap() */
423 		return;
424 	}
425 	icmd = priv->qlcmd;
426 	icmd->result = ql_pcmd(icmd);
427 	priv->qlcmd = NULL;
428 	/*
429 	 *	If result is CHECK CONDITION done calls qcommand to request
430 	 *	sense
431 	 */
432 	(icmd->scsi_done) (icmd);
433 }
434 
435 irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id, struct pt_regs *regs)
436 {
437 	unsigned long flags;
438 	struct Scsi_Host *host = dev_id;
439 
440 	spin_lock_irqsave(host->host_lock, flags);
441 	ql_ihandl(irq, dev_id, regs);
442 	spin_unlock_irqrestore(host->host_lock, flags);
443 	return IRQ_HANDLED;
444 }
445 
446 /*
447  *	Queued command
448  */
449 
450 int qlogicfas408_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
451 {
452 	struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
453 	if (cmd->device->id == priv->qinitid) {
454 		cmd->result = DID_BAD_TARGET << 16;
455 		done(cmd);
456 		return 0;
457 	}
458 
459 	cmd->scsi_done = done;
460 	/* wait for the last command's interrupt to finish */
461 	while (priv->qlcmd != NULL) {
462 		barrier();
463 		cpu_relax();
464 	}
465 	ql_icmd(cmd);
466 	return 0;
467 }
468 
469 /*
470  *	Return bios parameters
471  */
472 
473 int qlogicfas408_biosparam(struct scsi_device * disk,
474 		        struct block_device *dev,
475 			sector_t capacity, int ip[])
476 {
477 /* This should mimic the DOS Qlogic driver's behavior exactly */
478 	ip[0] = 0x40;
479 	ip[1] = 0x20;
480 	ip[2] = (unsigned long) capacity / (ip[0] * ip[1]);
481 	if (ip[2] > 1024) {
482 		ip[0] = 0xff;
483 		ip[1] = 0x3f;
484 		ip[2] = (unsigned long) capacity / (ip[0] * ip[1]);
485 #if 0
486 		if (ip[2] > 1023)
487 			ip[2] = 1023;
488 #endif
489 	}
490 	return 0;
491 }
492 
493 /*
494  *	Abort a command in progress
495  */
496 
497 int qlogicfas408_abort(Scsi_Cmnd * cmd)
498 {
499 	struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
500 	priv->qabort = 1;
501 	ql_zap(priv);
502 	return SUCCESS;
503 }
504 
505 /*
506  *	Reset SCSI bus
507  *	FIXME: This function is invoked with cmd = NULL directly by
508  *	the PCMCIA qlogic_stub code. This wants fixing
509  */
510 
511 int qlogicfas408_bus_reset(Scsi_Cmnd * cmd)
512 {
513 	struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
514 	priv->qabort = 2;
515 	ql_zap(priv);
516 	return SUCCESS;
517 }
518 
519 /*
520  *	Reset SCSI host controller
521  */
522 
523 int qlogicfas408_host_reset(Scsi_Cmnd * cmd)
524 {
525 	return FAILED;
526 }
527 
528 /*
529  *	Reset SCSI device
530  */
531 
532 int qlogicfas408_device_reset(Scsi_Cmnd * cmd)
533 {
534 	return FAILED;
535 }
536 
537 /*
538  *	Return info string
539  */
540 
541 const char *qlogicfas408_info(struct Scsi_Host *host)
542 {
543 	struct qlogicfas408_priv *priv = get_priv_by_host(host);
544 	return priv->qinfo;
545 }
546 
547 /*
548  *	Get type of chip
549  */
550 
551 int qlogicfas408_get_chip_type(int qbase, int int_type)
552 {
553 	REG1;
554 	return inb(qbase + 0xe) & 0xf8;
555 }
556 
557 /*
558  *	Perform initialization tasks
559  */
560 
561 void qlogicfas408_setup(int qbase, int id, int int_type)
562 {
563 	outb(1, qbase + 8);	/* set for PIO pseudo DMA */
564 	REG0;
565 	outb(0x40 | qlcfg8 | id, qbase + 8);	/* (ini) bus id, disable scsi rst */
566 	outb(qlcfg5, qbase + 5);	/* select timer */
567 	outb(qlcfg9, qbase + 9);	/* prescaler */
568 
569 #if QL_RESET_AT_START
570 	outb(3, qbase + 3);
571 
572 	REG1;
573 	/* FIXME: timeout */
574 	while (inb(qbase + 0xf) & 4)
575 		cpu_relax();
576 
577 	REG0;
578 #endif
579 }
580 
581 /*
582  *	Checks if this is a QLogic FAS 408
583  */
584 
585 int qlogicfas408_detect(int qbase, int int_type)
586 {
587         REG1;
588 	return (((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7) &&
589 	       ((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7));
590 }
591 
592 /*
593  *	Disable interrupts
594  */
595 
596 void qlogicfas408_disable_ints(struct qlogicfas408_priv *priv)
597 {
598 	int qbase = priv->qbase;
599 	int int_type = priv->int_type;
600 
601 	REG1;
602 	outb(0, qbase + 0xb);	/* disable ints */
603 }
604 
605 /*
606  *	Init and exit functions
607  */
608 
609 static int __init qlogicfas408_init(void)
610 {
611 	return 0;
612 }
613 
614 static void __exit qlogicfas408_exit(void)
615 {
616 
617 }
618 
619 MODULE_AUTHOR("Tom Zerucha, Michael Griffith");
620 MODULE_DESCRIPTION("Driver for the Qlogic FAS SCSI controllers");
621 MODULE_LICENSE("GPL");
622 module_init(qlogicfas408_init);
623 module_exit(qlogicfas408_exit);
624 
625 EXPORT_SYMBOL(qlogicfas408_info);
626 EXPORT_SYMBOL(qlogicfas408_queuecommand);
627 EXPORT_SYMBOL(qlogicfas408_abort);
628 EXPORT_SYMBOL(qlogicfas408_bus_reset);
629 EXPORT_SYMBOL(qlogicfas408_device_reset);
630 EXPORT_SYMBOL(qlogicfas408_host_reset);
631 EXPORT_SYMBOL(qlogicfas408_biosparam);
632 EXPORT_SYMBOL(qlogicfas408_ihandl);
633 EXPORT_SYMBOL(qlogicfas408_get_chip_type);
634 EXPORT_SYMBOL(qlogicfas408_setup);
635 EXPORT_SYMBOL(qlogicfas408_detect);
636 EXPORT_SYMBOL(qlogicfas408_disable_ints);
637 
638