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