linux/drivers/scsi/aha1740.c
<<
>>
Prefs
   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
  72struct 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
  80struct 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
  88static 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
  99static 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
 109static 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
 119static 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                                break;
 156                        case 0x00: /* No info, assume no error, should
 157                                    * not occur */
 158                                break;
 159                        case 0x11:
 160                        case 0x21:
 161                                retval=DID_TIME_OUT;
 162                                break;
 163                        case 0x0a:
 164                                retval=DID_BAD_TARGET;
 165                                break;
 166                        case 0x04:
 167                        case 0x05:
 168                                retval=DID_ABORT;
 169                                /* Either by this driver or the
 170                                 * AHA1740 itself */
 171                                break;
 172                        default:
 173                                retval=DID_ERROR; /* No further
 174                                                   * diagnostics
 175                                                   * possible */
 176                        }
 177                } else {
 178                        /* Michael suggests, and Brad concurs: */
 179                        if ( status_word.qf ) {
 180                                retval = DID_TIME_OUT; /* forces a redo */
 181                                /* I think this specific one should
 182                                 * not happen -Brad */
 183                                printk("aha1740.c: WARNING: AHA1740 queue overflow!\n");
 184                        } else
 185                                if ( status[0]&0x60 ) {
 186                                         /* Didn't find a better error */
 187                                        retval = DID_ERROR;
 188                                }
 189                        /* In any other case return DID_OK so for example
 190                           CONDITION_CHECKS make it through to the appropriate
 191                           device driver */
 192                }
 193        }
 194        /* Under all circumstances supply the target status -Michael */
 195        return status[3] | retval << 16;
 196}
 197
 198static int aha1740_test_port(unsigned int base)
 199{
 200        if ( inb(PORTADR(base)) & PORTADDR_ENH )
 201                return 1;   /* Okay, we're all set */
 202        
 203        printk("aha174x: Board detected, but not in enhanced mode, so disabled it.\n");
 204        return 0;
 205}
 206
 207/* A "high" level interrupt handler */
 208static irqreturn_t aha1740_intr_handle(int irq, void *dev_id)
 209{
 210        struct Scsi_Host *host = (struct Scsi_Host *) dev_id;
 211        void (*my_done)(struct scsi_cmnd *);
 212        int errstatus, adapstat;
 213        int number_serviced;
 214        struct ecb *ecbptr;
 215        struct scsi_cmnd *SCtmp;
 216        unsigned int base;
 217        unsigned long flags;
 218        int handled = 0;
 219        struct aha1740_sg *sgptr;
 220        struct eisa_device *edev;
 221        
 222        if (!host)
 223                panic("aha1740.c: Irq from unknown host!\n");
 224        spin_lock_irqsave(host->host_lock, flags);
 225        base = host->io_port;
 226        number_serviced = 0;
 227        edev = HOSTDATA(host)->edev;
 228
 229        while(inb(G2STAT(base)) & G2STAT_INTPEND) {
 230                handled = 1;
 231                DEB(printk("aha1740_intr top of loop.\n"));
 232                adapstat = inb(G2INTST(base));
 233                ecbptr = ecb_dma_to_cpu (host, inl(MBOXIN0(base)));
 234                outb(G2CNTRL_IRST,G2CNTRL(base)); /* interrupt reset */
 235      
 236                switch ( adapstat & G2INTST_MASK ) {
 237                case    G2INTST_CCBRETRY:
 238                case    G2INTST_CCBERROR:
 239                case    G2INTST_CCBGOOD:
 240                        /* Host Ready -> Mailbox in complete */
 241                        outb(G2CNTRL_HRDY,G2CNTRL(base));
 242                        if (!ecbptr) {
 243                                printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n",
 244                                       inb(G2STAT(base)),adapstat,
 245                                       inb(G2INTST(base)), number_serviced++);
 246                                continue;
 247                        }
 248                        SCtmp = ecbptr->SCpnt;
 249                        if (!SCtmp) {
 250                                printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n",
 251                                       inb(G2STAT(base)),adapstat,
 252                                       inb(G2INTST(base)), number_serviced++);
 253                                continue;
 254                        }
 255                        sgptr = (struct aha1740_sg *) SCtmp->host_scribble;
 256                        scsi_dma_unmap(SCtmp);
 257
 258                        /* Free the sg block */
 259                        dma_free_coherent (&edev->dev,
 260                                           sizeof (struct aha1740_sg),
 261                                           SCtmp->host_scribble,
 262                                           sgptr->sg_dma_addr);
 263            
 264                        /* Fetch the sense data, and tuck it away, in
 265                           the required slot.  The Adaptec
 266                           automatically fetches it, and there is no
 267                           guarantee that we will still have it in the
 268                           cdb when we come back */
 269                        if ( (adapstat & G2INTST_MASK) == G2INTST_CCBERROR ) {
 270                                memcpy_and_pad(SCtmp->sense_buffer,
 271                                               SCSI_SENSE_BUFFERSIZE,
 272                                               ecbptr->sense,
 273                                               sizeof(ecbptr->sense),
 274                                               0);
 275                                errstatus = aha1740_makecode(ecbptr->sense,ecbptr->status);
 276                        } else
 277                                errstatus = 0;
 278                        DEB(if (errstatus)
 279                            printk("aha1740_intr_handle: returning %6x\n",
 280                                   errstatus));
 281                        SCtmp->result = errstatus;
 282                        my_done = ecbptr->done;
 283                        memset(ecbptr,0,sizeof(struct ecb)); 
 284                        if ( my_done )
 285                                my_done(SCtmp);
 286                        break;
 287                        
 288                case    G2INTST_HARDFAIL:
 289                        printk(KERN_ALERT "aha1740 hardware failure!\n");
 290                        panic("aha1740.c");     /* Goodbye */
 291                        
 292                case    G2INTST_ASNEVENT:
 293                        printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n",
 294                               adapstat,
 295                               inb(MBOXIN0(base)),
 296                               inb(MBOXIN1(base)),
 297                               inb(MBOXIN2(base)),
 298                               inb(MBOXIN3(base))); /* Say What? */
 299                        /* Host Ready -> Mailbox in complete */
 300                        outb(G2CNTRL_HRDY,G2CNTRL(base));
 301                        break;
 302                        
 303                case    G2INTST_CMDGOOD:
 304                        /* set immediate command success flag here: */
 305                        break;
 306                        
 307                case    G2INTST_CMDERROR:
 308                        /* Set immediate command failure flag here: */
 309                        break;
 310                }
 311                number_serviced++;
 312        }
 313
 314        spin_unlock_irqrestore(host->host_lock, flags);
 315        return IRQ_RETVAL(handled);
 316}
 317
 318static int aha1740_queuecommand_lck(struct scsi_cmnd * SCpnt,
 319                                    void (*done)(struct scsi_cmnd *))
 320{
 321        unchar direction;
 322        unchar *cmd = (unchar *) SCpnt->cmnd;
 323        unchar target = scmd_id(SCpnt);
 324        struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host);
 325        unsigned long flags;
 326        dma_addr_t sg_dma;
 327        struct aha1740_sg *sgptr;
 328        int ecbno, nseg;
 329        DEB(int i);
 330
 331        if(*cmd == REQUEST_SENSE) {
 332                SCpnt->result = 0;
 333                done(SCpnt); 
 334                return 0;
 335        }
 336
 337#ifdef DEBUG
 338        if (*cmd == READ_10 || *cmd == WRITE_10)
 339                i = xscsi2int(cmd+2);
 340        else if (*cmd == READ_6 || *cmd == WRITE_6)
 341                i = scsi2int(cmd+2);
 342        else
 343                i = -1;
 344        printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",
 345               target, *cmd, i, bufflen);
 346        printk("scsi cmd:");
 347        for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
 348        printk("\n");
 349#endif
 350
 351        /* locate an available ecb */
 352        spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
 353        ecbno = host->last_ecb_used + 1; /* An optimization */
 354        if (ecbno >= AHA1740_ECBS)
 355                ecbno = 0;
 356        do {
 357                if (!host->ecb[ecbno].cmdw)
 358                        break;
 359                ecbno++;
 360                if (ecbno >= AHA1740_ECBS)
 361                        ecbno = 0;
 362        } while (ecbno != host->last_ecb_used);
 363
 364        if (host->ecb[ecbno].cmdw)
 365                panic("Unable to find empty ecb for aha1740.\n");
 366
 367        host->ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command
 368                                                    doubles as reserved flag */
 369
 370        host->last_ecb_used = ecbno;    
 371        spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
 372
 373#ifdef DEBUG
 374        printk("Sending command (%d %x)...", ecbno, done);
 375#endif
 376
 377        host->ecb[ecbno].cdblen = SCpnt->cmd_len; /* SCSI Command
 378                                                   * Descriptor Block
 379                                                   * Length */
 380
 381        direction = 0;
 382        if (*cmd == READ_10 || *cmd == READ_6)
 383                direction = 1;
 384        else if (*cmd == WRITE_10 || *cmd == WRITE_6)
 385                direction = 0;
 386
 387        memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len);
 388
 389        SCpnt->host_scribble = dma_alloc_coherent (&host->edev->dev,
 390                                                   sizeof (struct aha1740_sg),
 391                                                   &sg_dma, GFP_ATOMIC);
 392        if(SCpnt->host_scribble == NULL) {
 393                printk(KERN_WARNING "aha1740: out of memory in queuecommand!\n");
 394                return 1;
 395        }
 396        sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
 397        sgptr->sg_dma_addr = sg_dma;
 398
 399        nseg = scsi_dma_map(SCpnt);
 400        BUG_ON(nseg < 0);
 401        if (nseg) {
 402                struct scatterlist *sg;
 403                struct aha1740_chain * cptr;
 404                int i;
 405                DEB(unsigned char * ptr);
 406
 407                host->ecb[ecbno].sg = 1;  /* SCSI Initiator Command
 408                                           * w/scatter-gather*/
 409                cptr = sgptr->sg_chain;
 410                scsi_for_each_sg(SCpnt, sg, nseg, i) {
 411                        cptr[i].datalen = sg_dma_len (sg);
 412                        cptr[i].dataptr = sg_dma_address (sg);
 413                }
 414                host->ecb[ecbno].datalen = nseg * sizeof(struct aha1740_chain);
 415                host->ecb[ecbno].dataptr = sg_dma;
 416#ifdef DEBUG
 417                printk("cptr %x: ",cptr);
 418                ptr = (unsigned char *) cptr;
 419                for(i=0;i<24;i++) printk("%02x ", ptr[i]);
 420#endif
 421        } else {
 422                host->ecb[ecbno].datalen = 0;
 423                host->ecb[ecbno].dataptr = 0;
 424        }
 425        host->ecb[ecbno].lun = SCpnt->device->lun;
 426        host->ecb[ecbno].ses = 1; /* Suppress underrun errors */
 427        host->ecb[ecbno].dir = direction;
 428        host->ecb[ecbno].ars = 1; /* Yes, get the sense on an error */
 429        host->ecb[ecbno].senselen = 12;
 430        host->ecb[ecbno].senseptr = ecb_cpu_to_dma (SCpnt->device->host,
 431                                                    host->ecb[ecbno].sense);
 432        host->ecb[ecbno].statusptr = ecb_cpu_to_dma (SCpnt->device->host,
 433                                                     host->ecb[ecbno].status);
 434        host->ecb[ecbno].done = done;
 435        host->ecb[ecbno].SCpnt = SCpnt;
 436#ifdef DEBUG
 437        {
 438                int i;
 439                printk("aha1740_command: sending.. ");
 440                for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++)
 441                        printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]);
 442        }
 443        printk("\n");
 444#endif
 445        if (done) {
 446        /* The Adaptec Spec says the card is so fast that the loops
 447           will only be executed once in the code below. Even if this
 448           was true with the fastest processors when the spec was
 449           written, it doesn't seem to be true with today's fast
 450           processors. We print a warning if the code is executed more
 451           often than LOOPCNT_WARN. If this happens, it should be
 452           investigated. If the count reaches LOOPCNT_MAX, we assume
 453           something is broken; since there is no way to return an
 454           error (the return value is ignored by the mid-level scsi
 455           layer) we have to panic (and maybe that's the best thing we
 456           can do then anyhow). */
 457
 458#define LOOPCNT_WARN 10         /* excessive mbxout wait -> syslog-msg */
 459#define LOOPCNT_MAX 1000000     /* mbxout deadlock -> panic() after ~ 2 sec. */
 460                int loopcnt;
 461                unsigned int base = SCpnt->device->host->io_port;
 462                DEB(printk("aha1740[%d] critical section\n",ecbno));
 463
 464                spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
 465                for (loopcnt = 0; ; loopcnt++) {
 466                        if (inb(G2STAT(base)) & G2STAT_MBXOUT) break;
 467                        if (loopcnt == LOOPCNT_WARN) {
 468                                printk("aha1740[%d]_mbxout wait!\n",ecbno);
 469                        }
 470                        if (loopcnt == LOOPCNT_MAX)
 471                                panic("aha1740.c: mbxout busy!\n");
 472                }
 473                outl (ecb_cpu_to_dma (SCpnt->device->host, host->ecb + ecbno),
 474                      MBOXOUT0(base));
 475                for (loopcnt = 0; ; loopcnt++) {
 476                        if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break;
 477                        if (loopcnt == LOOPCNT_WARN) {
 478                                printk("aha1740[%d]_attn wait!\n",ecbno);
 479                        }
 480                        if (loopcnt == LOOPCNT_MAX)
 481                                panic("aha1740.c: attn wait failed!\n");
 482                }
 483                outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */
 484                spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
 485                DEB(printk("aha1740[%d] request queued.\n",ecbno));
 486        } else
 487                printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
 488        return 0;
 489}
 490
 491static DEF_SCSI_QCMD(aha1740_queuecommand)
 492
 493/* Query the board for its irq_level and irq_type.  Nothing else matters
 494   in enhanced mode on an EISA bus. */
 495
 496static void aha1740_getconfig(unsigned int base, unsigned int *irq_level,
 497                              unsigned int *irq_type,
 498                              unsigned int *translation)
 499{
 500        static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
 501
 502        *irq_level = intab[inb(INTDEF(base)) & 0x7];
 503        *irq_type  = (inb(INTDEF(base)) & 0x8) >> 3;
 504        *translation = inb(RESV1(base)) & 0x1;
 505        outb(inb(INTDEF(base)) | 0x10, INTDEF(base));
 506}
 507
 508static int aha1740_biosparam(struct scsi_device *sdev,
 509                             struct block_device *dev,
 510                             sector_t capacity, int* ip)
 511{
 512        int size = capacity;
 513        int extended = HOSTDATA(sdev->host)->translation;
 514
 515        DEB(printk("aha1740_biosparam\n"));
 516        if (extended && (ip[2] > 1024)) {
 517                ip[0] = 255;
 518                ip[1] = 63;
 519                ip[2] = size / (255 * 63);
 520        } else {
 521                ip[0] = 64;
 522                ip[1] = 32;
 523                ip[2] = size >> 11;
 524        }
 525        return 0;
 526}
 527
 528static int aha1740_eh_abort_handler (struct scsi_cmnd *dummy)
 529{
 530/*
 531 * From Alan Cox :
 532 * The AHA1740 has firmware handled abort/reset handling. The "head in
 533 * sand" kernel code is correct for once 8)
 534 *
 535 * So we define a dummy handler just to keep the kernel SCSI code as
 536 * quiet as possible...
 537 */
 538
 539        return SUCCESS;
 540}
 541
 542static struct scsi_host_template aha1740_template = {
 543        .module           = THIS_MODULE,
 544        .proc_name        = "aha1740",
 545        .show_info        = aha1740_show_info,
 546        .name             = "Adaptec 174x (EISA)",
 547        .queuecommand     = aha1740_queuecommand,
 548        .bios_param       = aha1740_biosparam,
 549        .can_queue        = AHA1740_ECBS,
 550        .this_id          = 7,
 551        .sg_tablesize     = AHA1740_SCATTER,
 552        .eh_abort_handler = aha1740_eh_abort_handler,
 553};
 554
 555static int aha1740_probe (struct device *dev)
 556{
 557        int slotbase, rc;
 558        unsigned int irq_level, irq_type, translation;
 559        struct Scsi_Host *shpnt;
 560        struct aha1740_hostdata *host;
 561        struct eisa_device *edev = to_eisa_device (dev);
 562
 563        DEB(printk("aha1740_probe: \n"));
 564        
 565        slotbase = edev->base_addr + EISA_VENDOR_ID_OFFSET;
 566        if (!request_region(slotbase, SLOTSIZE, "aha1740")) /* See if in use */
 567                return -EBUSY;
 568        if (!aha1740_test_port(slotbase))
 569                goto err_release_region;
 570        aha1740_getconfig(slotbase,&irq_level,&irq_type,&translation);
 571        if ((inb(G2STAT(slotbase)) &
 572             (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) {
 573                /* If the card isn't ready, hard reset it */
 574                outb(G2CNTRL_HRST, G2CNTRL(slotbase));
 575                outb(0, G2CNTRL(slotbase));
 576        }
 577        printk(KERN_INFO "Configuring slot %d at IO:%x, IRQ %u (%s)\n",
 578               edev->slot, slotbase, irq_level, irq_type ? "edge" : "level");
 579        printk(KERN_INFO "aha174x: Extended translation %sabled.\n",
 580               translation ? "en" : "dis");
 581        shpnt = scsi_host_alloc(&aha1740_template,
 582                              sizeof(struct aha1740_hostdata));
 583        if(shpnt == NULL)
 584                goto err_release_region;
 585
 586        shpnt->base = 0;
 587        shpnt->io_port = slotbase;
 588        shpnt->n_io_port = SLOTSIZE;
 589        shpnt->irq = irq_level;
 590        shpnt->dma_channel = 0xff;
 591        host = HOSTDATA(shpnt);
 592        host->edev = edev;
 593        host->translation = translation;
 594        host->ecb_dma_addr = dma_map_single (&edev->dev, host->ecb,
 595                                             sizeof (host->ecb),
 596                                             DMA_BIDIRECTIONAL);
 597        if (!host->ecb_dma_addr) {
 598                printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n");
 599                goto err_host_put;
 600        }
 601        
 602        DEB(printk("aha1740_probe: enable interrupt channel %d\n",irq_level));
 603        if (request_irq(irq_level,aha1740_intr_handle,irq_type ? 0 : IRQF_SHARED,
 604                        "aha1740",shpnt)) {
 605                printk(KERN_ERR "aha1740_probe: Unable to allocate IRQ %d.\n",
 606                       irq_level);
 607                goto err_unmap;
 608        }
 609
 610        eisa_set_drvdata (edev, shpnt);
 611
 612        rc = scsi_add_host (shpnt, dev);
 613        if (rc)
 614                goto err_irq;
 615
 616        scsi_scan_host (shpnt);
 617        return 0;
 618
 619 err_irq:
 620        free_irq(irq_level, shpnt);
 621 err_unmap:
 622        dma_unmap_single (&edev->dev, host->ecb_dma_addr,
 623                          sizeof (host->ecb), DMA_BIDIRECTIONAL);
 624 err_host_put:
 625        scsi_host_put (shpnt);
 626 err_release_region:
 627        release_region(slotbase, SLOTSIZE);
 628
 629        return -ENODEV;
 630}
 631
 632static int aha1740_remove (struct device *dev)
 633{
 634        struct Scsi_Host *shpnt = dev_get_drvdata(dev);
 635        struct aha1740_hostdata *host = HOSTDATA (shpnt);
 636
 637        scsi_remove_host(shpnt);
 638        
 639        free_irq (shpnt->irq, shpnt);
 640        dma_unmap_single (dev, host->ecb_dma_addr,
 641                          sizeof (host->ecb), DMA_BIDIRECTIONAL);
 642        release_region (shpnt->io_port, SLOTSIZE);
 643
 644        scsi_host_put (shpnt);
 645        
 646        return 0;
 647}
 648
 649static struct eisa_device_id aha1740_ids[] = {
 650        { "ADP0000" },          /* 1740  */
 651        { "ADP0001" },          /* 1740A */
 652        { "ADP0002" },          /* 1742A */
 653        { "ADP0400" },          /* 1744  */
 654        { "" }
 655};
 656MODULE_DEVICE_TABLE(eisa, aha1740_ids);
 657
 658static struct eisa_driver aha1740_driver = {
 659        .id_table = aha1740_ids,
 660        .driver   = {
 661                .name    = "aha1740",
 662                .probe   = aha1740_probe,
 663                .remove  = aha1740_remove,
 664        },
 665};
 666
 667static __init int aha1740_init (void)
 668{
 669        return eisa_driver_register (&aha1740_driver);
 670}
 671
 672static __exit void aha1740_exit (void)
 673{
 674        eisa_driver_unregister (&aha1740_driver);
 675}
 676
 677module_init (aha1740_init);
 678module_exit (aha1740_exit);
 679
 680MODULE_LICENSE("GPL");
 681