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