1 /* $NetBSD: sii.c,v 1.7 2009/03/14 21:04:14 dsl Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell and Rick Macklem.
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 * @(#)sii.c 8.2 (Berkeley) 11/30/93
36 * from: Header: /sprite/src/kernel/dev/ds3100.md/RCS/devSII.c,
37 * v 9.2 89/09/14 13:37:41 jhh Exp $ SPRITE (DECWRL)";
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: sii.c,v 1.7 2009/03/14 21:04:14 dsl Exp $");
45 * SCSI interface driver
47 #include <sys/param.h>
50 #include <sys/device.h>
51 #include <sys/systm.h>
53 #include <machine/locore.h>
55 #include <dev/scsipi/scsi_all.h>
56 #include <dev/scsipi/scsi_message.h>
57 #include <dev/scsipi/scsipi_all.h>
58 #include <dev/scsipi/scsipi_disk.h>
59 #include <dev/scsipi/scsiconf.h>
61 /* old 4.4BSD/pmax scsi drivers */
62 #include <pmax/ibus/siireg.h> /* device registers */
63 #include <pmax/ibus/siivar.h> /* softc and prototypes */
65 #include <pmax/pmax/machdep.h> /* prom_scsiid prototype */
67 /* XXX not in dev/scsipi/scsi_message.h */
68 #define MSG_EXT_MODIFY_DATA_PTR 0x00
70 extern struct cfdriver sii_cd
;
73 * MACROS for timing out spin loops.
75 * Wait until expression is true.
77 * Control register bits can change at any time so when the CPU
78 * reads a register, the bits might change and
79 * invalidate the setup and hold times for the CPU.
80 * This macro reads the register twice to be sure the value is stable.
82 * args: var - variable to save control register contents
83 * reg - control register to read
84 * expr - expression to spin on
85 * spincount - maximum number of times through the loop
86 * cntr - variable for number of tries
88 #define SII_WAIT_UNTIL(var, reg, expr, spincount, cntr) { \
90 for (cntr = 0; cntr < spincount; cntr++) { \
91 while (tmp != (var = reg)) \
114 } sii_log
[NLOG
], *sii_logp
= sii_log
;
117 static u_char sii_buf
[256]; /* used for extended messages */
126 * Define a safe address in the SCSI buffer for doing status & message DMA
127 * XXX why not add another field to softc?
129 #define SII_BUF_ADDR(sc) ((sc)->sc_buf + SII_MAX_DMA_XFER_LENGTH * 14)
135 static void sii_Reset(struct siisoftc
*sc
, int resetbus
);
136 static void sii_StartCmd(struct siisoftc
*sc
, int target
);
137 static void sii_CmdDone(struct siisoftc
*sc
, int target
, int error
);
138 static void sii_DoIntr(struct siisoftc
*sc
, u_int dstat
);
139 static void sii_StateChg(struct siisoftc
*sc
, u_int cstat
);
140 static int sii_GetByte(SIIRegs
*regs
, int phase
, int ack
);
141 static void sii_DoSync(SIIRegs
*regs
, State
*state
);
142 static void sii_StartDMA(SIIRegs
*regs
, int phase
, u_short
*dmaAddr
,
146 static void sii_DumpLog(void);
151 * Match driver based on name
154 siiattach(struct siisoftc
*sc
)
158 sc
->sc_target
= -1; /* no command active */
161 * Give each target its own DMA buffer region.
162 * Make it big enough for 2 max transfers so we can ping pong buffers
163 * while we copy the data.
165 for (i
= 0; i
< SII_NCMD
; i
++) {
166 sc
->sc_st
[i
].dmaAddr
[0] = (u_short
*)
167 sc
->sc_buf
+ 2 * SII_MAX_DMA_XFER_LENGTH
* i
;
168 sc
->sc_st
[i
].dmaAddr
[1] = sc
->sc_st
[i
].dmaAddr
[0] +
169 SII_MAX_DMA_XFER_LENGTH
;
172 sii_Reset(sc
, RESET
);
173 printf(": target %d\n", sc
->sc_regs
->id
& SII_IDMSK
);
175 sc
->sc_adapter
.adapt_dev
= &sc
->sc_dev
;
176 sc
->sc_adapter
.adapt_nchannels
= 1;
177 sc
->sc_adapter
.adapt_openings
= 7;
178 sc
->sc_adapter
.adapt_max_periph
= 1;
179 sc
->sc_adapter
.adapt_ioctl
= NULL
;
180 sc
->sc_adapter
.adapt_minphys
= minphys
;
181 sc
->sc_adapter
.adapt_request
= sii_scsi_request
;
183 sc
->sc_channel
.chan_adapter
= &sc
->sc_adapter
;
184 sc
->sc_channel
.chan_bustype
= &scsi_bustype
;
185 sc
->sc_channel
.chan_channel
= 0;
186 sc
->sc_channel
.chan_ntargets
= 8;
187 sc
->sc_channel
.chan_nluns
= 8;
188 sc
->sc_channel
.chan_id
= sc
->sc_regs
->id
& SII_IDMSK
;
192 * Now try to attach all the sub-devices
194 config_found(&sc
->sc_dev
, &sc
->sc_channel
, scsiprint
);
198 * Start activity on a SCSI device.
199 * We maintain information on each device separately since devices can
200 * connect/disconnect during an operation.
204 sii_scsi_request(struct scsipi_channel
*chan
, scsipi_adapter_req_t req
, void *arg
)
206 struct scsipi_xfer
*xs
;
207 struct scsipi_periph
*periph
;
208 struct siisoftc
*sc
= (void *)chan
->chan_adapter
->adapt_dev
;
214 case ADAPTER_REQ_RUN_XFER
:
216 periph
= xs
->xs_periph
;
217 target
= periph
->periph_target
;
219 if (sc
->sc_cmd
[target
]) {
221 xs
->error
= XS_RESOURCE_SHORTAGE
;
223 printf("[busy at start]\n");
227 * Build a ScsiCmd for this command and start it.
229 sc
->sc_xs
[target
] = xs
;
230 sc
->sc_cmd
[target
] = &sc
->sc_cmd_fake
[target
]; /* XXX */
231 sc
->sc_cmd
[target
]->unit
= 0;
232 sc
->sc_cmd
[target
]->flags
= 0;
233 sc
->sc_cmd
[target
]->buflen
= xs
->datalen
;
234 sc
->sc_cmd
[target
]->buf
= xs
->data
;
235 sc
->sc_cmd
[target
]->cmdlen
= xs
->cmdlen
;
236 sc
->sc_cmd
[target
]->cmd
= (u_char
*)xs
->cmd
;
237 sc
->sc_cmd
[target
]->lun
= xs
->xs_periph
->periph_lun
;
238 sii_StartCmd(sc
, target
);
240 if ((xs
->xs_control
& XS_CTL_POLL
) == 0)
244 if ((xs
->xs_status
& XS_STS_DONE
) != 0)
247 /* XXX schedule another command? */
251 xs
->error
= XS_TIMEOUT
;
254 case ADAPTER_REQ_GROW_RESOURCES
:
255 /* XXX Not supported. */
258 case ADAPTER_REQ_SET_XFER_MODE
:
259 /* XXX Not supported. */
265 * Check to see if any SII chips have pending interrupts
266 * and process as appropriate.
271 struct siisoftc
*sc
= xxxsc
;
275 * Find which controller caused the interrupt.
277 dstat
= sc
->sc_regs
->dstat
;
278 if (dstat
& (SII_CI
| SII_DI
)) {
279 sii_DoIntr(sc
, dstat
);
280 return (0); /* XXX */
283 return (1); /* XXX spurious interrupt? */
287 * Reset the SII chip and do a SCSI reset if 'reset' is true.
288 * NOTE: if !cold && reset, should probably probe for devices
289 * since a SCSI bus reset will set UNIT_ATTENTION.
292 sii_Reset(struct siisoftc
* sc
, int reset
)
293 /* reset: TRUE => reset SCSI bus */
295 SIIRegs
*regs
= sc
->sc_regs
;
299 printf("sii: RESET\n");
302 * Reset the SII chip.
304 regs
->comm
= SII_CHRESET
;
306 * Set arbitrated bus mode.
310 * Set host adapter ID (from PROM sciiidN variable).
312 /* XXX device_unit() abuse */
313 regs
->id
= SII_ID_IO
| prom_scsiid(device_unit(&sc
->sc_dev
));
315 * Enable SII to drive the SCSI bus.
317 regs
->dictrl
= SII_PRE
;
324 * Assert SCSI bus reset for at least 25 Usec to clear the
325 * world. SII_DO_RST is self clearing.
326 * Delay 250 ms before doing any commands.
328 regs
->comm
= SII_DO_RST
;
332 /* rearbitrate synchronous offset */
333 for (i
= 0; i
< SII_NCMD
; i
++)
334 sc
->sc_st
[i
].dmaReqAck
= 0;
338 * Clear any pending interrupts from the reset.
340 regs
->cstat
= regs
->cstat
;
341 regs
->dstat
= regs
->dstat
;
343 * Set up SII for arbitrated bus mode, SCSI parity checking,
344 * Reselect Enable, and Interrupt Enable.
346 regs
->csr
= SII_HPM
| SII_RSE
| SII_PCE
| SII_IE
;
351 * Start a SCSI command by sending the cmd data
352 * to a SCSI controller via the SII.
353 * Call the device done proceedure if it can't be started.
354 * NOTE: we should be called with interrupts disabled.
357 sii_StartCmd(struct siisoftc
*sc
, int target
)
358 /* sc: which SII to use */
359 /* target: which command to start */
367 /* if another command is currently in progress, just wait */
368 if (sc
->sc_target
>= 0)
371 /* initialize state information for this command */
372 scsicmd
= sc
->sc_cmd
[target
];
373 state
= &sc
->sc_st
[target
];
374 state
->flags
= FIRST_DMA
;
377 state
->dmaCurPhase
= -1;
378 state
->dmaPrevPhase
= -1;
379 state
->dmaBufIndex
= 0;
380 state
->cmd
= scsicmd
->cmd
;
381 state
->cmdlen
= scsicmd
->cmdlen
;
382 if ((state
->buflen
= scsicmd
->buflen
) == 0) {
383 state
->dmaDataPhase
= -1; /* illegal phase. shouldn't happen */
384 state
->buf
= (char *)0;
386 state
->buf
= scsicmd
->buf
;
391 printf("sii_StartCmd: %s target %d cmd 0x%x addr %p size %d DMA %d\n",
393 target
, scsicmd
->cmd
[0], scsicmd
->buf
, scsicmd
->buflen
,
394 state
->dmaDataPhase
);
396 sii_debug_cmd
= scsicmd
->cmd
[0];
397 if (scsicmd
->cmd
[0] == READ_10
||
398 scsicmd
->cmd
[0] == WRITE_10
) {
399 sii_debug_bn
= (scsicmd
->cmd
[2] << 24) |
400 (scsicmd
->cmd
[3] << 16) |
401 (scsicmd
->cmd
[4] << 8) |
403 sii_debug_sz
= (scsicmd
->cmd
[7] << 8) | scsicmd
->cmd
[8];
410 /* try to select the target */
414 * Another device may have selected us; in which case,
415 * this command will be restarted later.
417 if ((status
= regs
->dstat
) & (SII_CI
| SII_DI
)) {
418 sii_DoIntr(sc
, status
);
422 sc
->sc_target
= target
;
424 /* seem to have problems with synchronous transfers */
425 if (scsicmd
->flags
& SCSICMD_USE_SYNC
) {
426 printf("sii_StartCmd: doing extended msg\n"); /* XXX */
428 * Setup to send both the identify message and the synchronous
429 * data transfer request.
431 sii_buf
[0] = MSG_IDENTIFYFLAG
| MSG_IDENTIFY_DISCFLAG
;
432 sii_buf
[1] = MSG_EXTENDED
;
433 sii_buf
[2] = MSG_EXT_SDTR_LEN
;
434 sii_buf
[3] = MSG_EXT_SDTR
;
436 sii_buf
[5] = 3; /* maximum SII chip supports */
438 state
->dmaCurPhase
= SII_MSG_OUT_PHASE
,
440 sc
->sii_copytobuf((u_short
*)sii_buf
,
441 (volatile u_short
*)SII_BUF_ADDR(sc
), 6);
442 regs
->slcsr
= target
;
443 regs
->dmctrl
= state
->dmaReqAck
;
444 regs
->dmaddrl
= (u_short
)(SII_BUF_ADDR(sc
) >> 1);
445 regs
->dmaddrh
= (u_short
)(SII_BUF_ADDR(sc
) >> 17) & 03;
447 regs
->comm
= SII_DMA
| SII_INXFER
| SII_SELECT
| SII_ATN
|
448 SII_CON
| SII_MSG_OUT_PHASE
;
452 /* do a chained, select with ATN and programmed I/O command */
453 regs
->data
= MSG_IDENTIFYFLAG
| MSG_IDENTIFY_DISCFLAG
|
455 regs
->slcsr
= target
;
456 regs
->dmctrl
= state
->dmaReqAck
;
457 regs
->comm
= SII_INXFER
| SII_SELECT
| SII_ATN
| SII_CON
|
463 * Wait for something to happen
464 * (should happen soon or we would use interrupts).
466 SII_WAIT_UNTIL(status
, regs
->cstat
, status
& (SII_CI
| SII_DI
),
467 SII_WAIT_COUNT
/4, retval
);
469 /* check to see if we are connected OK */
470 if ((status
& (SII_RST
| SII_SCH
| SII_STATE_MSK
)) ==
471 (SII_SCH
| SII_CON
)) {
472 regs
->cstat
= status
;
476 sii_logp
->target
= target
;
477 sii_logp
->cstat
= status
;
479 sii_logp
->comm
= regs
->comm
;
481 sii_logp
->rlen
= state
->buflen
;
482 sii_logp
->dlen
= state
->dmalen
;
483 if (++sii_logp
>= &sii_log
[NLOG
])
487 /* wait a short time for command phase */
488 SII_WAIT_UNTIL(status
, regs
->dstat
, status
& SII_MIS
,
489 SII_WAIT_COUNT
, retval
);
492 printf("sii_StartCmd: ds %x cnt %d\n", status
, retval
);
494 if ((status
& (SII_CI
| SII_MIS
| SII_PHASE_MSK
)) !=
495 (SII_MIS
| SII_CMD_PHASE
)) {
496 printf("sii_StartCmd: timeout cs %x ds %x cnt %d\n",
497 regs
->cstat
, status
, retval
); /* XXX */
498 /* process interrupt or continue until it happens */
499 if (status
& (SII_CI
| SII_DI
))
500 sii_DoIntr(sc
, status
);
503 regs
->dstat
= SII_DNE
; /* clear Msg Out DMA done */
505 /* send command data */
506 sc
->sii_copytobuf((u_short
*)state
->cmd
,
507 (volatile u_short
*)state
->dmaAddr
[0], state
->cmdlen
);
508 sii_StartDMA(regs
, state
->dmaCurPhase
= SII_CMD_PHASE
,
509 state
->dmaAddr
[0], state
->dmalen
= scsicmd
->cmdlen
);
511 /* wait a little while for DMA to finish */
512 SII_WAIT_UNTIL(status
, regs
->dstat
, status
& (SII_CI
| SII_DI
),
513 SII_WAIT_COUNT
, retval
);
516 printf("sii_StartCmd: ds %x, cnt %d\n", status
, retval
);
518 if (status
& (SII_CI
| SII_DI
))
519 sii_DoIntr(sc
, status
);
522 printf("sii_StartCmd: DONE ds %x\n", regs
->dstat
);
528 * Another device may have selected us; in which case,
529 * this command will be restarted later.
531 if (status
& (SII_CI
| SII_DI
)) {
532 sii_DoIntr(sc
, regs
->dstat
);
537 * Disconnect if selection command still in progress.
539 if (status
& SII_SIP
) {
540 error
= ENXIO
; /* device didn't respond */
541 regs
->comm
= SII_DISCON
;
543 SII_WAIT_UNTIL(status
, regs
->cstat
,
544 !(status
& (SII_CON
| SII_SIP
)),
545 SII_WAIT_COUNT
, retval
);
547 error
= EBUSY
; /* couldn't get the bus */
550 printf("sii_StartCmd: Couldn't select target %d error %d\n",
554 regs
->cstat
= 0xffff;
555 regs
->dstat
= 0xffff;
558 sii_CmdDone(sc
, target
, error
);
562 * Process interrupt conditions.
565 sii_DoIntr(struct siisoftc
*sc
, u_int dstat
)
567 SIIRegs
*regs
= sc
->sc_regs
;
578 printf("sii_DoIntr: cs %x, ds %x cm %x ",
579 regs
->cstat
, dstat
, comm
);
580 sii_logp
->target
= sc
->sc_target
;
581 sii_logp
->cstat
= regs
->cstat
;
582 sii_logp
->dstat
= dstat
;
583 sii_logp
->comm
= comm
;
585 if (sc
->sc_target
>= 0) {
586 sii_logp
->rlen
= sc
->sc_st
[sc
->sc_target
].buflen
;
587 sii_logp
->dlen
= sc
->sc_st
[sc
->sc_target
].dmalen
;
592 if (++sii_logp
>= &sii_log
[NLOG
])
596 regs
->dstat
= dstat
; /* acknowledge everything */
599 if (dstat
& SII_CI
) {
600 /* deglitch cstat register */
602 while (msg
!= (cstat
= regs
->cstat
))
604 regs
->cstat
= cstat
; /* acknowledge everything */
607 if (sii_logp
> sii_log
)
608 sii_logp
[-1].cstat
= cstat
;
610 sii_log
[NLOG
- 1].cstat
= cstat
;
613 /* check for a BUS RESET */
614 if (cstat
& SII_RST
) {
615 printf("%s: SCSI bus reset!!\n", sc
->sc_dev
.dv_xname
);
616 /* need to flush disconnected commands */
617 for (i
= 0; i
< SII_NCMD
; i
++) {
620 sii_CmdDone(sc
, i
, EIO
);
622 /* rearbitrate synchronous offset */
623 for (i
= 0; i
< SII_NCMD
; i
++)
624 sc
->sc_st
[i
].dmaReqAck
= 0;
631 * Check for a BUS ERROR.
632 * According to DEC, this feature doesn't really work
633 * and to just clear the bit if it's set.
635 if (cstat
& SII_BER
) {
636 regs
->cstat
= SII_BER
;
641 /* check for state change */
642 if (cstat
& SII_SCH
) {
643 sii_StateChg(sc
, cstat
);
648 /* check for DMA completion */
649 if (dstat
& SII_DNE
) {
654 * There is a race condition with SII_SCH. There is a short
655 * window between the time a SII_SCH is seen after a disconnect
656 * and when the SII_SCH is cleared. A reselect can happen
657 * in this window and we will clear the SII_SCH without
658 * processing the reconnect.
660 if (sc
->sc_target
< 0) {
662 printf("%s: target %d DNE?? dev %d,%d cs %x\n",
663 sc
->sc_dev
.dv_xname
, sc
->sc_target
,
664 regs
->slcsr
, regs
->destat
,
666 if (cstat
& SII_DST
) {
667 sc
->sc_target
= regs
->destat
;
668 state
= &sc
->sc_st
[sc
->sc_target
];
671 panic("sc_target 1");
673 state
= &sc
->sc_st
[sc
->sc_target
];
674 /* check for a PARITY ERROR */
675 if (dstat
& SII_IPE
) {
676 state
->flags
|= PARITY_ERR
;
677 printf("%s: Parity error!!\n", sc
->sc_dev
.dv_xname
);
680 /* dmalen = amount left to transfer, i = amount transfered */
683 state
->dmaCurPhase
= -1;
686 printf("DNE: amt %d ", i
);
687 if (!(dstat
& SII_TCZ
))
688 printf("no TCZ?? (%d) ", regs
->dmlotc
);
689 } else if (!(dstat
& SII_TCZ
)) {
690 printf("%s: device %d: no TCZ?? (%d)\n",
691 sc
->sc_dev
.dv_xname
, sc
->sc_target
, regs
->dmlotc
);
692 sii_DumpLog(); /* XXX */
695 switch (comm
& SII_PHASE_MSK
) {
700 case SII_DATA_IN_PHASE
:
701 /* check for more data for the same phase */
702 dma
= state
->dmaAddr
[state
->dmaBufIndex
];
706 if (state
->buflen
> 0 && !(dstat
& SII_MIS
)) {
709 /* start reading next chunk */
711 if (len
> SII_MAX_DMA_XFER_LENGTH
)
712 len
= SII_MAX_DMA_XFER_LENGTH
;
713 state
->dmaBufIndex
= !state
->dmaBufIndex
;
715 state
->dmaCurPhase
= SII_DATA_IN_PHASE
,
716 state
->dmaAddr
[state
->dmaBufIndex
],
717 state
->dmaCnt
= state
->dmalen
= len
);
718 dstat
&= ~(SII_IBF
| SII_TBE
);
720 /* copy in the data */
721 sc
->sii_copyfrombuf((volatile u_short
*)dma
, buf
, i
);
724 case SII_DATA_OUT_PHASE
:
725 state
->dmaBufIndex
= !state
->dmaBufIndex
;
729 /* check for more data for the same phase */
730 if (state
->buflen
<= 0 || (dstat
& SII_MIS
))
733 /* start next chunk */
735 if (i
> SII_MAX_DMA_XFER_LENGTH
) {
736 sii_StartDMA(regs
, state
->dmaCurPhase
=
738 state
->dmaAddr
[state
->dmaBufIndex
],
739 state
->dmaCnt
= state
->dmalen
=
740 SII_MAX_DMA_XFER_LENGTH
);
741 /* prepare for next chunk */
742 i
-= SII_MAX_DMA_XFER_LENGTH
;
743 if (i
> SII_MAX_DMA_XFER_LENGTH
)
744 i
= SII_MAX_DMA_XFER_LENGTH
;
745 sc
->sii_copytobuf((u_short
*)(state
->buf
+
746 SII_MAX_DMA_XFER_LENGTH
),
748 state
->dmaAddr
[!state
->dmaBufIndex
], i
);
750 sii_StartDMA(regs
, state
->dmaCurPhase
=
752 state
->dmaAddr
[state
->dmaBufIndex
],
753 state
->dmaCnt
= state
->dmalen
= i
);
755 dstat
&= ~(SII_IBF
| SII_TBE
);
759 /* check for phase change or another MsgIn/Out */
760 if (dstat
& (SII_MIS
| SII_IBF
| SII_TBE
)) {
762 * There is a race condition with SII_SCH. There is a short
763 * window between the time a SII_SCH is seen after a disconnect
764 * and when the SII_SCH is cleared. A reselect can happen
765 * in this window and we will clear the SII_SCH without
766 * processing the reconnect.
768 if (sc
->sc_target
< 0) {
770 printf("%s: target %d MIS?? dev %d,%d cs %x ds %x\n",
771 sc
->sc_dev
.dv_xname
, sc
->sc_target
,
772 regs
->slcsr
, regs
->destat
,
773 cstat
, dstat
); /* XXX */
774 if (cstat
& SII_DST
) {
775 sc
->sc_target
= regs
->destat
;
776 state
= &sc
->sc_st
[sc
->sc_target
];
782 panic("sc_target 2");
785 state
= &sc
->sc_st
[sc
->sc_target
];
786 switch (dstat
& SII_PHASE_MSK
) {
788 if (state
->dmaPrevPhase
>= 0) {
789 /* restart DMA after disconnect/reconnect */
790 if (state
->dmaPrevPhase
!= SII_CMD_PHASE
) {
791 printf("%s: device %d: DMA reselect phase doesn't match\n",
792 sc
->sc_dev
.dv_xname
, sc
->sc_target
);
795 state
->dmaCurPhase
= SII_CMD_PHASE
;
796 state
->dmaPrevPhase
= -1;
797 regs
->dmaddrl
= state
->dmaAddrL
;
798 regs
->dmaddrh
= state
->dmaAddrH
;
799 regs
->dmlotc
= state
->dmaCnt
;
800 if (state
->dmaCnt
& 1)
801 regs
->dmabyte
= state
->dmaByte
;
802 regs
->comm
= SII_DMA
| SII_INXFER
|
803 (comm
& SII_STATE_MSK
) | SII_CMD_PHASE
;
807 printf("Cmd dcnt %d dadr %x ",
809 (state
->dmaAddrH
<< 16) |
813 /* send command data */
816 printf("%s: device %d: cmd count exceeded\n",
817 sc
->sc_dev
.dv_xname
, sc
->sc_target
);
820 sc
->sii_copytobuf((u_short
*)state
->cmd
,
821 (volatile u_short
*)state
->dmaAddr
[0],
823 sii_StartDMA(regs
, state
->dmaCurPhase
=
824 SII_CMD_PHASE
, state
->dmaAddr
[0],
825 state
->dmaCnt
= state
->dmalen
= i
);
827 /* wait a short time for XFER complete */
828 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
829 dstat
& (SII_CI
| SII_DI
), SII_WAIT_COUNT
, i
);
830 if (dstat
& (SII_CI
| SII_DI
)) {
833 printf("cnt %d\n", i
);
834 else if (sii_debug
> 0)
835 printf("sii_DoIntr: cmd wait ds %x cnt %d\n",
842 case SII_DATA_IN_PHASE
:
843 case SII_DATA_OUT_PHASE
:
844 if (state
->cmdlen
> 0) {
845 printf("%s: device %d: cmd %x: command data not all sent (%d) 1\n",
846 sc
->sc_dev
.dv_xname
, sc
->sc_target
,
847 sc
->sc_cmd
[sc
->sc_target
]->cmd
[0],
854 if (state
->dmaPrevPhase
>= 0) {
855 /* restart DMA after disconnect/reconnect */
856 if (state
->dmaPrevPhase
!=
857 (dstat
& SII_PHASE_MSK
)) {
858 printf("%s: device %d: DMA reselect phase doesn't match\n",
859 sc
->sc_dev
.dv_xname
, sc
->sc_target
);
862 state
->dmaCurPhase
= state
->dmaPrevPhase
;
863 state
->dmaPrevPhase
= -1;
864 regs
->dmaddrl
= state
->dmaAddrL
;
865 regs
->dmaddrh
= state
->dmaAddrH
;
866 regs
->dmlotc
= state
->dmaCnt
;
867 if (state
->dmaCnt
& 1)
868 regs
->dmabyte
= state
->dmaByte
;
869 regs
->comm
= SII_DMA
| SII_INXFER
|
870 (comm
& SII_STATE_MSK
) |
875 printf("Data %d dcnt %d dadr %x ",
878 (state
->dmaAddrH
<< 16) |
885 printf("Data %d ", state
->dmaDataPhase
);
892 printf("%s: device %d: data count exceeded\n",
893 sc
->sc_dev
.dv_xname
, sc
->sc_target
);
896 if (i
> SII_MAX_DMA_XFER_LENGTH
)
897 i
= SII_MAX_DMA_XFER_LENGTH
;
898 if ((dstat
& SII_PHASE_MSK
) == SII_DATA_IN_PHASE
) {
900 state
->dmaCurPhase
= SII_DATA_IN_PHASE
,
901 state
->dmaAddr
[state
->dmaBufIndex
],
902 state
->dmaCnt
= state
->dmalen
= i
);
905 /* start first chunk */
906 if (state
->flags
& FIRST_DMA
) {
907 state
->flags
&= ~FIRST_DMA
;
908 sc
->sii_copytobuf((u_short
*)state
->buf
,
910 state
->dmaAddr
[state
->dmaBufIndex
], i
);
913 state
->dmaCurPhase
= SII_DATA_OUT_PHASE
,
914 state
->dmaAddr
[state
->dmaBufIndex
],
915 state
->dmaCnt
= state
->dmalen
= i
);
916 i
= state
->buflen
- SII_MAX_DMA_XFER_LENGTH
;
918 /* prepare for next chunk */
919 if (i
> SII_MAX_DMA_XFER_LENGTH
)
920 i
= SII_MAX_DMA_XFER_LENGTH
;
921 sc
->sii_copytobuf((u_short
*)(state
->buf
+
922 SII_MAX_DMA_XFER_LENGTH
),
924 state
->dmaAddr
[!state
->dmaBufIndex
], i
);
928 case SII_STATUS_PHASE
:
929 if (state
->cmdlen
> 0) {
930 printf("%s: device %d: cmd %x: command data not all sent (%d) 2\n",
931 sc
->sc_dev
.dv_xname
, sc
->sc_target
,
932 sc
->sc_cmd
[sc
->sc_target
]->cmd
[0],
940 /* read amount transfered if DMA didn't finish */
941 if (state
->dmalen
> 0) {
942 i
= state
->dmalen
- regs
->dmlotc
;
944 state
->dmaCurPhase
= -1;
947 (SII_STATE_MSK
| SII_PHASE_MSK
);
949 regs
->dstat
= SII_DNE
;
953 printf("DMA amt %d ", i
);
955 switch (comm
& SII_PHASE_MSK
) {
956 case SII_DATA_IN_PHASE
:
957 /* copy in the data */
958 sc
->sii_copyfrombuf((volatile u_short
*)
959 state
->dmaAddr
[state
->dmaBufIndex
],
963 case SII_DATA_OUT_PHASE
:
968 /* read a one byte status message */
969 state
->statusByte
= msg
=
970 sii_GetByte(regs
, SII_STATUS_PHASE
, 1);
977 printf("Status %x ", msg
);
978 if (sii_logp
> sii_log
)
979 sii_logp
[-1].msg
= msg
;
981 sii_log
[NLOG
- 1].msg
= msg
;
984 /* do a quick wait for COMMAND_COMPLETE */
985 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
986 dstat
& (SII_CI
| SII_DI
), SII_WAIT_COUNT
, i
);
987 if (dstat
& (SII_CI
| SII_DI
)) {
990 printf("cnt2 %d\n", i
);
996 case SII_MSG_IN_PHASE
:
998 * Save DMA state if DMA didn't finish.
999 * Be careful not to save state again after reconnect
1000 * and see RESTORE_POINTER message.
1001 * Note that the SII DMA address is not incremented
1004 if (state
->dmaCurPhase
>= 0) {
1005 /* save DMA registers */
1006 state
->dmaPrevPhase
= state
->dmaCurPhase
;
1007 state
->dmaCurPhase
= -1;
1008 if (dstat
& SII_OBB
)
1009 state
->dmaByte
= regs
->dmabyte
;
1012 i
= state
->dmaCnt
- i
;
1013 /* note: no carry from dmaddrl to dmaddrh */
1014 state
->dmaAddrL
= regs
->dmaddrl
+ i
;
1015 state
->dmaAddrH
= regs
->dmaddrh
;
1016 state
->dmaCnt
= regs
->dmlotc
;
1017 if (state
->dmaCnt
== 0)
1018 state
->dmaCnt
= SII_MAX_DMA_XFER_LENGTH
;
1020 (SII_STATE_MSK
| SII_PHASE_MSK
);
1022 regs
->dstat
= SII_DNE
;
1025 if (sii_debug
> 4) {
1026 printf("SavP dcnt %d dadr %x ",
1028 (state
->dmaAddrH
<< 16) |
1030 if (((dstat
& SII_OBB
) != 0) ^
1031 (state
->dmaCnt
& 1))
1033 } else if (sii_debug
> 0) {
1034 if (((dstat
& SII_OBB
) != 0) ^
1035 (state
->dmaCnt
& 1)) {
1036 printf("sii_DoIntr: OBB??? ds %x cnt %d\n",
1037 dstat
, state
->dmaCnt
);
1044 /* read a one byte message */
1045 msg
= sii_GetByte(regs
, SII_MSG_IN_PHASE
, 0);
1047 dstat
= regs
->dstat
;
1052 printf("MsgIn %x ", msg
);
1053 if (sii_logp
> sii_log
)
1054 sii_logp
[-1].msg
= msg
;
1056 sii_log
[NLOG
- 1].msg
= msg
;
1059 /* process message */
1061 case MSG_CMDCOMPLETE
:
1062 /* acknowledge last byte */
1063 regs
->comm
= SII_INXFER
| SII_MSG_IN_PHASE
|
1064 (comm
& SII_STATE_MSK
);
1065 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1066 dstat
& SII_DNE
, SII_WAIT_COUNT
, i
);
1067 regs
->dstat
= SII_DNE
;
1069 msg
= sc
->sc_target
;
1072 * Wait a short time for disconnect.
1073 * Don't be fooled if SII_BER happens first.
1074 * Note: a reselect may happen here.
1076 SII_WAIT_UNTIL(cstat
, regs
->cstat
,
1077 cstat
& (SII_RST
| SII_SCH
),
1079 if ((cstat
& (SII_RST
| SII_SCH
|
1080 SII_STATE_MSK
)) == SII_SCH
) {
1081 regs
->cstat
= SII_SCH
| SII_BER
;
1085 * Double check that we didn't miss a
1086 * state change between seeing it and
1087 * clearing the SII_SCH bit.
1090 if (!(i
& SII_SCH
) &&
1091 (i
& SII_STATE_MSK
) !=
1092 (cstat
& SII_STATE_MSK
))
1093 sii_StateChg(sc
, i
);
1097 printf("cs %x\n", cstat
);
1099 sii_CmdDone(sc
, msg
, 0);
1103 /* acknowledge last byte */
1104 regs
->comm
= SII_INXFER
| SII_MSG_IN_PHASE
|
1105 (comm
& SII_STATE_MSK
);
1106 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1107 dstat
& SII_DNE
, SII_WAIT_COUNT
, i
);
1108 regs
->dstat
= SII_DNE
;
1110 /* read the message length */
1111 msg
= sii_GetByte(regs
, SII_MSG_IN_PHASE
, 1);
1113 dstat
= regs
->dstat
;
1116 sii_buf
[1] = msg
; /* message length */
1120 * We read and acknowlege all the bytes
1121 * except the last so we can assert ATN
1122 * if needed before acknowledging the last.
1124 for (i
= 0; i
< msg
; i
++) {
1125 dstat
= sii_GetByte(regs
,
1126 SII_MSG_IN_PHASE
, i
< msg
- 1);
1127 if ((int)dstat
< 0) {
1128 dstat
= regs
->dstat
;
1131 sii_buf
[i
+ 2] = dstat
;
1134 switch (sii_buf
[2]) {
1135 case MSG_EXT_MODIFY_DATA_PTR
:
1136 /* acknowledge last byte */
1137 regs
->comm
= SII_INXFER
|
1139 (comm
& SII_STATE_MSK
);
1140 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1143 regs
->dstat
= SII_DNE
;
1145 i
= (sii_buf
[3] << 24) |
1146 (sii_buf
[4] << 16) |
1149 if (state
->dmaPrevPhase
>= 0) {
1150 state
->dmaAddrL
+= i
;
1155 case MSG_EXT_SDTR_LEN
:
1157 * Acknowledge last byte and
1158 * signal a request for MSG_OUT.
1160 regs
->comm
= SII_INXFER
| SII_ATN
|
1162 (comm
& SII_STATE_MSK
);
1163 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1166 regs
->dstat
= SII_DNE
;
1168 sii_DoSync(regs
, state
);
1174 * Acknowledge last byte and
1175 * signal a request for MSG_OUT.
1177 regs
->comm
= SII_INXFER
| SII_ATN
|
1179 (comm
& SII_STATE_MSK
);
1180 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1183 regs
->dstat
= SII_DNE
;
1186 /* wait for MSG_OUT phase */
1187 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1191 /* send a reject message */
1192 regs
->data
= MSG_MESSAGE_REJECT
;
1193 regs
->comm
= SII_INXFER
|
1194 (regs
->cstat
& SII_STATE_MSK
) |
1196 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1199 regs
->dstat
= SII_DNE
;
1204 case MSG_SAVEDATAPOINTER
:
1205 case MSG_RESTOREPOINTERS
:
1206 /* acknowledge last byte */
1207 regs
->comm
= SII_INXFER
| SII_MSG_IN_PHASE
|
1208 (comm
& SII_STATE_MSK
);
1209 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1210 dstat
& SII_DNE
, SII_WAIT_COUNT
, i
);
1211 regs
->dstat
= SII_DNE
;
1213 /* wait a short time for another msg */
1214 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1215 dstat
& (SII_CI
| SII_DI
),
1217 if (dstat
& (SII_CI
| SII_DI
)) {
1220 printf("cnt %d\n", i
);
1226 case MSG_DISCONNECT
:
1227 /* acknowledge last byte */
1228 regs
->comm
= SII_INXFER
| SII_MSG_IN_PHASE
|
1229 (comm
& SII_STATE_MSK
);
1230 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1231 dstat
& SII_DNE
, SII_WAIT_COUNT
, i
);
1232 regs
->dstat
= SII_DNE
;
1234 state
->prevComm
= comm
;
1237 printf("disconn %d ", sc
->sc_target
);
1240 * Wait a short time for disconnect.
1241 * Don't be fooled if SII_BER happens first.
1242 * Note: a reselect may happen here.
1244 SII_WAIT_UNTIL(cstat
, regs
->cstat
,
1245 cstat
& (SII_RST
| SII_SCH
),
1247 if ((cstat
& (SII_RST
| SII_SCH
|
1248 SII_STATE_MSK
)) != SII_SCH
) {
1251 printf("cnt %d\n", i
);
1253 dstat
= regs
->dstat
;
1256 regs
->cstat
= SII_SCH
| SII_BER
;
1261 * Double check that we didn't miss a state
1262 * change between seeing it and clearing
1266 if (!(i
& SII_SCH
) && (i
& SII_STATE_MSK
) !=
1267 (cstat
& SII_STATE_MSK
))
1268 sii_StateChg(sc
, i
);
1271 case MSG_MESSAGE_REJECT
:
1272 /* acknowledge last byte */
1273 regs
->comm
= SII_INXFER
| SII_MSG_IN_PHASE
|
1274 (comm
& SII_STATE_MSK
);
1275 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1276 dstat
& SII_DNE
, SII_WAIT_COUNT
, i
);
1277 regs
->dstat
= SII_DNE
;
1279 printf("%s: device %d: message reject.\n",
1280 sc
->sc_dev
.dv_xname
, sc
->sc_target
);
1284 if (!(msg
& MSG_IDENTIFYFLAG
)) {
1285 printf("%s: device %d: couldn't handle "
1286 "message 0x%x... rejecting.\n",
1287 sc
->sc_dev
.dv_xname
, sc
->sc_target
,
1294 /* acknowledge last byte */
1295 regs
->comm
= SII_INXFER
| SII_MSG_IN_PHASE
|
1296 (comm
& SII_STATE_MSK
);
1297 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1298 dstat
& SII_DNE
, SII_WAIT_COUNT
, i
);
1299 regs
->dstat
= SII_DNE
;
1301 /* may want to check LUN some day */
1302 /* wait a short time for another msg */
1303 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1304 dstat
& (SII_CI
| SII_DI
),
1306 if (dstat
& (SII_CI
| SII_DI
)) {
1309 printf("cnt %d\n", i
);
1316 case SII_MSG_OUT_PHASE
:
1321 printf("MsgOut %x\n", state
->flags
); /* XXX */
1324 * Check for parity error.
1325 * Hardware will automatically set ATN
1326 * to request the device for a MSG_OUT phase.
1328 if (state
->flags
& PARITY_ERR
) {
1329 state
->flags
&= ~PARITY_ERR
;
1330 regs
->data
= MSG_PARITY_ERROR
;
1332 regs
->data
= MSG_NOOP
;
1333 regs
->comm
= SII_INXFER
| (comm
& SII_STATE_MSK
) |
1337 /* wait a short time for XFER complete */
1338 SII_WAIT_UNTIL(dstat
, regs
->dstat
, dstat
& SII_DNE
,
1342 printf("ds %x i %d\n", dstat
, i
);
1344 /* just clear the DNE bit and check errors later */
1345 if (dstat
& SII_DNE
) {
1346 regs
->dstat
= SII_DNE
;
1352 printf("%s: Couldn't handle phase %d... ignoring.\n",
1353 sc
->sc_dev
.dv_xname
, dstat
& SII_PHASE_MSK
);
1362 * Check to make sure we won't be interrupted again.
1363 * Deglitch dstat register.
1366 while (msg
!= (dstat
= regs
->dstat
))
1368 if (dstat
& (SII_CI
| SII_DI
))
1371 if (sc
->sc_target
< 0) {
1372 /* look for another device that is ready */
1373 for (i
= 0; i
< SII_NCMD
; i
++) {
1374 /* don't restart a disconnected command */
1375 if (!sc
->sc_cmd
[i
] || sc
->sc_st
[i
].prevComm
)
1377 sii_StartCmd(sc
, i
);
1384 /* jump here to abort the current command */
1385 printf("%s: device %d: current command terminated\n",
1386 sc
->sc_dev
.dv_xname
, sc
->sc_target
);
1391 if ((cstat
= regs
->cstat
) & SII_CON
) {
1392 /* try to send an abort msg for awhile */
1393 regs
->dstat
= SII_DNE
;
1394 regs
->data
= MSG_ABORT
;
1395 regs
->comm
= SII_INXFER
| SII_ATN
| (cstat
& SII_STATE_MSK
) |
1398 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1399 (dstat
& (SII_DNE
| SII_PHASE_MSK
)) ==
1400 (SII_DNE
| SII_MSG_OUT_PHASE
),
1401 2 * SII_WAIT_COUNT
, i
);
1404 printf("Abort: cs %x ds %x i %d\n", cstat
, dstat
, i
);
1406 if ((dstat
& (SII_DNE
| SII_PHASE_MSK
)) ==
1407 (SII_DNE
| SII_MSG_OUT_PHASE
)) {
1408 /* disconnect if command in progress */
1409 regs
->comm
= SII_DISCON
;
1411 SII_WAIT_UNTIL(cstat
, regs
->cstat
,
1412 !(cstat
& SII_CON
), SII_WAIT_COUNT
, i
);
1417 printf("Abort: cs %x\n", cstat
);
1420 regs
->cstat
= 0xffff;
1421 regs
->dstat
= 0xffff;
1427 sii_CmdDone(sc
, i
, EIO
);
1430 printf("sii_DoIntr: after CmdDone target %d\n", sc
->sc_target
);
1435 sii_StateChg(struct siisoftc
*sc
, u_int cstat
)
1437 SIIRegs
*regs
= sc
->sc_regs
;
1446 switch (cstat
& SII_STATE_MSK
) {
1453 printf("disconn %d ", i
);
1455 if (i
>= 0 && !sc
->sc_st
[i
].prevComm
) {
1456 printf("%s: device %d: spurrious disconnect (%d)\n",
1457 sc
->sc_dev
.dv_xname
, i
, regs
->slcsr
);
1458 sc
->sc_st
[i
].prevComm
= 0;
1463 /* connected as initiator */
1465 if (sc
->sc_target
== i
)
1467 printf("%s: device %d: connect to device %d??\n",
1468 sc
->sc_dev
.dv_xname
, sc
->sc_target
, i
);
1474 * Wait for CON to become valid,
1475 * chip is slow sometimes.
1477 SII_WAIT_UNTIL(cstat
, regs
->cstat
,
1478 cstat
& SII_CON
, SII_WAIT_COUNT
, i
);
1479 if (!(cstat
& SII_CON
))
1483 case SII_CON
| SII_DST
:
1485 * Its a reselection. Save the ID and wait for
1486 * interrupts to tell us what to do next
1487 * (should be MSG_IN of IDENTIFY).
1488 * NOTE: sc_target may be >= 0 if we were in
1489 * the process of trying to start a command
1490 * and were reselected before the select
1493 sc
->sc_target
= i
= regs
->destat
;
1494 state
= &sc
->sc_st
[i
];
1495 regs
->comm
= SII_CON
| SII_DST
| SII_MSG_IN_PHASE
;
1496 regs
->dmctrl
= state
->dmaReqAck
;
1498 if (!state
->prevComm
) {
1499 printf("%s: device %d: spurious reselection\n",
1500 sc
->sc_dev
.dv_xname
, i
);
1503 state
->prevComm
= 0;
1506 printf("resel %d ", sc
->sc_target
);
1511 case SII_DST
| SII_TGT
:
1512 case SII_CON
| SII_DST
| SII_TGT
:
1513 /* connected as target */
1514 printf("%s: Selected by device %d as target!!\n",
1515 sc
->sc_dev
.dv_xname
, regs
->destat
);
1516 regs
->comm
= SII_DISCON
;
1518 SII_WAIT_UNTIL(!(regs
->cstat
& SII_CON
),
1520 regs
->cstat
= 0xffff;
1521 regs
->dstat
= 0xffff;
1527 printf("%s: Unknown state change (cs %x)!!\n",
1528 sc
->sc_dev
.dv_xname
, cstat
);
1536 * Read one byte of data.
1537 * If 'ack' is true, acknowledge the byte.
1540 sii_GetByte(SIIRegs
*regs
, int phase
, int ack
)
1547 dstat
= regs
->dstat
;
1548 state
= regs
->cstat
& SII_STATE_MSK
;
1550 if (!(dstat
& SII_IBF
) || (dstat
& SII_MIS
)) {
1551 regs
->comm
= state
| phase
;
1553 /* wait a short time for IBF */
1554 SII_WAIT_UNTIL(dstat
, regs
->dstat
, dstat
& SII_IBF
,
1557 if (!(dstat
& SII_IBF
))
1558 printf("status no IBF\n");
1561 if (dstat
& SII_DNE
) { /* XXX */
1562 printf("sii_GetByte: DNE set 5\n");
1566 regs
->dstat
= SII_DNE
;
1569 /* check for parity error */
1570 if (dstat
& SII_IPE
) {
1573 printf("cnt0 %d\n", i
);
1575 printf("sii_GetByte: data %x ?? ds %x cm %x i %d\n",
1576 data
, dstat
, regs
->comm
, i
); /* XXX */
1582 regs
->comm
= SII_INXFER
| state
| phase
;
1585 /* wait a short time for XFER complete */
1586 SII_WAIT_UNTIL(dstat
, regs
->dstat
, dstat
& SII_DNE
,
1590 if (dstat
& SII_DNE
) {
1591 regs
->dstat
= SII_DNE
;
1600 * Exchange messages to initiate synchronous data transfers.
1603 sii_DoSync(SIIRegs
*regs
, State
*state
)
1611 printf("sii_DoSync: len %d per %d req/ack %d\n",
1612 sii_buf
[1], sii_buf
[3], sii_buf
[4]);
1615 /* SII chip can only handle a minimum transfer period of ??? */
1616 if (sii_buf
[3] < 64)
1618 /* SII chip can only handle a maximum REQ/ACK offset of 3 */
1623 sii_buf
[0] = MSG_EXTENDED
;
1624 sii_buf
[1] = MSG_EXT_SDTR_LEN
;
1625 sii_buf
[2] = MSG_EXT_SDTR
;
1628 comm
= SII_INXFER
| SII_ATN
| SII_MSG_OUT_PHASE
|
1629 (regs
->cstat
& SII_STATE_MSK
);
1630 regs
->comm
= comm
& ~SII_INXFER
;
1631 for (j
= 0; j
< 5; j
++) {
1632 /* wait for target to request the next byte */
1633 SII_WAIT_UNTIL(dstat
, regs
->dstat
, dstat
& SII_TBE
,
1635 if (!(dstat
& SII_TBE
) ||
1636 (dstat
& SII_PHASE_MSK
) != SII_MSG_OUT_PHASE
) {
1637 printf("sii_DoSync: TBE? ds %x cm %x i %d\n",
1638 dstat
, comm
, i
); /* XXX */
1642 /* the last message byte should have ATN off */
1646 regs
->data
= sii_buf
[j
];
1650 /* wait a short time for XFER complete */
1651 SII_WAIT_UNTIL(dstat
, regs
->dstat
, dstat
& SII_DNE
,
1654 if (!(dstat
& SII_DNE
)) {
1655 printf("sii_DoSync: DNE? ds %x cm %x i %d\n",
1656 dstat
, comm
, i
); /* XXX */
1660 /* clear the DNE, other errors handled later */
1661 regs
->dstat
= SII_DNE
;
1665 sc
->sii_copytobuf((u_short
*)sii_buf
,
1666 (volatile u_short
*)SII_BUF_ADDR(sc
), 5);
1667 printf("sii_DoSync: %x %x %x ds %x\n",
1668 ((volatile u_short
*)SII_BUF_ADDR(sc
))[0],
1669 ((volatile u_short
*)SII_BUF_ADDR(sc
))[2],
1670 ((volatile u_short
*)SII_BUF_ADDR(sc
))[4],
1671 regs
->dstat
); /* XXX */
1672 regs
->dmaddrl
= (u_short
)(SII_BUF_ADDR(sc
) >> 1);
1673 regs
->dmaddrh
= (u_short
)(SII_BUF_ADDR(sc
) >> 17) & 03;
1675 regs
->comm
= SII_DMA
| SII_INXFER
| SII_ATN
|
1676 (regs
->cstat
& SII_STATE_MSK
) | SII_MSG_OUT_PHASE
;
1679 /* wait a short time for XFER complete */
1680 SII_WAIT_UNTIL(dstat
, regs
->dstat
,
1681 (dstat
& (SII_DNE
| SII_TCZ
)) == (SII_DNE
| SII_TCZ
),
1684 if ((dstat
& (SII_DNE
| SII_TCZ
)) != (SII_DNE
| SII_TCZ
)) {
1685 printf("sii_DoSync: ds %x cm %x i %d lotc %d\n",
1686 dstat
, regs
->comm
, i
, regs
->dmlotc
); /* XXX */
1687 sii_DumpLog(); /* XXX */
1690 /* clear the DNE, other errors handled later */
1691 regs
->dstat
= SII_DNE
;
1696 SII_WAIT_UNTIL(dstat
, regs
->dstat
, dstat
& (SII_CI
| SII_DI
),
1698 printf("sii_DoSync: ds %x cm %x i %d lotc %d\n",
1699 dstat
, regs
->comm
, i
, regs
->dmlotc
); /* XXX */
1702 state
->dmaReqAck
= len
;
1706 * Issue the sequence of commands to the controller to start DMA.
1707 * NOTE: the data buffer should be word-aligned for DMA out.
1710 sii_StartDMA(SIIRegs
*regs
, int phase
, u_short
*dmaAddr
, int size
)
1711 /* regs: which SII to use */
1712 /* phase: phase to send/receive data */
1713 /* dmaAddr: DMA buffer address */
1714 /* size: # of bytes to transfer */
1717 if (regs
->dstat
& SII_DNE
) { /* XXX */
1718 regs
->dstat
= SII_DNE
;
1719 printf("sii_StartDMA: DNE set\n");
1724 regs
->dmaddrl
= ((u_long
)dmaAddr
>> 1);
1725 regs
->dmaddrh
= ((u_long
)dmaAddr
>> 17) & 03;
1726 regs
->dmlotc
= size
;
1727 regs
->comm
= SII_DMA
| SII_INXFER
| (regs
->cstat
& SII_STATE_MSK
) |
1732 if (sii_debug
> 5) {
1733 printf("sii_StartDMA: cs 0x%x, ds 0x%x, cm 0x%x, size %d\n",
1734 regs
->cstat
, regs
->dstat
, regs
->comm
, size
);
1740 * Call the device driver's 'done' routine to let it know the command is done.
1741 * The 'done' routine may try to start another command.
1742 * To be fair, we should start pending commands for other devices
1743 * before allowing the same device to start another command.
1746 sii_CmdDone(struct siisoftc
*sc
, int target
, int error
)
1747 /* sc: which SII to use */
1748 /* target: which device is done */
1749 /* error: error code if any errors */
1754 scsicmd
= sc
->sc_cmd
[target
];
1756 if (target
< 0 || !scsicmd
)
1757 panic("sii_CmdDone");
1759 sc
->sc_cmd
[target
] = (ScsiCmd
*)0;
1761 if (sii_debug
> 1) {
1762 printf("sii_CmdDone: %s target %d cmd %x err %d resid %d\n",
1763 sc
->sc_dev
.dv_xname
,
1764 target
, scsicmd
->cmd
[0], error
, sc
->sc_st
[target
].buflen
);
1768 /* look for another device that is ready */
1769 for (i
= 0; i
< SII_NCMD
; i
++) {
1770 /* don't restart a disconnected command */
1771 if (!sc
->sc_cmd
[i
] || sc
->sc_st
[i
].prevComm
)
1773 sii_StartCmd(sc
, i
);
1777 sc
->sc_xs
[target
]->status
= sc
->sc_st
[target
].statusByte
;
1779 * Convert SII driver error code to MI SCSI XS_*.
1783 sc
->sc_xs
[target
]->error
= XS_NOERROR
;
1786 sc
->sc_xs
[target
]->error
= XS_SELTIMEOUT
;
1789 sc
->sc_xs
[target
]->error
= XS_BUSY
;
1792 sc
->sc_xs
[target
]->error
= XS_DRIVER_STUFFUP
;
1795 sc
->sc_xs
[target
]->error
= XS_DRIVER_STUFFUP
;
1797 sc
->sc_xs
[target
]->resid
= sc
->sc_st
[target
].buflen
;
1798 scsipi_done(sc
->sc_xs
[target
]);
1807 printf("sii: cmd %x bn %d cnt %d\n", sii_debug_cmd
, sii_debug_bn
,
1811 printf("target %d cs %x ds %x cm %x msg %x rlen %x dlen %x\n",
1812 lp
->target
, lp
->cstat
, lp
->dstat
, lp
->comm
, lp
->msg
,
1813 lp
->rlen
, lp
->dlen
);
1814 if (++lp
>= &sii_log
[NLOG
])
1816 } while (lp
!= sii_logp
);