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