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