1 /*
2 * seagate.c Copyright (C) 1992 Drew Eckhardt
3 * low level scsi driver for ST01/ST02 by
4 * Drew Eckhardt
5 *
6 * <drew@colorado.edu>
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 "seagate.h"
17 #include "scsi.h"
18 #include "hosts.h"
19
20
21 static int internal_command(unsigned char target, const void *cmnd,
22 void *buff, int bufflen, int reselect);
23
24 static int incommand; /*
25 set if arbitration has finished and we are
26 in some command phase.
27 */
28
29 static void *base_address = NULL; /*
30 Where the card ROM starts,
31 used to calculate memory mapped
32 register location.
33 */
34 static volatile int abort_confirm = 0;
35
36 static volatile void *st0x_cr_sr; /*
37 control register write,
38 status register read.
39 256 bytes in length.
40
41 Read is status of SCSI BUS,
42 as per STAT masks.
43
44 */
45
46
47 static volatile void *st0x_dr; /*
48 data register, read write
49 256 bytes in length.
50 */
51
52
53 static volatile int st0x_aborted=0; /*
54 set when we are aborted, ie by a time out, etc.
55 */
56
57 /*
58 In theory, we have a nice auto
59 detect routine - but this
60 overides it.
61 */
62
63
64 #define retcode(result) (((result) << 16) | (message << 8) | status)
65 #define STATUS (*(unsigned char *) st0x_cr_sr)
66 #define CONTROL STATUS
67 #define DATA (*(unsigned char *) st0x_dr)
68
69 #ifndef OVERRIDE
70 static const char * seagate_bases[] = {(char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000, (char *) 0xce000, (char *) 0xce000,
71 (char *) 0xdc000, (char *) 0xde000};
72 typedef struct
73 {
74 char *signature ;
75 unsigned offset;
76 unsigned length;
77 } Signature;
78
79 static const Signature signatures[] = {
80 #ifdef CONFIG_SCSI_SEAGATE
81 {"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40},
82
83 /*
84 The following two lines are NOT mistakes. One detects
85 ROM revision 3.0.0, the other 3.2. Since seagate
86 has only one type of SCSI adapter, and this is not
87 going to change, the "SEAGATE" and "SCSI" together
88 are probably "good enough"
89 */
90
91 {"SEAGATE SCSI BIOS ",16, 17},
92 {"SEAGATE SCSI BIOS ",17, 17},
93 #endif
94
95 /*
96 This is for the Future Domain 88x series. I've been told that
97 the Seagate controllers are just repackages of these, and seeing
98 early seagate BIOS bearing the Future Domain copyright,
99 I believe it.
100 */
101
102 #ifdef CONFIG_SCSI_FD_88x
103 {"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/90", 5, 46},
104 #endif
105 }
106 ;
107 /*
108 Note that the last signature handles BIOS revisions 3.0.0 and
109 3.2 - the real ID's are
110
111 SEAGATE SCSI BIOS REVISION 3.0.0
112 SEAGATE SCSI BIOS REVISION 3.2
113
114 */
115
116 #define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature))
117 #endif
118
119 /*
120 * hostno stores the hostnumber, as told to us by the init routine.
121 */
122
123 static int hostno = -1;
124 static void seagate_reconnect_intr(int);
125
126 int seagate_st0x_detect (int hostnum)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
127 {
128 #ifndef OVERRIDE
129 int i,j;
130 #endif
131 static struct sigaction seagate_sigaction = {
132 &seagate_reconnect_intr,
133 0,
134 SA_INTERRUPT,
135 NULL
136 };
137
138 /*
139 * First, we try for the manual override.
140 */
141 #ifdef DEBUG
142 printk("Autodetecting seagate ST0x\n");
143 #endif
144
145 if (hostno != -1)
146 {
147 printk ("ERROR : seagate_st0x_detect() called twice.\n");
148 return 0;
149 }
150
151 base_address = NULL;
152 #ifdef OVERRIDE
153 base_address = (void *) OVERRIDE;
154 #ifdef DEBUG
155 printk("Base address overridden to %x\n", base_address);
156 #endif
157 #else
158 /*
159 * To detect this card, we simply look for the signature
160 * from the BIOS version notice in all the possible locations
161 * of the ROM's. This has a nice sideeffect of not trashing
162 * any register locations that might be used by something else.
163 */
164
165 for (i = 0; i < (sizeof (seagate_bases) / sizeof (char * )); ++i)
166 for (j = 0; !base_address && j < NUM_SIGNATURES; ++j)
167 if (!memcmp ((void *) (seagate_bases[i] +
168 signatures[j].offset), (void *) signatures[j].signature,
169 signatures[j].length))
170 base_address = (void *) seagate_bases[i];
171 #endif
172
173 if (base_address)
174 {
175 st0x_cr_sr =(void *) (((unsigned char *) base_address) + 0x1a00);
176 st0x_dr = (void *) (((unsigned char *) base_address )+ 0x1c00);
177 #ifdef DEBUG
178 printk("ST0x detected. Base address = %x, cr = %x, dr = %x\n", base_address, st0x_cr_sr, st0x_dr);
179 #endif
180 /*
181 * At all times, we will use IRQ 5.
182 */
183 hostno = hostnum;
184 if (irqaction(5, &seagate_sigaction)) {
185 printk("Unable to allocate IRQ5 for ST0x driver\n");
186 return 0;
187 }
188 return -1;
189 }
190 else
191 {
192 #ifdef DEBUG
193 printk("ST0x not detected.\n");
194 #endif
195 return 0;
196 }
197 }
198
199 char *seagate_st0x_info(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
200 {
201 static char buffer[] = "Seagate ST-0X SCSI driver by Drew Eckhardt \n"
202 "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/seagate.c,v 1.1 1992/07/24 06:27:38 root Exp root $\n";
203 return buffer;
204 }
205
206 /*
207 * These are our saved pointers for the outstanding command that is
208 * waiting for a reconnect
209 */
210
211 static unsigned char current_target;
212 static unsigned char *current_cmnd, *current_data;
213 static int current_bufflen;
214 static void (*done_fn)(int, int) = NULL;
215
216 /*
217 * These control whether or not disconnect / reconnect will be attempted,
218 * or are being attempted.
219 */
220
221 #define NO_RECONNECT 0
222 #define RECONNECT_NOW 1
223 #define CAN_RECONNECT 2
224
225 /*
226 * This determines if we are expecting to reconnect or not.
227 */
228
229 static int should_reconnect = 0;
230
231 /*
232 * The seagate_reconnect_intr routine is called when a target reselects the
233 * host adapter. This occurs on the interrupt triggered by the target
234 * asserting SEL.
235 */
236
237 static void seagate_reconnect_intr (int unused)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
238 {
239 int temp;
240
241 /* enable all other interrupts. */
242 sti();
243 #if (DEBUG & PHASE_RESELECT)
244 printk("scsi%d : seagate_reconnect_intr() called\n", hostno);
245 #endif
246
247 if (!should_reconnect)
248 printk("scsi%d: unexpected interrupt.\n", hostno);
249 else
250 {
251 should_reconnect = 0;
252
253 #if (DEBUG & PHASE_RESELECT)
254 printk("scsi%d : internal_command("
255 "%d, %08x, %08x, %d, RECONNECT_NOW\n", hostno,
256 current_target, current_data, current_bufflen);
257 #endif
258
259 temp = internal_command (current_target,
260 current_cmnd, current_data, current_bufflen,
261 RECONNECT_NOW);
262
263 if (msg_byte(temp) != DISCONNECT)
264 {
265 if (done_fn)
266 {
267 #if (DEBUG & PHASE_RESELECT)
268 printk("scsi%d : done_fn(%d,%08x)", hostno,
269 hostno, temp);
270 #endif
271 done_fn (hostno, temp);
272 }
273 else
274 printk("done_fn() not defined.\n");
275 }
276 }
277 }
278
279 /*
280 * The seagate_st0x_queue_command() function provides a queued interface
281 * to the seagate SCSI driver. Basically, it just passes control onto the
282 * seagate_command() function, after fixing it so that the done_fn()
283 * is set to the one passed to the function.
284 */
285
286 int seagate_st0x_queue_command (unsigned char target, const void *cmnd,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
287 void *buff, int bufflen, void (*fn)(int,
288 int))
289 {
290 int result;
291
292 done_fn = fn;
293 current_target = target;
294 (const void *) current_cmnd = cmnd;
295 current_data = buff;
296 current_bufflen = bufflen;
297
298 result = internal_command (target, cmnd, buff, bufflen,
299 CAN_RECONNECT);
300 if (msg_byte(result) == DISCONNECT)
301 return 0;
302 else
303 {
304 done_fn (hostno, result);
305 return 1;
306 }
307 }
308
309 int seagate_st0x_command (unsigned char target, const void *cmnd,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
310 void *buff, int bufflen)
311 {
312 return internal_command (target, cmnd, buff, bufflen,
313 (int) NO_RECONNECT);
314 }
315
316 static int internal_command(unsigned char target, const void *cmnd,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
317 void *buff, int bufflen, int reselect)
318 {
319 int len;
320 unsigned char *data;
321 int clock;
322 int temp;
323
324
325 #if ((DEBUG & PHASE_ETC) || (DEBUG & PRINT_COMMAND) || (DEBUG & PHASE_EXIT))
326 int i;
327 #endif
328
329 #if (DEBUG & PHASE_ETC)
330 int phase=0, newphase;
331 #endif
332
333 int done = 0;
334 unsigned char status = 0;
335 unsigned char message = 0;
336 register unsigned char status_read;
337
338 len=bufflen;
339 data=(unsigned char *) buff;
340
341 incommand = 0;
342 st0x_aborted = 0;
343
344 #if (DEBUG & PRINT_COMMAND)
345 printk ("scsi%d : target = %d, command = ", hostno, target);
346 for (i = 0; i < COMMAND_SIZE(((unsigned char *)cmnd)[0]); ++i)
347 printk("%02x ", ((unsigned char *) cmnd)[i]);
348 printk("\n");
349 #endif
350
351 #if (DEBUG & PHASE_RESELECT)
352 switch (reselect)
353 {
354 case RECONNECT_NOW :
355 printk("scsi%d : reconnecting\n", hostno);
356 break;
357 case CAN_RECONNECT :
358 printk("scsi%d : allowed to reconnect\n", hostno);
359 break;
360 default :
361 printk("scsi%d : not allowed to reconnect\n", hostno);
362 }
363 #endif
364
365
366 if (target > 6)
367 return DID_BAD_TARGET;
368
369 /*
370 * We work it differently depending on if this is is "the first time,"
371 * or a reconnect. If this is a reselct phase, then SEL will
372 * be asserted, and we must skip selection / arbitration phases.
373 */
374
375 if (reselect == RECONNECT_NOW)
376 {
377 #if (DEBUG & PHASE_RESELECT)
378 printk("scsi%d : phase RESELECT \n", hostno);
379 #endif
380
381 /*
382 * At this point, we should find the logical or of our ID and the original
383 * target's ID on the BUS, with BSY, SEL, and I/O signals asserted.
384 *
385 * After ARBITRATION phase is completed, only SEL, BSY, and the
386 * target ID are asserted. A valid initator ID is not on the bus
387 * until IO is asserted, so we must wait for that.
388 */
389
390 for (clock = jiffies + 10, temp = 0; (jiffies < clock) &&
391 !(STATUS & STAT_IO););
392
393 if (jiffies >= clock)
394 {
395 #if (DEBUG & PHASE_RESELECT)
396 printk("scsi%d : RESELECT timed out while waiting for IO .\n",
397 hostno);
398 #endif
399 return (DID_BAD_INTR << 16);
400 }
401
402 /*
403 * After I/O is asserted by the target, we can read our ID and its
404 * ID off of the BUS.
405 */
406
407 if (!((temp = DATA) & 0x80))
408 {
409 #if (DEBUG & PHASE_RESELECT)
410 printk("scsi%d : detected reconnect request to different target.\n"
411 "\tData bus = %d\n", hostno, temp);
412 #endif
413 return (DID_BAD_INTR << 16);
414 }
415
416 if (!(temp & (1 << current_target)))
417 {
418 printk("scsi%d : Unexpected reselect interrupt. Data bus = %d\n",
419 hostno, temp);
420 return (DID_BAD_INTR << 16);
421 }
422 data=current_data; /* WDE add */
423 cmnd=current_cmnd; /* WDE add */
424 len=current_bufflen; /* WDE add */
425
426 /*
427 * We have determined that we have been selected. At this point,
428 * we must respond to the reselection by asserting BSY ourselves
429 */
430
431 CONTROL = (BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY);
432
433 /*
434 * The target will drop SEL, and raise BSY, at which time we must drop
435 * BSY.
436 */
437
438 for (clock = jiffies + 10; (jiffies < clock) && (STATUS & STAT_SEL););
439
440 if (jiffies >= clock)
441 {
442 CONTROL = (BASE_CMD | CMD_INTR);
443 #if (DEBUG & PHASE_RESELECT)
444 printk("scsi%d : RESELECT timed out while waiting for SEL.\n",
445 hostno);
446 #endif
447 return (DID_BAD_INTR << 16);
448 }
449
450 CONTROL = BASE_CMD;
451
452 /*
453 * At this point, we have connected with the target and can get
454 * on with our lives.
455 */
456 }
457 else
458 {
459 #if (DEBUG & PHASE_BUS_FREE)
460 printk ("scsi%d : phase = BUS FREE \n", hostno);
461 #endif
462
463 /*
464 * BUS FREE PHASE
465 *
466 * On entry, we make sure that the BUS is in a BUS FREE
467 * phase, by insuring that both BSY and SEL are low for
468 * at least one bus settle delay. Several reads help
469 * eliminate wire glitch.
470 */
471
472 clock = jiffies + ST0X_BUS_FREE_DELAY;
473
474 while (((STATUS | STATUS | STATUS) &
475 (STAT_BSY | STAT_SEL)) &&
476 (!st0x_aborted) && (jiffies < clock));
477
478 if (jiffies > clock)
479 return retcode(DID_BUS_BUSY);
480 else if (st0x_aborted)
481 return retcode(st0x_aborted);
482
483 /*
484 * Bus free has been detected, within BUS settle. I used to
485 * support an arbitration phase - however, on the Seagate, this
486 * degraded performance by a factor > 10 - so it is no more.
487 */
488
489 /*
490 * SELECTION PHASE
491 *
492 * Now, we select the disk, giving it the SCSI ID at data
493 * and a command of PARITY if necessary, and we raise SEL.
494 */
495
496 #if (DEBUG & PHASE_SELECTION)
497 printk("scsi%d : phase = SELECTION\n", hostno);
498 #endif
499
500 clock = jiffies + ST0X_SELECTION_DELAY;
501
502 /*
503 * If we wish to disconnect, we should request a MESSAGE OUT
504 * at this point. Technically, ATTN should be raised before
505 * SEL = true and BSY = false (from arbitration), but I think this
506 * should do.
507 */
508 if (reselect)
509 CONTROL = BASE_CMD | CMD_DRVR_ENABLE |
510 CMD_ATTN;
511
512 /*
513 * We must assert both our ID and our target's ID on the bus.
514 */
515 DATA = (unsigned char) ((1 << target) | 0x80);
516
517 /*
518 * If we are allowing ourselves to reconnect, then I will keep
519 * ATTN raised so we get MSG OUT.
520 */
521 CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL |
522 (reselect ? CMD_ATTN : 0);
523
524 /*
525 * When the SCSI device decides that we're gawking at it, it will
526 * respond by asserting BUSY on the bus.
527 */
528 while (!((status_read = STATUS) & STAT_BSY) &&
529 (jiffies < clock) && !st0x_aborted)
530
531 #if (DEBUG & PHASE_SELECTION)
532 {
533 temp = clock - jiffies;
534
535 if (!(jiffies % 5))
536 printk("seagate_st0x_timeout : %d \r",temp);
537
538 }
539 printk("Done. \n\r");
540 printk("scsi%d : status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n",
541 hostno, status_read, temp, st0x_aborted);
542 #else
543 ;
544 #endif
545
546
547 if ((jiffies > clock) || (!st0x_aborted &&
548 !(status_read & STAT_BSY)))
549 {
550 #if (DEBUG & PHASE_SELECT)
551 printk ("scsi%d : NO CONNECT with target %d, status = %x \n",
552 hostno, target, STATUS);
553 #endif
554 return retcode(DID_NO_CONNECT);
555 }
556
557 /*
558 * If we have been aborted, and we have a command in progress, IE the
559 * target still has BSY asserted, then we will reset the bus, and
560 * notify the midlevel driver to expect sense.
561 */
562
563 if (st0x_aborted)
564 {
565 CONTROL = BASE_CMD;
566 if (STATUS & STAT_BSY)
567 {
568 seagate_st0x_reset();
569 return retcode(DID_RESET);
570 }
571 return retcode(st0x_aborted);
572 }
573 }
574
575 CONTROL = BASE_CMD | CMD_DRVR_ENABLE |
576 ((reselect == CAN_RECONNECT) ? CMD_ATTN : 0) ;
577
578 /*
579 * INFORMATION TRANSFER PHASE
580 *
581 * The nasty looking read / write inline assembler loops we use for
582 * DATAIN and DATAOUT phases are approximately 4-5 times as fast as
583 * the 'C' versions - since we're moving 1024 bytes of data, this
584 * really adds up.
585 */
586
587 #if (DEBUG & PHASE_ETC)
588 printk("scsi%d : phase = INFORMATION TRANSFER\n", hostno);
589 #endif
590
591 incommand = 1;
592
593
594 /*
595 * Now, we poll the device for status information,
596 * and handle any requests it makes. Note that since we are unsure of
597 * how much data will be flowing across the system, etc and cannot
598 * make reasonable timeouts, that we will instead have the midlevel
599 * driver handle any timeouts that occur in this phase.
600 */
601
602 while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done)
603 {
604 #ifdef PARITY
605 if (status_read & STAT_PARITY)
606 {
607 done = 1;
608 st0x_aborted = DID_PARITY;
609 }
610 #endif
611
612 if (status_read & STAT_REQ)
613 {
614 #if (DEBUG & PHASE_ETC)
615 if ((newphase = (status_read & REQ_MASK)) != phase)
616 {
617 phase = newphase;
618 switch (phase)
619 {
620 case REQ_DATAOUT:
621 printk("scsi%d : phase = DATA OUT\n",
622 hostno);
623 break;
624 case REQ_DATAIN :
625 printk("scsi%d : phase = DATA IN\n",
626 hostno);
627 break;
628 case REQ_CMDOUT :
629 printk("scsi%d : phase = COMMAND OUT\n",
630 hostno);
631 break;
632 case REQ_STATIN :
633 printk("scsi%d : phase = STATUS IN\n",
634 hostno);
635 break;
636 case REQ_MSGOUT :
637 printk("scsi%d : phase = MESSAGE OUT\n",
638 hostno);
639 break;
640 case REQ_MSGIN :
641 printk("scsi%d : phase = MESSAGE IN\n",
642 hostno);
643 break;
644 default :
645 printk("scsi%d : phase = UNKNOWN\n",
646 hostno);
647 st0x_aborted = 1;
648 done = 1;
649 }
650 }
651 #endif
652
653 switch (status_read & REQ_MASK)
654 {
655 case REQ_DATAOUT :
656
657 /*
658 * We loop as long as we are in a data out phase, there is data to send,
659 * and BSY is still active.
660 */
661 __asm__ ("
662
663 /*
664 Local variables :
665 len = ecx
666 data = esi
667 st0x_cr_sr = ebx
668 st0x_dr = edi
669
670 Test for any data here at all.
671 */
672 movl %0, %%esi /* local value of data */
673 movl %1, %%ecx /* local value of len */
674 orl %%ecx, %%ecx
675 jz 2f
676
677 cld
678
679 movl _st0x_cr_sr, %%ebx
680 movl _st0x_dr, %%edi
681
682 1: movb (%%ebx), %%al
683 /*
684 Test for BSY
685 */
686
687 test $1, %%al
688 jz 2f
689
690 /*
691 Test for data out phase - STATUS & REQ_MASK should be REQ_DATAOUT, which is 0.
692 */
693 test $0xe, %%al
694 jnz 2f
695 /*
696 Test for REQ
697 */
698 test $0x10, %%al
699 jz 1b
700 lodsb
701 movb %%al, (%%edi)
702 loop 1b
703
704 2:
705 movl %%esi, %2
706 movl %%ecx, %3
707 ":
708 /* output */
709 "=r" (data), "=r" (len) :
710 /* input */
711 "0" (data), "1" (len) :
712 /* clobbered */
713 "ebx", "ecx", "edi", "esi");
714
715 break;
716
717 case REQ_DATAIN :
718 /*
719 * We loop as long as we are in a data in phase, there is room to read,
720 * and BSY is still active
721 */
722
723 __asm__ ("
724 /*
725 Local variables :
726 ecx = len
727 edi = data
728 esi = st0x_cr_sr
729 ebx = st0x_dr
730
731 Test for room to read
732 */
733
734 movl %0, %%edi /* data */
735 movl %1, %%ecx /* len */
736 orl %%ecx, %%ecx
737 jz 2f
738
739 cld
740 movl _st0x_cr_sr, %%esi
741 movl _st0x_dr, %%ebx
742
743 1: movb (%%esi), %%al
744 /*
745 Test for BSY
746 */
747
748 test $1, %%al
749 jz 2f
750
751 /*
752 Test for data in phase - STATUS & REQ_MASK should be REQ_DATAIN, = STAT_IO, which is 4.
753 */
754 movb $0xe, %%ah
755 andb %%al, %%ah
756 cmpb $0x04, %%ah
757 jne 2f
758
759 /*
760 Test for REQ
761 */
762 test $0x10, %%al
763 jz 1b
764
765 movb (%%ebx), %%al
766 stosb
767 loop 1b
768
769 2: movl %%edi, %2 /* data */
770 movl %%ecx, %3 /* len */
771 ":
772 /* output */
773 "=r" (data), "=r" (len) :
774 /* input */
775 "0" (data), "1" (len) :
776 /* clobbered */
777 "ebx", "ecx", "edi", "esi");
778 break;
779
780 case REQ_CMDOUT :
781 while (((status_read = STATUS) & STAT_BSY) &&
782 ((status_read & REQ_MASK) == REQ_CMDOUT))
783 if (status_read & STAT_REQ)
784 DATA = *(unsigned char *) cmnd ++;
785 break;
786
787 case REQ_STATIN :
788 status = DATA;
789 break;
790
791 case REQ_MSGOUT :
792 /*
793 * We can only have sent a MSG OUT if we requested to do this
794 * by raising ATTN. So, we must drop ATTN.
795 */
796
797 CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
798 /*
799 * If we are reconecting, then we must send an IDENTIFY message in
800 * response to MSGOUT.
801 */
802 if (reselect)
803 {
804 DATA = IDENTIFY(1,0);
805 #if (DEBUG & (PHASE_RESELECT | PHASE_MSGOUT))
806 printk("scsi%d : sent IDENTIFY message.\n", hostno);
807 #endif
808 }
809 else
810 {
811 DATA = MESSAGE_REJECT;
812
813 #if (DEBUG & PHASE_MSGOUT)
814 printk("scsi%d : sent MESSAGE REJECT message.\n", hostno);
815 #endif
816 }
817 break;
818
819 case REQ_MSGIN :
820 switch (message = DATA)
821 {
822 case DISCONNECT :
823 should_reconnect = 1;
824 current_data = data; /* WDE add */
825 current_bufflen = len; /* WDE add */
826 #if (DEBUG & (PHASE_RESELECT | PHASE_MSGIN))
827 printk("scsi%d : disconnected.\n", hostno);
828 done=1;
829 break;
830 #endif
831 case COMMAND_COMPLETE :
832 #if (DEBUG & PHASE_MSGIN)
833 printk("scsi%d : command complete.\n", hostno);
834 done=1;
835 break;
836 #endif
837 case ABORT :
838 #if (DEBUG & PHASE_MSGIN)
839 printk("scsi%d : abort message.\n", hostno);
840 #endif
841 done=1;
842 break;
843 case SAVE_POINTERS :
844 current_data = data; /* WDE mod */
845 current_bufflen = len; /* WDE add */
846 #if (DEBUG & PHASE_MSGIN)
847 printk("scsi%d : pointers saved.\n", hostno);
848 #endif
849 break;
850 case RESTORE_POINTERS:
851 data=current_data; /* WDE mod */
852 cmnd=current_cmnd;
853 #if (DEBUG & PHASE_MSGIN)
854 printk("scsi%d : pointers restored.\n", hostno);
855 #endif
856 break;
857 default:
858
859 /*
860 * IDENTIFY distinguishes itself from the other messages by setting the
861 * high byte.
862 */
863
864 if (message & 0x80)
865 {
866 #if (DEBUG & PHASE_MSGIN)
867 printk("scsi%d : IDENTIFY message received from id %d, lun %d.\n",
868 hostno, target, message & 7);
869 #endif
870 }
871 else
872 {
873
874 #if (DEBUG & PHASE_MSGIN)
875 printk("scsi%d : unknown message %d from target %d.\n",
876 hostno, message, target);
877 #endif
878 }
879 }
880 break;
881
882 default :
883 printk("scsi%d : unknown phase.\n", hostno);
884 st0x_aborted = DID_ERROR;
885 }
886 } /* while ends */
887 } /* if ends */
888
889 #if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT))
890 printk("Transfered %d bytes, allowed %d additional bytes\n", (bufflen - len), len);
891 #endif
892
893 #if (DEBUG & PHASE_EXIT)
894 printk("Buffer : \n");
895 for (i = 0; i < 20; ++i)
896 printk ("%02x ", ((unsigned char *) data)[i]); /* WDE mod */
897 printk("\n");
898 printk("Status = %02x, message = %02x\n", status, message);
899 #endif
900
901
902 if (st0x_aborted)
903 {
904 if (STATUS & STAT_BSY)
905 {
906 seagate_st0x_reset();
907 st0x_aborted = DID_RESET;
908 }
909 abort_confirm = 1;
910 }
911
912 if (should_reconnect)
913 {
914 #if (DEBUG & PHASE_RESELECT)
915 printk("scsi%d : exiting seagate_st0x_queue_command() with reconnect enabled.\n",
916 hostno);
917 #endif
918 CONTROL = BASE_CMD | CMD_INTR ;
919 }
920 else
921 CONTROL = BASE_CMD;
922
923 return retcode (st0x_aborted);
924 }
925
926 int seagate_st0x_abort (int code)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
927 {
928 if (code)
929 st0x_aborted = code;
930 else
931 st0x_aborted = DID_ABORT;
932
933 return 0;
934 }
935
936 /*
937 the seagate_st0x_reset function resets the SCSI bus
938 */
939
940 int seagate_st0x_reset (void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
941 {
942 unsigned clock;
943 /*
944 No timeouts - this command is going to fail because
945 it was reset.
946 */
947
948 #ifdef DEBUG
949 printk("In seagate_st0x_reset()\n");
950 #endif
951
952
953 /* assert RESET signal on SCSI bus. */
954
955 CONTROL = BASE_CMD | CMD_RST;
956 clock=jiffies+2;
957
958
959 /* Wait. */
960
961 while (jiffies < clock);
962
963 CONTROL = BASE_CMD;
964
965 st0x_aborted = DID_RESET;
966
967 #ifdef DEBUG
968 printk("SCSI bus reset.\n");
969 #endif
970 return 0;
971 }
972
973 #endif
974