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