| File: | obj-scan-build/../linux/src/drivers/scsi/aha1740.c |
| Location: | line 200, column 5 |
| Description: | Value stored to 'tmp' is never read |
| 1 | /* $Id: aha1740.c,v 1.1 1999/04/26 05:54:13 tb Exp $ |
| 2 | * 1993/03/31 |
| 3 | * linux/kernel/aha1740.c |
| 4 | * |
| 5 | * Based loosely on aha1542.c which is |
| 6 | * Copyright (C) 1992 Tommy Thorn and |
| 7 | * Modified by Eric Youngdale |
| 8 | * |
| 9 | * This file is aha1740.c, written and |
| 10 | * Copyright (C) 1992,1993 Brad McLean |
| 11 | * |
| 12 | * Modifications to makecode and queuecommand |
| 13 | * for proper handling of multiple devices courteously |
| 14 | * provided by Michael Weller, March, 1993 |
| 15 | * |
| 16 | * Multiple adapter support, extended translation detection, |
| 17 | * update to current scsi subsystem changes, proc fs support, |
| 18 | * working (!) module support based on patches from Andreas Arens, |
| 19 | * by Andreas Degert <ad@papyrus.hamburg.com>, 2/1997 |
| 20 | * |
| 21 | * aha1740_makecode may still need even more work |
| 22 | * if it doesn't work for your devices, take a look. |
| 23 | */ |
| 24 | |
| 25 | #ifdef MODULE |
| 26 | #include <linux/module.h> |
| 27 | #endif |
| 28 | |
| 29 | #include <linux/kernel.h> |
| 30 | #include <linux/head.h> |
| 31 | #include <linux/types.h> |
| 32 | #include <linux/string.h> |
| 33 | #include <linux/ioport.h> |
| 34 | #include <linux/proc_fs.h> |
| 35 | #include <linux/sched.h> |
| 36 | #include <asm/dma.h> |
| 37 | |
| 38 | #include <asm/system.h> |
| 39 | #include <asm/io.h> |
| 40 | #include <linux/blk.h> |
| 41 | #include "scsi.h" |
| 42 | #include "hosts.h" |
| 43 | #include "sd.h" |
| 44 | |
| 45 | #include "aha1740.h" |
| 46 | #include<linux/stat.h> |
| 47 | |
| 48 | struct proc_dir_entry proc_scsi_aha1740 = { |
| 49 | PROC_SCSI_AHA1740, 7, "aha1740", |
| 50 | S_IFDIR0040000 | S_IRUGO(00400|00040|00004) | S_IXUGO(00100|00010|00001), 2 |
| 51 | }; |
| 52 | |
| 53 | /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH |
| 54 | IT WORK, THEN: |
| 55 | #define DEBUG |
| 56 | */ |
| 57 | #ifdef DEBUG |
| 58 | #define DEB(x) x |
| 59 | #else |
| 60 | #define DEB(x) |
| 61 | #endif |
| 62 | |
| 63 | /* |
| 64 | static const char RCSid[] = "$Header: cvs/gnumach/linux/src/drivers/scsi/Attic/aha1740.c,v 1.1 1999/04/26 05:54:13 tb Exp $"; |
| 65 | */ |
| 66 | |
| 67 | struct aha1740_hostdata { |
| 68 | unsigned int slot; |
| 69 | unsigned int translation; |
| 70 | unsigned int last_ecb_used; |
| 71 | struct ecb ecb[AHA1740_ECBS32]; |
| 72 | }; |
| 73 | |
| 74 | #define HOSTDATA(host)((struct aha1740_hostdata *) &host->hostdata) ((struct aha1740_hostdata *) &host->hostdata) |
| 75 | |
| 76 | /* One for each IRQ level (9-15) */ |
| 77 | static struct Scsi_Host * aha_host[8] = {NULL((void *) 0), }; |
| 78 | |
| 79 | int aha1740_proc_info(char *buffer, char **start, off_t offset, |
| 80 | int length, int hostno, int inout) |
| 81 | { |
| 82 | int len; |
| 83 | struct Scsi_Host * shpnt; |
| 84 | struct aha1740_hostdata *host; |
| 85 | |
| 86 | if (inout) |
| 87 | return(-ENOSYS38); |
| 88 | |
| 89 | for (len = 0; len < 8; len++) { |
| 90 | shpnt = aha_host[len]; |
| 91 | if (shpnt && shpnt->host_no == hostno) |
| 92 | break; |
| 93 | } |
| 94 | host = HOSTDATA(shpnt)((struct aha1740_hostdata *) &shpnt->hostdata); |
| 95 | |
| 96 | len = sprintflinux_sprintf(buffer, "aha174x at IO:%x, IRQ %d, SLOT %d.\n" |
| 97 | "Extended translation %sabled.\n", |
| 98 | shpnt->io_port, shpnt->irq, host->slot, |
| 99 | host->translation ? "en" : "dis"); |
| 100 | |
| 101 | if (offset > len) { |
| 102 | *start = buffer; |
| 103 | return 0; |
| 104 | } |
| 105 | |
| 106 | *start = buffer + offset; |
| 107 | len -= offset; |
| 108 | if (len > length) |
| 109 | len = length; |
| 110 | return len; |
| 111 | } |
| 112 | |
| 113 | |
| 114 | int aha1740_makecode(unchar *sense, unchar *status) |
| 115 | { |
| 116 | struct statusword |
| 117 | { |
| 118 | ushort don:1, /* Command Done - No Error */ |
| 119 | du:1, /* Data underrun */ |
| 120 | :1, qf:1, /* Queue full */ |
| 121 | sc:1, /* Specification Check */ |
| 122 | dor:1, /* Data overrun */ |
| 123 | ch:1, /* Chaining Halted */ |
| 124 | intr:1, /* Interrupt issued */ |
| 125 | asa:1, /* Additional Status Available */ |
| 126 | sns:1, /* Sense information Stored */ |
| 127 | :1, ini:1, /* Initialization Required */ |
| 128 | me:1, /* Major error or exception */ |
| 129 | :1, eca:1, /* Extended Contingent alliance */ |
| 130 | :1; |
| 131 | } status_word; |
| 132 | int retval = DID_OK0x00; |
| 133 | |
| 134 | status_word = * (struct statusword *) status; |
| 135 | #ifdef DEBUG |
| 136 | printk("makecode from %x,%x,%x,%x %x,%x,%x,%x", |
| 137 | status[0], status[1], status[2], status[3], |
| 138 | sense[0], sense[1], sense[2], sense[3]); |
| 139 | #endif |
| 140 | if (!status_word.don) /* Anything abnormal was detected */ |
| 141 | { |
| 142 | if ( (status[1]&0x18) || status_word.sc ) /*Additional info available*/ |
| 143 | { |
| 144 | /* Use the supplied info for further diagnostics */ |
| 145 | switch ( status[2] ) |
| 146 | { |
| 147 | case 0x12: |
| 148 | if ( status_word.dor ) |
| 149 | retval=DID_ERROR0x07; /* It's an Overrun */ |
| 150 | /* If not overrun, assume underrun and ignore it! */ |
| 151 | case 0x00: /* No info, assume no error, should not occur */ |
| 152 | break; |
| 153 | case 0x11: |
| 154 | case 0x21: |
| 155 | retval=DID_TIME_OUT0x03; |
| 156 | break; |
| 157 | case 0x0a: |
| 158 | retval=DID_BAD_TARGET0x04; |
| 159 | break; |
| 160 | case 0x04: |
| 161 | case 0x05: |
| 162 | retval=DID_ABORT0x05; |
| 163 | /* Either by this driver or the AHA1740 itself */ |
| 164 | break; |
| 165 | default: |
| 166 | retval=DID_ERROR0x07; /* No further diagnostics possible */ |
| 167 | } |
| 168 | } |
| 169 | else |
| 170 | { /* Michael suggests, and Brad concurs: */ |
| 171 | if ( status_word.qf ) |
| 172 | { |
| 173 | retval = DID_TIME_OUT0x03; /* forces a redo */ |
| 174 | /* I think this specific one should not happen -Brad */ |
| 175 | printk("aha1740.c: WARNING: AHA1740 queue overflow!\n"); |
| 176 | } |
| 177 | else if ( status[0]&0x60 ) |
| 178 | { |
| 179 | retval = DID_ERROR0x07; /* Didn't find a better error */ |
| 180 | } |
| 181 | /* In any other case return DID_OK so for example |
| 182 | CONDITION_CHECKS make it through to the appropriate |
| 183 | device driver */ |
| 184 | } |
| 185 | } |
| 186 | /* Under all circumstances supply the target status -Michael */ |
| 187 | return status[3] | retval << 16; |
| 188 | } |
| 189 | |
| 190 | int aha1740_test_port(unsigned int base) |
| 191 | { |
| 192 | char name[4], tmp; |
| 193 | |
| 194 | /* Okay, look for the EISA ID's */ |
| 195 | name[0]= 'A' -1 + ((tmp = inb(HID0(base))((__builtin_constant_p(((base + 0x0))) && ((base + 0x0 )) < 256) ? __inbc((base + 0x0)) : __inb((base + 0x0)))) >> 2); /* First character */ |
| 196 | name[1]= 'A' -1 + ((tmp & 3) << 3); |
| 197 | name[1]+= ((tmp = inb(HID1(base))((__builtin_constant_p(((base + 0x1))) && ((base + 0x1 )) < 256) ? __inbc((base + 0x1)) : __inb((base + 0x1)))) >> 5)&0x7; /* Second Character */ |
| 198 | name[2]= 'A' -1 + (tmp & 0x1f); /* Third Character */ |
| 199 | name[3]=0; |
| 200 | tmp = inb(HID2(base))((__builtin_constant_p(((base + 0x2))) && ((base + 0x2 )) < 256) ? __inbc((base + 0x2)) : __inb((base + 0x2))); |
Value stored to 'tmp' is never read | |
| 201 | if ( strcmp ( name, HID_MFG"ADP" ) || inb(HID2(base))((__builtin_constant_p(((base + 0x2))) && ((base + 0x2 )) < 256) ? __inbc((base + 0x2)) : __inb((base + 0x2))) != HID_PRD0 ) |
| 202 | return 0; /* Not an Adaptec 174x */ |
| 203 | |
| 204 | /* if ( inb(HID3(base)) != HID_REV ) |
| 205 | printk("aha174x: Warning; board revision of %d; expected %d\n", |
| 206 | inb(HID3(base)),HID_REV); */ |
| 207 | |
| 208 | if ( inb(EBCNTRL(base))((__builtin_constant_p(((base + 0x4))) && ((base + 0x4 )) < 256) ? __inbc((base + 0x4)) : __inb((base + 0x4))) != EBCNTRL_VALUE1 ) |
| 209 | { |
| 210 | printk("aha174x: Board detected, but EBCNTRL = %x, so disabled it.\n", |
| 211 | inb(EBCNTRL(base))((__builtin_constant_p(((base + 0x4))) && ((base + 0x4 )) < 256) ? __inbc((base + 0x4)) : __inb((base + 0x4)))); |
| 212 | return 0; |
| 213 | } |
| 214 | |
| 215 | if ( inb(PORTADR(base))((__builtin_constant_p(((base + 0x40))) && ((base + 0x40 )) < 256) ? __inbc((base + 0x40)) : __inb((base + 0x40))) & PORTADDR_ENH0x80 ) |
| 216 | return 1; /* Okay, we're all set */ |
| 217 | |
| 218 | printk("aha174x: Board detected, but not in enhanced mode, so disabled it.\n"); |
| 219 | return 0; |
| 220 | } |
| 221 | |
| 222 | /* A "high" level interrupt handler */ |
| 223 | void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs) |
| 224 | { |
| 225 | void (*my_done)(Scsi_Cmnd *); |
| 226 | int errstatus, adapstat; |
| 227 | int number_serviced; |
| 228 | struct ecb *ecbptr; |
| 229 | Scsi_Cmnd *SCtmp; |
| 230 | unsigned int base; |
| 231 | |
| 232 | if (!aha_host[irq - 9]) |
| 233 | panic("aha1740.c: Irq from unknown host!\n"); |
| 234 | base = aha_host[irq - 9]->io_port; |
| 235 | number_serviced = 0; |
| 236 | |
| 237 | while(inb(G2STAT(base))((__builtin_constant_p(((base + 0x57))) && ((base + 0x57 )) < 256) ? __inbc((base + 0x57)) : __inb((base + 0x57))) & G2STAT_INTPEND2) |
| 238 | { |
| 239 | DEB(printk("aha1740_intr top of loop.\n")); |
| 240 | adapstat = inb(G2INTST(base))((__builtin_constant_p(((base + 0x56))) && ((base + 0x56 )) < 256) ? __inbc((base + 0x56)) : __inb((base + 0x56))); |
| 241 | ecbptr = (struct ecb *) bus_to_virtphys_to_virt(inl(MBOXIN0(base))((__builtin_constant_p(((base + 0x58))) && ((base + 0x58 )) < 256) ? __inlc((base + 0x58)) : __inl((base + 0x58)))); |
| 242 | outb(G2CNTRL_IRST,G2CNTRL(base))((__builtin_constant_p(((base + 0x55))) && ((base + 0x55 )) < 256) ? __outbc((0x40),((base + 0x55))) : __outb((0x40 ),((base + 0x55)))); /* interrupt reset */ |
| 243 | |
| 244 | switch ( adapstat & G2INTST_MASK0xf0 ) |
| 245 | { |
| 246 | case G2INTST_CCBRETRY0x50: |
| 247 | case G2INTST_CCBERROR0xc0: |
| 248 | case G2INTST_CCBGOOD0x10: |
| 249 | /* Host Ready -> Mailbox in complete */ |
| 250 | outb(G2CNTRL_HRDY,G2CNTRL(base))((__builtin_constant_p(((base + 0x55))) && ((base + 0x55 )) < 256) ? __outbc((0x20),((base + 0x55))) : __outb((0x20 ),((base + 0x55)))); |
| 251 | if (!ecbptr) |
| 252 | { |
| 253 | printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n", |
| 254 | inb(G2STAT(base))((__builtin_constant_p(((base + 0x57))) && ((base + 0x57 )) < 256) ? __inbc((base + 0x57)) : __inb((base + 0x57))),adapstat, |
| 255 | inb(G2INTST(base))((__builtin_constant_p(((base + 0x56))) && ((base + 0x56 )) < 256) ? __inbc((base + 0x56)) : __inb((base + 0x56))), number_serviced++); |
| 256 | continue; |
| 257 | } |
| 258 | SCtmp = ecbptr->SCpnt; |
| 259 | if (!SCtmp) |
| 260 | { |
| 261 | printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n", |
| 262 | inb(G2STAT(base))((__builtin_constant_p(((base + 0x57))) && ((base + 0x57 )) < 256) ? __inbc((base + 0x57)) : __inb((base + 0x57))),adapstat, |
| 263 | inb(G2INTST(base))((__builtin_constant_p(((base + 0x56))) && ((base + 0x56 )) < 256) ? __inbc((base + 0x56)) : __inb((base + 0x56))), number_serviced++); |
| 264 | continue; |
| 265 | } |
| 266 | if (SCtmp->host_scribble) |
| 267 | scsi_free(SCtmp->host_scribble, 512); |
| 268 | /* Fetch the sense data, and tuck it away, in the required slot. |
| 269 | The Adaptec automatically fetches it, and there is no |
| 270 | guarantee that we will still have it in the cdb when we come |
| 271 | back */ |
| 272 | if ( (adapstat & G2INTST_MASK0xf0) == G2INTST_CCBERROR0xc0 ) |
| 273 | { |
| 274 | memcpy(SCtmp->sense_buffer, ecbptr->sense,(__builtin_constant_p(sizeof(SCtmp->sense_buffer)) ? __constant_memcpy ((SCtmp->sense_buffer),(ecbptr->sense),(sizeof(SCtmp-> sense_buffer))) : __memcpy((SCtmp->sense_buffer),(ecbptr-> sense),(sizeof(SCtmp->sense_buffer)))) |
| 275 | sizeof(SCtmp->sense_buffer))(__builtin_constant_p(sizeof(SCtmp->sense_buffer)) ? __constant_memcpy ((SCtmp->sense_buffer),(ecbptr->sense),(sizeof(SCtmp-> sense_buffer))) : __memcpy((SCtmp->sense_buffer),(ecbptr-> sense),(sizeof(SCtmp->sense_buffer)))); |
| 276 | errstatus = aha1740_makecode(ecbptr->sense,ecbptr->status); |
| 277 | } |
| 278 | else |
| 279 | errstatus = 0; |
| 280 | DEB(if (errstatus) printk("aha1740_intr_handle: returning %6x\n", |
| 281 | errstatus)); |
| 282 | SCtmp->result = errstatus; |
| 283 | my_done = ecbptr->done; |
| 284 | memset(ecbptr,0,sizeof(struct ecb))(__builtin_constant_p(0) ? (__builtin_constant_p((sizeof(struct ecb))) ? __constant_c_and_count_memset(((ecbptr)),((0x01010101UL *(unsigned char)(0))),((sizeof(struct ecb)))) : __constant_c_memset (((ecbptr)),((0x01010101UL*(unsigned char)(0))),((sizeof(struct ecb))))) : (__builtin_constant_p((sizeof(struct ecb))) ? __memset_generic ((((ecbptr))),(((0))),(((sizeof(struct ecb))))) : __memset_generic (((ecbptr)),((0)),((sizeof(struct ecb)))))); |
| 285 | if ( my_done ) |
| 286 | my_done(SCtmp); |
| 287 | break; |
| 288 | case G2INTST_HARDFAIL0x70: |
| 289 | printk(KERN_ALERT"<1>" "aha1740 hardware failure!\n"); |
| 290 | panic("aha1740.c"); /* Goodbye */ |
| 291 | case G2INTST_ASNEVENT0xd0: |
| 292 | printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n", |
| 293 | adapstat, inb(MBOXIN0(base))((__builtin_constant_p(((base + 0x58))) && ((base + 0x58 )) < 256) ? __inbc((base + 0x58)) : __inb((base + 0x58))), inb(MBOXIN1(base))((__builtin_constant_p(((base + 0x59))) && ((base + 0x59 )) < 256) ? __inbc((base + 0x59)) : __inb((base + 0x59))), |
| 294 | inb(MBOXIN2(base))((__builtin_constant_p(((base + 0x5a))) && ((base + 0x5a )) < 256) ? __inbc((base + 0x5a)) : __inb((base + 0x5a))), inb(MBOXIN3(base))((__builtin_constant_p(((base + 0x5b))) && ((base + 0x5b )) < 256) ? __inbc((base + 0x5b)) : __inb((base + 0x5b)))); /* Say What? */ |
| 295 | /* Host Ready -> Mailbox in complete */ |
| 296 | outb(G2CNTRL_HRDY,G2CNTRL(base))((__builtin_constant_p(((base + 0x55))) && ((base + 0x55 )) < 256) ? __outbc((0x20),((base + 0x55))) : __outb((0x20 ),((base + 0x55)))); |
| 297 | break; |
| 298 | case G2INTST_CMDGOOD0xa0: |
| 299 | /* set immediate command success flag here: */ |
| 300 | break; |
| 301 | case G2INTST_CMDERROR0xe0: |
| 302 | /* Set immediate command failure flag here: */ |
| 303 | break; |
| 304 | } |
| 305 | number_serviced++; |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) |
| 310 | { |
| 311 | unchar direction; |
| 312 | unchar *cmd = (unchar *) SCpnt->cmnd; |
| 313 | unchar target = SCpnt->target; |
| 314 | struct aha1740_hostdata *host = HOSTDATA(SCpnt->host)((struct aha1740_hostdata *) &SCpnt->host->hostdata ); |
| 315 | unsigned long flags; |
| 316 | void *buff = SCpnt->request_buffer; |
| 317 | int bufflen = SCpnt->request_bufflen; |
| 318 | int ecbno; |
| 319 | DEB(int i); |
| 320 | |
| 321 | if(*cmd == REQUEST_SENSE0x03) |
| 322 | { |
| 323 | if (bufflen != sizeof(SCpnt->sense_buffer)) |
| 324 | { |
| 325 | printk("Wrong buffer length supplied for request sense (%d)\n", |
| 326 | bufflen); |
| 327 | } |
| 328 | SCpnt->result = 0; |
| 329 | done(SCpnt); |
| 330 | return 0; |
| 331 | } |
| 332 | |
| 333 | #ifdef DEBUG |
| 334 | if (*cmd == READ_100x28 || *cmd == WRITE_100x2a) |
| 335 | i = xscsi2int(cmd+2)( (((long)(cmd+2)[0]) << 24) + (((long)(cmd+2)[1]) << 16) + (((long)(cmd+2)[2]) << 8) + ((long)(cmd+2)[3]) ); |
| 336 | else if (*cmd == READ_60x08 || *cmd == WRITE_60x0a) |
| 337 | i = scsi2int(cmd+2)( (((long)*(cmd+2)) << 16) + (((long)(cmd+2)[1]) << 8) + ((long)(cmd+2)[2]) ); |
| 338 | else |
| 339 | i = -1; |
| 340 | printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ", |
| 341 | target, *cmd, i, bufflen); |
| 342 | printk("scsi cmd:"); |
| 343 | for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]); |
| 344 | printk("\n"); |
| 345 | #endif |
| 346 | |
| 347 | /* locate an available ecb */ |
| 348 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); |
| 349 | cli()__asm__ __volatile__ ("cli": : :"memory"); |
| 350 | ecbno = host->last_ecb_used + 1; /* An optimization */ |
| 351 | if (ecbno >= AHA1740_ECBS32) |
| 352 | ecbno = 0; |
| 353 | do { |
| 354 | if (!host->ecb[ecbno].cmdw) |
| 355 | break; |
| 356 | ecbno++; |
| 357 | if (ecbno >= AHA1740_ECBS32) |
| 358 | ecbno = 0; |
| 359 | } while (ecbno != host->last_ecb_used); |
| 360 | |
| 361 | if (host->ecb[ecbno].cmdw) |
| 362 | panic("Unable to find empty ecb for aha1740.\n"); |
| 363 | |
| 364 | host->ecb[ecbno].cmdw = AHA1740CMD_INIT0x01; /* SCSI Initiator Command |
| 365 | doubles as reserved flag */ |
| 366 | |
| 367 | host->last_ecb_used = ecbno; |
| 368 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); |
| 369 | |
| 370 | #ifdef DEBUG |
| 371 | printk("Sending command (%d %x)...", ecbno, done); |
| 372 | #endif |
| 373 | |
| 374 | host->ecb[ecbno].cdblen = SCpnt->cmd_len; /* SCSI Command Descriptor Block Length */ |
| 375 | |
| 376 | direction = 0; |
| 377 | if (*cmd == READ_100x28 || *cmd == READ_60x08) |
| 378 | direction = 1; |
| 379 | else if (*cmd == WRITE_100x2a || *cmd == WRITE_60x0a) |
| 380 | direction = 0; |
| 381 | |
| 382 | memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len)(__builtin_constant_p(SCpnt->cmd_len) ? __constant_memcpy( (host->ecb[ecbno].cdb),(cmd),(SCpnt->cmd_len)) : __memcpy ((host->ecb[ecbno].cdb),(cmd),(SCpnt->cmd_len))); |
| 383 | |
| 384 | if (SCpnt->use_sg) |
| 385 | { |
| 386 | struct scatterlist * sgpnt; |
| 387 | struct aha1740_chain * cptr; |
| 388 | int i; |
| 389 | DEB(unsigned char * ptr); |
| 390 | |
| 391 | host->ecb[ecbno].sg = 1; /* SCSI Initiator Command w/scatter-gather*/ |
| 392 | SCpnt->host_scribble = (unsigned char *) scsi_malloc(512); |
| 393 | sgpnt = (struct scatterlist *) SCpnt->request_buffer; |
| 394 | cptr = (struct aha1740_chain *) SCpnt->host_scribble; |
| 395 | if (cptr == NULL((void *) 0)) panic("aha1740.c: unable to allocate DMA memory\n"); |
| 396 | for(i=0; i<SCpnt->use_sg; i++) |
| 397 | { |
| 398 | cptr[i].datalen = sgpnt[i].length; |
| 399 | cptr[i].dataptr = virt_to_busvirt_to_phys(sgpnt[i].address); |
| 400 | } |
| 401 | host->ecb[ecbno].datalen = SCpnt->use_sg * sizeof(struct aha1740_chain); |
| 402 | host->ecb[ecbno].dataptr = virt_to_busvirt_to_phys(cptr); |
| 403 | #ifdef DEBUG |
| 404 | printk("cptr %x: ",cptr); |
| 405 | ptr = (unsigned char *) cptr; |
| 406 | for(i=0;i<24;i++) printk("%02x ", ptr[i]); |
| 407 | #endif |
| 408 | } |
| 409 | else |
| 410 | { |
| 411 | SCpnt->host_scribble = NULL((void *) 0); |
| 412 | host->ecb[ecbno].datalen = bufflen; |
| 413 | host->ecb[ecbno].dataptr = virt_to_busvirt_to_phys(buff); |
| 414 | } |
| 415 | host->ecb[ecbno].lun = SCpnt->lun; |
| 416 | host->ecb[ecbno].ses = 1; /* Suppress underrun errors */ |
| 417 | host->ecb[ecbno].dir = direction; |
| 418 | host->ecb[ecbno].ars = 1; /* Yes, get the sense on an error */ |
| 419 | host->ecb[ecbno].senselen = 12; |
| 420 | host->ecb[ecbno].senseptr = virt_to_busvirt_to_phys(host->ecb[ecbno].sense); |
| 421 | host->ecb[ecbno].statusptr = virt_to_busvirt_to_phys(host->ecb[ecbno].status); |
| 422 | host->ecb[ecbno].done = done; |
| 423 | host->ecb[ecbno].SCpnt = SCpnt; |
| 424 | #ifdef DEBUG |
| 425 | { |
| 426 | int i; |
| 427 | printk("aha1740_command: sending.. "); |
| 428 | for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++) |
| 429 | printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]); |
| 430 | } |
| 431 | printk("\n"); |
| 432 | #endif |
| 433 | if (done) |
| 434 | { /* The Adaptec Spec says the card is so fast that the loops will |
| 435 | only be executed once in the code below. Even if this was true |
| 436 | with the fastest processors when the spec was written, it doesn't |
| 437 | seem to be true with todays fast processors. We print a warning |
| 438 | if the code is executed more often than LOOPCNT_WARN. If this |
| 439 | happens, it should be investigated. If the count reaches |
| 440 | LOOPCNT_MAX, we assume something is broken; since there is no |
| 441 | way to return an error (the return value is ignored by the |
| 442 | mid-level scsi layer) we have to panic (and maybe that's the |
| 443 | best thing we can do then anyhow). */ |
| 444 | |
| 445 | #define LOOPCNT_WARN10 10 /* excessive mbxout wait -> syslog-msg */ |
| 446 | #define LOOPCNT_MAX1000000 1000000 /* mbxout deadlock -> panic() after ~ 2 sec. */ |
| 447 | int loopcnt; |
| 448 | unsigned int base = SCpnt->host->io_port; |
| 449 | DEB(printk("aha1740[%d] critical section\n",ecbno)); |
| 450 | save_flags(flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (flags): :"memory" ); |
| 451 | cli()__asm__ __volatile__ ("cli": : :"memory"); |
| 452 | for (loopcnt = 0; ; loopcnt++) { |
| 453 | if (inb(G2STAT(base))((__builtin_constant_p(((base + 0x57))) && ((base + 0x57 )) < 256) ? __inbc((base + 0x57)) : __inb((base + 0x57))) & G2STAT_MBXOUT4) break; |
| 454 | if (loopcnt == LOOPCNT_WARN10) { |
| 455 | printk("aha1740[%d]_mbxout wait!\n",ecbno); |
| 456 | cli()__asm__ __volatile__ ("cli": : :"memory"); /* printk may have done a sti()! */ |
| 457 | } |
| 458 | if (loopcnt == LOOPCNT_MAX1000000) |
| 459 | panic("aha1740.c: mbxout busy!\n"); |
| 460 | } |
| 461 | outl(virt_to_bus(host->ecb + ecbno), MBOXOUT0(base))((__builtin_constant_p(((base + 0x50))) && ((base + 0x50 )) < 256) ? __outlc((virt_to_phys(host->ecb + ecbno)),( (base + 0x50))) : __outl((virt_to_phys(host->ecb + ecbno)) ,((base + 0x50)))); |
| 462 | for (loopcnt = 0; ; loopcnt++) { |
| 463 | if (! (inb(G2STAT(base))((__builtin_constant_p(((base + 0x57))) && ((base + 0x57 )) < 256) ? __inbc((base + 0x57)) : __inb((base + 0x57))) & G2STAT_BUSY1)) break; |
| 464 | if (loopcnt == LOOPCNT_WARN10) { |
| 465 | printk("aha1740[%d]_attn wait!\n",ecbno); |
| 466 | cli()__asm__ __volatile__ ("cli": : :"memory"); |
| 467 | } |
| 468 | if (loopcnt == LOOPCNT_MAX1000000) |
| 469 | panic("aha1740.c: attn wait failed!\n"); |
| 470 | } |
| 471 | outb(ATTN_START | (target & 7), ATTN(base))((__builtin_constant_p(((base + 0x54))) && ((base + 0x54 )) < 256) ? __outbc((0x40 | (target & 7)),((base + 0x54 ))) : __outb((0x40 | (target & 7)),((base + 0x54)))); /* Start it up */ |
| 472 | restore_flags(flags)__asm__ __volatile__("push %0 ; popf": :"g" (flags):"memory"); |
| 473 | DEB(printk("aha1740[%d] request queued.\n",ecbno)); |
| 474 | } |
| 475 | else |
| 476 | printk(KERN_ALERT"<1>" "aha1740_queuecommand: done can't be NULL\n"); |
| 477 | return 0; |
| 478 | } |
| 479 | |
| 480 | static void internal_done(Scsi_Cmnd * SCpnt) |
| 481 | { |
| 482 | SCpnt->SCp.Status++; |
| 483 | } |
| 484 | |
| 485 | int aha1740_command(Scsi_Cmnd * SCpnt) |
| 486 | { |
| 487 | aha1740_queuecommand(SCpnt, internal_done); |
| 488 | SCpnt->SCp.Status = 0; |
| 489 | while (!SCpnt->SCp.Status) |
| 490 | barrier()__asm__ __volatile__("": : :"memory"); |
| 491 | return SCpnt->result; |
| 492 | } |
| 493 | |
| 494 | /* Query the board for its irq_level. Nothing else matters |
| 495 | in enhanced mode on an EISA bus. */ |
| 496 | |
| 497 | void aha1740_getconfig(unsigned int base, unsigned int *irq_level, |
| 498 | unsigned int *translation) |
| 499 | { |
| 500 | static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 }; |
| 501 | |
| 502 | *irq_level = intab[inb(INTDEF(base))((__builtin_constant_p(((base + 0x42))) && ((base + 0x42 )) < 256) ? __inbc((base + 0x42)) : __inb((base + 0x42))) & 0x7]; |
| 503 | *translation = inb(RESV1(base))((__builtin_constant_p(((base + 0x46))) && ((base + 0x46 )) < 256) ? __inbc((base + 0x46)) : __inb((base + 0x46))) & 0x1; |
| 504 | outb(inb(INTDEF(base)) | 0x10, INTDEF(base))((__builtin_constant_p(((base + 0x42))) && ((base + 0x42 )) < 256) ? __outbc((((__builtin_constant_p(((base + 0x42) )) && ((base + 0x42)) < 256) ? __inbc((base + 0x42 )) : __inb((base + 0x42))) | 0x10),((base + 0x42))) : __outb( (((__builtin_constant_p(((base + 0x42))) && ((base + 0x42 )) < 256) ? __inbc((base + 0x42)) : __inb((base + 0x42))) | 0x10),((base + 0x42)))); |
| 505 | } |
| 506 | |
| 507 | int aha1740_detect(Scsi_Host_Template * tpnt) |
| 508 | { |
| 509 | int count = 0, slot; |
| 510 | |
| 511 | DEB(printk("aha1740_detect: \n")); |
| 512 | |
| 513 | for ( slot=MINEISA1; slot <= MAXEISA8; slot++ ) |
| 514 | { |
| 515 | int slotbase; |
| 516 | unsigned int irq_level, translation; |
| 517 | struct Scsi_Host *shpnt; |
| 518 | struct aha1740_hostdata *host; |
| 519 | slotbase = SLOTBASE(slot)((slot << 12) + 0xc80); |
| 520 | /* |
| 521 | * The ioports for eisa boards are generally beyond that used in the |
| 522 | * check/allocate region code, but this may change at some point, |
| 523 | * so we go through the motions. |
| 524 | */ |
| 525 | if (check_region(slotbase, SLOTSIZE0x5c)) /* See if in use */ |
| 526 | continue; |
| 527 | if (!aha1740_test_port(slotbase)) |
| 528 | continue; |
| 529 | aha1740_getconfig(slotbase,&irq_level,&translation); |
| 530 | if ((inb(G2STAT(slotbase))((__builtin_constant_p(((slotbase + 0x57))) && ((slotbase + 0x57)) < 256) ? __inbc((slotbase + 0x57)) : __inb((slotbase + 0x57))) & |
| 531 | (G2STAT_MBXOUT4|G2STAT_BUSY1)) != G2STAT_MBXOUT4) |
| 532 | { /* If the card isn't ready, hard reset it */ |
| 533 | outb(G2CNTRL_HRST, G2CNTRL(slotbase))((__builtin_constant_p(((slotbase + 0x55))) && ((slotbase + 0x55)) < 256) ? __outbc((0x80),((slotbase + 0x55))) : __outb ((0x80),((slotbase + 0x55)))); |
| 534 | outb(0, G2CNTRL(slotbase))((__builtin_constant_p(((slotbase + 0x55))) && ((slotbase + 0x55)) < 256) ? __outbc((0),((slotbase + 0x55))) : __outb ((0),((slotbase + 0x55)))); |
| 535 | } |
| 536 | printk("Configuring aha174x at IO:%x, IRQ %d\n", slotbase, irq_level); |
| 537 | printk("aha174x: Extended translation %sabled.\n", |
| 538 | translation ? "en" : "dis"); |
| 539 | DEB(printk("aha1740_detect: enable interrupt channel %d\n",irq_level)); |
| 540 | if (request_irq(irq_level,aha1740_intr_handle,0,"aha1740",NULL((void *) 0))) { |
| 541 | printk("Unable to allocate IRQ for adaptec controller.\n"); |
| 542 | continue; |
| 543 | } |
| 544 | shpnt = scsi_register(tpnt, sizeof(struct aha1740_hostdata)); |
| 545 | request_region(slotbase, SLOTSIZE0x5c, "aha1740"); |
| 546 | shpnt->base = 0; |
| 547 | shpnt->io_port = slotbase; |
| 548 | shpnt->n_io_port = SLOTSIZE0x5c; |
| 549 | shpnt->irq = irq_level; |
| 550 | shpnt->dma_channel = 0xff; |
| 551 | host = HOSTDATA(shpnt)((struct aha1740_hostdata *) &shpnt->hostdata); |
| 552 | host->slot = slot; |
| 553 | host->translation = translation; |
| 554 | aha_host[irq_level - 9] = shpnt; |
| 555 | count++; |
| 556 | } |
| 557 | return count; |
| 558 | } |
| 559 | |
| 560 | /* Note: They following two functions do not apply very well to the Adaptec, |
| 561 | which basically manages its own affairs quite well without our interference, |
| 562 | so I haven't put anything into them. I can faintly imagine someone with a |
| 563 | *very* badly behaved SCSI target (perhaps an old tape?) wanting the abort(), |
| 564 | but it hasn't happened yet, and doing aborts brings the Adaptec to its |
| 565 | knees. I cannot (at this moment in time) think of any reason to reset the |
| 566 | card once it's running. So there. */ |
| 567 | |
| 568 | int aha1740_abort(Scsi_Cmnd * SCpnt) |
| 569 | { |
| 570 | DEB(printk("aha1740_abort called\n")); |
| 571 | return SCSI_ABORT_SNOOZE0; |
| 572 | } |
| 573 | |
| 574 | /* We do not implement a reset function here, but the upper level code assumes |
| 575 | that it will get some kind of response for the command in SCpnt. We must |
| 576 | oblige, or the command will hang the scsi system */ |
| 577 | |
| 578 | int aha1740_reset(Scsi_Cmnd * SCpnt, unsigned int ignored) |
| 579 | { |
| 580 | DEB(printk("aha1740_reset called\n")); |
| 581 | return SCSI_RESET_PUNT1; |
| 582 | } |
| 583 | |
| 584 | int aha1740_biosparam(Disk * disk, kdev_t dev, int* ip) |
| 585 | { |
| 586 | int size = disk->capacity; |
| 587 | int extended = HOSTDATA(disk->device->host)((struct aha1740_hostdata *) &disk->device->host-> hostdata)->translation; |
| 588 | |
| 589 | DEB(printk("aha1740_biosparam\n")); |
| 590 | if (extended && (ip[2] > 1024)) |
| 591 | { |
| 592 | ip[0] = 255; |
| 593 | ip[1] = 63; |
| 594 | ip[2] = size / (255 * 63); |
| 595 | } |
| 596 | else |
| 597 | { |
| 598 | ip[0] = 64; |
| 599 | ip[1] = 32; |
| 600 | ip[2] = size >> 11; |
| 601 | } |
| 602 | return 0; |
| 603 | } |
| 604 | |
| 605 | #ifdef MODULE |
| 606 | /* Eventually this will go into an include file, but this will be later */ |
| 607 | Scsi_Host_Template driver_template = AHA1740{((void *) 0), ((void *) 0), &proc_scsi_aha1740, aha1740_proc_info , "Adaptec 174x (EISA)", aha1740_detect, ((void *) 0), ((void *) 0), aha1740_command, aha1740_queuecommand, aha1740_abort, aha1740_reset, ((void *) 0), aha1740_biosparam, 32, 7, 16, 1 , 0, 0, 1}; |
| 608 | |
| 609 | #include "scsi_module.c" |
| 610 | #endif |
| 611 | |
| 612 | /* Okay, you made it all the way through. As of this writing, 3/31/93, I'm |
| 613 | brad@saturn.gaylord.com or brad@bradpc.gaylord.com. I'll try to help as time |
| 614 | permits if you have any trouble with this driver. Happy Linuxing! */ |