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@lxorguk.ukuu.org.uk>
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>
53 #include <linux/gfp.h>
56 #include <asm/system.h>
60 #include <scsi/scsi_host.h>
63 /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH
73 struct 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
];
82 struct aha1740_chain sg_chain
[AHA1740_SCATTER
];
83 dma_addr_t sg_dma_addr
;
84 dma_addr_t buf_dma_addr
;
87 #define HOSTDATA(host) ((struct aha1740_hostdata *) &host->hostdata)
89 static inline struct ecb
*ecb_dma_to_cpu (struct Scsi_Host
*host
,
92 struct aha1740_hostdata
*hdata
= HOSTDATA (host
);
95 offset
= dma
- hdata
->ecb_dma_addr
;
97 return (struct ecb
*)(((char *) hdata
->ecb
) + (unsigned int) offset
);
100 static inline dma_addr_t
ecb_cpu_to_dma (struct Scsi_Host
*host
, void *cpu
)
102 struct aha1740_hostdata
*hdata
= HOSTDATA (host
);
105 offset
= (char *) cpu
- (char *) hdata
->ecb
;
107 return hdata
->ecb_dma_addr
+ offset
;
110 static int aha1740_proc_info(struct Scsi_Host
*shpnt
, char *buffer
,
111 char **start
, off_t offset
,
112 int length
, int inout
)
115 struct aha1740_hostdata
*host
;
120 host
= HOSTDATA(shpnt
);
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");
132 *start
= buffer
+ offset
;
139 static int aha1740_makecode(unchar
*sense
, unchar
*status
)
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 */
159 status_word
= * (struct statusword
*) status
;
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]);
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] ) {
171 if ( status_word
.dor
)
172 retval
=DID_ERROR
; /* It's an Overrun */
173 /* If not overrun, assume underrun and
175 case 0x00: /* No info, assume no error, should
183 retval
=DID_BAD_TARGET
;
188 /* Either by this driver or the
192 retval
=DID_ERROR
; /* No further
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");
204 if ( status
[0]&0x60 ) {
205 /* Didn't find a better error */
208 /* In any other case return DID_OK so for example
209 CONDITION_CHECKS make it through to the appropriate
213 /* Under all circumstances supply the target status -Michael */
214 return status
[3] | retval
<< 16;
217 static int aha1740_test_port(unsigned int base
)
219 if ( inb(PORTADR(base
)) & PORTADDR_ENH
)
220 return 1; /* Okay, we're all set */
222 printk("aha174x: Board detected, but not in enhanced mode, so disabled it.\n");
226 /* A "high" level interrupt handler */
227 static irqreturn_t
aha1740_intr_handle(int irq
, void *dev_id
)
229 struct Scsi_Host
*host
= (struct Scsi_Host
*) dev_id
;
230 void (*my_done
)(Scsi_Cmnd
*);
231 int errstatus
, adapstat
;
238 struct aha1740_sg
*sgptr
;
239 struct eisa_device
*edev
;
242 panic("aha1740.c: Irq from unknown host!\n");
243 spin_lock_irqsave(host
->host_lock
, flags
);
244 base
= host
->io_port
;
246 edev
= HOSTDATA(host
)->edev
;
248 while(inb(G2STAT(base
)) & G2STAT_INTPEND
) {
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 */
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
));
262 printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n",
263 inb(G2STAT(base
)),adapstat
,
264 inb(G2INTST(base
)), number_serviced
++);
267 SCtmp
= ecbptr
->SCpnt
;
269 printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n",
270 inb(G2STAT(base
)),adapstat
,
271 inb(G2INTST(base
)), number_serviced
++);
274 sgptr
= (struct aha1740_sg
*) SCtmp
->host_scribble
;
275 scsi_dma_unmap(SCtmp
);
277 /* Free the sg block */
278 dma_free_coherent (&edev
->dev
,
279 sizeof (struct aha1740_sg
),
280 SCtmp
->host_scribble
,
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
);
295 printk("aha1740_intr_handle: returning %6x\n",
297 SCtmp
->result
= errstatus
;
298 my_done
= ecbptr
->done
;
299 memset(ecbptr
,0,sizeof(struct ecb
));
304 case G2INTST_HARDFAIL
:
305 printk(KERN_ALERT
"aha1740 hardware failure!\n");
306 panic("aha1740.c"); /* Goodbye */
308 case G2INTST_ASNEVENT
:
309 printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n",
314 inb(MBOXIN3(base
))); /* Say What? */
315 /* Host Ready -> Mailbox in complete */
316 outb(G2CNTRL_HRDY
,G2CNTRL(base
));
319 case G2INTST_CMDGOOD
:
320 /* set immediate command success flag here: */
323 case G2INTST_CMDERROR
:
324 /* Set immediate command failure flag here: */
330 spin_unlock_irqrestore(host
->host_lock
, flags
);
331 return IRQ_RETVAL(handled
);
334 static int aha1740_queuecommand_lck(Scsi_Cmnd
* SCpnt
, void (*done
)(Scsi_Cmnd
*))
337 unchar
*cmd
= (unchar
*) SCpnt
->cmnd
;
338 unchar target
= scmd_id(SCpnt
);
339 struct aha1740_hostdata
*host
= HOSTDATA(SCpnt
->device
->host
);
342 struct aha1740_sg
*sgptr
;
346 if(*cmd
== REQUEST_SENSE
) {
353 if (*cmd
== READ_10
|| *cmd
== WRITE_10
)
354 i
= xscsi2int(cmd
+2);
355 else if (*cmd
== READ_6
|| *cmd
== WRITE_6
)
359 printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",
360 target
, *cmd
, i
, bufflen
);
362 for (i
= 0; i
< SCpnt
->cmd_len
; i
++) printk("%02x ", cmd
[i
]);
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
)
372 if (!host
->ecb
[ecbno
].cmdw
)
375 if (ecbno
>= AHA1740_ECBS
)
377 } while (ecbno
!= host
->last_ecb_used
);
379 if (host
->ecb
[ecbno
].cmdw
)
380 panic("Unable to find empty ecb for aha1740.\n");
382 host
->ecb
[ecbno
].cmdw
= AHA1740CMD_INIT
; /* SCSI Initiator Command
383 doubles as reserved flag */
385 host
->last_ecb_used
= ecbno
;
386 spin_unlock_irqrestore(SCpnt
->device
->host
->host_lock
, flags
);
389 printk("Sending command (%d %x)...", ecbno
, done
);
392 host
->ecb
[ecbno
].cdblen
= SCpnt
->cmd_len
; /* SCSI Command
397 if (*cmd
== READ_10
|| *cmd
== READ_6
)
399 else if (*cmd
== WRITE_10
|| *cmd
== WRITE_6
)
402 memcpy(host
->ecb
[ecbno
].cdb
, cmd
, SCpnt
->cmd_len
);
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");
411 sgptr
= (struct aha1740_sg
*) SCpnt
->host_scribble
;
412 sgptr
->sg_dma_addr
= sg_dma
;
414 nseg
= scsi_dma_map(SCpnt
);
417 struct scatterlist
*sg
;
418 struct aha1740_chain
* cptr
;
420 DEB(unsigned char * ptr
);
422 host
->ecb
[ecbno
].sg
= 1; /* SCSI Initiator Command
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
);
429 host
->ecb
[ecbno
].datalen
= nseg
* sizeof(struct aha1740_chain
);
430 host
->ecb
[ecbno
].dataptr
= sg_dma
;
432 printk("cptr %x: ",cptr
);
433 ptr
= (unsigned char *) cptr
;
434 for(i
=0;i
<24;i
++) printk("%02x ", ptr
[i
]);
437 host
->ecb
[ecbno
].datalen
= 0;
438 host
->ecb
[ecbno
].dataptr
= 0;
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
;
454 printk("aha1740_command: sending.. ");
455 for (i
= 0; i
< sizeof(host
->ecb
[ecbno
]) - 10; i
++)
456 printk("%02x ", ((unchar
*)&host
->ecb
[ecbno
])[i
]);
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 todays 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). */
473 #define LOOPCNT_WARN 10 /* excessive mbxout wait -> syslog-msg */
474 #define LOOPCNT_MAX 1000000 /* mbxout deadlock -> panic() after ~ 2 sec. */
476 unsigned int base
= SCpnt
->device
->host
->io_port
;
477 DEB(printk("aha1740[%d] critical section\n",ecbno
));
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
);
485 if (loopcnt
== LOOPCNT_MAX
)
486 panic("aha1740.c: mbxout busy!\n");
488 outl (ecb_cpu_to_dma (SCpnt
->device
->host
, host
->ecb
+ ecbno
),
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
);
495 if (loopcnt
== LOOPCNT_MAX
)
496 panic("aha1740.c: attn wait failed!\n");
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
));
502 printk(KERN_ALERT
"aha1740_queuecommand: done can't be NULL\n");
506 static DEF_SCSI_QCMD(aha1740_queuecommand
)
508 /* Query the board for its irq_level and irq_type. Nothing else matters
509 in enhanced mode on an EISA bus. */
511 static void aha1740_getconfig(unsigned int base
, unsigned int *irq_level
,
512 unsigned int *irq_type
,
513 unsigned int *translation
)
515 static int intab
[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
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
));
523 static int aha1740_biosparam(struct scsi_device
*sdev
,
524 struct block_device
*dev
,
525 sector_t capacity
, int* ip
)
528 int extended
= HOSTDATA(sdev
->host
)->translation
;
530 DEB(printk("aha1740_biosparam\n"));
531 if (extended
&& (ip
[2] > 1024)) {
534 ip
[2] = size
/ (255 * 63);
543 static int aha1740_eh_abort_handler (Scsi_Cmnd
*dummy
)
547 * The AHA1740 has firmware handled abort/reset handling. The "head in
548 * sand" kernel code is correct for once 8)
550 * So we define a dummy handler just to keep the kernel SCSI code as
551 * quiet as possible...
557 static 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
,
566 .sg_tablesize
= AHA1740_SCATTER
,
567 .cmd_per_lun
= AHA1740_CMDLUN
,
568 .use_clustering
= ENABLE_CLUSTERING
,
569 .eh_abort_handler
= aha1740_eh_abort_handler
,
572 static int aha1740_probe (struct device
*dev
)
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
);
580 DEB(printk("aha1740_probe: \n"));
582 slotbase
= edev
->base_addr
+ EISA_VENDOR_ID_OFFSET
;
583 if (!request_region(slotbase
, SLOTSIZE
, "aha1740")) /* See if in use */
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
));
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
));
601 goto err_release_region
;
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
);
610 host
->translation
= translation
;
611 host
->ecb_dma_addr
= dma_map_single (&edev
->dev
, host
->ecb
,
614 if (!host
->ecb_dma_addr
) {
615 printk (KERN_ERR
"aha1740_probe: Couldn't map ECB, giving up\n");
616 scsi_unregister (shpnt
);
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
,
623 printk(KERN_ERR
"aha1740_probe: Unable to allocate IRQ %d.\n",
628 eisa_set_drvdata (edev
, shpnt
);
630 rc
= scsi_add_host (shpnt
, dev
);
634 scsi_scan_host (shpnt
);
638 free_irq(irq_level
, shpnt
);
640 dma_unmap_single (&edev
->dev
, host
->ecb_dma_addr
,
641 sizeof (host
->ecb
), DMA_BIDIRECTIONAL
);
643 scsi_host_put (shpnt
);
645 release_region(slotbase
, SLOTSIZE
);
650 static __devexit
int aha1740_remove (struct device
*dev
)
652 struct Scsi_Host
*shpnt
= dev_get_drvdata(dev
);
653 struct aha1740_hostdata
*host
= HOSTDATA (shpnt
);
655 scsi_remove_host(shpnt
);
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
);
662 scsi_host_put (shpnt
);
667 static struct eisa_device_id aha1740_ids
[] = {
668 { "ADP0000" }, /* 1740 */
669 { "ADP0001" }, /* 1740A */
670 { "ADP0002" }, /* 1742A */
671 { "ADP0400" }, /* 1744 */
674 MODULE_DEVICE_TABLE(eisa
, aha1740_ids
);
676 static struct eisa_driver aha1740_driver
= {
677 .id_table
= aha1740_ids
,
680 .probe
= aha1740_probe
,
681 .remove
= __devexit_p (aha1740_remove
),
685 static __init
int aha1740_init (void)
687 return eisa_driver_register (&aha1740_driver
);
690 static __exit
void aha1740_exit (void)
692 eisa_driver_unregister (&aha1740_driver
);
695 module_init (aha1740_init
);
696 module_exit (aha1740_exit
);
698 MODULE_LICENSE("GPL");