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

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