|
|
1.1 ! root 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 <[email protected]>, 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_IFDIR | S_IRUGO | S_IXUGO, 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: /afs/sipb.mit.edu/project/hurddev/cvsroot/gnumach/linux/src/drivers/scsi/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_ECBS]; ! 72: }; ! 73: ! 74: #define HOSTDATA(host) ((struct aha1740_hostdata *) &host->hostdata) ! 75: ! 76: /* One for each IRQ level (9-15) */ ! 77: static struct Scsi_Host * aha_host[8] = {NULL, }; ! 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(-ENOSYS); ! 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); ! 95: ! 96: len = 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_OK; ! 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_ERROR; /* 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_OUT; ! 156: break; ! 157: case 0x0a: ! 158: retval=DID_BAD_TARGET; ! 159: break; ! 160: case 0x04: ! 161: case 0x05: ! 162: retval=DID_ABORT; ! 163: /* Either by this driver or the AHA1740 itself */ ! 164: break; ! 165: default: ! 166: retval=DID_ERROR; /* No further diagnostics possible */ ! 167: } ! 168: } ! 169: else ! 170: { /* Michael suggests, and Brad concurs: */ ! 171: if ( status_word.qf ) ! 172: { ! 173: retval = DID_TIME_OUT; /* 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_ERROR; /* 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))) >> 2); /* First character */ ! 196: name[1]= 'A' -1 + ((tmp & 3) << 3); ! 197: name[1]+= ((tmp = inb(HID1(base))) >> 5)&0x7; /* Second Character */ ! 198: name[2]= 'A' -1 + (tmp & 0x1f); /* Third Character */ ! 199: name[3]=0; ! 200: tmp = inb(HID2(base)); ! 201: if ( strcmp ( name, HID_MFG ) || inb(HID2(base)) != HID_PRD ) ! 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)) != EBCNTRL_VALUE ) ! 209: { ! 210: printk("aha174x: Board detected, but EBCNTRL = %x, so disabled it.\n", ! 211: inb(EBCNTRL(base))); ! 212: return 0; ! 213: } ! 214: ! 215: if ( inb(PORTADR(base)) & PORTADDR_ENH ) ! 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)) & G2STAT_INTPEND) ! 238: { ! 239: DEB(printk("aha1740_intr top of loop.\n")); ! 240: adapstat = inb(G2INTST(base)); ! 241: ecbptr = (struct ecb *) bus_to_virt(inl(MBOXIN0(base))); ! 242: outb(G2CNTRL_IRST,G2CNTRL(base)); /* interrupt reset */ ! 243: ! 244: switch ( adapstat & G2INTST_MASK ) ! 245: { ! 246: case G2INTST_CCBRETRY: ! 247: case G2INTST_CCBERROR: ! 248: case G2INTST_CCBGOOD: ! 249: /* Host Ready -> Mailbox in complete */ ! 250: outb(G2CNTRL_HRDY,G2CNTRL(base)); ! 251: if (!ecbptr) ! 252: { ! 253: printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n", ! 254: inb(G2STAT(base)),adapstat, ! 255: inb(G2INTST(base)), 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)),adapstat, ! 263: inb(G2INTST(base)), 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_MASK) == G2INTST_CCBERROR ) ! 273: { ! 274: memcpy(SCtmp->sense_buffer, ecbptr->sense, ! 275: 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)); ! 285: if ( my_done ) ! 286: my_done(SCtmp); ! 287: break; ! 288: case G2INTST_HARDFAIL: ! 289: printk(KERN_ALERT "aha1740 hardware failure!\n"); ! 290: panic("aha1740.c"); /* Goodbye */ ! 291: case G2INTST_ASNEVENT: ! 292: printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n", ! 293: adapstat, inb(MBOXIN0(base)), inb(MBOXIN1(base)), ! 294: inb(MBOXIN2(base)), inb(MBOXIN3(base))); /* Say What? */ ! 295: /* Host Ready -> Mailbox in complete */ ! 296: outb(G2CNTRL_HRDY,G2CNTRL(base)); ! 297: break; ! 298: case G2INTST_CMDGOOD: ! 299: /* set immediate command success flag here: */ ! 300: break; ! 301: case G2INTST_CMDERROR: ! 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); ! 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_SENSE) ! 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_10 || *cmd == WRITE_10) ! 335: i = xscsi2int(cmd+2); ! 336: else if (*cmd == READ_6 || *cmd == WRITE_6) ! 337: i = scsi2int(cmd+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); ! 349: cli(); ! 350: ecbno = host->last_ecb_used + 1; /* An optimization */ ! 351: if (ecbno >= AHA1740_ECBS) ! 352: ecbno = 0; ! 353: do { ! 354: if (!host->ecb[ecbno].cmdw) ! 355: break; ! 356: ecbno++; ! 357: if (ecbno >= AHA1740_ECBS) ! 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_INIT; /* SCSI Initiator Command ! 365: doubles as reserved flag */ ! 366: ! 367: host->last_ecb_used = ecbno; ! 368: restore_flags(flags); ! 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_10 || *cmd == READ_6) ! 378: direction = 1; ! 379: else if (*cmd == WRITE_10 || *cmd == WRITE_6) ! 380: direction = 0; ! 381: ! 382: 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) 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_bus(sgpnt[i].address); ! 400: } ! 401: host->ecb[ecbno].datalen = SCpnt->use_sg * sizeof(struct aha1740_chain); ! 402: host->ecb[ecbno].dataptr = virt_to_bus(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; ! 412: host->ecb[ecbno].datalen = bufflen; ! 413: host->ecb[ecbno].dataptr = virt_to_bus(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_bus(host->ecb[ecbno].sense); ! 421: host->ecb[ecbno].statusptr = virt_to_bus(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_WARN 10 /* excessive mbxout wait -> syslog-msg */ ! 446: #define LOOPCNT_MAX 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); ! 451: cli(); ! 452: for (loopcnt = 0; ; loopcnt++) { ! 453: if (inb(G2STAT(base)) & G2STAT_MBXOUT) break; ! 454: if (loopcnt == LOOPCNT_WARN) { ! 455: printk("aha1740[%d]_mbxout wait!\n",ecbno); ! 456: cli(); /* printk may have done a sti()! */ ! 457: } ! 458: if (loopcnt == LOOPCNT_MAX) ! 459: panic("aha1740.c: mbxout busy!\n"); ! 460: } ! 461: outl(virt_to_bus(host->ecb + ecbno), MBOXOUT0(base)); ! 462: for (loopcnt = 0; ; loopcnt++) { ! 463: if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break; ! 464: if (loopcnt == LOOPCNT_WARN) { ! 465: printk("aha1740[%d]_attn wait!\n",ecbno); ! 466: cli(); ! 467: } ! 468: if (loopcnt == LOOPCNT_MAX) ! 469: panic("aha1740.c: attn wait failed!\n"); ! 470: } ! 471: outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */ ! 472: restore_flags(flags); ! 473: DEB(printk("aha1740[%d] request queued.\n",ecbno)); ! 474: } ! 475: else ! 476: printk(KERN_ALERT "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(); ! 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)) & 0x7]; ! 503: *translation = inb(RESV1(base)) & 0x1; ! 504: outb(inb(INTDEF(base)) | 0x10, INTDEF(base)); ! 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=MINEISA; slot <= MAXEISA; 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); ! 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, SLOTSIZE)) /* 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)) & ! 531: (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) ! 532: { /* If the card isn't ready, hard reset it */ ! 533: outb(G2CNTRL_HRST, G2CNTRL(slotbase)); ! 534: outb(0, G2CNTRL(slotbase)); ! 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)) { ! 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, SLOTSIZE, "aha1740"); ! 546: shpnt->base = 0; ! 547: shpnt->io_port = slotbase; ! 548: shpnt->n_io_port = SLOTSIZE; ! 549: shpnt->irq = irq_level; ! 550: shpnt->dma_channel = 0xff; ! 551: host = HOSTDATA(shpnt); ! 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_SNOOZE; ! 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_PUNT; ! 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)->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; ! 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: [email protected] or [email protected]. I'll try to help as time ! 614: permits if you have any trouble with this driver. Happy Linuxing! */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.