1 /* $NetBSD: siop2.c,v 1.35 2009/03/18 17:06:42 cegger Exp $ */
4 * Copyright (c) 1990 The Regents of the University of California.
7 * This code is derived from software contributed to Berkeley by
8 * Van Jacobson of Lawrence Berkeley Laboratory.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * @(#)siop.c 7.5 (Berkeley) 5/4/91
38 * Copyright (c) 1994,1998 Michael L. Hitch
40 * This code is derived from software contributed to Berkeley by
41 * Van Jacobson of Lawrence Berkeley Laboratory.
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
53 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
54 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
55 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
56 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
57 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
61 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63 * @(#)siop.c 7.5 (Berkeley) 5/4/91
67 * AMIGA 53C720/770 scsi adaptor driver
72 #include <sys/cdefs.h>
73 __KERNEL_RCSID(0, "$NetBSD: siop2.c,v 1.35 2009/03/18 17:06:42 cegger Exp $");
75 #include <sys/param.h>
76 #include <sys/systm.h>
77 #include <sys/callout.h>
78 #include <sys/kernel.h>
79 #include <sys/device.h>
80 #include <sys/disklabel.h>
82 #include <sys/malloc.h>
84 #include <uvm/uvm_extern.h>
86 #include <dev/scsipi/scsi_all.h>
87 #include <dev/scsipi/scsipi_all.h>
88 #include <dev/scsipi/scsiconf.h>
89 #include <machine/cpu.h>
91 #include <m68k/include/cacheops.h>
93 #include <amiga/amiga/custom.h>
94 #include <amiga/amiga/isr.h>
98 #include <amiga/dev/siopreg.h>
99 #include <amiga/dev/siopvar.h>
103 * In u-seconds, primarily for state changes on the SPC.
105 #define SCSI_CMD_WAIT 500000 /* wait per step of 'immediate' cmds */
106 #define SCSI_DATA_WAIT 500000 /* wait per data in/out step */
107 #define SCSI_INIT_WAIT 500000 /* wait per step (both) during init */
109 void siopng_select(struct siop_softc
*);
110 void siopngabort(struct siop_softc
*, siop_regmap_p
, const char *);
111 void siopngerror(struct siop_softc
*, siop_regmap_p
, u_char
);
112 int siopng_checkintr(struct siop_softc
*, u_char
, u_char
, u_short
, int *);
113 void siopngreset(struct siop_softc
*);
114 void siopngsetdelay(int);
115 void siopng_scsidone(struct siop_acb
*, int);
116 void siopng_timeout(void *);
117 void siopng_sched(struct siop_softc
*);
118 void siopng_poll(struct siop_softc
*, struct siop_acb
*);
119 void siopngintr(struct siop_softc
*);
120 void scsi_period_to_siopng(struct siop_softc
*, int);
121 void siopng_start(struct siop_softc
*, int, int, u_char
*, int, u_char
*, int);
122 void siopng_dump_acb(struct siop_acb
*);
124 /* 53C720/770 script */
126 #include <amiga/dev/siop2_script.out>
128 /* default to not inhibit sync negotiation on any drive */
129 u_char siopng_inhibit_sync
[16] = {
130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
131 }; /* initialize, so patchable */
133 u_char siopng_inhibit_wide
[16] = {
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
135 }; /* initialize, so patchable */
137 u_char siopng_allow_disc
[16] = {
138 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
141 int siopng_no_dma
= 0;
143 int siopng_reset_delay
= 250; /* delay after reset, in milleseconds */
145 int siopng_cmd_wait
= SCSI_CMD_WAIT
;
146 int siopng_data_wait
= SCSI_DATA_WAIT
;
147 int siopng_init_wait
= SCSI_INIT_WAIT
;
154 * 0x02 - DMA chaining
156 * 0x08 - phase mismatch
158 * 0x20 - panic on unhandled exceptions
159 * 0x100 - disconnect/reselect
161 int siopng_debug
= 0;
162 int siopngsync_debug
= 0;
163 int siopngdma_hits
= 0;
164 int siopngdma_misses
= 0;
165 int siopngchain_ints
= 0;
166 int siopngstarts
= 0;
169 #define SIOP_TRACE_SIZE 128
170 #define SIOP_TRACE(a,b,c,d) \
171 siopng_trbuf[siopng_trix] = (a); \
172 siopng_trbuf[siopng_trix+1] = (b); \
173 siopng_trbuf[siopng_trix+2] = (c); \
174 siopng_trbuf[siopng_trix+3] = (d); \
175 siopng_trix = (siopng_trix + 4) & (SIOP_TRACE_SIZE - 1);
176 u_char siopng_trbuf
[SIOP_TRACE_SIZE
];
178 void siopng_dump(struct siop_softc
*);
179 void siopng_dump_trace(void);
181 #define SIOP_TRACE(a,b,c,d)
185 static const char *siopng_chips
[] = {
186 "720", "720SE", "770", "0x3",
187 "810A", "0x5", "0x6", "0x7",
188 "0x8", "0x9", "0xA", "0xB",
189 "0xC", "0xD", "0xE", "0xF",
193 * default minphys routine for siopng based controllers
196 siopng_minphys(struct buf
*bp
)
200 * No max transfer at this level.
206 * used by specific siopng controller
210 siopng_scsipi_request(struct scsipi_channel
*chan
, scsipi_adapter_req_t req
,
213 struct scsipi_xfer
*xs
;
214 struct scsipi_periph
*periph
;
215 struct siop_acb
*acb
;
216 struct siop_softc
*sc
= (void *)chan
->chan_adapter
->adapt_dev
;
220 case ADAPTER_REQ_RUN_XFER
:
222 periph
= xs
->xs_periph
;
223 flags
= xs
->xs_control
;
226 if (flags
& XS_CTL_DATA_UIO
)
227 panic("siopng: scsi data uio requested");
230 if (sc
->sc_nexus
&& flags
& XS_CTL_POLL
)
231 /* panic("siopng_scsicmd: busy");*/
232 printf("siopng_scsicmd: busy\n");
235 acb
= sc
->free_list
.tqh_first
;
237 TAILQ_REMOVE(&sc
->free_list
, acb
, chain
);
243 * This should never happen as we track the resources
247 scsipi_printaddr(periph
);
248 printf("unable to allocate acb\n");
249 panic("siopng_scsipi_request");
252 acb
->flags
= ACB_ACTIVE
;
254 memcpy(&acb
->cmd
, xs
->cmd
, xs
->cmdlen
);
255 acb
->clen
= xs
->cmdlen
;
256 acb
->daddr
= xs
->data
;
257 acb
->dleft
= xs
->datalen
;
260 TAILQ_INSERT_TAIL(&sc
->ready_list
, acb
, chain
);
262 if (sc
->sc_nexus
== NULL
)
267 if (flags
& XS_CTL_POLL
|| siopng_no_dma
)
268 siopng_poll(sc
, acb
);
271 case ADAPTER_REQ_GROW_RESOURCES
:
274 case ADAPTER_REQ_SET_XFER_MODE
:
280 siopng_poll(struct siop_softc
*sc
, struct siop_acb
*acb
)
282 siop_regmap_p rp
= sc
->sc_siopp
;
283 struct scsipi_xfer
*xs
= acb
->xs
;
293 to
= xs
->timeout
/ 1000;
294 if (sc
->nexus_list
.tqh_first
)
295 printf("%s: siopng_poll called with disconnected device\n",
296 sc
->sc_dev
.dv_xname
);
298 /* use cmd_wait values? */
301 while (((istat
= rp
->siop_istat
) &
302 (SIOP_ISTAT_SIP
| SIOP_ISTAT_DIP
)) == 0) {
305 printf ("waiting: tgt %d cmd %02x sbcl %02x istat %02x sbdl %04x\n dsp %lx (+%lx) dcmd %lx ds %p timeout %d\n",
306 xs
->xs_periph
->periph_target
, acb
->cmd
.opcode
,
307 rp
->siop_sbcl
, istat
, rp
->siop_sbdl
, rp
->siop_dsp
,
308 rp
->siop_dsp
- sc
->sc_scriptspa
,
309 *((volatile long *)&rp
->siop_dcmd
), &acb
->ds
, acb
->xs
->timeout
);
320 sist
= rp
->siop_sist
;
321 dstat
= rp
->siop_dstat
;
322 if (siopng_checkintr(sc
, istat
, dstat
, sist
, &status
)) {
323 if (acb
!= sc
->sc_nexus
)
324 printf("%s: siopng_poll disconnected device completed\n",
325 sc
->sc_dev
.dv_xname
);
326 else if ((sc
->sc_flags
& SIOP_INTDEFER
) == 0) {
327 sc
->sc_flags
&= ~SIOP_INTSOFF
;
328 rp
->siop_sien
= sc
->sc_sien
;
329 rp
->siop_dien
= sc
->sc_dien
;
331 siopng_scsidone(sc
->sc_nexus
, status
);
333 if (xs
->xs_status
& XS_STS_DONE
)
340 * start next command that's ready
343 siopng_sched(struct siop_softc
*sc
)
345 struct scsipi_periph
*periph
;
346 struct siop_acb
*acb
;
351 printf("%s: siopng_sched- nexus %p/%d ready %p/%d\n",
352 sc
->sc_dev
.dv_xname
, sc
->sc_nexus
,
353 sc
->sc_nexus
->xs
->xs_periph
->periph_target
,
354 sc
->ready_list
.tqh_first
,
355 sc
->ready_list
.tqh_first
->xs
->xs_periph
->periph_target
);
359 for (acb
= sc
->ready_list
.tqh_first
; acb
; acb
= acb
->chain
.tqe_next
) {
360 periph
= acb
->xs
->xs_periph
;
361 i
= periph
->periph_target
;
362 if(!(sc
->sc_tinfo
[i
].lubusy
& (1 << periph
->periph_lun
))) {
363 struct siop_tinfo
*ti
= &sc
->sc_tinfo
[i
];
365 TAILQ_REMOVE(&sc
->ready_list
, acb
, chain
);
367 periph
= acb
->xs
->xs_periph
;
368 ti
= &sc
->sc_tinfo
[periph
->periph_target
];
369 ti
->lubusy
|= (1 << periph
->periph_lun
);
376 printf("%s: siopng_sched didn't find ready command\n",
377 sc
->sc_dev
.dv_xname
);
382 if (acb
->xs
->xs_control
& XS_CTL_RESET
)
386 acb
->cmd
.bytes
[0] |= periph
->periph_lun
<< 5; /* XXXX */
393 siopng_scsidone(struct siop_acb
*acb
, int stat
)
395 struct scsipi_xfer
*xs
;
396 struct scsipi_periph
*periph
;
397 struct siop_softc
*sc
;
400 if (acb
== NULL
|| (xs
= acb
->xs
) == NULL
) {
402 printf("siopng_scsidone: NULL acb or scsipi_xfer\n");
403 #if defined(DEBUG) && defined(DDB)
410 callout_stop(&xs
->xs_callout
);
412 periph
= xs
->xs_periph
;
413 sc
= (void *)periph
->periph_channel
->chan_adapter
->adapt_dev
;
416 xs
->resid
= 0; /* XXXX */
418 if (xs
->error
== XS_NOERROR
) {
419 if (stat
== SCSI_CHECK
|| stat
== SCSI_BUSY
)
424 * Remove the ACB from whatever queue it's on. We have to do a bit of
425 * a hack to figure out which queue it's on. Note that it is *not*
426 * necessary to cdr down the ready queue, but we must cdr down the
427 * nexus queue and see if it's there, so we can mark the unit as no
428 * longer busy. This code is sickening, but it works.
430 if (acb
== sc
->sc_nexus
) {
432 sc
->sc_tinfo
[periph
->periph_target
].lubusy
&=
433 ~(1<<periph
->periph_lun
);
434 if (sc
->ready_list
.tqh_first
)
435 dosched
= 1; /* start next command */
437 SIOP_TRACE('d','a',stat
,0)
438 } else if (sc
->ready_list
.tqh_last
== &acb
->chain
.tqe_next
) {
439 TAILQ_REMOVE(&sc
->ready_list
, acb
, chain
);
440 SIOP_TRACE('d','r',stat
,0)
442 register struct siop_acb
*acb2
;
443 for (acb2
= sc
->nexus_list
.tqh_first
; acb2
;
444 acb2
= acb2
->chain
.tqe_next
)
446 TAILQ_REMOVE(&sc
->nexus_list
, acb
, chain
);
447 sc
->sc_tinfo
[periph
->periph_target
].lubusy
448 &= ~(1<<periph
->periph_lun
);
454 else if (acb
->chain
.tqe_next
) {
455 TAILQ_REMOVE(&sc
->ready_list
, acb
, chain
);
458 printf("%s: can't find matching acb\n",
459 sc
->sc_dev
.dv_xname
);
464 SIOP_TRACE('d','n',stat
,0);
466 /* Put it on the free list. */
467 acb
->flags
= ACB_FREE
;
468 TAILQ_INSERT_HEAD(&sc
->free_list
, acb
, chain
);
470 sc
->sc_tinfo
[periph
->periph_target
].cmds
++;
474 if (dosched
&& sc
->sc_nexus
== NULL
)
479 siopngabort(register struct siop_softc
*sc
, siop_regmap_p rp
, const char *where
)
485 printf ("%s: abort %s: dstat %02x, istat %02x sist %04x sien %04x sbcl %02x\n",
487 where
, rp
->siop_dstat
, rp
->siop_istat
, rp
->siop_sist
,
488 rp
->siop_sien
, rp
->siop_sbcl
);
489 siopng_dump_registers(sc
);
491 if (sc
->sc_active
> 0) {
493 SET_SBIC_cmd (rp
, SBIC_CMD_ABORT
);
496 GET_SBIC_asr (rp
, asr
);
497 if (asr
& (SBIC_ASR_BSY
|SBIC_ASR_LCI
))
499 /* ok, get more drastic.. */
501 SET_SBIC_cmd (rp
, SBIC_CMD_RESET
);
503 SBIC_WAIT(rp
, SBIC_ASR_INT
, 0);
504 GET_SBIC_csr (rp
, csr
); /* clears interrupt also */
511 SBIC_WAIT (rp
, SBIC_ASR_INT
, 0);
512 GET_SBIC_csr (rp
, csr
);
514 while ((csr
!= SBIC_CSR_DISC
) && (csr
!= SBIC_CSR_DISC_1
)
515 && (csr
!= SBIC_CSR_CMD_INVALID
));
518 /* lets just hope it worked.. */
520 for (i
= 0; i
< 2; ++i
) {
521 if (sc
->sc_iob
[i
].sc_xs
&& &sc
->sc_iob
[i
] !=
523 printf ("siopngabort: cleanup!\n");
524 sc
->sc_iob
[i
].sc_xs
= NULL
;
527 #endif /* fix_this */
528 /* sc->sc_active = 0; */
533 siopnginitialize(struct siop_softc
*sc
)
537 extern u_long scsi_nosync
;
538 extern int shift_nosync
;
541 * Need to check that scripts is on a long word boundary
542 * Also should verify that dev doesn't span non-contiguous
545 sc
->sc_scriptspa
= kvtop((void *)__UNCONST(siopng_scripts
));
548 * malloc sc_acb to ensure that DS is on a long word boundary.
551 sc
->sc_acb
= malloc(sizeof(struct siop_acb
) * SIOP_NACB
,
553 if (sc
->sc_acb
== NULL
)
554 panic("siopnginitialize: ACB malloc failed!");
556 sc
->sc_tcp
[1] = 1000 / sc
->sc_clock_freq
;
557 sc
->sc_tcp
[2] = 1500 / sc
->sc_clock_freq
;
558 sc
->sc_tcp
[3] = 2000 / sc
->sc_clock_freq
;
559 sc
->sc_minsync
= sc
->sc_tcp
[1]; /* in 4ns units */
560 if (sc
->sc_minsync
< 25)
562 sc
->sc_minsync
>>= 1; /* Using clock doubler, allow Ultra */
563 if (sc
->sc_clock_freq
<= 25) {
564 sc
->sc_dcntl
|= 0x80; /* SCLK/1 */
565 sc
->sc_tcp
[0] = sc
->sc_tcp
[1];
566 } else if (sc
->sc_clock_freq
<= 37) {
567 sc
->sc_dcntl
|= 0x40; /* SCLK/1.5 */
568 sc
->sc_tcp
[0] = sc
->sc_tcp
[2];
569 } else if (sc
->sc_clock_freq
<= 50) {
570 sc
->sc_dcntl
|= 0x00; /* SCLK/2 */
571 sc
->sc_tcp
[0] = sc
->sc_tcp
[3];
573 sc
->sc_dcntl
|= 0xc0; /* SCLK/3 */
574 sc
->sc_tcp
[0] = 3000 / sc
->sc_clock_freq
;
578 inhibit_sync
= (scsi_nosync
>> shift_nosync
) & 0xffff;
579 shift_nosync
+= 16; /* XXX maxtarget */
582 printf("%s: Inhibiting synchronous transfer %02x\n",
583 sc
->sc_dev
.dv_xname
, inhibit_sync
);
585 for (i
= 0; i
< 16; ++i
) /* XXX maxtarget */
586 if (inhibit_sync
& (1 << i
))
587 siopng_inhibit_sync
[i
] = 1;
594 siopng_timeout(void *arg
)
596 struct siop_acb
*acb
;
597 struct scsipi_periph
*periph
;
598 struct siop_softc
*sc
;
602 periph
= acb
->xs
->xs_periph
;
603 sc
= device_private(periph
->periph_channel
->chan_adapter
->adapt_dev
);
604 scsipi_printaddr(periph
);
605 printf("timed out\n");
609 acb
->xs
->error
= XS_TIMEOUT
;
616 siopngreset(struct siop_softc
*sc
)
621 struct siop_acb
*acb
;
625 if (sc
->sc_flags
& SIOP_ALIVE
)
626 siopngabort(sc
, rp
, "reset");
628 printf("%s: ", sc
->sc_dev
.dv_xname
); /* XXXX */
634 * XXX - is this really needed?
636 rp
->siop_istat
|= SIOP_ISTAT_ABRT
; /* abort current script */
637 rp
->siop_istat
|= SIOP_ISTAT_RST
; /* reset chip */
638 rp
->siop_istat
&= ~SIOP_ISTAT_RST
;
640 * Reset SCSI bus (do we really want this?)
643 rp
->siop_scntl1
|= SIOP_SCNTL1_RST
;
645 rp
->siop_scntl1
&= ~SIOP_SCNTL1_RST
;
648 * Set up various chip parameters
650 rp
->siop_stest1
|= SIOP_STEST1_DBLEN
; /* SCLK doubler enable */
652 rp
->siop_stest3
|= SIOP_STEST3_HSC
; /* Halt SCSI clock */
653 rp
->siop_scntl3
= 0x15; /* SCF/CCF*/
654 rp
->siop_stest1
|= SIOP_STEST1_DBLSEL
; /* SCLK doubler select */
655 rp
->siop_stest3
&= ~SIOP_STEST3_HSC
; /* Clear Halt SCSI clock */
656 rp
->siop_scntl0
= SIOP_ARB_FULL
| /*SIOP_SCNTL0_EPC |*/ SIOP_SCNTL0_EPG
;
657 rp
->siop_dcntl
= sc
->sc_dcntl
;
658 rp
->siop_dmode
= 0xc0; /* XXX burst length */
659 rp
->siop_sien
= 0x00; /* don't enable interrupts yet */
660 rp
->siop_dien
= 0x00; /* don't enable interrupts yet */
661 rp
->siop_scid
= sc
->sc_channel
.chan_id
|
662 SIOP_SCID_RRE
| SIOP_SCID_SRE
;
663 rp
->siop_respid
= 1 << sc
->sc_channel
.chan_id
;
665 rp
->siop_stime0
= 0x0c; /* XXXXX check */
667 /* will need to re-negotiate sync xfers */
668 memset(&sc
->sc_sync
, 0, sizeof (sc
->sc_sync
));
671 if (i
& SIOP_ISTAT_SIP
)
672 dummy
= rp
->siop_sist
;
673 if (i
& SIOP_ISTAT_DIP
)
674 dummy
= rp
->siop_dstat
;
678 delay (siopng_reset_delay
* 1000);
681 * is lower half unterminated?
683 if ((rp
->siop_sbdl
& 0x00ff) == 0x00ff) {
684 printf(" no SCSI termination, host adapter deactivated.\n");
685 sc
->sc_channel
.chan_ntargets
= 0; /* XXX */
686 sc
->sc_flags
&= ~(SIOP_ALIVE
|SIOP_INTDEFER
|SIOP_INTSOFF
);
687 /* disable SCSI and DMA interrupts */
690 rp
->siop_sien
= sc
->sc_sien
;
691 rp
->siop_dien
= sc
->sc_dien
;
697 * Check if upper half of SCSI bus is unterminated, and disallow
698 * disconnections if it appears to be unterminated.
700 if ((rp
->siop_sbdl
& 0xff00) == 0xff00) {
701 printf(" NO WIDE TERM");
702 /* XXX need to restrict maximum target ID as well? */
703 sc
->sc_channel
.chan_ntargets
= 8;
704 for (i
= 0; i
< 16; ++i
) {
705 siopng_allow_disc
[i
] = 0;
706 siopng_inhibit_wide
[i
] |= 0x80;
710 printf("siopng type %s id %d reset V%d\n",
711 siopng_chips
[rp
->siop_macntl
>>4],
712 sc
->sc_channel
.chan_ntargets
,
713 rp
->siop_ctest3
>> 4);
715 if ((sc
->sc_flags
& SIOP_ALIVE
) == 0) {
716 TAILQ_INIT(&sc
->ready_list
);
717 TAILQ_INIT(&sc
->nexus_list
);
718 TAILQ_INIT(&sc
->free_list
);
721 memset(acb
, 0, sizeof(struct siop_acb
) * SIOP_NACB
);
722 for (i
= 0; i
< SIOP_NACB
; i
++) {
723 TAILQ_INSERT_TAIL(&sc
->free_list
, acb
, chain
);
726 memset(sc
->sc_tinfo
, 0, sizeof(sc
->sc_tinfo
));
728 if (sc
->sc_nexus
!= NULL
) {
729 sc
->sc_nexus
->xs
->error
= XS_RESET
;
730 siopng_scsidone(sc
->sc_nexus
, sc
->sc_nexus
->stat
[0]);
732 while ((acb
= sc
->nexus_list
.tqh_first
) > 0) {
733 acb
->xs
->error
= XS_RESET
;
734 siopng_scsidone(acb
, acb
->stat
[0]);
738 sc
->sc_flags
|= SIOP_ALIVE
;
739 sc
->sc_flags
&= ~(SIOP_INTDEFER
|SIOP_INTSOFF
);
740 /* enable SCSI and DMA interrupts */
741 sc
->sc_sien
= SIOP_SIEN_MA
| SIOP_SIEN_STO
| /*SIOP_SIEN_GEN |*/
742 /*SIOP_SIEN_SEL |*/ SIOP_SIEN_SGE
| SIOP_SIEN_UDC
|
743 SIOP_SIEN_RST
| SIOP_SIEN_PAR
;
744 sc
->sc_dien
= SIOP_DIEN_BF
| SIOP_DIEN_ABRT
| SIOP_DIEN_SIR
|
745 /*SIOP_DIEN_WTD |*/ SIOP_DIEN_IID
;
746 rp
->siop_sien
= sc
->sc_sien
;
747 rp
->siop_dien
= sc
->sc_dien
;
748 /*siopng_dump_registers(sc);*/
752 * Setup Data Storage for 53C720/770 and start SCRIPTS processing
756 siopng_start(struct siop_softc
*sc
, int target
, int lun
, u_char
*cbuf
,
757 int clen
, u_char
*buf
, int len
)
759 siop_regmap_p rp
= sc
->sc_siopp
;
763 struct siop_acb
*acb
= sc
->sc_nexus
;
769 if (siopng_debug
& 0x100 && rp
->siop_sbcl
& SIOP_BSY
) {
770 printf ("ACK! siopng was busy: rp %p script %p dsa %p active %ld\n",
771 rp
, &siopng_scripts
, &acb
->ds
, sc
->sc_active
);
772 printf ("istat %02x sfbr %02x respid %02x sien %04x dien %02x\n",
773 rp
->siop_istat
, rp
->siop_sfbr
, rp
->siop_respid
,
774 rp
->siop_sien
, rp
->siop_dien
);
780 acb
->msgout
[0] = MSG_IDENTIFY
| lun
;
781 if (siopng_allow_disc
[target
] & 2 ||
782 (siopng_allow_disc
[target
] && len
== 0))
783 acb
->msgout
[0] = MSG_IDENTIFY_DR
| lun
;
787 acb
->ds
.scsi_addr
= (target
<< 16) | (sc
->sc_sync
[target
].sxfer
<< 8) |
788 (sc
->sc_sync
[target
].scntl3
<< 24);
790 acb
->ds
.idbuf
= (char *) kvtop(&acb
->msgout
[0]);
791 acb
->ds
.cmdlen
= clen
;
792 acb
->ds
.cmdbuf
= (char *) kvtop(cbuf
);
794 acb
->ds
.stsbuf
= (char *) kvtop(&acb
->stat
[0]);
796 acb
->ds
.msgbuf
= (char *) kvtop(&acb
->msg
[0]);
798 acb
->ds
.msginlen
= 1;
799 acb
->ds
.extmsglen
= 1;
800 acb
->ds
.synmsglen
= 3;
801 acb
->ds
.msginbuf
= acb
->ds
.msgbuf
+ 1;
802 acb
->ds
.extmsgbuf
= acb
->ds
.msginbuf
+ 1;
803 acb
->ds
.synmsgbuf
= acb
->ds
.extmsgbuf
+ 1;
804 memset(&acb
->ds
.chain
, 0, sizeof (acb
->ds
.chain
));
806 if (sc
->sc_sync
[target
].state
== NEG_WIDE
) {
807 if (siopng_inhibit_wide
[target
]) {
808 sc
->sc_sync
[target
].state
= NEG_SYNC
;
809 sc
->sc_sync
[target
].scntl3
&= ~SIOP_SCNTL3_EWS
;
811 if (siopngsync_debug
)
812 printf ("Forcing target %d narrow\n", target
);
816 sc
->sc_sync
[target
].scntl3
= 0x15 | /* XXX */
817 (sc
->sc_sync
[target
].scntl3
& 0x88); /* XXX */
819 acb
->msgout
[1] = MSG_EXT_MESSAGE
;
821 acb
->msgout
[3] = MSG_WIDE_REQ
;
824 acb
->ds
.synmsglen
= 2;
825 sc
->sc_sync
[target
].state
= NEG_WAITW
;
827 if (siopngsync_debug
)
828 printf("Sending wide request to target %d\n", target
);
832 if (sc
->sc_sync
[target
].state
== NEG_SYNC
) {
833 if (siopng_inhibit_sync
[target
]) {
834 sc
->sc_sync
[target
].state
= NEG_DONE
;
835 sc
->sc_sync
[target
].scntl3
= 5 | /* XXX */
836 (sc
->sc_sync
[target
].scntl3
& 0x88); /* XXX */
837 sc
->sc_sync
[target
].sxfer
= 0;
839 if (siopngsync_debug
)
840 printf ("Forcing target %d asynchronous\n", target
);
844 sc
->sc_sync
[target
].scntl3
= 0x15 | /* XXX */
845 (sc
->sc_sync
[target
].scntl3
& 0x88); /* XXX */
847 acb
->msgout
[1] = MSG_EXT_MESSAGE
;
849 acb
->msgout
[3] = MSG_SYNC_REQ
;
850 #ifdef MAXTOR_SYNC_KLUDGE
851 acb
->msgout
[4] = 50 / 4; /* ask for ridiculous period */
853 acb
->msgout
[4] = sc
->sc_minsync
;
855 acb
->msgout
[5] = SIOP_MAX_OFFSET
;
857 sc
->sc_sync
[target
].state
= NEG_WAITS
;
859 if (siopngsync_debug
)
860 printf ("Sending sync request to target %d\n", target
);
866 * Build physical DMA addresses for scatter/gather I/O
870 acb
->iob_curbuf
= acb
->iob_curlen
= 0;
876 acb
->ds
.chain
[nchain
].databuf
= (char *) kvtop (addr
);
877 if (count
< (tcount
= PAGE_SIZE
- ((int) addr
& PGOFSET
)))
880 #if DEBUG_ONLY_IF_DESPERATE
881 printf("chain[%d]: count %d tcount %d vaddr %p paddr %p\n",
882 nchain
, count
, tcount
, addr
,
883 acb
->ds
.chain
[nchain
].databuf
);
885 acb
->ds
.chain
[nchain
].datalen
= tcount
;
888 if (acb
->ds
.chain
[nchain
].databuf
== dmaend
) {
889 dmaend
+= acb
->ds
.chain
[nchain
].datalen
;
890 acb
->ds
.chain
[nchain
].datalen
= 0;
891 acb
->ds
.chain
[--nchain
].datalen
+= tcount
;
897 dmaend
= acb
->ds
.chain
[nchain
].databuf
+
898 acb
->ds
.chain
[nchain
].datalen
;
899 acb
->ds
.chain
[nchain
].datalen
= tcount
;
901 if (nchain
) /* Don't count miss on first one */
908 if (nchain
!= 1 && len
!= 0 && siopng_debug
& 3) {
909 printf ("DMA chaining set: %d\n", nchain
);
910 for (i
= 0; i
< nchain
; ++i
) {
911 printf (" [%d] %8p %lx\n", i
, acb
->ds
.chain
[i
].databuf
,
912 acb
->ds
.chain
[i
].datalen
);
917 /* push data cache for all data the 53c720/770 needs to access */
918 dma_cachectl ((void *)acb
, sizeof (struct siop_acb
));
919 dma_cachectl (cbuf
, clen
);
920 if (buf
!= NULL
&& len
!= 0)
921 dma_cachectl (buf
, len
);
923 if (siopng_debug
& 0x100 && rp
->siop_sbcl
& SIOP_BSY
) {
924 printf ("ACK! siopng was busy at start: rp %p script %p dsa %p active %ld\n",
925 rp
, &siopng_scripts
, &acb
->ds
, sc
->sc_active
);
931 if (sc
->nexus_list
.tqh_first
== NULL
) {
932 callout_reset(&acb
->xs
->xs_callout
,
933 mstohz(acb
->xs
->timeout
) + 1, siopng_timeout
, acb
);
934 if (rp
->siop_istat
& SIOP_ISTAT_CON
)
935 printf("%s: siopng_select while connected?\n",
936 sc
->sc_dev
.dv_xname
);
939 rp
->siop_scntl3
= sc
->sc_sync
[target
].scntl3
;
941 rp
->siop_dsa
= kvtop((void *)&acb
->ds
);
942 rp
->siop_dsp
= sc
->sc_scriptspa
;
943 SIOP_TRACE('s',1,0,0)
945 if ((rp
->siop_istat
& SIOP_ISTAT_CON
) == 0) {
946 rp
->siop_istat
= SIOP_ISTAT_SIGP
;
947 SIOP_TRACE('s',2,0,0);
950 SIOP_TRACE('s',3,rp
->siop_istat
,0);
959 * Process a DMA or SCSI interrupt from the 53C720/770 SIOP
963 siopng_checkintr(struct siop_softc
*sc
, u_char istat
, u_char dstat
,
964 u_short sist
, int *status
)
966 siop_regmap_p rp
= sc
->sc_siopp
;
967 struct siop_acb
*acb
= sc
->sc_nexus
;
969 int dfifo
, dbc
, sstat0
, sstat1
, sstat2
;
971 dfifo
= rp
->siop_dfifo
;
973 sstat0
= rp
->siop_sstat0
;
974 sstat1
= rp
->siop_sstat1
;
975 sstat2
= rp
->siop_sstat2
;
976 rp
->siop_ctest3
|= SIOP_CTEST8_CLF
;
977 while ((rp
->siop_ctest1
& SIOP_CTEST1_FMT
) != SIOP_CTEST1_FMT
)
979 rp
->siop_ctest3
&= ~SIOP_CTEST8_CLF
;
983 if (siopng_debug
& 0x100) {
984 DCIAS(&acb
->stat
[0]); /* XXX */
985 printf ("siopngchkintr: istat %x dstat %x sist %x dsps %x sbcl %x sts %x msg %x\n",
986 istat
, dstat
, sist
, rp
->siop_dsps
, rp
->siop_sbcl
, acb
->stat
[0], acb
->msg
[0]);
987 printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n",
988 acb
->msg
[0], acb
->msg
[1], acb
->msg
[2],
989 acb
->msg
[3], acb
->msg
[4], acb
->msg
[5]);
992 if (rp
->siop_dsp
&& (rp
->siop_dsp
< sc
->sc_scriptspa
||
993 rp
->siop_dsp
>= sc
->sc_scriptspa
+ sizeof(siopng_scripts
))) {
994 printf ("%s: dsp not within script dsp %lx scripts %lx:%lx",
995 sc
->sc_dev
.dv_xname
, rp
->siop_dsp
, sc
->sc_scriptspa
,
996 sc
->sc_scriptspa
+ sizeof(siopng_scripts
));
997 printf(" istat %x dstat %x sist %x\n",
1004 SIOP_TRACE('i',dstat
,istat
,(istat
&SIOP_ISTAT_DIP
)?rp
->siop_dsps
&0xff:sist
);
1005 if (dstat
& SIOP_DSTAT_SIR
&& rp
->siop_dsps
== 0xff00) {
1006 /* Normal completion status, or check condition */
1008 if (rp
->siop_dsa
!= kvtop((void *)&acb
->ds
)) {
1009 printf ("siopng: invalid dsa: %lx %x\n", rp
->siop_dsa
,
1010 (unsigned)kvtop((void *)&acb
->ds
));
1011 panic("*** siopng DSA invalid ***");
1014 target
= acb
->xs
->xs_periph
->periph_target
;
1015 if (sc
->sc_sync
[target
].state
== NEG_WAITW
) {
1016 if (acb
->msg
[1] == 0xff)
1017 printf ("%s: target %d ignored wide request\n",
1018 sc
->sc_dev
.dv_xname
, target
);
1019 else if (acb
->msg
[1] == MSG_REJECT
)
1020 printf ("%s: target %d rejected wide request\n",
1021 sc
->sc_dev
.dv_xname
, target
);
1023 printf("%s: target %d (wide) %02x %02x %02x %02x\n",
1024 sc
->sc_dev
.dv_xname
, target
, acb
->msg
[1],
1025 acb
->msg
[2], acb
->msg
[3], acb
->msg
[4]);
1026 if (acb
->msg
[1] == MSG_EXT_MESSAGE
&&
1028 acb
->msg
[3] == MSG_WIDE_REQ
)
1029 sc
->sc_sync
[target
].scntl3
= acb
->msg
[4] ?
1030 sc
->sc_sync
[target
].scntl3
| SIOP_SCNTL3_EWS
:
1031 sc
->sc_sync
[target
].scntl3
& ~SIOP_SCNTL3_EWS
;
1033 sc
->sc_sync
[target
].state
= NEG_SYNC
;
1035 if (sc
->sc_sync
[target
].state
== NEG_WAITS
) {
1036 if (acb
->msg
[1] == 0xff)
1037 printf ("%s: target %d ignored sync request\n",
1038 sc
->sc_dev
.dv_xname
, target
);
1039 else if (acb
->msg
[1] == MSG_REJECT
)
1040 printf ("%s: target %d rejected sync request\n",
1041 sc
->sc_dev
.dv_xname
, target
);
1043 /* XXX - need to set sync transfer parameters */
1044 printf("%s: target %d (sync) %02x %02x %02x\n",
1045 sc
->sc_dev
.dv_xname
, target
, acb
->msg
[1],
1046 acb
->msg
[2], acb
->msg
[3]);
1047 sc
->sc_sync
[target
].state
= NEG_DONE
;
1049 dma_cachectl(&acb
->stat
[0], 1);
1050 *status
= acb
->stat
[0];
1052 if (rp
->siop_sbcl
& SIOP_BSY
) {
1053 /*printf ("ACK! siop was busy at end: rp %x script %x dsa %x\n",
1054 rp, &siopng_scripts, &acb->ds);*/
1059 if (acb
->msg
[0] != 0x00)
1060 printf("%s: message was not COMMAND COMPLETE: %x\n",
1061 sc
->sc_dev
.dv_xname
, acb
->msg
[0]);
1063 if (sc
->nexus_list
.tqh_first
)
1064 rp
->siop_dcntl
|= SIOP_DCNTL_STD
;
1067 if (dstat
& SIOP_DSTAT_SIR
&& rp
->siop_dsps
== 0xff0b) {
1068 target
= acb
->xs
->xs_periph
->periph_target
;
1069 if (acb
->msg
[1] == MSG_EXT_MESSAGE
&& acb
->msg
[2] == 2 &&
1070 acb
->msg
[3] == MSG_WIDE_REQ
) {
1072 if (siopngsync_debug
)
1073 printf ("wide msg in: %02x %02x %02x %02x %02x %02x\n",
1074 acb
->msg
[0], acb
->msg
[1], acb
->msg
[2],
1075 acb
->msg
[3], acb
->msg
[4], acb
->msg
[5]);
1077 sc
->sc_sync
[target
].scntl3
&= ~(SIOP_SCNTL3_EWS
);
1078 if (acb
->msg
[2] == 2 &&
1079 acb
->msg
[3] == MSG_WIDE_REQ
&&
1081 sc
->sc_sync
[target
].scntl3
|= SIOP_SCNTL3_EWS
;
1082 printf ("%s: target %d now wide %d\n",
1083 sc
->sc_dev
.dv_xname
, target
,
1086 rp
->siop_scntl3
= sc
->sc_sync
[target
].scntl3
;
1087 if (sc
->sc_sync
[target
].state
== NEG_WAITW
) {
1088 sc
->sc_sync
[target
].state
= NEG_SYNC
;
1089 rp
->siop_dsp
= sc
->sc_scriptspa
+ Ent_clear_ack
;
1092 rp
->siop_dcntl
|= SIOP_DCNTL_STD
;
1093 sc
->sc_sync
[target
].state
= NEG_SYNC
;
1096 if (acb
->msg
[1] == MSG_EXT_MESSAGE
&& acb
->msg
[2] == 3 &&
1097 acb
->msg
[3] == MSG_SYNC_REQ
) {
1099 if (siopngsync_debug
)
1100 printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n",
1101 acb
->msg
[0], acb
->msg
[1], acb
->msg
[2],
1102 acb
->msg
[3], acb
->msg
[4], acb
->msg
[5]);
1104 sc
->sc_sync
[target
].sxfer
= 0;
1105 sc
->sc_sync
[target
].scntl3
= 5 | /* XXX */
1106 (sc
->sc_sync
[target
].scntl3
& 0x88); /* XXX */
1107 if (acb
->msg
[2] == 3 &&
1108 acb
->msg
[3] == MSG_SYNC_REQ
&&
1110 #ifdef MAXTOR_KLUDGE
1112 * Kludge for my Maxtor XT8580S
1113 * It accepts whatever we request, even
1114 * though it won't work. So we ask for
1115 * a short period than we can handle. If
1116 * the device says it can do it, use 208ns.
1117 * If the device says it can do less than
1118 * 100ns, then we limit it to 100ns.
1120 if (acb
->msg
[4] && acb
->msg
[4] < 100 / 4) {
1122 printf ("%d: target %d wanted %dns period\n",
1123 sc
->sc_dev
.dv_xname
, target
,
1126 if (acb
->msg
[4] == 50 / 4)
1127 acb
->msg
[4] = 208 / 4;
1129 acb
->msg
[4] = 100 / 4;
1131 #endif /* MAXTOR_KLUDGE */
1132 printf ("%s: target %d now synchronous, period=%dns, offset=%d\n",
1133 sc
->sc_dev
.dv_xname
, target
,
1134 (acb
->msg
[4] == 12) ? 50 : acb
->msg
[4] * 4,
1136 scsi_period_to_siopng (sc
, target
);
1138 rp
->siop_sxfer
= sc
->sc_sync
[target
].sxfer
;
1139 rp
->siop_scntl3
= sc
->sc_sync
[target
].scntl3
;
1140 if (sc
->sc_sync
[target
].state
== NEG_WAITS
) {
1141 sc
->sc_sync
[target
].state
= NEG_DONE
;
1142 rp
->siop_dsp
= sc
->sc_scriptspa
+ Ent_clear_ack
;
1145 rp
->siop_dcntl
|= SIOP_DCNTL_STD
;
1146 sc
->sc_sync
[target
].state
= NEG_DONE
;
1149 /* XXX - not SDTR message */
1151 if (sist
& SIOP_SIST_MA
) { /* Phase mismatch */
1155 printf("%s: Phase mismatch with no active command?\n",
1156 sc
->sc_dev
.dv_xname
);
1160 adjust
= ((dfifo
- (dbc
& 0x7f)) & 0x7f);
1161 if (sstat0
& SIOP_SSTAT0_OLF
) /* sstat0 SODL lsb */
1163 if (sstat0
& SIOP_SSTAT0_ORF
) /* sstat0 SODR lsb */
1165 if (sstat2
& SIOP_SSTAT2_OLF1
) /* sstat2 SODL msb */
1167 if (sstat2
& SIOP_SSTAT2_ORF1
) /* sstat2 SODR msb */
1170 *((long *)__UNVOLATILE(&rp
->siop_dcmd
)) & 0xffffff;
1171 acb
->iob_curlen
+= adjust
;
1173 *((long *)__UNVOLATILE(&rp
->siop_dnad
)) - adjust
;
1175 if (siopng_debug
& 0x100) {
1177 printf ("Phase mismatch: curbuf %lx curlen %lx dfifo %x dbc %x sstat1 %x adjust %x sbcl %x starts %d acb %p\n",
1178 acb
->iob_curbuf
, acb
->iob_curlen
, dfifo
,
1179 dbc
, sstat1
, adjust
, rp
->siop_sbcl
, siopngstarts
, acb
);
1180 if (acb
->ds
.chain
[1].datalen
) {
1181 for (i
= 0; acb
->ds
.chain
[i
].datalen
; ++i
)
1182 printf("chain[%d] addr %p len %lx\n",
1183 i
, acb
->ds
.chain
[i
].databuf
,
1184 acb
->ds
.chain
[i
].datalen
);
1188 dma_cachectl ((void *)acb
, sizeof(*acb
));
1191 SIOP_TRACE('m',rp
->siop_sbcl
,(rp
->siop_dsp
>>8),rp
->siop_dsp
);
1192 if (siopng_debug
& 9)
1193 printf ("Phase mismatch: %x dsp +%lx dcmd %lx\n",
1195 rp
->siop_dsp
- sc
->sc_scriptspa
,
1196 *((volatile long *)&rp
->siop_dcmd
));
1198 if ((rp
->siop_sbcl
& SIOP_REQ
) == 0) {
1199 printf ("Phase mismatch: REQ not asserted! %02x dsp %lx\n",
1200 rp
->siop_sbcl
, rp
->siop_dsp
);
1201 #if defined(DEBUG) && defined(DDB)
1205 switch (rp
->siop_sbcl
& 7) {
1206 case 0: /* data out */
1207 case 1: /* data in */
1208 case 2: /* status */
1209 case 3: /* command */
1210 case 6: /* message in */
1211 case 7: /* message out */
1212 rp
->siop_dsp
= sc
->sc_scriptspa
+ Ent_switch
;
1219 if (sist
& SIOP_SIST_STO
) { /* Select timed out */
1222 printf("%s: Select timeout with no active command?\n",
1223 sc
->sc_dev
.dv_xname
);
1224 if (rp
->siop_sbcl
& SIOP_BSY
) {
1225 printf ("ACK! siop was busy at timeout: rp %p script %p dsa %p\n",
1226 rp
, &siopng_scripts
, &acb
->ds
);
1227 printf(" sbcl %x sdid %x istat %x dstat %x sist %x\n",
1228 rp
->siop_sbcl
, rp
->siop_sdid
, istat
, dstat
, sist
);
1229 if (!(rp
->siop_sbcl
& SIOP_BSY
)) {
1230 printf ("Yikes, it's not busy now!\n");
1233 if (sc
->nexus_list
.tqh_first
)
1234 rp
->siop_dsp
= sc
->sc_scriptspa
+ Ent_wait_reselect
;
1238 /* rp->siop_dcntl |= SIOP_DCNTL_STD;*/
1246 acb
->xs
->error
= XS_SELTIMEOUT
;
1247 if (sc
->nexus_list
.tqh_first
)
1248 rp
->siop_dsp
= sc
->sc_scriptspa
+ Ent_wait_reselect
;
1252 target
= acb
->xs
->xs_periph
->periph_target
;
1255 if (sist
& SIOP_SIST_UDC
) {
1258 printf("%s: Unexpected disconnect with no active command?\n",
1259 sc
->sc_dev
.dv_xname
);
1260 printf ("%s: target %d disconnected unexpectedly\n",
1261 sc
->sc_dev
.dv_xname
, target
);
1262 siopng_dump_registers(sc
);
1266 siopngabort (sc
, rp
, "siopngchkintr");
1269 if (sc
->nexus_list
.tqh_first
)
1270 rp
->siop_dsp
= sc
->sc_scriptspa
+ Ent_wait_reselect
;
1271 return (acb
!= NULL
);
1273 if (dstat
& SIOP_DSTAT_SIR
&& (rp
->siop_dsps
== 0xff01 ||
1274 rp
->siop_dsps
== 0xff02)) {
1276 if (siopng_debug
& 0x100)
1277 printf ("%s: ID %02x disconnected TEMP %lx (+%lx) curbuf %lx curlen %lx buf %p len %lx dfifo %x dbc %x sstat1 %x starts %d acb %p\n",
1278 sc
->sc_dev
.dv_xname
, 1 << target
, rp
->siop_temp
,
1279 rp
->siop_temp
? rp
->siop_temp
- sc
->sc_scriptspa
: 0,
1280 acb
->iob_curbuf
, acb
->iob_curlen
,
1281 acb
->ds
.chain
[0].databuf
, acb
->ds
.chain
[0].datalen
, dfifo
, dbc
, sstat1
, siopngstarts
, acb
);
1284 printf("%s: Disconnect with no active command?\n",
1285 sc
->sc_dev
.dv_xname
);
1289 * XXXX need to update iob_curbuf/iob_curlen to reflect
1290 * current data transferred. If device disconnected in
1291 * the middle of a DMA block, they should already be set
1292 * by the phase change interrupt. If the disconnect
1293 * occurs on a DMA block boundary, we have to figure out
1294 * which DMA block it was.
1296 if (acb
->iob_len
&& rp
->siop_temp
) {
1297 int n
= rp
->siop_temp
- sc
->sc_scriptspa
;
1299 if (acb
->iob_curlen
&& acb
->iob_curlen
!= acb
->ds
.chain
[0].datalen
)
1300 printf("%s: iob_curbuf/len already set? n %x iob %lx/%lx chain[0] %p/%lx\n",
1301 sc
->sc_dev
.dv_xname
, n
, acb
->iob_curbuf
, acb
->iob_curlen
,
1302 acb
->ds
.chain
[0].databuf
, acb
->ds
.chain
[0].datalen
);
1304 n
= (n
- Ent_dataout
) / 16;
1306 n
= (n
- Ent_datain
) / 16;
1307 if (n
<= 0 && n
> DMAMAXIO
)
1308 printf("TEMP invalid %d\n", n
);
1310 acb
->iob_curbuf
= (u_long
)acb
->ds
.chain
[n
].databuf
;
1311 acb
->iob_curlen
= acb
->ds
.chain
[n
].datalen
;
1314 if (siopng_debug
& 0x100) {
1315 printf("%s: TEMP offset %d", sc
->sc_dev
.dv_xname
, n
);
1316 printf(" curbuf %lx curlen %lx\n", acb
->iob_curbuf
,
1322 * If data transfer was interrupted by disconnect, iob_curbuf
1323 * and iob_curlen should reflect the point of interruption.
1324 * Adjust the DMA chain so that the data transfer begins
1325 * at the appropriate place upon reselection.
1326 * XXX This should only be done on save data pointer message?
1328 if (acb
->iob_curlen
) {
1332 if (siopng_debug
& 0x100)
1333 printf ("%s: adjusting DMA chain\n",
1334 sc
->sc_dev
.dv_xname
);
1335 if (rp
->siop_dsps
== 0xff02)
1336 printf ("%s: ID %02x disconnected without Save Data Pointers\n",
1337 sc
->sc_dev
.dv_xname
, 1 << target
);
1339 for (i
= 0; i
< DMAMAXIO
; ++i
) {
1340 if (acb
->ds
.chain
[i
].datalen
== 0)
1342 if (acb
->iob_curbuf
>= (long)acb
->ds
.chain
[i
].databuf
&&
1343 acb
->iob_curbuf
< (long)(acb
->ds
.chain
[i
].databuf
+
1344 acb
->ds
.chain
[i
].datalen
))
1347 if (i
>= DMAMAXIO
|| acb
->ds
.chain
[i
].datalen
== 0) {
1348 printf("couldn't find saved data pointer: ");
1349 printf("curbuf %lx curlen %lx i %d\n",
1350 acb
->iob_curbuf
, acb
->iob_curlen
, i
);
1356 if (siopng_debug
& 0x100)
1357 printf(" chain[0]: %p/%lx -> %lx/%lx\n",
1358 acb
->ds
.chain
[0].databuf
,
1359 acb
->ds
.chain
[0].datalen
,
1363 acb
->ds
.chain
[0].databuf
= (char *)acb
->iob_curbuf
;
1364 acb
->ds
.chain
[0].datalen
= acb
->iob_curlen
;
1365 for (j
= 1, ++i
; i
< DMAMAXIO
&& acb
->ds
.chain
[i
].datalen
; ++i
, ++j
) {
1367 if (siopng_debug
& 0x100)
1368 printf(" chain[%d]: %p/%lx -> %p/%lx\n", j
,
1369 acb
->ds
.chain
[j
].databuf
,
1370 acb
->ds
.chain
[j
].datalen
,
1371 acb
->ds
.chain
[i
].databuf
,
1372 acb
->ds
.chain
[i
].datalen
);
1374 acb
->ds
.chain
[j
].databuf
= acb
->ds
.chain
[i
].databuf
;
1375 acb
->ds
.chain
[j
].datalen
= acb
->ds
.chain
[i
].datalen
;
1378 acb
->ds
.chain
[j
].datalen
= 0;
1379 DCIAS(kvtop((void *)&acb
->ds
.chain
));
1381 ++sc
->sc_tinfo
[target
].dconns
;
1383 * add nexus to waiting list
1385 * try to start another command for another target/lun
1387 acb
->status
= sc
->sc_flags
& SIOP_INTSOFF
;
1388 TAILQ_INSERT_HEAD(&sc
->nexus_list
, acb
, chain
);
1389 sc
->sc_nexus
= NULL
; /* no current device */
1390 /* start script to wait for reselect */
1391 if (sc
->sc_nexus
== NULL
)
1392 rp
->siop_dsp
= sc
->sc_scriptspa
+ Ent_wait_reselect
;
1393 /* XXXX start another command ? */
1394 if (sc
->ready_list
.tqh_first
)
1398 rp
->siop_dcntl
|= SIOP_DCNTL_STD
;
1402 if (dstat
& SIOP_DSTAT_SIR
&& rp
->siop_dsps
== 0xff03) {
1403 int reselid
= rp
->siop_scratcha
& 0x7f;
1404 int reselun
= rp
->siop_sfbr
& 0x07;
1406 sc
->sc_sstat1
= rp
->siop_sbcl
; /* XXXX save current SBCL */
1408 if (siopng_debug
& 0x100)
1409 printf ("%s: target ID %02x reselected dsps %lx\n",
1410 sc
->sc_dev
.dv_xname
, reselid
,
1412 if ((rp
->siop_sfbr
& 0x80) == 0)
1413 printf("%s: Reselect message in was not identify: %x\n",
1414 sc
->sc_dev
.dv_xname
, rp
->siop_sfbr
);
1418 if (siopng_debug
& 0x100)
1419 printf ("%s: reselect ID %02x w/active\n",
1420 sc
->sc_dev
.dv_xname
, reselid
);
1422 TAILQ_INSERT_HEAD(&sc
->ready_list
, sc
->sc_nexus
, chain
);
1423 sc
->sc_tinfo
[sc
->sc_nexus
->xs
->xs_periph
->periph_target
].lubusy
1424 &= ~(1 << sc
->sc_nexus
->xs
->xs_periph
->periph_lun
);
1428 * locate acb of reselecting device
1429 * set sc->sc_nexus to acb
1431 for (acb
= sc
->nexus_list
.tqh_first
; acb
;
1432 acb
= acb
->chain
.tqe_next
) {
1433 if (reselid
!= ((acb
->ds
.scsi_addr
>> 16) & 0xff) ||
1434 reselun
!= (acb
->msgout
[0] & 0x07))
1436 TAILQ_REMOVE(&sc
->nexus_list
, acb
, chain
);
1438 sc
->sc_flags
|= acb
->status
;
1440 DCIAS(kvtop(&acb
->stat
[0]));
1441 rp
->siop_dsa
= kvtop((void *)&acb
->ds
);
1443 sc
->sc_sync
[acb
->xs
->xs_periph
->periph_target
].sxfer
;
1446 sc
->sc_sync
[acb
->xs
->xs_periph
->periph_target
].scntl3
;
1451 printf("%s: target ID %02x reselect nexus_list %p\n",
1452 sc
->sc_dev
.dv_xname
, reselid
,
1453 sc
->nexus_list
.tqh_first
);
1454 panic("unable to find reselecting device");
1456 dma_cachectl ((void *)acb
, sizeof(*acb
));
1458 rp
->siop_dcntl
|= SIOP_DCNTL_STD
;
1461 if (dstat
& SIOP_DSTAT_SIR
&& rp
->siop_dsps
== 0xff04) {
1463 u_short ctest2
= rp
->siop_ctest2
;
1465 /* reselect was interrupted (by Sig_P or select) */
1466 if (siopng_debug
& 0x100 ||
1467 (ctest2
& SIOP_CTEST2_SIGP
) == 0)
1468 printf ("%s: reselect interrupted (Sig_P?) scntl1 %x ctest2 %x sfbr %x istat %x/%x\n",
1469 sc
->sc_dev
.dv_xname
, rp
->siop_scntl1
,
1470 ctest2
, rp
->siop_sfbr
, istat
, rp
->siop_istat
);
1472 /* XXX assumes it was not select */
1473 if (sc
->sc_nexus
== NULL
) {
1475 printf("%s: reselect interrupted, sc_nexus == NULL\n",
1476 sc
->sc_dev
.dv_xname
);
1484 rp
->siop_dcntl
|= SIOP_DCNTL_STD
;
1487 target
= sc
->sc_nexus
->xs
->xs_periph
->periph_target
;
1489 rp
->siop_dsa
= kvtop((void *)&sc
->sc_nexus
->ds
);
1490 rp
->siop_sxfer
= sc
->sc_sync
[target
].sxfer
;
1492 rp
->siop_scntl3
= sc
->sc_sync
[target
].scntl3
;
1494 rp
->siop_dsp
= sc
->sc_scriptspa
;
1497 if (dstat
& SIOP_DSTAT_SIR
&& rp
->siop_dsps
== 0xff06) {
1499 printf("%s: Bad message-in with no active command?\n",
1500 sc
->sc_dev
.dv_xname
);
1501 /* Unrecognized message in byte */
1502 dma_cachectl (&acb
->msg
[1],1);
1503 printf ("%s: Unrecognized message in data sfbr %x msg %x sbcl %x\n",
1504 sc
->sc_dev
.dv_xname
, rp
->siop_sfbr
, acb
->msg
[1], rp
->siop_sbcl
);
1505 /* what should be done here? */
1506 DCIAS(kvtop(&acb
->msg
[1]));
1507 rp
->siop_dsp
= sc
->sc_scriptspa
+ Ent_clear_ack
;
1510 if (dstat
& SIOP_DSTAT_SIR
&& rp
->siop_dsps
== 0xff0a) {
1511 /* Status phase wasn't followed by message in phase? */
1512 printf ("%s: Status phase not followed by message in phase? sbcl %x sbdl %x\n",
1513 sc
->sc_dev
.dv_xname
, rp
->siop_sbcl
, rp
->siop_sbdl
);
1514 if (rp
->siop_sbcl
== 0xa7) {
1515 /* It is now, just continue the script? */
1516 rp
->siop_dcntl
|= SIOP_DCNTL_STD
;
1520 if (sist
== 0 && dstat
& SIOP_DSTAT_SIR
) {
1521 dma_cachectl (&acb
->stat
[0], 1);
1522 dma_cachectl (&acb
->msg
[0], 1);
1523 printf ("SIOP interrupt: %lx sts %x msg %x %x sbcl %x\n",
1524 rp
->siop_dsps
, acb
->stat
[0], acb
->msg
[0], acb
->msg
[1],
1528 return 0; /* siopngreset has cleaned up */
1530 if (sist
& SIOP_SIST_SGE
)
1531 printf ("SIOP: SCSI Gross Error\n");
1532 if (sist
& SIOP_SIST_PAR
)
1533 printf ("SIOP: Parity Error\n");
1534 if (dstat
& SIOP_DSTAT_IID
)
1535 printf ("SIOP: Invalid instruction detected\n");
1538 * temporary panic for unhandled conditions
1539 * displays various things about the 53C720/770 status and registers
1541 * XXXX need to clean this up to print out the info, reset, and continue
1543 printf ("siopngchkintr: target %x ds %p\n", target
, &acb
->ds
);
1544 printf ("scripts %lx ds %x rp %x dsp %lx dcmd %lx\n",
1545 sc
->sc_scriptspa
, (unsigned)kvtop((void *)&acb
->ds
),
1546 (unsigned)kvtop((void *)__UNVOLATILE(rp
)), rp
->siop_dsp
,
1547 *((long *)__UNVOLATILE(&rp
->siop_dcmd
)));
1548 printf ("siopngchkintr: istat %x dstat %x sist %x dsps %lx dsa %lx sbcl %x sts %x msg %x %x sfbr %x\n",
1549 istat
, dstat
, sist
, rp
->siop_dsps
, rp
->siop_dsa
,
1550 rp
->siop_sbcl
, acb
->stat
[0], acb
->msg
[0], acb
->msg
[1], rp
->siop_sfbr
);
1552 if (siopng_debug
& 0x20)
1553 panic("siopngchkintr: **** temp ****");
1558 siopngreset (sc
); /* hard reset */
1560 return 0; /* siopngreset cleaned up */
1564 siopng_select(struct siop_softc
*sc
)
1567 struct siop_acb
*acb
= sc
->sc_nexus
;
1570 if (siopng_debug
& 1)
1571 printf ("%s: select ", sc
->sc_dev
.dv_xname
);
1575 if (acb
->xs
->xs_control
& XS_CTL_POLL
|| siopng_no_dma
) {
1576 sc
->sc_flags
|= SIOP_INTSOFF
;
1577 sc
->sc_flags
&= ~SIOP_INTDEFER
;
1578 if ((rp
->siop_istat
& 0x08) == 0) {
1583 } else if ((sc
->sc_flags
& SIOP_INTDEFER
) == 0) {
1584 sc
->sc_flags
&= ~SIOP_INTSOFF
;
1585 if ((rp
->siop_istat
& 0x08) == 0) {
1586 rp
->siop_sien
= sc
->sc_sien
;
1587 rp
->siop_dien
= sc
->sc_dien
;
1592 if (siopng_debug
& 1)
1593 printf ("siopng_select: target %x cmd %02x ds %p\n",
1594 acb
->xs
->xs_periph
->periph_target
, acb
->cmd
.opcode
,
1598 siopng_start(sc
, acb
->xs
->xs_periph
->periph_target
,
1599 acb
->xs
->xs_periph
->periph_lun
,
1600 (u_char
*)&acb
->cmd
, acb
->clen
, acb
->daddr
, acb
->dleft
);
1606 * 53C720/770 interrupt handler
1610 siopngintr(register struct siop_softc
*sc
)
1613 u_char istat
, dstat
;
1618 istat
= sc
->sc_istat
;
1619 if ((istat
& (SIOP_ISTAT_SIP
| SIOP_ISTAT_DIP
)) == 0) {
1624 /* Got a valid interrupt on this device */
1626 dstat
= sc
->sc_dstat
;
1628 if (dstat
& SIOP_DSTAT_SIR
)
1629 sc
->sc_intcode
= rp
->siop_dsps
;
1632 if (siopng_debug
& 1)
1633 printf ("%s: intr istat %x dstat %x sist %x\n",
1634 sc
->sc_dev
.dv_xname
, istat
, dstat
, sist
);
1635 if (!sc
->sc_active
) {
1636 printf ("%s: spurious interrupt? istat %x dstat %x sist %x nexus %p status %x\n",
1637 sc
->sc_dev
.dv_xname
, istat
, dstat
, sist
,
1638 sc
->sc_nexus
, sc
->sc_nexus
? sc
->sc_nexus
->stat
[0] : 0);
1643 if (siopng_debug
& 5) {
1644 DCIAS(kvtop(&sc
->sc_nexus
->stat
[0]));
1645 printf ("%s: intr istat %x dstat %x sist %x dsps %lx sbcl %x sts %x msg %x\n",
1646 sc
->sc_dev
.dv_xname
, istat
, dstat
, sist
,
1647 rp
->siop_dsps
, rp
->siop_sbcl
,
1648 sc
->sc_nexus
->stat
[0], sc
->sc_nexus
->msg
[0]);
1651 if (sc
->sc_flags
& SIOP_INTDEFER
) {
1652 sc
->sc_flags
&= ~(SIOP_INTDEFER
| SIOP_INTSOFF
);
1653 rp
->siop_sien
= sc
->sc_sien
;
1654 rp
->siop_dien
= sc
->sc_dien
;
1656 if (siopng_checkintr (sc
, istat
, dstat
, sist
, &status
)) {
1659 printf ("siopngintr: status == 0xff\n");
1661 if ((sc
->sc_flags
& (SIOP_INTSOFF
| SIOP_INTDEFER
)) != SIOP_INTSOFF
) {
1663 if (rp
->siop_sbcl
& SIOP_BSY
) {
1664 printf ("%s: SCSI bus busy at completion",
1665 sc
->sc_dev
.dv_xname
);
1666 printf(" targ %d sbcl %02x sfbr %x respid %02x dsp +%x\n",
1667 sc
->sc_nexus
->xs
->xs_periph
->periph_target
,
1668 rp
->siop_sbcl
, rp
->siop_sfbr
, rp
->siop_respid
,
1669 rp
->siop_dsp
- sc
->sc_scriptspa
);
1672 siopng_scsidone(sc
->sc_nexus
, sc
->sc_nexus
?
1673 sc
->sc_nexus
->stat
[0] : -1);
1680 * This is based on the Progressive Peripherals 33 MHz Zeus driver and will
1681 * not be correct for other 53c710 boards.
1685 scsi_period_to_siopng(struct siop_softc
*sc
, int target
)
1687 int period
, offset
, sxfer
, scntl3
= 0;
1689 period
= sc
->sc_nexus
->msg
[4];
1690 offset
= sc
->sc_nexus
->msg
[5];
1692 for (scntl3
= 1; scntl3
< 4; ++scntl3
) {
1693 sxfer
= (period
* 4 - 1) / sc
->sc_tcp
[scntl3
] - 3;
1694 if (sxfer
>= 0 && sxfer
<= 7)
1698 printf("siopng sync: unable to compute sync params for period %dns\n",
1701 * XXX need to pick a value we can do and renegotiate
1705 sxfer
= (sxfer
<< 4) | ((offset
<= SIOP_MAX_OFFSET
) ?
1706 offset
: SIOP_MAX_OFFSET
);
1708 printf("siopng sync: params for period %dns: sxfer %x scntl3 %x",
1709 period
* 4, sxfer
, scntl3
);
1710 printf(" actual period %dns\n",
1711 sc
->sc_tcp
[scntl3
] * ((sxfer
>> 4) + 4));
1712 #endif /* DEBUG_SYNC */
1715 sxfer
= offset
<= SIOP_MAX_OFFSET
? offset
: SIOP_MAX_OFFSET
;
1716 sxfer
|= 0x20; /* XXX XFERP: 5 */
1718 if (period
<= (50 / 4)) /* XXX */
1719 scntl3
= 0x95; /* Ultra, SCF: /1, CCF: /4 */
1720 else if (period
<= (100 / 4))
1721 scntl3
= 0x35; /* SCF: /2, CCF: /4 */
1722 else if (period
<= (200 / 4))
1723 scntl3
= 0x55; /* SCF: /4, CCF: /4 */
1725 scntl3
= 0xff; /* XXX ??? */
1730 sc
->sc_sync
[target
].sxfer
= sxfer
;
1731 sc
->sc_sync
[target
].scntl3
= scntl3
|
1732 (sc
->sc_sync
[target
].scntl3
& SIOP_SCNTL3_EWS
);
1734 printf ("siopng sync: siop_sxfr %02x, siop_scntl3 %02x\n", sxfer
, scntl3
);
1739 siopng_dump_registers(struct siop_softc
*sc
)
1741 siop_regmap_p rp
= sc
->sc_siopp
;
1743 printf(" scntl0 %02x scntl1 %02x scntl2 %02x scntl3 %02x\n",
1744 rp
->siop_scntl0
, rp
->siop_scntl1
, rp
->siop_scntl2
, rp
->siop_scntl3
);
1745 printf(" scid %02x sxfer %02x sdid %02x gpreg %02x\n",
1746 rp
->siop_scid
, rp
->siop_sxfer
, rp
->siop_sdid
, rp
->siop_gpreg
);
1747 printf(" sfbr %02x socl %02x ssid %02x sbcl %02x\n",
1748 rp
->siop_sfbr
, rp
->siop_socl
, rp
->siop_ssid
, rp
->siop_sbcl
);
1749 printf(" dstat %02x sstat0 %02x sstat1 %02x sstat2 %02x\n",
1750 rp
->siop_dstat
, rp
->siop_sstat0
, rp
->siop_sstat1
, rp
->siop_sstat2
);
1751 printf(" ctest0 %02x ctest1 %02x ctest2 %02x ctest3 %02x\n",
1752 rp
->siop_ctest0
, rp
->siop_ctest1
, rp
->siop_ctest2
, rp
->siop_ctest3
);
1753 printf(" dfifo %02x ctest4 %02x ctest5 %02x ctest6 %02x\n",
1754 0, rp
->siop_ctest4
, rp
->siop_ctest5
, rp
->siop_ctest6
);
1755 printf(" dcmd %02x dbc2 %02x dbc1 %02x dbc0 %02x\n",
1756 rp
->siop_dcmd
, rp
->siop_dbc2
, rp
->siop_dbc1
, rp
->siop_dbc0
);
1757 printf(" dmode %02x dien %02x dwt %02x dcntl %02x\n",
1758 rp
->siop_dmode
, rp
->siop_dien
, rp
->siop_dwt
, rp
->siop_dcntl
);
1759 printf(" stest0 %02x stest1 %02x stest2 %02x stest3 %02x\n",
1760 rp
->siop_stest0
, rp
->siop_stest1
, rp
->siop_stest2
, rp
->siop_stest3
);
1761 printf(" istat %02x sien %04x sist %04x respid %04x\n",
1762 rp
->siop_istat
, rp
->siop_sien
, rp
->siop_sist
, rp
->siop_respid
);
1763 printf(" sidl %04x sodl %04x sbdl %04x\n",
1764 rp
->siop_sidl
, rp
->siop_sodl
, rp
->siop_sbdl
);
1765 printf(" dsps %08lx dsp %08lx (+%lx)\n",
1766 rp
->siop_dsps
, rp
->siop_dsp
, rp
->siop_dsp
> sc
->sc_scriptspa
?
1767 rp
->siop_dsp
- sc
->sc_scriptspa
: 0);
1768 printf(" dsa %08lx temp %08lx dnad %08lx\n",
1769 rp
->siop_dsa
, rp
->siop_temp
, rp
->siop_dnad
);
1770 printf(" scratcha %08lx scratchb %08lx adder %08lx\n",
1771 rp
->siop_scratcha
, rp
->siop_scratchb
, rp
->siop_adder
);
1778 siopng_dump_trace(void)
1782 printf("siopng trace: next index %d\n", siopng_trix
);
1785 printf("%3d: '%c' %02x %02x %02x\n", i
, siopng_trbuf
[i
],
1786 siopng_trbuf
[i
+ 1], siopng_trbuf
[i
+ 2], siopng_trbuf
[i
+ 3]);
1787 i
= (i
+ 4) & (SIOP_TRACE_SIZE
- 1);
1788 } while (i
!= siopng_trix
);
1793 siopng_dump_acb(struct siop_acb
*acb
)
1795 u_char
*b
= (u_char
*) &acb
->cmd
;
1798 printf("acb@%p ", acb
);
1799 if (acb
->xs
== NULL
) {
1800 printf("<unused>\n");
1803 printf("(%d:%d) flags %2x clen %2d cmd ",
1804 acb
->xs
->xs_periph
->periph_target
,
1805 acb
->xs
->xs_periph
->periph_lun
, acb
->flags
, acb
->clen
);
1806 for (i
= acb
->clen
; i
; --i
)
1807 printf(" %02x", *b
++);
1809 printf(" xs: %p data %p:%04x ", acb
->xs
, acb
->xs
->data
,
1811 printf("va %p:%lx ", acb
->iob_buf
, acb
->iob_len
);
1812 printf("cur %lx:%lx\n", acb
->iob_curbuf
, acb
->iob_curlen
);
1816 siopng_dump(struct siop_softc
*sc
)
1818 struct siop_acb
*acb
;
1819 siop_regmap_p rp
= sc
->sc_siopp
;
1825 siopng_dump_trace();
1827 printf("%s@%p regs %p istat %x\n",
1828 sc
->sc_dev
.dv_xname
, sc
, rp
, rp
->siop_istat
);
1829 if ((acb
= sc
->free_list
.tqh_first
) > 0) {
1830 printf("Free list:\n");
1832 siopng_dump_acb(acb
);
1833 acb
= acb
->chain
.tqe_next
;
1836 if ((acb
= sc
->ready_list
.tqh_first
) > 0) {
1837 printf("Ready list:\n");
1839 siopng_dump_acb(acb
);
1840 acb
= acb
->chain
.tqe_next
;
1843 if ((acb
= sc
->nexus_list
.tqh_first
) > 0) {
1844 printf("Nexus list:\n");
1846 siopng_dump_acb(acb
);
1847 acb
= acb
->chain
.tqe_next
;
1852 siopng_dump_acb(sc
->sc_nexus
);
1854 for (i
= 0; i
< 8; ++i
) {
1855 if (sc
->sc_tinfo
[i
].cmds
> 2) {
1856 printf("tgt %d: cmds %d disc %d lubusy %x\n",
1857 i
, sc
->sc_tinfo
[i
].cmds
,
1858 sc
->sc_tinfo
[i
].dconns
,
1859 sc
->sc_tinfo
[i
].lubusy
);