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>
55 #include <asm/system.h>
59 #include <scsi/scsi_host.h>
62 /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH
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
];
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
,
91 struct aha1740_hostdata
*hdata
= HOSTDATA (host
);
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
);
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
)
114 struct aha1740_hostdata
*host
;
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");
131 *start
= buffer
+ offset
;
138 static int aha1740_makecode(unchar
*sense
, unchar
*status
)
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 */
158 status_word
= * (struct statusword
*) status
;
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]);
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] ) {
170 if ( status_word
.dor
)
171 retval
=DID_ERROR
; /* It's an Overrun */
172 /* If not overrun, assume underrun and
174 case 0x00: /* No info, assume no error, should
182 retval
=DID_BAD_TARGET
;
187 /* Either by this driver or the
191 retval
=DID_ERROR
; /* No further
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");
203 if ( status
[0]&0x60 ) {
204 /* Didn't find a better error */
207 /* In any other case return DID_OK so for example
208 CONDITION_CHECKS make it through to the appropriate
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");
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
;
237 struct aha1740_sg
*sgptr
;
238 struct eisa_device
*edev
;
241 panic("aha1740.c: Irq from unknown host!\n");
242 spin_lock_irqsave(host
->host_lock
, flags
);
243 base
= host
->io_port
;
245 edev
= HOSTDATA(host
)->edev
;
247 while(inb(G2STAT(base
)) & G2STAT_INTPEND
) {
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
));
261 printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n",
262 inb(G2STAT(base
)),adapstat
,
263 inb(G2INTST(base
)), number_serviced
++);
266 SCtmp
= ecbptr
->SCpnt
;
268 printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n",
269 inb(G2STAT(base
)),adapstat
,
270 inb(G2INTST(base
)), number_serviced
++);
273 sgptr
= (struct aha1740_sg
*) SCtmp
->host_scribble
;
275 /* We used scatter-gather.
276 Do the unmapping dance. */
277 dma_unmap_sg (&edev
->dev
,
278 (struct scatterlist
*) SCtmp
->request_buffer
,
280 SCtmp
->sc_data_direction
);
282 dma_unmap_single (&edev
->dev
,
284 SCtmp
->request_bufflen
,
288 /* Free the sg block */
289 dma_free_coherent (&edev
->dev
,
290 sizeof (struct aha1740_sg
),
291 SCtmp
->host_scribble
,
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
);
306 printk("aha1740_intr_handle: returning %6x\n",
308 SCtmp
->result
= errstatus
;
309 my_done
= ecbptr
->done
;
310 memset(ecbptr
,0,sizeof(struct ecb
));
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",
325 inb(MBOXIN3(base
))); /* Say What? */
326 /* Host Ready -> Mailbox in complete */
327 outb(G2CNTRL_HRDY
,G2CNTRL(base
));
330 case G2INTST_CMDGOOD
:
331 /* set immediate command success flag here: */
334 case G2INTST_CMDERROR
:
335 /* Set immediate command failure flag here: */
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
*))
348 unchar
*cmd
= (unchar
*) SCpnt
->cmnd
;
349 unchar target
= scmd_id(SCpnt
);
350 struct aha1740_hostdata
*host
= HOSTDATA(SCpnt
->device
->host
);
352 void *buff
= SCpnt
->request_buffer
;
353 int bufflen
= SCpnt
->request_bufflen
;
355 struct aha1740_sg
*sgptr
;
359 if(*cmd
== REQUEST_SENSE
) {
366 if (*cmd
== READ_10
|| *cmd
== WRITE_10
)
367 i
= xscsi2int(cmd
+2);
368 else if (*cmd
== READ_6
|| *cmd
== WRITE_6
)
372 printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",
373 target
, *cmd
, i
, bufflen
);
375 for (i
= 0; i
< SCpnt
->cmd_len
; i
++) printk("%02x ", cmd
[i
]);
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
)
385 if (!host
->ecb
[ecbno
].cmdw
)
388 if (ecbno
>= AHA1740_ECBS
)
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
);
402 printk("Sending command (%d %x)...", ecbno
, done
);
405 host
->ecb
[ecbno
].cdblen
= SCpnt
->cmd_len
; /* SCSI Command
410 if (*cmd
== READ_10
|| *cmd
== READ_6
)
412 else if (*cmd
== WRITE_10
|| *cmd
== WRITE_6
)
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");
424 sgptr
= (struct aha1740_sg
*) SCpnt
->host_scribble
;
425 sgptr
->sg_dma_addr
= sg_dma
;
428 struct scatterlist
* sgpnt
;
429 struct aha1740_chain
* cptr
;
431 DEB(unsigned char * ptr
);
433 host
->ecb
[ecbno
].sg
= 1; /* SCSI Initiator Command
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
;
446 printk("cptr %x: ",cptr
);
447 ptr
= (unsigned char *) cptr
;
448 for(i
=0;i
<24;i
++) printk("%02x ", ptr
[i
]);
451 host
->ecb
[ecbno
].datalen
= bufflen
;
452 sgptr
->buf_dma_addr
= dma_map_single (&host
->edev
->dev
,
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
;
471 printk("aha1740_command: sending.. ");
472 for (i
= 0; i
< sizeof(host
->ecb
[ecbno
]) - 10; i
++)
473 printk("%02x ", ((unchar
*)&host
->ecb
[ecbno
])[i
]);
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. */
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
),
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
));
519 printk(KERN_ALERT
"aha1740_queuecommand: done can't be NULL\n");
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
)
543 int extended
= HOSTDATA(sdev
->host
)->translation
;
545 DEB(printk("aha1740_biosparam\n"));
546 if (extended
&& (ip
[2] > 1024)) {
549 ip
[2] = size
/ (255 * 63);
558 static int aha1740_eh_abort_handler (Scsi_Cmnd
*dummy
)
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...
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
,
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
)
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 */
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
));
616 goto err_release_region
;
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
);
625 host
->translation
= translation
;
626 host
->ecb_dma_addr
= dma_map_single (&edev
->dev
, host
->ecb
,
629 if (!host
->ecb_dma_addr
) {
630 printk (KERN_ERR
"aha1740_probe: Couldn't map ECB, giving up\n");
631 scsi_unregister (shpnt
);
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
,
638 printk(KERN_ERR
"aha1740_probe: Unable to allocate IRQ %d.\n",
643 eisa_set_drvdata (edev
, shpnt
);
645 rc
= scsi_add_host (shpnt
, dev
);
649 scsi_scan_host (shpnt
);
653 free_irq(irq_level
, shpnt
);
655 dma_unmap_single (&edev
->dev
, host
->ecb_dma_addr
,
656 sizeof (host
->ecb
), DMA_BIDIRECTIONAL
);
658 scsi_host_put (shpnt
);
660 release_region(slotbase
, SLOTSIZE
);
665 static __devexit
int aha1740_remove (struct device
*dev
)
667 struct Scsi_Host
*shpnt
= dev
->driver_data
;
668 struct aha1740_hostdata
*host
= HOSTDATA (shpnt
);
670 scsi_remove_host(shpnt
);
672 free_irq (shpnt
->irq
, shpnt
);
673 dma_unmap_single (dev
, host
->ecb_dma_addr
,
674 sizeof (host
->ecb
), DMA_BIDIRECTIONAL
);
675 release_region (shpnt
->io_port
, SLOTSIZE
);
677 scsi_host_put (shpnt
);
682 static struct eisa_device_id aha1740_ids
[] = {
683 { "ADP0000" }, /* 1740 */
684 { "ADP0001" }, /* 1740A */
685 { "ADP0002" }, /* 1742A */
686 { "ADP0400" }, /* 1744 */
689 MODULE_DEVICE_TABLE(eisa
, aha1740_ids
);
691 static struct eisa_driver aha1740_driver
= {
692 .id_table
= aha1740_ids
,
695 .probe
= aha1740_probe
,
696 .remove
= __devexit_p (aha1740_remove
),
700 static __init
int aha1740_init (void)
702 return eisa_driver_register (&aha1740_driver
);
705 static __exit
void aha1740_exit (void)
707 eisa_driver_unregister (&aha1740_driver
);
710 module_init (aha1740_init
);
711 module_exit (aha1740_exit
);
713 MODULE_LICENSE("GPL");