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 /* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH
58 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 $";
61 struct aha1740_hostdata
{
63 unsigned int translation
;
64 unsigned int last_ecb_used
;
65 struct ecb ecb
[AHA1740_ECBS
];
68 #define HOSTDATA(host) ((struct aha1740_hostdata *) &host->hostdata)
70 /* One for each IRQ level (9-15) */
71 static struct Scsi_Host
* aha_host
[8] = {NULL
, };
73 int aha1740_proc_info(char *buffer
, char **start
, off_t offset
,
74 int length
, int hostno
, int inout
)
77 struct Scsi_Host
* shpnt
;
78 struct aha1740_hostdata
*host
;
83 for (len
= 0; len
< 8; len
++) {
84 shpnt
= aha_host
[len
];
85 if (shpnt
&& shpnt
->host_no
== hostno
)
88 host
= HOSTDATA(shpnt
);
90 len
= sprintf(buffer
, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n"
91 "Extended translation %sabled.\n",
92 shpnt
->io_port
, shpnt
->irq
, host
->slot
,
93 host
->translation
? "en" : "dis");
100 *start
= buffer
+ offset
;
108 int aha1740_makecode(unchar
*sense
, unchar
*status
)
112 ushort don
:1, /* Command Done - No Error */
113 du
:1, /* Data underrun */
114 :1, qf
:1, /* Queue full */
115 sc
:1, /* Specification Check */
116 dor
:1, /* Data overrun */
117 ch
:1, /* Chaining Halted */
118 intr
:1, /* Interrupt issued */
119 asa
:1, /* Additional Status Available */
120 sns
:1, /* Sense information Stored */
121 :1, ini
:1, /* Initialization Required */
122 me
:1, /* Major error or exception */
123 :1, eca
:1, /* Extended Contingent alliance */
128 status_word
= * (struct statusword
*) status
;
130 printk("makecode from %x,%x,%x,%x %x,%x,%x,%x",
131 status
[0], status
[1], status
[2], status
[3],
132 sense
[0], sense
[1], sense
[2], sense
[3]);
134 if (!status_word
.don
) /* Anything abnormal was detected */
136 if ( (status
[1]&0x18) || status_word
.sc
) /*Additional info available*/
138 /* Use the supplied info for further diagnostics */
142 if ( status_word
.dor
)
143 retval
=DID_ERROR
; /* It's an Overrun */
144 /* If not overrun, assume underrun and ignore it! */
145 case 0x00: /* No info, assume no error, should not occur */
152 retval
=DID_BAD_TARGET
;
157 /* Either by this driver or the AHA1740 itself */
160 retval
=DID_ERROR
; /* No further diagnostics possible */
164 { /* Michael suggests, and Brad concurs: */
165 if ( status_word
.qf
)
167 retval
= DID_TIME_OUT
; /* forces a redo */
168 /* I think this specific one should not happen -Brad */
169 printk("aha1740.c: WARNING: AHA1740 queue overflow!\n");
171 else if ( status
[0]&0x60 )
173 retval
= DID_ERROR
; /* Didn't find a better error */
175 /* In any other case return DID_OK so for example
176 CONDITION_CHECKS make it through to the appropriate
180 /* Under all circumstances supply the target status -Michael */
181 return status
[3] | retval
<< 16;
184 int aha1740_test_port(unsigned int base
)
188 /* Okay, look for the EISA ID's */
189 name
[0]= 'A' -1 + ((tmp
= inb(HID0(base
))) >> 2); /* First character */
190 name
[1]= 'A' -1 + ((tmp
& 3) << 3);
191 name
[1]+= ((tmp
= inb(HID1(base
))) >> 5)&0x7; /* Second Character */
192 name
[2]= 'A' -1 + (tmp
& 0x1f); /* Third Character */
194 tmp
= inb(HID2(base
));
195 if ( strcmp ( name
, HID_MFG
) || inb(HID2(base
)) != HID_PRD
)
196 return 0; /* Not an Adaptec 174x */
198 /* if ( inb(HID3(base)) != HID_REV )
199 printk("aha174x: Warning; board revision of %d; expected %d\n",
200 inb(HID3(base)),HID_REV); */
202 if ( inb(EBCNTRL(base
)) != EBCNTRL_VALUE
)
204 printk("aha174x: Board detected, but EBCNTRL = %x, so disabled it.\n",
209 if ( inb(PORTADR(base
)) & PORTADDR_ENH
)
210 return 1; /* Okay, we're all set */
212 printk("aha174x: Board detected, but not in enhanced mode, so disabled it.\n");
216 /* A "high" level interrupt handler */
217 void aha1740_intr_handle(int irq
, void *dev_id
, struct pt_regs
* regs
)
219 void (*my_done
)(Scsi_Cmnd
*);
220 int errstatus
, adapstat
;
227 spin_lock_irqsave(&io_request_lock
, flags
);
229 if (!aha_host
[irq
- 9])
230 panic("aha1740.c: Irq from unknown host!\n");
231 base
= aha_host
[irq
- 9]->io_port
;
234 while(inb(G2STAT(base
)) & G2STAT_INTPEND
)
236 DEB(printk("aha1740_intr top of loop.\n"));
237 adapstat
= inb(G2INTST(base
));
238 ecbptr
= (struct ecb
*) bus_to_virt(inl(MBOXIN0(base
)));
239 outb(G2CNTRL_IRST
,G2CNTRL(base
)); /* interrupt reset */
241 switch ( adapstat
& G2INTST_MASK
)
243 case G2INTST_CCBRETRY
:
244 case G2INTST_CCBERROR
:
245 case G2INTST_CCBGOOD
:
246 /* Host Ready -> Mailbox in complete */
247 outb(G2CNTRL_HRDY
,G2CNTRL(base
));
250 printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n",
251 inb(G2STAT(base
)),adapstat
,
252 inb(G2INTST(base
)), number_serviced
++);
255 SCtmp
= ecbptr
->SCpnt
;
258 printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n",
259 inb(G2STAT(base
)),adapstat
,
260 inb(G2INTST(base
)), number_serviced
++);
263 if (SCtmp
->host_scribble
)
264 scsi_free(SCtmp
->host_scribble
, 512);
265 /* Fetch the sense data, and tuck it away, in the required slot.
266 The Adaptec automatically fetches it, and there is no
267 guarantee that we will still have it in the cdb when we come
269 if ( (adapstat
& G2INTST_MASK
) == G2INTST_CCBERROR
)
271 memcpy(SCtmp
->sense_buffer
, ecbptr
->sense
,
272 sizeof(SCtmp
->sense_buffer
));
273 errstatus
= aha1740_makecode(ecbptr
->sense
,ecbptr
->status
);
277 DEB(if (errstatus
) printk("aha1740_intr_handle: returning %6x\n",
279 SCtmp
->result
= errstatus
;
280 my_done
= ecbptr
->done
;
281 memset(ecbptr
,0,sizeof(struct ecb
));
285 case G2INTST_HARDFAIL
:
286 printk(KERN_ALERT
"aha1740 hardware failure!\n");
287 panic("aha1740.c"); /* Goodbye */
288 case G2INTST_ASNEVENT
:
289 printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n",
290 adapstat
, inb(MBOXIN0(base
)), inb(MBOXIN1(base
)),
291 inb(MBOXIN2(base
)), inb(MBOXIN3(base
))); /* Say What? */
292 /* Host Ready -> Mailbox in complete */
293 outb(G2CNTRL_HRDY
,G2CNTRL(base
));
295 case G2INTST_CMDGOOD
:
296 /* set immediate command success flag here: */
298 case G2INTST_CMDERROR
:
299 /* Set immediate command failure flag here: */
305 spin_unlock_irqrestore(&io_request_lock
, flags
);
308 int aha1740_queuecommand(Scsi_Cmnd
* SCpnt
, void (*done
)(Scsi_Cmnd
*))
311 unchar
*cmd
= (unchar
*) SCpnt
->cmnd
;
312 unchar target
= SCpnt
->target
;
313 struct aha1740_hostdata
*host
= HOSTDATA(SCpnt
->host
);
315 void *buff
= SCpnt
->request_buffer
;
316 int bufflen
= SCpnt
->request_bufflen
;
320 if(*cmd
== REQUEST_SENSE
)
322 if (bufflen
!= sizeof(SCpnt
->sense_buffer
))
324 printk("Wrong buffer length supplied for request sense (%d)\n",
333 if (*cmd
== READ_10
|| *cmd
== WRITE_10
)
334 i
= xscsi2int(cmd
+2);
335 else if (*cmd
== READ_6
|| *cmd
== WRITE_6
)
339 printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",
340 target
, *cmd
, i
, bufflen
);
342 for (i
= 0; i
< SCpnt
->cmd_len
; i
++) printk("%02x ", cmd
[i
]);
346 /* locate an available ecb */
349 ecbno
= host
->last_ecb_used
+ 1; /* An optimization */
350 if (ecbno
>= AHA1740_ECBS
)
353 if (!host
->ecb
[ecbno
].cmdw
)
356 if (ecbno
>= AHA1740_ECBS
)
358 } while (ecbno
!= host
->last_ecb_used
);
360 if (host
->ecb
[ecbno
].cmdw
)
361 panic("Unable to find empty ecb for aha1740.\n");
363 host
->ecb
[ecbno
].cmdw
= AHA1740CMD_INIT
; /* SCSI Initiator Command
364 doubles as reserved flag */
366 host
->last_ecb_used
= ecbno
;
367 restore_flags(flags
);
370 printk("Sending command (%d %x)...", ecbno
, done
);
373 host
->ecb
[ecbno
].cdblen
= SCpnt
->cmd_len
; /* SCSI Command Descriptor Block Length */
376 if (*cmd
== READ_10
|| *cmd
== READ_6
)
378 else if (*cmd
== WRITE_10
|| *cmd
== WRITE_6
)
381 memcpy(host
->ecb
[ecbno
].cdb
, cmd
, SCpnt
->cmd_len
);
385 struct scatterlist
* sgpnt
;
386 struct aha1740_chain
* cptr
;
388 DEB(unsigned char * ptr
);
390 host
->ecb
[ecbno
].sg
= 1; /* SCSI Initiator Command w/scatter-gather*/
391 SCpnt
->host_scribble
= (unsigned char *) scsi_malloc(512);
392 sgpnt
= (struct scatterlist
*) SCpnt
->request_buffer
;
393 cptr
= (struct aha1740_chain
*) SCpnt
->host_scribble
;
394 if (cptr
== NULL
) panic("aha1740.c: unable to allocate DMA memory\n");
395 for(i
=0; i
<SCpnt
->use_sg
; i
++)
397 cptr
[i
].datalen
= sgpnt
[i
].length
;
398 cptr
[i
].dataptr
= virt_to_bus(sgpnt
[i
].address
);
400 host
->ecb
[ecbno
].datalen
= SCpnt
->use_sg
* sizeof(struct aha1740_chain
);
401 host
->ecb
[ecbno
].dataptr
= virt_to_bus(cptr
);
403 printk("cptr %x: ",cptr
);
404 ptr
= (unsigned char *) cptr
;
405 for(i
=0;i
<24;i
++) printk("%02x ", ptr
[i
]);
410 SCpnt
->host_scribble
= NULL
;
411 host
->ecb
[ecbno
].datalen
= bufflen
;
412 host
->ecb
[ecbno
].dataptr
= virt_to_bus(buff
);
414 host
->ecb
[ecbno
].lun
= SCpnt
->lun
;
415 host
->ecb
[ecbno
].ses
= 1; /* Suppress underrun errors */
416 host
->ecb
[ecbno
].dir
= direction
;
417 host
->ecb
[ecbno
].ars
= 1; /* Yes, get the sense on an error */
418 host
->ecb
[ecbno
].senselen
= 12;
419 host
->ecb
[ecbno
].senseptr
= virt_to_bus(host
->ecb
[ecbno
].sense
);
420 host
->ecb
[ecbno
].statusptr
= virt_to_bus(host
->ecb
[ecbno
].status
);
421 host
->ecb
[ecbno
].done
= done
;
422 host
->ecb
[ecbno
].SCpnt
= SCpnt
;
426 printk("aha1740_command: sending.. ");
427 for (i
= 0; i
< sizeof(host
->ecb
[ecbno
]) - 10; i
++)
428 printk("%02x ", ((unchar
*)&host
->ecb
[ecbno
])[i
]);
433 { /* The Adaptec Spec says the card is so fast that the loops will
434 only be executed once in the code below. Even if this was true
435 with the fastest processors when the spec was written, it doesn't
436 seem to be true with todays fast processors. We print a warning
437 if the code is executed more often than LOOPCNT_WARN. If this
438 happens, it should be investigated. If the count reaches
439 LOOPCNT_MAX, we assume something is broken; since there is no
440 way to return an error (the return value is ignored by the
441 mid-level scsi layer) we have to panic (and maybe that's the
442 best thing we can do then anyhow). */
444 #define LOOPCNT_WARN 10 /* excessive mbxout wait -> syslog-msg */
445 #define LOOPCNT_MAX 1000000 /* mbxout deadlock -> panic() after ~ 2 sec. */
447 unsigned int base
= SCpnt
->host
->io_port
;
448 DEB(printk("aha1740[%d] critical section\n",ecbno
));
451 for (loopcnt
= 0; ; loopcnt
++) {
452 if (inb(G2STAT(base
)) & G2STAT_MBXOUT
) break;
453 if (loopcnt
== LOOPCNT_WARN
) {
454 printk("aha1740[%d]_mbxout wait!\n",ecbno
);
455 cli(); /* printk may have done a sti()! */
457 if (loopcnt
== LOOPCNT_MAX
)
458 panic("aha1740.c: mbxout busy!\n");
460 outl(virt_to_bus(host
->ecb
+ ecbno
), MBOXOUT0(base
));
461 for (loopcnt
= 0; ; loopcnt
++) {
462 if (! (inb(G2STAT(base
)) & G2STAT_BUSY
)) break;
463 if (loopcnt
== LOOPCNT_WARN
) {
464 printk("aha1740[%d]_attn wait!\n",ecbno
);
467 if (loopcnt
== LOOPCNT_MAX
)
468 panic("aha1740.c: attn wait failed!\n");
470 outb(ATTN_START
| (target
& 7), ATTN(base
)); /* Start it up */
471 restore_flags(flags
);
472 DEB(printk("aha1740[%d] request queued.\n",ecbno
));
475 printk(KERN_ALERT
"aha1740_queuecommand: done can't be NULL\n");
479 static void internal_done(Scsi_Cmnd
* SCpnt
)
484 int aha1740_command(Scsi_Cmnd
* SCpnt
)
486 aha1740_queuecommand(SCpnt
, internal_done
);
487 SCpnt
->SCp
.Status
= 0;
488 while (!SCpnt
->SCp
.Status
)
490 return SCpnt
->result
;
493 /* Query the board for its irq_level. Nothing else matters
494 in enhanced mode on an EISA bus. */
496 void aha1740_getconfig(unsigned int base
, unsigned int *irq_level
,
497 unsigned int *translation
)
499 static int intab
[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
501 *irq_level
= intab
[inb(INTDEF(base
)) & 0x7];
502 *translation
= inb(RESV1(base
)) & 0x1;
503 outb(inb(INTDEF(base
)) | 0x10, INTDEF(base
));
506 int aha1740_detect(Scsi_Host_Template
* tpnt
)
510 DEB(printk("aha1740_detect: \n"));
512 for ( slot
=MINEISA
; slot
<= MAXEISA
; slot
++ )
515 unsigned int irq_level
, translation
;
516 struct Scsi_Host
*shpnt
;
517 struct aha1740_hostdata
*host
;
518 slotbase
= SLOTBASE(slot
);
520 * The ioports for eisa boards are generally beyond that used in the
521 * check/allocate region code, but this may change at some point,
522 * so we go through the motions.
524 if (check_region(slotbase
, SLOTSIZE
)) /* See if in use */
526 if (!aha1740_test_port(slotbase
))
528 aha1740_getconfig(slotbase
,&irq_level
,&translation
);
529 if ((inb(G2STAT(slotbase
)) &
530 (G2STAT_MBXOUT
|G2STAT_BUSY
)) != G2STAT_MBXOUT
)
531 { /* If the card isn't ready, hard reset it */
532 outb(G2CNTRL_HRST
, G2CNTRL(slotbase
));
533 outb(0, G2CNTRL(slotbase
));
535 printk("Configuring aha174x at IO:%x, IRQ %d\n", slotbase
, irq_level
);
536 printk("aha174x: Extended translation %sabled.\n",
537 translation
? "en" : "dis");
538 DEB(printk("aha1740_detect: enable interrupt channel %d\n",irq_level
));
539 if (request_irq(irq_level
,aha1740_intr_handle
,0,"aha1740",NULL
)) {
540 printk("Unable to allocate IRQ for adaptec controller.\n");
543 shpnt
= scsi_register(tpnt
, sizeof(struct aha1740_hostdata
));
546 free_irq(irq_level
, NULL
);
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);
609 /* Eventually this will go into an include file, but this will be later */
610 static Scsi_Host_Template driver_template
= AHA1740
;
612 #include "scsi_module.c"
614 /* Okay, you made it all the way through. As of this writing, 3/31/93, I'm
615 brad@saturn.gaylord.com or brad@bradpc.gaylord.com. I'll try to help as time
616 permits if you have any trouble with this driver. Happy Linuxing! */