This source file includes following definitions.
- BiosSignature
- sea_queue_length
- seaprobe
- seaprint
- seaattach
- seaintr
- sea_init
- sea_scsi_cmd
- sea_get_scb
- sea_send_scb
- sea_main
- sea_free_scb
- sea_timeout
- sea_reselect
- sea_transfer_pio
- sea_select
- sea_abort
- sea_done
- sea_poll
- sea_information_transfer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 #include <sys/types.h>
68 #include <sys/param.h>
69 #include <sys/systm.h>
70 #include <sys/kernel.h>
71 #include <sys/errno.h>
72 #include <sys/ioctl.h>
73 #include <sys/device.h>
74 #include <sys/buf.h>
75 #include <sys/proc.h>
76 #include <sys/user.h>
77 #include <sys/queue.h>
78 #include <sys/malloc.h>
79
80 #include <machine/intr.h>
81 #include <machine/pio.h>
82
83 #include <scsi/scsi_all.h>
84 #include <scsi/scsi_message.h>
85 #include <scsi/scsiconf.h>
86
87 #include <dev/isa/isareg.h>
88 #include <dev/isa/isavar.h>
89 #include <i386/isa/isa_machdep.h>
90
91 #define SEA_SCB_MAX 32
92 #define SCB_TABLE_SIZE 8
93 #define BLOCK_SIZE 512
94
95
96
97
98
99
100
101
102
103
104 #define SEA_BLINDTRANSFER
105 #define SEA_ASSEMBLER
106
107
108
109
110
111 #undef SEA_NOMSGS
112
113
114
115
116 #undef SEA_NODATAOUT
117
118
119
120
121 #undef SEA_DEBUGQUEUE
122
123
124
125
126
127 #define CMD_RST 0x01
128 #define CMD_SEL 0x02
129 #define CMD_BSY 0x04
130 #define CMD_ATTN 0x08
131 #define CMD_START_ARB 0x10
132 #define CMD_EN_PARITY 0x20
133 #define CMD_INTR 0x40
134 #define CMD_DRVR_ENABLE 0x80
135
136
137
138
139 #define STAT_BSY 0x01
140 #define STAT_MSG 0x02
141 #define STAT_IO 0x04
142 #define STAT_CD 0x08
143 #define STAT_REQ 0x10
144 #define STAT_SEL 0x20
145 #define STAT_PARITY 0x40
146 #define STAT_ARB_CMPL 0x80
147
148
149
150
151 #define PH_DATAOUT (0)
152 #define PH_DATAIN (STAT_IO)
153 #define PH_CMD (STAT_CD)
154 #define PH_STAT (STAT_CD | STAT_IO)
155 #define PH_MSGOUT (STAT_MSG | STAT_CD)
156 #define PH_MSGIN (STAT_MSG | STAT_CD | STAT_IO)
157
158 #define PH_MASK (STAT_MSG | STAT_CD | STAT_IO)
159
160 #define PH_INVALID 0xff
161
162 #define SEA_RAMOFFSET 0x00001800
163
164 #define BASE_CMD (CMD_INTR | CMD_EN_PARITY)
165
166 #define SEAGATE 1
167 #define FDOMAIN 2
168 #define FDOMAIN840 3
169
170
171
172
173 struct sea_scb {
174 u_char *data;
175 int datalen;
176 TAILQ_ENTRY(sea_scb) chain;
177 struct scsi_xfer *xs;
178 int flags;
179 #define SCB_FREE 0
180 #define SCB_ACTIVE 1
181 #define SCB_ABORTED 2
182 #define SCB_TIMEOUT 4
183 #define SCB_ERROR 8
184 };
185
186
187
188
189
190 struct sea_softc {
191 struct device sc_dev;
192 struct isadev sc_id;
193 void *sc_ih;
194
195 int type;
196 caddr_t maddr;
197 caddr_t maddr_cr_sr;
198 caddr_t maddr_dr;
199
200 struct scsi_link sc_link;
201 TAILQ_HEAD(, sea_scb) free_list, ready_list, nexus_list;
202 struct sea_scb *nexus;
203 int numscbs;
204 struct sea_scb scb[SCB_TABLE_SIZE];
205
206 int our_id;
207 u_char our_id_mask;
208 volatile u_char busy[8];
209
210 };
211
212
213 static volatile int main_running = 0;
214
215 #define STATUS (*(volatile u_char *)sea->maddr_cr_sr)
216 #define CONTROL STATUS
217 #define DATA (*(volatile u_char *)sea->maddr_dr)
218
219
220
221
222
223 #define TAG_NEXT -1
224 #define TAG_NONE -2
225
226
227
228
229 typedef struct {
230 char *signature;
231 int offset, length;
232 int type;
233 } BiosSignature;
234
235
236
237
238 static const BiosSignature signatures[] = {
239 {"ST01 v1.7 (C) Copyright 1987 Seagate", 15, 37, SEAGATE},
240 {"SCSI BIOS 2.00 (C) Copyright 1987 Seagate", 15, 40, SEAGATE},
241
242
243
244
245
246
247
248 {"SEAGATE SCSI BIOS ", 16, 17, SEAGATE},
249 {"SEAGATE SCSI BIOS ", 17, 17, SEAGATE},
250
251
252
253
254
255 {"FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89", 5, 45, FDOMAIN},
256 {"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89", 5, 46, FDOMAIN},
257 {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90",5, 47, FDOMAIN},
258 {"FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90",5, 47, FDOMAIN},
259 {"FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90", 5, 46, FDOMAIN},
260 {"FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92", 5, 44, FDOMAIN},
261 {"FUTURE DOMAIN TMC-950", 5, 21, FDOMAIN},
262 };
263
264 #define nsignatures (sizeof(signatures) / sizeof(signatures[0]))
265
266 #ifdef notdef
267 static const char *bases[] = {
268 (char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000,
269 (char *) 0xce000, (char *) 0xdc000, (char *) 0xde000
270 };
271
272 #define nbases (sizeof(bases) / sizeof(bases[0]))
273 #endif
274
275 struct sea_scb *sea_get_scb(struct sea_softc *, int);
276 int seaintr(void *);
277 int sea_scsi_cmd(struct scsi_xfer *);
278 int sea_poll(struct sea_softc *, struct scsi_xfer *, int);
279 int sea_select(struct sea_softc *sea, struct sea_scb *scb);
280 int sea_transfer_pio(struct sea_softc *sea, u_char *phase,
281 int *count, u_char **data);
282 int sea_abort(struct sea_softc *, struct sea_scb *scb);
283 static void sea_main(void);
284 static void sea_information_transfer(struct sea_softc *);
285 void sea_timeout(void *);
286 void sea_done(struct sea_softc *, struct sea_scb *);
287 void sea_free_scb(struct sea_softc *, struct sea_scb *, int);
288 void sea_init(struct sea_softc *);
289 void sea_send_scb(struct sea_softc *sea, struct sea_scb *scb);
290 void sea_reselect(struct sea_softc *sea);
291
292 struct scsi_adapter sea_switch = {
293 sea_scsi_cmd,
294 minphys,
295 0,
296 0,
297 };
298
299
300 struct scsi_device sea_dev = {
301 NULL,
302 NULL,
303 NULL,
304 NULL,
305 };
306
307 int seaprobe(struct device *, void *, void *);
308 void seaattach(struct device *, struct device *, void *);
309 int seaprint(void *, const char *);
310
311 struct cfattach sea_ca = {
312 sizeof(struct sea_softc), seaprobe, seaattach
313 };
314
315 struct cfdriver sea_cd = {
316 NULL, "sea", DV_DULL
317 };
318
319 #ifdef SEA_DEBUGQUEUE
320 void
321 sea_queue_length(struct sea_softc *sea)
322 {
323 struct sea_scb *scb;
324 int connected, issued, disconnected;
325
326 connected = sea->nexus ? 1 : 0;
327 issued = 0;
328 TAILQ_FOREACH(scb, &sea->ready_list, chain)
329 issued++;
330 disconnected = 0;
331 TAILQ_FOREACH(scb, &sea->nexus_list, chain)
332 disconnected++;
333 printf("%s: length: %d/%d/%d\n", sea->sc_dev.dv_xname, connected,
334 issued, disconnected);
335 }
336 #endif
337
338
339
340
341
342
343
344 int
345 seaprobe(struct device *parent, void *match, void *aux)
346 {
347 struct sea_softc *sea = match;
348 struct isa_attach_args *ia = aux;
349 int i;
350
351
352
353
354
355
356
357
358
359 if (ia->ia_maddr == MADDRUNK) {
360
361 return 0;
362 } else
363 sea->maddr = ISA_HOLE_VADDR(ia->ia_maddr);
364
365
366 for (i = 0; i < nsignatures; i++)
367 if (!bcmp(sea->maddr + signatures[i].offset,
368 signatures[i].signature, signatures[i].length)) {
369 sea->type = signatures[i].type;
370 break;
371 }
372
373
374 switch (sea->type) {
375 case SEAGATE:
376 case FDOMAIN840:
377 sea->maddr_cr_sr =
378 (void *) (((u_char *)sea->maddr) + 0x1a00);
379 sea->maddr_dr =
380 (void *) (((u_char *)sea->maddr) + 0x1c00);
381 break;
382 case FDOMAIN:
383 sea->maddr_cr_sr =
384 (void *) (((u_char *)sea->maddr) + 0x1c00);
385 sea->maddr_dr =
386 (void *) (((u_char *)sea->maddr) + 0x1e00);
387 break;
388 default:
389 #if 0
390 printf("%s: board type unknown at address %p\n",
391 sea->sc_dev.dv_xname, sea->maddr);
392 #endif
393 return 0;
394 }
395
396
397 *((u_char *)sea->maddr + SEA_RAMOFFSET) = 0xa5;
398 *((u_char *)sea->maddr + SEA_RAMOFFSET + 1) = 0x5a;
399
400 if ((*((u_char *)sea->maddr + SEA_RAMOFFSET) != 0xa5) ||
401 (*((u_char *)sea->maddr + SEA_RAMOFFSET + 1) != 0x5a)) {
402 printf("%s: board RAM failure\n", sea->sc_dev.dv_xname);
403 return 0;
404 }
405
406 ia->ia_drq = DRQUNK;
407 ia->ia_msize = 0x2000;
408 ia->ia_iosize = 0;
409 return 1;
410 }
411
412 int
413 seaprint(void *aux, const char *name)
414 {
415 if (name != NULL)
416 printf("%s: scsibus ", name);
417 return UNCONF;
418 }
419
420
421
422
423 void
424 seaattach(struct device *parent, struct device *self, void *aux)
425 {
426 struct isa_attach_args *ia = aux;
427 struct sea_softc *sea = (void *)self;
428 struct scsibus_attach_args saa;
429
430 sea_init(sea);
431
432
433
434
435 sea->sc_link.adapter_softc = sea;
436 sea->sc_link.adapter_target = sea->our_id;
437 sea->sc_link.adapter = &sea_switch;
438 sea->sc_link.device = &sea_dev;
439 sea->sc_link.openings = 1;
440
441 printf("\n");
442
443 sea->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
444 IPL_BIO, seaintr, sea, sea->sc_dev.dv_xname);
445
446 bzero(&saa, sizeof(saa));
447 saa.saa_sc_link = &sea->sc_link;
448
449
450
451
452 config_found(self, &saa, seaprint);
453 }
454
455
456
457
458 int
459 seaintr(void *arg)
460 {
461 struct sea_softc *sea = arg;
462
463 #ifdef DEBUG
464 if ((STATUS & STAT_PARITY) == 0 &&
465 (STATUS & (STAT_SEL | STAT_IO)) != (STAT_SEL | STAT_IO))
466 return 0;
467 #endif
468
469 loop:
470
471
472
473 if (STATUS & STAT_PARITY) {
474
475 printf("%s: parity error\n", sea->sc_dev.dv_xname);
476 return 1;
477 }
478
479 if ((STATUS & (STAT_SEL | STAT_IO)) == (STAT_SEL | STAT_IO)) {
480
481 sea_reselect(sea);
482 if (!main_running)
483 sea_main();
484 goto loop;
485 }
486
487 return 1;
488 }
489
490
491
492
493 void
494 sea_init(struct sea_softc *sea)
495 {
496 int i;
497
498
499 CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_RST;
500 delay(25);
501 CONTROL = BASE_CMD;
502 delay(10);
503
504
505 switch (sea->type) {
506 case SEAGATE:
507 sea->our_id = 7;
508 break;
509 case FDOMAIN:
510 case FDOMAIN840:
511 sea->our_id = 6;
512 break;
513 }
514 sea->our_id_mask = 1 << sea->our_id;
515
516
517 sea->nexus = 0;
518 TAILQ_INIT(&sea->ready_list);
519 TAILQ_INIT(&sea->nexus_list);
520 TAILQ_INIT(&sea->free_list);
521 for (i = 0; i < 8; i++)
522 sea->busy[i] = 0x00;
523
524
525 sea->numscbs = SCB_TABLE_SIZE;
526 for (i = 0; i < SCB_TABLE_SIZE; i++) {
527 TAILQ_INSERT_TAIL(&sea->free_list, &sea->scb[i], chain);
528 }
529 }
530
531
532
533
534
535 int
536 sea_scsi_cmd(struct scsi_xfer *xs)
537 {
538 struct scsi_link *sc_link = xs->sc_link;
539 struct sea_softc *sea = sc_link->adapter_softc;
540 struct sea_scb *scb;
541 int flags;
542 int s;
543
544 SC_DEBUG(sc_link, SDEV_DB2, ("sea_scsi_cmd\n"));
545
546 flags = xs->flags;
547 if (flags & ITSDONE) {
548 printf("%s: done?\n", sea->sc_dev.dv_xname);
549 xs->flags &= ~ITSDONE;
550 }
551 if ((scb = sea_get_scb(sea, flags)) == NULL) {
552 return TRY_AGAIN_LATER;
553 }
554 scb->flags = SCB_ACTIVE;
555 scb->xs = xs;
556
557 if (flags & SCSI_RESET) {
558
559
560
561
562 printf("%s: resetting\n", sea->sc_dev.dv_xname);
563 xs->error = XS_DRIVER_STUFFUP;
564 return COMPLETE;
565 }
566
567
568
569
570 scb->datalen = xs->datalen;
571 scb->data = xs->data;
572
573 #ifdef SEA_DEBUGQUEUE
574 sea_queue_length(sea);
575 #endif
576
577 s = splbio();
578
579 sea_send_scb(sea, scb);
580
581
582
583
584 if ((flags & SCSI_POLL) == 0) {
585 timeout_set(&scb->xs->stimeout, sea_timeout, scb);
586 timeout_add(&scb->xs->stimeout, (xs->timeout * hz) / 1000);
587 splx(s);
588 return SUCCESSFULLY_QUEUED;
589 }
590
591 splx(s);
592
593
594
595
596 if (sea_poll(sea, xs, xs->timeout)) {
597 sea_timeout(scb);
598 if (sea_poll(sea, xs, 2000))
599 sea_timeout(scb);
600 }
601 return COMPLETE;
602 }
603
604
605
606
607
608 struct sea_scb *
609 sea_get_scb(struct sea_softc *sea, int flags)
610 {
611 int s;
612 struct sea_scb *scb;
613
614 s = splbio();
615
616
617
618
619
620 for (;;) {
621 scb = TAILQ_FIRST(&sea->free_list);
622 if (scb) {
623 TAILQ_REMOVE(&sea->free_list, scb, chain);
624 break;
625 }
626 if (sea->numscbs < SEA_SCB_MAX) {
627 scb = (struct sea_scb *) malloc(sizeof(struct sea_scb),
628 M_TEMP, M_NOWAIT);
629 if (scb) {
630 bzero(scb, sizeof(struct sea_scb));
631 sea->numscbs++;
632 } else
633 printf("%s: can't malloc scb\n",
634 sea->sc_dev.dv_xname);
635 break;
636 }
637 if ((flags & SCSI_NOSLEEP) != 0)
638 break;
639 tsleep(&sea->free_list, PRIBIO, "seascb", 0);
640 }
641
642 splx(s);
643 return scb;
644 }
645
646
647
648
649
650
651
652
653
654 void
655 sea_send_scb(struct sea_softc *sea, struct sea_scb *scb)
656 {
657
658 TAILQ_INSERT_TAIL(&sea->ready_list, scb, chain);
659
660 if (!main_running)
661 sea_main();
662 }
663
664
665
666
667
668
669 void
670 sea_main(void)
671 {
672 struct sea_softc *sea;
673 struct sea_scb *scb;
674 int done;
675 int unit;
676 int s;
677
678 main_running = 1;
679
680
681
682
683
684 loop:
685 done = 1;
686 for (unit = 0; unit < sea_cd.cd_ndevs; unit++) {
687 sea = sea_cd.cd_devs[unit];
688 if (!sea)
689 continue;
690 s = splbio();
691 if (!sea->nexus) {
692
693
694
695
696 TAILQ_FOREACH(scb, &sea->ready_list, chain) {
697 if (!(sea->busy[scb->xs->sc_link->target] &
698 (1 << scb->xs->sc_link->lun))) {
699 TAILQ_REMOVE(&sea->ready_list, scb,
700 chain);
701
702
703 splx(s);
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728 if ((STATUS & (STAT_SEL | STAT_IO)) ==
729 (STAT_SEL | STAT_IO)) {
730 sea_reselect(sea);
731 break;
732 }
733 if (sea_select(sea, scb)) {
734 s = splbio();
735 TAILQ_INSERT_HEAD(&sea->ready_list,
736 scb, chain);
737 splx(s);
738 } else
739 break;
740 }
741 }
742 if (!sea->nexus) {
743
744 if ((STATUS & (STAT_SEL | STAT_IO)) ==
745 (STAT_SEL | STAT_IO)) {
746 sea_reselect(sea);
747 }
748 }
749 }
750
751 splx(s);
752 if (sea->nexus) {
753 sea_information_transfer(sea);
754 done = 0;
755 } else
756 break;
757 }
758
759 if (!done)
760 goto loop;
761
762 main_running = 0;
763 }
764
765 void
766 sea_free_scb(struct sea_softc *sea, struct sea_scb *scb, int flags)
767 {
768 int s;
769
770 s = splbio();
771
772 scb->flags = SCB_FREE;
773 TAILQ_INSERT_HEAD(&sea->free_list, scb, chain);
774
775
776
777
778
779 if (TAILQ_NEXT(scb, chain) == NULL)
780 wakeup((caddr_t)&sea->free_list);
781
782 splx(s);
783 }
784
785 void
786 sea_timeout(void *arg)
787 {
788 struct sea_scb *scb = arg;
789 struct scsi_xfer *xs = scb->xs;
790 struct scsi_link *sc_link = xs->sc_link;
791 struct sea_softc *sea = sc_link->adapter_softc;
792 int s;
793
794 sc_print_addr(sc_link);
795 printf("timed out");
796
797 s = splbio();
798
799
800
801
802
803
804 if (scb->flags & SCB_ABORTED) {
805
806 printf(" AGAIN\n");
807 scb->xs->retries = 0;
808 scb->flags |= SCB_ABORTED;
809 sea_done(sea, scb);
810 } else {
811
812 printf("\n");
813 scb->flags |= SCB_ABORTED;
814 sea_abort(sea, scb);
815
816 if ((xs->flags & SCSI_POLL) == 0) {
817 timeout_set(&scb->xs->stimeout, sea_timeout, scb);
818 timeout_add(&scb->xs->stimeout, 2 * hz);
819 }
820 }
821
822 splx(s);
823 }
824
825 void
826 sea_reselect(struct sea_softc *sea)
827 {
828 u_char target_mask;
829 int i;
830 u_char lun, phase;
831 u_char msg[3];
832 int len;
833 u_char *data;
834 struct sea_scb *scb;
835 int abort = 0;
836
837 if (!((target_mask = STATUS) & STAT_SEL)) {
838 printf("%s: wrong state 0x%x\n", sea->sc_dev.dv_xname,
839 target_mask);
840 return;
841 }
842
843
844
845 for (i = 10; i && (STATUS & (STAT_SEL | STAT_IO | STAT_BSY)) !=
846 (STAT_SEL | STAT_IO | 0); i--);
847
848
849 target_mask = DATA;
850
851 if (!(target_mask & sea->our_id_mask)) {
852 printf("%s: polled reselection was not for me: 0x%x\n",
853 sea->sc_dev.dv_xname, target_mask);
854 return;
855 }
856
857 target_mask &= ~sea->our_id_mask;
858
859 CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY;
860
861 for (i = 50000; i && (STATUS & STAT_SEL); i++);
862
863 CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
864
865 for (i = 50000; i && !(STATUS & STAT_REQ); i--);
866
867
868 len = 3;
869 data = msg;
870 phase = PH_MSGIN;
871 sea_transfer_pio(sea, &phase, &len, &data);
872
873 if (MSG_ISIDENTIFY(msg[0])) {
874 printf("%s: expecting IDENTIFY message, got 0x%x\n",
875 sea->sc_dev.dv_xname, msg[0]);
876 abort = 1;
877 scb = NULL;
878 } else {
879 lun = msg[0] & 0x07;
880
881
882
883
884
885
886 TAILQ_FOREACH(scb, &sea->nexus_list, chain)
887 if (target_mask == (1 << scb->xs->sc_link->target) &&
888 lun == scb->xs->sc_link->lun) {
889 TAILQ_REMOVE(&sea->nexus_list, scb,
890 chain);
891 break;
892 }
893 if (!scb) {
894 printf("%s: target %02x lun %d not disconnected\n",
895 sea->sc_dev.dv_xname, target_mask, lun);
896
897
898
899
900 abort = 1;
901 }
902 }
903
904 if (abort) {
905 msg[0] = MSG_ABORT;
906 len = 1;
907 data = msg;
908 phase = PH_MSGOUT;
909 CONTROL = BASE_CMD | CMD_ATTN;
910 sea_transfer_pio(sea, &phase, &len, &data);
911 } else
912 sea->nexus = scb;
913
914 return;
915 }
916
917
918
919
920 int
921 sea_transfer_pio(struct sea_softc *sea, u_char *phase, int *count, u_char **data)
922 {
923 u_char p = *phase, tmp;
924 int c = *count;
925 u_char *d = *data;
926 int timeout;
927
928 do {
929
930
931
932
933 for (timeout = 0; timeout < 50000; timeout++)
934 if ((tmp = STATUS) & STAT_REQ)
935 break;
936 if (!(tmp & STAT_REQ)) {
937 printf("%s: timeout waiting for STAT_REQ\n",
938 sea->sc_dev.dv_xname);
939 break;
940 }
941
942
943
944
945
946 if (sea->type == FDOMAIN840)
947 tmp = ((tmp & 0x08) >> 2) |
948 ((tmp & 0x02) << 2) |
949 (tmp & 0xf5);
950 if ((tmp & PH_MASK) != p)
951 break;
952
953
954 if (!(p & STAT_IO))
955 DATA = *d;
956 else
957 *d = DATA;
958 ++d;
959
960
961
962
963
964
965
966
967
968 #if 0
969
970
971
972
973
974 for (timeout = 0; timeout < 200000L; timeout++)
975 if (!(STATUS & STAT_REQ))
976 break;
977 if (STATUS & STAT_REQ)
978 printf("%s: timeout on wait for !STAT_REQ",
979 sea->sc_dev.dv_xname);
980 #endif
981 } while (--c);
982
983 *count = c;
984 *data = d;
985 tmp = STATUS;
986 if (tmp & STAT_REQ)
987 *phase = tmp & PH_MASK;
988 else
989 *phase = PH_INVALID;
990
991 if (c && (*phase != p))
992 return -1;
993 return 0;
994 }
995
996
997
998
999
1000
1001
1002 int
1003 sea_select(struct sea_softc *sea, struct sea_scb *scb)
1004 {
1005 u_char msg[3], phase;
1006 u_char *data;
1007 int len;
1008 int timeout;
1009
1010 CONTROL = BASE_CMD;
1011 DATA = sea->our_id_mask;
1012 CONTROL = (BASE_CMD & ~CMD_INTR) | CMD_START_ARB;
1013
1014
1015 for (timeout = 0; timeout < 3000000L; timeout++)
1016 if (STATUS & STAT_ARB_CMPL)
1017 break;
1018 if (!(STATUS & STAT_ARB_CMPL)) {
1019 if (STATUS & STAT_SEL) {
1020 printf("%s: arbitration lost\n", sea->sc_dev.dv_xname);
1021 scb->flags |= SCB_ERROR;
1022 } else {
1023 printf("%s: arbitration timeout\n",
1024 sea->sc_dev.dv_xname);
1025 scb->flags |= SCB_TIMEOUT;
1026 }
1027 CONTROL = BASE_CMD;
1028 return -1;
1029 }
1030
1031 delay(2);
1032 DATA = (u_char)((1 << scb->xs->sc_link->target) | sea->our_id_mask);
1033 CONTROL =
1034 #ifdef SEA_NOMSGS
1035 (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE | CMD_SEL;
1036 #else
1037 (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE | CMD_SEL | CMD_ATTN;
1038 #endif
1039 delay(1);
1040
1041
1042 for (timeout = 0; timeout < 2000000L; timeout++)
1043 if (STATUS & STAT_BSY)
1044 break;
1045 if (!(STATUS & STAT_BSY)) {
1046
1047 CONTROL = BASE_CMD;
1048 scb->flags |= SCB_TIMEOUT;
1049 return 0;
1050 }
1051
1052
1053 #ifdef SEA_NOMSGS
1054 CONTROL = (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE;
1055 #else
1056 CONTROL = (BASE_CMD & ~CMD_INTR) | CMD_DRVR_ENABLE | CMD_ATTN;
1057 #endif
1058 delay(1);
1059
1060
1061 for (timeout = 0; timeout < 2000000L; timeout++)
1062 if (STATUS & STAT_REQ)
1063 break;
1064
1065 CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
1066 if (!(STATUS & STAT_REQ)) {
1067
1068
1069
1070
1071
1072
1073 } else {
1074 msg[0] = MSG_IDENTIFY(scb->xs->sc_link->lun, 1);
1075 len = 1;
1076 data = msg;
1077 phase = PH_MSGOUT;
1078
1079 sea_transfer_pio(sea, &phase, &len, &data);
1080 }
1081 if (!(STATUS & STAT_BSY))
1082 printf("%s: after successful arbitrate: no STAT_BSY!\n",
1083 sea->sc_dev.dv_xname);
1084
1085 sea->nexus = scb;
1086 sea->busy[scb->xs->sc_link->target] |= 1 << scb->xs->sc_link->lun;
1087
1088 CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
1089
1090 return 0;
1091 }
1092
1093
1094
1095
1096 int
1097 sea_abort(struct sea_softc *sea, struct sea_scb *scb)
1098 {
1099 struct sea_scb *tmp;
1100 u_char msg, phase, *msgptr;
1101 int len;
1102
1103
1104
1105
1106
1107
1108 TAILQ_FOREACH(tmp, &sea->ready_list, chain)
1109 if (scb == tmp) {
1110 TAILQ_REMOVE(&sea->ready_list, scb, chain);
1111
1112 return 1;
1113 }
1114
1115
1116
1117
1118
1119 if (sea->nexus)
1120 return 0;
1121
1122
1123
1124
1125
1126
1127 TAILQ_FOREACH(tmp, &sea->nexus_list, chain)
1128 if (scb == tmp) {
1129 if (sea_select(sea, scb))
1130 return 0;
1131
1132 msg = MSG_ABORT;
1133 msgptr = &msg;
1134 len = 1;
1135 phase = PH_MSGOUT;
1136 CONTROL = BASE_CMD | CMD_ATTN;
1137 sea_transfer_pio(sea, &phase, &len, &msgptr);
1138
1139 TAILQ_FOREACH(tmp, &sea->nexus_list, chain)
1140 if (scb == tmp) {
1141 TAILQ_REMOVE(&sea->nexus_list,
1142 scb, chain);
1143
1144
1145 return 1;
1146 }
1147 }
1148
1149
1150 return 1;
1151 }
1152
1153 void
1154 sea_done(struct sea_softc *sea, struct sea_scb *scb)
1155 {
1156 struct scsi_xfer *xs = scb->xs;
1157
1158 timeout_del(&scb->xs->stimeout);
1159
1160 xs->resid = scb->datalen;
1161
1162
1163 if (scb->flags == SCB_ACTIVE) {
1164 xs->resid = 0;
1165 } else {
1166 if (scb->flags & (SCB_TIMEOUT | SCB_ABORTED))
1167 xs->error = XS_TIMEOUT;
1168 if (scb->flags & SCB_ERROR)
1169 xs->error = XS_DRIVER_STUFFUP;
1170 }
1171 xs->flags |= ITSDONE;
1172 sea_free_scb(sea, scb, xs->flags);
1173 scsi_done(xs);
1174 }
1175
1176
1177
1178
1179 int
1180 sea_poll(struct sea_softc *sea, struct scsi_xfer *xs, int count)
1181 {
1182 int s;
1183
1184 while (count) {
1185
1186 s = splbio();
1187 if (!main_running)
1188 sea_main();
1189 splx(s);
1190 if (xs->flags & ITSDONE)
1191 return 0;
1192 delay(1000);
1193 count--;
1194 }
1195 return 1;
1196 }
1197
1198
1199
1200
1201
1202 void
1203 sea_information_transfer(struct sea_softc *sea)
1204 {
1205 int timeout;
1206 u_char msgout = MSG_NOOP;
1207 int len;
1208 int s;
1209 u_char *data;
1210 u_char phase, tmp, old_phase = PH_INVALID;
1211 struct sea_scb *scb = sea->nexus;
1212 int loop;
1213
1214 for (timeout = 0; timeout < 10000000L; timeout++) {
1215 tmp = STATUS;
1216 if (tmp & STAT_PARITY)
1217 printf("%s: parity error detected\n",
1218 sea->sc_dev.dv_xname);
1219 if (!(tmp & STAT_BSY)) {
1220 for (loop = 0; loop < 20; loop++)
1221 if ((tmp = STATUS) & STAT_BSY)
1222 break;
1223 if (!(tmp & STAT_BSY)) {
1224 printf("%s: !STAT_BSY unit in data transfer!\n",
1225 sea->sc_dev.dv_xname);
1226 s = splbio();
1227 sea->nexus = NULL;
1228 scb->flags = SCB_ERROR;
1229 splx(s);
1230 sea_done(sea, scb);
1231 return;
1232 }
1233 }
1234
1235
1236 if (!(tmp & STAT_REQ))
1237 continue;
1238
1239 if (sea->type == FDOMAIN840)
1240 tmp = ((tmp & 0x08) >> 2) |
1241 ((tmp & 0x02) << 2) |
1242 (tmp & 0xf5);
1243 phase = tmp & PH_MASK;
1244 if (phase != old_phase)
1245 old_phase = phase;
1246
1247 switch (phase) {
1248 case PH_DATAOUT:
1249 #ifdef SEA_NODATAOUT
1250 printf("%s: SEA_NODATAOUT set, attempted DATAOUT aborted\n",
1251 sea->sc_dev.dv_xname);
1252 msgout = MSG_ABORT;
1253 CONTROL = BASE_CMD | CMD_ATTN;
1254 break;
1255 #endif
1256 case PH_DATAIN:
1257 if (!scb->data)
1258 printf("no data address!\n");
1259 #ifdef SEA_BLINDTRANSFER
1260 if (scb->datalen && !(scb->datalen % BLOCK_SIZE)) {
1261 while (scb->datalen) {
1262 for (loop = 0; loop < 50000; loop++)
1263 if ((tmp = STATUS) & STAT_REQ)
1264 break;
1265 if (!(tmp & STAT_REQ)) {
1266 printf("%s: timeout waiting for STAT_REQ\n",
1267 sea->sc_dev.dv_xname);
1268
1269 }
1270 if (sea->type == FDOMAIN840)
1271 tmp = ((tmp & 0x08) >> 2) |
1272 ((tmp & 0x02) << 2) |
1273 (tmp & 0xf5);
1274 if ((tmp & PH_MASK) != phase)
1275 break;
1276 if (!(phase & STAT_IO)) {
1277 int block = BLOCK_SIZE;
1278 void *a = sea->maddr_dr;
1279 #ifdef SEA_ASSEMBLER
1280 asm("shr $2, %%ecx\n\t\
1281 cld\n\t\
1282 rep\n\t\
1283 movsl" :
1284 "=S" (scb->data),
1285 "=c" (block) ,
1286 "=D" (a) :
1287 "0" (scb->data),
1288 "2" (a),
1289 "1" (block) );
1290 #else
1291 for (count = 0;
1292 count < BLOCK_SIZE;
1293 count++)
1294 DATA = *(scb->data++);
1295 #endif
1296 } else {
1297 int block = BLOCK_SIZE;
1298 void *a = sea->maddr_dr;
1299 #ifdef SEA_ASSEMBLER
1300 asm("shr $2, %%ecx\n\t\
1301 cld\n\t\
1302 rep\n\t\
1303 movsl" :
1304 "=D" (scb->data), "=c" (block) ,
1305 "=S" (a) :
1306 "0" (scb->data),
1307 "2" (a) ,
1308 "1" (block) );
1309 #else
1310 for (count = 0;
1311 count < BLOCK_SIZE;
1312 count++)
1313 *(scb->data++) = DATA;
1314 #endif
1315 }
1316 scb->datalen -= BLOCK_SIZE;
1317 }
1318 }
1319 #endif
1320 if (scb->datalen)
1321 sea_transfer_pio(sea, &phase, &scb->datalen,
1322 &scb->data);
1323 break;
1324 case PH_MSGIN:
1325
1326 len = 1;
1327 data = &tmp;
1328 sea_transfer_pio(sea, &phase, &len, &data);
1329
1330
1331 switch (tmp) {
1332 case MSG_ABORT:
1333 scb->flags = SCB_ABORTED;
1334 printf("sea: command aborted by target\n");
1335 CONTROL = BASE_CMD;
1336 sea_done(sea, scb);
1337 return;
1338 case MSG_CMDCOMPLETE:
1339 s = splbio();
1340 sea->nexus = NULL;
1341 splx(s);
1342 sea->busy[scb->xs->sc_link->target] &=
1343 ~(1 << scb->xs->sc_link->lun);
1344 CONTROL = BASE_CMD;
1345 sea_done(sea, scb);
1346 return;
1347 case MSG_MESSAGE_REJECT:
1348 printf("%s: message_reject received\n",
1349 sea->sc_dev.dv_xname);
1350 break;
1351 case MSG_DISCONNECT:
1352 s = splbio();
1353 TAILQ_INSERT_TAIL(&sea->nexus_list,
1354 scb, chain);
1355 sea->nexus = NULL;
1356 CONTROL = BASE_CMD;
1357 splx(s);
1358 return;
1359 case MSG_SAVEDATAPOINTER:
1360 case MSG_RESTOREPOINTERS:
1361
1362 break;
1363 default:
1364
1365
1366
1367
1368
1369
1370 printf("%s: unknown message in: %x\n",
1371 sea->sc_dev.dv_xname, tmp);
1372 break;
1373 }
1374 break;
1375 case PH_MSGOUT:
1376 len = 1;
1377 data = &msgout;
1378
1379 sea_transfer_pio(sea, &phase, &len, &data);
1380 if (msgout == MSG_ABORT) {
1381 printf("%s: sent message abort to target\n",
1382 sea->sc_dev.dv_xname);
1383 s = splbio();
1384 sea->busy[scb->xs->sc_link->target] &=
1385 ~(1 << scb->xs->sc_link->lun);
1386 sea->nexus = NULL;
1387 scb->flags = SCB_ABORTED;
1388 splx(s);
1389
1390 sea_done(sea, scb);
1391 return;
1392 }
1393 msgout = MSG_NOOP;
1394 break;
1395 case PH_CMD:
1396 len = scb->xs->cmdlen;
1397 data = (char *) scb->xs->cmd;
1398 sea_transfer_pio(sea, &phase, &len, &data);
1399 break;
1400 case PH_STAT:
1401 len = 1;
1402 data = &tmp;
1403 sea_transfer_pio(sea, &phase, &len, &data);
1404 scb->xs->status = tmp;
1405 break;
1406 default:
1407 printf("sea: unknown phase\n");
1408 }
1409 }
1410
1411
1412 printf("%s: timeout in data transfer\n", sea->sc_dev.dv_xname);
1413 scb->flags = SCB_TIMEOUT;
1414
1415 sea_done(sea, scb);
1416 }