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 
 301       if (!SCtmp || !SCtmp->scsi_done) {
 302         printk("aha1542_intr_handle: Unexpected interrupt\n");
 303         return;
 304       }
 305       
 306       my_done = SCtmp->scsi_done;
 307       if (SCtmp->host_scribble) scsi_free(SCtmp->host_scribble, 512);
 308       
 309       /* Fetch the sense data, and tuck it away, in the required slot.  The
 310          Adaptec automatically fetches it, and there is no guarantee that
 311          we will still have it in the cdb when we come back */
 312       if (ccb[mbo].tarstat == 2)
 313         memcpy(SCtmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen], 
 314                sizeof(SCtmp->sense_buffer));
 315       
 316       
 317       /* is there mail :-) */
 318       
 319       /* more error checking left out here */
 320       if (mbistatus != 1)
 321         /* This is surely wrong, but I don't know what's right */
 322         errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);
 323       else
 324         errstatus = 0;
 325       
 326 #ifdef DEBUG
 327       if(errstatus) printk("(aha1542 error:%x %x %x) ",errstatus, 
 328                            ccb[mbo].hastat, ccb[mbo].tarstat);
 329 #endif
 330 
 331       if (ccb[mbo].tarstat == 2) {
 332 #ifdef DEBUG
 333         int i;
 334 #endif
 335         DEB(printk("aha1542_intr_handle: sense:"));
 336 #ifdef DEBUG
 337         for (i = 0; i < 12; i++)
 338           printk("%02x ", ccb[mbo].cdb[ccb[mbo].cdblen+i]);
 339         printk("\n");
 340 #endif
 341         /*
 342           DEB(printk("aha1542_intr_handle: buf:"));
 343           for (i = 0; i < bufflen; i++)
 344           printk("%02x ", ((unchar *)buff)[i]);
 345           printk("\n");
 346           */
 347       }
 348       DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));
 349       SCtmp->result = errstatus;
 350       SCint[mbo] = NULL;  /* This effectively frees up the mailbox slot, as
 351                              far as queuecommand is concerned */
 352       my_done(SCtmp);
 353       number_serviced++;
 354     };
 355 }
 356 
 357 int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
 358 {
 359     unchar ahacmd = CMD_START_SCSI;
 360     unchar direction;
 361     unchar *cmd = (unchar *) SCpnt->cmnd;
 362     unchar target = SCpnt->target;
 363     unchar lun = SCpnt->lun;
 364     void *buff = SCpnt->request_buffer;
 365     int bufflen = SCpnt->request_bufflen;
 366     int mbo;
 367 
 368     DEB(int i);
 369 
 370     DEB(if (target > 1) {
 371       SCpnt->result = DID_TIME_OUT << 16;
 372       done(SCpnt); return 0;});
 373     
 374     if(*cmd == REQUEST_SENSE){
 375 #ifndef DEBUG
 376       if (bufflen != 16) {
 377         printk("Wrong buffer length supplied for request sense (%d)\n",bufflen);
 378         panic("aha1542.c");
 379       };
 380 #endif
 381       SCpnt->result = 0;
 382       done(SCpnt); 
 383       return 0;
 384     };
 385 
 386 #ifdef DEBUG
 387     if (*cmd == READ_10 || *cmd == WRITE_10)
 388       i = xscsi2int(cmd+2);
 389     else if (*cmd == READ_6 || *cmd == WRITE_6)
 390       i = scsi2int(cmd+2);
 391     else
 392       i = -1;
 393     if (done)
 394       printk("aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
 395     else
 396       printk("aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);
 397     aha1542_stat();
 398     printk("aha1542_queuecommand: dumping scsi cmd:");
 399     for (i = 0; i < (*cmd<=0x1f?6:10); i++) printk("%02x ", cmd[i]);
 400     printk("\n");
 401     if (*cmd == WRITE_10 || *cmd == WRITE_6)
 402       return 0; /* we are still testing, so *don't* write */
 403 #endif
 404 /* Use the outgoing mailboxes in a round-robin fashion, because this
 405    is how the host adapter will scan for them */
 406 
 407     cli();
 408     mbo = aha1542_last_mbo_used + 1;
 409     if (mbo >= AHA1542_MAILBOXES) mbo = 0;
 410 
 411     do{
 412       if(mb[mbo].status == 0 && SCint[mbo] == NULL)
 413         break;
 414       mbo++;
 415       if (mbo >= AHA1542_MAILBOXES) mbo = 0;
 416     } while (mbo != aha1542_last_mbo_used);
 417 
 418     if(mb[mbo].status || SCint[mbo])
 419       panic("Unable to find empty mailbox for aha1542.\n");
 420 
 421     SCint[mbo] = SCpnt;  /* This will effectively prevent someone else from
 422                             screwing with this cdb. */
 423 
 424     aha1542_last_mbo_used = mbo;    
 425     sti();
 426 
 427 #ifdef DEBUG
 428     printk("Sending command (%d %x)...",mbo, done);
 429 #endif
 430 
 431     memset(&ccb[mbo], 0, sizeof(struct ccb));
 432 
 433     ccb[mbo].cdblen = (*cmd<=0x1f)?6:10;        /* SCSI Command Descriptor Block Length */
 434 
 435     direction = 0;
 436     if (*cmd == READ_10 || *cmd == READ_6)
 437         direction = 8;
 438     else if (*cmd == WRITE_10 || *cmd == WRITE_6)
 439         direction = 16;
 440 
 441     memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);
 442 
 443     if (SCpnt->use_sg) {
 444       struct scatterlist * sgpnt;
 445       struct chain * cptr;
 446 #ifdef DEBUG
 447       unsigned char * ptr;
 448 #endif
 449       int i;
 450       ccb[mbo].op = 2;        /* SCSI Initiator Command  w/scatter-gather*/
 451       SCpnt->host_scribble = scsi_malloc(512);
 452       sgpnt = (struct scatterlist *) SCpnt->request_buffer;
 453       cptr = (struct chain *) SCpnt->host_scribble; 
 454       if (cptr == NULL) panic("aha1542.c: unable to allocate DMA memory\n");
 455       for(i=0; i<SCpnt->use_sg; i++) {
 456         if(sgpnt[i].length == 0 || SCpnt->use_sg > 16 || 
 457            (((int)sgpnt[i].address) & 1) || (sgpnt[i].length & 1)){
 458           unsigned char * ptr;
 459           printk("Bad segment list supplied to aha1542.c (%d, %d)\n",SCpnt->use_sg,i);
 460           for(i=0;i<SCpnt->use_sg++;i++){
 461             printk("%d: %x %x %d\n",i,sgpnt[i].address, sgpnt[i].alt_address,
 462                    sgpnt[i].length);
 463           };
 464           printk("cptr %x: ",cptr);
 465           ptr = (unsigned char *) &cptr[i];
 466           for(i=0;i<18;i++) printk("%02x ", ptr[i]);
 467           panic("Foooooooood fight!");
 468         };
 469         any2scsi(cptr[i].dataptr, sgpnt[i].address);
 470         any2scsi(cptr[i].datalen, sgpnt[i].length);
 471       };
 472       any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));
 473       any2scsi(ccb[mbo].dataptr, cptr);
 474 #ifdef DEBUG
 475       printk("cptr %x: ",cptr);
 476       ptr = (unsigned char *) cptr;
 477       for(i=0;i<18;i++) printk("%02x ", ptr[i]);
 478 #endif
 479     } else {
 480       ccb[mbo].op = 0;        /* SCSI Initiator Command */
 481       SCpnt->host_scribble = NULL;
 482       any2scsi(ccb[mbo].datalen, bufflen);
 483       any2scsi(ccb[mbo].dataptr, buff);
 484     };
 485     ccb[mbo].idlun = (target&7)<<5 | direction | (lun & 7); /*SCSI Target Id*/
 486     ccb[mbo].rsalen = 12;
 487     ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;
 488     ccb[mbo].commlinkid = 0;
 489 
 490 #ifdef DEBUGd
 491     { int i;
 492     printk("aha1542_command: sending.. ");
 493     for (i = 0; i < sizeof(ccb[mbo])-10; i++)
 494       printk("%02x ", ((unchar *)&ccb[mbo])[i]);
 495     };
 496 #endif
 497     
 498     if (done) {
 499         DEB(printk("aha1542_queuecommand: now waiting for interrupt "); aha1542_stat());
 500         SCpnt->scsi_done = done;
 501         mb[mbo].status = 1;
 502         aha1542_out(&ahacmd, 1);                /* start scsi command */
 503         DEB(aha1542_stat());
 504     }
 505     else
 506       printk("aha1542_queuecommand: done can't be NULL\n");
 507     
 508     return 0;
 509 }
 510 
 511 static volatile int internal_done_flag = 0;
 512 static volatile int internal_done_errcode = 0;
 513 static void internal_done(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 514 {
 515     internal_done_errcode = SCpnt->result;
 516     ++internal_done_flag;
 517 }
 518 
 519 int aha1542_command(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 520 {
 521     DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));
 522 
 523     aha1542_queuecommand(SCpnt, internal_done);
 524 
 525     while (!internal_done_flag);
 526     internal_done_flag = 0;
 527     return internal_done_errcode;
 528 }
 529 
 530 /* Initialize mailboxes */
 531 static void setup_mailboxes()
     /* [previous][next][first][last][top][bottom][index][help] */
 532 {
 533     int i;
 534     static unchar cmd[5] = {CMD_MBINIT, AHA1542_MAILBOXES};
 535 
 536     for(i=0; i<AHA1542_MAILBOXES; i++){
 537       mb[i].status = mb[AHA1542_MAILBOXES+i].status = 0;
 538       any2scsi(mb[i].ccbptr, &ccb[i]);
 539     };
 540     aha1542_intr_reset();     /* reset interrupts, so they don't block */       
 541     any2scsi((cmd+2), mb);
 542     aha1542_out(cmd, 5);
 543     WAIT(INTRFLAGS, INTRMASK, HACC, 0);
 544     while (0) {
 545       fail:
 546         printk("aha1542_detect: failed setting up mailboxes\n");
 547     }
 548     aha1542_intr_reset();
 549 }
 550 
 551 /* Query the board to find out if it is a 1542 or a 1740, or whatever. */
 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] */