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
12 * Modifications to makecode and queuecommand
13 * for proper handling of multiple devices courteously
14 * provided by Michael Weller, March, 1993
16 * Multiple adapter support, extended translation detection,
17 * update to current scsi subsystem changes, proc fs support,
18 * working (!) module support based on patches from Andreas Arens,
19 * by Andreas Degert <ad@papyrus.hamburg.com>, 2/1997
21 * aha1740_makecode may still need even more work
22 * if it doesn't work for your devices, take a look.
26 #include <linux/module.h>
29 #include <linux/kernel.h>
30 #include <linux/types.h>
31 #include <linux/string.h>
32 #include <linux/ioport.h>
33 #include <linux/proc_fs.h>
34 #include <linux/sched.h>
37 #include <asm/system.h>
39 #include <linux/blk.h>
45 #include<linux/stat.h>
47 struct proc_dir_entry proc_scsi_aha1740
= {
48 PROC_SCSI_AHA1740
, 7, "aha1740",
49 S_IFDIR
| S_IRUGO
| S_IXUGO
, 2
52 /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH
63 static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha1740.c,v 1.1 1992/07/24 06:27:38 root Exp root $";
66 struct aha1740_hostdata
{
68 unsigned int translation
;
69 unsigned int last_ecb_used
;
70 struct ecb ecb
[AHA1740_ECBS
];
73 #define HOSTDATA(host) ((struct aha1740_hostdata *) &host->hostdata)
75 /* One for each IRQ level (9-15) */
76 static struct Scsi_Host
* aha_host
[8] = {NULL
, };
78 int aha1740_proc_info(char *buffer
, char **start
, off_t offset
,
79 int length
, int hostno
, int inout
)
82 struct Scsi_Host
* shpnt
;
83 struct aha1740_hostdata
*host
;
88 for (len
= 0; len
< 8; len
++) {
89 shpnt
= aha_host
[len
];
90 if (shpnt
&& shpnt
->host_no
== hostno
)
93 host
= HOSTDATA(shpnt
);
95 len
= sprintf(buffer
, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n"
96 "Extended translation %sabled.\n",
97 shpnt
->io_port
, shpnt
->irq
, host
->slot
,
98 host
->translation
? "en" : "dis");
105 *start
= buffer
+ offset
;
113 int aha1740_makecode(unchar
*sense
, unchar
*status
)
117 ushort don
:1, /* Command Done - No Error */
118 du
:1, /* Data underrun */
119 :1, qf
:1, /* Queue full */
120 sc
:1, /* Specification Check */
121 dor
:1, /* Data overrun */
122 ch
:1, /* Chaining Halted */
123 intr
:1, /* Interrupt issued */
124 asa
:1, /* Additional Status Available */
125 sns
:1, /* Sense information Stored */
126 :1, ini
:1, /* Initialization Required */
127 me
:1, /* Major error or exception */
128 :1, eca
:1, /* Extended Contingent alliance */
133 status_word
= * (struct statusword
*) status
;
135 printk("makecode from %x,%x,%x,%x %x,%x,%x,%x",
136 status
[0], status
[1], status
[2], status
[3],
137 sense
[0], sense
[1], sense
[2], sense
[3]);
139 if (!status_word
.don
) /* Anything abnormal was detected */
141 if ( (status
[1]&0x18) || status_word
.sc
) /*Additional info available*/
143 /* Use the supplied info for further diagnostics */
147 if ( status_word
.dor
)
148 retval
=DID_ERROR
; /* It's an Overrun */
149 /* If not overrun, assume underrun and ignore it! */
150 case 0x00: /* No info, assume no error, should not occur */
157 retval
=DID_BAD_TARGET
;
162 /* Either by this driver or the AHA1740 itself */
165 retval
=DID_ERROR
; /* No further diagnostics possible */
169 { /* Michael suggests, and Brad concurs: */
170 if ( status_word
.qf
)
172 retval
= DID_TIME_OUT
; /* forces a redo */
173 /* I think this specific one should not happen -Brad */
174 printk("aha1740.c: WARNING: AHA1740 queue overflow!\n");
176 else if ( status
[0]&0x60 )
178 retval
= DID_ERROR
; /* Didn't find a better error */
180 /* In any other case return DID_OK so for example
181 CONDITION_CHECKS make it through to the appropriate
185 /* Under all circumstances supply the target status -Michael */
186 return status
[3] | retval
<< 16;
189 int aha1740_test_port(unsigned int base
)
193 /* Okay, look for the EISA ID's */
194 name
[0]= 'A' -1 + ((tmp
= inb(HID0(base
))) >> 2); /* First character */
195 name
[1]= 'A' -1 + ((tmp
& 3) << 3);
196 name
[1]+= ((tmp
= inb(HID1(base
))) >> 5)&0x7; /* Second Character */
197 name
[2]= 'A' -1 + (tmp
& 0x1f); /* Third Character */
199 tmp
= inb(HID2(base
));
200 if ( strcmp ( name
, HID_MFG
) || inb(HID2(base
)) != HID_PRD
)
201 return 0; /* Not an Adaptec 174x */
203 /* if ( inb(HID3(base)) != HID_REV )
204 printk("aha174x: Warning; board revision of %d; expected %d\n",
205 inb(HID3(base)),HID_REV); */
207 if ( inb(EBCNTRL(base
)) != EBCNTRL_VALUE
)
209 printk("aha174x: Board detected, but EBCNTRL = %x, so disabled it.\n",
214 if ( inb(PORTADR(base
)) & PORTADDR_ENH
)
215 return 1; /* Okay, we're all set */
217 printk("aha174x: Board detected, but not in enhanced mode, so disabled it.\n");
221 /* A "high" level interrupt handler */
222 void aha1740_intr_handle(int irq
, void *dev_id
, struct pt_regs
* regs
)
224 void (*my_done
)(Scsi_Cmnd
*);
225 int errstatus
, adapstat
;
232 spin_lock_irqsave(&io_request_lock
, flags
);
234 if (!aha_host
[irq
- 9])
235 panic("aha1740.c: Irq from unknown host!\n");
236 base
= aha_host
[irq
- 9]->io_port
;
239 while(inb(G2STAT(base
)) & G2STAT_INTPEND
)
241 DEB(printk("aha1740_intr top of loop.\n"));
242 adapstat
= inb(G2INTST(base
));
243 ecbptr
= (struct ecb
*) bus_to_virt(inl(MBOXIN0(base
)));
244 outb(G2CNTRL_IRST
,G2CNTRL(base
)); /* interrupt reset */
246 switch ( adapstat
& G2INTST_MASK
)
248 case G2INTST_CCBRETRY
:
249 case G2INTST_CCBERROR
:
250 case G2INTST_CCBGOOD
:
251 /* Host Ready -> Mailbox in complete */
252 outb(G2CNTRL_HRDY
,G2CNTRL(base
));
255 printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n",
256 inb(G2STAT(base
)),adapstat
,
257 inb(G2INTST(base
)), number_serviced
++);
260 SCtmp
= ecbptr
->SCpnt
;
263 printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n",
264 inb(G2STAT(base
)),adapstat
,
265 inb(G2INTST(base
)), number_serviced
++);
268 if (SCtmp
->host_scribble
)
269 scsi_free(SCtmp
->host_scribble
, 512);
270 /* Fetch the sense data, and tuck it away, in the required slot.
271 The Adaptec automatically fetches it, and there is no
272 guarantee that we will still have it in the cdb when we come
274 if ( (adapstat
& G2INTST_MASK
) == G2INTST_CCBERROR
)
276 memcpy(SCtmp
->sense_buffer
, ecbptr
->sense
,
277 sizeof(SCtmp
->sense_buffer
));
278 errstatus
= aha1740_makecode(ecbptr
->sense
,ecbptr
->status
);
282 DEB(if (errstatus
) printk("aha1740_intr_handle: returning %6x\n",
284 SCtmp
->result
= errstatus
;
285 my_done
= ecbptr
->done
;
286 memset(ecbptr
,0,sizeof(struct ecb
));
290 case G2INTST_HARDFAIL
:
291 printk(KERN_ALERT
"aha1740 hardware failure!\n");
292 panic("aha1740.c"); /* Goodbye */
293 case G2INTST_ASNEVENT
:
294 printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n",
295 adapstat
, inb(MBOXIN0(base
)), inb(MBOXIN1(base
)),
296 inb(MBOXIN2(base
)), inb(MBOXIN3(base
))); /* Say What? */
297 /* Host Ready -> Mailbox in complete */
298 outb(G2CNTRL_HRDY
,G2CNTRL(base
));
300 case G2INTST_CMDGOOD
:
301 /* set immediate command success flag here: */
303 case G2INTST_CMDERROR
:
304 /* Set immediate command failure flag here: */
310 spin_unlock_irqrestore(&io_request_lock
, flags
);
313 int aha1740_queuecommand(Scsi_Cmnd
* SCpnt
, void (*done
)(Scsi_Cmnd
*))
316 unchar
*cmd
= (unchar
*) SCpnt
->cmnd
;
317 unchar target
= SCpnt
->target
;
318 struct aha1740_hostdata
*host
= HOSTDATA(SCpnt
->host
);
320 void *buff
= SCpnt
->request_buffer
;
321 int bufflen
= SCpnt
->request_bufflen
;
325 if(*cmd
== REQUEST_SENSE
)
327 if (bufflen
!= sizeof(SCpnt
->sense_buffer
))
329 printk("Wrong buffer length supplied for request sense (%d)\n",
338 if (*cmd
== READ_10
|| *cmd
== WRITE_10
)
339 i
= xscsi2int(cmd
+2);
340 else if (*cmd
== READ_6
|| *cmd
== WRITE_6
)
344 printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",
345 target
, *cmd
, i
, bufflen
);
347 for (i
= 0; i
< SCpnt
->cmd_len
; i
++) printk("%02x ", cmd
[i
]);
351 /* locate an available ecb */
354 ecbno
= host
->last_ecb_used
+ 1; /* An optimization */
355 if (ecbno
>= AHA1740_ECBS
)
358 if (!host
->ecb
[ecbno
].cmdw
)
361 if (ecbno
>= AHA1740_ECBS
)
363 } while (ecbno
!= host
->last_ecb_used
);
365 if (host
->ecb
[ecbno
].cmdw
)
366 panic("Unable to find empty ecb for aha1740.\n");
368 host
->ecb
[ecbno
].cmdw
= AHA1740CMD_INIT
; /* SCSI Initiator Command
369 doubles as reserved flag */
371 host
->last_ecb_used
= ecbno
;
372 restore_flags(flags
);
375 printk("Sending command (%d %x)...", ecbno
, done
);
378 host
->ecb
[ecbno
].cdblen
= SCpnt
->cmd_len
; /* SCSI Command Descriptor Block Length */
381 if (*cmd
== READ_10
|| *cmd
== READ_6
)
383 else if (*cmd
== WRITE_10
|| *cmd
== WRITE_6
)
386 memcpy(host
->ecb
[ecbno
].cdb
, cmd
, SCpnt
->cmd_len
);
390 struct scatterlist
* sgpnt
;
391 struct aha1740_chain
* cptr
;
393 DEB(unsigned char * ptr
);
395 host
->ecb
[ecbno
].sg
= 1; /* SCSI Initiator Command w/scatter-gather*/
396 SCpnt
->host_scribble
= (unsigned char *) scsi_malloc(512);
397 sgpnt
= (struct scatterlist
*) SCpnt
->request_buffer
;
398 cptr
= (struct aha1740_chain
*) SCpnt
->host_scribble
;
399 if (cptr
== NULL
) panic("aha1740.c: unable to allocate DMA memory\n");
400 for(i
=0; i
<SCpnt
->use_sg
; i
++)
402 cptr
[i
].datalen
= sgpnt
[i
].length
;
403 cptr
[i
].dataptr
= virt_to_bus(sgpnt
[i
].address
);
405 host
->ecb
[ecbno
].datalen
= SCpnt
->use_sg
* sizeof(struct aha1740_chain
);
406 host
->ecb
[ecbno
].dataptr
= virt_to_bus(cptr
);
408 printk("cptr %x: ",cptr
);
409 ptr
= (unsigned char *) cptr
;
410 for(i
=0;i
<24;i
++) printk("%02x ", ptr
[i
]);
415 SCpnt
->host_scribble
= NULL
;
416 host
->ecb
[ecbno
].datalen
= bufflen
;
417 host
->ecb
[ecbno
].dataptr
= virt_to_bus(buff
);
419 host
->ecb
[ecbno
].lun
= SCpnt
->lun
;
420 host
->ecb
[ecbno
].ses
= 1; /* Suppress underrun errors */
421 host
->ecb
[ecbno
].dir
= direction
;
422 host
->ecb
[ecbno
].ars
= 1; /* Yes, get the sense on an error */
423 host
->ecb
[ecbno
].senselen
= 12;
424 host
->ecb
[ecbno
].senseptr
= virt_to_bus(host
->ecb
[ecbno
].sense
);
425 host
->ecb
[ecbno
].statusptr
= virt_to_bus(host
->ecb
[ecbno
].status
);
426 host
->ecb
[ecbno
].done
= done
;
427 host
->ecb
[ecbno
].SCpnt
= SCpnt
;
431 printk("aha1740_command: sending.. ");
432 for (i
= 0; i
< sizeof(host
->ecb
[ecbno
]) - 10; i
++)
433 printk("%02x ", ((unchar
*)&host
->ecb
[ecbno
])[i
]);
438 { /* The Adaptec Spec says the card is so fast that the loops will
439 only be executed once in the code below. Even if this was true
440 with the fastest processors when the spec was written, it doesn't
441 seem to be true with todays fast processors. We print a warning
442 if the code is executed more often than LOOPCNT_WARN. If this
443 happens, it should be investigated. If the count reaches
444 LOOPCNT_MAX, we assume something is broken; since there is no
445 way to return an error (the return value is ignored by the
446 mid-level scsi layer) we have to panic (and maybe that's the
447 best thing we can do then anyhow). */
449 #define LOOPCNT_WARN 10 /* excessive mbxout wait -> syslog-msg */
450 #define LOOPCNT_MAX 1000000 /* mbxout deadlock -> panic() after ~ 2 sec. */
452 unsigned int base
= SCpnt
->host
->io_port
;
453 DEB(printk("aha1740[%d] critical section\n",ecbno
));
456 for (loopcnt
= 0; ; loopcnt
++) {
457 if (inb(G2STAT(base
)) & G2STAT_MBXOUT
) break;
458 if (loopcnt
== LOOPCNT_WARN
) {
459 printk("aha1740[%d]_mbxout wait!\n",ecbno
);
460 cli(); /* printk may have done a sti()! */
462 if (loopcnt
== LOOPCNT_MAX
)
463 panic("aha1740.c: mbxout busy!\n");
465 outl(virt_to_bus(host
->ecb
+ ecbno
), MBOXOUT0(base
));
466 for (loopcnt
= 0; ; loopcnt
++) {
467 if (! (inb(G2STAT(base
)) & G2STAT_BUSY
)) break;
468 if (loopcnt
== LOOPCNT_WARN
) {
469 printk("aha1740[%d]_attn wait!\n",ecbno
);
472 if (loopcnt
== LOOPCNT_MAX
)
473 panic("aha1740.c: attn wait failed!\n");
475 outb(ATTN_START
| (target
& 7), ATTN(base
)); /* Start it up */
476 restore_flags(flags
);
477 DEB(printk("aha1740[%d] request queued.\n",ecbno
));
480 printk(KERN_ALERT
"aha1740_queuecommand: done can't be NULL\n");
484 static void internal_done(Scsi_Cmnd
* SCpnt
)
489 int aha1740_command(Scsi_Cmnd
* SCpnt
)
491 aha1740_queuecommand(SCpnt
, internal_done
);
492 SCpnt
->SCp
.Status
= 0;
493 while (!SCpnt
->SCp
.Status
)
495 return SCpnt
->result
;
498 /* Query the board for its irq_level. Nothing else matters
499 in enhanced mode on an EISA bus. */
501 void aha1740_getconfig(unsigned int base
, unsigned int *irq_level
,
502 unsigned int *translation
)
504 static int intab
[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
506 *irq_level
= intab
[inb(INTDEF(base
)) & 0x7];
507 *translation
= inb(RESV1(base
)) & 0x1;
508 outb(inb(INTDEF(base
)) | 0x10, INTDEF(base
));
511 int aha1740_detect(Scsi_Host_Template
* tpnt
)
515 DEB(printk("aha1740_detect: \n"));
517 for ( slot
=MINEISA
; slot
<= MAXEISA
; slot
++ )
520 unsigned int irq_level
, translation
;
521 struct Scsi_Host
*shpnt
;
522 struct aha1740_hostdata
*host
;
523 slotbase
= SLOTBASE(slot
);
525 * The ioports for eisa boards are generally beyond that used in the
526 * check/allocate region code, but this may change at some point,
527 * so we go through the motions.
529 if (check_region(slotbase
, SLOTSIZE
)) /* See if in use */
531 if (!aha1740_test_port(slotbase
))
533 aha1740_getconfig(slotbase
,&irq_level
,&translation
);
534 if ((inb(G2STAT(slotbase
)) &
535 (G2STAT_MBXOUT
|G2STAT_BUSY
)) != G2STAT_MBXOUT
)
536 { /* If the card isn't ready, hard reset it */
537 outb(G2CNTRL_HRST
, G2CNTRL(slotbase
));
538 outb(0, G2CNTRL(slotbase
));
540 printk("Configuring aha174x at IO:%x, IRQ %d\n", slotbase
, irq_level
);
541 printk("aha174x: Extended translation %sabled.\n",
542 translation
? "en" : "dis");
543 DEB(printk("aha1740_detect: enable interrupt channel %d\n",irq_level
));
544 if (request_irq(irq_level
,aha1740_intr_handle
,0,"aha1740",NULL
)) {
545 printk("Unable to allocate IRQ for adaptec controller.\n");
548 shpnt
= scsi_register(tpnt
, sizeof(struct aha1740_hostdata
));
549 request_region(slotbase
, SLOTSIZE
, "aha1740");
551 shpnt
->io_port
= slotbase
;
552 shpnt
->n_io_port
= SLOTSIZE
;
553 shpnt
->irq
= irq_level
;
554 shpnt
->dma_channel
= 0xff;
555 host
= HOSTDATA(shpnt
);
557 host
->translation
= translation
;
558 aha_host
[irq_level
- 9] = shpnt
;
564 /* Note: They following two functions do not apply very well to the Adaptec,
565 which basically manages its own affairs quite well without our interference,
566 so I haven't put anything into them. I can faintly imagine someone with a
567 *very* badly behaved SCSI target (perhaps an old tape?) wanting the abort(),
568 but it hasn't happened yet, and doing aborts brings the Adaptec to its
569 knees. I cannot (at this moment in time) think of any reason to reset the
570 card once it's running. So there. */
572 int aha1740_abort(Scsi_Cmnd
* SCpnt
)
574 DEB(printk("aha1740_abort called\n"));
575 return SCSI_ABORT_SNOOZE
;
578 /* We do not implement a reset function here, but the upper level code assumes
579 that it will get some kind of response for the command in SCpnt. We must
580 oblige, or the command will hang the scsi system */
582 int aha1740_reset(Scsi_Cmnd
* SCpnt
, unsigned int ignored
)
584 DEB(printk("aha1740_reset called\n"));
585 return SCSI_RESET_PUNT
;
588 int aha1740_biosparam(Disk
* disk
, kdev_t dev
, int* ip
)
590 int size
= disk
->capacity
;
591 int extended
= HOSTDATA(disk
->device
->host
)->translation
;
593 DEB(printk("aha1740_biosparam\n"));
594 if (extended
&& (ip
[2] > 1024))
598 ip
[2] = size
/ (255 * 63);
610 /* Eventually this will go into an include file, but this will be later */
611 Scsi_Host_Template driver_template
= AHA1740
;
613 #include "scsi_module.c"
616 /* Okay, you made it all the way through. As of this writing, 3/31/93, I'm
617 brad@saturn.gaylord.com or brad@bradpc.gaylord.com. I'll try to help as time
618 permits if you have any trouble with this driver. Happy Linuxing! */