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