Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

Linux/drivers/scsi/aha1740.c

  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 
 72 struct 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 
 80 struct 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 
 88 static 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 
 99 static 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 
109 static 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 
119 static 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 
197 static 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 */
207 static 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 
314 static 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 
486 static 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 
491 static 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 
503 static 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 
523 static 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 
537 static 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 
552 static 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 
630 static 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 
647 static struct eisa_device_id aha1740_ids[] = {
648         { "ADP0000" },          /* 1740  */
649         { "ADP0001" },          /* 1740A */
650         { "ADP0002" },          /* 1742A */
651         { "ADP0400" },          /* 1744  */
652         { "" }
653 };
654 MODULE_DEVICE_TABLE(eisa, aha1740_ids);
655 
656 static 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 
665 static __init int aha1740_init (void)
666 {
667         return eisa_driver_register (&aha1740_driver);
668 }
669 
670 static __exit void aha1740_exit (void)
671 {
672         eisa_driver_unregister (&aha1740_driver);
673 }
674 
675 module_init (aha1740_init);
676 module_exit (aha1740_exit);
677 
678 MODULE_LICENSE("GPL");
679 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us