FreeBSD/Linux Kernel Cross Reference
sys/i386ipsc/sdintr.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * Copyright 1988, 1989, 1990, 1991 by Intel Corporation,
28 * Santa Clara, California.
29 *
30 * All Rights Reserved
31 *
32 * Permission to use, copy, modify, and distribute this software and its
33 * documentation for any purpose and without fee is hereby granted,
34 * provided that the above copyright notice appears in all copies and that
35 * both the copyright notice and this permission notice appear in
36 * supporting documentation, and that the name of Intel not be used in
37 * advertising or publicity pertaining to distribution of the software
38 * without specific, written prior permission.
39 *
40 * INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING
41 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
42 * SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
43 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
44 * PROFITS, WHETHER IN ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS
45 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
46 * THIS SOFTWARE.
47 */
48 /*
49 * HISTORY
50 * $Log: sdintr.c,v $
51 * Revision 2.4 91/07/01 08:24:24 jsb
52 * Replace "Wrong direction DATAOUT" assertion with printf.
53 * I seem to hit this a lot when running a STD+iPSC+NORMA+TEST kernel.
54 * [91/06/29 16:13:34 jsb]
55 *
56 * Revision 2.3 91/06/18 20:50:37 jsb
57 * New copyright from Intel.
58 * [91/06/18 20:08:01 jsb]
59 *
60 * Revision 2.2 90/12/04 14:47:48 jsb
61 * First checkin.
62 * [90/12/04 10:58:42 jsb]
63 *
64 */
65 /*
66 * sdintr.c Don Cameron September 1989
67 *
68 * This is the bottom half of the SCSI disk driver for MACH on the iPSC/2.
69 * The code is a rewrite of scsiphase.c for NX on the iPSC/2 and portions
70 * of hd.c for MACH on the AT.
71 */
72
73 #include <sys/types.h>
74 #include <i386ipsc/scsi.h>
75 #include <i386at/disk.h>
76
77 #ifdef MACH_KERNEL
78 #include <i386/mach_param.h>
79 #include <device/buf.h>
80 #include <i386ipsc/sd.h>
81 #include <device/errno.h>
82 #else MACH_KERNEL
83 #include <i386ipsc/hz.h>
84 #include <sys/ioctl.h>
85 #include <sys/param.h>
86 #include <sys/buf.h>
87 #include <i386ipsc/sd.h>
88 #include <sys/errno.h>
89 #include <sys/user.h>
90 #include <sys/vmparam.h>
91 #include <sys/uio.h>
92 #endif MACH_KERNEL
93
94 #define ONE_SECOND (666000) /* Best guess of one second delay */
95 #ifdef MACH_KERNEL
96 unsigned long elapsed_ticks; /* Used to wait for a retry */
97 #else MACH_KERNEL
98 extern time_t lbolt; /* Used to wait for a retry */
99 #endif MACH_KERNEL
100
101 int target_id = -1; /* Current active drive on SCSI bus */
102 int command_waiting = 0; /* Bit set of drives with pending commands */
103 unsigned short scsi_st; /* SCSI controller status */
104 unsigned char scsi_ist; /* SCSI controller interrupt status */
105 unsigned char scsi_msg; /* Recent message byte */
106 unsigned long data_count; /* Byte count for current transfer phase */
107 unsigned long read_fifo; /* Byte count transferred from read fifo */
108 unsigned long write_fifo; /* Byte count transferred to write fifo */
109
110 int step; /* Driver state */
111
112 #define ASSERT(t,m) if (!(t)) panic(m)
113
114 /* Variables defined in sd.c */
115 extern struct hh hh[NDRIVES];
116 extern int scanning; /* In drive scan, timeouts OK */
117 extern int write_reserved; /* Write fifo lock variable */
118 extern volatile caddr_t scsiphys0;
119 extern volatile caddr_t scsiphys1;
120 extern volatile caddr_t scsiphys2;
121 extern volatile caddr_t scsiphys3;
122
123 static int fsi; /* Controller fifo save count */
124 static unsigned char fifo_save[16]; /* Controller fifo save area */
125
126 typedef struct { unsigned char byte[2048]; } B2048;
127 typedef struct { unsigned char byte[4096]; } B4096;
128
129 static char priority[] = { /* Priority array for drive selection */
130 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
131 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
132 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
133 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
134 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
135 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
136 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
137 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
138 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
139 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
140 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
141 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
142 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
143 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
144 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
145 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
146 };
147
148 /* forward declarations */
149 static void sendcmd();
150 static void delay_one_second();
151
152 static dbgbuf[128]; /* DFC DBG */
153
154 /***************************************************************************
155 *
156 * Calling Sequence:
157 * sdintr();
158 *
159 * Description:
160 * Service SCSI interrupt.
161 *
162 * Parameters:
163 * none
164 *
165 * Returns:
166 * none
167 *
168 */
169
170 sdintr()
171 {
172 SCSI_SENSE sense; /* Struct to read sense data into */
173 struct hh *hh_p;
174
175 if (target_id != -1)
176 hh_p = &hh[target_id];
177
178 /*
179 * Get status
180 */
181 scsi_st = SCSI_STATUS;
182
183 /*
184 * Check for major error
185 */
186
187 if ((scsi_st & ESP_GROSS_STAT) != 0) {
188 return;
189 }
190
191
192 /*
193 * Test for SCSI controller interrupt
194 */
195
196 if ((scsi_st & SCSI_EINT_STAT) == 0) {
197
198 /* Read (and clear) interrupt status */
199 scsi_ist = SCSI_INT_STATUS;
200
201 /*
202 * If a data transfer was in progress,
203 * clean up FIFO and complete the transfer.
204 */
205
206 if (data_count != 0) {
207 int cnt;
208
209 /*
210 * Set cnt to the number of bytes transferred
211 * by the controller. Read the transfer counter
212 * if necessary.
213 */
214
215 if ((scsi_st & ESP_COUNT_STAT) == 0) {
216 unsigned short t;
217
218 t = SCSI_COUNT_LO;
219 shortdelay();
220 t |= (unsigned short)(SCSI_COUNT_HI) << 8;
221
222 cnt = data_count - t;
223
224 } else {
225 cnt = data_count;
226 }
227
228 if (hh_p->direction == 1) { /* Read */
229 unsigned long *dp;
230
231 /*
232 * Take all remaining bytes from
233 * the read FIFO.
234 */
235
236 cnt -= read_fifo;
237 dp = (unsigned long *)hh_p->rw_addr;
238 hh_p->transfer_length -= cnt;
239 if (hh_p->buf_io) {
240 hh_p->buflst.b_actf->b_resid -= cnt;
241 }
242 hh_p->rw_addr += cnt;
243
244 /*
245 * Transfer the data
246 */
247
248 if (cnt >= 4096) {
249 *(B4096 *)dp = *(B4096 *)(SCSI_FIFO);
250 (char *) dp += 4096;
251 cnt -= 4096;
252 }
253 if (cnt >= 2048) {
254 *(B2048 *)dp = *(B2048 *)(SCSI_FIFO);
255 (char *) dp += 2048;
256 cnt -= 2048;
257 }
258 for (; cnt > 0; cnt -= 4) {
259 *dp++ = *(unsigned long *)(SCSI_FIFO);
260 }
261
262 read_fifo = 0;
263
264 } else { /* Write */
265
266 /*
267 * Save the SCSI controller FIFO in fifo_save
268 */
269
270 fsi = SCSI_FIFO_FLAGS;
271 if (fsi != 0) {
272 int i;
273
274 for (i = 0; i < fsi; i++)
275 fifo_save[i] = SCSI_ESP_FIFO;
276 }
277
278 /*
279 * Adjust write_fifo to reflect the amount
280 * of data remaining in the write FIFO
281 */
282
283 write_fifo -= cnt;
284 }
285 data_count = 0;
286 }
287
288 /*
289 * Check for special kinds of interrupts
290 */
291
292 if (scsi_ist & ESP_ILLCMD_INT) {
293
294 if (step == RSEL_STEP) {
295 time_t t;
296
297 /*
298 * Illegal command interrupt comes from
299 * select command executing after
300 * reselection occurs. The reselection
301 * interrupt has already been processed
302 * and a ESP_MSGACCEPT command queued.
303 *
304 * Give the ESP 5 ms to respond to the
305 * ESP_MSGACCEPT command. If it does, go on;
306 * otherwise reissue the command.
307 *
308 * NB: Trying to wait for 5ms under UNIX is
309 * a joke of course, because the clock
310 * ticks occur in increments like 10ms
311 * and we need to wait for two clicks
312 * because the first one may not have
313 * been a whole one.
314 */
315 #ifdef MACH_KERNEL
316 t = elapsed_ticks + MIN(2, HZ/200);
317 #else MACH_KERNEL
318 t = lbolt + MIN(2, HZ/200);
319 #endif MACH_KERNEL
320 do {
321 scsi_st = SCSI_STATUS;
322 } while ((scsi_st & SCSI_EINT_STAT) != 0 &&
323 #ifdef MACH_KERNEL
324 elapsed_ticks < t);
325 #else MACH_KERNEL
326 lbolt < t);
327 #endif MACH_KERNEL
328 if ((scsi_st & SCSI_EINT_STAT) != 0) {
329 SCSI_COMMAND = ESP_MSGACCEPT;
330 }
331 goto exitint;
332 }
333
334
335 } else if (scsi_ist & ESP_RESET_INT) {
336 /*
337 * Ignore SCSI bus reset
338 */
339
340 goto exitint;
341
342 } else if (scsi_ist & ESP_RESEL_INT) {
343 unsigned char id;
344
345 /*
346 * Controller has been reselected by a drive
347 */
348
349 if (step == CMD_STEP) {
350
351 /*
352 * Reselection overrides a command
353 * being sent to another drive.
354 * Set command_waiting flag for the other drive.
355 */
356
357 command_waiting |= 1 << target_id;
358 step = NULL_STEP;
359 target_id = -1;
360 }
361
362 /*
363 * Get ID and message bytes from controller FIFO
364 */
365
366 id = SCSI_ESP_FIFO;
367 scsi_msg = SCSI_ESP_FIFO;
368 shortdelay();
369 if (SCSI_FIFO_FLAGS != 0) {
370 /*
371 * The FIFO had some bytes in it from a
372 * command that was being sent to
373 * another drive
374 */
375
376 SCSI_COMMAND = ESP_FLUSH_FIFO;
377 }
378
379 /*
380 * Decode drive number from id byte
381 * and accept reselection message
382 */
383
384 for (target_id = 0;
385 (id & (1 << target_id)) == 0;
386 target_id++);
387
388 SCSI_COMMAND = ESP_MSGACCEPT;
389 step = RSEL_STEP;
390 goto exitint;
391
392 } else if (scsi_ist & ESP_DISC_INT) {
393 int drive, st;
394
395 /*
396 * The current target drive has disconnected
397 */
398
399 drive = target_id;
400 target_id = -1;
401
402 st = step;
403 step = NULL_STEP;
404
405 if (st == DONE_STEP) {
406
407 /*
408 * Current operation is complete.
409 * Check for error status.
410 */
411
412 if (hh_p->cmd_st == CMD_ST_CHECK) {
413 /*
414 * Send request sense command
415 */
416
417 bzero(hh_p->cmd, 6);
418 hh_p->cmd_len = 6;
419 hh_p->cmd[0] = SCSI_SENSE_CMD;
420 hh_p->cmd[4] = sizeof(SCSI_SENSE);
421 hh_p->transfer_length = sizeof(SCSI_SENSE);
422 hh_p->rw_addr = (paddr_t)&sense;
423 hh_p->buf_io = 0;
424 hh_p->direction = 1;
425 command_waiting |= 1 << drive;
426 } else if (hh_p->buf_io) {
427 struct buf *bp;
428
429 bp = hh_p->buflst.b_actf;
430 if (bp->b_resid != 0) {
431 sdrestart();
432 }
433 else {
434 hh_p->cmd_busy = 0;
435 hh_p->buflst.b_actf =
436 bp->av_forw;
437 biodone(bp);
438 sdstart();
439 wakeup(&hh_p->cmd_busy);
440 }
441 } else {
442 hh_p->cmd_busy = 0;
443 wakeup(&hh_p->cmd_busy);
444 }
445
446 } else if (st != DISC_STEP) {
447
448 /*
449 * If disconnect was unexpected, set
450 * timeout status
451 */
452
453 hh_p->cmd_st = CMD_ST_TIMEOUT;
454 hh_p->cmd_busy = 0;
455 SCSI_COMMAND = ESP_FLUSH_FIFO;
456 shortdelay();
457 SCSI_COMMAND = ESP_ENABLE_SEL;
458 ASSERT(scanning, "Unexpected disconnect");
459 wakeup(&hh_p->cmd_busy);
460 goto exitint;
461 }
462
463 /*
464 * Enable reselection by any drive
465 */
466
467 SCSI_COMMAND = ESP_ENABLE_SEL;
468
469 /*
470 * If there are commands waiting, attempt to
471 * send one now while the bus is available
472 */
473
474 if (command_waiting != 0) {
475 sendcmd(priority[command_waiting], 1);
476 }
477 goto exitint;
478 }
479
480 /*
481 * The distinction of CMD_STEP and RSEL_STEP is
482 * not important at this stage
483 */
484
485 if (step == CMD_STEP || step == RSEL_STEP) {
486 step = NULL_STEP;
487 }
488
489 /*
490 * Switch according to the bus phase asserted by the drive
491 */
492
493 switch (scsi_st & ESP_PHASE_STAT) {
494
495 case ESP_COMMAND_PH:
496 ASSERT(0, "Unexpected SCSI phase");
497
498 case ESP_MSGIN_PH:
499 if (step == NULL_STEP) {
500 ASSERT(SCSI_FIFO_FLAGS == 0,
501 "ESP FIFO not clear in MSGIN");
502
503 /* Initiate transfer of a message byte */
504 SCSI_COMMAND = ESP_TRANSFER;
505 step = MSG_STEP;
506
507 } else if (step == MSG_STEP) {
508 unsigned char msg;
509
510 step = NULL_STEP;
511
512 /*
513 * Obtain a message byte
514 */
515
516 msg = SCSI_ESP_FIFO;
517 shortdelay();
518
519 /*
520 * Accept the message
521 */
522
523 SCSI_COMMAND = ESP_MSGACCEPT;
524
525 /*
526 * Switch based on the message contents
527 */
528
529 switch(msg) {
530
531 case MSG_SAVE_DP:
532 break; /* Ignore */
533
534 case MSG_REST_DP:
535 break; /* Ignore */
536
537 case MSG_DISCONNECT:
538 /* Expect disconnect interrupt */
539 step = DISC_STEP;
540 break;
541
542 case MSG_REJECT:
543 ASSERT(0, "Message rejected");
544
545 case MSG_NOP:
546 break; /* Ignore */
547
548 default:
549 ASSERT(0, "Invalid message in");
550 }
551
552 } else /* step == STATUS_STEP */ {
553 unsigned long t;
554
555 /*
556 * Obtain status and message bytes
557 */
558
559 t = *(unsigned long *)(SCSI_FIFO);
560
561 hh_p->cmd_st = t;
562 hh_p->cmd_msg = t >> 8;
563
564 /*
565 * Accept message and expect command
566 * completion disconnect
567 */
568
569 SCSI_COMMAND = ESP_MSGACCEPT;
570 step = DONE_STEP;
571
572 /*
573 * If write command completed, release
574 * write FIFO lock
575 */
576
577 if (hh_p->cmd[0] == SCSI_WRITE_CMD) {
578 write_reserved = 0;
579 }
580
581 }
582 break;
583
584 case ESP_MSGOUT_PH:
585 ASSERT(0, "Unexpected phase MSGOUT");
586 break;
587
588 case ESP_DATAOUT_PH:
589 if (hh_p->direction != 0) {
590 printf("sd%d: false interrupt\n", target_id);
591 return;
592 }
593
594 /*
595 * Set up write transfer
596 */
597
598 set_fifo_write();
599 data_count = hh_p->transfer_length + write_fifo;
600
601 SCSI_COUNT_LO = data_count;
602 shortdelay();
603 SCSI_COUNT_HI = data_count >> 8;
604
605 /*
606 * Replace data in the controller FIFO from
607 * a previous transfer phase
608 */
609
610 if (fsi != 0) {
611 int i;
612
613 for (i = 0; i < fsi; i++)
614 SCSI_ESP_FIFO = fifo_save[i];
615 fsi = 0;
616 }
617
618 /*
619 * Start filling the write FIFO if there is room in it
620 */
621
622 if ((scsi_st & SCSI_WHF_STAT) == 0) {
623 unsigned long *dp;
624 unsigned long cnt;
625
626 cnt = hh_p->transfer_length;
627 if (cnt > 4096)
628 cnt = 4096;
629 if (cnt > 2048 &&
630 (scsi_st & SCSI_WEF_STAT) != 0)
631 cnt = 2048;
632
633 dp = (unsigned long *)(hh_p->rw_addr);
634 hh_p->transfer_length -= cnt;
635 if (hh_p->buf_io) {
636 hh_p->buflst.b_actf->b_resid -= cnt;
637 }
638 hh_p->rw_addr += cnt;
639 write_fifo += cnt;
640
641 if (cnt == 4096) {
642 *(B4096 *)(SCSI_FIFO) = *(B4096 *)dp;
643
644 } else {
645 if (cnt >= 2048) {
646 *(B2048 *)(SCSI_FIFO) = *(B2048 *)dp;
647 (char *) dp += 2048;
648 cnt -= 2048;
649 }
650 for (; cnt > 0; cnt -= 4) {
651 *(unsigned long *)(SCSI_FIFO) = *dp++;
652 }
653 }
654 }
655
656 /*
657 * Issue transfer command. Early versions
658 * of controller chip require NOP before
659 * transfer.
660 */
661
662 shortdelay();
663 SCSI_COMMAND = ESP_NOP;
664 shortdelay();
665 SCSI_COMMAND = ESP_TRANSFER | ESP_DMA;
666 break;
667
668 case ESP_DATAIN_PH:
669 ASSERT(hh_p->direction == 1,
670 "Wrong direction DATAIN");
671
672 /*
673 * Set up read transfer
674 */
675
676 set_fifo_read();
677 data_count = hh_p->transfer_length;
678 SCSI_COUNT_LO = data_count;
679 shortdelay();
680 SCSI_COUNT_HI = data_count >> 8;
681
682 /*
683 * Issue transfer command. Early versions
684 * of controller chip require NOP before
685 * transfer.
686 */
687
688 shortdelay();
689 SCSI_COMMAND = ESP_NOP;
690 shortdelay();
691 SCSI_COMMAND = ESP_TRANSFER | ESP_DMA;
692 break;
693
694 case ESP_STATUS_PH:
695
696 /*
697 * Set up controller to DMA status and message
698 * bytes into the read FIFO. This saves an
699 * interrupt compared with using the controller FIFO.
700 */
701
702 set_fifo_read();
703 SCSI_COUNT_LO = 2;
704 shortdelay();
705 SCSI_COUNT_HI = 0;
706 shortdelay();
707 SCSI_COMMAND = ESP_COMPLETE | ESP_DMA;
708 step = STATUS_STEP;
709 break;
710 }
711
712 }
713
714 exitint:
715 ;
716 }
717
718 /***************************************************************************
719 * Calling Sequence:
720 * sendcmd(drive);
721 *
722 * Description:
723 * Send command to selected drive.
724 *
725 * Parameters:
726 * drive Drive index.
727 *
728 * Returns:
729 * none
730 *
731 */
732
733 static void sendcmd(drive)
734 int drive;
735 {
736 int i;
737 struct hh *hh_p;
738
739 hh_p = &hh[drive];
740 if (hh_p->cmd[0] == SCSI_WRITE_CMD) {
741 write_reserved = 1;
742 }
743 hh_p->cmd_busy = 1;
744 if (target_id == -1) {
745 data_count = 0;
746 command_waiting &= ~(1 << drive);
747 step = CMD_STEP;
748 target_id = drive;
749
750
751 SCSI_ESP_FIFO = MSG_IDENTIFY;
752 shortdelay();
753 SCSI_ID = target_id;
754 for (i = 0; i < hh_p->cmd_len; i++) {
755 SCSI_ESP_FIFO = hh_p->cmd[i];
756 }
757 SCSI_COMMAND = ESP_SELATN;
758 } else {
759 command_waiting |= 1 << drive;
760
761 }
762 }
763
764 /***************************************************************************
765 *
766 * Calling Sequence:
767 * reset_controller();
768 *
769 * Description:
770 * Reset ESP.
771 *
772 * Parameters:
773 * none
774 */
775
776 reset_controller()
777 {
778 int tmp; /* dummy var to force read of SCSI chip */
779
780 /*
781 * Initialize operating globals
782 */
783
784 target_id = -1;
785 write_reserved = 0;
786 command_waiting = 0;
787
788 tmp = SCSI_RESET_ESP;
789 shortdelay();
790 tmp = SCSI_RESET_FIFO;
791 shortdelay();
792 write_fifo = SCSI_CLEAR_CNT;
793 shortdelay();
794 set_fifo_read();
795 shortdelay();
796
797 data_count = 0;
798 SCSI_COMMAND = ESP_RESET_CHIP;
799 shortdelay();
800 SCSI_COMMAND = ESP_NOP;
801 shortdelay();
802
803 SCSI_CLOCK = 5;
804 shortdelay();
805 SCSI_CONFIG = 0x97;
806 shortdelay();
807 SCSI_TIMEOUT = 0x93;
808 shortdelay();
809 SCSI_SYNC_PER = 0x05;
810 shortdelay();
811 SCSI_SYNC_OFF = 0x00;
812 shortdelay();
813
814 data_count = 0;
815 read_fifo = 0;
816 write_fifo = 0;
817 fsi = 0;
818 }
819
820 /***************************************************************************
821 *
822 * Calling Sequence:
823 * reset_bus();
824 *
825 * Description:
826 * Reset SCSI bus.
827 *
828 * Parameters:
829 * none
830 *
831 * Returns:
832 * none
833 *
834 */
835
836 reset_bus()
837 {
838 data_count = 0;
839 SCSI_COMMAND = ESP_RESET_BUS;
840
841 delay_one_second();
842
843 scsi_st = SCSI_STATUS;
844 shortdelay();
845 scsi_ist = SCSI_INT_STATUS;
846 }
847
848 /***************************************************************************
849 *
850 * Calling Sequence:
851 * shortdelay();
852 *
853 * Description:
854 * Short delay for ESP.
855 *
856 * Parameters:
857 * none
858 *
859 * Returns:
860 * none
861 */
862
863
864 #define SHORTDELAY 10
865
866 shortdelay()
867 {
868 volatile unsigned long t;
869
870 for (t = SHORTDELAY; t; t--);
871 }
872
873 /***************************************************************************
874 *
875 * Calling Sequence:
876 * set_fifo_read();
877 *
878 * Description:
879 * Put SCSI controller FIFO's in read mode.
880 *
881 * Parameters:
882 * none
883 *
884 * Returns:
885 * none
886 *
887 */
888
889
890 set_fifo_read()
891 {
892
893 SCSI_READ_MODE = SCSI_CLEAR_CNT;
894 }
895
896 /***************************************************************************
897 *
898 * Calling Sequence:
899 * set_fifo_write();
900 *
901 * Description:
902 * Put SCSI controller FIFO's in write mode.
903 *
904 * Parameters:
905 * none
906 *
907 * Returns:
908 * none
909 *
910 */
911
912 set_fifo_write()
913 {
914
915 SCSI_WRITE_MODE = SCSI_CLEAR_CNT;
916 }
917
918 /***************************************************************************
919 *
920 * Calling Sequence:
921 * reverse_long(p);
922 *
923 * Description:
924 * Reverse the bytes of a long.
925 *
926 * Parameters:
927 * p: Pointer to a long.
928 *
929 * Returns:
930 * Side effect in *p.
931 *
932 */
933
934 reverse_long(p)
935 unsigned char *p;
936 {
937 unsigned char t;
938
939 t = p[0];
940 p[0] = p[3];
941 p[3] = t;
942
943 t = p[1];
944 p[1] = p[2];
945 p[2] = t;
946 }
947
948 /*
949 * delay_one_second
950 * Delay for one second.
951 */
952 static void delay_one_second()
953 {
954 long time;
955 /* Have to brute force this */
956 time = ONE_SECOND;
957 while (time--);
958 }
Cache object: 3dd7c41103abcbd0394e0287d4c9238c
|