This source file includes following definitions.
- seagate_st0x_detect
- seagate_st0x_info
- seagate_unexpected_intr
- seagate_reconnect_intr
- seagate_st0x_queue_command
- seagate_st0x_command
- internal_command
- seagate_st0x_abort
- seagate_st0x_reset
1
2
3
4
5
6
7
8
9 #include <linux/config.h>
10
11 #if defined(CONFIG_SCSI_SEAGATE) || defined(CONFIG_SCSI_FD_88x)
12 #include <asm/io.h>
13 #include <asm/system.h>
14 #include <linux/sched.h>
15 #include "seagate.h"
16 #include "scsi.h"
17 #include "hosts.h"
18
19 extern void seagate_intr(void);
20 static int internal_command(unsigned char target, const void *cmnd,
21 void *buff, int bufflen, int reselect);
22 void (*do_seagate)(void) = NULL;
23
24 static int incommand;
25
26
27
28
29 static void *base_address = NULL;
30
31
32
33
34 static volatile int abort_confirm = 0;
35
36 static volatile void *st0x_cr_sr;
37
38
39
40
41
42
43
44
45
46
47 static volatile void *st0x_dr;
48
49
50
51
52
53 static volatile int st0x_aborted=0;
54
55
56
57
58
59
60
61
62
63
64 #define retcode(result) (((result) << 16) | (message << 8) | status)
65 #define STATUS (*(unsigned char *) st0x_cr_sr)
66 #define CONTROL STATUS
67 #define DATA (*(unsigned char *) st0x_dr)
68
69 #ifndef OVERRIDE
70 static const char * seagate_bases[] = {(char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000, (char *) 0xce000, (char *) 0xce000,
71 (char *) 0xdc000, (char *) 0xde000};
72 typedef struct
73 {
74 char *signature ;
75 unsigned offset;
76 unsigned length;
77 } Signature;
78
79 static const Signature signatures[] = {
80 #ifdef CONFIG_SCSI_SEAGATE
81 {"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40},
82
83
84
85
86
87
88
89
90
91 {"SEAGATE SCSI BIOS ",16, 17},
92 {"SEAGATE SCSI BIOS ",17, 17},
93 #endif
94
95
96
97
98
99
100
101
102 #ifdef CONFIG_SCSI_FD_88x
103 {"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/90", 5, 46},
104 #endif
105 }
106 ;
107
108
109
110
111
112
113
114
115
116 #define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature))
117 #endif
118
119
120
121
122
123 static int hostno = -1;
124
125 int seagate_st0x_detect (int hostnum)
126 {
127 #ifndef OVERRIDE
128 int i,j;
129 #endif
130
131
132
133
134 #ifdef DEBUG
135 printk("Autodetecting seagate ST0x\n");
136 #endif
137
138 if (hostno != -1)
139 {
140 printk ("ERROR : seagate_st0x_detect() called twice.\n");
141 return 0;
142 }
143
144 base_address = NULL;
145 #ifdef OVERRIDE
146 base_address = (void *) OVERRIDE;
147 #ifdef DEBUG
148 printk("Base address overridden to %x\n", base_address);
149 #endif
150 #else
151
152
153
154
155
156
157
158 for (i = 0; i < (sizeof (seagate_bases) / sizeof (char * )); ++i)
159 for (j = 0; !base_address && j < NUM_SIGNATURES; ++j)
160 if (!memcmp ((void *) (seagate_bases[i] +
161 signatures[j].offset), (void *) signatures[j].signature,
162 signatures[j].length))
163 base_address = (void *) seagate_bases[i];
164 #endif
165
166 if (base_address)
167 {
168 st0x_cr_sr =(void *) (((unsigned char *) base_address) + 0x1a00);
169 st0x_dr = (void *) (((unsigned char *) base_address )+ 0x1c00);
170 #ifdef DEBUG
171 printk("ST0x detected. Base address = %x, cr = %x, dr = %x\n", base_address, st0x_cr_sr, st0x_dr);
172 #endif
173 hostno = hostnum;
174
175
176
177
178
179 #if 1
180 set_intr_gate (0x25, seagate_intr);
181 __asm__("
182 inb $0x21, %%al
183 andb $0xdf, %%al
184 outb %%al, $0x21"::);
185 #endif
186 return -1;
187 }
188 else
189 {
190 #ifdef DEBUG
191 printk("ST0x not detected.\n");
192 #endif
193 return 0;
194 }
195 }
196
197 char *seagate_st0x_info(void)
198 {
199 static char buffer[] = "Seagate ST-0X SCSI driver by Drew Eckhardt \n"
200 "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/seagate.c,v 1.1 1992/07/24 06:27:38 root Exp root $\n";
201 return buffer;
202 }
203
204
205
206
207
208
209 static unsigned char current_target;
210 static unsigned char *current_cmnd, *current_data;
211 static int current_bufflen;
212 static void (*done_fn)(int, int) = NULL;
213
214
215
216
217
218
219 #define NO_RECONNECT 0
220 #define RECONNECT_NOW 1
221 #define CAN_RECONNECT 2
222
223
224
225
226
227 static int should_reconnect = 0;
228
229 void seagate_unexpected_intr (void)
230 {
231 printk("scsi%d: unexpected interrupt.\n", hostno);
232 }
233
234
235
236
237
238
239
240 void seagate_reconnect_intr (void)
241 {
242 int temp;
243
244 #if (DEBUG & PHASE_RESELECT)
245 printk("scsi%d : seagate_reconnect_intr() called\n", hostno);
246 #endif
247
248 if (!should_reconnect)
249 seagate_unexpected_intr();
250 else
251 {
252 should_reconnect = 0;
253
254 #if (DEBUG & PHASE_RESELECT)
255 printk("scsi%d : internal_command("
256 "%d, %08x, %08x, %d, RECONNECT_NOW\n", hostno,
257 current_target, current_data, current_bufflen);
258 #endif
259
260 temp = internal_command (current_target,
261 current_cmnd, current_data, current_bufflen,
262 RECONNECT_NOW);
263
264 if (msg_byte(temp) != DISCONNECT)
265 {
266 if (done_fn)
267 {
268 #if (DEBUG & PHASE_RESELECT)
269 printk("scsi%d : done_fn(%d,%08x)", hostno,
270 hostno, temp);
271 #endif
272 done_fn (hostno, temp);
273 }
274 else
275 printk("done_fn() not defined.\n");
276 }
277 }
278 }
279
280
281
282
283
284
285
286
287 int seagate_st0x_queue_command (unsigned char target, const void *cmnd,
288 void *buff, int bufflen, void (*fn)(int,
289 int))
290 {
291 int result;
292
293 done_fn = fn;
294 current_target = target;
295 (const void *) current_cmnd = cmnd;
296 current_data = buff;
297 current_bufflen = bufflen;
298
299 result = internal_command (target, cmnd, buff, bufflen,
300 CAN_RECONNECT);
301 if (msg_byte(result) == DISCONNECT)
302 return 0;
303 else
304 {
305 done_fn (hostno, result);
306 return 1;
307 }
308 }
309
310 int seagate_st0x_command (unsigned char target, const void *cmnd,
311 void *buff, int bufflen)
312 {
313 return internal_command (target, cmnd, buff, bufflen,
314 (int) NO_RECONNECT);
315 }
316
317 static int internal_command(unsigned char target, const void *cmnd,
318 void *buff, int bufflen, int reselect)
319 {
320 int len;
321 unsigned char *data;
322 int clock;
323 int temp;
324
325
326 #if ((DEBUG & PHASE_ETC) || (DEBUG & PRINT_COMMAND) || (DEBUG & PHASE_EXIT))
327 int i;
328 #endif
329
330 #if (DEBUG & PHASE_ETC)
331 int phase=0, newphase;
332 #endif
333
334 int done = 0;
335 unsigned char status = 0;
336 unsigned char message = 0;
337 register unsigned char status_read;
338
339 do_seagate = seagate_unexpected_intr;
340
341 len=bufflen;
342 data=(unsigned char *) buff;
343
344 incommand = 0;
345 st0x_aborted = 0;
346
347 #if (DEBUG & PRINT_COMMAND)
348 printk ("scsi%d : target = %d, command = ", hostno, target);
349 for (i = 0; i < COMMAND_SIZE(((unsigned char *)cmnd)[0]); ++i)
350 printk("%02x ", ((unsigned char *) cmnd)[i]);
351 printk("\n");
352 #endif
353
354 #if (DEBUG & PHASE_RESELECT)
355 switch (reselect)
356 {
357 case RECONNECT_NOW :
358 printk("scsi%d : reconnecting\n", hostno);
359 break;
360 case CAN_RECONNECT :
361 printk("scsi%d : allowed to reconnect\n", hostno);
362 break;
363 default :
364 printk("scsi%d : not allowed to reconnect\n", hostno);
365 }
366 #endif
367
368
369 if (target > 6)
370 {
371 if (reselect == RECONNECT_NOW)
372 eoi();
373 return DID_BAD_TARGET;
374 }
375
376
377
378
379
380
381
382 if (reselect == RECONNECT_NOW)
383 {
384 #if (DEBUG & PHASE_RESELECT)
385 printk("scsi%d : phase RESELECT \n", hostno);
386 #endif
387
388
389
390
391
392
393
394
395
396
397 for (clock = jiffies + 10, temp = 0; (jiffies < clock) &&
398 !(STATUS & STAT_IO););
399
400 if (jiffies >= clock)
401 {
402 #if (DEBUG & PHASE_RESELECT)
403 printk("scsi%d : RESELECT timed out while waiting for IO .\n",
404 hostno);
405 #endif
406 eoi();
407 return (DID_BAD_INTR << 16);
408 }
409
410
411
412
413
414
415 if (!((temp = DATA) & 0x80))
416 {
417 #if (DEBUG & PHASE_RESELECT)
418 printk("scsi%d : detected reconnect request to different target.\n"
419 "\tData bus = %d\n", hostno, temp);
420 #endif
421 eoi();
422 return (DID_BAD_INTR << 16);
423 }
424
425 if (!(temp & (1 << current_target)))
426 {
427 printk("scsi%d : Unexpected reselect interrupt. Data bus = %d\n",
428 hostno, temp);
429 eoi();
430 return (DID_BAD_INTR << 16);
431 }
432 data=current_data;
433 cmnd=current_cmnd;
434 len=current_bufflen;
435
436
437
438
439
440
441 CONTROL = (BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY);
442
443
444
445
446
447
448 for (clock = jiffies + 10; (jiffies < clock) && (STATUS & STAT_SEL););
449
450 if (jiffies >= clock)
451 {
452 CONTROL = (BASE_CMD | CMD_INTR);
453 #if (DEBUG & PHASE_RESELECT)
454 printk("scsi%d : RESELECT timed out while waiting for SEL.\n",
455 hostno);
456 #endif
457 eoi();
458 return (DID_BAD_INTR << 16);
459 }
460
461 CONTROL = BASE_CMD;
462
463
464
465
466
467 eoi();
468 }
469 else
470 {
471 #if (DEBUG & PHASE_BUS_FREE)
472 printk ("scsi%d : phase = BUS FREE \n", hostno);
473 #endif
474
475
476
477
478
479
480
481
482
483
484 clock = jiffies + ST0X_BUS_FREE_DELAY;
485
486 while (((STATUS | STATUS | STATUS) &
487 (STAT_BSY | STAT_SEL)) &&
488 (!st0x_aborted) && (jiffies < clock));
489
490 if (jiffies > clock)
491 return retcode(DID_BUS_BUSY);
492 else if (st0x_aborted)
493 return retcode(st0x_aborted);
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508 #if (DEBUG & PHASE_SELECTION)
509 printk("scsi%d : phase = SELECTION\n", hostno);
510 #endif
511
512 clock = jiffies + ST0X_SELECTION_DELAY;
513
514
515
516
517
518
519
520 if (reselect)
521 CONTROL = BASE_CMD | CMD_DRVR_ENABLE |
522 CMD_ATTN;
523
524
525
526
527 DATA = (unsigned char) ((1 << target) | 0x80);
528
529
530
531
532
533 CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL |
534 (reselect ? CMD_ATTN : 0);
535
536
537
538
539
540 while (!((status_read = STATUS) & STAT_BSY) &&
541 (jiffies < clock) && !st0x_aborted)
542
543 #if (DEBUG & PHASE_SELECTION)
544 {
545 temp = clock - jiffies;
546
547 if (!(jiffies % 5))
548 printk("seagate_st0x_timeout : %d \r",temp);
549
550 }
551 printk("Done. \n\r");
552 printk("scsi%d : status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n",
553 hostno, status_read, temp, st0x_aborted);
554 #else
555 ;
556 #endif
557
558
559 if ((jiffies > clock) || (!st0x_aborted &&
560 !(status_read & STAT_BSY)))
561 {
562 #if (DEBUG & PHASE_SELECT)
563 printk ("scsi%d : NO CONNECT with target %d, status = %x \n",
564 hostno, target, STATUS);
565 #endif
566 return retcode(DID_NO_CONNECT);
567 }
568
569
570
571
572
573
574
575 if (st0x_aborted)
576 {
577 CONTROL = BASE_CMD;
578 if (STATUS & STAT_BSY)
579 {
580 seagate_st0x_reset();
581 return retcode(DID_RESET);
582 }
583 return retcode(st0x_aborted);
584 }
585 }
586
587 CONTROL = BASE_CMD | CMD_DRVR_ENABLE |
588 ((reselect == CAN_RECONNECT) ? CMD_ATTN : 0) ;
589
590
591
592
593
594
595
596
597
598
599 #if (DEBUG & PHASE_ETC)
600 printk("scsi%d : phase = INFORMATION TRANSFER\n", hostno);
601 #endif
602
603 incommand = 1;
604
605
606
607
608
609
610
611
612
613
614 while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done)
615 {
616 #ifdef PARITY
617 if (status_read & STAT_PARITY)
618 {
619 done = 1;
620 st0x_aborted = DID_PARITY;
621 }
622 #endif
623
624 if (status_read & STAT_REQ)
625 {
626 #if (DEBUG & PHASE_ETC)
627 if ((newphase = (status_read & REQ_MASK)) != phase)
628 {
629 phase = newphase;
630 switch (phase)
631 {
632 case REQ_DATAOUT:
633 printk("scsi%d : phase = DATA OUT\n",
634 hostno);
635 break;
636 case REQ_DATAIN :
637 printk("scsi%d : phase = DATA IN\n",
638 hostno);
639 break;
640 case REQ_CMDOUT :
641 printk("scsi%d : phase = COMMAND OUT\n",
642 hostno);
643 break;
644 case REQ_STATIN :
645 printk("scsi%d : phase = STATUS IN\n",
646 hostno);
647 break;
648 case REQ_MSGOUT :
649 printk("scsi%d : phase = MESSAGE OUT\n",
650 hostno);
651 break;
652 case REQ_MSGIN :
653 printk("scsi%d : phase = MESSAGE IN\n",
654 hostno);
655 break;
656 default :
657 printk("scsi%d : phase = UNKNOWN\n",
658 hostno);
659 st0x_aborted = 1;
660 done = 1;
661 }
662 }
663 #endif
664
665 switch (status_read & REQ_MASK)
666 {
667 case REQ_DATAOUT :
668
669
670
671
672
673 __asm__ ("
674
675
676
677
678
679
680
681
682
683
684 movl %0, %%esi
685 movl %1, %%ecx
686 orl %%ecx, %%ecx
687 jz 2f
688
689 cld
690
691 movl _st0x_cr_sr, %%ebx
692 movl _st0x_dr, %%edi
693
694 1: movb (%%ebx), %%al
695
696
697
698
699 test $1, %%al
700 jz 2f
701
702
703
704
705 test $0xe, %%al
706 jnz 2f
707
708
709
710 test $0x10, %%al
711 jz 1b
712 lodsb
713 movb %%al, (%%edi)
714 loop 1b
715
716 2:
717 movl %%esi, %2
718 movl %%ecx, %3
719 ":
720
721 "=r" (data), "=r" (len) :
722
723 "0" (data), "1" (len) :
724
725 "ebx", "ecx", "edi", "esi");
726
727 break;
728
729 case REQ_DATAIN :
730
731
732
733
734
735 __asm__ ("
736
737
738
739
740
741
742
743
744
745
746 movl %0, %%edi
747 movl %1, %%ecx
748 orl %%ecx, %%ecx
749 jz 2f
750
751 cld
752 movl _st0x_cr_sr, %%esi
753 movl _st0x_dr, %%ebx
754
755 1: movb (%%esi), %%al
756
757
758
759
760 test $1, %%al
761 jz 2f
762
763
764
765
766 movb $0xe, %%ah
767 andb %%al, %%ah
768 cmpb $0x04, %%ah
769 jne 2f
770
771
772
773
774 test $0x10, %%al
775 jz 1b
776
777 movb (%%ebx), %%al
778 stosb
779 loop 1b
780
781 2: movl %%edi, %2
782 movl %%ecx, %3
783 ":
784
785 "=r" (data), "=r" (len) :
786
787 "0" (data), "1" (len) :
788
789 "ebx", "ecx", "edi", "esi");
790 break;
791
792 case REQ_CMDOUT :
793 while (((status_read = STATUS) & STAT_BSY) &&
794 ((status_read & REQ_MASK) == REQ_CMDOUT))
795 if (status_read & STAT_REQ)
796 DATA = *(unsigned char *) cmnd ++;
797 break;
798
799 case REQ_STATIN :
800 status = DATA;
801 break;
802
803 case REQ_MSGOUT :
804
805
806
807
808
809 CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
810
811
812
813
814 if (reselect)
815 {
816 DATA = IDENTIFY(1,0);
817 #if (DEBUG & (PHASE_RESELECT | PHASE_MSGOUT))
818 printk("scsi%d : sent IDENTIFY message.\n", hostno);
819 #endif
820 }
821 else
822 {
823 DATA = MESSAGE_REJECT;
824
825 #if (DEBUG & PHASE_MSGOUT)
826 printk("scsi%d : sent MESSAGE REJECT message.\n", hostno);
827 #endif
828 }
829 break;
830
831 case REQ_MSGIN :
832 switch (message = DATA)
833 {
834 case DISCONNECT :
835 should_reconnect = 1;
836 current_data = data;
837 current_bufflen = len;
838 #if (DEBUG & (PHASE_RESELECT | PHASE_MSGIN))
839 printk("scsi%d : disconnected.\n", hostno);
840 done=1;
841 break;
842 #endif
843 case COMMAND_COMPLETE :
844 #if (DEBUG & PHASE_MSGIN)
845 printk("scsi%d : command complete.\n", hostno);
846 done=1;
847 break;
848 #endif
849 case ABORT :
850 #if (DEBUG & PHASE_MSGIN)
851 printk("scsi%d : abort message.\n", hostno);
852 #endif
853 done=1;
854 break;
855 case SAVE_POINTERS :
856 current_data = data;
857 current_bufflen = len;
858 #if (DEBUG & PHASE_MSGIN)
859 printk("scsi%d : pointers saved.\n", hostno);
860 #endif
861 break;
862 case RESTORE_POINTERS:
863 data=current_data;
864 cmnd=current_cmnd;
865 #if (DEBUG & PHASE_MSGIN)
866 printk("scsi%d : pointers restored.\n", hostno);
867 #endif
868 break;
869 default:
870
871
872
873
874
875
876 if (message & 0x80)
877 {
878 #if (DEBUG & PHASE_MSGIN)
879 printk("scsi%d : IDENTIFY message received from id %d, lun %d.\n",
880 hostno, target, message & 7);
881 #endif
882 }
883 else
884 {
885
886 #if (DEBUG & PHASE_MSGIN)
887 printk("scsi%d : unknown message %d from target %d.\n",
888 hostno, message, target);
889 #endif
890 }
891 }
892 break;
893
894 default :
895 printk("scsi%d : unknown phase.\n", hostno);
896 st0x_aborted = DID_ERROR;
897 }
898 }
899 }
900
901 #if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT))
902 printk("Transfered %d bytes, allowed %d additional bytes\n", (bufflen - len), len);
903 #endif
904
905 #if (DEBUG & PHASE_EXIT)
906 printk("Buffer : \n");
907 for (i = 0; i < 20; ++i)
908 printk ("%02x ", ((unsigned char *) data)[i]);
909 printk("\n");
910 printk("Status = %02x, message = %02x\n", status, message);
911 #endif
912
913
914 if (st0x_aborted)
915 {
916 if (STATUS & STAT_BSY)
917 {
918 seagate_st0x_reset();
919 st0x_aborted = DID_RESET;
920 }
921 abort_confirm = 1;
922 }
923
924 if (should_reconnect)
925 {
926 #if (DEBUG & PHASE_RESELECT)
927 printk("scsi%d : exiting seagate_st0x_queue_command() with reconnect enabled.\n",
928 hostno);
929 #endif
930 do_seagate = seagate_reconnect_intr;
931 CONTROL = BASE_CMD | CMD_INTR ;
932 }
933 else
934 CONTROL = BASE_CMD;
935
936 return retcode (st0x_aborted);
937 }
938
939 int seagate_st0x_abort (int code)
940 {
941 if (code)
942 st0x_aborted = code;
943 else
944 st0x_aborted = DID_ABORT;
945
946 return 0;
947 }
948
949
950
951
952
953 int seagate_st0x_reset (void)
954 {
955 unsigned clock;
956
957
958
959
960
961 #ifdef DEBUG
962 printk("In seagate_st0x_reset()\n");
963 #endif
964
965
966
967
968 CONTROL = BASE_CMD | CMD_RST;
969 clock=jiffies+2;
970
971
972
973
974 while (jiffies < clock);
975
976 CONTROL = BASE_CMD;
977
978 st0x_aborted = DID_RESET;
979
980 #ifdef DEBUG
981 printk("SCSI bus reset.\n");
982 #endif
983 return 0;
984 }
985
986 #endif
987