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
- seagate_st0x_biosparam
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <linux/config.h>
19
20 #if defined(CONFIG_SCSI_SEAGATE) || defined(CONFIG_SCSI_FD_88x)
21 #include <asm/io.h>
22 #include <asm/system.h>
23 #include <linux/signal.h>
24 #include <linux/sched.h>
25 #include "../blk.h"
26 #include "scsi.h"
27 #include "hosts.h"
28 #include "seagate.h"
29
30 #ifndef IRQ
31 #define IRQ 5
32 #endif
33
34 #if (defined(FAST32) && !defined(FAST))
35 #define FAST
36 #endif
37
38 #if defined(LINKED)
39 #undef LINKED
40 #endif
41
42 static int internal_command(unsigned char target, unsigned char lun,
43 const void *cmnd,
44 void *buff, int bufflen, int reselect);
45
46 static int incommand;
47
48
49
50
51 static void *base_address = NULL;
52
53
54
55
56 static volatile int abort_confirm = 0;
57
58 static volatile void *st0x_cr_sr;
59
60
61
62
63
64
65
66
67
68
69 static volatile void *st0x_dr;
70
71
72
73
74
75 static volatile int st0x_aborted=0;
76
77
78
79
80
81
82
83
84 static unsigned char controller_type;
85
86 #define retcode(result) (((result) << 16) | (message << 8) | status)
87 #define STATUS (*(volatile unsigned char *) st0x_cr_sr)
88 #define CONTROL STATUS
89 #define DATA (*(volatile unsigned char *) st0x_dr)
90
91 #ifndef OVERRIDE
92 static const char * seagate_bases[] = {
93 (char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000,
94 (char *) 0xce000, (char *) 0xdc000, (char *) 0xde000
95 };
96
97 typedef struct {
98 char *signature ;
99 unsigned offset;
100 unsigned length;
101 unsigned char type;
102 } Signature;
103
104 static const Signature signatures[] = {
105 #ifdef CONFIG_SCSI_SEAGATE
106 {"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40, SEAGATE},
107
108
109
110
111
112
113
114
115
116 {"SEAGATE SCSI BIOS ",16, 17, SEAGATE},
117 {"SEAGATE SCSI BIOS ",17, 17, SEAGATE},
118
119
120
121
122
123
124
125
126 {"FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88",5,48, FD},
127 {"FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89", 5, 46, FD},
128 {"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89", 5, 46, FD},
129 {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90",5, 47, FD},
130 {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90",5, 47, FD},
131 {"FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90", 5, 46, FD},
132 {"FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92", 5, 44, FD},
133 #endif
134 }
135 ;
136
137
138
139
140
141
142
143
144
145 #define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature))
146 #endif
147
148
149
150
151
152 static int hostno = -1;
153 static void seagate_reconnect_intr(int);
154
155
156
157
158
159
160
161 #ifdef FAST
162 static int fast = 1;
163 #endif
164
165 int seagate_st0x_detect (int hostnum)
166 {
167 #ifndef OVERRIDE
168 int i,j;
169 #endif
170 static struct sigaction seagate_sigaction = {
171 &seagate_reconnect_intr,
172 0,
173 SA_INTERRUPT,
174 NULL
175 };
176
177
178
179
180 #ifdef DEBUG
181 printk("Autodetecting seagate ST0x\n");
182 #endif
183
184 if (hostno != -1)
185 {
186 printk ("ERROR : seagate_st0x_detect() called twice.\n");
187 return 0;
188 }
189
190 base_address = NULL;
191 #ifdef OVERRIDE
192 base_address = (void *) OVERRIDE;
193
194
195 #ifdef CONTROLLER
196 controller_type = CONTROLLER;
197 #else
198 #error Please use -DCONTROLLER=SEAGATE or -DCONTROLLER=FD to override controller type
199 #endif
200 #ifdef DEBUG
201 printk("Base address overridden to %x, controller type is %s\n",
202 base_address,controller_type == SEAGATE ? "SEAGATE" : "FD");
203 #endif
204 #else
205
206
207
208
209
210
211
212 for (i = 0; i < (sizeof (seagate_bases) / sizeof (char * )); ++i)
213 for (j = 0; !base_address && j < NUM_SIGNATURES; ++j)
214 if (!memcmp ((void *) (seagate_bases[i] +
215 signatures[j].offset), (void *) signatures[j].signature,
216 signatures[j].length)) {
217 base_address = (void *) seagate_bases[i];
218 controller_type = signatures[j].type;
219 }
220 #endif
221
222 scsi_hosts[hostnum].this_id = (controller_type == SEAGATE) ? 7 : 6;
223
224 if (base_address)
225 {
226 st0x_cr_sr =(void *) (((unsigned char *) base_address) + (controller_type == SEAGATE ? 0x1a00 : 0x1c00));
227 st0x_dr = (void *) (((unsigned char *) base_address ) + (controller_type == SEAGATE ? 0x1c00 : 0x1e00));
228 #ifdef DEBUG
229 printk("ST0x detected. Base address = %x, cr = %x, dr = %x\n", base_address, st0x_cr_sr, st0x_dr);
230 #endif
231
232
233
234
235 hostno = hostnum;
236 if (irqaction(IRQ, &seagate_sigaction)) {
237 printk("scsi%d : unable to allocate IRQ%d\n",
238 hostno, IRQ);
239 return 0;
240 }
241 return -1;
242 }
243 else
244 {
245 #ifdef DEBUG
246 printk("ST0x not detected.\n");
247 #endif
248 return 0;
249 }
250 }
251
252 const char *seagate_st0x_info(void) {
253 static char buffer[256];
254 sprintf(buffer, "scsi%d : %s at irq %d address %p options :"
255 #ifdef FAST
256 #ifdef FAST32
257 " FAST32"
258 #else
259 " FAST"
260 #endif
261 #endif
262
263 #ifdef LINKED
264 " LINKED"
265 #endif
266 "\n", hostno, (controller_type == SEAGATE) ? "seagate" :
267 "FD TMC-950", IRQ, base_address);
268 return buffer;
269 }
270
271
272
273
274
275
276 static unsigned char current_target, current_lun;
277 static unsigned char *current_cmnd, *current_data;
278 static int current_nobuffs;
279 static struct scatterlist *current_buffer;
280 static int current_bufflen;
281
282 #ifdef LINKED
283
284
285
286
287
288
289
290 static int linked_connected = 0;
291 static unsigned char linked_target, linked_lun;
292 #endif
293
294
295 static void (*done_fn)(Scsi_Cmnd *) = NULL;
296 static Scsi_Cmnd * SCint = NULL;
297
298
299
300
301
302
303 #define NO_RECONNECT 0
304 #define RECONNECT_NOW 1
305 #define CAN_RECONNECT 2
306
307 #ifdef LINKED
308
309
310
311
312
313
314
315 #define LINKED_RIGHT 3
316 #define LINKED_WRONG 4
317 #endif
318
319
320
321
322
323 static int should_reconnect = 0;
324
325
326
327
328
329
330
331 static void seagate_reconnect_intr (int unused)
332 {
333 int temp;
334 Scsi_Cmnd * SCtmp;
335
336
337 sti();
338 #if (DEBUG & PHASE_RESELECT)
339 printk("scsi%d : seagate_reconnect_intr() called\n", hostno);
340 #endif
341
342 if (!should_reconnect)
343 printk("scsi%d: unexpected interrupt.\n", hostno);
344 else {
345 should_reconnect = 0;
346
347 #if (DEBUG & PHASE_RESELECT)
348 printk("scsi%d : internal_command("
349 "%d, %08x, %08x, %d, RECONNECT_NOW\n", hostno,
350 current_target, current_data, current_bufflen);
351 #endif
352
353 temp = internal_command (current_target, current_lun,
354 current_cmnd, current_data, current_bufflen,
355 RECONNECT_NOW);
356
357 if (msg_byte(temp) != DISCONNECT) {
358 if (done_fn) {
359 #if (DEBUG & PHASE_RESELECT)
360 printk("scsi%d : done_fn(%d,%08x)", hostno,
361 hostno, temp);
362 #endif
363 if(!SCint) panic("SCint == NULL in seagate");
364 SCtmp = SCint;
365 SCint = NULL;
366 SCtmp->result = temp;
367 done_fn (SCtmp);
368 } else
369 printk("done_fn() not defined.\n");
370 }
371 }
372 }
373
374
375
376
377
378
379
380
381
382
383
384
385 static int recursion_depth = 0;
386
387 int seagate_st0x_queue_command (Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
388 {
389 int result, reconnect;
390 Scsi_Cmnd * SCtmp;
391
392 done_fn = done;
393 current_target = SCpnt->target;
394 current_lun = SCpnt->lun;
395 (const void *) current_cmnd = SCpnt->cmnd;
396 current_data = (unsigned char *) SCpnt->request_buffer;
397 current_bufflen = SCpnt->request_bufflen;
398 SCint = SCpnt;
399 if(recursion_depth) {
400 return 0;
401 };
402 recursion_depth++;
403 do{
404 #ifdef LINKED
405
406
407
408
409 current_cmnd[COMMAND_SIZE(current_cmnd[0])] |= 0x01;
410 if (linked_connected) {
411 #if (DEBUG & DEBUG_LINKED)
412 printk("scsi%d : using linked commands, current I_T_L nexus is ",
413 hostno);
414 #endif
415 if ((linked_target == current_target) &&
416 (linked_lun == current_lun)) {
417 #if (DEBUG & DEBUG_LINKED)
418 printk("correct\n");
419 #endif
420 reconnect = LINKED_RIGHT;
421 } else {
422 #if (DEBUG & DEBUG_LINKED)
423 printk("incorrect\n");
424 #endif
425 reconnect = LINKED_WRONG;
426 }
427 } else
428 #endif
429 reconnect = CAN_RECONNECT;
430
431
432
433
434
435 result = internal_command (SCint->target, SCint->lun, SCint->cmnd, SCint->request_buffer,
436 SCint->request_bufflen,
437 reconnect);
438 if (msg_byte(result) == DISCONNECT) break;
439 SCtmp = SCint;
440 SCint = NULL;
441 SCtmp->result = result;
442 done_fn (SCtmp);
443 } while(SCint);
444 recursion_depth--;
445 return 0;
446 }
447
448 int seagate_st0x_command (Scsi_Cmnd * SCpnt) {
449 return internal_command (SCpnt->target, SCpnt->lun, SCpnt->cmnd, SCpnt->request_buffer,
450 SCpnt->request_bufflen,
451 (int) NO_RECONNECT);
452 }
453
454 static int internal_command(unsigned char target, unsigned char lun, const void *cmnd,
455 void *buff, int bufflen, int reselect) {
456 int len;
457 unsigned char *data;
458 struct scatterlist *buffer;
459 int nobuffs;
460 int clock;
461 int temp;
462
463
464 #if ((DEBUG & PHASE_ETC) || (DEBUG & PRINT_COMMAND) || (DEBUG & PHASE_EXIT))
465 int i;
466 #endif
467
468 #if (DEBUG & PHASE_ETC)
469 int phase=0, newphase;
470 #endif
471
472 int done = 0;
473 unsigned char status = 0;
474 unsigned char message = 0;
475 register unsigned char status_read;
476
477 unsigned transfersize = 0, underflow = 0;
478
479 incommand = 0;
480 st0x_aborted = 0;
481
482 #if (DEBUG & PRINT_COMMAND)
483 printk ("scsi%d : target = %d, command = ", hostno, target);
484 for (i = 0; i < COMMAND_SIZE(((unsigned char *)cmnd)[0]); ++i)
485 printk("%02x ", ((unsigned char *) cmnd)[i]);
486 printk("\n");
487 #endif
488
489 #if (DEBUG & PHASE_RESELECT)
490 switch (reselect) {
491 case RECONNECT_NOW :
492 printk("scsi%d : reconnecting\n", hostno);
493 break;
494 #ifdef LINKED
495 case LINKED_RIGHT :
496 printk("scsi%d : connected, can reconnect\n", hostno);
497 break;
498 case LINKED_WRONG :
499 printk("scsi%d : connected to wrong target, can reconnect\n",
500 hostno);
501 break;
502 #endif
503 case CAN_RECONNECT :
504 printk("scsi%d : allowed to reconnect\n", hostno);
505 break;
506 default :
507 printk("scsi%d : not allowed to reconnect\n", hostno);
508 }
509 #endif
510
511
512 if (target == (controller_type == SEAGATE ? 7 : 6))
513 return DID_BAD_TARGET;
514
515
516
517
518
519
520
521 switch (reselect) {
522 case RECONNECT_NOW:
523 #if (DEBUG & PHASE_RESELECT)
524 printk("scsi%d : phase RESELECT \n", hostno);
525 #endif
526
527
528
529
530
531
532
533
534
535
536 for (clock = jiffies + 10, temp = 0; (jiffies < clock) &&
537 !(STATUS & STAT_IO););
538
539 if (jiffies >= clock)
540 {
541 #if (DEBUG & PHASE_RESELECT)
542 printk("scsi%d : RESELECT timed out while waiting for IO .\n",
543 hostno);
544 #endif
545 return (DID_BAD_INTR << 16);
546 }
547
548
549
550
551
552
553 if (!((temp = DATA) & (controller_type == SEAGATE ? 0x80 : 0x40)))
554 {
555 #if (DEBUG & PHASE_RESELECT)
556 printk("scsi%d : detected reconnect request to different target.\n"
557 "\tData bus = %d\n", hostno, temp);
558 #endif
559 return (DID_BAD_INTR << 16);
560 }
561
562 if (!(temp & (1 << current_target)))
563 {
564 printk("scsi%d : Unexpected reselect interrupt. Data bus = %d\n",
565 hostno, temp);
566 return (DID_BAD_INTR << 16);
567 }
568
569 buffer=current_buffer;
570 cmnd=current_cmnd;
571 data=current_data;
572 len=current_bufflen;
573 nobuffs=current_nobuffs;
574
575
576
577
578
579
580 CONTROL = (BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY);
581
582
583
584
585
586
587 for (clock = jiffies + 10; (jiffies < clock) && (STATUS & STAT_SEL););
588
589 if (jiffies >= clock)
590 {
591 CONTROL = (BASE_CMD | CMD_INTR);
592 #if (DEBUG & PHASE_RESELECT)
593 printk("scsi%d : RESELECT timed out while waiting for SEL.\n",
594 hostno);
595 #endif
596 return (DID_BAD_INTR << 16);
597 }
598
599 CONTROL = BASE_CMD;
600
601
602
603
604
605 break;
606 case CAN_RECONNECT:
607
608 #ifdef LINKED
609
610
611
612
613
614
615
616 connect_loop :
617
618 #endif
619
620 #if (DEBUG & PHASE_BUS_FREE)
621 printk ("scsi%d : phase = BUS FREE \n", hostno);
622 #endif
623
624
625
626
627
628
629
630
631
632
633 clock = jiffies + ST0X_BUS_FREE_DELAY;
634
635 while (((STATUS | STATUS | STATUS) &
636 (STAT_BSY | STAT_SEL)) &&
637 (!st0x_aborted) && (jiffies < clock));
638
639 if (jiffies > clock)
640 return retcode(DID_BUS_BUSY);
641 else if (st0x_aborted)
642 return retcode(st0x_aborted);
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657 #if (DEBUG & PHASE_SELECTION)
658 printk("scsi%d : phase = SELECTION\n", hostno);
659 #endif
660
661 clock = jiffies + ST0X_SELECTION_DELAY;
662
663
664
665
666
667
668
669 if (reselect)
670 CONTROL = BASE_CMD | CMD_DRVR_ENABLE |
671 CMD_ATTN;
672
673
674
675
676 DATA = (unsigned char) ((1 << target) | (controller_type == SEAGATE ? 0x80 : 0x40));
677
678
679
680
681
682 CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL |
683 (reselect ? CMD_ATTN : 0);
684
685
686
687
688
689 while (!((status_read = STATUS) & STAT_BSY) &&
690 (jiffies < clock) && !st0x_aborted)
691
692 #if (DEBUG & PHASE_SELECTION)
693 {
694 temp = clock - jiffies;
695
696 if (!(jiffies % 5))
697 printk("seagate_st0x_timeout : %d \r",temp);
698
699 }
700 printk("Done. \n");
701 printk("scsi%d : status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n",
702 hostno, status_read, temp, st0x_aborted);
703 #else
704 ;
705 #endif
706
707
708 if ((jiffies > clock) || (!st0x_aborted &&
709 !(status_read & STAT_BSY)))
710 {
711 #if (DEBUG & PHASE_SELECT)
712 printk ("scsi%d : NO CONNECT with target %d, status = %x \n",
713 hostno, target, STATUS);
714 #endif
715 return retcode(DID_NO_CONNECT);
716 }
717
718
719
720
721
722
723
724 if (st0x_aborted) {
725 CONTROL = BASE_CMD;
726 if (STATUS & STAT_BSY) {
727 seagate_st0x_reset();
728 return retcode(DID_RESET);
729 }
730 return retcode(st0x_aborted);
731 }
732
733
734
735 if ((nobuffs = SCint->use_sg)) {
736 #if (DEBUG & DEBUG_SG)
737 {
738 int i;
739 printk("scsi%d : scatter gather requested, using %d buffers.\n",
740 hostno, nobuffs);
741 for (i = 0; i < nobuffs; ++i)
742 printk("scsi%d : buffer %d address = %08x length = %d\n",
743 hostno, i, buffer[i].address, buffer[i].length);
744 }
745 #endif
746
747 buffer = (struct scatterlist *) SCint->buffer;
748 len = buffer->length;
749 data = (unsigned char *) buffer->address;
750 } else {
751 #if (DEBUG & DEBUG_SG)
752 printk("scsi%d : scatter gather not requested.\n", hostno);
753 #endif
754 buffer = NULL;
755 len = SCint->request_bufflen;
756 data = (unsigned char *) SCint->request_buffer;
757 }
758
759 break;
760 #ifdef LINKED
761 case LINKED_RIGHT:
762 break;
763 case LINKED_WRONG:
764 break;
765 #endif
766 }
767
768
769
770
771
772
773
774
775
776
777
778 CONTROL = BASE_CMD | CMD_DRVR_ENABLE |
779 (((reselect == CAN_RECONNECT)
780 #ifdef LINKED
781 || (reselect == LINKED_WRONG)
782 #endif
783 ) ? CMD_ATTN : 0) ;
784
785
786
787
788
789
790
791
792
793
794 #if (DEBUG & PHASE_ETC)
795 printk("scsi%d : phase = INFORMATION TRANSFER\n", hostno);
796 #endif
797
798 incommand = 1;
799 transfersize = SCint->transfersize;
800 underflow = SCint->underflow;
801
802
803
804
805
806
807
808
809
810
811 while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done)
812 {
813 #ifdef PARITY
814 if (status_read & STAT_PARITY)
815 {
816 done = 1;
817 st0x_aborted = DID_PARITY;
818 }
819 #endif
820
821 if (status_read & STAT_REQ)
822 {
823 #if (DEBUG & PHASE_ETC)
824 if ((newphase = (status_read & REQ_MASK)) != phase)
825 {
826 phase = newphase;
827 switch (phase)
828 {
829 case REQ_DATAOUT:
830 printk("scsi%d : phase = DATA OUT\n",
831 hostno);
832 break;
833 case REQ_DATAIN :
834 printk("scsi%d : phase = DATA IN\n",
835 hostno);
836 break;
837 case REQ_CMDOUT :
838 printk("scsi%d : phase = COMMAND OUT\n",
839 hostno);
840 break;
841 case REQ_STATIN :
842 printk("scsi%d : phase = STATUS IN\n",
843 hostno);
844 break;
845 case REQ_MSGOUT :
846 printk("scsi%d : phase = MESSAGE OUT\n",
847 hostno);
848 break;
849 case REQ_MSGIN :
850 printk("scsi%d : phase = MESSAGE IN\n",
851 hostno);
852 break;
853 default :
854 printk("scsi%d : phase = UNKNOWN\n",
855 hostno);
856 st0x_aborted = 1;
857 done = 1;
858 }
859 }
860 #endif
861 switch (status_read & REQ_MASK)
862 {
863 case REQ_DATAOUT :
864
865
866
867
868
869 #ifdef FAST
870 if (!len) {
871 #if 0
872 printk("scsi%d: underflow to target %d lun %d \n",
873 hostno, target, lun);
874 st0x_aborted = DID_ERROR;
875 fast = 0;
876 #endif
877 break;
878 }
879
880 if (fast && transfersize && !(len % transfersize) && (len >= transfersize)
881 #ifdef FAST32
882 && !(transfersize % 4)
883 #endif
884 ) {
885 #if (DEBUG & DEBUG_FAST)
886 printk("scsi%d : FAST transfer, underflow = %d, transfersize = %d\n"
887 " len = %d, data = %08x\n", hostno, SCint->underflow,
888 SCint->transfersize, len, data);
889 #endif
890
891 __asm__("
892 cld;
893 movl %0, %%edi;
894 "
895 #ifdef FAST32
896 " shr $2, %%ecx;
897 1: lodsl;
898 movl %%eax, (%%edi);
899 "
900 #else
901 "1: lodsb;
902 movb %%al, (%%edi);
903 "
904 #endif
905 " loop 1b;" : :
906
907 "r" (st0x_dr), "S" (data), "c" (SCint->transfersize) :
908
909 "eax", "esi", "ecx", "edi");
910
911 len -= transfersize;
912 data += transfersize;
913
914 #if (DEBUG & DEBUG_FAST)
915 printk("scsi%d : FAST transfer complete len = %d data = %08x\n",
916 hostno, len, data);
917 #endif
918
919
920 } else
921 #endif
922
923 {
924
925
926
927
928 __asm__ (
929
930
931
932
933
934
935
936
937
938
939 "movl %0, %%esi\n"
940 "\tmovl %1, %%ecx\n"
941 "\torl %%ecx, %%ecx
942 jz 2f
943
944 cld
945
946 movl _st0x_cr_sr, %%ebx
947 movl _st0x_dr, %%edi
948
949 1: movb (%%ebx), %%al\n"
950
951
952
953
954 "\ttest $1, %%al
955 jz 2f\n"
956
957
958
959
960 "\ttest $0xe, %%al
961 jnz 2f \n"
962
963
964
965 "\ttest $0x10, %%al
966 jz 1b
967 lodsb
968 movb %%al, (%%edi)
969 loop 1b
970
971 2:
972 movl %%esi, %2
973 movl %%ecx, %3
974 ":
975
976 "=r" (data), "=r" (len) :
977
978 "0" (data), "1" (len) :
979
980 "ebx", "ecx", "edi", "esi");
981 }
982
983 if (!len && nobuffs) {
984 --nobuffs;
985 ++buffer;
986 len = buffer->length;
987 data = (unsigned char *) buffer->address;
988 #if (DEBUG & DEBUG_SG)
989 printk("scsi%d : next scatter-gather buffer len = %d address = %08x\n",
990 hostno, len, data);
991 #endif
992 }
993 break;
994
995 case REQ_DATAIN :
996 #ifdef FAST
997 if (!len) {
998 #if 0
999 printk("scsi%d: overflow from target %d lun %d \n",
1000 hostno, target, lun);
1001 st0x_aborted = DID_ERROR;
1002 fast = 0;
1003 #endif
1004 break;
1005 }
1006
1007 if (fast && transfersize && !(len % transfersize) && (len >= transfersize)
1008 #ifdef FAST32
1009 && !(transfersize % 4)
1010 #endif
1011 ) {
1012 #if (DEBUG & DEBUG_FAST)
1013 printk("scsi%d : FAST transfer, underflow = %d, transfersize = %d\n"
1014 " len = %d, data = %08x\n", hostno, SCint->underflow,
1015 SCint->transfersize, len, data);
1016 #endif
1017 __asm__("
1018 cld;
1019 movl %0, %%esi;
1020 "
1021 #ifdef FAST32
1022 " shr $2, %%ecx;
1023 1: movl (%%esi), %%eax;
1024 stosl;
1025 "
1026 #else
1027 "1: movb (%%esi), %%al;
1028 stosb;
1029 "
1030 #endif
1031
1032 " loop 1b;" : :
1033
1034 "r" (st0x_dr), "D" (data), "c" (SCint->transfersize) :
1035
1036 "eax", "ecx", "edi", "esi");
1037
1038 len -= transfersize;
1039 data += transfersize;
1040
1041 #if (DEBUG & DEBUG_FAST)
1042 printk("scsi%d : FAST transfer complete len = %d data = %08x\n",
1043 hostno, len, data);
1044 #endif
1045
1046 } else
1047 #endif
1048 {
1049
1050
1051
1052
1053
1054 __asm__ (
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065 "movl %0, %%edi\n"
1066 "\tmovl %1, %%ecx\n"
1067 "\torl %%ecx, %%ecx
1068 jz 2f
1069
1070 cld
1071 movl _st0x_cr_sr, %%esi
1072 movl _st0x_dr, %%ebx
1073
1074 1: movb (%%esi), %%al\n"
1075
1076
1077
1078
1079 "\ttest $1, %%al
1080 jz 2f\n"
1081
1082
1083
1084
1085 "\tmovb $0xe, %%ah
1086 andb %%al, %%ah
1087 cmpb $0x04, %%ah
1088 jne 2f\n"
1089
1090
1091
1092
1093 "\ttest $0x10, %%al
1094 jz 1b
1095
1096 movb (%%ebx), %%al
1097 stosb
1098 loop 1b
1099
1100 2: movl %%edi, %2\n" /* data */
1101 "\tmovl %%ecx, %3\n"
1102 :
1103
1104 "=r" (data), "=r" (len) :
1105
1106 "0" (data), "1" (len) :
1107
1108 "ebx", "ecx", "edi", "esi");
1109 }
1110 if (!len && nobuffs) {
1111 --nobuffs;
1112 ++buffer;
1113 len = buffer->length;
1114 data = (unsigned char *) buffer->address;
1115 #if (DEBUG & DEBUG_SG)
1116 printk("scsi%d : next scatter-gather buffer len = %d address = %08x\n",
1117 hostno, len, data);
1118 #endif
1119 }
1120
1121 break;
1122
1123 case REQ_CMDOUT :
1124 while (((status_read = STATUS) & STAT_BSY) &&
1125 ((status_read & REQ_MASK) == REQ_CMDOUT))
1126 if (status_read & STAT_REQ) {
1127 DATA = *(unsigned char *) cmnd;
1128 cmnd = 1+(unsigned char *) cmnd;
1129 }
1130 break;
1131
1132 case REQ_STATIN :
1133 status = DATA;
1134 break;
1135
1136 case REQ_MSGOUT :
1137
1138
1139
1140
1141
1142 CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
1143
1144
1145
1146
1147 switch (reselect) {
1148 case CAN_RECONNECT:
1149 DATA = IDENTIFY(1, lun);
1150 #if (DEBUG & (PHASE_RESELECT | PHASE_MSGOUT))
1151 printk("scsi%d : sent IDENTIFY message.\n", hostno);
1152 #endif
1153 break;
1154 #ifdef LINKED
1155 case LINKED_WRONG:
1156 DATA = ABORT;
1157 linked_connected = 0;
1158 reselect = CAN_RECONNECT;
1159 goto connect_loop;
1160 #if (DEBUG & (PHASE_MSGOUT | DEBUG_LINKED))
1161 printk("scsi%d : sent ABORT message to cancle incorrect I_T_L nexus.\n", hostno);
1162 #endif
1163 #endif
1164 #if (DEBUG & DEBUG_LINKED)
1165 printk("correct\n");
1166 #endif
1167 default:
1168 DATA = NOP;
1169 #if (DEBUG & PHASE_MSGOUT)
1170 printk("scsi%d : sent NOP message.\n", hostno);
1171 #endif
1172 }
1173 break;
1174
1175 case REQ_MSGIN :
1176 switch (message = DATA) {
1177 case DISCONNECT :
1178 should_reconnect = 1;
1179 current_data = data;
1180 current_buffer = buffer;
1181 current_bufflen = len;
1182 current_nobuffs = nobuffs;
1183 #ifdef LINKED
1184 linked_connected = 0;
1185 #endif
1186 done=1;
1187 #if (DEBUG & (PHASE_RESELECT | PHASE_MSGIN))
1188 printk("scsi%d : disconnected.\n", hostno);
1189 #endif
1190 break;
1191
1192 #ifdef LINKED
1193 case LINKED_CMD_COMPLETE:
1194 case LINKED_FLG_CMD_COMPLETE:
1195 #endif
1196 case COMMAND_COMPLETE :
1197
1198
1199
1200 #if (DEBUG & PHASE_MSGIN)
1201 printk("scsi%d : command complete.\n", hostno);
1202 #endif
1203 done = 1;
1204 break;
1205 case ABORT :
1206 #if (DEBUG & PHASE_MSGIN)
1207 printk("scsi%d : abort message.\n", hostno);
1208 #endif
1209 done=1;
1210 break;
1211 case SAVE_POINTERS :
1212 current_buffer = buffer;
1213 current_bufflen = len;
1214 current_data = data;
1215 current_nobuffs = nobuffs;
1216 #if (DEBUG & PHASE_MSGIN)
1217 printk("scsi%d : pointers saved.\n", hostno);
1218 #endif
1219 break;
1220 case RESTORE_POINTERS:
1221 buffer=current_buffer;
1222 cmnd=current_cmnd;
1223 data=current_data;
1224 len=current_bufflen;
1225 nobuffs=current_nobuffs;
1226 #if (DEBUG & PHASE_MSGIN)
1227 printk("scsi%d : pointers restored.\n", hostno);
1228 #endif
1229 break;
1230 default:
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241 if (message & 0x80) {
1242 #if (DEBUG & PHASE_MSGIN)
1243 printk("scsi%d : IDENTIFY message received from id %d, lun %d.\n",
1244 hostno, target, message & 7);
1245 #endif
1246 } else {
1247
1248
1249
1250
1251
1252
1253
1254 #if (DEBUG & PHASE_MSGIN)
1255 printk("scsi%d : unknown message %d from target %d.\n",
1256 hostno, message, target);
1257 #endif
1258 }
1259 }
1260 break;
1261
1262 default :
1263 printk("scsi%d : unknown phase.\n", hostno);
1264 st0x_aborted = DID_ERROR;
1265 }
1266 }
1267 }
1268
1269 #if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT))
1270 printk("Transfered %d bytes, allowed %d additional bytes\n", (bufflen - len), len);
1271 #endif
1272
1273 #if (DEBUG & PHASE_EXIT)
1274 printk("Buffer : \n");
1275 for (i = 0; i < 20; ++i)
1276 printk ("%02x ", ((unsigned char *) data)[i]);
1277 printk("\n");
1278 printk("Status = %02x, message = %02x\n", status, message);
1279 #endif
1280
1281 if (st0x_aborted) {
1282 if (STATUS & STAT_BSY) {
1283 seagate_st0x_reset();
1284 st0x_aborted = DID_RESET;
1285 }
1286 abort_confirm = 1;
1287 }
1288 #ifdef LINKED
1289 else {
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300 switch (message) {
1301 case LINKED_CMD_COMPLETE :
1302 case LINKED_FLG_CMD_COMPLETE :
1303 message = COMMAND_COMPLETE;
1304 linked_target = current_target;
1305 linked_lun = current_lun;
1306 linked_connected = 1;
1307 #if (DEBUG & DEBUG_LINKED)
1308 printk("scsi%d : keeping I_T_L nexus established for linked command.\n",
1309 hostno);
1310 #endif
1311
1312
1313
1314 if ((status == INTERMEDIATE_GOOD) ||
1315 (status == INTERMEDIATE_C_GOOD))
1316 status = GOOD;
1317
1318 break;
1319
1320
1321
1322
1323
1324
1325 default :
1326 #if (DEBUG & DEBUG_LINKED)
1327 printk("scsi%d : closing I_T_L nexus.\n", hostno);
1328 #endif
1329 linked_connected = 0;
1330 }
1331 }
1332 #endif
1333
1334
1335
1336
1337 if (should_reconnect) {
1338 #if (DEBUG & PHASE_RESELECT)
1339 printk("scsi%d : exiting seagate_st0x_queue_command() with reconnect enabled.\n",
1340 hostno);
1341 #endif
1342 CONTROL = BASE_CMD | CMD_INTR ;
1343 } else
1344 CONTROL = BASE_CMD;
1345
1346 return retcode (st0x_aborted);
1347 }
1348
1349 int seagate_st0x_abort (Scsi_Cmnd * SCpnt, int code)
1350 {
1351 if (code)
1352 st0x_aborted = code;
1353 else
1354 st0x_aborted = DID_ABORT;
1355
1356 return 0;
1357 }
1358
1359
1360
1361
1362
1363 int seagate_st0x_reset (void)
1364 {
1365 unsigned clock;
1366
1367
1368
1369
1370
1371 #ifdef DEBUG
1372 printk("In seagate_st0x_reset()\n");
1373 #endif
1374
1375
1376
1377
1378 CONTROL = BASE_CMD | CMD_RST;
1379 clock=jiffies+2;
1380
1381
1382
1383
1384 while (jiffies < clock);
1385
1386 CONTROL = BASE_CMD;
1387
1388 st0x_aborted = DID_RESET;
1389
1390 #ifdef DEBUG
1391 printk("SCSI bus reset.\n");
1392 #endif
1393 return 0;
1394 }
1395
1396 #ifdef CONFIG_BLK_DEV_SD
1397
1398 #include <asm/segment.h>
1399 #include "sd.h"
1400 #include "scsi_ioctl.h"
1401
1402 int seagate_st0x_biosparam(int size, int dev, int* ip) {
1403 unsigned char buf[256 + sizeof(int) * 2], cmd[6], *data, *page;
1404 int *sizes, result, formatted_sectors, total_sectors;
1405 int cylinders, heads, sectors;
1406
1407 unsigned long oldfs;
1408 Scsi_Device *disk;
1409
1410 disk = rscsi_disks[MINOR(dev) >> 4].device;
1411
1412
1413
1414
1415
1416
1417 if (disk->scsi_level < 2)
1418 return -1;
1419
1420 sizes = (int *) buf;
1421 data = (unsigned char *) (sizes + 2);
1422
1423
1424
1425
1426
1427
1428 oldfs = get_fs();
1429 set_fs(get_ds());
1430
1431 cmd[0] = MODE_SENSE;
1432 cmd[1] = (disk->lun << 5) & 0xe5;
1433 cmd[2] = 0x04;
1434 cmd[3] = 0;
1435 cmd[4] = 255;
1436 cmd[5] = 0;
1437
1438
1439
1440
1441
1442
1443 sizes[0] = 0;
1444 sizes[1] = 256;
1445
1446 memcpy (data, cmd, 6);
1447
1448 if (!(result = scsi_ioctl (disk, SCSI_IOCTL_SEND_COMMAND, (void *) buf))) {
1449
1450
1451
1452
1453
1454 page = data + 4 + data[3];
1455 heads = (int) page[5];
1456 cylinders = (page[2] << 16) | (page[3] << 8) | page[4];
1457
1458 cmd[2] = 0x03;
1459 memcpy (data, cmd, 6);
1460
1461 if (!(result = scsi_ioctl (disk, SCSI_IOCTL_SEND_COMMAND, (void *) buf))) {
1462 page = data + 4 + data[3];
1463 sectors = (page[10] << 8) | page[11];
1464
1465
1466
1467
1468
1469
1470
1471 formatted_sectors = (data[4 + 1] << 16) | (data[4 + 2] << 8) |
1472 data[4 + 3] ;
1473
1474 total_sectors = (heads * cylinders * sectors);
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484 printk("scsi%d : heads = %d cylinders = %d sectors = %d total = %d formatted = %d\n",
1485 hostno, heads, cylinders, sectors, total_sectors, formatted_sectors);
1486
1487 cylinders -= ((total_sectors - formatted_sectors) / (heads * sectors));
1488
1489
1490
1491
1492
1493
1494
1495 if ((cylinders > 1024) || (sectors > 64))
1496 result = -1;
1497 else {
1498 ip[0] = heads;
1499 ip[1] = sectors;
1500 ip[2] = cylinders;
1501 }
1502
1503
1504
1505
1506
1507
1508 }
1509 }
1510
1511 set_fs(oldfs);
1512 return result;
1513 }
1514 #endif
1515
1516 #endif
1517