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