Fixed printf's so that they announce them selfs correctly (ie aha%d: before
[unix-history] / sys / i386 / isa / aha1542.c
CommitLineData
15637ed4
RG
1/*
2 * (Mostly) Written by Julian Elischer (julian@tfs.com)
3 * for TRW Financial Systems for use under the MACH(2.5) operating system.
4 *
5 * TRW Financial Systems, in accordance with their agreement with Carnegie
6 * Mellon University, makes this software available to CMU to distribute
7 * or use in any manner that they see fit as long as this message is kept with
8 * the software. For this reason TFS also grants any other persons or
9 * organisations permission to use or modify this software.
10 *
11 * TFS supplies this software to be publicly redistributed
12 * on the understanding that TFS is not responsible for the correct
13 * functioning of this software in any circumstances.
14 *
98639498 15 * $Id$
15637ed4
RG
16 */
17
18/*
19 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
20 */
21
15637ed4
RG
22/*
23 * a FEW lines in this driver come from a MACH adaptec-disk driver
24 * so the copyright below is included:
25 *
26 * Copyright 1990 by Open Software Foundation,
27 * Grenoble, FRANCE
28 *
29 * All Rights Reserved
30 *
31 * Permission to use, copy, modify, and distribute this software and
32 * its documentation for any purpose and without fee is hereby granted,
33 * provided that the above copyright notice appears in all copies and
34 * that both the copyright notice and this permission notice appear in
35 * supporting documentation, and that the name of OSF or Open Software
36 * Foundation not be used in advertising or publicity pertaining to
37 * distribution of the software without specific, written prior
38 * permission.
39 *
40 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
41 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
42 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
43 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
44 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
45 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
46 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
47 */
48
49
50#include <sys/types.h>
51#include <aha.h>
52
53#include <sys/param.h>
54#include <sys/systm.h>
55#include <sys/errno.h>
56#include <sys/ioctl.h>
57#include <sys/buf.h>
58#include <sys/proc.h>
59#include <sys/user.h>
60
61#ifdef MACH /* EITHER CMU OR OSF */
62#include <i386/ipl.h>
63#include <i386at/scsi.h>
64#include <i386at/scsiconf.h>
65
66#ifdef OSF /* OSF ONLY */
67#include <sys/table.h>
68#include <i386/handler.h>
69#include <i386/dispatcher.h>
70#include <i386/AT386/atbus.h>
71
72#else OSF /* CMU ONLY */
73#include <i386at/atbus.h>
74#include <i386/pio.h>
75#endif OSF
76#endif MACH /* end of MACH specific */
77
78#ifdef __386BSD__ /* 386BSD specific */
79#define isa_dev isa_device
80#define dev_unit id_unit
81#define dev_addr id_iobase
82
83#include <i386/isa/isa_device.h>
84#include <scsi/scsi_all.h>
85#include <scsi/scsiconf.h>
86#endif __386BSD__
87
88
89#ifdef __386BSD__
90#include "ddb.h"
91#if NDDB > 0
92int Debugger();
93#else NDDB
94#define Debugger() panic("should call debugger here (adaptec.c)")
95#endif NDDB
96#endif __386BSD__
b33502d5 97extern int hz;
15637ed4
RG
98extern int delaycount; /* from clock setup code */
99
100/************************** board definitions *******************************/
101/*
102 * I/O Port Interface
103 */
104
105#define AHA_BASE aha_base[unit]
106#define AHA_CTRL_STAT_PORT (AHA_BASE + 0x0) /* control & status */
107#define AHA_CMD_DATA_PORT (AHA_BASE + 0x1) /* cmds and datas */
108#define AHA_INTR_PORT (AHA_BASE + 0x2) /* Intr. stat */
109
110/*
111 * AHA_CTRL_STAT bits (write)
112 */
113
114#define AHA_HRST 0x80 /* Hardware reset */
115#define AHA_SRST 0x40 /* Software reset */
116#define AHA_IRST 0x20 /* Interrupt reset */
117#define AHA_SCRST 0x10 /* SCSI bus reset */
118
119/*
120 * AHA_CTRL_STAT bits (read)
121 */
122
123#define AHA_STST 0x80 /* Self test in Progress */
124#define AHA_DIAGF 0x40 /* Diagnostic Failure */
125#define AHA_INIT 0x20 /* Mbx Init required */
126#define AHA_IDLE 0x10 /* Host Adapter Idle */
127#define AHA_CDF 0x08 /* cmd/data out port full */
128#define AHA_DF 0x04 /* Data in port full */
129#define AHA_INVDCMD 0x01 /* Invalid command */
130
131/*
132 * AHA_CMD_DATA bits (write)
133 */
134
135#define AHA_NOP 0x00 /* No operation */
136#define AHA_MBX_INIT 0x01 /* Mbx initialization */
137#define AHA_START_SCSI 0x02 /* start scsi command */
138#define AHA_START_BIOS 0x03 /* start bios command */
139#define AHA_INQUIRE 0x04 /* Adapter Inquiry */
140#define AHA_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
141#define AHA_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
142#define AHA_BUS_ON_TIME_SET 0x07 /* set bus-on time */
143#define AHA_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
144#define AHA_SPEED_SET 0x09 /* set transfer speed */
145#define AHA_DEV_GET 0x0a /* return installed devices */
146#define AHA_CONF_GET 0x0b /* return configuration data */
147#define AHA_TARGET_EN 0x0c /* enable target mode */
148#define AHA_SETUP_GET 0x0d /* return setup data */
149#define AHA_WRITE_CH2 0x1a /* write channel 2 buffer */
150#define AHA_READ_CH2 0x1b /* read channel 2 buffer */
151#define AHA_WRITE_FIFO 0x1c /* write fifo buffer */
152#define AHA_READ_FIFO 0x1d /* read fifo buffer */
153#define AHA_ECHO 0x1e /* Echo command data */
154
155struct aha_cmd_buf {
156 u_char byte[16];
157};
158
159/*
160 * AHA_INTR_PORT bits (read)
161 */
162
163#define AHA_ANY_INTR 0x80 /* Any interrupt */
164#define AHA_SCRD 0x08 /* SCSI reset detected */
165#define AHA_HACC 0x04 /* Command complete */
166#define AHA_MBOA 0x02 /* MBX out empty */
167#define AHA_MBIF 0x01 /* MBX in full */
168
169/*
170 * Mail box defs
171 */
172
173#define AHA_MBX_SIZE 16 /* mail box size */
174
175struct aha_mbx {
176 struct aha_mbx_out {
177 unsigned char cmd;
178 unsigned char ccb_addr[3];
179 } mbo [AHA_MBX_SIZE];
180 struct aha_mbx_in{
181 unsigned char stat;
182 unsigned char ccb_addr[3];
183 } mbi[AHA_MBX_SIZE];
184};
185
186/*
187 * mbo.cmd values
188 */
189
190#define AHA_MBO_FREE 0x0 /* MBO entry is free */
191#define AHA_MBO_START 0x1 /* MBO activate entry */
192#define AHA_MBO_ABORT 0x2 /* MBO abort entry */
193
194#define AHA_MBI_FREE 0x0 /* MBI entry is free */
195#define AHA_MBI_OK 0x1 /* completed without error */
196#define AHA_MBI_ABORT 0x2 /* aborted ccb */
197#define AHA_MBI_UNKNOWN 0x3 /* Tried to abort invalid CCB */
198#define AHA_MBI_ERROR 0x4 /* Completed with error */
199
200extern struct aha_mbx aha_mbx[];
201
202/* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
203#define AHA_NSEG 17 /* Number of scatter gather segments <= 16 */
204 /* allow 64 K i/o (min) */
205
206struct aha_ccb {
207 unsigned char opcode;
208 unsigned char lun:3;
209 unsigned char data_in:1; /* must be 0 */
210 unsigned char data_out:1; /* must be 0 */
211 unsigned char target:3;
212 unsigned char scsi_cmd_length;
213 unsigned char req_sense_length;
214 unsigned char data_length[3];
215 unsigned char data_addr[3];
216 unsigned char link_addr[3];
217 unsigned char link_id;
218 unsigned char host_stat;
219 unsigned char target_stat;
220 unsigned char reserved[2];
221 struct scsi_generic scsi_cmd;
222 struct scsi_sense_data scsi_sense;
223 struct aha_scat_gath {
224 unsigned char seg_len[3];
225 unsigned char seg_addr[3];
226 } scat_gath[AHA_NSEG];
227 struct aha_ccb *next;
228 struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */
229 struct aha_mbx_out *mbx; /* pointer to mail box */
15637ed4
RG
230 int flags;
231#define CCB_FREE 0
232#define CCB_ACTIVE 1
233#define CCB_ABORTED 2
234
235};
236
15637ed4
RG
237
238/*
239 * opcode fields
240 */
241
242#define AHA_INITIATOR_CCB 0x00 /* SCSI Initiator CCB */
243#define AHA_TARGET_CCB 0x01 /* SCSI Target CCB */
244#define AHA_INIT_SCAT_GATH_CCB 0x02 /* SCSI Initiator with scattter gather*/
245#define AHA_RESET_CCB 0x81 /* SCSI Bus reset */
246
247
248/*
249 * aha_ccb.host_stat values
250 */
251
252#define AHA_OK 0x00 /* cmd ok */
253#define AHA_LINK_OK 0x0a /* Link cmd ok */
254#define AHA_LINK_IT 0x0b /* Link cmd ok + int */
255#define AHA_SEL_TIMEOUT 0x11 /* Selection time out */
256#define AHA_OVER_UNDER 0x12 /* Data over/under run */
257#define AHA_BUS_FREE 0x13 /* Bus dropped at unexpected time */
258#define AHA_INV_BUS 0x14 /* Invalid bus phase/sequence */
259#define AHA_BAD_MBO 0x15 /* Incorrect MBO cmd */
260#define AHA_BAD_CCB 0x16 /* Incorrect ccb opcode */
261#define AHA_BAD_LINK 0x17 /* Not same values of LUN for links */
262#define AHA_INV_TARGET 0x18 /* Invalid target direction */
263#define AHA_CCB_DUP 0x19 /* Duplicate CCB received */
264#define AHA_INV_CCB 0x1a /* Invalid CCB or segment list */
265#define AHA_ABORTED 42
266
267
268
269
270struct aha_setup
271{
272 u_char sync_neg:1;
273 u_char parity:1;
274 u_char :6;
275 u_char speed;
276 u_char bus_on;
277 u_char bus_off;
278 u_char num_mbx;
279 u_char mbx[3];
280 struct
281 {
282 u_char offset:4;
283 u_char period:3;
284 u_char valid:1;
285 }sync[8];
286 u_char disc_sts;
287};
288
289struct aha_config
290{
291 u_char chan;
292 u_char intr;
293 u_char scsi_dev:3;
294 u_char :5;
295};
296
297#define INT9 0x01
298#define INT10 0x02
299#define INT11 0x04
300#define INT12 0x08
301#define INT14 0x20
302#define INT15 0x40
303
304#define CHAN0 0x01
305#define CHAN5 0x20
306#define CHAN6 0x40
307#define CHAN7 0x80
308
309
310/*********************************** end of board definitions***************/
311
312
313#ifdef MACH
314#define PHYSTOKV(x) phystokv(x)
315#define KVTOPHYS(x) kvtophys(x)
316#else MACH
317#ifdef __386BSD__
318#define PHYSTOKV(x) (x | 0xFE000000)
319#define KVTOPHYS(x) vtophys(x)
320#else __386BSD__
321#endif __386BSD__
322#endif MACH
323#define AHA_DMA_PAGES AHA_NSEG
324
325#define PAGESIZ 4096
326#define INVALIDATE_CACHE {asm volatile( ".byte 0x0F ;.byte 0x08" ); }
327
328
329u_char aha_scratch_buf[256];
330#ifdef MACH
331caddr_t aha_base[NAHA]; /* base port for each board */
332#else
333short aha_base[NAHA]; /* base port for each board */
334#endif
335struct aha_mbx aha_mbx[NAHA];
336struct aha_ccb *aha_ccb_free[NAHA];
337struct aha_ccb aha_ccb[NAHA][AHA_MBX_SIZE];
338struct scsi_xfer aha_scsi_xfer[NAHA];
339struct isa_dev *ahainfo[NAHA];
340struct aha_ccb *aha_get_ccb();
341int aha_int[NAHA];
342int aha_dma[NAHA];
343int aha_scsi_dev[NAHA];
344int aha_initialized[NAHA];
345#ifdef OSF
346int aha_attached[NAHA];
347#endif OSF
b33502d5
RG
348#ifdef AHADEBUG
349int aha_debug = 1;
350#endif /*AHADEBUG*/
15637ed4
RG
351
352int ahaprobe(), ahaattach(), ahaintr();
353#ifdef MACH
354struct isa_driver ahadriver = { ahaprobe, 0, ahaattach, "aha", 0, 0, 0};
355int (*ahaintrs[])() = {ahaintr, 0};
356#endif
357#ifdef __386BSD__
358struct isa_driver ahadriver = { ahaprobe, ahaattach, "aha",};
359#endif __386BSD__
360static int ahaunit = 0;
361
362
363#define aha_abortmbx(mbx) \
364 (mbx)->cmd = AHA_MBO_ABORT; \
365 outb(AHA_CMD_DATA_PORT, AHA_START_SCSI);
366#define aha_startmbx(mbx) \
367 (mbx)->cmd = AHA_MBO_START; \
368 outb(AHA_CMD_DATA_PORT, AHA_START_SCSI);
369
370
371
372int aha_scsi_cmd();
373int aha_timeout();
374void ahaminphys();
375long int aha_adapter_info();
376
377struct scsi_switch aha_switch =
378{
98639498 379 "aha",
15637ed4
RG
380 aha_scsi_cmd,
381 ahaminphys,
382 0,
383 0,
384 aha_adapter_info,
385 0,0,0
386};
387#define AHA_CMD_TIMEOUT_FUDGE 200 /* multiplied to get Secs */
388#define AHA_RESET_TIMEOUT 1000000 /* time to wait for reset */
389#define AHA_SCSI_TIMEOUT_FUDGE 20 /* divided by for mSecs */
390
391
392/***********************************************************************\
393* aha_cmd(unit,icnt, ocnt,wait, retval, opcode, args) *
394* Activate Adapter command *
395* icnt: number of args (outbound bytes written after opcode) *
396* ocnt: number of expected returned bytes *
397* wait: number of seconds to wait for response *
398* retval: buffer where to place returned bytes *
399* opcode: opcode AHA_NOP, AHA_MBX_INIT, AHA_START_SCSI ... *
400* args: parameters *
401* *
402* Performs an adapter command through the ports. Not to be confused *
403* with a scsi command, which is read in via the dma *
404* One of the adapter commands tells it to read in a scsi command *
405\***********************************************************************/
406
407
408aha_cmd(unit,icnt, ocnt, wait,retval, opcode, args)
409
410u_char *retval;
411unsigned opcode;
412u_char args;
413{
414 unsigned *ic = &opcode;
415 u_char oc;
416 register i;
417 int sts;
418
419 /*******************************************************\
420 * multiply the wait argument by a big constant *
421 * zero defaults to 1 *
422 \*******************************************************/
423 if(!wait)
424 wait = AHA_CMD_TIMEOUT_FUDGE * delaycount;
425 else
426 wait *= AHA_CMD_TIMEOUT_FUDGE * delaycount;
427 /*******************************************************\
428 * Wait for the adapter to go idle, unless it's one of *
429 * the commands which don't need this *
430 \*******************************************************/
431 if (opcode != AHA_MBX_INIT && opcode != AHA_START_SCSI)
432 {
433 i = AHA_CMD_TIMEOUT_FUDGE * delaycount; /* 1 sec?*/
434 while (--i)
435 {
436 sts = inb(AHA_CTRL_STAT_PORT);
437 if (sts & AHA_IDLE)
438 {
439 break;
440 }
441 }
442 if (!i)
443 {
98639498
RG
444 printf("aha%d: aha_cmd, host not idle(0x%x)\n",
445 unit,sts);
15637ed4
RG
446 return(ENXIO);
447 }
448 }
449 /*******************************************************\
450 * Now that it is idle, if we expect output, preflush the*
451 * queue feeding to us. *
452 \*******************************************************/
453 if (ocnt)
454 {
455 while((inb(AHA_CTRL_STAT_PORT)) & AHA_DF)
456 inb(AHA_CMD_DATA_PORT);
457 }
458
459 /*******************************************************\
460 * Output the command and the number of arguments given *
461 * for each byte, first check the port is empty. *
462 \*******************************************************/
463 icnt++; /* include the command */
464 while (icnt--)
465 {
466 sts = inb(AHA_CTRL_STAT_PORT);
467 for (i=0; i< wait; i++)
468 {
469 sts = inb(AHA_CTRL_STAT_PORT);
470 if (!(sts & AHA_CDF))
471 break;
472 }
473 if (i >= wait)
474 {
98639498 475 printf("aha%d: aha_cmd, cmd/data port full\n",unit);
15637ed4
RG
476 outb(AHA_CTRL_STAT_PORT, AHA_SRST);
477 return(ENXIO);
478 }
479 outb(AHA_CMD_DATA_PORT, (u_char)(*ic++));
480 }
481 /*******************************************************\
482 * If we expect input, loop that many times, each time, *
483 * looking for the data register to have valid data *
484 \*******************************************************/
485 while (ocnt--)
486 {
487 sts = inb(AHA_CTRL_STAT_PORT);
488 for (i=0; i< wait; i++)
489 {
490 sts = inb(AHA_CTRL_STAT_PORT);
491 if (sts & AHA_DF)
492 break;
493 }
494 if (i >= wait)
495 {
98639498
RG
496 printf("aha%d: aha_cmd, cmd/data port empty %d\n",
497 unit,ocnt);
15637ed4
RG
498 return(ENXIO);
499 }
500 oc = inb(AHA_CMD_DATA_PORT);
501 if (retval)
502 *retval++ = oc;
503 }
504 /*******************************************************\
505 * Wait for the board to report a finised instruction *
506 \*******************************************************/
507 i=AHA_CMD_TIMEOUT_FUDGE * delaycount; /* 1 sec? */
508 while (--i)
509 {
510 sts = inb(AHA_INTR_PORT);
511 if (sts & AHA_HACC)
512 {
513 break;
514 }
515 }
516 if (!i)
517 {
98639498 518 printf("aha%d: aha_cmd, host not finished(0x%x)\n",unit,sts);
15637ed4
RG
519 return(ENXIO);
520 }
521 outb(AHA_CTRL_STAT_PORT, AHA_IRST);
522 return(0);
523}
524
525/*******************************************************\
526* Check if the device can be found at the port given *
527* and if so, set it up ready for further work *
528* as an argument, takes the isa_dev structure from *
529* autoconf.c *
530\*******************************************************/
531ahaprobe(dev)
532struct isa_dev *dev;
533{
534 int unit = ahaunit;
535#if defined(OSF)
536 static ihandler_t aha_handler[NAHA];
537 static ihandler_id_t *aha_handler_id[NAHA];
538 register ihandler_t *chp = &aha_handler[unit];;
539#endif /* defined(OSF) */
540
541 /***********************************************\
542 /***********************************************\
543 * find unit and check we have that many defined *
544 \***********************************************/
545 dev->dev_unit = unit;
546 aha_base[unit] = dev->dev_addr;
547 if(unit >= NAHA)
548 {
98639498 549 printf("aha%d: unit number too high\n",unit);
15637ed4
RG
550 return(0);
551 }
552 /***********************************************\
553 * Try initialise a unit at this location *
554 * sets up dma and bus speed, loads aha_int[unit]*
555 \***********************************************/
556 if (aha_init(unit) != 0)
557 {
558 return(0);
559 }
560
561 /***********************************************\
562 * If it's there, put in it's interrupt vectors *
563 \***********************************************/
564#if !defined(OSF)
565#if defined MACH
566 iunit[aha_int[unit]] =unit;
567 ivect[aha_int[unit]] = ahaintr;
568 intpri[aha_int[unit]] = dev->dev_spl;
569 form_pic_mask();
570 /*take_dev_irq(dev);*/
571#else
572#ifdef __386BSD__
573 dev->id_irq = (1 << aha_int[unit]);
574 dev->id_drq = aha_dma[unit];
575#endif __386BSD__
576#endif
577#else /* !defined(OSF) */
578
ec134874 579 dev->dev_pic = aha_dma[unit];
15637ed4
RG
580 chp->ih_level = dev->dev_pic;
581 chp->ih_handler = dev->dev_intr[0];
582 chp->ih_resolver = i386_resolver;
583 chp->ih_rdev = dev;
584 chp->ih_stats.intr_type = INTR_DEVICE;
585 chp->ih_stats.intr_cnt = 0;
586 chp->ih_hparam[0].intparam = unit;
587 if ((aha_handler_id[unit] = handler_add(chp)) != NULL)
588 handler_enable(aha_handler_id[unit]);
589 else
590 panic("Unable to add aha interrupt handler");
591#endif /* !defined(OSF) */
98639498
RG
592#ifndef __386BSD__
593 printf("port=%x spl=%d\n", dev->dev_addr, dev->dev_spl);
15637ed4
RG
594#endif __386BSD__
595 ahaunit ++;
596 return(1);
597}
598
599/***********************************************\
600* Attach all the sub-devices we can find *
601\***********************************************/
602ahaattach(dev)
603struct isa_dev *dev;
604{
605 int unit = dev->dev_unit;
606
15637ed4
RG
607 /***********************************************\
608 * ask the adapter what subunits are present *
609 \***********************************************/
610 scsi_attachdevs( unit, aha_scsi_dev[unit], &aha_switch);
611#if defined(OSF)
612 aha_attached[unit]=1;
613#endif /* defined(OSF) */
15637ed4 614 return;
15637ed4
RG
615}
616
15637ed4
RG
617/***********************************************\
618* Return some information to the caller about *
619* the adapter and it's capabilities *
620\***********************************************/
621long int aha_adapter_info(unit)
622int unit;
623{
624 return(2); /* 2 outstanding requests at a time per device */
625}
626
627/***********************************************\
628* Catch an interrupt from the adaptor *
629\***********************************************/
630ahaintr(unit)
631{
632 struct aha_ccb *ccb;
633 unsigned char stat;
634 register i;
635
b33502d5 636#ifdef AHADEBUG
15637ed4
RG
637 if(scsi_debug & PRINTROUTINES)
638 printf("ahaintr ");
b33502d5 639#endif /*AHADEBUG*/
15637ed4
RG
640 /***********************************************\
641 * First acknowlege the interrupt, Then if it's *
642 * not telling about a completed operation *
643 * just return. *
644 \***********************************************/
645 stat = inb(AHA_INTR_PORT);
646 outb(AHA_CTRL_STAT_PORT, AHA_IRST);
b33502d5 647#ifdef AHADEBUG
15637ed4
RG
648 if(scsi_debug & TRACEINTERRUPTS)
649 printf("int ");
b33502d5 650#endif /*AHADEBUG*/
15637ed4
RG
651 if (! (stat & AHA_MBIF))
652 return(1);
b33502d5 653#ifdef AHADEBUG
15637ed4
RG
654 if(scsi_debug & TRACEINTERRUPTS)
655 printf("b ");
b33502d5 656#endif /*AHADEBUG*/
15637ed4
RG
657#if defined(OSF)
658 if (!aha_attached[unit])
659 {
660 return(1);
661 }
662#endif /* defined(OSF) */
663 /***********************************************\
664 * If it IS then process the competed operation *
665 \***********************************************/
666 for (i = 0; i < AHA_MBX_SIZE; i++)
667 {
668 if (aha_mbx[unit].mbi[i].stat != AHA_MBI_FREE)
669 {
670 ccb = (struct aha_ccb *)PHYSTOKV(
671 (_3btol(aha_mbx[unit].mbi[i].ccb_addr)));
672
673 if((stat = aha_mbx[unit].mbi[i].stat) != AHA_MBI_OK)
674 {
675 switch(stat)
676 {
677 case AHA_MBI_ABORT:
b33502d5 678#ifdef AHADEBUG
15637ed4
RG
679 if(aha_debug)
680 printf("abort");
b33502d5 681#endif /*AHADEBUG*/
15637ed4
RG
682 ccb->host_stat = AHA_ABORTED;
683 break;
684
685 case AHA_MBI_UNKNOWN:
686 ccb = (struct aha_ccb *)0;
b33502d5 687#ifdef AHADEBUG
15637ed4
RG
688 if(aha_debug)
689 printf("unknown ccb for abort ");
b33502d5 690#endif /*AHADEBUG*/
15637ed4
RG
691 /* may have missed it */
692 /* no such ccb known for abort */
693
694 case AHA_MBI_ERROR:
695 break;
696
697 default:
698 panic("Impossible mbxi status");
699
700 }
b33502d5 701#ifdef AHADEBUG
15637ed4
RG
702 if( aha_debug && ccb )
703 {
704 u_char *cp;
705 cp = (u_char *)(&(ccb->scsi_cmd));
706 printf("op=%x %x %x %x %x %x\n",
707 cp[0], cp[1], cp[2],
708 cp[3], cp[4], cp[5]);
709 printf("stat %x for mbi[%d]\n"
710 , aha_mbx[unit].mbi[i].stat, i);
711 printf("addr = 0x%x\n", ccb);
712 }
b33502d5 713#endif /*AHADEBUG*/
15637ed4
RG
714 }
715 if(ccb)
716 {
b33502d5 717 untimeout(aha_timeout,ccb);
15637ed4
RG
718 aha_done(unit,ccb);
719 }
720 aha_mbx[unit].mbi[i].stat = AHA_MBI_FREE;
721 }
722 }
723 return(1);
724}
725
726/***********************************************\
727* A ccb (and hence a mbx-out is put onto the *
728* free list. *
729\***********************************************/
730aha_free_ccb(unit,ccb, flags)
731struct aha_ccb *ccb;
732{
733 unsigned int opri;
734
b33502d5 735#ifdef AHADEBUG
15637ed4
RG
736 if(scsi_debug & PRINTROUTINES)
737 printf("ccb%d(0x%x)> ",unit,flags);
b33502d5 738#endif /*AHADEBUG*/
15637ed4
RG
739 if (!(flags & SCSI_NOMASK))
740 opri = splbio();
741
742 ccb->next = aha_ccb_free[unit];
743 aha_ccb_free[unit] = ccb;
744 ccb->flags = CCB_FREE;
15637ed4
RG
745 /***********************************************\
746 * If there were none, wake abybody waiting for *
747 * one to come free, starting with queued entries*
748 \***********************************************/
749 if (!ccb->next) {
750 wakeup(&aha_ccb_free[unit]);
751 }
752 if (!(flags & SCSI_NOMASK))
753 splx(opri);
754}
755
756/***********************************************\
757* Get a free ccb (and hence mbox-out entry) *
758\***********************************************/
759struct aha_ccb *
760aha_get_ccb(unit,flags)
761{
762 unsigned opri;
763 struct aha_ccb *rc;
764
b33502d5 765#ifdef AHADEBUG
15637ed4
RG
766 if(scsi_debug & PRINTROUTINES)
767 printf("<ccb%d(0x%x) ",unit,flags);
b33502d5 768#endif /*AHADEBUG*/
15637ed4
RG
769 if (!(flags & SCSI_NOMASK))
770 opri = splbio();
771 /***********************************************\
772 * If we can and have to, sleep waiting for one *
773 * to come free *
774 \***********************************************/
775 while ((!(rc = aha_ccb_free[unit])) && (!(flags & SCSI_NOSLEEP)))
776 {
777 sleep(&aha_ccb_free[unit], PRIBIO);
778 }
779 if (rc)
780 {
781 aha_ccb_free[unit] = aha_ccb_free[unit]->next;
782 rc->flags = CCB_ACTIVE;
783 }
784 if (!(flags & SCSI_NOMASK))
785 splx(opri);
786 return(rc);
787}
788
789
790/***********************************************\
791* We have a ccb which has been processed by the *
792* adaptor, now we look to see how the operation *
793* went. Wake up the owner if waiting *
794\***********************************************/
795aha_done(unit,ccb)
796struct aha_ccb *ccb;
797{
798 struct scsi_sense_data *s1,*s2;
799 struct scsi_xfer *xs = ccb->xfer;
800
b33502d5 801#ifdef AHADEBUG
15637ed4
RG
802 if(scsi_debug & PRINTROUTINES )
803 printf("aha_done ");
b33502d5 804#endif /*AHADEBUG*/
15637ed4
RG
805 /***********************************************\
806 * Otherwise, put the results of the operation *
807 * into the xfer and call whoever started it *
808 \***********************************************/
809 if(!(xs->flags & INUSE))
810 {
98639498 811 printf("aha%d: exiting but not in use!\n",unit);
15637ed4
RG
812 Debugger();
813 }
814 if ( ( ccb->host_stat != AHA_OK
815 || ccb->target_stat != SCSI_OK)
816 && (!(xs->flags & SCSI_ERR_OK)))
817 {
818 s1 = (struct scsi_sense_data *)(((char *)(&ccb->scsi_cmd))
819 + ccb->scsi_cmd_length);
820 s2 = &(xs->sense);
821
822 if(ccb->host_stat)
823 {
824 switch(ccb->host_stat)
825 {
826 case AHA_ABORTED:
827 case AHA_SEL_TIMEOUT: /* No response */
828 xs->error = XS_TIMEOUT;
829 break;
830 default: /* Other scsi protocol messes */
831 xs->error = XS_DRIVER_STUFFUP;
b33502d5 832#ifdef AHADEBUG
15637ed4
RG
833 if (aha_debug > 1)
834 {
835 printf("host_stat%x\n",
836 ccb->host_stat);
837 }
b33502d5 838#endif /*AHADEBUG*/
15637ed4
RG
839 }
840
841 }
842 else
843 {
844 switch(ccb->target_stat)
845 {
846 case 0x02:
847 /* structure copy!!!!!*/
848 *s2=*s1;
849 xs->error = XS_SENSE;
850 break;
851 case 0x08:
852 xs->error = XS_BUSY;
853 break;
854 default:
b33502d5 855#ifdef AHADEBUG
15637ed4
RG
856 if (aha_debug > 1)
857 {
858 printf("target_stat%x\n",
859 ccb->target_stat);
860 }
b33502d5 861#endif /*AHADEBUG*/
15637ed4
RG
862 xs->error = XS_DRIVER_STUFFUP;
863 }
864 }
865 }
866 else /* All went correctly OR errors expected */
867 {
868 xs->resid = 0;
869 }
870 xs->flags |= ITSDONE;
871 aha_free_ccb(unit,ccb, xs->flags);
872 if(xs->when_done)
873 (*(xs->when_done))(xs->done_arg,xs->done_arg2);
874}
875
876
877/***********************************************\
878* Start the board, ready for normal operation *
879\***********************************************/
880aha_init(unit)
881int unit;
882{
883 unsigned char ad[3];
884 volatile int i,sts;
885 struct aha_config conf;
886
887 /***********************************************\
888 * reset board, If it doesn't respond, assume *
889 * that it's not there.. good for the probe *
890 \***********************************************/
891
892 outb(AHA_CTRL_STAT_PORT, AHA_HRST|AHA_SRST);
893
894 for (i=0; i < AHA_RESET_TIMEOUT; i++)
895 {
896 sts = inb(AHA_CTRL_STAT_PORT) ;
897 if ( sts == (AHA_IDLE | AHA_INIT))
898 break;
899 }
900 if (i >= AHA_RESET_TIMEOUT)
901 {
b33502d5 902#ifdef AHADEBUG
15637ed4
RG
903 if (aha_debug)
904 printf("aha_init: No answer from adaptec board\n");
b33502d5 905#endif /*AHADEBUG*/
15637ed4
RG
906 return(ENXIO);
907 }
908
909 /***********************************************\
910 * Assume we have a board at this stage *
911 * setup dma channel from jumpers and save int *
912 * level *
913 \***********************************************/
914#ifdef __386BSD__
98639498
RG
915 printf("aha%d: reading board settings, ",unit);
916#define PRNT(x) printf(x)
15637ed4
RG
917#else __386BSD__
918 printf("aha%d:",unit);
919#define PRNT(x) printf(x)
920#endif __386BSD__
98639498 921 DELAY(1000); /* for Bustek 545 */
15637ed4
RG
922 aha_cmd(unit,0, sizeof(conf), 0 ,&conf, AHA_CONF_GET);
923 switch(conf.chan)
924 {
925 case CHAN0:
926 outb(0x0b, 0x0c);
927 outb(0x0a, 0x00);
928 aha_dma[unit] = 0;
929 PRNT("dma=0 ");
930 break;
931 case CHAN5:
932 outb(0xd6, 0xc1);
933 outb(0xd4, 0x01);
934 aha_dma[unit] = 5;
935 PRNT("dma=5 ");
936 break;
937 case CHAN6:
938 outb(0xd6, 0xc2);
939 outb(0xd4, 0x02);
940 aha_dma[unit] = 6;
941 PRNT("dma=6 ");
942 break;
943 case CHAN7:
944 outb(0xd6, 0xc3);
945 outb(0xd4, 0x03);
946 aha_dma[unit] = 7;
947 PRNT("dma=7 ");
948 break;
949 default:
950 printf("illegal dma jumper setting\n");
951 return(EIO);
952 }
953 switch(conf.intr)
954 {
955 case INT9:
956 aha_int[unit] = 9;
957 PRNT("int=9 ");
958 break;
959 case INT10:
960 aha_int[unit] = 10;
961 PRNT("int=10 ");
962 break;
963 case INT11:
964 aha_int[unit] = 11;
965 PRNT("int=11 ");
966 break;
967 case INT12:
968 aha_int[unit] = 12;
969 PRNT("int=12 ");
970 break;
971 case INT14:
972 aha_int[unit] = 14;
973 PRNT("int=14 ");
974 break;
975 case INT15:
976 aha_int[unit] = 15;
977 PRNT("int=15 ");
978 break;
979 default:
980 printf("illegal int jumper setting\n");
981 return(EIO);
982 }
983 /* who are we on the scsi bus */
984 aha_scsi_dev[unit] = conf.scsi_dev;
985
986
987 /***********************************************\
988 * Initialize memory transfer speed *
989 \***********************************************/
990 if(!(aha_set_bus_speed(unit)))
991 {
992 return(EIO);
993 }
994
995
996 /***********************************************\
997 * Initialize mail box *
998 \***********************************************/
999
1000 lto3b(KVTOPHYS(&aha_mbx[unit]), ad);
1001
1002 aha_cmd(unit,4, 0, 0, 0, AHA_MBX_INIT,
1003 AHA_MBX_SIZE,
1004 ad[0],
1005 ad[1],
1006 ad[2]);
1007
1008
1009 /***********************************************\
1010 * link the ccb's with the mbox-out entries and *
1011 * into a free-list *
1012 \***********************************************/
1013 for (i=0; i < AHA_MBX_SIZE; i++) {
1014 aha_ccb[unit][i].next = aha_ccb_free[unit];
1015 aha_ccb_free[unit] = &aha_ccb[unit][i];
1016 aha_ccb_free[unit]->flags = CCB_FREE;
1017 aha_ccb_free[unit]->mbx = &aha_mbx[unit].mbo[i];
1018 lto3b(KVTOPHYS(aha_ccb_free[unit]), aha_mbx[unit].mbo[i].ccb_addr);
1019 }
1020
1021 /***********************************************\
1022 * Note that we are going and return (to probe) *
1023 \***********************************************/
1024 aha_initialized[unit]++;
1025 return(0);
1026}
1027
1028
1029
1030
1031
1032void ahaminphys(bp)
1033struct buf *bp;
1034{
1035#ifdef MACH
1036#if !defined(OSF)
1037 bp->b_flags |= B_NPAGES; /* can support scat/gather */
1038#endif /* !defined(OSF) */
1039#endif MACH
1040/* aha seems to explode with 17 segs (64k may require 17 segs) */
1041/* on old boards so use a max of 16 segs if you have problems here*/
1042 if(bp->b_bcount > ((AHA_NSEG - 1) * PAGESIZ))
1043 {
1044 bp->b_bcount = ((AHA_NSEG - 1) * PAGESIZ);
1045 }
1046}
1047
1048/***********************************************\
1049* start a scsi operation given the command and *
1050* the data address. Also needs the unit, target *
1051* and lu *
1052\***********************************************/
1053int aha_scsi_cmd(xs)
1054struct scsi_xfer *xs;
1055{
1056 struct scsi_sense_data *s1,*s2;
1057 struct aha_ccb *ccb;
1058 struct aha_scat_gath *sg;
1059 int seg; /* scatter gather seg being worked on */
1060 int i = 0;
1061 int rc = 0;
1062 int thiskv;
1063 int thisphys,nextphys;
1064 int unit =xs->adapter;
1065 int bytes_this_seg,bytes_this_page,datalen,flags;
1066 struct iovec *iovp;
1067 int s;
1068
b33502d5 1069#ifdef AHADEBUG
15637ed4
RG
1070 if(scsi_debug & PRINTROUTINES)
1071 printf("aha_scsi_cmd ");
b33502d5 1072#endif /*AHADEBUG*/
15637ed4
RG
1073 /***********************************************\
1074 * get a ccb (mbox-out) to use. If the transfer *
1075 * is from a buf (possibly from interrupt time) *
1076 * then we can't allow it to sleep *
1077 \***********************************************/
1078 flags = xs->flags;
1079 if(!(flags & INUSE))
1080 {
98639498 1081 printf("aha%d: not in use!\n",unit);
15637ed4
RG
1082 Debugger();
1083 xs->flags |= INUSE;
1084 }
1085 if(flags & ITSDONE)
1086 {
98639498 1087 printf("aha%d: Already done! check device retry code\n",unit);
15637ed4
RG
1088 Debugger();
1089 xs->flags &= ~ITSDONE;
1090 }
1091 if(xs->bp) flags |= (SCSI_NOSLEEP); /* just to be sure */
1092 if (!(ccb = aha_get_ccb(unit,flags)))
1093 {
1094 xs->error = XS_DRIVER_STUFFUP;
1095 return(TRY_AGAIN_LATER);
1096 }
1097
1098 if (ccb->mbx->cmd != AHA_MBO_FREE)
98639498 1099 printf("aha%d: MBO not free\n",unit);
15637ed4
RG
1100
1101 /***********************************************\
1102 * Put all the arguments for the xfer in the ccb *
1103 \***********************************************/
1104 ccb->xfer = xs;
1105 if(flags & SCSI_RESET)
1106 {
1107 ccb->opcode = AHA_RESET_CCB;
1108 }
1109 else
1110 {
1111 /* can't use S/G if zero length */
1112 ccb->opcode = (xs->datalen?
1113 AHA_INIT_SCAT_GATH_CCB
1114 :AHA_INITIATOR_CCB);
1115 }
1116 ccb->target = xs->targ;;
1117 ccb->data_out = 0;
1118 ccb->data_in = 0;
1119 ccb->lun = xs->lu;
1120 ccb->scsi_cmd_length = xs->cmdlen;
1121 ccb->req_sense_length = sizeof(ccb->scsi_sense);
1122
1123 if((xs->datalen) && (!(flags & SCSI_RESET)))
1124 { /* can use S/G only if not zero length */
1125 lto3b(KVTOPHYS(ccb->scat_gath), ccb->data_addr );
1126 sg = ccb->scat_gath ;
1127 seg = 0;
1128 if(flags & SCSI_DATA_UIO)
1129 {
1130 iovp = ((struct uio *)xs->data)->uio_iov;
1131 datalen = ((struct uio *)xs->data)->uio_iovcnt;
1132 while ((datalen) && (seg < AHA_NSEG))
1133 {
1134 lto3b(iovp->iov_base,&(sg->seg_addr));
1135 lto3b(iovp->iov_len,&(sg->seg_len));
b33502d5 1136#ifdef AHADEBUG
15637ed4
RG
1137 if(scsi_debug & SHOWSCATGATH)
1138 printf("(0x%x@0x%x)"
1139 ,iovp->iov_len
1140 ,iovp->iov_base);
b33502d5 1141#endif /*AHADEBUG*/
15637ed4
RG
1142 sg++;
1143 iovp++;
1144 seg++;
1145 datalen--;
1146 }
1147 }
1148 else
1149 {
1150 /***********************************************\
1151 * Set up the scatter gather block *
1152 \***********************************************/
1153
b33502d5 1154#ifdef AHADEBUG
15637ed4
RG
1155 if(scsi_debug & SHOWSCATGATH)
1156 printf("%d @0x%x:- ",xs->datalen,xs->data);
b33502d5 1157#endif /*AHADEBUG*/
15637ed4
RG
1158 datalen = xs->datalen;
1159 thiskv = (int)xs->data;
1160 thisphys = KVTOPHYS(thiskv);
1161
1162 while ((datalen) && (seg < AHA_NSEG))
1163 {
1164 bytes_this_seg = 0;
1165
1166 /* put in the base address */
1167 lto3b(thisphys,&(sg->seg_addr));
1168
b33502d5 1169#ifdef AHADEBUG
15637ed4
RG
1170 if(scsi_debug & SHOWSCATGATH)
1171 printf("0x%x",thisphys);
b33502d5 1172#endif /*AHADEBUG*/
15637ed4
RG
1173
1174 /* do it at least once */
1175 nextphys = thisphys;
1176 while ((datalen) && (thisphys == nextphys))
1177 /***************************************\
1178 * This page is contiguous (physically) *
1179 * with the the last, just extend the *
1180 * length *
1181 \***************************************/
1182 {
1183 /** how far to the end of the page ***/
1184 nextphys = (thisphys & (~(PAGESIZ - 1)))
1185 + PAGESIZ;
1186 bytes_this_page = nextphys - thisphys;
1187 /**** or the data ****/
1188 bytes_this_page = min(bytes_this_page
1189 ,datalen);
1190 bytes_this_seg += bytes_this_page;
1191 datalen -= bytes_this_page;
1192
1193 /**** get more ready for the next page ****/
1194 thiskv = (thiskv & (~(PAGESIZ - 1)))
1195 + PAGESIZ;
1196 if(datalen)
1197 thisphys = KVTOPHYS(thiskv);
1198 }
1199 /***************************************\
1200 * next page isn't contiguous, finish the seg*
1201 \***************************************/
b33502d5 1202#ifdef AHADEBUG
15637ed4
RG
1203 if(scsi_debug & SHOWSCATGATH)
1204 printf("(0x%x)",bytes_this_seg);
b33502d5 1205#endif /*AHADEBUG*/
15637ed4
RG
1206 lto3b(bytes_this_seg,&(sg->seg_len));
1207 sg++;
1208 seg++;
1209 }
1210 }
1211 lto3b(seg * sizeof(struct aha_scat_gath),ccb->data_length);
b33502d5 1212#ifdef AHADEBUG
15637ed4
RG
1213 if(scsi_debug & SHOWSCATGATH)
1214 printf("\n");
b33502d5 1215#endif /*AHADEBUG*/
15637ed4
RG
1216 if (datalen)
1217 { /* there's still data, must have run out of segs! */
98639498 1218 printf("aha%d: aha_scsi_cmd, more than %d DMA segs\n",
15637ed4
RG
1219 unit,AHA_NSEG);
1220 xs->error = XS_DRIVER_STUFFUP;
1221 aha_free_ccb(unit,ccb,flags);
1222 return(HAD_ERROR);
1223 }
1224
1225 }
1226 else
1227 { /* No data xfer, use non S/G values */
1228 lto3b(0, ccb->data_addr );
1229 lto3b(0,ccb->data_length);
1230 }
1231 lto3b(0, ccb->link_addr );
1232 /***********************************************\
1233 * Put the scsi command in the ccb and start it *
1234 \***********************************************/
1235 if(!(flags & SCSI_RESET))
1236 bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
b33502d5 1237#ifdef AHADEBUG
15637ed4
RG
1238 if(scsi_debug & SHOWCOMMANDS)
1239 {
1240 u_char *b = (u_char *)&ccb->scsi_cmd;
1241 if(!(flags & SCSI_RESET))
1242 {
1243 int i = 0;
1244 printf("aha%d:%d:%d-"
1245 ,unit
1246 ,ccb->target
1247 ,ccb->lun );
1248 while(i < ccb->scsi_cmd_length )
1249 {
1250 if(i) printf(",");
1251 printf("%x",b[i++]);
1252 }
1253 }
1254 else
1255 {
1256 printf("aha%d:%d:%d-RESET- "
1257 ,unit
1258 ,ccb->target
1259 ,ccb->lun
1260 );
1261 }
1262 }
b33502d5 1263#endif /*AHADEBUG*/
15637ed4
RG
1264 if (!(flags & SCSI_NOMASK))
1265 {
1266 s= splbio(); /* stop instant timeouts */
b33502d5 1267 timeout(aha_timeout,ccb,(xs->timeout * hz) / 1000);
15637ed4
RG
1268 aha_startmbx(ccb->mbx);
1269 /***********************************************\
1270 * Usually return SUCCESSFULLY QUEUED *
1271 \***********************************************/
1272 splx(s);
b33502d5 1273#ifdef AHADEBUG
15637ed4
RG
1274 if(scsi_debug & TRACEINTERRUPTS)
1275 printf("sent ");
b33502d5 1276#endif /*AHADEBUG*/
15637ed4
RG
1277 return(SUCCESSFULLY_QUEUED);
1278 }
1279 aha_startmbx(ccb->mbx);
b33502d5 1280#ifdef AHADEBUG
15637ed4
RG
1281 if(scsi_debug & TRACEINTERRUPTS)
1282 printf("cmd_sent, waiting ");
b33502d5 1283#endif /*AHADEBUG*/
15637ed4
RG
1284 /***********************************************\
1285 * If we can't use interrupts, poll on completion*
1286 \***********************************************/
1287 {
1288 int done = 0;
1289 int count = delaycount * xs->timeout / AHA_SCSI_TIMEOUT_FUDGE;
1290 while((!done) && count)
1291 {
1292 i=0;
1293 while ( (!done) && i<AHA_MBX_SIZE)
1294 {
1295 if ((aha_mbx[unit].mbi[i].stat != AHA_MBI_FREE )
1296 && (PHYSTOKV(_3btol(aha_mbx[unit].mbi[i].ccb_addr)
1297 == (int)ccb)))
1298 {
1299 aha_mbx[unit].mbi[i].stat = AHA_MBI_FREE;
1300 aha_done(unit,ccb);
1301 done++;
1302 }
1303 i++;
1304 }
1305 count--;
1306 }
1307 if (!count)
1308 {
1309 if (!(xs->flags & SCSI_SILENT))
98639498 1310 printf("aha%d: cmd fail\n",unit);
15637ed4
RG
1311 aha_abortmbx(ccb->mbx);
1312 count = delaycount * 2000 / AHA_SCSI_TIMEOUT_FUDGE;
1313 while((!done) && count)
1314 {
1315 i=0;
1316 while ( (!done) && i<AHA_MBX_SIZE)
1317 {
1318 if ((aha_mbx[unit].mbi[i].stat != AHA_MBI_FREE )
1319 && (PHYSTOKV(_3btol(aha_mbx[unit].mbi[i].ccb_addr)
1320 == (int)ccb)))
1321 {
1322 aha_mbx[unit].mbi[i].stat = AHA_MBI_FREE;
1323 aha_done(unit,ccb);
1324 done++;
1325 }
1326 i++;
1327 }
1328 count--;
1329 }
1330 if(!count)
1331 {
98639498 1332 printf("aha%d: abort failed in wait\n",unit);
15637ed4
RG
1333 ccb->mbx->cmd = AHA_MBO_FREE;
1334 }
1335 aha_free_ccb(unit,ccb,flags);
1336 ahaintr(unit);
1337 xs->error = XS_DRIVER_STUFFUP;
1338 return(HAD_ERROR);
1339 }
1340 ahaintr(unit);
1341 if(xs->error) return(HAD_ERROR);
1342 return(COMPLETE);
1343
1344 }
1345}
1346/***************************************************************\
1347* try each speed in turn, when we find one that works, use *
1348* the NEXT one for a safety margin, unless that doesn't exist *
1349* or doesn't work. returns the nSEC value of the time used *
1350* or 0 if it could get a working speed ( or the NEXT speed *
1351* failed) *
1352\***************************************************************/
1353
1354int aha_set_bus_speed(unit)
1355int unit;
1356{
1357 int speed;
1358 int retval,retval2;
1359
1360#ifdef EISA
1361 speed = 0; /* start at the fastest */
1362#else EISA
1363 speed = 1; /* 100 ns can crash some ISA busses (!?!) */
1364#endif EISA
1365 while (1)
1366 {
1367 retval = aha_bus_speed_check(unit,speed);
1368 if(retval == HAD_ERROR)
1369 {
1370 printf("no working bus speed!!!\n");
1371 return(0);
1372 }
1373 if(retval == 0)
1374 {
1375 speed++;
1376 }
1377 else /* Go one slower to be safe */
1378 { /* unless eisa at 100 ns.. trust it */
1379 if(speed != 0)
1380 {
1381 speed++;
1382 }
98639498 1383 printf("%d nSEC ok, using ",retval);
15637ed4
RG
1384 retval2 = aha_bus_speed_check(unit,speed);
1385 if(retval2 == HAD_ERROR) /* retval is slowest already */
1386 {
b33502d5 1387 printf("marginal ");
15637ed4
RG
1388 retval2 = retval;
1389 }
1390 if(retval2)
1391 {
98639498 1392 printf("%d nSEC\n",retval2);
15637ed4
RG
1393 return(retval2);
1394 }
1395 else
1396 {
98639498 1397 printf(".. slower failed, abort\n",retval);
15637ed4
RG
1398 return(0);
1399 }
1400
1401 }
1402 }
1403}
1404
1405/***************************************************************\
1406* Set the DMA speed to the Nth speed and try an xfer. If it *
1407* fails return 0, if it succeeds return the nSec value selected *
1408* If there is no such speed return HAD_ERROR. *
1409\***************************************************************/
1410static struct bus_speed
1411{
1412 char arg;
1413 int nsecs;
1414}aha_bus_speeds[] =
1415{
1416 {0x88,100},
1417 {0x99,150},
1418 {0xaa,200},
1419 {0xbb,250},
1420 {0xcc,300},
1421 {0xdd,350},
1422 {0xee,400},
1423 {0xff,450}
1424};
1425static char aha_test_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz!@";
1426
1427int aha_bus_speed_check(unit,speed)
1428int unit,speed;
1429{
1430 int numspeeds = sizeof(aha_bus_speeds)/sizeof(struct bus_speed);
1431 u_char ad[3];
1432
1433 /*******************************************************\
1434 * Check we have such an entry *
1435 \*******************************************************/
1436 if(speed >= numspeeds) return(HAD_ERROR); /* illegal speed */
1437
1438 /*******************************************************\
1439 * Set the dma-speed *
1440 \*******************************************************/
1441 aha_cmd(unit,1, 0, 0, 0, AHA_SPEED_SET,aha_bus_speeds[speed].arg);
1442
1443 /*******************************************************\
1444 * put the test data into the buffer and calculate *
1445 * it's address. Read it onto the board *
1446 \*******************************************************/
1447 strcpy(aha_scratch_buf,aha_test_string);
1448 lto3b(KVTOPHYS(aha_scratch_buf),ad);
1449
1450 aha_cmd(unit,3, 0, 0, 0, AHA_WRITE_FIFO, ad[0], ad[1], ad[2]);
1451
1452 /*******************************************************\
1453 * clear the buffer then copy the contents back from the *
1454 * board. *
1455 \*******************************************************/
1456 bzero(aha_scratch_buf,54); /* 54 bytes transfered by test */
1457
1458 aha_cmd(unit,3, 0, 0, 0, AHA_READ_FIFO, ad[0], ad[1], ad[2]);
1459
1460 /*******************************************************\
1461 * Compare the original data and the final data and *
1462 * return the correct value depending upon the result *
1463 \*******************************************************/
1464 if(strcmp(aha_test_string,aha_scratch_buf))
1465 { /* copy failed.. assume too fast */
1466 return(0);
1467 }
1468 else
1469 { /* copy succeded assume speed ok */
1470 return(aha_bus_speeds[speed].nsecs);
1471 }
1472}
1473
1474
15637ed4 1475
b33502d5 1476aha_timeout(struct aha_ccb *ccb)
15637ed4 1477{
b33502d5
RG
1478 int unit;
1479 int s = splbio();
15637ed4 1480
b33502d5 1481 unit = ccb->xfer->adapter;
98639498 1482 printf("aha%d: device %d timed out ",unit ,ccb->xfer->targ);
b33502d5
RG
1483
1484 /***************************************\
1485 * If The ccb's mbx is not free, then *
1486 * the board has gone south *
1487 \***************************************/
1488 if(ccb->mbx->cmd != AHA_MBO_FREE)
15637ed4 1489 {
98639498 1490 printf("aha%d: not taking commands!\n",unit);
b33502d5 1491 Debugger();
15637ed4 1492 }
b33502d5
RG
1493 /***************************************\
1494 * If it has been through before, then *
1495 * a previous abort has failed, don't *
1496 * try abort again *
1497 \***************************************/
1498 if(ccb->flags == CCB_ABORTED) /* abort timed out */
15637ed4 1499 {
b33502d5
RG
1500 printf(" AGAIN\n");
1501 ccb->xfer->retries = 0; /* I MEAN IT ! */
1502 ccb->host_stat = AHA_ABORTED;
1503 aha_done(unit,ccb);
15637ed4 1504 }
b33502d5 1505 else /* abort the operation that has timed out */
15637ed4 1506 {
b33502d5
RG
1507 printf("\n");
1508 aha_abortmbx(ccb->mbx);
1509 /* 2 secs for the abort */
1510 timeout(aha_timeout,ccb,2 * hz);
1511 ccb->flags = CCB_ABORTED;
15637ed4
RG
1512 }
1513 splx(s);
15637ed4 1514}