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 static void setup_mailboxes(void);
  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     setup_mailboxes();
 189     
 190     debug = 3;
 191     /* Test the basic ECHO command */
 192     outb(CMD_ECHO, DATA);
 193     
 194     debug = 4;
 195     /* Wait for CDF=0. If any of the others are set, it's bad */
 196     WAIT(STATUS, STATMASK, 0, STST|DIAGF|INVDCMD|DF|CDF);
 197     
 198     debug = 5;
 199     /* The meaning of life */
 200     outb(42, DATA);
 201     
 202     debug = 6;
 203     /* Expect only DF, that is, data ready */
 204     WAIT(STATUS, STATMASK, DF, STST|DIAGF|CDF|INVDCMD);
 205     
 206     debug = 7;
 207     /* Is the answer correct? */
 208     if (inb(DATA) != 42) goto fail;
 209     
 210     debug = 8;
 211     /* Reading port should reset DF */
 212     if (inb(STATUS) & DF) goto fail;
 213     
 214     debug = 9;
 215     /* When HACC, command is completed, and we're though testing */
 216     WAIT(INTRFLAGS, HACC, HACC, 0);
 217     /* now initialize adapter */
 218     
 219     debug = 10;
 220     /* Clear interrupts */
 221     outb(IRST, CONTROL);
 222     
 223     debug = 11;
 224     
 225     return debug;                               /* 1 = ok */
 226   fail:
 227     return 0;                                   /* 0 = not ok */
 228 }
 229 
 230 /* What's this little function for? */
 231 const char *aha1542_info(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 232 {
 233     static char buffer[] = "Adaptec 1542";
 234     return buffer;
 235 }
 236 
 237 /* A "high" level interrupt handler */
 238 void aha1542_intr_handle(int foo)
     /* [previous][next][first][last][top][bottom][index][help] */
 239 {
 240     void (*my_done)(Scsi_Cmnd *) = NULL;
 241     int errstatus, mbi, mbo, mbistatus;
 242     int number_serviced;
 243     Scsi_Cmnd * SCtmp;
 244 
 245 #ifdef DEBUG
 246     {
 247     int flag = inb(INTRFLAGS);
 248     printk("aha1542_intr_handle: ");
 249     if (!(flag&ANYINTR)) printk("no interrupt?");
 250     if (flag&MBIF) printk("MBIF ");
 251     if (flag&MBOA) printk("MBOF ");
 252     if (flag&HACC) printk("HACC ");
 253     if (flag&SCRD) printk("SCRD ");
 254     printk("status %02x\n", inb(STATUS));
 255   };
 256 #endif
 257     number_serviced = 0;
 258 
 259     while(1==1){
 260       aha1542_intr_reset();
 261 
 262       cli();
 263       mbi = aha1542_last_mbi_used + 1;
 264       if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES;
 265       
 266       do{
 267         if(mb[mbi].status != 0) break;
 268         mbi++;
 269         if (mbi >= 2*AHA1542_MAILBOXES) mbi = AHA1542_MAILBOXES;
 270       } while (mbi != aha1542_last_mbi_used);
 271       
 272       if(mb[mbi].status == 0){
 273         sti();
 274         /* Hmm, no mail.  Must have read it the last time around */
 275         if (number_serviced) return;
 276         printk("aha1542.c: interrupt received, but no mail.\n");
 277         return;
 278       };
 279 
 280       mbo = (scsi2int(mb[mbi].ccbptr) - ((unsigned int) &ccb[0])) / sizeof(struct ccb);
 281       mbistatus = mb[mbi].status;
 282       mb[mbi].status = 0;
 283       aha1542_last_mbi_used = mbi;
 284       sti();
 285       
 286 #ifdef DEBUG
 287       {
 288         if (ccb[mbo].tarstat|ccb[mbo].hastat)
 289           printk("aha1542_command: returning %x (status %d)\n", 
 290                  ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);
 291       };
 292 #endif
 293 
 294       if(mbistatus == 3) continue; /* Aborted command not found */
 295 
 296 #ifdef DEBUG
 297       printk("...done %d %d\n",mbo, mbi);
 298 #endif
 299       
 300       SCtmp = SCint[mbo];
 301 
 302       if (!SCtmp || !SCtmp->scsi_done) {
 303         printk("aha1542_intr_handle: Unexpected interrupt\n");
 304         return;
 305       }
 306       
 307       my_done = SCtmp->scsi_done;
 308       if (SCtmp->host_scribble) scsi_free(SCtmp->host_scribble, 512);
 309       
 310       /* Fetch the sense data, and tuck it away, in the required slot.  The
 311          Adaptec automatically fetches it, and there is no guarantee that
 312          we will still have it in the cdb when we come back */
 313       if (ccb[mbo].tarstat == 2)
 314         memcpy(SCtmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen], 
 315                sizeof(SCtmp->sense_buffer));
 316       
 317       
 318       /* is there mail :-) */
 319       
 320       /* more error checking left out here */
 321       if (mbistatus != 1)
 322         /* This is surely wrong, but I don't know what's right */
 323         errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
 324       else
 325         errstatus = 0;
 326       
 327 #ifdef DEBUG
 328       if(errstatus) printk("(aha1542 error:%x %x %x) ",errstatus, 
 329                            ccb[mbo].hastat, ccb[mbo].tarstat);
 330 #endif
 331 
 332       if (ccb[mbo].tarstat == 2) {
 333 #ifdef DEBUG
 334         int i;
 335 #endif
 336         DEB(printk("aha1542_intr_handle: sense:"));
 337 #ifdef DEBUG
 338         for (i = 0; i < 12; i++)
 339           printk("%02x ", ccb[mbo].cdb[ccb[mbo].cdblen+i]);
 340         printk("\n");
 341 #endif
 342         /*
 343           DEB(printk("aha1542_intr_handle: buf:"));
 344           for (i = 0; i < bufflen; i++)
 345           printk("%02x ", ((unchar *)buff)[i]);
 346           printk("\n");
 347           */
 348       }
 349       DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
 350       SCtmp->result = errstatus;
 351       SCint[mbo] = NULL;  /* This effectively frees up the mailbox slot, as
 352                              far as queuecommand is concerned */
 353       my_done(SCtmp);
 354       number_serviced++;
 355     };
 356 }
 357 
 358 int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
 359 {
 360     unchar ahacmd = CMD_START_SCSI;
 361     unchar direction;
 362     unchar *cmd = (unchar *) SCpnt->cmnd;
 363     unchar target = SCpnt->target;
 364     unchar lun = SCpnt->lun;
 365     void *buff = SCpnt->request_buffer;
 366     int bufflen = SCpnt->request_bufflen;
 367     int mbo;
 368 
 369     DEB(int i);
 370 
 371     DEB(if (target > 1) {
 372       SCpnt->result = DID_TIME_OUT << 16;
 373       done(SCpnt); return 0;});
 374     
 375     if(*cmd == REQUEST_SENSE){
 376 #ifndef DEBUG
 377       if (bufflen != 16) {
 378         printk("Wrong buffer length supplied for request sense (%d)\n",bufflen);
 379         panic("aha1542.c");
 380       };
 381 #endif
 382       SCpnt->result = 0;
 383       done(SCpnt); 
 384       return 0;
 385     };
 386 
 387 #ifdef DEBUG
 388     if (*cmd == READ_10 || *cmd == WRITE_10)
 389       i = xscsi2int(cmd+2);
 390     else if (*cmd == READ_6 || *cmd == WRITE_6)
 391       i = scsi2int(cmd+2);
 392     else
 393       i = -1;
 394     if (done)
 395       printk("aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
 396     else
 397       printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
 398     aha1542_stat();
 399     printk("aha1542_queuecommand: dumping scsi cmd:");
 400     for (i = 0; i < (COMMAND_SIZE(*cmd)); i++) printk("%02x ", cmd[i]);
 401     printk("\n");
 402     if (*cmd == WRITE_10 || *cmd == WRITE_6)
 403       return 0; /* we are still testing, so *don't* write */
 404 #endif
 405 /* Use the outgoing mailboxes in a round-robin fashion, because this
 406    is how the host adapter will scan for them */
 407 
 408     cli();
 409     mbo = aha1542_last_mbo_used + 1;
 410     if (mbo >= AHA1542_MAILBOXES) mbo = 0;
 411 
 412     do{
 413       if(mb[mbo].status == 0 && SCint[mbo] == NULL)
 414         break;
 415       mbo++;
 416       if (mbo >= AHA1542_MAILBOXES) mbo = 0;
 417     } while (mbo != aha1542_last_mbo_used);
 418 
 419     if(mb[mbo].status || SCint[mbo])
 420       panic("Unable to find empty mailbox for aha1542.\n");
 421 
 422     SCint[mbo] = SCpnt;  /* This will effectively prevent someone else from
 423                             screwing with this cdb. */
 424 
 425     aha1542_last_mbo_used = mbo;    
 426     sti();
 427 
 428 #ifdef DEBUG
 429     printk("Sending command (%d %x)...",mbo, done);
 430 #endif
 431 
 432     memset(&ccb[mbo], 0, sizeof(struct ccb));
 433 
 434     ccb[mbo].cdblen = COMMAND_SIZE(*cmd);     /* SCSI Command Descriptor Block Length */
 435 
 436     direction = 0;
 437     if (*cmd == READ_10 || *cmd == READ_6)
 438         direction = 8;
 439     else if (*cmd == WRITE_10 || *cmd == WRITE_6)
 440         direction = 16;
 441 
 442     memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
 443 
 444     if (SCpnt->use_sg) {
 445       struct scatterlist * sgpnt;
 446       struct chain * cptr;
 447 #ifdef DEBUG
 448       unsigned char * ptr;
 449 #endif
 450       int i;
 451       ccb[mbo].op = 2;        /* SCSI Initiator Command  w/scatter-gather*/
 452       SCpnt->host_scribble = scsi_malloc(512);
 453       sgpnt = (struct scatterlist *) SCpnt->request_buffer;
 454       cptr = (struct chain *) SCpnt->host_scribble; 
 455       if (cptr == NULL) panic("aha1542.c: unable to allocate DMA memory\n");
 456       for(i=0; i<SCpnt->use_sg; i++) {
 457         if(sgpnt[i].length == 0 || SCpnt->use_sg > 16 || 
 458            (((int)sgpnt[i].address) & 1) || (sgpnt[i].length & 1)){
 459           unsigned char * ptr;
 460           printk("Bad segment list supplied to aha1542.c (%d, %d)\n",SCpnt->use_sg,i);
 461           for(i=0;i<SCpnt->use_sg++;i++){
 462             printk("%d: %x %x %d\n",i,sgpnt[i].address, sgpnt[i].alt_address,
 463                    sgpnt[i].length);
 464           };
 465           printk("cptr %x: ",cptr);
 466           ptr = (unsigned char *) &cptr[i];
 467           for(i=0;i<18;i++) printk("%02x ", ptr[i]);
 468           panic("Foooooooood fight!");
 469         };
 470         any2scsi(cptr[i].dataptr, sgpnt[i].address);
 471         any2scsi(cptr[i].datalen, sgpnt[i].length);
 472       };
 473       any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));
 474       any2scsi(ccb[mbo].dataptr, cptr);
 475 #ifdef DEBUG
 476       printk("cptr %x: ",cptr);
 477       ptr = (unsigned char *) cptr;
 478       for(i=0;i<18;i++) printk("%02x ", ptr[i]);
 479 #endif
 480     } else {
 481       ccb[mbo].op = 0;        /* SCSI Initiator Command */
 482       SCpnt->host_scribble = NULL;
 483       any2scsi(ccb[mbo].datalen, bufflen);
 484       any2scsi(ccb[mbo].dataptr, buff);
 485     };
 486     ccb[mbo].idlun = (target&7)<<5 | direction | (lun & 7); /*SCSI Target Id*/
 487     ccb[mbo].rsalen = 12;
 488     ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
 489     ccb[mbo].commlinkid = 0;
 490 
 491 #ifdef DEBUGd
 492     { int i;
 493     printk("aha1542_command: sending.. ");
 494     for (i = 0; i < sizeof(ccb[mbo])-10; i++)
 495       printk("%02x ", ((unchar *)&ccb[mbo])[i]);
 496     };
 497 #endif
 498     
 499     if (done) {
 500         DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat());
 501         SCpnt->scsi_done = done;
 502         mb[mbo].status = 1;
 503         aha1542_out(&ahacmd, 1);                /* start scsi command */
 504         DEB(aha1542_stat());
 505     }
 506     else
 507       printk("aha1542_queuecommand: done can't be NULL\n");
 508     
 509     return 0;
 510 }
 511 
 512 static volatile int internal_done_flag = 0;
 513 static volatile int internal_done_errcode = 0;
 514 static void internal_done(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 515 {
 516     internal_done_errcode = SCpnt->result;
 517     ++internal_done_flag;
 518 }
 519 
 520 int aha1542_command(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 521 {
 522     DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));
 523 
 524     aha1542_queuecommand(SCpnt, internal_done);
 525 
 526     while (!internal_done_flag);
 527     internal_done_flag = 0;
 528     return internal_done_errcode;
 529 }
 530 
 531 /* Initialize mailboxes */
 532 static void setup_mailboxes(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 533 {
 534     int i;
 535     static unchar cmd[5] = {CMD_MBINIT, AHA1542_MAILBOXES};
 536 
 537     for(i=0; i<AHA1542_MAILBOXES; i++){
 538       mb[i].status = mb[AHA1542_MAILBOXES+i].status = 0;
 539       any2scsi(mb[i].ccbptr, &ccb[i]);
 540     };
 541     aha1542_intr_reset();     /* reset interrupts, so they don't block */       
 542     any2scsi((cmd+2), mb);
 543     aha1542_out(cmd, 5);
 544     WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 545     while (0) {
 546       fail:
 547         printk("aha1542_detect: failed setting up mailboxes\n");
 548     }
 549     aha1542_intr_reset();
 550 }
 551 
 552 static int aha1542_getconfig(int hostnum)
     /* [previous][next][first][last][top][bottom][index][help] */
 553 {
 554   static unchar inquiry_cmd[] = {CMD_RETCONF };
 555   static unchar inquiry_result[3];
 556   int i;
 557   i = inb(STATUS);
 558   if (i & DF) {
 559     i = inb(DATA);
 560   };
 561   aha1542_out(inquiry_cmd, 1);
 562   aha1542_in(inquiry_result, 3);
 563   WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 564   while (0) {
 565   fail:
 566     printk("aha1542_detect: query board settings\n");
 567   }
 568   aha1542_intr_reset();
 569   switch(inquiry_result[0]){
 570   case 0x80:
 571     dma_chan = 7;
 572     break;
 573   case 0x40:
 574     dma_chan = 6;
 575     break;
 576   case 0x20:
 577     dma_chan = 5;
 578     break;
 579   case 1:
 580     printk("DMA priority 0 not available for Adaptec driver\n");
 581     return -1;
 582   default:
 583     printk("Unable to determine Adaptec DMA priority.  Disabling board\n");
 584     return -1;
 585   };
 586   switch(inquiry_result[1]){
 587   case 0x40:
 588     irq_level = 15;
 589     break;
 590   case 0x20:
 591     irq_level = 14;
 592     break;
 593   case 0x8:
 594     irq_level = 12;
 595     break;
 596   case 0x4:
 597     irq_level = 11;
 598     break;
 599   case 0x2:
 600     irq_level = 10;
 601     break;
 602   case 0x1:
 603     irq_level = 9;
 604     break;
 605   default:
 606     printk("Unable to determine Adaptec IRQ level.  Disabling board\n");
 607     return -1;
 608   };
 609   return 0;
 610 }
 611 
 612 /* Query the board to find out if it is a 1542 or a 1740, or whatever. */
 613 static void aha1542_query(int hostnum)
     /* [previous][next][first][last][top][bottom][index][help] */
 614 {
 615   static unchar inquiry_cmd[] = {CMD_INQUIRY };
 616   static unchar inquiry_result[4];
 617   int i;
 618   i = inb(STATUS);
 619   if (i & DF) {
 620     i = inb(DATA);
 621   };
 622   aha1542_out(inquiry_cmd, 1);
 623   aha1542_in(inquiry_result, 4);
 624   WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 625   while (0) {
 626   fail:
 627     printk("aha1542_detect: query card type\n");
 628   }
 629   aha1542_intr_reset();
 630 
 631 /* For an AHA1740 series board, we ignore the board since there is a
 632    hardware bug which can lead to wrong blocks being returned if the board
 633    is operating in the 1542 emulation mode.  Since there is an extended mode
 634    driver, we simply ignore the board and let the 1740 driver pick it up.
 635 */
 636 
 637   if (inquiry_result[0] == 0x43) {
 638     printk("aha1542.c: Emulation mode not supported for AHA 174N hardware.\n");
 639     aha_disable = 1;
 640   };
 641 }
 642 
 643 /* return non-zero on detection */
 644 int aha1542_detect(int hostnum)
     /* [previous][next][first][last][top][bottom][index][help] */
 645 {
 646     int i;
 647     int indx;
 648 
 649     DEB(printk("aha1542_detect: \n"));
 650     
 651     indx = 0;
 652     while(indx < sizeof(bases)/sizeof(bases[0])){
 653       i = aha1542_test_port(bases[indx]);
 654       if (i) break;
 655       indx++;
 656     }
 657     if (indx == sizeof(bases)/sizeof(bases[0])) return 0;
 658  
 659     /* Set the Bus on/off-times as not to ruin floppy performance */
 660     {
 661         static unchar oncmd[] = {CMD_BUSON_TIME, 7};
 662         static unchar offcmd[] = {CMD_BUSOFF_TIME, 5};
 663 
 664         aha1542_intr_reset();
 665         aha1542_out(oncmd, 2);
 666         WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 667         aha1542_intr_reset();
 668         aha1542_out(offcmd, 2);
 669         WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 670         while (0) {
 671           fail:
 672             printk("aha1542_detect: setting bus on/off-time failed\n");
 673         }
 674         aha1542_intr_reset();
 675     }
 676     aha1542_query(hostnum);
 677 
 678     if (aha_disable) return 0;
 679 
 680     if (aha1542_getconfig(hostnum) == -1) return 0;
 681     
 682     printk("Configuring Adaptec at IO:%x, IRQ %d, DMA priority %d\n",base,
 683            irq_level, dma_chan);
 684 
 685     DEB(aha1542_stat());
 686     setup_mailboxes();
 687 
 688     DEB(aha1542_stat());
 689 
 690     DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level));
 691 
 692     if (request_irq(irq_level,aha1542_intr_handle)) {
 693       printk("Unable to allocate IRQ for adaptec controller.\n");
 694       return 0;
 695     };
 696 
 697     if(request_dma(dma_chan)){
 698       printk("Unable to allocate DMA channel for Adaptec.\n");
 699       free_irq(irq_level);
 700       return 0;
 701     };
 702 
 703     if(dma_chan >= 5){
 704       outb(((dma_chan - 4)|CASCADE),DMA_MODE_REG);
 705       outb((dma_chan-4),DMA_MASK_REG);
 706     };
 707 
 708 #if 0
 709     DEB(printk(" *** READ CAPACITY ***\n"));
 710 
 711     {
 712         unchar buf[8];
 713         static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 714         int i;
 715         
 716         for (i = 0; i < sizeof(buf); ++i) buf[i] = 0x87;
 717         for (i = 0; i < 2; ++i)
 718           if (!aha1542_command(i, cmd, buf, sizeof(buf))) {
 719               printk("aha_detect: LU %d sector_size %d device_size %d\n",
 720                      i, xscsi2int(buf+4), xscsi2int(buf));
 721           }
 722     }
 723 
 724     DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n"));
 725 
 726     for (i = 0; i < 4; ++i)
 727       {
 728           unsigned char cmd[10];
 729           static buffer[512];
 730           
 731           cmd[0] = READ_10;
 732           cmd[1] = 0;
 733           xany2scsi(cmd+2, i);
 734           cmd[6] = 0;
 735           cmd[7] = 0;
 736           cmd[8] = 1;
 737           cmd[9] = 0;
 738           aha1542_command(0, cmd, buffer, 512);
 739       }
 740 #endif
 741     aha1542_host = hostnum;
 742     return 1;
 743 }
 744 
 745 /* The abort command does not leave the device in a clean state where
 746    it is available to be used again.  Until this gets worked out, we will
 747    leave it commented out.  */
 748 
 749 int aha1542_abort(Scsi_Cmnd * SCpnt, int i)
     /* [previous][next][first][last][top][bottom][index][help] */
 750 {
 751 #if 0
 752     unchar ahacmd = CMD_START_SCSI;
 753     int mbo;
 754 #endif
 755     DEB(printk("aha1542_abort\n"));
 756 #if 0
 757     cli();
 758     for(mbo = 0; mbo < AHA1542_MAILBOXES; mbo++)
 759       if (SCpnt == SCint[mbo]){
 760         mb[mbo].status = 2;  /* Abort command */
 761         aha1542_out(&ahacmd, 1);                /* start scsi command */
 762         sti();
 763         break;
 764       };
 765 #endif
 766     return 0;
 767 }
 768 
 769 int aha1542_reset(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 770 {
 771     DEB(printk("aha1542_reset called\n"));
 772     return 0;
 773 }
 774 
 775 int aha1542_biosparam(int size, int dev, int* info){
     /* [previous][next][first][last][top][bottom][index][help] */
 776   info[0] = 64;
 777   info[1] = 32;
 778   info[2] = size >> 11;
 779 /*  if (info[2] >= 1024) info[2] = 1024; */
 780   return 0;
 781 }

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