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