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     any2scsi(mb[mbo].ccbptr, &ccb[mbo]); /* This gets trashed for some reason*/
 435 
 436     memset(&ccb[mbo], 0, sizeof(struct ccb));
 437 
 438     ccb[mbo].cdblen = COMMAND_SIZE(*cmd);     /* SCSI Command Descriptor Block Length */
 439 
 440     direction = 0;
 441     if (*cmd == READ_10 || *cmd == READ_6)
 442         direction = 8;
 443     else if (*cmd == WRITE_10 || *cmd == WRITE_6)
 444         direction = 16;
 445 
 446     memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
 447 
 448     if (SCpnt->use_sg) {
 449       struct scatterlist * sgpnt;
 450       struct chain * cptr;
 451 #ifdef DEBUG
 452       unsigned char * ptr;
 453 #endif
 454       int i;
 455       ccb[mbo].op = 2;        /* SCSI Initiator Command  w/scatter-gather*/
 456       SCpnt->host_scribble = (unsigned char *) scsi_malloc(512);
 457       sgpnt = (struct scatterlist *) SCpnt->request_buffer;
 458       cptr = (struct chain *) SCpnt->host_scribble; 
 459       if (cptr == NULL) panic("aha1542.c: unable to allocate DMA memory\n");
 460       for(i=0; i<SCpnt->use_sg; i++) {
 461         if(sgpnt[i].length == 0 || SCpnt->use_sg > 16 || 
 462            (((int)sgpnt[i].address) & 1) || (sgpnt[i].length & 1)){
 463           unsigned char * ptr;
 464           printk("Bad segment list supplied to aha1542.c (%d, %d)\n",SCpnt->use_sg,i);
 465           for(i=0;i<SCpnt->use_sg++;i++){
 466             printk("%d: %x %x %d\n",i,sgpnt[i].address, sgpnt[i].alt_address,
 467                    sgpnt[i].length);
 468           };
 469           printk("cptr %x: ",cptr);
 470           ptr = (unsigned char *) &cptr[i];
 471           for(i=0;i<18;i++) printk("%02x ", ptr[i]);
 472           panic("Foooooooood fight!");
 473         };
 474         any2scsi(cptr[i].dataptr, sgpnt[i].address);
 475         any2scsi(cptr[i].datalen, sgpnt[i].length);
 476       };
 477       any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));
 478       any2scsi(ccb[mbo].dataptr, cptr);
 479 #ifdef DEBUG
 480       printk("cptr %x: ",cptr);
 481       ptr = (unsigned char *) cptr;
 482       for(i=0;i<18;i++) printk("%02x ", ptr[i]);
 483 #endif
 484     } else {
 485       ccb[mbo].op = 0;        /* SCSI Initiator Command */
 486       SCpnt->host_scribble = NULL;
 487       any2scsi(ccb[mbo].datalen, bufflen);
 488       any2scsi(ccb[mbo].dataptr, buff);
 489     };
 490     ccb[mbo].idlun = (target&7)<<5 | direction | (lun & 7); /*SCSI Target Id*/
 491     ccb[mbo].rsalen = 12;
 492     ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
 493     ccb[mbo].commlinkid = 0;
 494 
 495 #ifdef DEBUGd
 496     { int i;
 497     printk("aha1542_command: sending.. ");
 498     for (i = 0; i < sizeof(ccb[mbo])-10; i++)
 499       printk("%02x ", ((unchar *)&ccb[mbo])[i]);
 500     };
 501 #endif
 502     
 503     if (done) {
 504         DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat());
 505         SCpnt->scsi_done = done;
 506         mb[mbo].status = 1;
 507         aha1542_out(&ahacmd, 1);                /* start scsi command */
 508         DEB(aha1542_stat());
 509     }
 510     else
 511       printk("aha1542_queuecommand: done can't be NULL\n");
 512     
 513     return 0;
 514 }
 515 
 516 static volatile int internal_done_flag = 0;
 517 static volatile int internal_done_errcode = 0;
 518 static void internal_done(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 519 {
 520     internal_done_errcode = SCpnt->result;
 521     ++internal_done_flag;
 522 }
 523 
 524 int aha1542_command(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 525 {
 526     DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));
 527 
 528     aha1542_queuecommand(SCpnt, internal_done);
 529 
 530     while (!internal_done_flag);
 531     internal_done_flag = 0;
 532     return internal_done_errcode;
 533 }
 534 
 535 /* Initialize mailboxes */
 536 static void setup_mailboxes(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 537 {
 538     int i;
 539     static unchar cmd[5] = {CMD_MBINIT, AHA1542_MAILBOXES};
 540 
 541     for(i=0; i<AHA1542_MAILBOXES; i++){
 542       mb[i].status = mb[AHA1542_MAILBOXES+i].status = 0;
 543       any2scsi(mb[i].ccbptr, &ccb[i]);
 544     };
 545     aha1542_intr_reset();     /* reset interrupts, so they don't block */       
 546     any2scsi((cmd+2), mb);
 547     aha1542_out(cmd, 5);
 548     WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 549     while (0) {
 550       fail:
 551         printk("aha1542_detect: failed setting up mailboxes\n");
 552     }
 553     aha1542_intr_reset();
 554 }
 555 
 556 static int aha1542_getconfig(int hostnum)
     /* [previous][next][first][last][top][bottom][index][help] */
 557 {
 558   static unchar inquiry_cmd[] = {CMD_RETCONF };
 559   static unchar inquiry_result[3];
 560   int i;
 561   i = inb(STATUS);
 562   if (i & DF) {
 563     i = inb(DATA);
 564   };
 565   aha1542_out(inquiry_cmd, 1);
 566   aha1542_in(inquiry_result, 3);
 567   WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 568   while (0) {
 569   fail:
 570     printk("aha1542_detect: query board settings\n");
 571   }
 572   aha1542_intr_reset();
 573   switch(inquiry_result[0]){
 574   case 0x80:
 575     dma_chan = 7;
 576     break;
 577   case 0x40:
 578     dma_chan = 6;
 579     break;
 580   case 0x20:
 581     dma_chan = 5;
 582     break;
 583   case 0x01:
 584     printk("DMA priority 0 not available for Adaptec driver\n");
 585     return -1;
 586   case 0:
 587     /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel.
 588        Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */
 589     dma_chan = 0xFF;
 590     break;
 591   default:
 592     printk("Unable to determine Adaptec DMA priority.  Disabling board\n");
 593     return -1;
 594   };
 595   switch(inquiry_result[1]){
 596   case 0x40:
 597     irq_level = 15;
 598     break;
 599   case 0x20:
 600     irq_level = 14;
 601     break;
 602   case 0x8:
 603     irq_level = 12;
 604     break;
 605   case 0x4:
 606     irq_level = 11;
 607     break;
 608   case 0x2:
 609     irq_level = 10;
 610     break;
 611   case 0x1:
 612     irq_level = 9;
 613     break;
 614   default:
 615     printk("Unable to determine Adaptec IRQ level.  Disabling board\n");
 616     return -1;
 617   };
 618   return 0;
 619 }
 620 
 621 /* Query the board to find out if it is a 1542 or a 1740, or whatever. */
 622 static void aha1542_query(int hostnum)
     /* [previous][next][first][last][top][bottom][index][help] */
 623 {
 624   static unchar inquiry_cmd[] = {CMD_INQUIRY };
 625   static unchar inquiry_result[4];
 626   int i;
 627   i = inb(STATUS);
 628   if (i & DF) {
 629     i = inb(DATA);
 630   };
 631   aha1542_out(inquiry_cmd, 1);
 632   aha1542_in(inquiry_result, 4);
 633   WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 634   while (0) {
 635   fail:
 636     printk("aha1542_detect: query card type\n");
 637   }
 638   aha1542_intr_reset();
 639 
 640 /* For an AHA1740 series board, we ignore the board since there is a
 641    hardware bug which can lead to wrong blocks being returned if the board
 642    is operating in the 1542 emulation mode.  Since there is an extended mode
 643    driver, we simply ignore the board and let the 1740 driver pick it up.
 644 */
 645 
 646   if (inquiry_result[0] == 0x43) {
 647     printk("aha1542.c: Emulation mode not supported for AHA 174N hardware.\n");
 648     aha_disable = 1;
 649   };
 650 }
 651 
 652 /* return non-zero on detection */
 653 int aha1542_detect(int hostnum)
     /* [previous][next][first][last][top][bottom][index][help] */
 654 {
 655     int i;
 656     int indx;
 657 
 658     DEB(printk("aha1542_detect: \n"));
 659     
 660     indx = 0;
 661     while(indx < sizeof(bases)/sizeof(bases[0])){
 662       i = aha1542_test_port(bases[indx]);
 663       if (i) break;
 664       indx++;
 665     }
 666     if (indx == sizeof(bases)/sizeof(bases[0])) return 0;
 667  
 668     /* Set the Bus on/off-times as not to ruin floppy performance */
 669     {
 670         static unchar oncmd[] = {CMD_BUSON_TIME, 7};
 671         static unchar offcmd[] = {CMD_BUSOFF_TIME, 5};
 672 
 673         aha1542_intr_reset();
 674         aha1542_out(oncmd, 2);
 675         WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 676         aha1542_intr_reset();
 677         aha1542_out(offcmd, 2);
 678         WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 679         while (0) {
 680           fail:
 681             printk("aha1542_detect: setting bus on/off-time failed\n");
 682         }
 683         aha1542_intr_reset();
 684     }
 685     aha1542_query(hostnum);
 686 
 687     if (aha_disable) return 0;
 688 
 689     if (aha1542_getconfig(hostnum) == -1) return 0;
 690     
 691     printk("Configuring Adaptec at IO:%x, IRQ %d",base, irq_level);
 692     if (dma_chan != 0xFF)
 693         printk(", DMA priority %d", dma_chan);
 694     printk("\n");
 695 
 696     DEB(aha1542_stat());
 697     setup_mailboxes();
 698 
 699     DEB(aha1542_stat());
 700 
 701     DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
 702 
 703     if (request_irq(irq_level,aha1542_intr_handle)) {
 704         printk("Unable to allocate IRQ for adaptec controller.\n");
 705         return 0;
 706     }
 707 
 708     if (dma_chan != 0xFF) {
 709         if (request_dma(dma_chan)) {
 710             printk("Unable to allocate DMA channel for Adaptec.\n");
 711             free_irq(irq_level);
 712             return 0;
 713         }
 714 
 715         if (dma_chan >= 5) {
 716             outb((dma_chan - 4) | CASCADE, DMA_MODE_REG);
 717             outb(dma_chan - 4, DMA_MASK_REG);
 718         }
 719     }
 720 
 721 #if 0
 722     DEB(printk(" *** READ CAPACITY ***\n"));
 723 
 724     {
 725         unchar buf[8];
 726         static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 727         int i;
 728         
 729         for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87;
 730         for (i = 0; i < 2; ++i)
 731           if (!aha1542_command(i, cmd, buf, sizeof(buf))) {
 732               printk("aha_detect: LU %d sector_size %d device_size %d\n",
 733                      i, xscsi2int(buf+4), xscsi2int(buf));
 734           }
 735     }
 736 
 737     DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n"));
 738 
 739     for (i = 0; i < 4; ++i)
 740       {
 741           unsigned char cmd[10];
 742           static buffer[512];
 743           
 744           cmd[0] = READ_10;
 745           cmd[1] = 0;
 746           xany2scsi(cmd+2, i);
 747           cmd[6] = 0;
 748           cmd[7] = 0;
 749           cmd[8] = 1;
 750           cmd[9] = 0;
 751           aha1542_command(0, cmd, buffer, 512);
 752       }
 753 #endif
 754     aha1542_host = hostnum;
 755     return 1;
 756 }
 757 
 758 /* The abort command does not leave the device in a clean state where
 759    it is available to be used again.  Until this gets worked out, we will
 760    leave it commented out.  */
 761 
 762 int aha1542_abort(Scsi_Cmnd * SCpnt, int i)
     /* [previous][next][first][last][top][bottom][index][help] */
 763 {
 764 #if 0
 765     unchar ahacmd = CMD_START_SCSI;
 766     int mbo;
 767 #endif
 768     DEB(printk("aha1542_abort\n"));
 769 #if 0
 770     cli();
 771     for(mbo = 0; mbo < AHA1542_MAILBOXES; mbo++)
 772       if (SCpnt == SCint[mbo]){
 773         mb[mbo].status = 2;  /* Abort command */
 774         aha1542_out(&ahacmd, 1);                /* start scsi command */
 775         sti();
 776         break;
 777       };
 778 #endif
 779     return 0;
 780 }
 781 
 782 int aha1542_reset(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 783 {
 784     DEB(printk("aha1542_reset called\n"));
 785     return 0;
 786 }
 787 
 788 int aha1542_biosparam(int size, int dev, int * ip)
     /* [previous][next][first][last][top][bottom][index][help] */
 789 {
 790   ip[0] = 64;
 791   ip[1] = 32;
 792   ip[2] = size >> 11;
 793 /*  if (ip[2] >= 1024) ip[2] = 1024; */
 794   return 0;
 795 }

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