root/drivers/scsi/aha1740.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ecb_dma_to_cpu
  2. ecb_cpu_to_dma
  3. aha1740_show_info
  4. aha1740_makecode
  5. aha1740_test_port
  6. aha1740_intr_handle
  7. aha1740_queuecommand_lck
  8. DEF_SCSI_QCMD
  9. aha1740_biosparam
  10. aha1740_eh_abort_handler
  11. aha1740_probe
  12. aha1740_remove
  13. aha1740_init
  14. aha1740_exit

   1 /*  $Id$
   2  *  1993/03/31
   3  *  linux/kernel/aha1740.c
   4  *
   5  *  Based loosely on aha1542.c which is
   6  *  Copyright (C) 1992  Tommy Thorn and
   7  *  Modified by Eric Youngdale
   8  *
   9  *  This file is aha1740.c, written and
  10  *  Copyright (C) 1992,1993  Brad McLean
  11  *  brad@saturn.gaylord.com or brad@bradpc.gaylord.com.
  12  *  
  13  *  Modifications to makecode and queuecommand
  14  *  for proper handling of multiple devices courteously
  15  *  provided by Michael Weller, March, 1993
  16  *
  17  *  Multiple adapter support, extended translation detection,
  18  *  update to current scsi subsystem changes, proc fs support,
  19  *  working (!) module support based on patches from Andreas Arens,
  20  *  by Andreas Degert <ad@papyrus.hamburg.com>, 2/1997
  21  *
  22  * aha1740_makecode may still need even more work
  23  * if it doesn't work for your devices, take a look.
  24  *
  25  * Reworked for new_eh and new locking by Alan Cox <alan@lxorguk.ukuu.org.uk>
  26  *
  27  * Converted to EISA and generic DMA APIs by Marc Zyngier
  28  * <maz@wild-wind.fr.eu.org>, 4/2003.
  29  *
  30  * Shared interrupt support added by Rask Ingemann Lambertsen
  31  * <rask@sygehus.dk>, 10/2003
  32  *
  33  * For the avoidance of doubt the "preferred form" of this code is one which
  34  * is in an open non patent encumbered format. Where cryptographic key signing
  35  * forms part of the process of creating an executable the information
  36  * including keys needed to generate an equivalently functional executable
  37  * are deemed to be part of the source code.
  38  */
  39 
  40 #include <linux/blkdev.h>
  41 #include <linux/interrupt.h>
  42 #include <linux/module.h>
  43 #include <linux/kernel.h>
  44 #include <linux/types.h>
  45 #include <linux/string.h>
  46 #include <linux/ioport.h>
  47 #include <linux/proc_fs.h>
  48 #include <linux/stat.h>
  49 #include <linux/init.h>
  50 #include <linux/device.h>
  51 #include <linux/eisa.h>
  52 #include <linux/dma-mapping.h>
  53 #include <linux/gfp.h>
  54 
  55 #include <asm/dma.h>
  56 #include <asm/io.h>
  57 
  58 #include "scsi.h"
  59 #include <scsi/scsi_host.h>
  60 #include "aha1740.h"
  61 
  62 /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH
  63    IT WORK, THEN:
  64 #define DEBUG
  65 */
  66 #ifdef DEBUG
  67 #define DEB(x) x
  68 #else
  69 #define DEB(x)
  70 #endif
  71 
  72 struct aha1740_hostdata {
  73         struct eisa_device *edev;
  74         unsigned int translation;
  75         unsigned int last_ecb_used;
  76         dma_addr_t ecb_dma_addr;
  77         struct ecb ecb[AHA1740_ECBS];
  78 };
  79 
  80 struct aha1740_sg {
  81         struct aha1740_chain sg_chain[AHA1740_SCATTER];
  82         dma_addr_t sg_dma_addr;
  83         dma_addr_t buf_dma_addr;
  84 };
  85 
  86 #define HOSTDATA(host) ((struct aha1740_hostdata *) &host->hostdata)
  87 
  88 static inline struct ecb *ecb_dma_to_cpu (struct Scsi_Host *host,
  89                                           dma_addr_t dma)
  90 {
  91         struct aha1740_hostdata *hdata = HOSTDATA (host);
  92         dma_addr_t offset;
  93 
  94         offset = dma - hdata->ecb_dma_addr;
  95 
  96         return (struct ecb *)(((char *) hdata->ecb) + (unsigned int) offset);
  97 }
  98 
  99 static inline dma_addr_t ecb_cpu_to_dma (struct Scsi_Host *host, void *cpu)
 100 {
 101         struct aha1740_hostdata *hdata = HOSTDATA (host);
 102         dma_addr_t offset;
 103     
 104         offset = (char *) cpu - (char *) hdata->ecb;
 105 
 106         return hdata->ecb_dma_addr + offset;
 107 }
 108 
 109 static int aha1740_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
 110 {
 111         struct aha1740_hostdata *host = HOSTDATA(shpnt);
 112         seq_printf(m, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n"
 113                       "Extended translation %sabled.\n",
 114                       shpnt->io_port, shpnt->irq, host->edev->slot,
 115                       host->translation ? "en" : "dis");
 116         return 0;
 117 }
 118 
 119 static int aha1740_makecode(unchar *sense, unchar *status)
 120 {
 121         struct statusword
 122         {
 123                 ushort  don:1,  /* Command Done - No Error */
 124                         du:1,   /* Data underrun */
 125                     :1, qf:1,   /* Queue full */
 126                         sc:1,   /* Specification Check */
 127                         dor:1,  /* Data overrun */
 128                         ch:1,   /* Chaining Halted */
 129                         intr:1, /* Interrupt issued */
 130                         asa:1,  /* Additional Status Available */
 131                         sns:1,  /* Sense information Stored */
 132                     :1, ini:1,  /* Initialization Required */
 133                         me:1,   /* Major error or exception */
 134                     :1, eca:1,  /* Extended Contingent alliance */
 135                     :1;
 136         } status_word;
 137         int retval = DID_OK;
 138 
 139         status_word = * (struct statusword *) status;
 140 #ifdef DEBUG
 141         printk("makecode from %x,%x,%x,%x %x,%x,%x,%x",
 142                status[0], status[1], status[2], status[3],
 143                sense[0], sense[1], sense[2], sense[3]);
 144 #endif
 145         if (!status_word.don) { /* Anything abnormal was detected */
 146                 if ( (status[1]&0x18) || status_word.sc ) {
 147                         /*Additional info available*/
 148                         /* Use the supplied info for further diagnostics */
 149                         switch ( status[2] ) {
 150                         case 0x12:
 151                                 if ( status_word.dor )
 152                                         retval=DID_ERROR; /* It's an Overrun */
 153                                 /* If not overrun, assume underrun and
 154                                  * ignore it! */
 155                         case 0x00: /* No info, assume no error, should
 156                                     * not occur */
 157                                 break;
 158                         case 0x11:
 159                         case 0x21:
 160                                 retval=DID_TIME_OUT;
 161                                 break;
 162                         case 0x0a:
 163                                 retval=DID_BAD_TARGET;
 164                                 break;
 165                         case 0x04:
 166                         case 0x05:
 167                                 retval=DID_ABORT;
 168                                 /* Either by this driver or the
 169                                  * AHA1740 itself */
 170                                 break;
 171                         default:
 172                                 retval=DID_ERROR; /* No further
 173                                                    * diagnostics
 174                                                    * possible */
 175                         }
 176                 } else {
 177                         /* Michael suggests, and Brad concurs: */
 178                         if ( status_word.qf ) {
 179                                 retval = DID_TIME_OUT; /* forces a redo */
 180                                 /* I think this specific one should
 181                                  * not happen -Brad */
 182                                 printk("aha1740.c: WARNING: AHA1740 queue overflow!\n");
 183                         } else
 184                                 if ( status[0]&0x60 ) {
 185                                          /* Didn't find a better error */
 186                                         retval = DID_ERROR;
 187                                 }
 188                         /* In any other case return DID_OK so for example
 189                            CONDITION_CHECKS make it through to the appropriate
 190                            device driver */
 191                 }
 192         }
 193         /* Under all circumstances supply the target status -Michael */
 194         return status[3] | retval << 16;
 195 }
 196 
 197 static int aha1740_test_port(unsigned int base)
 198 {
 199         if ( inb(PORTADR(base)) & PORTADDR_ENH )
 200                 return 1;   /* Okay, we're all set */
 201         
 202         printk("aha174x: Board detected, but not in enhanced mode, so disabled it.\n");
 203         return 0;
 204 }
 205 
 206 /* A "high" level interrupt handler */
 207 static irqreturn_t aha1740_intr_handle(int irq, void *dev_id)
 208 {
 209         struct Scsi_Host *host = (struct Scsi_Host *) dev_id;
 210         void (*my_done)(struct scsi_cmnd *);
 211         int errstatus, adapstat;
 212         int number_serviced;
 213         struct ecb *ecbptr;
 214         struct scsi_cmnd *SCtmp;
 215         unsigned int base;
 216         unsigned long flags;
 217         int handled = 0;
 218         struct aha1740_sg *sgptr;
 219         struct eisa_device *edev;
 220         
 221         if (!host)
 222                 panic("aha1740.c: Irq from unknown host!\n");
 223         spin_lock_irqsave(host->host_lock, flags);
 224         base = host->io_port;
 225         number_serviced = 0;
 226         edev = HOSTDATA(host)->edev;
 227 
 228         while(inb(G2STAT(base)) & G2STAT_INTPEND) {
 229                 handled = 1;
 230                 DEB(printk("aha1740_intr top of loop.\n"));
 231                 adapstat = inb(G2INTST(base));
 232                 ecbptr = ecb_dma_to_cpu (host, inl(MBOXIN0(base)));
 233                 outb(G2CNTRL_IRST,G2CNTRL(base)); /* interrupt reset */
 234       
 235                 switch ( adapstat & G2INTST_MASK ) {
 236                 case    G2INTST_CCBRETRY:
 237                 case    G2INTST_CCBERROR:
 238                 case    G2INTST_CCBGOOD:
 239                         /* Host Ready -> Mailbox in complete */
 240                         outb(G2CNTRL_HRDY,G2CNTRL(base));
 241                         if (!ecbptr) {
 242                                 printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n",
 243                                        inb(G2STAT(base)),adapstat,
 244                                        inb(G2INTST(base)), number_serviced++);
 245                                 continue;
 246                         }
 247                         SCtmp = ecbptr->SCpnt;
 248                         if (!SCtmp) {
 249                                 printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n",
 250                                        inb(G2STAT(base)),adapstat,
 251                                        inb(G2INTST(base)), number_serviced++);
 252                                 continue;
 253                         }
 254                         sgptr = (struct aha1740_sg *) SCtmp->host_scribble;
 255                         scsi_dma_unmap(SCtmp);
 256 
 257                         /* Free the sg block */
 258                         dma_free_coherent (&edev->dev,
 259                                            sizeof (struct aha1740_sg),
 260                                            SCtmp->host_scribble,
 261                                            sgptr->sg_dma_addr);
 262             
 263                         /* Fetch the sense data, and tuck it away, in
 264                            the required slot.  The Adaptec
 265                            automatically fetches it, and there is no
 266                            guarantee that we will still have it in the
 267                            cdb when we come back */
 268                         if ( (adapstat & G2INTST_MASK) == G2INTST_CCBERROR ) {
 269                                 memcpy(SCtmp->sense_buffer, ecbptr->sense, 
 270                                        SCSI_SENSE_BUFFERSIZE);
 271                                 errstatus = aha1740_makecode(ecbptr->sense,ecbptr->status);
 272                         } else
 273                                 errstatus = 0;
 274                         DEB(if (errstatus)
 275                             printk("aha1740_intr_handle: returning %6x\n",
 276                                    errstatus));
 277                         SCtmp->result = errstatus;
 278                         my_done = ecbptr->done;
 279                         memset(ecbptr,0,sizeof(struct ecb)); 
 280                         if ( my_done )
 281                                 my_done(SCtmp);
 282                         break;
 283                         
 284                 case    G2INTST_HARDFAIL:
 285                         printk(KERN_ALERT "aha1740 hardware failure!\n");
 286                         panic("aha1740.c");     /* Goodbye */
 287                         
 288                 case    G2INTST_ASNEVENT:
 289                         printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n",
 290                                adapstat,
 291                                inb(MBOXIN0(base)),
 292                                inb(MBOXIN1(base)),
 293                                inb(MBOXIN2(base)),
 294                                inb(MBOXIN3(base))); /* Say What? */
 295                         /* Host Ready -> Mailbox in complete */
 296                         outb(G2CNTRL_HRDY,G2CNTRL(base));
 297                         break;
 298                         
 299                 case    G2INTST_CMDGOOD:
 300                         /* set immediate command success flag here: */
 301                         break;
 302                         
 303                 case    G2INTST_CMDERROR:
 304                         /* Set immediate command failure flag here: */
 305                         break;
 306                 }
 307                 number_serviced++;
 308         }
 309 
 310         spin_unlock_irqrestore(host->host_lock, flags);
 311         return IRQ_RETVAL(handled);
 312 }
 313 
 314 static int aha1740_queuecommand_lck(struct scsi_cmnd * SCpnt,
 315                                     void (*done)(struct scsi_cmnd *))
 316 {
 317         unchar direction;
 318         unchar *cmd = (unchar *) SCpnt->cmnd;
 319         unchar target = scmd_id(SCpnt);
 320         struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host);
 321         unsigned long flags;
 322         dma_addr_t sg_dma;
 323         struct aha1740_sg *sgptr;
 324         int ecbno, nseg;
 325         DEB(int i);
 326 
 327         if(*cmd == REQUEST_SENSE) {
 328                 SCpnt->result = 0;
 329                 done(SCpnt); 
 330                 return 0;
 331         }
 332 
 333 #ifdef DEBUG
 334         if (*cmd == READ_10 || *cmd == WRITE_10)
 335                 i = xscsi2int(cmd+2);
 336         else if (*cmd == READ_6 || *cmd == WRITE_6)
 337                 i = scsi2int(cmd+2);
 338         else
 339                 i = -1;
 340         printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",
 341                target, *cmd, i, bufflen);
 342         printk("scsi cmd:");
 343         for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
 344         printk("\n");
 345 #endif
 346 
 347         /* locate an available ecb */
 348         spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
 349         ecbno = host->last_ecb_used + 1; /* An optimization */
 350         if (ecbno >= AHA1740_ECBS)
 351                 ecbno = 0;
 352         do {
 353                 if (!host->ecb[ecbno].cmdw)
 354                         break;
 355                 ecbno++;
 356                 if (ecbno >= AHA1740_ECBS)
 357                         ecbno = 0;
 358         } while (ecbno != host->last_ecb_used);
 359 
 360         if (host->ecb[ecbno].cmdw)
 361                 panic("Unable to find empty ecb for aha1740.\n");
 362 
 363         host->ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command
 364                                                     doubles as reserved flag */
 365 
 366         host->last_ecb_used = ecbno;    
 367         spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
 368 
 369 #ifdef DEBUG
 370         printk("Sending command (%d %x)...", ecbno, done);
 371 #endif
 372 
 373         host->ecb[ecbno].cdblen = SCpnt->cmd_len; /* SCSI Command
 374                                                    * Descriptor Block
 375                                                    * Length */
 376 
 377         direction = 0;
 378         if (*cmd == READ_10 || *cmd == READ_6)
 379                 direction = 1;
 380         else if (*cmd == WRITE_10 || *cmd == WRITE_6)
 381                 direction = 0;
 382 
 383         memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len);
 384 
 385         SCpnt->host_scribble = dma_alloc_coherent (&host->edev->dev,
 386                                                    sizeof (struct aha1740_sg),
 387                                                    &sg_dma, GFP_ATOMIC);
 388         if(SCpnt->host_scribble == NULL) {
 389                 printk(KERN_WARNING "aha1740: out of memory in queuecommand!\n");
 390                 return 1;
 391         }
 392         sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
 393         sgptr->sg_dma_addr = sg_dma;
 394 
 395         nseg = scsi_dma_map(SCpnt);
 396         BUG_ON(nseg < 0);
 397         if (nseg) {
 398                 struct scatterlist *sg;
 399                 struct aha1740_chain * cptr;
 400                 int i;
 401                 DEB(unsigned char * ptr);
 402 
 403                 host->ecb[ecbno].sg = 1;  /* SCSI Initiator Command
 404                                            * w/scatter-gather*/
 405                 cptr = sgptr->sg_chain;
 406                 scsi_for_each_sg(SCpnt, sg, nseg, i) {
 407                         cptr[i].datalen = sg_dma_len (sg);
 408                         cptr[i].dataptr = sg_dma_address (sg);
 409                 }
 410                 host->ecb[ecbno].datalen = nseg * sizeof(struct aha1740_chain);
 411                 host->ecb[ecbno].dataptr = sg_dma;
 412 #ifdef DEBUG
 413                 printk("cptr %x: ",cptr);
 414                 ptr = (unsigned char *) cptr;
 415                 for(i=0;i<24;i++) printk("%02x ", ptr[i]);
 416 #endif
 417         } else {
 418                 host->ecb[ecbno].datalen = 0;
 419                 host->ecb[ecbno].dataptr = 0;
 420         }
 421         host->ecb[ecbno].lun = SCpnt->device->lun;
 422         host->ecb[ecbno].ses = 1; /* Suppress underrun errors */
 423         host->ecb[ecbno].dir = direction;
 424         host->ecb[ecbno].ars = 1; /* Yes, get the sense on an error */
 425         host->ecb[ecbno].senselen = 12;
 426         host->ecb[ecbno].senseptr = ecb_cpu_to_dma (SCpnt->device->host,
 427                                                     host->ecb[ecbno].sense);
 428         host->ecb[ecbno].statusptr = ecb_cpu_to_dma (SCpnt->device->host,
 429                                                      host->ecb[ecbno].status);
 430         host->ecb[ecbno].done = done;
 431         host->ecb[ecbno].SCpnt = SCpnt;
 432 #ifdef DEBUG
 433         {
 434                 int i;
 435                 printk("aha1740_command: sending.. ");
 436                 for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++)
 437                         printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]);
 438         }
 439         printk("\n");
 440 #endif
 441         if (done) {
 442         /* The Adaptec Spec says the card is so fast that the loops
 443            will only be executed once in the code below. Even if this
 444            was true with the fastest processors when the spec was
 445            written, it doesn't seem to be true with today's fast
 446            processors. We print a warning if the code is executed more
 447            often than LOOPCNT_WARN. If this happens, it should be
 448            investigated. If the count reaches LOOPCNT_MAX, we assume
 449            something is broken; since there is no way to return an
 450            error (the return value is ignored by the mid-level scsi
 451            layer) we have to panic (and maybe that's the best thing we
 452            can do then anyhow). */
 453 
 454 #define LOOPCNT_WARN 10         /* excessive mbxout wait -> syslog-msg */
 455 #define LOOPCNT_MAX 1000000     /* mbxout deadlock -> panic() after ~ 2 sec. */
 456                 int loopcnt;
 457                 unsigned int base = SCpnt->device->host->io_port;
 458                 DEB(printk("aha1740[%d] critical section\n",ecbno));
 459 
 460                 spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
 461                 for (loopcnt = 0; ; loopcnt++) {
 462                         if (inb(G2STAT(base)) & G2STAT_MBXOUT) break;
 463                         if (loopcnt == LOOPCNT_WARN) {
 464                                 printk("aha1740[%d]_mbxout wait!\n",ecbno);
 465                         }
 466                         if (loopcnt == LOOPCNT_MAX)
 467                                 panic("aha1740.c: mbxout busy!\n");
 468                 }
 469                 outl (ecb_cpu_to_dma (SCpnt->device->host, host->ecb + ecbno),
 470                       MBOXOUT0(base));
 471                 for (loopcnt = 0; ; loopcnt++) {
 472                         if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break;
 473                         if (loopcnt == LOOPCNT_WARN) {
 474                                 printk("aha1740[%d]_attn wait!\n",ecbno);
 475                         }
 476                         if (loopcnt == LOOPCNT_MAX)
 477                                 panic("aha1740.c: attn wait failed!\n");
 478                 }
 479                 outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */
 480                 spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
 481                 DEB(printk("aha1740[%d] request queued.\n",ecbno));
 482         } else
 483                 printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
 484         return 0;
 485 }
 486 
 487 static DEF_SCSI_QCMD(aha1740_queuecommand)
 488 
 489 /* Query the board for its irq_level and irq_type.  Nothing else matters
 490    in enhanced mode on an EISA bus. */
 491 
 492 static void aha1740_getconfig(unsigned int base, unsigned int *irq_level,
 493                               unsigned int *irq_type,
 494                               unsigned int *translation)
 495 {
 496         static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
 497 
 498         *irq_level = intab[inb(INTDEF(base)) & 0x7];
 499         *irq_type  = (inb(INTDEF(base)) & 0x8) >> 3;
 500         *translation = inb(RESV1(base)) & 0x1;
 501         outb(inb(INTDEF(base)) | 0x10, INTDEF(base));
 502 }
 503 
 504 static int aha1740_biosparam(struct scsi_device *sdev,
 505                              struct block_device *dev,
 506                              sector_t capacity, int* ip)
 507 {
 508         int size = capacity;
 509         int extended = HOSTDATA(sdev->host)->translation;
 510 
 511         DEB(printk("aha1740_biosparam\n"));
 512         if (extended && (ip[2] > 1024)) {
 513                 ip[0] = 255;
 514                 ip[1] = 63;
 515                 ip[2] = size / (255 * 63);
 516         } else {
 517                 ip[0] = 64;
 518                 ip[1] = 32;
 519                 ip[2] = size >> 11;
 520         }
 521         return 0;
 522 }
 523 
 524 static int aha1740_eh_abort_handler (struct scsi_cmnd *dummy)
 525 {
 526 /*
 527  * From Alan Cox :
 528  * The AHA1740 has firmware handled abort/reset handling. The "head in
 529  * sand" kernel code is correct for once 8)
 530  *
 531  * So we define a dummy handler just to keep the kernel SCSI code as
 532  * quiet as possible...
 533  */
 534 
 535         return SUCCESS;
 536 }
 537 
 538 static struct scsi_host_template aha1740_template = {
 539         .module           = THIS_MODULE,
 540         .proc_name        = "aha1740",
 541         .show_info        = aha1740_show_info,
 542         .name             = "Adaptec 174x (EISA)",
 543         .queuecommand     = aha1740_queuecommand,
 544         .bios_param       = aha1740_biosparam,
 545         .can_queue        = AHA1740_ECBS,
 546         .this_id          = 7,
 547         .sg_tablesize     = AHA1740_SCATTER,
 548         .eh_abort_handler = aha1740_eh_abort_handler,
 549 };
 550 
 551 static int aha1740_probe (struct device *dev)
 552 {
 553         int slotbase, rc;
 554         unsigned int irq_level, irq_type, translation;
 555         struct Scsi_Host *shpnt;
 556         struct aha1740_hostdata *host;
 557         struct eisa_device *edev = to_eisa_device (dev);
 558 
 559         DEB(printk("aha1740_probe: \n"));
 560         
 561         slotbase = edev->base_addr + EISA_VENDOR_ID_OFFSET;
 562         if (!request_region(slotbase, SLOTSIZE, "aha1740")) /* See if in use */
 563                 return -EBUSY;
 564         if (!aha1740_test_port(slotbase))
 565                 goto err_release_region;
 566         aha1740_getconfig(slotbase,&irq_level,&irq_type,&translation);
 567         if ((inb(G2STAT(slotbase)) &
 568              (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) {
 569                 /* If the card isn't ready, hard reset it */
 570                 outb(G2CNTRL_HRST, G2CNTRL(slotbase));
 571                 outb(0, G2CNTRL(slotbase));
 572         }
 573         printk(KERN_INFO "Configuring slot %d at IO:%x, IRQ %u (%s)\n",
 574                edev->slot, slotbase, irq_level, irq_type ? "edge" : "level");
 575         printk(KERN_INFO "aha174x: Extended translation %sabled.\n",
 576                translation ? "en" : "dis");
 577         shpnt = scsi_host_alloc(&aha1740_template,
 578                               sizeof(struct aha1740_hostdata));
 579         if(shpnt == NULL)
 580                 goto err_release_region;
 581 
 582         shpnt->base = 0;
 583         shpnt->io_port = slotbase;
 584         shpnt->n_io_port = SLOTSIZE;
 585         shpnt->irq = irq_level;
 586         shpnt->dma_channel = 0xff;
 587         host = HOSTDATA(shpnt);
 588         host->edev = edev;
 589         host->translation = translation;
 590         host->ecb_dma_addr = dma_map_single (&edev->dev, host->ecb,
 591                                              sizeof (host->ecb),
 592                                              DMA_BIDIRECTIONAL);
 593         if (!host->ecb_dma_addr) {
 594                 printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n");
 595                 scsi_host_put (shpnt);
 596                 goto err_host_put;
 597         }
 598         
 599         DEB(printk("aha1740_probe: enable interrupt channel %d\n",irq_level));
 600         if (request_irq(irq_level,aha1740_intr_handle,irq_type ? 0 : IRQF_SHARED,
 601                         "aha1740",shpnt)) {
 602                 printk(KERN_ERR "aha1740_probe: Unable to allocate IRQ %d.\n",
 603                        irq_level);
 604                 goto err_unmap;
 605         }
 606 
 607         eisa_set_drvdata (edev, shpnt);
 608 
 609         rc = scsi_add_host (shpnt, dev);
 610         if (rc)
 611                 goto err_irq;
 612 
 613         scsi_scan_host (shpnt);
 614         return 0;
 615 
 616  err_irq:
 617         free_irq(irq_level, shpnt);
 618  err_unmap:
 619         dma_unmap_single (&edev->dev, host->ecb_dma_addr,
 620                           sizeof (host->ecb), DMA_BIDIRECTIONAL);
 621  err_host_put:
 622         scsi_host_put (shpnt);
 623  err_release_region:
 624         release_region(slotbase, SLOTSIZE);
 625 
 626         return -ENODEV;
 627 }
 628 
 629 static int aha1740_remove (struct device *dev)
 630 {
 631         struct Scsi_Host *shpnt = dev_get_drvdata(dev);
 632         struct aha1740_hostdata *host = HOSTDATA (shpnt);
 633 
 634         scsi_remove_host(shpnt);
 635         
 636         free_irq (shpnt->irq, shpnt);
 637         dma_unmap_single (dev, host->ecb_dma_addr,
 638                           sizeof (host->ecb), DMA_BIDIRECTIONAL);
 639         release_region (shpnt->io_port, SLOTSIZE);
 640 
 641         scsi_host_put (shpnt);
 642         
 643         return 0;
 644 }
 645 
 646 static struct eisa_device_id aha1740_ids[] = {
 647         { "ADP0000" },          /* 1740  */
 648         { "ADP0001" },          /* 1740A */
 649         { "ADP0002" },          /* 1742A */
 650         { "ADP0400" },          /* 1744  */
 651         { "" }
 652 };
 653 MODULE_DEVICE_TABLE(eisa, aha1740_ids);
 654 
 655 static struct eisa_driver aha1740_driver = {
 656         .id_table = aha1740_ids,
 657         .driver   = {
 658                 .name    = "aha1740",
 659                 .probe   = aha1740_probe,
 660                 .remove  = aha1740_remove,
 661         },
 662 };
 663 
 664 static __init int aha1740_init (void)
 665 {
 666         return eisa_driver_register (&aha1740_driver);
 667 }
 668 
 669 static __exit void aha1740_exit (void)
 670 {
 671         eisa_driver_unregister (&aha1740_driver);
 672 }
 673 
 674 module_init (aha1740_init);
 675 module_exit (aha1740_exit);
 676 
 677 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */