| File: | obj-scan-build/../linux/src/drivers/scsi/qlogicfas.c |
| Location: | line 406, column 3 |
| Description: | Value stored to 'k' is never read |
| 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.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_HIGH2 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_IRQ1 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_PDMA1 1 |
| 44 | |
| 45 | /* This should be 1 to enable parity detection */ |
| 46 | #define QL_ENABLE_PARITY1 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_START0 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 XTALFREQ40 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 SLOWCABLE1 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 FASTSCSI0 0 |
| 80 | |
| 81 | /* This when set to 1 will set a faster sync transfer rate */ |
| 82 | #define FASTCLK0 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 SYNCXFRPD5 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 SYNCOFFST0 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_HIGH2 |
| 109 | #define QL_INT_ACTIVE_HIGH2 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_IFDIR0040000 | S_IRUGO(00400|00040|00004) | S_IXUGO(00100|00010|00001), 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 = ( XTALFREQ40 << 5 ); /* 15625/512 */ |
| 148 | static int qlcfg6 = SYNCXFRPD5; |
| 149 | static int qlcfg7 = SYNCOFFST0; |
| 150 | static int qlcfg8 = ( SLOWCABLE1 << 7 ) | ( QL_ENABLE_PARITY1 << 4 ); |
| 151 | static int qlcfg9 = ( ( XTALFREQ40 + 4 ) / 5 ); |
| 152 | static int qlcfgc = ( FASTCLK0 << 3 ) | ( FASTSCSI0 << 4 ); |
| 153 | |
| 154 | /*----------------------------------------------------------------*/ |
| 155 | /* The qlogic card uses two register maps - These macros select which one */ |
| 156 | #define REG0( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd))), (( __builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc((4),(qbase + 0xd)) : __outb((4),(qbase + 0xd) ))) ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd )((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd))), outb( 4 , qbase + 0xd )((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((4),(qbase + 0xd)) : __outb((4),(qbase + 0xd)))) |
| 157 | #define REG1( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd))), ((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc( (0xb4 | 2),(qbase + 0xd)) : __outb((0xb4 | 2),(qbase + 0xd))) ) ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd )((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd))), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd )((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((0xb4 | 2),(qbase + 0xd)) : __outb((0xb4 | 2),(qbase + 0xd)))) |
| 158 | |
| 159 | /* following is watchdog timeout in microseconds */ |
| 160 | #define WATCHDOG5000000 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)((__builtin_constant_p((0x3da)) && (0x3da) < 256) ? __inbc(0x3da) : __inb(0x3da));outb(0x31,0x3c0)((__builtin_constant_p((0x3c0)) && (0x3c0) < 256) ? __outbc((0x31),(0x3c0)) : __outb((0x31),(0x3c0)));outb((i),0x3c0)((__builtin_constant_p((0x3c0)) && (0x3c0) < 256) ? __outbc(((i)),(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 )__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); |
| 182 | cli()__asm__ __volatile__ ("cli": : :"memory"); |
| 183 | x = inb(qbase + 0xd)((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)); |
| 184 | REG0( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd))), (( __builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc((4),(qbase + 0xd)) : __outb((4),(qbase + 0xd) ))); |
| 185 | outb(3, qbase + 3)((__builtin_constant_p((qbase + 3)) && (qbase + 3) < 256) ? __outbc((3),(qbase + 3)) : __outb((3),(qbase + 3))); /* reset SCSI */ |
| 186 | outb(2, qbase + 3)((__builtin_constant_p((qbase + 3)) && (qbase + 3) < 256) ? __outbc((2),(qbase + 3)) : __outb((2),(qbase + 3))); /* reset chip */ |
| 187 | if (x & 0x80) |
| 188 | REG1( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd))), ((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc( (0xb4 | 2),(qbase + 0xd)) : __outb((0xb4 | 2),(qbase + 0xd))) ); |
| 189 | restore_flags( flags )__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); |
| 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_PDMA1 |
| 200 | rtrc(4){} |
| 201 | /* empty fifo in large chunks */ |
| 202 | if( reqlen >= 128 && (inb( qbase + 8 )((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __inbc(qbase + 8) : __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 )((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __inbc(qbase + 8) : __inb(qbase + 8))) & 4 ) { |
| 209 | insl( qbase + 4, request, 21 ); |
| 210 | reqlen -= 84; |
| 211 | request += 84; |
| 212 | } |
| 213 | if( reqlen >= 44 && (inb( qbase + 8 )((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __inbc(qbase + 8) : __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)((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __inbc(qbase + 8) : __inb(qbase + 8))) & 0x10 ) ) { |
| 226 | *request++ = inb(qbase + 4)((__builtin_constant_p((qbase + 4)) && (qbase + 4) < 256) ? __inbc(qbase + 4) : __inb(qbase + 4)); |
| 227 | reqlen--; |
| 228 | } |
| 229 | if( j & 0x10 ) |
| 230 | j = inb(qbase+8)((__builtin_constant_p((qbase+8)) && (qbase+8) < 256 ) ? __inbc(qbase+8) : __inb(qbase+8)); |
| 231 | |
| 232 | } |
| 233 | } |
| 234 | else { /* out */ |
| 235 | #if QL_TURBO_PDMA1 |
| 236 | rtrc(4){} |
| 237 | if( reqlen >= 128 && inb( qbase + 8 )((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __inbc(qbase + 8) : __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 )((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __inbc(qbase + 8) : __inb(qbase + 8))) & 8) ) { |
| 244 | outsl( qbase + 4, request, 21 ); |
| 245 | reqlen -= 84; |
| 246 | request += 84; |
| 247 | } |
| 248 | if( reqlen >= 40 && !(inb( qbase + 8 )((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __inbc(qbase + 8) : __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)((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __inbc(qbase + 8) : __inb(qbase + 8))) & 2 ) ) { |
| 260 | outb(*request++, qbase + 4)((__builtin_constant_p((qbase + 4)) && (qbase + 4) < 256) ? __outbc((*request++),(qbase + 4)) : __outb((*request++ ),(qbase + 4))); |
| 261 | reqlen--; |
| 262 | } |
| 263 | if( j & 2 ) |
| 264 | j = inb(qbase+8)((__builtin_constant_p((qbase+8)) && (qbase+8) < 256 ) ? __inbc(qbase+8) : __inb(qbase+8)); |
| 265 | } |
| 266 | } |
| 267 | /* maybe return reqlen */ |
| 268 | return inb( qbase + 8 )((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __inbc(qbase + 8) : __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 + WATCHDOG5000000; |
| 278 | while ( i > jiffies && !qabort && !((k = inb(qbase + 4)((__builtin_constant_p((qbase + 4)) && (qbase + 4) < 256) ? __inbc(qbase + 4) : __inb(qbase + 4))) & 0xe0)) |
| 279 | barrier()__asm__ __volatile__("": : :"memory"); |
| 280 | if (i <= jiffies) |
| 281 | return (DID_TIME_OUT0x03); |
| 282 | if (qabort) |
| 283 | return (qabort == 1 ? DID_ABORT0x05 : DID_RESET0x08); |
| 284 | if (k & 0x60) |
| 285 | ql_zap(); |
| 286 | if (k & 0x20) |
| 287 | return (DID_PARITY0x06); |
| 288 | if (k & 0x40) |
| 289 | return (DID_ERROR0x07); |
| 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 )__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); |
| 303 | cli()__asm__ __volatile__ ("cli": : :"memory"); |
| 304 | REG0( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd))), (( __builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc((4),(qbase + 0xd)) : __outb((4),(qbase + 0xd) ))); |
| 305 | /* clearing of interrupts and the fifo is needed */ |
| 306 | inb(qbase + 5)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __inbc(qbase + 5) : __inb(qbase + 5)); /* clear interrupts */ |
| 307 | if (inb(qbase + 5)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __inbc(qbase + 5) : __inb(qbase + 5))) /* if still interrupting */ |
| 308 | outb(2, qbase + 3)((__builtin_constant_p((qbase + 3)) && (qbase + 3) < 256) ? __outbc((2),(qbase + 3)) : __outb((2),(qbase + 3))); /* reset chip */ |
| 309 | else if (inb(qbase + 7)((__builtin_constant_p((qbase + 7)) && (qbase + 7) < 256) ? __inbc(qbase + 7) : __inb(qbase + 7)) & 0x1f) |
| 310 | outb(1, qbase + 3)((__builtin_constant_p((qbase + 3)) && (qbase + 3) < 256) ? __outbc((1),(qbase + 3)) : __outb((1),(qbase + 3))); /* clear fifo */ |
| 311 | while (inb(qbase + 5)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __inbc(qbase + 5) : __inb(qbase + 5))); /* clear ints */ |
| 312 | REG1( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd))), ((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc( (0xb4 | 2),(qbase + 0xd)) : __outb((0xb4 | 2),(qbase + 0xd))) ); |
| 313 | outb(1, qbase + 8)((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __outbc((1),(qbase + 8)) : __outb((1),(qbase + 8))); /* set for PIO pseudo DMA */ |
| 314 | outb(0, qbase + 0xb)((__builtin_constant_p((qbase + 0xb)) && (qbase + 0xb ) < 256) ? __outbc((0),(qbase + 0xb)) : __outb((0),(qbase + 0xb))); /* disable ints */ |
| 315 | inb(qbase + 8)((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __inbc(qbase + 8) : __inb(qbase + 8)); /* clear int bits */ |
| 316 | REG0( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd))), (( __builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc((4),(qbase + 0xd)) : __outb((4),(qbase + 0xd) ))); |
| 317 | outb(0x40, qbase + 0xb)((__builtin_constant_p((qbase + 0xb)) && (qbase + 0xb ) < 256) ? __outbc((0x40),(qbase + 0xb)) : __outb((0x40),( qbase + 0xb))); /* enable features */ |
| 318 | |
| 319 | /* configurables */ |
| 320 | outb( qlcfgc , qbase + 0xc)((__builtin_constant_p((qbase + 0xc)) && (qbase + 0xc ) < 256) ? __outbc((qlcfgc),(qbase + 0xc)) : __outb((qlcfgc ),(qbase + 0xc))); |
| 321 | /* config: no reset interrupt, (initiator) bus id */ |
| 322 | outb( 0x40 | qlcfg8 | qinitid, qbase + 8)((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __outbc((0x40 | qlcfg8 | qinitid),(qbase + 8)) : __outb ((0x40 | qlcfg8 | qinitid),(qbase + 8))); |
| 323 | outb( qlcfg7 , qbase + 7 )((__builtin_constant_p((qbase + 7)) && (qbase + 7) < 256) ? __outbc((qlcfg7),(qbase + 7)) : __outb((qlcfg7),(qbase + 7))); |
| 324 | outb( qlcfg6 , qbase + 6 )((__builtin_constant_p((qbase + 6)) && (qbase + 6) < 256) ? __outbc((qlcfg6),(qbase + 6)) : __outb((qlcfg6),(qbase + 6))); |
| 325 | /**/ |
| 326 | outb(qlcfg5, qbase + 5)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __outbc((qlcfg5),(qbase + 5)) : __outb((qlcfg5),(qbase + 5))); /* select timer */ |
| 327 | outb(qlcfg9 & 7, qbase + 9)((__builtin_constant_p((qbase + 9)) && (qbase + 9) < 256) ? __outbc((qlcfg9 & 7),(qbase + 9)) : __outb((qlcfg9 & 7),(qbase + 9))); /* prescaler */ |
| 328 | /* outb(0x99, qbase + 5); */ |
| 329 | outb(cmd->target, qbase + 4)((__builtin_constant_p((qbase + 4)) && (qbase + 4) < 256) ? __outbc((cmd->target),(qbase + 4)) : __outb((cmd-> target),(qbase + 4))); |
| 330 | |
| 331 | for (i = 0; i < cmd->cmd_len; i++) |
| 332 | outb(cmd->cmnd[i], qbase + 2)((__builtin_constant_p((qbase + 2)) && (qbase + 2) < 256) ? __outbc((cmd->cmnd[i]),(qbase + 2)) : __outb((cmd-> cmnd[i]),(qbase + 2))); |
| 333 | qlcmd = cmd; |
| 334 | outb(0x41, qbase + 3)((__builtin_constant_p((qbase + 3)) && (qbase + 3) < 256) ? __outbc((0x41),(qbase + 3)) : __outb((0x41),(qbase + 3 ))); /* select and send command */ |
| 335 | restore_flags( flags )__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); |
| 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)((__builtin_constant_p((qbase + 6)) && (qbase + 6) < 256) ? __inbc(qbase + 6) : __inb(qbase + 6)); |
| 352 | i = inb(qbase + 5)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __inbc(qbase + 5) : __inb(qbase + 5)); |
| 353 | if (i == 0x20) { |
| 354 | return (DID_NO_CONNECT0x01 << 16); |
| 355 | } |
| 356 | i |= inb(qbase + 5)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __inbc(qbase + 5) : __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_INTR0x09 << 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 )((__builtin_constant_p((qbase+7)) && (qbase+7) < 256 ) ? __inbc(qbase+7) : __inb(qbase+7)) & 0x1f ); |
| 369 | ql_zap(); |
| 370 | return (DID_ERROR0x07 << 16); |
| 371 | } |
| 372 | result = DID_OK0x00; |
| 373 | if (inb(qbase + 7)((__builtin_constant_p((qbase + 7)) && (qbase + 7) < 256) ? __inbc(qbase + 7) : __inb(qbase + 7)) & 0x1f) /* if some bytes in fifo */ |
| 374 | outb(1, qbase + 3)((__builtin_constant_p((qbase + 3)) && (qbase + 3) < 256) ? __outbc((1),(qbase + 3)) : __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)((__builtin_constant_p((qbase + 4)) && (qbase + 4) < 256) ? __inbc(qbase + 4) : __inb(qbase + 4))) & 6)) { /* data phase */ |
| 379 | rtrc(2){} |
| 380 | outb(reqlen, qbase)((__builtin_constant_p((qbase)) && (qbase) < 256) ? __outbc((reqlen),(qbase)) : __outb((reqlen),(qbase))); /* low-mid xfer cnt */ |
| 381 | outb(reqlen >> 8, qbase+1)((__builtin_constant_p((qbase+1)) && (qbase+1) < 256 ) ? __outbc((reqlen >> 8),(qbase+1)) : __outb((reqlen >> 8),(qbase+1))); /* low-mid xfer cnt */ |
| 382 | outb(reqlen >> 16, qbase + 0xe)((__builtin_constant_p((qbase + 0xe)) && (qbase + 0xe ) < 256) ? __outbc((reqlen >> 16),(qbase + 0xe)) : __outb ((reqlen >> 16),(qbase + 0xe))); /* high xfer cnt */ |
| 383 | outb(0x90, qbase + 3)((__builtin_constant_p((qbase + 3)) && (qbase + 3) < 256) ? __outbc((0x90),(qbase + 3)) : __outb((0x90),(qbase + 3 ))); /* command do xfer */ |
| 384 | /* PIO pseudo DMA to buffer or sglist */ |
| 385 | REG1( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd))), ((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc( (0xb4 | 2),(qbase + 0xd)) : __outb((0xb4 | 2),(qbase + 0xd))) ); |
| 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( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd))), (( __builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc((4),(qbase + 0xd)) : __outb((4),(qbase + 0xd) ))); |
| 394 | return ((qabort == 1 ? DID_ABORT0x05 : DID_RESET0x08) << 16); |
| 395 | } |
| 396 | if (ql_pdma(phase, sglist->address, sglist->length)) |
| 397 | break; |
| 398 | sglist++; |
| 399 | } |
| 400 | } |
| 401 | REG0( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd))), (( __builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc((4),(qbase + 0xd)) : __outb((4),(qbase + 0xd) ))); |
| 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)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __inbc(qbase + 5) : __inb(qbase + 5)); /* should be 0x10, bus service */ |
Value stored to 'k' is never read | |
| 407 | } |
| 408 | /*** Enter Status (and Message In) Phase ***/ |
| 409 | k = jiffies + WATCHDOG5000000; |
| 410 | while ( k > jiffies && !qabort && !(inb(qbase + 4)((__builtin_constant_p((qbase + 4)) && (qbase + 4) < 256) ? __inbc(qbase + 4) : __inb(qbase + 4)) & 6)); /* wait for status phase */ |
| 411 | if ( k <= jiffies ) { |
| 412 | ql_zap(); |
| 413 | return (DID_TIME_OUT0x03 << 16); |
| 414 | } |
| 415 | while (inb(qbase + 5)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __inbc(qbase + 5) : __inb(qbase + 5))); /* clear pending ints */ |
| 416 | if (qabort) |
| 417 | return ((qabort == 1 ? DID_ABORT0x05 : DID_RESET0x08) << 16); |
| 418 | outb(0x11, qbase + 3)((__builtin_constant_p((qbase + 3)) && (qbase + 3) < 256) ? __outbc((0x11),(qbase + 3)) : __outb((0x11),(qbase + 3 ))); /* get status and message */ |
| 419 | if ((k = ql_wai())) |
| 420 | return (k << 16); |
| 421 | i = inb(qbase + 5)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __inbc(qbase + 5) : __inb(qbase + 5)); /* get chip irq stat */ |
| 422 | j = inb(qbase + 7)((__builtin_constant_p((qbase + 7)) && (qbase + 7) < 256) ? __inbc(qbase + 7) : __inb(qbase + 7)) & 0x1f; /* and bytes rec'd */ |
| 423 | status = inb(qbase + 2)((__builtin_constant_p((qbase + 2)) && (qbase + 2) < 256) ? __inbc(qbase + 2) : __inb(qbase + 2)); |
| 424 | message = inb(qbase + 2)((__builtin_constant_p((qbase + 2)) && (qbase + 2) < 256) ? __inbc(qbase + 2) : __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_ERROR0x07; |
| 429 | } |
| 430 | outb(0x12, qbase + 3)((__builtin_constant_p((qbase + 3)) && (qbase + 3) < 256) ? __outbc((0x12),(qbase + 3)) : __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)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __inbc(qbase + 5) : __inb(qbase + 5)); /* should be bus service */ |
| 436 | while (!qabort && ((i & 0x20) != 0x20)) { |
| 437 | barrier()__asm__ __volatile__("": : :"memory"); |
| 438 | i |= inb(qbase + 5)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __inbc(qbase + 5) : __inb(qbase + 5)); |
| 439 | } |
| 440 | rtrc(0){} |
| 441 | if (qabort) |
| 442 | return ((qabort == 1 ? DID_ABORT0x05 : DID_RESET0x08) << 16); |
| 443 | return (result << 16) | (message << 8) | (status & STATUS_MASK0x3e); |
| 444 | } |
| 445 | |
| 446 | #if QL_USE_IRQ1 |
| 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( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd))), (( __builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc((4),(qbase + 0xd)) : __outb((4),(qbase + 0xd) ))); |
| 453 | if (!(inb(qbase + 4)((__builtin_constant_p((qbase + 4)) && (qbase + 4) < 256) ? __inbc(qbase + 4) : __inb(qbase + 4)) & 0x80)) /* false alarm? */ |
| 454 | return; |
| 455 | if (qlcmd == NULL((void *) 0)) { /* no command to process? */ |
| 456 | int i; |
| 457 | i = 16; |
| 458 | while (i-- && inb(qbase + 5)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __inbc(qbase + 5) : __inb(qbase + 5))); /* maybe also ql_zap() */ |
| 459 | return; |
| 460 | } |
| 461 | icmd = qlcmd; |
| 462 | icmd->result = ql_pcmd(icmd); |
| 463 | qlcmd = NULL((void *) 0); |
| 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_IRQ1 |
| 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_IRQ1 |
| 482 | if (qlirq >= 0) { |
| 483 | qlogicfas_queuecommand(cmd, qlidone); |
| 484 | while (qlcmd != NULL((void *) 0)); |
| 485 | return cmd->result; |
| 486 | } |
| 487 | #endif |
| 488 | /* non-irq version */ |
| 489 | if (cmd->target == qinitid) |
| 490 | return (DID_BAD_TARGET0x04 << 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_IRQ1 |
| 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_TARGET0x04 << 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((void *) 0)) |
| 512 | barrier()__asm__ __volatile__("": : :"memory"); |
| 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( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd))), ((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc( (0xb4 | 2),(qbase + 0xd)) : __outb((0xb4 | 2),(qbase + 0xd))) ); |
| 558 | if ( ( (inb(qbase + 0xe)((__builtin_constant_p((qbase + 0xe)) && (qbase + 0xe ) < 256) ? __inbc(qbase + 0xe) : __inb(qbase + 0xe)) ^ inb(qbase + 0xe)((__builtin_constant_p((qbase + 0xe)) && (qbase + 0xe ) < 256) ? __inbc(qbase + 0xe) : __inb(qbase + 0xe))) == 7 ) |
| 559 | && ( (inb(qbase + 0xe)((__builtin_constant_p((qbase + 0xe)) && (qbase + 0xe ) < 256) ? __inbc(qbase + 0xe) : __inb(qbase + 0xe)) ^ inb(qbase + 0xe)((__builtin_constant_p((qbase + 0xe)) && (qbase + 0xe ) < 256) ? __inbc(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)((__builtin_constant_p((qbase + 0xe)) && (qbase + 0xe ) < 256) ? __inbc(qbase + 0xe) : __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)((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __outbc((1),(qbase + 8)) : __outb((1),(qbase + 8))); /* set for PIO pseudo DMA */ |
| 573 | REG0( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd))), (( __builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc((4),(qbase + 0xd)) : __outb((4),(qbase + 0xd) ))); |
| 574 | outb(0x40 | qlcfg8 | qinitid, qbase + 8)((__builtin_constant_p((qbase + 8)) && (qbase + 8) < 256) ? __outbc((0x40 | qlcfg8 | qinitid),(qbase + 8)) : __outb ((0x40 | qlcfg8 | qinitid),(qbase + 8))); /* (ini) bus id, disable scsi rst */ |
| 575 | outb(qlcfg5, qbase + 5)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __outbc((qlcfg5),(qbase + 5)) : __outb((qlcfg5),(qbase + 5))); /* select timer */ |
| 576 | outb(qlcfg9, qbase + 9)((__builtin_constant_p((qbase + 9)) && (qbase + 9) < 256) ? __outbc((qlcfg9),(qbase + 9)) : __outb((qlcfg9),(qbase + 9))); /* prescaler */ |
| 577 | #if QL_RESET_AT_START0 |
| 578 | outb( 3 , qbase + 3 )((__builtin_constant_p((qbase + 3)) && (qbase + 3) < 256) ? __outbc((3),(qbase + 3)) : __outb((3),(qbase + 3))); |
| 579 | REG1( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd))), ((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc( (0xb4 | 2),(qbase + 0xd)) : __outb((0xb4 | 2),(qbase + 0xd))) ); |
| 580 | while( inb( qbase + 0xf )((__builtin_constant_p((qbase + 0xf)) && (qbase + 0xf ) < 256) ? __inbc(qbase + 0xf) : __inb(qbase + 0xf)) & 4 ); |
| 581 | REG0( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd))), (( __builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc((4),(qbase + 0xd)) : __outb((4),(qbase + 0xd) ))); |
| 582 | #endif |
| 583 | #if QL_USE_IRQ1 |
| 584 | /* IRQ probe - toggle pin and check request pending */ |
| 585 | |
| 586 | if( qlirq == -1 ) { |
| 587 | save_flags( flags )__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); |
| 588 | cli()__asm__ __volatile__ ("cli": : :"memory"); |
| 589 | i = 0xffff; |
| 590 | j = 3; |
| 591 | outb(0x90, qbase + 3)((__builtin_constant_p((qbase + 3)) && (qbase + 3) < 256) ? __outbc((0x90),(qbase + 3)) : __outb((0x90),(qbase + 3 ))); /* illegal command - cause interrupt */ |
| 592 | REG1( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) | 0x80),(qbase + 0xd))), ((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc( (0xb4 | 2),(qbase + 0xd)) : __outb((0xb4 | 2),(qbase + 0xd))) ); |
| 593 | outb(10, 0x20)((__builtin_constant_p((0x20)) && (0x20) < 256) ? __outbc ((10),(0x20)) : __outb((10),(0x20))); /* access pending interrupt map */ |
| 594 | outb(10, 0xa0)((__builtin_constant_p((0xa0)) && (0xa0) < 256) ? __outbc ((10),(0xa0)) : __outb((10),(0xa0))); |
| 595 | while (j--) { |
| 596 | outb(0xb0 | QL_INT_ACTIVE_HIGH , qbase + 0xd)((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((0xb0 | 2),(qbase + 0xd)) : __outb((0xb0 | 2),(qbase + 0xd))); /* int pin off */ |
| 597 | i &= ~(inb(0x20)((__builtin_constant_p((0x20)) && (0x20) < 256) ? __inbc (0x20) : __inb(0x20)) | (inb(0xa0)((__builtin_constant_p((0xa0)) && (0xa0) < 256) ? __inbc (0xa0) : __inb(0xa0)) << 8)); /* find IRQ off */ |
| 598 | outb(0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd)((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((0xb4 | 2),(qbase + 0xd)) : __outb((0xb4 | 2),(qbase + 0xd))); /* int pin on */ |
| 599 | i &= inb(0x20)((__builtin_constant_p((0x20)) && (0x20) < 256) ? __inbc (0x20) : __inb(0x20)) | (inb(0xa0)((__builtin_constant_p((0xa0)) && (0xa0) < 256) ? __inbc (0xa0) : __inb(0xa0)) << 8); /* find IRQ on */ |
| 600 | } |
| 601 | REG0( ((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd ) < 256) ? __outbc((((__builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd)) : __outb((((__builtin_constant_p ((qbase + 0xd)) && (qbase + 0xd) < 256) ? __inbc(qbase + 0xd) : __inb(qbase + 0xd)) & 0x7f),(qbase + 0xd))), (( __builtin_constant_p((qbase + 0xd)) && (qbase + 0xd) < 256) ? __outbc((4),(qbase + 0xd)) : __outb((4),(qbase + 0xd) ))); |
| 602 | while (inb(qbase + 5)((__builtin_constant_p((qbase + 5)) && (qbase + 5) < 256) ? __inbc(qbase + 5) : __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 )__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); |
| 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((void *) 0))) |
| 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 | sprintflinux_sprintf(qinfo, "Qlogicfas Driver version 0.45, chip %02X at %03X, IRQ %d, TPdma:%d", |
| 624 | qltyp, qbase, qlirq, QL_TURBO_PDMA1 ); |
| 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{ ((void *) 0), ((void *) 0), ((void *) 0), ((void *) 0), ((void *) 0), qlogicfas_detect, ((void *) 0), qlogicfas_info, qlogicfas_command , qlogicfas_queuecommand, qlogicfas_abort, qlogicfas_reset, ( (void *) 0), qlogicfas_biosparam, 0, -1, 0xff, 1, 0, 0, 0 }; |
| 676 | |
| 677 | #include "scsi_module.c" |
| 678 | #endif |
| 679 |