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 zerucha@shell.portal.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.41
22
23 Functions as standalone, loadable, and PCMCIA driver, the latter from
24 Dave Hind's PCMCIA package.
25
26 Redistributable under terms of the GNU Public License
27
28 */
29 /*----------------------------------------------------------------*/
30 /* Configuration */
31
32 /* Set the following to 1 to enable the use of interrupts. Note that 0 tends
33 to be more stable, but slower (or ties up the system more) */
34 #define QL_USE_IRQ 1
35
36 /* Set the following to max out the speed of the PIO PseudoDMA transfers,
37 again, 0 tends to be slower, but more stable. */
38 #define QL_TURBO_PDMA 1
39
40 /* This should be 1 to enable parity detection */
41 #define QL_ENABLE_PARITY 1
42
43 /* This will reset all devices when the driver is initialized (during bootup).
44 The other linux drivers don't do this, but the DOS drivers do, and after
45 using DOS or some kind of crash or lockup this will bring things back
46 without requiring a cold boot. It does take some time to recover from a
47 reset, so it is slower, and I have seen timeouts so that devices weren't
48 recognized when this was set. */
49 #define QL_RESET_AT_START 0
50
51 /* crystal frequency in megahertz (for offset 5 and 9)
52 Please set this for your card. Most Qlogic cards are 40 Mhz. The
53 Control Concepts ISA (not VLB) is 24 Mhz */
54 #define XTALFREQ 40
55
56 /**********/
57 /* DANGER! modify these at your own risk */
58 /* SLOWCABLE can usually be reset to zero if you have a clean setup and
59 proper termination. The rest are for synchronous transfers and other
60 advanced features if your device can transfer faster than 5Mb/sec.
61 If you are really curious, email me for a quick howto until I have
62 something official */
63 /**********/
64
65 /*****/
66 /* config register 1 (offset 8) options */
67 /* This needs to be set to 1 if your cabling is long or noisy */
68 #define SLOWCABLE 1
69
70 /*****/
71 /* offset 0xc */
72 /* This will set fast (10Mhz) synchronous timing when set to 1
73 For this to have an effect, FASTCLK must also be 1 */
74 #define FASTSCSI 0
75
76 /* This when set to 1 will set a faster sync transfer rate */
77 #define FASTCLK 0
78 /*(XTALFREQ>25?1:0)*/
79
80 /*****/
81 /* offset 6 */
82 /* This is the sync transfer divisor, XTALFREQ/X will be the maximum
83 achievable data rate (assuming the rest of the system is capable
84 and set properly) */
85 #define SYNCXFRPD 5
86 /*(XTALFREQ/5)*/
87
88 /*****/
89 /* offset 7 */
90 /* This is the count of how many synchronous transfers can take place
91 i.e. how many reqs can occur before an ack is given.
92 The maximum value for this is 15, the upper bits can modify
93 REQ/ACK assertion and deassertion during synchronous transfers
94 If this is 0, the bus will only transfer asynchronously */
95 #define SYNCOFFST 0
96 /* for the curious, bits 7&6 control the deassertion delay in 1/2 cycles
97 of the 40Mhz clock. If FASTCLK is 1, specifying 01 (1/2) will
98 cause the deassertion to be early by 1/2 clock. Bits 5&4 control
99 the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */
100
101 /*----------------------------------------------------------------*/
102 #ifdef PCMCIA
103 #define MODULE
104 #endif
105
106 #if defined(MODULE)
107 #include <linux/config.h>
108 #include <linux/module.h>
109 #endif
110
111 #ifdef PCMCIA
112 #undef MODULE
113 #endif
114
115 #include "../block/blk.h" /* to get disk capacity */
116 #include <linux/kernel.h>
117 #include <linux/string.h>
118 #include <linux/ioport.h>
119 #include <linux/sched.h>
120 #include <unistd.h>
121 #include <asm/io.h>
122 #include <asm/irq.h>
123 #include "sd.h"
124 #include "hosts.h"
125 #include "qlogic.h"
126
127 /*----------------------------------------------------------------*/
128 /* driver state info, local to driver */
129 static int qbase = 0; /* Port */
130 static int qinitid; /* initiator ID */
131 static int qabort; /* Flag to cause an abort */
132 static int qlirq = -1; /* IRQ being used */
133 static char qinfo[80]; /* description */
134 static Scsi_Cmnd *qlcmd; /* current command being processed */
135
136 static int qlcfg5 = ( XTALFREQ << 5 ); /* 15625/512 */
137 static int qlcfg6 = SYNCXFRPD;
138 static int qlcfg7 = SYNCOFFST;
139 static int qlcfg8 = ( SLOWCABLE << 7 ) | ( QL_ENABLE_PARITY << 4 );
140 static int qlcfg9 = ( ( XTALFREQ + 4 ) / 5 );
141 static int qlcfgc = ( FASTCLK << 3 ) | ( FASTSCSI << 4 );
142
143 /*----------------------------------------------------------------*/
144 /* The qlogic card uses two register maps - These macros select which one */
145 #define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd ))
146 #define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb6 , qbase + 0xd ))
147
148 /* following is watchdog timeout in microseconds */
149 #define WATCHDOG 5000000
150
151 /*----------------------------------------------------------------*/
152 /* the following will set the monitor border color (useful to find
153 where something crashed or gets stuck at and as a simple profiler) */
154
155 #if 0
156 #define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);}
157 #else
158 #define rtrc(i) {}
159 #endif
160
161 /*----------------------------------------------------------------*/
162 /* local functions */
163 /*----------------------------------------------------------------*/
164 static void ql_zap(void);
165 /* error recovery - reset everything */
166 void ql_zap()
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
167 {
168 int x;
169 unsigned long flags;
170 save_flags( flags );
171 cli();
172 x = inb(qbase + 0xd);
173 REG0;
174 outb(3, qbase + 3); /* reset SCSI */
175 outb(2, qbase + 3); /* reset chip */
176 if (x & 0x80)
177 REG1;
178 restore_flags( flags );
179 }
180
181 /*----------------------------------------------------------------*/
182 /* do pseudo-dma */
183 static int ql_pdma(int phase, char *request, int reqlen)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
184 {
185 int j;
186 j = 0;
187 if (phase & 1) { /* in */
188 #if QL_TURBO_PDMA
189 rtrc(4)
190 /* empty fifo in large chunks */
191 if( reqlen >= 128 && (inb( qbase + 8 ) & 2) ) { /* full */
192 insl( qbase + 4, request, 32 );
193 reqlen -= 128;
194 request += 128;
195 }
196 while( reqlen >= 84 && !( j & 0xc0 ) ) /* 2/3 */
197 if( (j=inb( qbase + 8 )) & 4 ) {
198 insl( qbase + 4, request, 21 );
199 reqlen -= 84;
200 request += 84;
201 }
202 if( reqlen >= 44 && (inb( qbase + 8 ) & 8) ) { /* 1/3 */
203 insl( qbase + 4, request, 11 );
204 reqlen -= 44;
205 request += 44;
206 }
207 #endif
208 /* until both empty and int (or until reclen is 0) */
209 rtrc(7)
210 j = 0;
211 while( reqlen && !( (j & 0x10) && (j & 0xc0) ) ) {
212 /* while bytes to receive and not empty */
213 j &= 0xc0;
214 while ( reqlen && !( (j=inb(qbase + 8)) & 0x10 ) ) {
215 *request++ = inb(qbase + 4);
216 reqlen--;
217 }
218 if( j & 0x10 )
219 j = inb(qbase+8);
220
221 }
222 }
223 else { /* out */
224 #if QL_TURBO_PDMA
225 rtrc(4)
226 if( reqlen >= 128 && inb( qbase + 8 ) & 0x10 ) { /* empty */
227 outsl(qbase + 4, request, 32 );
228 reqlen -= 128;
229 request += 128;
230 }
231 while( reqlen >= 84 && !( j & 0xc0 ) ) /* 1/3 */
232 if( !((j=inb( qbase + 8 )) & 8) ) {
233 outsl( qbase + 4, request, 21 );
234 reqlen -= 84;
235 request += 84;
236 }
237 if( reqlen >= 40 && !(inb( qbase + 8 ) & 4 ) ) { /* 2/3 */
238 outsl( qbase + 4, request, 10 );
239 reqlen -= 40;
240 request += 40;
241 }
242 #endif
243 /* until full and int (or until reclen is 0) */
244 rtrc(7)
245 j = 0;
246 while( reqlen && !( (j & 2) && (j & 0xc0) ) ) {
247 /* while bytes to send and not full */
248 while ( reqlen && !( (j=inb(qbase + 8)) & 2 ) ) {
249 outb(*request++, qbase + 4);
250 reqlen--;
251 }
252 if( j & 2 )
253 j = inb(qbase+8);
254 }
255 }
256 /* maybe return reqlen */
257 return inb( qbase + 8 ) & 0xc0;
258 }
259
260 /*----------------------------------------------------------------*/
261 /* wait for interrupt flag (polled - not real hardware interrupt) */
262 static int ql_wai(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
263 {
264 int i,k;
265 i = jiffies + WATCHDOG;
266 while ( i > jiffies && !qabort && !((k = inb(qbase + 4)) & 0xe0));
267 if (i <= jiffies)
268 return (DID_TIME_OUT);
269 if (qabort)
270 return (qabort == 1 ? DID_ABORT : DID_RESET);
271 if (k & 0x60)
272 ql_zap();
273 if (k & 0x20)
274 return (DID_PARITY);
275 if (k & 0x40)
276 return (DID_ERROR);
277 return 0;
278 }
279
280 /*----------------------------------------------------------------*/
281 /* initiate scsi command - queueing handler */
282 static void ql_icmd(Scsi_Cmnd * cmd)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
283 {
284 unsigned int i;
285 unsigned long flags;
286
287 qabort = 0;
288
289 save_flags( flags );
290 cli();
291 REG0;
292 /* clearing of interrupts and the fifo is needed */
293 inb(qbase + 5); /* clear interrupts */
294 if (inb(qbase + 5)) /* if still interrupting */
295 outb(2, qbase + 3); /* reset chip */
296 else if (inb(qbase + 7) & 0x1f)
297 outb(1, qbase + 3); /* clear fifo */
298 while (inb(qbase + 5)); /* clear ints */
299 REG1;
300 outb(1, qbase + 8); /* set for PIO pseudo DMA */
301 outb(0, qbase + 0xb); /* disable ints */
302 inb(qbase + 8); /* clear int bits */
303 REG0;
304 outb(0x40, qbase + 0xb); /* enable features */
305
306 /* configurables */
307 outb( qlcfgc , qbase + 0xc);
308 /* config: no reset interrupt, (initiator) bus id */
309 outb( 0x40 | qlcfg8 | qinitid, qbase + 8);
310 outb( qlcfg7 , qbase + 7 );
311 outb( qlcfg6 , qbase + 6 );
312 /**/
313 outb(qlcfg5, qbase + 5); /* select timer */
314 outb(qlcfg9 & 7, qbase + 9); /* prescaler */
315 /* outb(0x99, qbase + 5); */
316 outb(cmd->target, qbase + 4);
317
318 for (i = 0; i < cmd->cmd_len; i++)
319 outb(cmd->cmnd[i], qbase + 2);
320 qlcmd = cmd;
321 outb(0x41, qbase + 3); /* select and send command */
322 restore_flags( flags );
323 }
324 /*----------------------------------------------------------------*/
325 /* process scsi command - usually after interrupt */
326 static unsigned int ql_pcmd(Scsi_Cmnd * cmd)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
327 {
328 unsigned int i, j, k;
329 unsigned int result; /* ultimate return result */
330 unsigned int status; /* scsi returned status */
331 unsigned int message; /* scsi returned message */
332 unsigned int phase; /* recorded scsi phase */
333 unsigned int reqlen; /* total length of transfer */
334 struct scatterlist *sglist; /* scatter-gather list pointer */
335 unsigned int sgcount; /* sg counter */
336
337 rtrc(1)
338 j = inb(qbase + 6);
339 i = inb(qbase + 5);
340 if (i == 0x20) {
341 return (DID_NO_CONNECT << 16);
342 }
343 i |= inb(qbase + 5); /* the 0x10 bit can be set after the 0x08 */
344 if (i != 0x18) {
345 printk("Ql:Bad Interrupt status:%02x\n", i);
346 ql_zap();
347 return (DID_BAD_INTR << 16);
348 }
349 j &= 7; /* j = inb( qbase + 7 ) >> 5; */
350 /* correct status is supposed to be step 4 */
351 /* it sometimes returns step 3 but with 0 bytes left to send */
352 /* We can try stuffing the FIFO with the max each time, but we will get a
353 sequence of 3 if any bytes are left (but we do flush the FIFO anyway */
354 if(j != 3 && j != 4) {
355 printk("Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", j, i, inb( qbase+7 ) & 0x1f );
356 ql_zap();
357 return (DID_ERROR << 16);
358 }
359 result = DID_OK;
360 if (inb(qbase + 7) & 0x1f) /* if some bytes in fifo */
361 outb(1, qbase + 3); /* clear fifo */
362 /* note that request_bufflen is the total xfer size when sg is used */
363 reqlen = cmd->request_bufflen;
364 /* note that it won't work if transfers > 16M are requested */
365 if (reqlen && !((phase = inb(qbase + 4)) & 6)) { /* data phase */
366 rtrc(2)
367 outb(reqlen, qbase); /* low-mid xfer cnt */
368 outb(reqlen >> 8, qbase+1); /* low-mid xfer cnt */
369 outb(reqlen >> 16, qbase + 0xe); /* high xfer cnt */
370 outb(0x90, qbase + 3); /* command do xfer */
371 /* PIO pseudo DMA to buffer or sglist */
372 REG1;
373 if (!cmd->use_sg)
374 ql_pdma(phase, cmd->request_buffer, cmd->request_bufflen);
375 else {
376 sgcount = cmd->use_sg;
377 sglist = cmd->request_buffer;
378 while (sgcount--) {
379 if (qabort) {
380 REG0;
381 return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
382 }
383 if (ql_pdma(phase, sglist->address, sglist->length))
384 break;
385 sglist++;
386 }
387 }
388 REG0;
389 rtrc(2)
390 /* wait for irq (split into second state of irq handler if this can take time) */
391 if ((k = ql_wai()))
392 return (k << 16);
393 k = inb(qbase + 5); /* should be 0x10, bus service */
394 }
395 /*** Enter Status (and Message In) Phase ***/
396 k = jiffies + WATCHDOG;
397 while ( k > jiffies && !qabort && !(inb(qbase + 4) & 6)); /* wait for status phase */
398 if ( k <= jiffies ) {
399 ql_zap();
400 return (DID_TIME_OUT << 16);
401 }
402 while (inb(qbase + 5)); /* clear pending ints */
403 if (qabort)
404 return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
405 outb(0x11, qbase + 3); /* get status and message */
406 if ((k = ql_wai()))
407 return (k << 16);
408 i = inb(qbase + 5); /* get chip irq stat */
409 j = inb(qbase + 7) & 0x1f; /* and bytes rec'd */
410 status = inb(qbase + 2);
411 message = inb(qbase + 2);
412 /* should get function complete int if Status and message, else bus serv if only status */
413 if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) {
414 printk("Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j);
415 result = DID_ERROR;
416 }
417 outb(0x12, qbase + 3); /* done, disconnect */
418 rtrc(1)
419 if ((k = ql_wai()))
420 return (k << 16);
421 /* should get bus service interrupt and disconnect interrupt */
422 i = inb(qbase + 5); /* should be bus service */
423 while (!qabort && ((i & 0x20) != 0x20))
424 i |= inb(qbase + 5);
425 rtrc(0)
426 if (qabort)
427 return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
428 return (result << 16) | (message << 8) | (status & STATUS_MASK);
429 }
430
431 #if QL_USE_IRQ
432 /*----------------------------------------------------------------*/
433 /* interrupt handler */
434 static void ql_ihandl(int irq, struct pt_regs * regs)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
435 {
436 Scsi_Cmnd *icmd;
437 REG0;
438 if (!(inb(qbase + 4) & 0x80)) /* false alarm? */
439 return;
440 if (qlcmd == NULL) { /* no command to process? */
441 int i;
442 i = 16;
443 while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */
444 return;
445 }
446 icmd = qlcmd;
447 icmd->result = ql_pcmd(icmd);
448 qlcmd = NULL;
449 /* if result is CHECK CONDITION done calls qcommand to request sense */
450 (icmd->scsi_done) (icmd);
451 }
452 #endif
453
454 /*----------------------------------------------------------------*/
455 /* global functions */
456 /*----------------------------------------------------------------*/
457 /* non queued command */
458 #if QL_USE_IRQ
459 static void qlidone(Scsi_Cmnd * cmd) {}; /* null function */
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
460 #endif
461
462 /* command process */
463 int qlogic_command(Scsi_Cmnd * cmd)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
464 {
465 int k;
466 #if QL_USE_IRQ
467 if (qlirq >= 0) {
468 qlogic_queuecommand(cmd, qlidone);
469 while (qlcmd != NULL);
470 return cmd->result;
471 }
472 #endif
473 /* non-irq version */
474 if (cmd->target == qinitid)
475 return (DID_BAD_TARGET << 16);
476 ql_icmd(cmd);
477 if ((k = ql_wai()))
478 return (k << 16);
479 return ql_pcmd(cmd);
480
481 }
482
483 #if QL_USE_IRQ
484 /*----------------------------------------------------------------*/
485 /* queued command */
486 int qlogic_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
487 {
488 if(cmd->target == qinitid) {
489 cmd->result = DID_BAD_TARGET << 16;
490 done(cmd);
491 return 0;
492 }
493
494 cmd->scsi_done = done;
495 /* wait for the last command's interrupt to finish */
496 while (qlcmd != NULL);
497 ql_icmd(cmd);
498 return 0;
499 }
500 #else
501 int qlogic_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
502 {
503 return 1;
504 }
505 #endif
506
507 #ifdef PCMCIA
508 /*----------------------------------------------------------------*/
509 /* allow PCMCIA code to preset the port */
510 /* port should be 0 and irq to -1 respectively for autoprobing */
511 void qlogic_preset(int port, int irq)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
512 {
513 qbase=port;
514 qlirq=irq;
515 }
516 #endif
517
518 /*----------------------------------------------------------------*/
519 /* look for qlogic card and init if found */
520 int qlogic_detect(Scsi_Host_Template * host)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
521 {
522 int i, j; /* these are only used by IRQ detect */
523 int qltyp; /* type of chip */
524 struct Scsi_Host *hreg; /* registered host structure */
525 unsigned long flags;
526
527 /* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself decodes the
528 address - I check 230 first since MIDI cards are typically at 330
529
530 Theoretically, two Qlogic cards can coexist in the same system. This
531 should work by simply using this as a loadable module for the second
532 card, but I haven't tested this.
533 */
534
535 if( !qbase ) {
536 for (qbase = 0x230; qbase < 0x430; qbase += 0x100) {
537 if( check_region( qbase , 0x10 ) )
538 continue;
539 REG1;
540 if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 )
541 && ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) )
542 break;
543 }
544 if (qbase == 0x430)
545 return 0;
546 }
547 else
548 printk( "Ql: Using preset base address of %03x\n", qbase );
549
550 qltyp = inb(qbase + 0xe) & 0xf8;
551 qinitid = host->this_id;
552 if (qinitid < 0)
553 qinitid = 7; /* if no ID, use 7 */
554 outb(1, qbase + 8); /* set for PIO pseudo DMA */
555 REG0;
556 outb(0x40 | qlcfg8 | qinitid, qbase + 8); /* (ini) bus id, disable scsi rst */
557 outb(qlcfg5, qbase + 5); /* select timer */
558 outb(qlcfg9, qbase + 9); /* prescaler */
559 qlirq = -1;
560 #if QL_RESET_AT_START
561 outb( 3 , qbase + 3 );
562 REG1;
563 while( inb( qbase + 0xf ) & 4 );
564 REG0;
565 #endif
566 #if QL_USE_IRQ
567 /* IRQ probe - toggle pin and check request pending */
568 if( qlirq == -1 ) {
569 save_flags( flags );
570 cli();
571 i = 0xffff;
572 j = 3;
573 outb(0x90, qbase + 3); /* illegal command - cause interrupt */
574 REG1;
575 outb(10, 0x20); /* access pending interrupt map */
576 outb(10, 0xa0);
577 while (j--) {
578 outb(0xb2 , qbase + 0xd); /* int pin off */
579 i &= ~(inb(0x20) | (inb(0xa0) << 8)); /* find IRQ off */
580 outb(0xb6 , qbase + 0xd); /* int pin on */
581 i &= inb(0x20) | (inb(0xa0) << 8); /* find IRQ on */
582 }
583 REG0;
584 while (inb(qbase + 5)); /* purge int */
585 while (i) /* find on bit */
586 i >>= 1, qlirq++; /* should check for exactly 1 on */
587 if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic"))
588 host->can_queue = 1;
589 restore_flags( flags );
590 }
591 else
592 printk( "Ql: Using preset IRQ of %d\n", qlirq );
593 #endif
594 request_region( qbase , 0x10 ,"qlogic");
595 hreg = scsi_register( host , 0 ); /* no host data */
596 hreg->io_port = qbase;
597 hreg->n_io_port = 16;
598 hreg->dma_channel = -1;
599 if( qlirq != -1 )
600 hreg->irq = qlirq;
601
602 sprintf(qinfo, "Qlogic Driver version 0.41, chip %02X at %03X, IRQ %d, TPdma:%d",
603 qltyp, qbase, qlirq, QL_TURBO_PDMA );
604 host->name = qinfo;
605
606 return 1;
607 }
608
609 /*----------------------------------------------------------------*/
610 /* return bios parameters */
611 int qlogic_biosparam(Disk * disk, int dev, int ip[])
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
612 {
613 /* This should mimic the DOS Qlogic driver's behavior exactly */
614 ip[0] = 0x40;
615 ip[1] = 0x20;
616 ip[2] = disk->capacity / (ip[0] * ip[1]);
617 if (ip[2] > 1024) {
618 ip[0] = 0xff;
619 ip[1] = 0x3f;
620 ip[2] = disk->capacity / (ip[0] * ip[1]);
621 if (ip[2] > 1023)
622 ip[2] = 1023;
623 }
624 return 0;
625 }
626
627 /*----------------------------------------------------------------*/
628 /* abort command in progress */
629 int qlogic_abort(Scsi_Cmnd * cmd)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
630 {
631 qabort = 1;
632 ql_zap();
633 return 0;
634 }
635
636 /*----------------------------------------------------------------*/
637 /* reset SCSI bus */
638 int qlogic_reset(Scsi_Cmnd * cmd)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
639 {
640 qabort = 2;
641 ql_zap();
642 return 1;
643 }
644
645 /*----------------------------------------------------------------*/
646 /* return info string */
647 const char *qlogic_info(struct Scsi_Host * host)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
648 {
649 return qinfo;
650 }
651
652 #ifdef MODULE
653 /* Eventually this will go into an include file, but this will be later */
654 Scsi_Host_Template driver_template = QLOGIC;
655
656 #include "scsi_module.c"
657 #endif