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