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 #include<linux/stat.h>
135
136 struct proc_dir_entry proc_scsi_qlogic = {
137 PROC_SCSI_QLOGIC, 6, "qlogic",
138 S_IFDIR | S_IRUGO | S_IXUGO, 2
139 };
140
141 /*----------------------------------------------------------------*/
142 /* driver state info, local to driver */
143 static int qbase = 0; /* Port */
144 static int qinitid; /* initiator ID */
145 static int qabort; /* Flag to cause an abort */
146 static int qlirq = -1; /* IRQ being used */
147 static char qinfo[80]; /* description */
148 static Scsi_Cmnd *qlcmd; /* current command being processed */
149
150 static int qlcfg5 = ( XTALFREQ << 5 ); /* 15625/512 */
151 static int qlcfg6 = SYNCXFRPD;
152 static int qlcfg7 = SYNCOFFST;
153 static int qlcfg8 = ( SLOWCABLE << 7 ) | ( QL_ENABLE_PARITY << 4 );
154 static int qlcfg9 = ( ( XTALFREQ + 4 ) / 5 );
155 static int qlcfgc = ( FASTCLK << 3 ) | ( FASTSCSI << 4 );
156
157 /*----------------------------------------------------------------*/
158 /* The qlogic card uses two register maps - These macros select which one */
159 #define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd ))
160 #define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd ))
161
162 /* following is watchdog timeout in microseconds */
163 #define WATCHDOG 5000000
164
165 /*----------------------------------------------------------------*/
166 /* the following will set the monitor border color (useful to find
167 where something crashed or gets stuck at and as a simple profiler) */
168
169 #if 0
170 #define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);}
171 #else
172 #define rtrc(i) {}
173 #endif
174
175 /*----------------------------------------------------------------*/
176 /* local functions */
177 /*----------------------------------------------------------------*/
178 static void ql_zap(void);
179 /* error recovery - reset everything */
180 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)
*/
181 {
182 int x;
183 unsigned long flags;
184 save_flags( flags );
185 cli();
186 x = inb(qbase + 0xd);
187 REG0;
188 outb(3, qbase + 3); /* reset SCSI */
189 outb(2, qbase + 3); /* reset chip */
190 if (x & 0x80)
191 REG1;
192 restore_flags( flags );
193 }
194
195 /*----------------------------------------------------------------*/
196 /* do pseudo-dma */
197 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)
*/
198 {
199 int j;
200 j = 0;
201 if (phase & 1) { /* in */
202 #if QL_TURBO_PDMA
203 rtrc(4)
204 /* empty fifo in large chunks */
205 if( reqlen >= 128 && (inb( qbase + 8 ) & 2) ) { /* full */
206 insl( qbase + 4, request, 32 );
207 reqlen -= 128;
208 request += 128;
209 }
210 while( reqlen >= 84 && !( j & 0xc0 ) ) /* 2/3 */
211 if( (j=inb( qbase + 8 )) & 4 ) {
212 insl( qbase + 4, request, 21 );
213 reqlen -= 84;
214 request += 84;
215 }
216 if( reqlen >= 44 && (inb( qbase + 8 ) & 8) ) { /* 1/3 */
217 insl( qbase + 4, request, 11 );
218 reqlen -= 44;
219 request += 44;
220 }
221 #endif
222 /* until both empty and int (or until reclen is 0) */
223 rtrc(7)
224 j = 0;
225 while( reqlen && !( (j & 0x10) && (j & 0xc0) ) ) {
226 /* while bytes to receive and not empty */
227 j &= 0xc0;
228 while ( reqlen && !( (j=inb(qbase + 8)) & 0x10 ) ) {
229 *request++ = inb(qbase + 4);
230 reqlen--;
231 }
232 if( j & 0x10 )
233 j = inb(qbase+8);
234
235 }
236 }
237 else { /* out */
238 #if QL_TURBO_PDMA
239 rtrc(4)
240 if( reqlen >= 128 && inb( qbase + 8 ) & 0x10 ) { /* empty */
241 outsl(qbase + 4, request, 32 );
242 reqlen -= 128;
243 request += 128;
244 }
245 while( reqlen >= 84 && !( j & 0xc0 ) ) /* 1/3 */
246 if( !((j=inb( qbase + 8 )) & 8) ) {
247 outsl( qbase + 4, request, 21 );
248 reqlen -= 84;
249 request += 84;
250 }
251 if( reqlen >= 40 && !(inb( qbase + 8 ) & 4 ) ) { /* 2/3 */
252 outsl( qbase + 4, request, 10 );
253 reqlen -= 40;
254 request += 40;
255 }
256 #endif
257 /* until full and int (or until reclen is 0) */
258 rtrc(7)
259 j = 0;
260 while( reqlen && !( (j & 2) && (j & 0xc0) ) ) {
261 /* while bytes to send and not full */
262 while ( reqlen && !( (j=inb(qbase + 8)) & 2 ) ) {
263 outb(*request++, qbase + 4);
264 reqlen--;
265 }
266 if( j & 2 )
267 j = inb(qbase+8);
268 }
269 }
270 /* maybe return reqlen */
271 return inb( qbase + 8 ) & 0xc0;
272 }
273
274 /*----------------------------------------------------------------*/
275 /* wait for interrupt flag (polled - not real hardware interrupt) */
276 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)
*/
277 {
278 int i,k;
279 k = 0;
280 i = jiffies + WATCHDOG;
281 while ( i > jiffies && !qabort && !((k = inb(qbase + 4)) & 0xe0))
282 barrier();
283 if (i <= jiffies)
284 return (DID_TIME_OUT);
285 if (qabort)
286 return (qabort == 1 ? DID_ABORT : DID_RESET);
287 if (k & 0x60)
288 ql_zap();
289 if (k & 0x20)
290 return (DID_PARITY);
291 if (k & 0x40)
292 return (DID_ERROR);
293 return 0;
294 }
295
296 /*----------------------------------------------------------------*/
297 /* initiate scsi command - queueing handler */
298 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)
*/
299 {
300 unsigned int i;
301 unsigned long flags;
302
303 qabort = 0;
304
305 save_flags( flags );
306 cli();
307 REG0;
308 /* clearing of interrupts and the fifo is needed */
309 inb(qbase + 5); /* clear interrupts */
310 if (inb(qbase + 5)) /* if still interrupting */
311 outb(2, qbase + 3); /* reset chip */
312 else if (inb(qbase + 7) & 0x1f)
313 outb(1, qbase + 3); /* clear fifo */
314 while (inb(qbase + 5)); /* clear ints */
315 REG1;
316 outb(1, qbase + 8); /* set for PIO pseudo DMA */
317 outb(0, qbase + 0xb); /* disable ints */
318 inb(qbase + 8); /* clear int bits */
319 REG0;
320 outb(0x40, qbase + 0xb); /* enable features */
321
322 /* configurables */
323 outb( qlcfgc , qbase + 0xc);
324 /* config: no reset interrupt, (initiator) bus id */
325 outb( 0x40 | qlcfg8 | qinitid, qbase + 8);
326 outb( qlcfg7 , qbase + 7 );
327 outb( qlcfg6 , qbase + 6 );
328 /**/
329 outb(qlcfg5, qbase + 5); /* select timer */
330 outb(qlcfg9 & 7, qbase + 9); /* prescaler */
331 /* outb(0x99, qbase + 5); */
332 outb(cmd->target, qbase + 4);
333
334 for (i = 0; i < cmd->cmd_len; i++)
335 outb(cmd->cmnd[i], qbase + 2);
336 qlcmd = cmd;
337 outb(0x41, qbase + 3); /* select and send command */
338 restore_flags( flags );
339 }
340 /*----------------------------------------------------------------*/
341 /* process scsi command - usually after interrupt */
342 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)
*/
343 {
344 unsigned int i, j, k;
345 unsigned int result; /* ultimate return result */
346 unsigned int status; /* scsi returned status */
347 unsigned int message; /* scsi returned message */
348 unsigned int phase; /* recorded scsi phase */
349 unsigned int reqlen; /* total length of transfer */
350 struct scatterlist *sglist; /* scatter-gather list pointer */
351 unsigned int sgcount; /* sg counter */
352
353 rtrc(1)
354 j = inb(qbase + 6);
355 i = inb(qbase + 5);
356 if (i == 0x20) {
357 return (DID_NO_CONNECT << 16);
358 }
359 i |= inb(qbase + 5); /* the 0x10 bit can be set after the 0x08 */
360 if (i != 0x18) {
361 printk("Ql:Bad Interrupt status:%02x\n", i);
362 ql_zap();
363 return (DID_BAD_INTR << 16);
364 }
365 j &= 7; /* j = inb( qbase + 7 ) >> 5; */
366 /* correct status is supposed to be step 4 */
367 /* it sometimes returns step 3 but with 0 bytes left to send */
368 /* We can try stuffing the FIFO with the max each time, but we will get a
369 sequence of 3 if any bytes are left (but we do flush the FIFO anyway */
370 if(j != 3 && j != 4) {
371 printk("Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", j, i, inb( qbase+7 ) & 0x1f );
372 ql_zap();
373 return (DID_ERROR << 16);
374 }
375 result = DID_OK;
376 if (inb(qbase + 7) & 0x1f) /* if some bytes in fifo */
377 outb(1, qbase + 3); /* clear fifo */
378 /* note that request_bufflen is the total xfer size when sg is used */
379 reqlen = cmd->request_bufflen;
380 /* note that it won't work if transfers > 16M are requested */
381 if (reqlen && !((phase = inb(qbase + 4)) & 6)) { /* data phase */
382 rtrc(2)
383 outb(reqlen, qbase); /* low-mid xfer cnt */
384 outb(reqlen >> 8, qbase+1); /* low-mid xfer cnt */
385 outb(reqlen >> 16, qbase + 0xe); /* high xfer cnt */
386 outb(0x90, qbase + 3); /* command do xfer */
387 /* PIO pseudo DMA to buffer or sglist */
388 REG1;
389 if (!cmd->use_sg)
390 ql_pdma(phase, cmd->request_buffer, cmd->request_bufflen);
391 else {
392 sgcount = cmd->use_sg;
393 sglist = cmd->request_buffer;
394 while (sgcount--) {
395 if (qabort) {
396 REG0;
397 return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
398 }
399 if (ql_pdma(phase, sglist->address, sglist->length))
400 break;
401 sglist++;
402 }
403 }
404 REG0;
405 rtrc(2)
406 /* wait for irq (split into second state of irq handler if this can take time) */
407 if ((k = ql_wai()))
408 return (k << 16);
409 k = inb(qbase + 5); /* should be 0x10, bus service */
410 }
411 /*** Enter Status (and Message In) Phase ***/
412 k = jiffies + WATCHDOG;
413 while ( k > jiffies && !qabort && !(inb(qbase + 4) & 6)); /* wait for status phase */
414 if ( k <= jiffies ) {
415 ql_zap();
416 return (DID_TIME_OUT << 16);
417 }
418 while (inb(qbase + 5)); /* clear pending ints */
419 if (qabort)
420 return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
421 outb(0x11, qbase + 3); /* get status and message */
422 if ((k = ql_wai()))
423 return (k << 16);
424 i = inb(qbase + 5); /* get chip irq stat */
425 j = inb(qbase + 7) & 0x1f; /* and bytes rec'd */
426 status = inb(qbase + 2);
427 message = inb(qbase + 2);
428 /* should get function complete int if Status and message, else bus serv if only status */
429 if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) {
430 printk("Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j);
431 result = DID_ERROR;
432 }
433 outb(0x12, qbase + 3); /* done, disconnect */
434 rtrc(1)
435 if ((k = ql_wai()))
436 return (k << 16);
437 /* should get bus service interrupt and disconnect interrupt */
438 i = inb(qbase + 5); /* should be bus service */
439 while (!qabort && ((i & 0x20) != 0x20)) {
440 barrier();
441 i |= inb(qbase + 5);
442 }
443 rtrc(0)
444 if (qabort)
445 return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
446 return (result << 16) | (message << 8) | (status & STATUS_MASK);
447 }
448
449 #if QL_USE_IRQ
450 /*----------------------------------------------------------------*/
451 /* interrupt handler */
452 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)
*/
453 {
454 Scsi_Cmnd *icmd;
455 REG0;
456 if (!(inb(qbase + 4) & 0x80)) /* false alarm? */
457 return;
458 if (qlcmd == NULL) { /* no command to process? */
459 int i;
460 i = 16;
461 while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */
462 return;
463 }
464 icmd = qlcmd;
465 icmd->result = ql_pcmd(icmd);
466 qlcmd = NULL;
467 /* if result is CHECK CONDITION done calls qcommand to request sense */
468 (icmd->scsi_done) (icmd);
469 }
470 #endif
471
472 /*----------------------------------------------------------------*/
473 /* global functions */
474 /*----------------------------------------------------------------*/
475 /* non queued command */
476 #if QL_USE_IRQ
477 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)
*/
478 #endif
479
480 /* command process */
481 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)
*/
482 {
483 int k;
484 #if QL_USE_IRQ
485 if (qlirq >= 0) {
486 qlogic_queuecommand(cmd, qlidone);
487 while (qlcmd != NULL);
488 return cmd->result;
489 }
490 #endif
491 /* non-irq version */
492 if (cmd->target == qinitid)
493 return (DID_BAD_TARGET << 16);
494 ql_icmd(cmd);
495 if ((k = ql_wai()))
496 return (k << 16);
497 return ql_pcmd(cmd);
498
499 }
500
501 #if QL_USE_IRQ
502 /*----------------------------------------------------------------*/
503 /* queued command */
504 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)
*/
505 {
506 if(cmd->target == qinitid) {
507 cmd->result = DID_BAD_TARGET << 16;
508 done(cmd);
509 return 0;
510 }
511
512 cmd->scsi_done = done;
513 /* wait for the last command's interrupt to finish */
514 while (qlcmd != NULL)
515 barrier();
516 ql_icmd(cmd);
517 return 0;
518 }
519 #else
520 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)
*/
521 {
522 return 1;
523 }
524 #endif
525
526 #ifdef PCMCIA
527 /*----------------------------------------------------------------*/
528 /* allow PCMCIA code to preset the port */
529 /* port should be 0 and irq to -1 respectively for autoprobing */
530 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)
*/
531 {
532 qbase=port;
533 qlirq=irq;
534 }
535 #endif
536
537 /*----------------------------------------------------------------*/
538 /* look for qlogic card and init if found */
539 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)
*/
540 {
541 int i, j; /* these are only used by IRQ detect */
542 int qltyp; /* type of chip */
543 struct Scsi_Host *hreg; /* registered host structure */
544 unsigned long flags;
545
546 host->proc_dir = &proc_scsi_qlogic;
547
548 /* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself decodes the
549 address - I check 230 first since MIDI cards are typically at 330
550
551 Theoretically, two Qlogic cards can coexist in the same system. This
552 should work by simply using this as a loadable module for the second
553 card, but I haven't tested this.
554 */
555
556 if( !qbase ) {
557 for (qbase = 0x230; qbase < 0x430; qbase += 0x100) {
558 if( check_region( qbase , 0x10 ) )
559 continue;
560 REG1;
561 if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 )
562 && ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) )
563 break;
564 }
565 if (qbase == 0x430)
566 return 0;
567 }
568 else
569 printk( "Ql: Using preset base address of %03x\n", qbase );
570
571 qltyp = inb(qbase + 0xe) & 0xf8;
572 qinitid = host->this_id;
573 if (qinitid < 0)
574 qinitid = 7; /* if no ID, use 7 */
575 outb(1, qbase + 8); /* set for PIO pseudo DMA */
576 REG0;
577 outb(0x40 | qlcfg8 | qinitid, qbase + 8); /* (ini) bus id, disable scsi rst */
578 outb(qlcfg5, qbase + 5); /* select timer */
579 outb(qlcfg9, qbase + 9); /* prescaler */
580 #if QL_RESET_AT_START
581 outb( 3 , qbase + 3 );
582 REG1;
583 while( inb( qbase + 0xf ) & 4 );
584 REG0;
585 #endif
586 #if QL_USE_IRQ
587 /* IRQ probe - toggle pin and check request pending */
588
589 if( qlirq == -1 ) {
590 save_flags( flags );
591 cli();
592 i = 0xffff;
593 j = 3;
594 outb(0x90, qbase + 3); /* illegal command - cause interrupt */
595 REG1;
596 outb(10, 0x20); /* access pending interrupt map */
597 outb(10, 0xa0);
598 while (j--) {
599 outb(0xb0 | QL_INT_ACTIVE_HIGH , qbase + 0xd); /* int pin off */
600 i &= ~(inb(0x20) | (inb(0xa0) << 8)); /* find IRQ off */
601 outb(0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd); /* int pin on */
602 i &= inb(0x20) | (inb(0xa0) << 8); /* find IRQ on */
603 }
604 REG0;
605 while (inb(qbase + 5)); /* purge int */
606 j = -1;
607 while (i) /* find on bit */
608 i >>= 1, j++; /* should check for exactly 1 on */
609 qlirq = j;
610 restore_flags( flags );
611 }
612 else
613 printk( "Ql: Using preset IRQ %d\n", qlirq );
614
615 if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic"))
616 host->can_queue = 1;
617 #endif
618 request_region( qbase , 0x10 ,"qlogic");
619 hreg = scsi_register( host , 0 ); /* no host data */
620 hreg->io_port = qbase;
621 hreg->n_io_port = 16;
622 hreg->dma_channel = -1;
623 if( qlirq != -1 )
624 hreg->irq = qlirq;
625
626 sprintf(qinfo, "Qlogic Driver version 0.43, chip %02X at %03X, IRQ %d, TPdma:%d",
627 qltyp, qbase, qlirq, QL_TURBO_PDMA );
628 host->name = qinfo;
629
630 return 1;
631 }
632
633 /*----------------------------------------------------------------*/
634 /* return bios parameters */
635 int qlogic_biosparam(Disk * disk, kdev_t 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)
*/
636 {
637 /* This should mimic the DOS Qlogic driver's behavior exactly */
638 ip[0] = 0x40;
639 ip[1] = 0x20;
640 ip[2] = disk->capacity / (ip[0] * ip[1]);
641 if (ip[2] > 1024) {
642 ip[0] = 0xff;
643 ip[1] = 0x3f;
644 ip[2] = disk->capacity / (ip[0] * ip[1]);
645 if (ip[2] > 1023)
646 ip[2] = 1023;
647 }
648 return 0;
649 }
650
651 /*----------------------------------------------------------------*/
652 /* abort command in progress */
653 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)
*/
654 {
655 qabort = 1;
656 ql_zap();
657 return 0;
658 }
659
660 /*----------------------------------------------------------------*/
661 /* reset SCSI bus */
662 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)
*/
663 {
664 qabort = 2;
665 ql_zap();
666 return 1;
667 }
668
669 /*----------------------------------------------------------------*/
670 /* return info string */
671 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)
*/
672 {
673 return qinfo;
674 }
675
676 #ifdef MODULE
677 /* Eventually this will go into an include file, but this will be later */
678 Scsi_Host_Template driver_template = QLOGIC;
679
680 #include "scsi_module.c"
681 #endif