root/kernel/blk_drv/scsi/aha1542.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. aha1542_stat
  2. aha1542_out
  3. aha1542_in
  4. makecode
  5. aha1542_test_port
  6. aha1542_info
  7. aha1542_intr_handle
  8. aha1542_queuecommand
  9. internal_done
  10. aha1542_command
  11. setup_mailboxes
  12. aha1542_getconfig
  13. aha1542_query
  14. aha1542_detect
  15. aha1542_abort
  16. aha1542_reset
  17. aha1542_biosparam

   1 /* $Id: aha1542.c,v 1.1 1992/07/24 06:27:38 root Exp root $
   2  *  linux/kernel/aha1542.c
   3  *
   4  *  Copyright (C) 1992  Tommy Thorn
   5  *
   6  *  Modified by Eric Youngdale
   7  *        Use request_irq and request_dma to help prevent unexpected conflicts
   8  *        Set up on-board DMA controller, such that we do not have to
   9  *        have the bios enabled to use the aha1542.
  10  */
  11 
  12 #include <linux/kernel.h>
  13 #include <linux/head.h>
  14 #include <linux/types.h>
  15 #include <linux/string.h>
  16 
  17 #include <linux/sched.h>
  18 #include <asm/dma.h>
  19 
  20 #include <asm/system.h>
  21 #include <asm/io.h>
  22 #include "../blk.h"
  23 #include "scsi.h"
  24 #include "hosts.h"
  25 
  26 #include "aha1542.h"
  27 
  28 #ifdef DEBUG
  29 #define DEB(x) x
  30 #else
  31 #define DEB(x)
  32 #endif
  33 /*
  34 static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha1542.c,v 1.1 1992/07/24 06:27:38 root Exp root $";
  35 */
  36 
  37 /* The adaptec can be configured for quite a number of addresses, but
  38 I generally do not want the card poking around at random.  We allow
  39 two addresses - this allows people to use the Adaptec with a Midi
  40 card, which also used 0x330 */
  41 
  42 static unsigned int bases[]={0x330, 0x334};
  43 
  44 static unsigned int base;
  45 static unsigned char dma_chan;
  46 static unsigned char irq_level;
  47 
  48 static int aha_disable = 0;
  49 
  50 /* The DMA-Controller.  We need to fool with this because we want to 
  51    be able to use the aha1542 without having to have the bios enabled */
  52 #define DMA_MODE_REG    0xd6
  53 #define DMA_MASK_REG    0xd4
  54 #define CASCADE         0xc0
  55 
  56 static struct mailbox mb[2*AHA1542_MAILBOXES];
  57 static struct ccb ccb[AHA1542_MAILBOXES];
  58 
  59 static Scsi_Cmnd * SCint[AHA1542_MAILBOXES] = {NULL, };
  60 
  61 /* This will effectively start both of them at the first mailbox */
  62 static int aha1542_last_mbi_used  = (2*AHA1542_MAILBOXES - 1);
  63 static int aha1542_last_mbo_used  = (AHA1542_MAILBOXES - 1);
  64 
  65 
  66 static long WAITnexttimeout = 3000000;
  67 
  68 static int aha1542_host = 0;
  69 extern void aha1542_interrupt();
  70 
  71 #define aha1542_intr_reset()  outb(IRST, CONTROL)
  72 
  73 #define WAIT(port, mask, allof, noneof)                                 \
  74  { register WAITbits;                                                   \
  75    register WAITtimeout = WAITnexttimeout;                              \
  76    while (1) {                                                          \
  77      WAITbits = inb(port) & (mask);                                     \
  78      if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \
  79        break;                                                           \
  80      if (--WAITtimeout == 0) goto fail;                                 \
  81    }                                                                    \
  82  }
  83 
  84 static void aha1542_stat(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86 /*    int s = inb(STATUS), i = inb(INTRFLAGS);
  87   printk("status=%x intrflags=%x\n", s, i, WAITnexttimeout-WAITtimeout); */
  88 }
  89 
  90 static int aha1542_out(unchar *cmdp, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92     while (len--)
  93       {
  94           WAIT(STATUS, CDF, 0, CDF);
  95           outb(*cmdp++, DATA);
  96       }
  97     return 0;
  98   fail:
  99     printk("aha1542_out failed(%d): ", len+1); aha1542_stat();
 100     return 1;
 101 }
 102 
 103 static int aha1542_in(unchar *cmdp, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105     while (len--)
 106       {
 107           WAIT(STATUS, DF, DF, 0);
 108           *cmdp++ = inb(DATA);
 109       }
 110     return 0;
 111   fail:
 112     printk("aha1542_in failed(%d): ", len+1); aha1542_stat();
 113     return 1;
 114 }
 115 int makecode(unsigned hosterr, unsigned scsierr)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117     switch (hosterr) {
 118       case 0x0:
 119       case 0xa: /* Linked command complete without error and linked normally */
 120       case 0xb: /* Linked command complete without error, interrupt generated */
 121         hosterr = 0;
 122         break;
 123 
 124       case 0x11: /* Selection time out-The initiator selection or target
 125                     reselection was not complete within the SCSI Time out period */
 126         hosterr = DID_TIME_OUT;
 127         break;
 128 
 129       case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
 130                     thean was allocated by the Data Length field or the sum of the
 131                     Scatter / Gather Data Length fields. */
 132 
 133       case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
 134 
 135       case 0x15: /* MBO command was not 00, 01 or 02-The first byte of the CB was
 136                     invalid. This usually indicates a software failure. */
 137 
 138       case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid.
 139                     This usually indicates a software failure. */
 140 
 141       case 0x17: /* Linked CCB does not have the same LUN-A subsequent CCB of a set
 142                     of linked CCB's does not specify the same logical unit number as
 143                     the first. */
 144       case 0x18: /* Invalid Target Direction received from Host-The direction of a
 145                     Target Mode CCB was invalid. */
 146 
 147       case 0x19: /* Duplicate CCB Received in Target Mode-More than once CCB was
 148                     received to service data transfer between the same target LUN
 149                     and initiator SCSI ID in the same direction. */
 150 
 151       case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero
 152                     length segment or invalid segment list boundaries was received.
 153                     A CCB parameter was invalid. */
 154         hosterr = DID_ERROR; /* Couldn't find any better */
 155         break;
 156 
 157       case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
 158                     phase sequence was requested by the target. The host adapter
 159                     will generate a SCSI Reset Condition, notifying the host with
 160                     a SCRD interrupt */
 161         hosterr = DID_RESET;
 162         break;
 163       default:
 164         printk("makecode: unknown hoststatus %x\n", hosterr);
 165         break;
 166     }
 167     return scsierr|(hosterr << 16);
 168 }
 169 
 170 int aha1542_test_port(int bse)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172     volatile int debug = 0;
 173     
 174     base = bse;
 175     /* Reset the adapter. I ought to make a hard reset, but it's not really nessesary */
 176     
 177     /*  DEB(printk("aha1542_test_port called \n")); */
 178     
 179     outb(SRST|IRST/*|SCRST*/, CONTROL);
 180     
 181     debug = 1;
 182     /* Expect INIT and IDLE, any of the others are bad */
 183     WAIT(STATUS, STATMASK, INIT|IDLE, STST|DIAGF|INVDCMD|DF|CDF);
 184     
 185     debug = 2;
 186     /* Shouldn't have generated any interrupts during reset */
 187     if (inb(INTRFLAGS)&INTRMASK) goto fail;
 188     
 189     debug = 3;
 190     /* Test the basic ECHO command */
 191     outb(CMD_ECHO, DATA);
 192     
 193     debug = 4;
 194     /* Wait for CDF=0. If any of the others are set, it's bad */
 195     WAIT(STATUS, STATMASK, 0, STST|DIAGF|INVDCMD|DF|CDF);
 196     
 197     debug = 5;
 198     /* The meaning of life */
 199     outb(42, DATA);
 200     
 201     debug = 6;
 202     /* Expect only DF, that is, data ready */
 203     WAIT(STATUS, STATMASK, DF, STST|DIAGF|CDF|INVDCMD);
 204     
 205     debug = 7;
 206     /* Is the answer correct? */
 207     if (inb(DATA) != 42) goto fail;
 208     
 209     debug = 8;
 210     /* Reading port should reset DF */
 211     if (inb(STATUS) & DF) goto fail;
 212     
 213     debug = 9;
 214     /* When HACC, command is completed, and we're though testing */
 215     WAIT(INTRFLAGS, HACC, HACC, 0);
 216     /* now initialize adapter */
 217     
 218     debug = 10;
 219     /* Clear interrupts */
 220     outb(IRST, CONTROL);
 221     
 222     debug = 11;
 223     
 224     return debug;                               /* 1 = ok */
 225   fail:
 226     return 0;                                   /* 0 = not ok */
 227 }
 228 
 229 /* What's this little function for? */
 230 const char *aha1542_info(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 231 {
 232     static char buffer[] = "";                  /* looks nicer without anything here */
 233     return buffer;
 234 }
 235 
 236 /* A "high" level interrupt handler */
 237 void aha1542_intr_handle(int foo)
     /* [previous][next][first][last][top][bottom][index][help] */
 238 {
 239     void (*my_done)(Scsi_Cmnd *) = NULL;
 240     int errstatus, mbi, mbo, mbistatus;
 241     int number_serviced;
 242     Scsi_Cmnd * SCtmp;
 243 
 244 #ifdef DEBUG
 245     {
 246     int flag = inb(INTRFLAGS);
 247     printk("aha1542_intr_handle: ");
 248     if (!(flag&ANYINTR)) printk("no interrupt?");
 249     if (flag&MBIF) printk("MBIF ");
 250     if (flag&MBOA) printk("MBOF ");
 251     if (flag&HACC) printk("HACC ");
 252     if (flag&SCRD) printk("SCRD ");
 253     printk("status %02x\n", inb(STATUS));
 254   };
 255 #endif
 256     number_serviced = 0;
 257 
 258     while(1==1){
 259       aha1542_intr_reset();
 260 
 261       cli();
 262       mbi = aha1542_last_mbi_used + 1;
 263       if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES;
 264       
 265       do{
 266         if(mb[mbi].status != 0) break;
 267         mbi++;
 268         if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES;
 269       } while (mbi != aha1542_last_mbi_used);
 270       
 271       if(mb[mbi].status == 0){
 272         sti();
 273         /* Hmm, no mail.  Must have read it the last time around */
 274         if (number_serviced) return;
 275         printk("aha1542.c: interrupt received, but no mail.\n");
 276         return;
 277       };
 278 
 279       mbo = (scsi2int(mb[mbi].ccbptr) - ((unsigned int) &ccb[0])) / sizeof(struct ccb);
 280       mbistatus = mb[mbi].status;
 281       mb[mbi].status = 0;
 282       aha1542_last_mbi_used = mbi;
 283       sti();
 284       
 285 #ifdef DEBUG
 286       {
 287         if (ccb[mbo].tarstat|ccb[mbo].hastat)
 288           printk("aha1542_command: returning %x (status %d)\n", 
 289                  ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
 290       };
 291 #endif
 292 
 293       if(mbistatus == 3) continue; /* Aborted command not found */
 294 
 295 #ifdef DEBUG
 296       printk("...done %d %d\n",mbo, mbi);
 297 #endif
 298       
 299       SCtmp = SCint[mbo];
 300       my_done = SCtmp->scsi_done;
 301       if (SCtmp->host_scribble) scsi_free(SCtmp->host_scribble, 512);
 302       
 303       if (!my_done) {
 304         printk("aha1542_intr_handle: Unexpected interrupt\n");
 305         return;
 306       }
 307       
 308       /* Fetch the sense data, and tuck it away, in the required slot.  The
 309          Adaptec automatically fetches it, and there is no guarantee that
 310          we will still have it in the cdb when we come back */
 311       if (ccb[mbo].tarstat == 2)
 312         memcpy(SCtmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen], 
 313                sizeof(SCtmp->sense_buffer));
 314       
 315       
 316       /* is there mail :-) */
 317       
 318       /* more error checking left out here */
 319       if (mbistatus != 1)
 320         /* This is surely wrong, but I don't know what's right */
 321         errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
 322       else
 323         errstatus = 0;
 324       
 325 #ifdef DEBUG
 326       if(errstatus) printk("(aha1542 error:%x %x %x) ",errstatus, 
 327                            ccb[mbo].hastat, ccb[mbo].tarstat);
 328 #endif
 329 
 330       if (ccb[mbo].tarstat == 2) {
 331 #ifdef DEBUG
 332         int i;
 333 #endif
 334         DEB(printk("aha1542_intr_handle: sense:"));
 335 #ifdef DEBUG
 336         for (i = 0; i < 12; i++)
 337           printk("%02x ", ccb[mbo].cdb[ccb[mbo].cdblen+i]);
 338         printk("\n");
 339 #endif
 340         /*
 341           DEB(printk("aha1542_intr_handle: buf:"));
 342           for (i = 0; i < bufflen; i++)
 343           printk("%02x ", ((unchar *)buff)[i]);
 344           printk("\n");
 345           */
 346       }
 347       DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
 348       SCtmp->result = errstatus;
 349       SCint[mbo] = NULL;  /* This effectively frees up the mailbox slot, as
 350                              far as queuecommand is concerned */
 351       my_done(SCtmp);
 352       number_serviced++;
 353     };
 354 }
 355 
 356 int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
 357 {
 358     unchar ahacmd = CMD_START_SCSI;
 359     unchar direction;
 360     unchar *cmd = (unchar *) SCpnt->cmnd;
 361     unchar target = SCpnt->target;
 362     unchar lun = SCpnt->lun;
 363     void *buff = SCpnt->request_buffer;
 364     int bufflen = SCpnt->request_bufflen;
 365     int mbo;
 366 
 367     DEB(int i);
 368 
 369     DEB(if (target > 1) {
 370       SCpnt->result = DID_TIME_OUT << 16;
 371       done(SCpnt); return 0;});
 372     
 373     if(*cmd == REQUEST_SENSE){
 374 #ifndef DEBUG
 375       if (bufflen != 16) {
 376         printk("Wrong buffer length supplied for request sense (%d)\n",bufflen);
 377         panic("aha1542.c");
 378       };
 379 #endif
 380       SCpnt->result = 0;
 381       done(SCpnt); 
 382       return 0;
 383     };
 384 
 385 #ifdef DEBUG
 386     if (*cmd == READ_10 || *cmd == WRITE_10)
 387       i = xscsi2int(cmd+2);
 388     else if (*cmd == READ_6 || *cmd == WRITE_6)
 389       i = scsi2int(cmd+2);
 390     else
 391       i = -1;
 392     if (done)
 393       printk("aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
 394     else
 395       printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
 396     aha1542_stat();
 397     printk("aha1542_queuecommand: dumping scsi cmd:");
 398     for (i = 0; i < (*cmd<=0x1f?6:10); i++) printk("%02x ", cmd[i]);
 399     printk("\n");
 400     if (*cmd == WRITE_10 || *cmd == WRITE_6)
 401       return 0; /* we are still testing, so *don't* write */
 402 #endif
 403 /* Use the outgoing mailboxes in a round-robin fashion, because this
 404    is how the host adapter will scan for them */
 405 
 406     cli();
 407     mbo = aha1542_last_mbo_used + 1;
 408     if (mbo >= AHA1542_MAILBOXES) mbo = 0;
 409 
 410     do{
 411       if(mb[mbo].status == 0 && SCint[mbo] == NULL)
 412         break;
 413       mbo++;
 414       if (mbo >= AHA1542_MAILBOXES) mbo = 0;
 415     } while (mbo != aha1542_last_mbo_used);
 416 
 417     if(mb[mbo].status || SCint[mbo])
 418       panic("Unable to find empty mailbox for aha1542.\n");
 419 
 420     SCint[mbo] = SCpnt;  /* This will effectively prevent someone else from
 421                             screwing with this cdb. */
 422 
 423     aha1542_last_mbo_used = mbo;    
 424     sti();
 425 
 426 #ifdef DEBUG
 427     printk("Sending command (%d %x)...",mbo, done);
 428 #endif
 429 
 430     memset(&ccb[mbo], 0, sizeof(struct ccb));
 431 
 432     ccb[mbo].cdblen = (*cmd<=0x1f)?6:10;        /* SCSI Command Descriptor Block Length */
 433 
 434     direction = 0;
 435     if (*cmd == READ_10 || *cmd == READ_6)
 436         direction = 8;
 437     else if (*cmd == WRITE_10 || *cmd == WRITE_6)
 438         direction = 16;
 439 
 440     memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
 441 
 442     if (SCpnt->use_sg) {
 443       struct scatterlist * sgpnt;
 444       struct chain * cptr;
 445 #ifdef DEBUG
 446       unsigned char * ptr;
 447 #endif
 448       int i;
 449       ccb[mbo].op = 2;        /* SCSI Initiator Command  w/scatter-gather*/
 450       SCpnt->host_scribble = scsi_malloc(512);
 451       sgpnt = (struct scatterlist *) SCpnt->request_buffer;
 452       cptr = (struct chain *) SCpnt->host_scribble; 
 453       if (cptr == NULL) panic("aha1542.c: unable to allocate DMA memory\n");
 454       for(i=0; i<SCpnt->use_sg; i++) {
 455         if(sgpnt[i].length == 0 || SCpnt->use_sg > 16 || 
 456            (((int)sgpnt[i].address) & 1) || (sgpnt[i].length & 1)){
 457           unsigned char * ptr;
 458           printk("Bad segment list supplied to aha1542.c (%d, %d)\n",SCpnt->use_sg,i);
 459           for(i=0;i<SCpnt->use_sg++;i++){
 460             printk("%d: %x %x %d\n",i,sgpnt[i].address, sgpnt[i].alt_address,
 461                    sgpnt[i].length);
 462           };
 463           printk("cptr %x: ",cptr);
 464           ptr = (unsigned char *) &cptr[i];
 465           for(i=0;i<18;i++) printk("%02x ", ptr[i]);
 466           panic("Foooooooood fight!");
 467         };
 468         any2scsi(cptr[i].dataptr, sgpnt[i].address);
 469         any2scsi(cptr[i].datalen, sgpnt[i].length);
 470       };
 471       any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));
 472       any2scsi(ccb[mbo].dataptr, cptr);
 473 #ifdef DEBUG
 474       printk("cptr %x: ",cptr);
 475       ptr = (unsigned char *) cptr;
 476       for(i=0;i<18;i++) printk("%02x ", ptr[i]);
 477 #endif
 478     } else {
 479       ccb[mbo].op = 0;        /* SCSI Initiator Command */
 480       SCpnt->host_scribble = NULL;
 481       any2scsi(ccb[mbo].datalen, bufflen);
 482       any2scsi(ccb[mbo].dataptr, buff);
 483     };
 484     ccb[mbo].idlun = (target&7)<<5 | direction | (lun & 7); /*SCSI Target Id*/
 485     ccb[mbo].rsalen = 12;
 486     ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
 487     ccb[mbo].commlinkid = 0;
 488 
 489 #ifdef DEBUGd
 490     { int i;
 491     printk("aha1542_command: sending.. ");
 492     for (i = 0; i < sizeof(ccb[mbo])-10; i++)
 493       printk("%02x ", ((unchar *)&ccb[mbo])[i]);
 494     };
 495 #endif
 496     
 497     if (done) {
 498         DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat());
 499         SCpnt->scsi_done = done;
 500         mb[mbo].status = 1;
 501         aha1542_out(&ahacmd, 1);                /* start scsi command */
 502         DEB(aha1542_stat());
 503     }
 504     else
 505       printk("aha1542_queuecommand: done can't be NULL\n");
 506     
 507     return 0;
 508 }
 509 
 510 static volatile int internal_done_flag = 0;
 511 static volatile int internal_done_errcode = 0;
 512 static void internal_done(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 513 {
 514     internal_done_errcode = SCpnt->result;
 515     ++internal_done_flag;
 516 }
 517 
 518 int aha1542_command(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 519 {
 520     DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));
 521 
 522     aha1542_queuecommand(SCpnt, internal_done);
 523 
 524     while (!internal_done_flag);
 525     internal_done_flag = 0;
 526     return internal_done_errcode;
 527 }
 528 
 529 /* Initialize mailboxes */
 530 static void setup_mailboxes()
     /* [previous][next][first][last][top][bottom][index][help] */
 531 {
 532     int i;
 533     static unchar cmd[5] = {CMD_MBINIT, AHA1542_MAILBOXES};
 534 
 535     for(i=0; i<AHA1542_MAILBOXES; i++){
 536       mb[i].status = mb[AHA1542_MAILBOXES+i].status = 0;
 537       any2scsi(mb[i].ccbptr, &ccb[i]);
 538     };
 539     aha1542_intr_reset();     /* reset interrupts, so they don't block */       
 540     any2scsi((cmd+2), mb);
 541     aha1542_out(cmd, 5);
 542     WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 543     while (0) {
 544       fail:
 545         printk("aha1542_detect: failed setting up mailboxes\n");
 546     }
 547     aha1542_intr_reset();
 548 }
 549 
 550 /* Query the board to find out if it is a 1542 or a 1740, or whatever. */
 551 static int aha1542_getconfig(int hostnum)
     /* [previous][next][first][last][top][bottom][index][help] */
 552 {
 553   static unchar inquiry_cmd[] = {CMD_RETCONF };
 554   static unchar inquiry_result[3];
 555   int i;
 556   i = inb(STATUS);
 557   if (i & DF) {
 558     i = inb(DATA);
 559   };
 560   aha1542_out(inquiry_cmd, 1);
 561   aha1542_in(inquiry_result, 3);
 562   WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 563   while (0) {
 564   fail:
 565     printk("aha1542_detect: query board settings\n");
 566   }
 567   aha1542_intr_reset();
 568   switch(inquiry_result[0]){
 569   case 0x80:
 570     dma_chan = 7;
 571     break;
 572   case 0x40:
 573     dma_chan = 6;
 574     break;
 575   case 0x20:
 576     dma_chan = 5;
 577     break;
 578   case 1:
 579     printk("DMA priority 0 not available for Adaptec driver\n");
 580     return -1;
 581   default:
 582     printk("Unable to determine Adaptec DMA priority.  Disabling board\n");
 583     return -1;
 584   };
 585   switch(inquiry_result[1]){
 586   case 0x40:
 587     irq_level = 15;
 588     break;
 589   case 0x20:
 590     irq_level = 14;
 591     break;
 592   case 0x8:
 593     irq_level = 12;
 594     break;
 595   case 0x4:
 596     irq_level = 11;
 597     break;
 598   case 0x2:
 599     irq_level = 10;
 600     break;
 601   case 0x1:
 602     irq_level = 9;
 603     break;
 604   default:
 605     printk("Unable to determine Adaptec IRQ level.  Disabling board\n");
 606     return -1;
 607   };
 608   return 0;
 609 }
 610 
 611 /* Query the board to find out if it is a 1542 or a 1740, or whatever. */
 612 static void aha1542_query(int hostnum)
     /* [previous][next][first][last][top][bottom][index][help] */
 613 {
 614   static unchar inquiry_cmd[] = {CMD_INQUIRY };
 615   static unchar inquiry_result[4];
 616   int i;
 617   i = inb(STATUS);
 618   if (i & DF) {
 619     i = inb(DATA);
 620   };
 621   aha1542_out(inquiry_cmd, 1);
 622   aha1542_in(inquiry_result, 4);
 623   WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 624   while (0) {
 625   fail:
 626     printk("aha1542_detect: query card type\n");
 627   }
 628   aha1542_intr_reset();
 629 
 630 /* For an AHA1740 series board, we ignore the board since there is a
 631    hardware bug which can lead to wrong blocks being returned if the board
 632    is operating in the 1542 emulation mode.  Since there is an extended mode
 633    driver, we simply ignore the board and let the 1740 driver pick it up.
 634 */
 635 
 636   if (inquiry_result[0] == 0x43) {
 637     printk("aha1542.c: Emulation mode not supported for AHA 174N hardware.\n");
 638     aha_disable = 1;
 639   };
 640 }
 641 
 642 /* return non-zero on detection */
 643 int aha1542_detect(int hostnum)
     /* [previous][next][first][last][top][bottom][index][help] */
 644 {
 645     int i;
 646     int indx;
 647 
 648     DEB(printk("aha1542_detect: \n"));
 649     
 650     indx = 0;
 651     while(indx < sizeof(bases)/sizeof(bases[0])){
 652       i = aha1542_test_port(bases[indx]);
 653       if (i) break;
 654       indx++;
 655     }
 656     if (indx == sizeof(bases)/sizeof(bases[0])) return 0;
 657  
 658     /* Set the Bus on/off-times as not to ruin floppy performance */
 659     {
 660         static unchar oncmd[] = {CMD_BUSON_TIME, 7};
 661         static unchar offcmd[] = {CMD_BUSOFF_TIME, 5};
 662 
 663         aha1542_intr_reset();
 664         aha1542_out(oncmd, 2);
 665         WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 666         aha1542_intr_reset();
 667         aha1542_out(offcmd, 2);
 668         WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 669         while (0) {
 670           fail:
 671             printk("aha1542_detect: setting bus on/off-time failed\n");
 672         }
 673         aha1542_intr_reset();
 674     }
 675     aha1542_query(hostnum);
 676 
 677     if (aha_disable) return 0;
 678 
 679     if (aha1542_getconfig(hostnum) == -1) return 0;
 680     
 681     printk("Configuring Adaptec at IO:%x, IRQ %d, DMA priority %d\n",base,
 682            irq_level, dma_chan);
 683 
 684     DEB(aha1542_stat());
 685     setup_mailboxes();
 686 
 687     DEB(aha1542_stat());
 688 
 689     DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
 690 
 691     if (request_irq(irq_level,aha1542_intr_handle)) {
 692       printk("Unable to allocate IRQ for adaptec controller.\n");
 693       return 0;
 694     };
 695 
 696     if(request_dma(dma_chan)){
 697       printk("Unable to allocate DMA channel for Adaptec.\n");
 698       free_irq(irq_level);
 699       return 0;
 700     };
 701 
 702     if(dma_chan >= 5){
 703       outb(((dma_chan - 4)|CASCADE),DMA_MODE_REG);
 704       outb((dma_chan-4),DMA_MASK_REG);
 705     };
 706 
 707 #if 0
 708     DEB(printk(" *** READ CAPACITY ***\n"));
 709 
 710     {
 711         unchar buf[8];
 712         static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 713         int i;
 714         
 715         for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87;
 716         for (i = 0; i < 2; ++i)
 717           if (!aha1542_command(i, cmd, buf, sizeof(buf))) {
 718               printk("aha_detect: LU %d sector_size %d device_size %d\n",
 719                      i, xscsi2int(buf+4), xscsi2int(buf));
 720           }
 721     }
 722 
 723     DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n"));
 724 
 725     for (i = 0; i < 4; ++i)
 726       {
 727           unsigned char cmd[10];
 728           static buffer[512];
 729           
 730           cmd[0] = READ_10;
 731           cmd[1] = 0;
 732           xany2scsi(cmd+2, i);
 733           cmd[6] = 0;
 734           cmd[7] = 0;
 735           cmd[8] = 1;
 736           cmd[9] = 0;
 737           aha1542_command(0, cmd, buffer, 512);
 738       }
 739 #endif
 740     aha1542_host = hostnum;
 741     return 1;
 742 }
 743 
 744 /* The abort command does not leave the device in a clean state where
 745    it is available to be used again.  Until this gets worked out, we will
 746    leave it commented out.  */
 747 
 748 int aha1542_abort(Scsi_Cmnd * SCpnt, int i)
     /* [previous][next][first][last][top][bottom][index][help] */
 749 {
 750 #if 0
 751     unchar ahacmd = CMD_START_SCSI;
 752     int mbo;
 753 #endif
 754     DEB(printk("aha1542_abort\n"));
 755 #if 0
 756     cli();
 757     for(mbo = 0; mbo < AHA1542_MAILBOXES; mbo++)
 758       if (SCpnt == SCint[mbo]){
 759         mb[mbo].status = 2;  /* Abort command */
 760         aha1542_out(&ahacmd, 1);                /* start scsi command */
 761         sti();
 762         break;
 763       };
 764 #endif
 765     return 0;
 766 }
 767 
 768 int aha1542_reset(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 769 {
 770     DEB(printk("aha1542_reset called\n"));
 771     return 0;
 772 }
 773 
 774 int aha1542_biosparam(int size, int dev, int* info){
     /* [previous][next][first][last][top][bottom][index][help] */
 775   info[0] = 64;
 776   info[1] = 32;
 777   info[2] = size >> 11;
 778   if (info[2] >= 1024) info[2] = 1024;
 779   return 0;
 780 }

/* [previous][next][first][last][top][bottom][index][help] */