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