[NETFILTER]: nf_conntrack: fix helper structure alignment
[linux-2.6.22.y-op.git] / drivers / scsi / aha1740.c
blobc3c38a7e8d32d091a3bbd7ee925d7e81bc1492d2
1 /* $Id$
2 * 1993/03/31
3 * linux/kernel/aha1740.c
5 * Based loosely on aha1542.c which is
6 * Copyright (C) 1992 Tommy Thorn and
7 * Modified by Eric Youngdale
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.
13 * Modifications to makecode and queuecommand
14 * for proper handling of multiple devices courteously
15 * provided by Michael Weller, March, 1993
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
22 * aha1740_makecode may still need even more work
23 * if it doesn't work for your devices, take a look.
25 * Reworked for new_eh and new locking by Alan Cox <alan@redhat.com>
27 * Converted to EISA and generic DMA APIs by Marc Zyngier
28 * <maz@wild-wind.fr.eu.org>, 4/2003.
30 * Shared interrupt support added by Rask Ingemann Lambertsen
31 * <rask@sygehus.dk>, 10/2003
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.
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>
54 #include <asm/dma.h>
55 #include <asm/system.h>
56 #include <asm/io.h>
58 #include "scsi.h"
59 #include <scsi/scsi_host.h>
60 #include "aha1740.h"
62 /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH
63 IT WORK, THEN:
64 #define DEBUG
66 #ifdef DEBUG
67 #define DEB(x) x
68 #else
69 #define DEB(x)
70 #endif
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];
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;
86 #define HOSTDATA(host) ((struct aha1740_hostdata *) &host->hostdata)
88 static inline struct ecb *ecb_dma_to_cpu (struct Scsi_Host *host,
89 dma_addr_t dma)
91 struct aha1740_hostdata *hdata = HOSTDATA (host);
92 dma_addr_t offset;
94 offset = dma - hdata->ecb_dma_addr;
96 return (struct ecb *)(((char *) hdata->ecb) + (unsigned int) offset);
99 static inline dma_addr_t ecb_cpu_to_dma (struct Scsi_Host *host, void *cpu)
101 struct aha1740_hostdata *hdata = HOSTDATA (host);
102 dma_addr_t offset;
104 offset = (char *) cpu - (char *) hdata->ecb;
106 return hdata->ecb_dma_addr + offset;
109 static int aha1740_proc_info(struct Scsi_Host *shpnt, char *buffer,
110 char **start, off_t offset,
111 int length, int inout)
113 int len;
114 struct aha1740_hostdata *host;
116 if (inout)
117 return-ENOSYS;
119 host = HOSTDATA(shpnt);
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");
126 if (offset > len) {
127 *start = buffer;
128 return 0;
131 *start = buffer + offset;
132 len -= offset;
133 if (len > length)
134 len = length;
135 return len;
138 static int aha1740_makecode(unchar *sense, unchar *status)
140 struct statusword
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 */
155 } status_word;
156 int retval = DID_OK;
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 */
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;
207 /* In any other case return DID_OK so for example
208 CONDITION_CHECKS make it through to the appropriate
209 device driver */
212 /* Under all circumstances supply the target status -Michael */
213 return status[3] | retval << 16;
216 static int aha1740_test_port(unsigned int base)
218 if ( inb(PORTADR(base)) & PORTADDR_ENH )
219 return 1; /* Okay, we're all set */
221 printk("aha174x: Board detected, but not in enhanced mode, so disabled it.\n");
222 return 0;
225 /* A "high" level interrupt handler */
226 static irqreturn_t aha1740_intr_handle(int irq, void *dev_id)
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;
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;
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 */
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;
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;
273 sgptr = (struct aha1740_sg *) SCtmp->host_scribble;
274 if (SCtmp->use_sg) {
275 /* We used scatter-gather.
276 Do the unmapping dance. */
277 dma_unmap_sg (&edev->dev,
278 (struct scatterlist *) SCtmp->request_buffer,
279 SCtmp->use_sg,
280 SCtmp->sc_data_direction);
281 } else {
282 dma_unmap_single (&edev->dev,
283 sgptr->buf_dma_addr,
284 SCtmp->request_bufflen,
285 DMA_BIDIRECTIONAL);
288 /* Free the sg block */
289 dma_free_coherent (&edev->dev,
290 sizeof (struct aha1740_sg),
291 SCtmp->host_scribble,
292 sgptr->sg_dma_addr);
294 /* Fetch the sense data, and tuck it away, in
295 the required slot. The Adaptec
296 automatically fetches it, and there is no
297 guarantee that we will still have it in the
298 cdb when we come back */
299 if ( (adapstat & G2INTST_MASK) == G2INTST_CCBERROR ) {
300 memcpy(SCtmp->sense_buffer, ecbptr->sense,
301 sizeof(SCtmp->sense_buffer));
302 errstatus = aha1740_makecode(ecbptr->sense,ecbptr->status);
303 } else
304 errstatus = 0;
305 DEB(if (errstatus)
306 printk("aha1740_intr_handle: returning %6x\n",
307 errstatus));
308 SCtmp->result = errstatus;
309 my_done = ecbptr->done;
310 memset(ecbptr,0,sizeof(struct ecb));
311 if ( my_done )
312 my_done(SCtmp);
313 break;
315 case G2INTST_HARDFAIL:
316 printk(KERN_ALERT "aha1740 hardware failure!\n");
317 panic("aha1740.c"); /* Goodbye */
319 case G2INTST_ASNEVENT:
320 printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n",
321 adapstat,
322 inb(MBOXIN0(base)),
323 inb(MBOXIN1(base)),
324 inb(MBOXIN2(base)),
325 inb(MBOXIN3(base))); /* Say What? */
326 /* Host Ready -> Mailbox in complete */
327 outb(G2CNTRL_HRDY,G2CNTRL(base));
328 break;
330 case G2INTST_CMDGOOD:
331 /* set immediate command success flag here: */
332 break;
334 case G2INTST_CMDERROR:
335 /* Set immediate command failure flag here: */
336 break;
338 number_serviced++;
341 spin_unlock_irqrestore(host->host_lock, flags);
342 return IRQ_RETVAL(handled);
345 static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
347 unchar direction;
348 unchar *cmd = (unchar *) SCpnt->cmnd;
349 unchar target = scmd_id(SCpnt);
350 struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host);
351 unsigned long flags;
352 void *buff = SCpnt->request_buffer;
353 int bufflen = SCpnt->request_bufflen;
354 dma_addr_t sg_dma;
355 struct aha1740_sg *sgptr;
356 int ecbno;
357 DEB(int i);
359 if(*cmd == REQUEST_SENSE) {
360 SCpnt->result = 0;
361 done(SCpnt);
362 return 0;
365 #ifdef DEBUG
366 if (*cmd == READ_10 || *cmd == WRITE_10)
367 i = xscsi2int(cmd+2);
368 else if (*cmd == READ_6 || *cmd == WRITE_6)
369 i = scsi2int(cmd+2);
370 else
371 i = -1;
372 printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",
373 target, *cmd, i, bufflen);
374 printk("scsi cmd:");
375 for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
376 printk("\n");
377 #endif
379 /* locate an available ecb */
380 spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
381 ecbno = host->last_ecb_used + 1; /* An optimization */
382 if (ecbno >= AHA1740_ECBS)
383 ecbno = 0;
384 do {
385 if (!host->ecb[ecbno].cmdw)
386 break;
387 ecbno++;
388 if (ecbno >= AHA1740_ECBS)
389 ecbno = 0;
390 } while (ecbno != host->last_ecb_used);
392 if (host->ecb[ecbno].cmdw)
393 panic("Unable to find empty ecb for aha1740.\n");
395 host->ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command
396 doubles as reserved flag */
398 host->last_ecb_used = ecbno;
399 spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
401 #ifdef DEBUG
402 printk("Sending command (%d %x)...", ecbno, done);
403 #endif
405 host->ecb[ecbno].cdblen = SCpnt->cmd_len; /* SCSI Command
406 * Descriptor Block
407 * Length */
409 direction = 0;
410 if (*cmd == READ_10 || *cmd == READ_6)
411 direction = 1;
412 else if (*cmd == WRITE_10 || *cmd == WRITE_6)
413 direction = 0;
415 memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len);
417 SCpnt->host_scribble = dma_alloc_coherent (&host->edev->dev,
418 sizeof (struct aha1740_sg),
419 &sg_dma, GFP_ATOMIC);
420 if(SCpnt->host_scribble == NULL) {
421 printk(KERN_WARNING "aha1740: out of memory in queuecommand!\n");
422 return 1;
424 sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
425 sgptr->sg_dma_addr = sg_dma;
427 if (SCpnt->use_sg) {
428 struct scatterlist * sgpnt;
429 struct aha1740_chain * cptr;
430 int i, count;
431 DEB(unsigned char * ptr);
433 host->ecb[ecbno].sg = 1; /* SCSI Initiator Command
434 * w/scatter-gather*/
435 sgpnt = (struct scatterlist *) SCpnt->request_buffer;
436 cptr = sgptr->sg_chain;
437 count = dma_map_sg (&host->edev->dev, sgpnt, SCpnt->use_sg,
438 SCpnt->sc_data_direction);
439 for(i=0; i < count; i++) {
440 cptr[i].datalen = sg_dma_len (sgpnt + i);
441 cptr[i].dataptr = sg_dma_address (sgpnt + i);
443 host->ecb[ecbno].datalen = count*sizeof(struct aha1740_chain);
444 host->ecb[ecbno].dataptr = sg_dma;
445 #ifdef DEBUG
446 printk("cptr %x: ",cptr);
447 ptr = (unsigned char *) cptr;
448 for(i=0;i<24;i++) printk("%02x ", ptr[i]);
449 #endif
450 } else {
451 host->ecb[ecbno].datalen = bufflen;
452 sgptr->buf_dma_addr = dma_map_single (&host->edev->dev,
453 buff, bufflen,
454 DMA_BIDIRECTIONAL);
455 host->ecb[ecbno].dataptr = sgptr->buf_dma_addr;
457 host->ecb[ecbno].lun = SCpnt->device->lun;
458 host->ecb[ecbno].ses = 1; /* Suppress underrun errors */
459 host->ecb[ecbno].dir = direction;
460 host->ecb[ecbno].ars = 1; /* Yes, get the sense on an error */
461 host->ecb[ecbno].senselen = 12;
462 host->ecb[ecbno].senseptr = ecb_cpu_to_dma (SCpnt->device->host,
463 host->ecb[ecbno].sense);
464 host->ecb[ecbno].statusptr = ecb_cpu_to_dma (SCpnt->device->host,
465 host->ecb[ecbno].status);
466 host->ecb[ecbno].done = done;
467 host->ecb[ecbno].SCpnt = SCpnt;
468 #ifdef DEBUG
470 int i;
471 printk("aha1740_command: sending.. ");
472 for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++)
473 printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]);
475 printk("\n");
476 #endif
477 if (done) {
478 /* The Adaptec Spec says the card is so fast that the loops
479 will only be executed once in the code below. Even if this
480 was true with the fastest processors when the spec was
481 written, it doesn't seem to be true with todays fast
482 processors. We print a warning if the code is executed more
483 often than LOOPCNT_WARN. If this happens, it should be
484 investigated. If the count reaches LOOPCNT_MAX, we assume
485 something is broken; since there is no way to return an
486 error (the return value is ignored by the mid-level scsi
487 layer) we have to panic (and maybe that's the best thing we
488 can do then anyhow). */
490 #define LOOPCNT_WARN 10 /* excessive mbxout wait -> syslog-msg */
491 #define LOOPCNT_MAX 1000000 /* mbxout deadlock -> panic() after ~ 2 sec. */
492 int loopcnt;
493 unsigned int base = SCpnt->device->host->io_port;
494 DEB(printk("aha1740[%d] critical section\n",ecbno));
496 spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
497 for (loopcnt = 0; ; loopcnt++) {
498 if (inb(G2STAT(base)) & G2STAT_MBXOUT) break;
499 if (loopcnt == LOOPCNT_WARN) {
500 printk("aha1740[%d]_mbxout wait!\n",ecbno);
502 if (loopcnt == LOOPCNT_MAX)
503 panic("aha1740.c: mbxout busy!\n");
505 outl (ecb_cpu_to_dma (SCpnt->device->host, host->ecb + ecbno),
506 MBOXOUT0(base));
507 for (loopcnt = 0; ; loopcnt++) {
508 if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break;
509 if (loopcnt == LOOPCNT_WARN) {
510 printk("aha1740[%d]_attn wait!\n",ecbno);
512 if (loopcnt == LOOPCNT_MAX)
513 panic("aha1740.c: attn wait failed!\n");
515 outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */
516 spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
517 DEB(printk("aha1740[%d] request queued.\n",ecbno));
518 } else
519 printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
520 return 0;
523 /* Query the board for its irq_level and irq_type. Nothing else matters
524 in enhanced mode on an EISA bus. */
526 static void aha1740_getconfig(unsigned int base, unsigned int *irq_level,
527 unsigned int *irq_type,
528 unsigned int *translation)
530 static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
532 *irq_level = intab[inb(INTDEF(base)) & 0x7];
533 *irq_type = (inb(INTDEF(base)) & 0x8) >> 3;
534 *translation = inb(RESV1(base)) & 0x1;
535 outb(inb(INTDEF(base)) | 0x10, INTDEF(base));
538 static int aha1740_biosparam(struct scsi_device *sdev,
539 struct block_device *dev,
540 sector_t capacity, int* ip)
542 int size = capacity;
543 int extended = HOSTDATA(sdev->host)->translation;
545 DEB(printk("aha1740_biosparam\n"));
546 if (extended && (ip[2] > 1024)) {
547 ip[0] = 255;
548 ip[1] = 63;
549 ip[2] = size / (255 * 63);
550 } else {
551 ip[0] = 64;
552 ip[1] = 32;
553 ip[2] = size >> 11;
555 return 0;
558 static int aha1740_eh_abort_handler (Scsi_Cmnd *dummy)
561 * From Alan Cox :
562 * The AHA1740 has firmware handled abort/reset handling. The "head in
563 * sand" kernel code is correct for once 8)
565 * So we define a dummy handler just to keep the kernel SCSI code as
566 * quiet as possible...
569 return 0;
572 static struct scsi_host_template aha1740_template = {
573 .module = THIS_MODULE,
574 .proc_name = "aha1740",
575 .proc_info = aha1740_proc_info,
576 .name = "Adaptec 174x (EISA)",
577 .queuecommand = aha1740_queuecommand,
578 .bios_param = aha1740_biosparam,
579 .can_queue = AHA1740_ECBS,
580 .this_id = 7,
581 .sg_tablesize = AHA1740_SCATTER,
582 .cmd_per_lun = AHA1740_CMDLUN,
583 .use_clustering = ENABLE_CLUSTERING,
584 .eh_abort_handler = aha1740_eh_abort_handler,
587 static int aha1740_probe (struct device *dev)
589 int slotbase;
590 unsigned int irq_level, irq_type, translation;
591 struct Scsi_Host *shpnt;
592 struct aha1740_hostdata *host;
593 struct eisa_device *edev = to_eisa_device (dev);
595 DEB(printk("aha1740_probe: \n"));
597 slotbase = edev->base_addr + EISA_VENDOR_ID_OFFSET;
598 if (!request_region(slotbase, SLOTSIZE, "aha1740")) /* See if in use */
599 return -EBUSY;
600 if (!aha1740_test_port(slotbase))
601 goto err_release_region;
602 aha1740_getconfig(slotbase,&irq_level,&irq_type,&translation);
603 if ((inb(G2STAT(slotbase)) &
604 (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) {
605 /* If the card isn't ready, hard reset it */
606 outb(G2CNTRL_HRST, G2CNTRL(slotbase));
607 outb(0, G2CNTRL(slotbase));
609 printk(KERN_INFO "Configuring slot %d at IO:%x, IRQ %u (%s)\n",
610 edev->slot, slotbase, irq_level, irq_type ? "edge" : "level");
611 printk(KERN_INFO "aha174x: Extended translation %sabled.\n",
612 translation ? "en" : "dis");
613 shpnt = scsi_host_alloc(&aha1740_template,
614 sizeof(struct aha1740_hostdata));
615 if(shpnt == NULL)
616 goto err_release_region;
618 shpnt->base = 0;
619 shpnt->io_port = slotbase;
620 shpnt->n_io_port = SLOTSIZE;
621 shpnt->irq = irq_level;
622 shpnt->dma_channel = 0xff;
623 host = HOSTDATA(shpnt);
624 host->edev = edev;
625 host->translation = translation;
626 host->ecb_dma_addr = dma_map_single (&edev->dev, host->ecb,
627 sizeof (host->ecb),
628 DMA_BIDIRECTIONAL);
629 if (!host->ecb_dma_addr) {
630 printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n");
631 scsi_unregister (shpnt);
632 goto err_host_put;
635 DEB(printk("aha1740_probe: enable interrupt channel %d\n",irq_level));
636 if (request_irq(irq_level,aha1740_intr_handle,irq_type ? 0 : IRQF_SHARED,
637 "aha1740",shpnt)) {
638 printk(KERN_ERR "aha1740_probe: Unable to allocate IRQ %d.\n",
639 irq_level);
640 goto err_unmap;
643 eisa_set_drvdata (edev, shpnt);
644 scsi_add_host (shpnt, dev); /* XXX handle failure */
645 scsi_scan_host (shpnt);
646 return 0;
648 err_unmap:
649 dma_unmap_single (&edev->dev, host->ecb_dma_addr,
650 sizeof (host->ecb), DMA_BIDIRECTIONAL);
651 err_host_put:
652 scsi_host_put (shpnt);
653 err_release_region:
654 release_region(slotbase, SLOTSIZE);
656 return -ENODEV;
659 static __devexit int aha1740_remove (struct device *dev)
661 struct Scsi_Host *shpnt = dev->driver_data;
662 struct aha1740_hostdata *host = HOSTDATA (shpnt);
664 scsi_remove_host(shpnt);
666 free_irq (shpnt->irq, shpnt);
667 dma_unmap_single (dev, host->ecb_dma_addr,
668 sizeof (host->ecb), DMA_BIDIRECTIONAL);
669 release_region (shpnt->io_port, SLOTSIZE);
671 scsi_host_put (shpnt);
673 return 0;
676 static struct eisa_device_id aha1740_ids[] = {
677 { "ADP0000" }, /* 1740 */
678 { "ADP0001" }, /* 1740A */
679 { "ADP0002" }, /* 1742A */
680 { "ADP0400" }, /* 1744 */
681 { "" }
683 MODULE_DEVICE_TABLE(eisa, aha1740_ids);
685 static struct eisa_driver aha1740_driver = {
686 .id_table = aha1740_ids,
687 .driver = {
688 .name = "aha1740",
689 .probe = aha1740_probe,
690 .remove = __devexit_p (aha1740_remove),
694 static __init int aha1740_init (void)
696 return eisa_driver_register (&aha1740_driver);
699 static __exit void aha1740_exit (void)
701 eisa_driver_unregister (&aha1740_driver);
704 module_init (aha1740_init);
705 module_exit (aha1740_exit);
707 MODULE_LICENSE("GPL");