si.c revision 1.14 1 /* $NetBSD: si.c,v 1.14 1995/01/24 05:55:50 gwr Exp $ */
2
3 /*
4 * Copyright (C) 1994 Adam Glass, Gordon W. Ross
5 * Copyright (C) 1993 Allen K. Briggs, Chris P. Caputo,
6 * Michael L. Finch, Bradley A. Grantham, and
7 * Lawrence A. Kesteloot
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the Alice Group.
21 * 4. The names of the Alice Group or any of its members may not be used
22 * to endorse or promote products derived from this software without
23 * specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 #define DEBUG 1
38
39 /* XXX - Need to add support for real DMA. -gwr */
40 /* #define PSEUDO_DMA 1 (broken) */
41
42 #include <sys/types.h>
43 #include <sys/malloc.h>
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/errno.h>
47 #include <sys/buf.h>
48 #include <sys/proc.h>
49 #include <sys/user.h>
50 #include <sys/device.h>
51
52 #include <machine/autoconf.h>
53 #include <machine/isr.h>
54 #include <machine/obio.h>
55
56 #include <scsi/scsi_all.h>
57 #include <scsi/scsi_debug.h>
58 #include <scsi/scsiconf.h>
59
60 #include "scsi_defs.h"
61 #include "scsi_5380.h"
62 #include "scsi_sunsi.h"
63
64 #ifdef DEBUG
65 static int si_debug = 0;
66 static int si_flags = 0 /* | SDEV_DB2 */ ;
67 #endif
68
69 #define SCI_PHASE_DISC 0 /* sort of ... */
70 #define SCI_CLR_INTR(regs) ((volatile)(regs->sci_iack))
71 #define SCI_ACK(ptr,phase) (ptr)->sci_tcmd = (phase)
72 #define SCSI_TIMEOUT_VAL 10000000
73 #define WAIT_FOR_NOT_REQ(ptr) { \
74 int scsi_timeout = SCSI_TIMEOUT_VAL; \
75 while ( ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
76 ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
77 ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
78 (--scsi_timeout) ); \
79 if (!scsi_timeout) { \
80 printf("scsi timeout--WAIT_FOR_NOT_REQ---%s, line %d.\n", \
81 __FILE__, __LINE__); \
82 goto scsi_timeout_error; \
83 } \
84 }
85 #define WAIT_FOR_REQ(ptr) { \
86 int scsi_timeout = SCSI_TIMEOUT_VAL; \
87 while ( (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
88 (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
89 (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
90 (--scsi_timeout) ); \
91 if (!scsi_timeout) { \
92 printf("scsi timeout--WAIT_FOR_REQ---%s, line %d.\n", \
93 __FILE__, __LINE__); \
94 goto scsi_timeout_error; \
95 } \
96 }
97 #define WAIT_FOR_BSY(ptr) { \
98 int scsi_timeout = SCSI_TIMEOUT_VAL; \
99 while ( (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
100 (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
101 (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
102 (--scsi_timeout) ); \
103 if (!scsi_timeout) { \
104 printf("scsi timeout--WAIT_FOR_BSY---%s, line %d.\n", \
105 __FILE__, __LINE__); \
106 goto scsi_timeout_error; \
107 } \
108 }
109
110 #define ARBITRATION_RETRIES 1000
111
112 #ifdef DDB
113 int Debugger();
114 #else
115 #define Debugger() panic("Should call Debugger here %s:%d", \
116 __FILE__, __LINE__)
117 #endif
118
119 struct ncr5380_softc {
120 struct device sc_dev;
121 volatile void *sc_regs;
122 int sc_adapter_type;
123 struct scsi_link sc_link;
124 };
125
126 static void ncr5380_minphys(struct buf *bp);
127 static int ncr5380_scsi_cmd(struct scsi_xfer *xs);
128 static int ncr5380_reset_adapter(struct ncr5380_softc *);
129 static int ncr5380_reset_scsibus(struct ncr5380_softc *);
130 static int ncr5380_poll(int adapter, int timeout);
131 static int ncr5380_send_cmd(struct scsi_xfer *xs);
132
133 static int ncr_intr(void *);
134
135 static int si_generic(int adapter, int id, int lun,
136 struct scsi_generic *cmd, int cmdlen,
137 void *databuf, int datalen);
138 static int si_group0(int adapter, int id, int lun,
139 int opcode, int addr, int len,
140 int flags, caddr_t databuf, int datalen);
141
142 static char scsi_name[] = "si";
143
144 struct scsi_adapter ncr5380_switch = {
145 ncr5380_scsi_cmd, /* scsi_cmd() */
146 ncr5380_minphys, /* scsi_minphys() */
147 NULL, /* open_target_lu() */
148 NULL, /* close_target_lu() */
149 };
150
151 /* This is copied from julian's bt driver */
152 /* "so we have a default dev struct for our link struct." */
153 struct scsi_device ncr_dev = {
154 NULL, /* Use default error handler. */
155 NULL, /* Use default start handler. */
156 NULL, /* Use default async handler. */
157 NULL, /* Use default "done" routine. */
158 };
159
160 static int si_match();
161 static void si_attach();
162
163 struct cfdriver sicd = {
164 NULL, "si", si_match, si_attach, DV_DULL,
165 sizeof(struct ncr5380_softc), NULL, 0,
166 };
167
168 static int
169 si_print(aux, name)
170 void *aux;
171 char *name;
172 {
173 }
174
175 static int
176 si_match(parent, vcf, args)
177 struct device *parent;
178 void *vcf, *args;
179 {
180 struct cfdata *cf = vcf;
181 struct confargs *ca = args;
182 int x;
183
184 /* Allow default address for OBIO only. */
185 switch (ca->ca_bustype) {
186 case BUS_OBIO:
187 if (ca->ca_paddr == -1)
188 ca->ca_paddr = OBIO_NCR_SCSI;
189 break;
190 case BUS_VME16:
191 if (ca->ca_paddr == -1)
192 return (0);
193 break;
194 default:
195 return (0);
196 }
197
198 /* Default interrupt priority always splbio==2 */
199 if (ca->ca_intpri == -1)
200 ca->ca_intpri = 2;
201
202 x = bus_peek(ca->ca_bustype, ca->ca_paddr + 1, 1);
203 return (x != -1);
204 }
205
206 static void
207 si_attach(parent, self, args)
208 struct device *parent, *self;
209 void *args;
210 {
211 struct ncr5380_softc *ncr5380 = (struct ncr5380_softc *) self;
212 volatile sci_regmap_t *regs;
213 struct confargs *ca = args;
214
215 switch (ca->ca_bustype) {
216
217 case BUS_OBIO:
218 regs = (sci_regmap_t *)
219 obio_alloc(ca->ca_paddr, sizeof(*regs));
220 isr_add_autovect(ncr_intr, (void *)ncr5380,
221 ca->ca_intpri);
222 break;
223
224 case BUS_VME16:
225 regs = (sci_regmap_t *)
226 bus_mapin(ca->ca_bustype, ca->ca_paddr, sizeof(*regs));
227 isr_add_vectored(ncr_intr, (void *)ncr5380,
228 ca->ca_intpri, ca->ca_intvec);
229 break;
230
231 default:
232 printf("unknown\n");
233 return;
234 }
235
236 ncr5380->sc_adapter_type = ca->ca_bustype;
237 ncr5380->sc_regs = regs;
238
239 /*
240 * fill in the prototype scsi_link.
241 */
242 ncr5380->sc_link.adapter_softc = ncr5380;
243 ncr5380->sc_link.adapter_target = 7;
244 ncr5380->sc_link.adapter = &ncr5380_switch;
245 ncr5380->sc_link.device = &ncr_dev;
246 ncr5380->sc_link.openings = 2;
247 #ifdef DEBUG
248 ncr5380->sc_link.flags |= si_flags;
249 #endif
250
251 printf("\n");
252 ncr5380_reset_adapter(ncr5380);
253 ncr5380_reset_scsibus(ncr5380);
254 config_found(self, &(ncr5380->sc_link), si_print);
255 }
256
257 #define MIN_PHYS 65536 /*BARF!!!!*/
258 static void
259 ncr5380_minphys(struct buf *bp)
260 {
261 if (bp->b_bcount > MIN_PHYS) {
262 printf("Uh-oh... ncr5380_minphys setting bp->b_bcount = %x.\n", MIN_PHYS);
263 bp->b_bcount = MIN_PHYS;
264 }
265 }
266 #undef MIN_PHYS
267
268 static int
269 ncr5380_scsi_cmd(struct scsi_xfer *xs)
270 {
271 int flags, s, r;
272
273 flags = xs->flags;
274 if (xs->bp) flags |= (SCSI_NOSLEEP);
275 if ( flags & ITSDONE ) {
276 printf("Already done?");
277 xs->flags &= ~ITSDONE;
278 }
279 if ( ! ( flags & INUSE ) ) {
280 printf("Not in use?");
281 xs->flags |= INUSE;
282 }
283
284 /* At autoconfig time, do NOT lower the spl! */
285 if ((flags & SCSI_POLL) == 0)
286 s = splbio();
287
288 if ( flags & SCSI_RESET ) {
289 printf("flags & SCSIRESET.\n");
290 ncr5380_reset_scsibus(xs->sc_link->adapter_softc);
291 r = COMPLETE;
292 } else {
293 r = ncr5380_send_cmd(xs);
294 xs->flags |= ITSDONE;
295 scsi_done(xs);
296 }
297
298 if ((flags & SCSI_POLL) == 0)
299 splx(s);
300
301 switch(r) {
302 case COMPLETE:
303 case SUCCESSFULLY_QUEUED:
304 r = SUCCESSFULLY_QUEUED;
305 if (xs->flags & SCSI_POLL)
306 r = COMPLETE;
307 break;
308 default:
309 break;
310 }
311 return r;
312 }
313
314 #ifdef DEBUG
315 static int
316 ncr5380_show_scsi_cmd(struct scsi_xfer *xs)
317 {
318 u_char *b = (u_char *) xs->cmd;
319 int i = 0;
320
321 if ( ! ( xs->flags & SCSI_RESET ) ) {
322 printf("si(%d:%d:%d)-",
323 xs->sc_link->scsibus,
324 xs->sc_link->target,
325 xs->sc_link->lun);
326 while (i < xs->cmdlen) {
327 if (i) printf(",");
328 printf("%x",b[i++]);
329 }
330 printf("-\n");
331 } else {
332 printf("si(%d:%d:%d)-RESET-\n",
333 xs->sc_link->scsibus,
334 xs->sc_link->target,
335 xs->sc_link->lun);
336 }
337 }
338 #endif
339
340 /*
341 * Actual chip control.
342 */
343
344 static void
345 ncr_sbc_intr(struct ncr5380_softc *ncr5380)
346 {
347 volatile sci_regmap_t *regs = ncr5380->sc_regs;
348
349 if ((regs->sci_csr & SCI_CSR_INT) == 0) {
350 #ifdef DEBUG
351 printf (" ncr_sbc_intr: spurrious\n");
352 #endif
353 return;
354 }
355
356 SCI_CLR_INTR(regs);
357 #ifdef DEBUG
358 printf (" ncr_sbc_intr\n");
359 #endif
360 }
361
362 static void
363 ncr_dma_intr(struct ncr5380_softc *ncr5380)
364 {
365 volatile struct si_regs *regs = ncr5380->sc_regs;
366
367 #ifdef DEBUG
368 printf (" ncr_dma_intr\n");
369 #endif
370 }
371
372 static int
373 ncr_intr(void *arg)
374 {
375 struct ncr5380_softc *ncr5380 = arg;
376 volatile struct si_regs *si = ncr5380->sc_regs;
377 int rv = 0;
378
379 /* Interrupts not enabled? Can not be for us. */
380 if ((si->si_csr & SI_CSR_INTR_EN) == 0)
381 return rv;
382
383 if (si->si_csr & SI_CSR_DMA_IP) {
384 ncr_dma_intr(ncr5380);
385 rv++;
386 }
387 if (si->si_csr & SI_CSR_SBC_IP) {
388 ncr_sbc_intr(ncr5380);
389 rv++;
390 }
391 return rv;
392 }
393
394 static int
395 ncr5380_reset_adapter(struct ncr5380_softc *ncr5380)
396 {
397 volatile struct si_regs *si = ncr5380->sc_regs;
398
399 #ifdef DEBUG
400 if (si_debug) {
401 printf("si_reset_adapter\n");
402 }
403 #endif
404
405 /* The reset bits are active low. */
406 si->si_csr = 0;
407 delay(100);
408 si->si_csr = SI_CSR_FIFO_RES | SI_CSR_SCSI_RES;
409 }
410
411 static int
412 ncr5380_reset_scsibus(struct ncr5380_softc *ncr5380)
413 {
414 volatile sci_regmap_t *regs = ncr5380->sc_regs;
415
416 #ifdef DEBUG
417 if (si_debug) {
418 printf("si_reset_scsibus\n");
419 }
420 #endif
421
422 regs->sci_icmd = SCI_ICMD_TEST;
423 regs->sci_icmd = SCI_ICMD_TEST | SCI_ICMD_RST;
424 delay(2500);
425 regs->sci_icmd = 0;
426
427 regs->sci_mode = 0;
428 regs->sci_tcmd = SCI_PHASE_DISC;
429 regs->sci_sel_enb = 0;
430
431 SCI_CLR_INTR(regs);
432 SCI_CLR_INTR(regs);
433 }
434
435 static int
436 ncr5380_poll(int adapter, int timeout)
437 {
438 }
439
440 static int
441 ncr5380_send_cmd(struct scsi_xfer *xs)
442 {
443 int sense;
444
445 #ifdef DIAGNOSTIC
446 if ((getsr() & PSL_IPL) < PSL_IPL2)
447 panic("ncr_send_cmd: bad spl");
448 #endif
449
450 #ifdef DEBUG
451 if (si_debug & 2)
452 ncr5380_show_scsi_cmd(xs);
453 #endif
454
455 sense = si_generic( xs->sc_link->scsibus, xs->sc_link->target,
456 xs->sc_link->lun, xs->cmd, xs->cmdlen,
457 xs->data, xs->datalen );
458
459 switch (sense) {
460 case 0: /* success */
461 xs->resid = 0;
462 xs->error = XS_NOERROR;
463 break;
464
465 case 0x02: /* Check condition */
466 #ifdef DEBUG
467 if (si_debug)
468 printf("check cond. target %d.\n",
469 xs->sc_link->target);
470 #endif
471 delay(10); /* Phil's fix for slow devices. */
472 si_group0(xs->sc_link->scsibus,
473 xs->sc_link->target,
474 xs->sc_link->lun,
475 0x3, 0x0,
476 sizeof(struct scsi_sense_data),
477 0, (caddr_t) &(xs->sense),
478 sizeof(struct scsi_sense_data));
479 xs->error = XS_SENSE;
480 break;
481 case 0x08: /* Busy */
482 xs->error = XS_BUSY;
483 break;
484 default:
485 xs->error = XS_DRIVER_STUFFUP;
486 break;
487
488 }
489 return (COMPLETE);
490 }
491
492 static int
493 si_select_target(register volatile sci_regmap_t *regs,
494 u_char myid, u_char tid, int with_atn)
495 {
496 register u_char bid, icmd;
497 int ret = SCSI_RET_RETRY;
498 int arb_retries, arb_wait;
499
500 /* for our purposes.. */
501 myid = 1 << myid;
502 tid = 1 << tid;
503
504 regs->sci_sel_enb = 0; /* we don't want any interrupts. */
505 regs->sci_tcmd = 0; /* get into a harmless state */
506
507 arb_retries = ARBITRATION_RETRIES;
508
509 retry_arbitration:
510 regs->sci_mode = 0; /* get into a harmless state */
511 if (--arb_retries <= 0) {
512 #ifdef DEBUG
513 if (si_debug) {
514 printf("si_select: arb_retries expended\n");
515 }
516 #endif
517 goto lost;
518 }
519
520 if ((regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
521 (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
522 (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)))
523 {
524 #ifdef DEBUG
525 if (si_debug) {
526 printf("si_select_target: still BSY|SEL\n");
527 }
528 #endif
529 return ret;
530 }
531
532 regs->sci_odata = myid;
533 regs->sci_mode = SCI_MODE_ARB;
534 /* regs->sci_mode |= SCI_MODE_ARB; XXX? */
535
536 /* AIP might not set if BSY went true after we checked */
537 /* Wait up to about 100 usec. for it to appear. */
538 arb_wait = 50; /* X2 */
539 do {
540 if (regs->sci_icmd & SCI_ICMD_AIP)
541 break;
542 delay2us();
543 } while (--arb_wait > 0);
544 if (arb_wait <= 0) {
545 /* XXX - Could have missed it? */
546 goto retry_arbitration;
547 }
548 #ifdef DEBUG
549 if (si_debug) {
550 printf("si_select_target: API after %d tries (last wait %d)\n",
551 ARBITRATION_RETRIES - arb_retries,
552 (50 - arb_wait));
553 }
554 #endif
555
556 delay(3); /* 2.2 uSec. arbitration delay */
557
558 if (regs->sci_icmd & SCI_ICMD_LST) {
559 #ifdef DEBUG
560 if (si_debug)
561 printf ("lost 1\n");
562 #endif
563 goto retry_arbitration; /* XXX */
564 }
565
566 regs->sci_mode &= ~SCI_MODE_PAR_CHK;
567 bid = regs->sci_data;
568
569 if ((bid & ~myid) > myid) {
570 #ifdef DEBUG
571 if (si_debug)
572 printf ("lost 2\n");
573 #endif
574 /* Trying again will not help. */
575 goto lost;
576 }
577 if (regs->sci_icmd & SCI_ICMD_LST) {
578 #ifdef DEBUG
579 if (si_debug)
580 printf ("lost 3\n");
581 #endif
582 goto lost;
583 }
584
585 /* Won arbitration, enter selection phase now */
586 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
587 icmd |= (with_atn ? (SCI_ICMD_SEL|SCI_ICMD_ATN) : SCI_ICMD_SEL);
588 regs->sci_icmd = icmd;
589
590 if (regs->sci_icmd & SCI_ICMD_LST) {
591 #ifdef DEBUG
592 if (si_debug)
593 printf ("nosel\n");
594 #endif
595 goto nosel;
596 }
597
598 /* XXX a target that violates specs might still drive the bus XXX */
599 /* XXX should put our id out, and after the delay check nothi XXX */
600 /* XXX ng else is out there. XXX */
601
602 delay2us();
603
604 regs->sci_sel_enb = 0;
605
606 regs->sci_odata = myid | tid;
607
608 icmd |= SCI_ICMD_BSY|SCI_ICMD_DATA;
609 regs->sci_icmd = icmd;
610
611 /* regs->sci_mode &= ~SCI_MODE_ARB; 2 deskew delays, too */
612 regs->sci_mode = 0; /* 2 deskew delays, too */
613
614 icmd &= ~SCI_ICMD_BSY;
615 regs->sci_icmd = icmd;
616
617 /* bus settle delay, 400ns */
618 delay2us(); /* too much (was 2) ? */
619
620 regs->sci_mode |= SCI_MODE_PAR_CHK;
621
622 {
623 register int timeo = 2500;/* 250 msecs in 100 usecs chunks */
624 while ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) {
625 if (--timeo > 0) {
626 delay(100);
627 } else {
628 /* This is the "normal" no-such-device select error. */
629 #ifdef DEBUG
630 if (si_debug)
631 printf("si_select: did not see BSY\n");
632 #endif
633 goto nodev;
634 }
635 }
636 }
637
638 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL);
639 regs->sci_icmd = icmd;
640 /* regs->sci_sel_enb = myid;*/ /* looks like we should NOT have it */
641 /* XXX - SCI_MODE_PAR_CHK ? */
642 return SCSI_RET_SUCCESS;
643
644 nodev:
645 ret = SCSI_RET_DEVICE_DOWN;
646 regs->sci_sel_enb = myid;
647 nosel:
648 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL|SCI_ICMD_ATN);
649 regs->sci_icmd = icmd;
650 regs->sci_mode = 0;
651 return ret;
652
653 lost:
654 regs->sci_icmd = 0;
655 regs->sci_mode = 0;
656 #ifdef DEBUG
657 if (si_debug) {
658 printf("si_select: lost arbitration\n");
659 }
660 #endif
661 return ret;
662 }
663
664 sci_data_out(regs, phase, count, data)
665 register volatile sci_regmap_t *regs;
666 unsigned char *data;
667 {
668 register unsigned char icmd;
669 register int cnt=0;
670
671 /* ..checks.. */
672
673 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
674 loop:
675 if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase)
676 return cnt;
677
678 WAIT_FOR_REQ(regs);
679 icmd |= SCI_ICMD_DATA;
680 regs->sci_icmd = icmd;
681 regs->sci_odata = *data++;
682 icmd |= SCI_ICMD_ACK;
683 regs->sci_icmd = icmd;
684
685 icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_ACK);
686 WAIT_FOR_NOT_REQ(regs);
687 regs->sci_icmd = icmd;
688 ++cnt;
689 if (--count > 0)
690 goto loop;
691 scsi_timeout_error:
692 return cnt;
693 }
694
695 sci_data_in(regs, phase, count, data)
696 register volatile sci_regmap_t *regs;
697 unsigned char *data;
698 {
699 register unsigned char icmd;
700 register int cnt=0;
701
702 /* ..checks.. */
703
704 icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
705
706 loop:
707 if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase)
708 return cnt;
709
710 WAIT_FOR_REQ(regs);
711 *data++ = regs->sci_data;
712 icmd |= SCI_ICMD_ACK;
713 regs->sci_icmd = icmd;
714
715 icmd &= ~SCI_ICMD_ACK;
716 WAIT_FOR_NOT_REQ(regs);
717 regs->sci_icmd = icmd;
718 ++cnt;
719 if (--count > 0)
720 goto loop;
721
722 scsi_timeout_error:
723 return cnt;
724 }
725
726 static int
727 si_command_transfer(register volatile sci_regmap_t *regs,
728 int maxlen, u_char *data, u_char *status, u_char *msg)
729 {
730 int xfer=0, phase;
731
732 /* printf("command_transfer called for 0x%x.\n", *data); */
733
734 regs->sci_icmd = 0;
735
736 while (1) {
737
738 WAIT_FOR_REQ(regs);
739
740 phase = SCI_CUR_PHASE(regs->sci_bus_csr);
741
742 switch (phase) {
743 case SCSI_PHASE_CMD:
744 SCI_ACK(regs,SCSI_PHASE_CMD);
745 xfer += sci_data_out(regs, SCSI_PHASE_CMD,
746 maxlen, data);
747 return xfer;
748 case SCSI_PHASE_DATA_IN:
749 printf("Data in phase in command_transfer?\n");
750 return 0;
751 case SCSI_PHASE_DATA_OUT:
752 printf("Data out phase in command_transfer?\n");
753 return 0;
754 case SCSI_PHASE_STATUS:
755 SCI_ACK(regs,SCSI_PHASE_STATUS);
756 printf("status in command_transfer.\n");
757 sci_data_in(regs, SCSI_PHASE_STATUS,
758 1, status);
759 break;
760 case SCSI_PHASE_MESSAGE_IN:
761 SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN);
762 printf("msgin in command_transfer.\n");
763 sci_data_in(regs, SCSI_PHASE_MESSAGE_IN,
764 1, msg);
765 break;
766 case SCSI_PHASE_MESSAGE_OUT:
767 SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT);
768 sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT,
769 1, msg);
770 break;
771 default:
772 printf("Unexpected phase 0x%x in "
773 "command_transfer().\n", phase);
774 scsi_timeout_error:
775 return xfer;
776 break;
777 }
778 }
779 }
780
781 static int
782 si_data_transfer(register volatile sci_regmap_t *regs,
783 int maxlen, u_char *data, u_char *status, u_char *msg)
784 {
785 int retlen = 0, xfer, phase;
786
787 regs->sci_icmd = 0;
788
789 *status = 0;
790
791 while (1) {
792
793 WAIT_FOR_REQ(regs);
794
795 phase = SCI_CUR_PHASE(regs->sci_bus_csr);
796
797 switch (phase) {
798 case SCSI_PHASE_CMD:
799 printf("Command phase in data_transfer().\n");
800 return retlen;
801 case SCSI_PHASE_DATA_IN:
802 SCI_ACK(regs,SCSI_PHASE_DATA_IN);
803 #if PSEUDO_DMA
804 xfer = sci_pdma_in(regs, SCSI_PHASE_DATA_IN,
805 maxlen, data);
806 #else
807 xfer = sci_data_in(regs, SCSI_PHASE_DATA_IN,
808 maxlen, data);
809 #endif
810 retlen += xfer;
811 maxlen -= xfer;
812 break;
813 case SCSI_PHASE_DATA_OUT:
814 SCI_ACK(regs,SCSI_PHASE_DATA_OUT);
815 #if PSEUDO_DMA
816 xfer = sci_pdma_out(regs, SCSI_PHASE_DATA_OUT,
817 maxlen, data);
818 #else
819 xfer = sci_data_out(regs, SCSI_PHASE_DATA_OUT,
820 maxlen, data);
821 #endif
822 retlen += xfer;
823 maxlen -= xfer;
824 break;
825 case SCSI_PHASE_STATUS:
826 SCI_ACK(regs,SCSI_PHASE_STATUS);
827 sci_data_in(regs, SCSI_PHASE_STATUS,
828 1, status);
829 break;
830 case SCSI_PHASE_MESSAGE_IN:
831 SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN);
832 sci_data_in(regs, SCSI_PHASE_MESSAGE_IN,
833 1, msg);
834 if (*msg == 0) {
835 return retlen;
836 } else {
837 printf( "message 0x%x in "
838 "data_transfer.\n", *msg);
839 }
840 break;
841 case SCSI_PHASE_MESSAGE_OUT:
842 SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT);
843 sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT,
844 1, msg);
845 break;
846 default:
847 printf( "Unexpected phase 0x%x in "
848 "data_transfer().\n", phase);
849 scsi_timeout_error:
850 return retlen;
851 break;
852 }
853 }
854 }
855
856 static int
857 si_dorequest(register volatile sci_regmap_t *regs,
858 int target, int lun, u_char *cmd, int cmdlen,
859 char *databuf, int datalen, int *sent, int *ret)
860 {
861 /* Returns 0 on success, -1 on internal error, or the status byte */
862 int cmd_bytes_sent, r;
863 u_char stat, msg, c;
864
865 *sent = 0;
866
867 if ( ( r = si_select_target(regs, 7, target, 1) ) != SCSI_RET_SUCCESS) {
868 #ifdef DEBUG
869 if (si_debug) {
870 printf("si_dorequest: select returned %d\n", r);
871 }
872 #endif
873 *ret = r;
874 SCI_CLR_INTR(regs);
875 switch (r) {
876 case SCSI_RET_RETRY:
877 return 0x08;
878 default:
879 printf("si_select_target(target %d, lun %d) failed(%d).\n",
880 target, lun, r);
881 case SCSI_RET_DEVICE_DOWN:
882 return -1;
883 }
884 }
885
886 c = 0x80 | lun;
887
888 if ((cmd_bytes_sent = si_command_transfer(regs, cmdlen,
889 (u_char *) cmd, &stat, &c)) != cmdlen)
890 {
891 SCI_CLR_INTR(regs);
892 *ret = SCSI_RET_COMMAND_FAIL;
893 printf("Data underrun sending CCB (%d bytes of %d, sent).\n",
894 cmd_bytes_sent, cmdlen);
895 return -1;
896 }
897
898 *sent=si_data_transfer(regs, datalen, (u_char *)databuf,
899 &stat, &msg);
900 #ifdef DEBUG
901 if (si_debug) {
902 printf("si_dorequest: data transfered = %d\n", *sent);
903 }
904 #endif
905
906 *ret = 0;
907 return stat;
908 }
909
910 static int
911 si_generic(int adapter, int id, int lun, struct scsi_generic *cmd,
912 int cmdlen, void *databuf, int datalen)
913 {
914 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter];
915 register volatile sci_regmap_t *regs = ncr5380->sc_regs;
916 int i,j,sent,ret;
917
918 if (cmd->opcode == TEST_UNIT_READY) /* XXX */
919 cmd->bytes[0] = ((u_char) lun << 5);
920
921 i = si_dorequest(regs, id, lun, (u_char *) cmd, cmdlen,
922 databuf, datalen, &sent, &ret);
923
924 return i;
925 }
926
927 static int
928 si_group0(int adapter, int id, int lun, int opcode, int addr, int len,
929 int flags, caddr_t databuf, int datalen)
930 {
931 register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter];
932 register volatile sci_regmap_t *regs = ncr5380->sc_regs;
933 unsigned char cmd[6];
934 int i,j,sent,ret;
935
936 cmd[0] = opcode; /* Operation code */
937 cmd[1] = (lun << 5) | ((addr >> 16) & 0x1F); /* Lun & MSB of addr */
938 cmd[2] = (addr >> 8) & 0xFF; /* addr */
939 cmd[3] = addr & 0xFF; /* LSB of addr */
940 cmd[4] = len; /* Allocation length */
941 cmd[5] = flags; /* Link/Flag */
942
943 i = si_dorequest(regs, id, lun, cmd, 6, databuf, datalen, &sent, &ret);
944
945 return i;
946 }
947