OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [scsi/] [qlogicfas.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*----------------------------------------------------------------*/
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.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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.