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_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_lck(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 today's 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
 505static DEF_SCSI_QCMD(aha1740_queuecommand)
 506
 507/* Query the board for its irq_level and irq_type.  Nothing else matters
 508   in enhanced mode on an EISA bus. */
 509
 510static void aha1740_getconfig(unsigned int base, unsigned int *irq_level,
 511                              unsigned int *irq_type,
 512                              unsigned int *translation)
 513{
 514        static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
 515
 516        *irq_level = intab[inb(INTDEF(base)) & 0x7];
 517        *irq_type  = (inb(INTDEF(base)) & 0x8) >> 3;
 518        *translation = inb(RESV1(base)) & 0x1;
 519        outb(inb(INTDEF(base)) | 0x10, INTDEF(base));
 520}
 521
 522static int aha1740_biosparam(struct scsi_device *sdev,
 523                             struct block_device *dev,
 524                             sector_t capacity, int* ip)
 525{
 526        int size = capacity;
 527        int extended = HOSTDATA(sdev->host)->translation;
 528
 529        DEB(printk("aha1740_biosparam\n"));
 530        if (extended && (ip[2] > 1024)) {
 531                ip[0] = 255;
 532                ip[1] = 63;
 533                ip[2] = size / (255 * 63);
 534        } else {
 535                ip[0] = 64;
 536                ip[1] = 32;
 537                ip[2] = size >> 11;
 538        }
 539        return 0;
 540}
 541
 542static int aha1740_eh_abort_handler (Scsi_Cmnd *dummy)
 543{
 544/*
 545 * From Alan Cox :
 546 * The AHA1740 has firmware handled abort/reset handling. The "head in
 547 * sand" kernel code is correct for once 8)
 548 *
 549 * So we define a dummy handler just to keep the kernel SCSI code as
 550 * quiet as possible...
 551 */
 552
 553        return 0;
 554}
 555
 556static struct scsi_host_template aha1740_template = {
 557        .module           = THIS_MODULE,
 558        .proc_name        = "aha1740",
 559        .proc_info        = aha1740_proc_info,
 560        .name             = "Adaptec 174x (EISA)",
 561        .queuecommand     = aha1740_queuecommand,
 562        .bios_param       = aha1740_biosparam,
 563        .can_queue        = AHA1740_ECBS,
 564        .this_id          = 7,
 565        .sg_tablesize     = AHA1740_SCATTER,
 566        .cmd_per_lun      = AHA1740_CMDLUN,
 567        .use_clustering   = ENABLE_CLUSTERING,
 568        .eh_abort_handler = aha1740_eh_abort_handler,
 569};
 570
 571static int aha1740_probe (struct device *dev)
 572{
 573        int slotbase, rc;
 574        unsigned int irq_level, irq_type, translation;
 575        struct Scsi_Host *shpnt;
 576        struct aha1740_hostdata *host;
 577        struct eisa_device *edev = to_eisa_device (dev);
 578
 579        DEB(printk("aha1740_probe: \n"));
 580        
 581        slotbase = edev->base_addr + EISA_VENDOR_ID_OFFSET;
 582        if (!request_region(slotbase, SLOTSIZE, "aha1740")) /* See if in use */
 583                return -EBUSY;
 584        if (!aha1740_test_port(slotbase))
 585                goto err_release_region;
 586        aha1740_getconfig(slotbase,&irq_level,&irq_type,&translation);
 587        if ((inb(G2STAT(slotbase)) &
 588             (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) {
 589                /* If the card isn't ready, hard reset it */
 590                outb(G2CNTRL_HRST, G2CNTRL(slotbase));
 591                outb(0, G2CNTRL(slotbase));
 592        }
 593        printk(KERN_INFO "Configuring slot %d at IO:%x, IRQ %u (%s)\n",
 594               edev->slot, slotbase, irq_level, irq_type ? "edge" : "level");
 595        printk(KERN_INFO "aha174x: Extended translation %sabled.\n",
 596               translation ? "en" : "dis");
 597        shpnt = scsi_host_alloc(&aha1740_template,
 598                              sizeof(struct aha1740_hostdata));
 599        if(shpnt == NULL)
 600                goto err_release_region;
 601
 602        shpnt->base = 0;
 603        shpnt->io_port = slotbase;
 604        shpnt->n_io_port = SLOTSIZE;
 605        shpnt->irq = irq_level;
 606        shpnt->dma_channel = 0xff;
 607        host = HOSTDATA(shpnt);
 608        host->edev = edev;
 609        host->translation = translation;
 610        host->ecb_dma_addr = dma_map_single (&edev->dev, host->ecb,
 611                                             sizeof (host->ecb),
 612                                             DMA_BIDIRECTIONAL);
 613        if (!host->ecb_dma_addr) {
 614                printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n");
 615                scsi_unregister (shpnt);
 616                goto err_host_put;
 617        }
 618        
 619        DEB(printk("aha1740_probe: enable interrupt channel %d\n",irq_level));
 620        if (request_irq(irq_level,aha1740_intr_handle,irq_type ? 0 : IRQF_SHARED,
 621                        "aha1740",shpnt)) {
 622                printk(KERN_ERR "aha1740_probe: Unable to allocate IRQ %d.\n",
 623                       irq_level);
 624                goto err_unmap;
 625        }
 626
 627        eisa_set_drvdata (edev, shpnt);
 628
 629        rc = scsi_add_host (shpnt, dev);
 630        if (rc)
 631                goto err_irq;
 632
 633        scsi_scan_host (shpnt);
 634        return 0;
 635
 636 err_irq:
 637        free_irq(irq_level, shpnt);
 638 err_unmap:
 639        dma_unmap_single (&edev->dev, host->ecb_dma_addr,
 640                          sizeof (host->ecb), DMA_BIDIRECTIONAL);
 641 err_host_put:
 642        scsi_host_put (shpnt);
 643 err_release_region:
 644        release_region(slotbase, SLOTSIZE);
 645
 646        return -ENODEV;
 647}
 648
 649static int aha1740_remove (struct device *dev)
 650{
 651        struct Scsi_Host *shpnt = dev_get_drvdata(dev);
 652        struct aha1740_hostdata *host = HOSTDATA (shpnt);
 653
 654        scsi_remove_host(shpnt);
 655        
 656        free_irq (shpnt->irq, shpnt);
 657        dma_unmap_single (dev, host->ecb_dma_addr,
 658                          sizeof (host->ecb), DMA_BIDIRECTIONAL);
 659        release_region (shpnt->io_port, SLOTSIZE);
 660
 661        scsi_host_put (shpnt);
 662        
 663        return 0;
 664}
 665
 666static struct eisa_device_id aha1740_ids[] = {
 667        { "ADP0000" },          /* 1740  */
 668        { "ADP0001" },          /* 1740A */
 669        { "ADP0002" },          /* 1742A */
 670        { "ADP0400" },          /* 1744  */
 671        { "" }
 672};
 673MODULE_DEVICE_TABLE(eisa, aha1740_ids);
 674
 675static struct eisa_driver aha1740_driver = {
 676        .id_table = aha1740_ids,
 677        .driver   = {
 678                .name    = "aha1740",
 679                .probe   = aha1740_probe,
 680                .remove  = aha1740_remove,
 681        },
 682};
 683
 684static __init int aha1740_init (void)
 685{
 686        return eisa_driver_register (&aha1740_driver);
 687}
 688
 689static __exit void aha1740_exit (void)
 690{
 691        eisa_driver_unregister (&aha1740_driver);
 692}
 693
 694module_init (aha1740_init);
 695module_exit (aha1740_exit);
 696
 697MODULE_LICENSE("GPL");
 698
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.