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