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