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                        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
 197static 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 */
 207static 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)(Scsi_Cmnd *);
 211        int errstatus, adapstat;
 212        int number_serviced;
 213        struct ecb *ecbptr;
 214        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
 314static int aha1740_queuecommand_lck(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 315{
 316        unchar direction;
 317        unchar *cmd = (unchar *) SCpnt->cmnd;
 318        unchar target = scmd_id(SCpnt);
 319        struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host);
 320        unsigned long flags;
 321        dma_addr_t sg_dma;
 322        struct aha1740_sg *sgptr;
 323        int ecbno, nseg;
 324        DEB(int i);
 325
 326        if(*cmd == REQUEST_SENSE) {
 327                SCpnt->result = 0;
 328                done(SCpnt); 
 329                return 0;
 330        }
 331
 332#ifdef DEBUG
 333        if (*cmd == READ_10 || *cmd == WRITE_10)
 334                i = xscsi2int(cmd+2);
 335        else if (*cmd == READ_6 || *cmd == WRITE_6)
 336                i = scsi2int(cmd+2);
 337        else
 338                i = -1;
 339        printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",
 340               target, *cmd, i, bufflen);
 341        printk("scsi cmd:");
 342        for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
 343        printk("\n");
 344#endif
 345
 346        /* locate an available ecb */
 347        spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
 348        ecbno = host->last_ecb_used + 1; /* An optimization */
 349        if (ecbno >= AHA1740_ECBS)
 350                ecbno = 0;
 351        do {
 352                if (!host->ecb[ecbno].cmdw)
 353                        break;
 354                ecbno++;
 355                if (ecbno >= AHA1740_ECBS)
 356                        ecbno = 0;
 357        } while (ecbno != host->last_ecb_used);
 358
 359        if (host->ecb[ecbno].cmdw)
 360                panic("Unable to find empty ecb for aha1740.\n");
 361
 362        host->ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command
 363                                                    doubles as reserved flag */
 364
 365        host->last_ecb_used = ecbno;    
 366        spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
 367
 368#ifdef DEBUG
 369        printk("Sending command (%d %x)...", ecbno, done);
 370#endif
 371
 372        host->ecb[ecbno].cdblen = SCpnt->cmd_len; /* SCSI Command
 373                                                   * Descriptor Block
 374                                                   * Length */
 375
 376        direction = 0;
 377        if (*cmd == READ_10 || *cmd == READ_6)
 378                direction = 1;
 379        else if (*cmd == WRITE_10 || *cmd == WRITE_6)
 380                direction = 0;
 381
 382        memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len);
 383
 384        SCpnt->host_scribble = dma_alloc_coherent (&host->edev->dev,
 385                                                   sizeof (struct aha1740_sg),
 386                                                   &sg_dma, GFP_ATOMIC);
 387        if(SCpnt->host_scribble == NULL) {
 388                printk(KERN_WARNING "aha1740: out of memory in queuecommand!\n");
 389                return 1;
 390        }
 391        sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
 392        sgptr->sg_dma_addr = sg_dma;
 393
 394        nseg = scsi_dma_map(SCpnt);
 395        BUG_ON(nseg < 0);
 396        if (nseg) {
 397                struct scatterlist *sg;
 398                struct aha1740_chain * cptr;
 399                int i;
 400                DEB(unsigned char * ptr);
 401
 402                host->ecb[ecbno].sg = 1;  /* SCSI Initiator Command
 403                                           * w/scatter-gather*/
 404                cptr = sgptr->sg_chain;
 405                scsi_for_each_sg(SCpnt, sg, nseg, i) {
 406                        cptr[i].datalen = sg_dma_len (sg);
 407                        cptr[i].dataptr = sg_dma_address (sg);
 408                }
 409                host->ecb[ecbno].datalen = nseg * sizeof(struct aha1740_chain);
 410                host->ecb[ecbno].dataptr = sg_dma;
 411#ifdef DEBUG
 412                printk("cptr %x: ",cptr);
 413                ptr = (unsigned char *) cptr;
 414                for(i=0;i<24;i++) printk("%02x ", ptr[i]);
 415#endif
 416        } else {
 417                host->ecb[ecbno].datalen = 0;
 418                host->ecb[ecbno].dataptr = 0;
 419        }
 420        host->ecb[ecbno].lun = SCpnt->device->lun;
 421        host->ecb[ecbno].ses = 1; /* Suppress underrun errors */
 422        host->ecb[ecbno].dir = direction;
 423        host->ecb[ecbno].ars = 1; /* Yes, get the sense on an error */
 424        host->ecb[ecbno].senselen = 12;
 425        host->ecb[ecbno].senseptr = ecb_cpu_to_dma (SCpnt->device->host,
 426                                                    host->ecb[ecbno].sense);
 427        host->ecb[ecbno].statusptr = ecb_cpu_to_dma (SCpnt->device->host,
 428                                                     host->ecb[ecbno].status);
 429        host->ecb[ecbno].done = done;
 430        host->ecb[ecbno].SCpnt = SCpnt;
 431#ifdef DEBUG
 432        {
 433                int i;
 434                printk("aha1740_command: sending.. ");
 435                for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++)
 436                        printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]);
 437        }
 438        printk("\n");
 439#endif
 440        if (done) {
 441        /* The Adaptec Spec says the card is so fast that the loops
 442           will only be executed once in the code below. Even if this
 443           was true with the fastest processors when the spec was
 444           written, it doesn't seem to be true with today's fast
 445           processors. We print a warning if the code is executed more
 446           often than LOOPCNT_WARN. If this happens, it should be
 447           investigated. If the count reaches LOOPCNT_MAX, we assume
 448           something is broken; since there is no way to return an
 449           error (the return value is ignored by the mid-level scsi
 450           layer) we have to panic (and maybe that's the best thing we
 451           can do then anyhow). */
 452
 453#define LOOPCNT_WARN 10         /* excessive mbxout wait -> syslog-msg */
 454#define LOOPCNT_MAX 1000000     /* mbxout deadlock -> panic() after ~ 2 sec. */
 455                int loopcnt;
 456                unsigned int base = SCpnt->device->host->io_port;
 457                DEB(printk("aha1740[%d] critical section\n",ecbno));
 458
 459                spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
 460                for (loopcnt = 0; ; loopcnt++) {
 461                        if (inb(G2STAT(base)) & G2STAT_MBXOUT) break;
 462                        if (loopcnt == LOOPCNT_WARN) {
 463                                printk("aha1740[%d]_mbxout wait!\n",ecbno);
 464                        }
 465                        if (loopcnt == LOOPCNT_MAX)
 466                                panic("aha1740.c: mbxout busy!\n");
 467                }
 468                outl (ecb_cpu_to_dma (SCpnt->device->host, host->ecb + ecbno),
 469                      MBOXOUT0(base));
 470                for (loopcnt = 0; ; loopcnt++) {
 471                        if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break;
 472                        if (loopcnt == LOOPCNT_WARN) {
 473                                printk("aha1740[%d]_attn wait!\n",ecbno);
 474                        }
 475                        if (loopcnt == LOOPCNT_MAX)
 476                                panic("aha1740.c: attn wait failed!\n");
 477                }
 478                outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */
 479                spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
 480                DEB(printk("aha1740[%d] request queued.\n",ecbno));
 481        } else
 482                printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
 483        return 0;
 484}
 485
 486static DEF_SCSI_QCMD(aha1740_queuecommand)
 487
 488/* Query the board for its irq_level and irq_type.  Nothing else matters
 489   in enhanced mode on an EISA bus. */
 490
 491static void aha1740_getconfig(unsigned int base, unsigned int *irq_level,
 492                              unsigned int *irq_type,
 493                              unsigned int *translation)
 494{
 495        static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
 496
 497        *irq_level = intab[inb(INTDEF(base)) & 0x7];
 498        *irq_type  = (inb(INTDEF(base)) & 0x8) >> 3;
 499        *translation = inb(RESV1(base)) & 0x1;
 500        outb(inb(INTDEF(base)) | 0x10, INTDEF(base));
 501}
 502
 503static int aha1740_biosparam(struct scsi_device *sdev,
 504                             struct block_device *dev,
 505                             sector_t capacity, int* ip)
 506{
 507        int size = capacity;
 508        int extended = HOSTDATA(sdev->host)->translation;
 509
 510        DEB(printk("aha1740_biosparam\n"));
 511        if (extended && (ip[2] > 1024)) {
 512                ip[0] = 255;
 513                ip[1] = 63;
 514                ip[2] = size / (255 * 63);
 515        } else {
 516                ip[0] = 64;
 517                ip[1] = 32;
 518                ip[2] = size >> 11;
 519        }
 520        return 0;
 521}
 522
 523static int aha1740_eh_abort_handler (Scsi_Cmnd *dummy)
 524{
 525/*
 526 * From Alan Cox :
 527 * The AHA1740 has firmware handled abort/reset handling. The "head in
 528 * sand" kernel code is correct for once 8)
 529 *
 530 * So we define a dummy handler just to keep the kernel SCSI code as
 531 * quiet as possible...
 532 */
 533
 534        return 0;
 535}
 536
 537static struct scsi_host_template aha1740_template = {
 538        .module           = THIS_MODULE,
 539        .proc_name        = "aha1740",
 540        .show_info        = aha1740_show_info,
 541        .name             = "Adaptec 174x (EISA)",
 542        .queuecommand     = aha1740_queuecommand,
 543        .bios_param       = aha1740_biosparam,
 544        .can_queue        = AHA1740_ECBS,
 545        .this_id          = 7,
 546        .sg_tablesize     = AHA1740_SCATTER,
 547        .cmd_per_lun      = AHA1740_CMDLUN,
 548        .use_clustering   = ENABLE_CLUSTERING,
 549        .eh_abort_handler = aha1740_eh_abort_handler,
 550};
 551
 552static int aha1740_probe (struct device *dev)
 553{
 554        int slotbase, rc;
 555        unsigned int irq_level, irq_type, translation;
 556        struct Scsi_Host *shpnt;
 557        struct aha1740_hostdata *host;
 558        struct eisa_device *edev = to_eisa_device (dev);
 559
 560        DEB(printk("aha1740_probe: \n"));
 561        
 562        slotbase = edev->base_addr + EISA_VENDOR_ID_OFFSET;
 563        if (!request_region(slotbase, SLOTSIZE, "aha1740")) /* See if in use */
 564                return -EBUSY;
 565        if (!aha1740_test_port(slotbase))
 566                goto err_release_region;
 567        aha1740_getconfig(slotbase,&irq_level,&irq_type,&translation);
 568        if ((inb(G2STAT(slotbase)) &
 569             (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) {
 570                /* If the card isn't ready, hard reset it */
 571                outb(G2CNTRL_HRST, G2CNTRL(slotbase));
 572                outb(0, G2CNTRL(slotbase));
 573        }
 574        printk(KERN_INFO "Configuring slot %d at IO:%x, IRQ %u (%s)\n",
 575               edev->slot, slotbase, irq_level, irq_type ? "edge" : "level");
 576        printk(KERN_INFO "aha174x: Extended translation %sabled.\n",
 577               translation ? "en" : "dis");
 578        shpnt = scsi_host_alloc(&aha1740_template,
 579                              sizeof(struct aha1740_hostdata));
 580        if(shpnt == NULL)
 581                goto err_release_region;
 582
 583        shpnt->base = 0;
 584        shpnt->io_port = slotbase;
 585        shpnt->n_io_port = SLOTSIZE;
 586        shpnt->irq = irq_level;
 587        shpnt->dma_channel = 0xff;
 588        host = HOSTDATA(shpnt);
 589        host->edev = edev;
 590        host->translation = translation;
 591        host->ecb_dma_addr = dma_map_single (&edev->dev, host->ecb,
 592                                             sizeof (host->ecb),
 593                                             DMA_BIDIRECTIONAL);
 594        if (!host->ecb_dma_addr) {
 595                printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n");
 596                scsi_unregister (shpnt);
 597                goto err_host_put;
 598        }
 599        
 600        DEB(printk("aha1740_probe: enable interrupt channel %d\n",irq_level));
 601        if (request_irq(irq_level,aha1740_intr_handle,irq_type ? 0 : IRQF_SHARED,
 602                        "aha1740",shpnt)) {
 603                printk(KERN_ERR "aha1740_probe: Unable to allocate IRQ %d.\n",
 604                       irq_level);
 605                goto err_unmap;
 606        }
 607
 608        eisa_set_drvdata (edev, shpnt);
 609
 610        rc = scsi_add_host (shpnt, dev);
 611        if (rc)
 612                goto err_irq;
 613
 614        scsi_scan_host (shpnt);
 615        return 0;
 616
 617 err_irq:
 618        free_irq(irq_level, shpnt);
 619 err_unmap:
 620        dma_unmap_single (&edev->dev, host->ecb_dma_addr,
 621                          sizeof (host->ecb), DMA_BIDIRECTIONAL);
 622 err_host_put:
 623        scsi_host_put (shpnt);
 624 err_release_region:
 625        release_region(slotbase, SLOTSIZE);
 626
 627        return -ENODEV;
 628}
 629
 630static int aha1740_remove (struct device *dev)
 631{
 632        struct Scsi_Host *shpnt = dev_get_drvdata(dev);
 633        struct aha1740_hostdata *host = HOSTDATA (shpnt);
 634
 635        scsi_remove_host(shpnt);
 636        
 637        free_irq (shpnt->irq, shpnt);
 638        dma_unmap_single (dev, host->ecb_dma_addr,
 639                          sizeof (host->ecb), DMA_BIDIRECTIONAL);
 640        release_region (shpnt->io_port, SLOTSIZE);
 641
 642        scsi_host_put (shpnt);
 643        
 644        return 0;
 645}
 646
 647static struct eisa_device_id aha1740_ids[] = {
 648        { "ADP0000" },          /* 1740  */
 649        { "ADP0001" },          /* 1740A */
 650        { "ADP0002" },          /* 1742A */
 651        { "ADP0400" },          /* 1744  */
 652        { "" }
 653};
 654MODULE_DEVICE_TABLE(eisa, aha1740_ids);
 655
 656static struct eisa_driver aha1740_driver = {
 657        .id_table = aha1740_ids,
 658        .driver   = {
 659                .name    = "aha1740",
 660                .probe   = aha1740_probe,
 661                .remove  = aha1740_remove,
 662        },
 663};
 664
 665static __init int aha1740_init (void)
 666{
 667        return eisa_driver_register (&aha1740_driver);
 668}
 669
 670static __exit void aha1740_exit (void)
 671{
 672        eisa_driver_unregister (&aha1740_driver);
 673}
 674
 675module_init (aha1740_init);
 676module_exit (aha1740_exit);
 677
 678MODULE_LICENSE("GPL");
 679
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.