sii.c revision 1.6 1 /* $NetBSD: sii.c,v 1.6 2009/03/14 15:36:11 dsl Exp $ */
2
3 /*-
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell and Rick Macklem.
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. 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.
21 *
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
32 * SUCH DAMAGE.
33 *
34 * @(#)sii.c 8.2 (Berkeley) 11/30/93
35 *
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)";
38 */
39
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: sii.c,v 1.6 2009/03/14 15:36:11 dsl Exp $");
42
43 #include "sii.h"
44 /*
45 * SCSI interface driver
46 */
47 #include <sys/param.h>
48 #include <sys/buf.h>
49 #include <sys/conf.h>
50 #include <sys/device.h>
51 #include <sys/systm.h>
52
53 #include <machine/locore.h>
54
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>
60
61 /* old 4.4BSD/pmax scsi drivers */
62 #include <pmax/ibus/siireg.h> /* device registers */
63 #include <pmax/ibus/siivar.h> /* softc and prototypes */
64
65 #include <pmax/pmax/machdep.h> /* prom_scsiid prototype */
66
67 /* XXX not in dev/scsipi/scsi_message.h */
68 #define MSG_EXT_MODIFY_DATA_PTR 0x00
69
70 extern struct cfdriver sii_cd;
71
72 /*
73 * MACROS for timing out spin loops.
74 *
75 * Wait until expression is true.
76 *
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.
81 *
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
87 */
88 #define SII_WAIT_UNTIL(var, reg, expr, spincount, cntr) { \
89 u_int tmp = reg; \
90 for (cntr = 0; cntr < spincount; cntr++) { \
91 while (tmp != (var = reg)) \
92 tmp = var; \
93 if (expr) \
94 break; \
95 if (cntr >= 100) \
96 DELAY(100); \
97 } \
98 }
99
100 #ifdef DEBUG
101 int sii_debug = 1;
102 int sii_debug_cmd;
103 int sii_debug_bn;
104 int sii_debug_sz;
105 #define NLOG 16
106 struct sii_log {
107 u_short cstat;
108 u_short dstat;
109 u_short comm;
110 u_short msg;
111 int rlen;
112 int dlen;
113 int target;
114 } sii_log[NLOG], *sii_logp = sii_log;
115 #endif
116
117 static u_char sii_buf[256]; /* used for extended messages */
118
119 #define NORESET 0
120 #define RESET 1
121 #define NOWAIT 0
122 #define WAIT 1
123
124
125 /*
126 * Define a safe address in the SCSI buffer for doing status & message DMA
127 * XXX why not add another field to softc?
128 */
129 #define SII_BUF_ADDR(sc) ((sc)->sc_buf + SII_MAX_DMA_XFER_LENGTH * 14)
130
131 /*
132 * Forward references
133 */
134
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,
143 int size);
144
145 #ifdef DEBUG
146 static void sii_DumpLog(void);
147 #endif
148
149
150 /*
151 * Match driver based on name
152 */
153 void
154 siiattach(struct siisoftc *sc)
155 {
156 int i;
157
158 sc->sc_target = -1; /* no command active */
159
160 /*
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.
164 */
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;
170 }
171
172 sii_Reset(sc, RESET);
173 printf(": target %d\n", sc->sc_regs->id & SII_IDMSK);
174
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;
182
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;
189
190
191 /*
192 * Now try to attach all the sub-devices
193 */
194 config_found(&sc->sc_dev, &sc->sc_channel, scsiprint);
195 }
196
197 /*
198 * Start activity on a SCSI device.
199 * We maintain information on each device separately since devices can
200 * connect/disconnect during an operation.
201 */
202
203 void
204 sii_scsi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg)
205 {
206 struct scsipi_xfer *xs;
207 struct scsipi_periph *periph;
208 struct siisoftc *sc = (void *)chan->chan_adapter->adapt_dev;
209 int target;
210 int s;
211 int count;
212
213 switch (req) {
214 case ADAPTER_REQ_RUN_XFER:
215 xs = arg;
216 periph = xs->xs_periph;
217 target = periph->periph_target;
218 s = splbio();
219 if (sc->sc_cmd[target]) {
220 splx(s);
221 xs->error = XS_RESOURCE_SHORTAGE;
222 scsipi_done(xs);
223 printf("[busy at start]\n");
224 return;
225 }
226 /*
227 * Build a ScsiCmd for this command and start it.
228 */
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);
239 splx(s);
240 if ((xs->xs_control & XS_CTL_POLL) == 0)
241 return;
242 count = xs->timeout;
243 while (count) {
244 if ((xs->xs_status & XS_STS_DONE) != 0)
245 return;
246 siiintr(sc);
247 /* XXX schedule another command? */
248 DELAY(1000);
249 --count;
250 }
251 xs->error = XS_TIMEOUT;
252 scsipi_done(xs);
253 return;
254 case ADAPTER_REQ_GROW_RESOURCES:
255 /* XXX Not supported. */
256 return;
257
258 case ADAPTER_REQ_SET_XFER_MODE:
259 /* XXX Not supported. */
260 return;
261 }
262 }
263
264 /*
265 * Check to see if any SII chips have pending interrupts
266 * and process as appropriate.
267 */
268 int
269 siiintr(void *xxxsc)
270 {
271 struct siisoftc *sc = xxxsc;
272 u_int dstat;
273
274 /*
275 * Find which controller caused the interrupt.
276 */
277 dstat = sc->sc_regs->dstat;
278 if (dstat & (SII_CI | SII_DI)) {
279 sii_DoIntr(sc, dstat);
280 return (0); /* XXX */
281 }
282
283 return (1); /* XXX spurious interrupt? */
284 }
285
286 /*
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.
290 */
291 static void
292 sii_Reset(sc, reset)
293 struct siisoftc* sc;
294 int reset; /* TRUE => reset SCSI bus */
295 {
296 SIIRegs *regs = sc->sc_regs;
297
298 #ifdef DEBUG
299 if (sii_debug > 1)
300 printf("sii: RESET\n");
301 #endif
302 /*
303 * Reset the SII chip.
304 */
305 regs->comm = SII_CHRESET;
306 /*
307 * Set arbitrated bus mode.
308 */
309 regs->csr = SII_HPM;
310 /*
311 * Set host adapter ID (from PROM sciiidN variable).
312 */
313 /* XXX device_unit() abuse */
314 regs->id = SII_ID_IO | prom_scsiid(device_unit(&sc->sc_dev));
315 /*
316 * Enable SII to drive the SCSI bus.
317 */
318 regs->dictrl = SII_PRE;
319 regs->dmctrl = 0;
320
321 if (reset) {
322 int i;
323
324 /*
325 * Assert SCSI bus reset for at least 25 Usec to clear the
326 * world. SII_DO_RST is self clearing.
327 * Delay 250 ms before doing any commands.
328 */
329 regs->comm = SII_DO_RST;
330 wbflush();
331 DELAY(250000);
332
333 /* rearbitrate synchronous offset */
334 for (i = 0; i < SII_NCMD; i++)
335 sc->sc_st[i].dmaReqAck = 0;
336 }
337
338 /*
339 * Clear any pending interrupts from the reset.
340 */
341 regs->cstat = regs->cstat;
342 regs->dstat = regs->dstat;
343 /*
344 * Set up SII for arbitrated bus mode, SCSI parity checking,
345 * Reselect Enable, and Interrupt Enable.
346 */
347 regs->csr = SII_HPM | SII_RSE | SII_PCE | SII_IE;
348 wbflush();
349 }
350
351 /*
352 * Start a SCSI command by sending the cmd data
353 * to a SCSI controller via the SII.
354 * Call the device done proceedure if it can't be started.
355 * NOTE: we should be called with interrupts disabled.
356 */
357 static void
358 sii_StartCmd(sc, target)
359 struct siisoftc *sc; /* which SII to use */
360 int target; /* which command to start */
361 {
362 SIIRegs *regs;
363 ScsiCmd *scsicmd;
364 State *state;
365 u_int status;
366 int error, retval;
367
368 /* if another command is currently in progress, just wait */
369 if (sc->sc_target >= 0)
370 return;
371
372 /* initialize state information for this command */
373 scsicmd = sc->sc_cmd[target];
374 state = &sc->sc_st[target];
375 state->flags = FIRST_DMA;
376 state->prevComm = 0;
377 state->dmalen = 0;
378 state->dmaCurPhase = -1;
379 state->dmaPrevPhase = -1;
380 state->dmaBufIndex = 0;
381 state->cmd = scsicmd->cmd;
382 state->cmdlen = scsicmd->cmdlen;
383 if ((state->buflen = scsicmd->buflen) == 0) {
384 state->dmaDataPhase = -1; /* illegal phase. shouldn't happen */
385 state->buf = (char *)0;
386 } else {
387 state->buf = scsicmd->buf;
388 }
389
390 #ifdef DEBUG
391 if (sii_debug > 1) {
392 printf("sii_StartCmd: %s target %d cmd 0x%x addr %p size %d DMA %d\n",
393 sc->sc_dev.dv_xname,
394 target, scsicmd->cmd[0], scsicmd->buf, scsicmd->buflen,
395 state->dmaDataPhase);
396 }
397 sii_debug_cmd = scsicmd->cmd[0];
398 if (scsicmd->cmd[0] == READ_10 ||
399 scsicmd->cmd[0] == WRITE_10) {
400 sii_debug_bn = (scsicmd->cmd[2] << 24) |
401 (scsicmd->cmd[3] << 16) |
402 (scsicmd->cmd[4] << 8) |
403 scsicmd->cmd[5];
404 sii_debug_sz = (scsicmd->cmd[7] << 8) | scsicmd->cmd[8];
405 } else {
406 sii_debug_bn = 0;
407 sii_debug_sz = 0;
408 }
409 #endif
410
411 /* try to select the target */
412 regs = sc->sc_regs;
413
414 /*
415 * Another device may have selected us; in which case,
416 * this command will be restarted later.
417 */
418 if ((status = regs->dstat) & (SII_CI | SII_DI)) {
419 sii_DoIntr(sc, status);
420 return;
421 }
422
423 sc->sc_target = target;
424 #if 0
425 /* seem to have problems with synchronous transfers */
426 if (scsicmd->flags & SCSICMD_USE_SYNC) {
427 printf("sii_StartCmd: doing extended msg\n"); /* XXX */
428 /*
429 * Setup to send both the identify message and the synchronous
430 * data transfer request.
431 */
432 sii_buf[0] = MSG_IDENTIFYFLAG | MSG_IDENTIFY_DISCFLAG;
433 sii_buf[1] = MSG_EXTENDED;
434 sii_buf[2] = MSG_EXT_SDTR_LEN;
435 sii_buf[3] = MSG_EXT_SDTR;
436 sii_buf[4] = 0;
437 sii_buf[5] = 3; /* maximum SII chip supports */
438
439 state->dmaCurPhase = SII_MSG_OUT_PHASE,
440 state->dmalen = 6;
441 sc->sii_copytobuf((u_short *)sii_buf,
442 (volatile u_short *)SII_BUF_ADDR(sc), 6);
443 regs->slcsr = target;
444 regs->dmctrl = state->dmaReqAck;
445 regs->dmaddrl = (u_short)(SII_BUF_ADDR(sc) >> 1);
446 regs->dmaddrh = (u_short)(SII_BUF_ADDR(sc) >> 17) & 03;
447 regs->dmlotc = 6;
448 regs->comm = SII_DMA | SII_INXFER | SII_SELECT | SII_ATN |
449 SII_CON | SII_MSG_OUT_PHASE;
450 } else
451 #endif
452 {
453 /* do a chained, select with ATN and programmed I/O command */
454 regs->data = MSG_IDENTIFYFLAG | MSG_IDENTIFY_DISCFLAG |
455 scsicmd->lun;
456 regs->slcsr = target;
457 regs->dmctrl = state->dmaReqAck;
458 regs->comm = SII_INXFER | SII_SELECT | SII_ATN | SII_CON |
459 SII_MSG_OUT_PHASE;
460 }
461 wbflush();
462
463 /*
464 * Wait for something to happen
465 * (should happen soon or we would use interrupts).
466 */
467 SII_WAIT_UNTIL(status, regs->cstat, status & (SII_CI | SII_DI),
468 SII_WAIT_COUNT/4, retval);
469
470 /* check to see if we are connected OK */
471 if ((status & (SII_RST | SII_SCH | SII_STATE_MSK)) ==
472 (SII_SCH | SII_CON)) {
473 regs->cstat = status;
474 wbflush();
475
476 #ifdef DEBUG
477 sii_logp->target = target;
478 sii_logp->cstat = status;
479 sii_logp->dstat = 0;
480 sii_logp->comm = regs->comm;
481 sii_logp->msg = -1;
482 sii_logp->rlen = state->buflen;
483 sii_logp->dlen = state->dmalen;
484 if (++sii_logp >= &sii_log[NLOG])
485 sii_logp = sii_log;
486 #endif
487
488 /* wait a short time for command phase */
489 SII_WAIT_UNTIL(status, regs->dstat, status & SII_MIS,
490 SII_WAIT_COUNT, retval);
491 #ifdef DEBUG
492 if (sii_debug > 2)
493 printf("sii_StartCmd: ds %x cnt %d\n", status, retval);
494 #endif
495 if ((status & (SII_CI | SII_MIS | SII_PHASE_MSK)) !=
496 (SII_MIS | SII_CMD_PHASE)) {
497 printf("sii_StartCmd: timeout cs %x ds %x cnt %d\n",
498 regs->cstat, status, retval); /* XXX */
499 /* process interrupt or continue until it happens */
500 if (status & (SII_CI | SII_DI))
501 sii_DoIntr(sc, status);
502 return;
503 }
504 regs->dstat = SII_DNE; /* clear Msg Out DMA done */
505
506 /* send command data */
507 sc->sii_copytobuf((u_short *)state->cmd,
508 (volatile u_short *)state->dmaAddr[0], state->cmdlen);
509 sii_StartDMA(regs, state->dmaCurPhase = SII_CMD_PHASE,
510 state->dmaAddr[0], state->dmalen = scsicmd->cmdlen);
511
512 /* wait a little while for DMA to finish */
513 SII_WAIT_UNTIL(status, regs->dstat, status & (SII_CI | SII_DI),
514 SII_WAIT_COUNT, retval);
515 #ifdef DEBUG
516 if (sii_debug > 2)
517 printf("sii_StartCmd: ds %x, cnt %d\n", status, retval);
518 #endif
519 if (status & (SII_CI | SII_DI))
520 sii_DoIntr(sc, status);
521 #ifdef DEBUG
522 if (sii_debug > 2)
523 printf("sii_StartCmd: DONE ds %x\n", regs->dstat);
524 #endif
525 return;
526 }
527
528 /*
529 * Another device may have selected us; in which case,
530 * this command will be restarted later.
531 */
532 if (status & (SII_CI | SII_DI)) {
533 sii_DoIntr(sc, regs->dstat);
534 return;
535 }
536
537 /*
538 * Disconnect if selection command still in progress.
539 */
540 if (status & SII_SIP) {
541 error = ENXIO; /* device didn't respond */
542 regs->comm = SII_DISCON;
543 wbflush();
544 SII_WAIT_UNTIL(status, regs->cstat,
545 !(status & (SII_CON | SII_SIP)),
546 SII_WAIT_COUNT, retval);
547 } else
548 error = EBUSY; /* couldn't get the bus */
549 #ifdef DEBUG
550 if (sii_debug > 1)
551 printf("sii_StartCmd: Couldn't select target %d error %d\n",
552 target, error);
553 #endif
554 sc->sc_target = -1;
555 regs->cstat = 0xffff;
556 regs->dstat = 0xffff;
557 regs->comm = 0;
558 wbflush();
559 sii_CmdDone(sc, target, error);
560 }
561
562 /*
563 * Process interrupt conditions.
564 */
565 static void
566 sii_DoIntr(struct siisoftc *sc, u_int dstat)
567 {
568 SIIRegs *regs = sc->sc_regs;
569 State *state;
570 u_int cstat;
571 int i, msg;
572 u_int comm;
573
574 again:
575 comm = regs->comm;
576
577 #ifdef DEBUG
578 if (sii_debug > 3)
579 printf("sii_DoIntr: cs %x, ds %x cm %x ",
580 regs->cstat, dstat, comm);
581 sii_logp->target = sc->sc_target;
582 sii_logp->cstat = regs->cstat;
583 sii_logp->dstat = dstat;
584 sii_logp->comm = comm;
585 sii_logp->msg = -1;
586 if (sc->sc_target >= 0) {
587 sii_logp->rlen = sc->sc_st[sc->sc_target].buflen;
588 sii_logp->dlen = sc->sc_st[sc->sc_target].dmalen;
589 } else {
590 sii_logp->rlen = 0;
591 sii_logp->dlen = 0;
592 }
593 if (++sii_logp >= &sii_log[NLOG])
594 sii_logp = sii_log;
595 #endif
596
597 regs->dstat = dstat; /* acknowledge everything */
598 wbflush();
599
600 if (dstat & SII_CI) {
601 /* deglitch cstat register */
602 msg = regs->cstat;
603 while (msg != (cstat = regs->cstat))
604 msg = cstat;
605 regs->cstat = cstat; /* acknowledge everything */
606 wbflush();
607 #ifdef DEBUG
608 if (sii_logp > sii_log)
609 sii_logp[-1].cstat = cstat;
610 else
611 sii_log[NLOG - 1].cstat = cstat;
612 #endif
613
614 /* check for a BUS RESET */
615 if (cstat & SII_RST) {
616 printf("%s: SCSI bus reset!!\n", sc->sc_dev.dv_xname);
617 /* need to flush disconnected commands */
618 for (i = 0; i < SII_NCMD; i++) {
619 if (!sc->sc_cmd[i])
620 continue;
621 sii_CmdDone(sc, i, EIO);
622 }
623 /* rearbitrate synchronous offset */
624 for (i = 0; i < SII_NCMD; i++)
625 sc->sc_st[i].dmaReqAck = 0;
626 sc->sc_target = -1;
627 return;
628 }
629
630 #ifdef notdef
631 /*
632 * Check for a BUS ERROR.
633 * According to DEC, this feature doesn't really work
634 * and to just clear the bit if it's set.
635 */
636 if (cstat & SII_BER) {
637 regs->cstat = SII_BER;
638 wbflush();
639 }
640 #endif
641
642 /* check for state change */
643 if (cstat & SII_SCH) {
644 sii_StateChg(sc, cstat);
645 comm = regs->comm;
646 }
647 }
648
649 /* check for DMA completion */
650 if (dstat & SII_DNE) {
651 u_short *dma;
652 char *buf;
653
654 /*
655 * There is a race condition with SII_SCH. There is a short
656 * window between the time a SII_SCH is seen after a disconnect
657 * and when the SII_SCH is cleared. A reselect can happen
658 * in this window and we will clear the SII_SCH without
659 * processing the reconnect.
660 */
661 if (sc->sc_target < 0) {
662 cstat = regs->cstat;
663 printf("%s: target %d DNE?? dev %d,%d cs %x\n",
664 sc->sc_dev.dv_xname, sc->sc_target,
665 regs->slcsr, regs->destat,
666 cstat); /* XXX */
667 if (cstat & SII_DST) {
668 sc->sc_target = regs->destat;
669 state = &sc->sc_st[sc->sc_target];
670 state->prevComm = 0;
671 } else
672 panic("sc_target 1");
673 }
674 state = &sc->sc_st[sc->sc_target];
675 /* check for a PARITY ERROR */
676 if (dstat & SII_IPE) {
677 state->flags |= PARITY_ERR;
678 printf("%s: Parity error!!\n", sc->sc_dev.dv_xname);
679 goto abort;
680 }
681 /* dmalen = amount left to transfer, i = amount transfered */
682 i = state->dmalen;
683 state->dmalen = 0;
684 state->dmaCurPhase = -1;
685 #ifdef DEBUG
686 if (sii_debug > 4) {
687 printf("DNE: amt %d ", i);
688 if (!(dstat & SII_TCZ))
689 printf("no TCZ?? (%d) ", regs->dmlotc);
690 } else if (!(dstat & SII_TCZ)) {
691 printf("%s: device %d: no TCZ?? (%d)\n",
692 sc->sc_dev.dv_xname, sc->sc_target, regs->dmlotc);
693 sii_DumpLog(); /* XXX */
694 }
695 #endif
696 switch (comm & SII_PHASE_MSK) {
697 case SII_CMD_PHASE:
698 state->cmdlen -= i;
699 break;
700
701 case SII_DATA_IN_PHASE:
702 /* check for more data for the same phase */
703 dma = state->dmaAddr[state->dmaBufIndex];
704 buf = state->buf;
705 state->buf += i;
706 state->buflen -= i;
707 if (state->buflen > 0 && !(dstat & SII_MIS)) {
708 int len;
709
710 /* start reading next chunk */
711 len = state->buflen;
712 if (len > SII_MAX_DMA_XFER_LENGTH)
713 len = SII_MAX_DMA_XFER_LENGTH;
714 state->dmaBufIndex = !state->dmaBufIndex;
715 sii_StartDMA(regs,
716 state->dmaCurPhase = SII_DATA_IN_PHASE,
717 state->dmaAddr[state->dmaBufIndex],
718 state->dmaCnt = state->dmalen = len);
719 dstat &= ~(SII_IBF | SII_TBE);
720 }
721 /* copy in the data */
722 sc->sii_copyfrombuf((volatile u_short *)dma, buf, i);
723 break;
724
725 case SII_DATA_OUT_PHASE:
726 state->dmaBufIndex = !state->dmaBufIndex;
727 state->buf += i;
728 state->buflen -= i;
729
730 /* check for more data for the same phase */
731 if (state->buflen <= 0 || (dstat & SII_MIS))
732 break;
733
734 /* start next chunk */
735 i = state->buflen;
736 if (i > SII_MAX_DMA_XFER_LENGTH) {
737 sii_StartDMA(regs, state->dmaCurPhase =
738 SII_DATA_OUT_PHASE,
739 state->dmaAddr[state->dmaBufIndex],
740 state->dmaCnt = state->dmalen =
741 SII_MAX_DMA_XFER_LENGTH);
742 /* prepare for next chunk */
743 i -= SII_MAX_DMA_XFER_LENGTH;
744 if (i > SII_MAX_DMA_XFER_LENGTH)
745 i = SII_MAX_DMA_XFER_LENGTH;
746 sc->sii_copytobuf((u_short *)(state->buf +
747 SII_MAX_DMA_XFER_LENGTH),
748 (volatile u_short *)
749 state->dmaAddr[!state->dmaBufIndex], i);
750 } else {
751 sii_StartDMA(regs, state->dmaCurPhase =
752 SII_DATA_OUT_PHASE,
753 state->dmaAddr[state->dmaBufIndex],
754 state->dmaCnt = state->dmalen = i);
755 }
756 dstat &= ~(SII_IBF | SII_TBE);
757 }
758 }
759
760 /* check for phase change or another MsgIn/Out */
761 if (dstat & (SII_MIS | SII_IBF | SII_TBE)) {
762 /*
763 * There is a race condition with SII_SCH. There is a short
764 * window between the time a SII_SCH is seen after a disconnect
765 * and when the SII_SCH is cleared. A reselect can happen
766 * in this window and we will clear the SII_SCH without
767 * processing the reconnect.
768 */
769 if (sc->sc_target < 0) {
770 cstat = regs->cstat;
771 printf("%s: target %d MIS?? dev %d,%d cs %x ds %x\n",
772 sc->sc_dev.dv_xname, sc->sc_target,
773 regs->slcsr, regs->destat,
774 cstat, dstat); /* XXX */
775 if (cstat & SII_DST) {
776 sc->sc_target = regs->destat;
777 state = &sc->sc_st[sc->sc_target];
778 state->prevComm = 0;
779 } else {
780 #ifdef DEBUG
781 sii_DumpLog();
782 #endif
783 panic("sc_target 2");
784 }
785 }
786 state = &sc->sc_st[sc->sc_target];
787 switch (dstat & SII_PHASE_MSK) {
788 case SII_CMD_PHASE:
789 if (state->dmaPrevPhase >= 0) {
790 /* restart DMA after disconnect/reconnect */
791 if (state->dmaPrevPhase != SII_CMD_PHASE) {
792 printf("%s: device %d: DMA reselect phase doesn't match\n",
793 sc->sc_dev.dv_xname, sc->sc_target);
794 goto abort;
795 }
796 state->dmaCurPhase = SII_CMD_PHASE;
797 state->dmaPrevPhase = -1;
798 regs->dmaddrl = state->dmaAddrL;
799 regs->dmaddrh = state->dmaAddrH;
800 regs->dmlotc = state->dmaCnt;
801 if (state->dmaCnt & 1)
802 regs->dmabyte = state->dmaByte;
803 regs->comm = SII_DMA | SII_INXFER |
804 (comm & SII_STATE_MSK) | SII_CMD_PHASE;
805 wbflush();
806 #ifdef DEBUG
807 if (sii_debug > 4)
808 printf("Cmd dcnt %d dadr %x ",
809 state->dmaCnt,
810 (state->dmaAddrH << 16) |
811 state->dmaAddrL);
812 #endif
813 } else {
814 /* send command data */
815 i = state->cmdlen;
816 if (i == 0) {
817 printf("%s: device %d: cmd count exceeded\n",
818 sc->sc_dev.dv_xname, sc->sc_target);
819 goto abort;
820 }
821 sc->sii_copytobuf((u_short *)state->cmd,
822 (volatile u_short *)state->dmaAddr[0],
823 i);
824 sii_StartDMA(regs, state->dmaCurPhase =
825 SII_CMD_PHASE, state->dmaAddr[0],
826 state->dmaCnt = state->dmalen = i);
827 }
828 /* wait a short time for XFER complete */
829 SII_WAIT_UNTIL(dstat, regs->dstat,
830 dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i);
831 if (dstat & (SII_CI | SII_DI)) {
832 #ifdef DEBUG
833 if (sii_debug > 4)
834 printf("cnt %d\n", i);
835 else if (sii_debug > 0)
836 printf("sii_DoIntr: cmd wait ds %x cnt %d\n",
837 dstat, i);
838 #endif
839 goto again;
840 }
841 break;
842
843 case SII_DATA_IN_PHASE:
844 case SII_DATA_OUT_PHASE:
845 if (state->cmdlen > 0) {
846 printf("%s: device %d: cmd %x: command data not all sent (%d) 1\n",
847 sc->sc_dev.dv_xname, sc->sc_target,
848 sc->sc_cmd[sc->sc_target]->cmd[0],
849 state->cmdlen);
850 state->cmdlen = 0;
851 #ifdef DEBUG
852 sii_DumpLog();
853 #endif
854 }
855 if (state->dmaPrevPhase >= 0) {
856 /* restart DMA after disconnect/reconnect */
857 if (state->dmaPrevPhase !=
858 (dstat & SII_PHASE_MSK)) {
859 printf("%s: device %d: DMA reselect phase doesn't match\n",
860 sc->sc_dev.dv_xname, sc->sc_target);
861 goto abort;
862 }
863 state->dmaCurPhase = state->dmaPrevPhase;
864 state->dmaPrevPhase = -1;
865 regs->dmaddrl = state->dmaAddrL;
866 regs->dmaddrh = state->dmaAddrH;
867 regs->dmlotc = state->dmaCnt;
868 if (state->dmaCnt & 1)
869 regs->dmabyte = state->dmaByte;
870 regs->comm = SII_DMA | SII_INXFER |
871 (comm & SII_STATE_MSK) |
872 state->dmaCurPhase;
873 wbflush();
874 #ifdef DEBUG
875 if (sii_debug > 4)
876 printf("Data %d dcnt %d dadr %x ",
877 state->dmaDataPhase,
878 state->dmaCnt,
879 (state->dmaAddrH << 16) |
880 state->dmaAddrL);
881 #endif
882 break;
883 }
884 #ifdef DEBUG
885 if (sii_debug > 4) {
886 printf("Data %d ", state->dmaDataPhase);
887 if (sii_debug > 5)
888 printf("\n");
889 }
890 #endif
891 i = state->buflen;
892 if (i == 0) {
893 printf("%s: device %d: data count exceeded\n",
894 sc->sc_dev.dv_xname, sc->sc_target);
895 goto abort;
896 }
897 if (i > SII_MAX_DMA_XFER_LENGTH)
898 i = SII_MAX_DMA_XFER_LENGTH;
899 if ((dstat & SII_PHASE_MSK) == SII_DATA_IN_PHASE) {
900 sii_StartDMA(regs,
901 state->dmaCurPhase = SII_DATA_IN_PHASE,
902 state->dmaAddr[state->dmaBufIndex],
903 state->dmaCnt = state->dmalen = i);
904 break;
905 }
906 /* start first chunk */
907 if (state->flags & FIRST_DMA) {
908 state->flags &= ~FIRST_DMA;
909 sc->sii_copytobuf((u_short *)state->buf,
910 (volatile u_short *)
911 state->dmaAddr[state->dmaBufIndex], i);
912 }
913 sii_StartDMA(regs,
914 state->dmaCurPhase = SII_DATA_OUT_PHASE,
915 state->dmaAddr[state->dmaBufIndex],
916 state->dmaCnt = state->dmalen = i);
917 i = state->buflen - SII_MAX_DMA_XFER_LENGTH;
918 if (i > 0) {
919 /* prepare for next chunk */
920 if (i > SII_MAX_DMA_XFER_LENGTH)
921 i = SII_MAX_DMA_XFER_LENGTH;
922 sc->sii_copytobuf((u_short *)(state->buf +
923 SII_MAX_DMA_XFER_LENGTH),
924 (volatile u_short *)
925 state->dmaAddr[!state->dmaBufIndex], i);
926 }
927 break;
928
929 case SII_STATUS_PHASE:
930 if (state->cmdlen > 0) {
931 printf("%s: device %d: cmd %x: command data not all sent (%d) 2\n",
932 sc->sc_dev.dv_xname, sc->sc_target,
933 sc->sc_cmd[sc->sc_target]->cmd[0],
934 state->cmdlen);
935 state->cmdlen = 0;
936 #ifdef DEBUG
937 sii_DumpLog();
938 #endif
939 }
940
941 /* read amount transfered if DMA didn't finish */
942 if (state->dmalen > 0) {
943 i = state->dmalen - regs->dmlotc;
944 state->dmalen = 0;
945 state->dmaCurPhase = -1;
946 regs->dmlotc = 0;
947 regs->comm = comm &
948 (SII_STATE_MSK | SII_PHASE_MSK);
949 wbflush();
950 regs->dstat = SII_DNE;
951 wbflush();
952 #ifdef DEBUG
953 if (sii_debug > 4)
954 printf("DMA amt %d ", i);
955 #endif
956 switch (comm & SII_PHASE_MSK) {
957 case SII_DATA_IN_PHASE:
958 /* copy in the data */
959 sc->sii_copyfrombuf((volatile u_short*)
960 state->dmaAddr[state->dmaBufIndex],
961 state->buf, i);
962
963 case SII_CMD_PHASE:
964 case SII_DATA_OUT_PHASE:
965 state->buflen -= i;
966 }
967 }
968
969 /* read a one byte status message */
970 state->statusByte = msg =
971 sii_GetByte(regs, SII_STATUS_PHASE, 1);
972 if (msg < 0) {
973 dstat = regs->dstat;
974 goto again;
975 }
976 #ifdef DEBUG
977 if (sii_debug > 4)
978 printf("Status %x ", msg);
979 if (sii_logp > sii_log)
980 sii_logp[-1].msg = msg;
981 else
982 sii_log[NLOG - 1].msg = msg;
983 #endif
984
985 /* do a quick wait for COMMAND_COMPLETE */
986 SII_WAIT_UNTIL(dstat, regs->dstat,
987 dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i);
988 if (dstat & (SII_CI | SII_DI)) {
989 #ifdef DEBUG
990 if (sii_debug > 4)
991 printf("cnt2 %d\n", i);
992 #endif
993 goto again;
994 }
995 break;
996
997 case SII_MSG_IN_PHASE:
998 /*
999 * Save DMA state if DMA didn't finish.
1000 * Be careful not to save state again after reconnect
1001 * and see RESTORE_POINTER message.
1002 * Note that the SII DMA address is not incremented
1003 * as DMA proceeds.
1004 */
1005 if (state->dmaCurPhase >= 0) {
1006 /* save DMA registers */
1007 state->dmaPrevPhase = state->dmaCurPhase;
1008 state->dmaCurPhase = -1;
1009 if (dstat & SII_OBB)
1010 state->dmaByte = regs->dmabyte;
1011 i = regs->dmlotc;
1012 if (i != 0)
1013 i = state->dmaCnt - i;
1014 /* note: no carry from dmaddrl to dmaddrh */
1015 state->dmaAddrL = regs->dmaddrl + i;
1016 state->dmaAddrH = regs->dmaddrh;
1017 state->dmaCnt = regs->dmlotc;
1018 if (state->dmaCnt == 0)
1019 state->dmaCnt = SII_MAX_DMA_XFER_LENGTH;
1020 regs->comm = comm &
1021 (SII_STATE_MSK | SII_PHASE_MSK);
1022 wbflush();
1023 regs->dstat = SII_DNE;
1024 wbflush();
1025 #ifdef DEBUG
1026 if (sii_debug > 4) {
1027 printf("SavP dcnt %d dadr %x ",
1028 state->dmaCnt,
1029 (state->dmaAddrH << 16) |
1030 state->dmaAddrL);
1031 if (((dstat & SII_OBB) != 0) ^
1032 (state->dmaCnt & 1))
1033 printf("OBB??? ");
1034 } else if (sii_debug > 0) {
1035 if (((dstat & SII_OBB) != 0) ^
1036 (state->dmaCnt & 1)) {
1037 printf("sii_DoIntr: OBB??? ds %x cnt %d\n",
1038 dstat, state->dmaCnt);
1039 sii_DumpLog();
1040 }
1041 }
1042 #endif
1043 }
1044
1045 /* read a one byte message */
1046 msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 0);
1047 if (msg < 0) {
1048 dstat = regs->dstat;
1049 goto again;
1050 }
1051 #ifdef DEBUG
1052 if (sii_debug > 4)
1053 printf("MsgIn %x ", msg);
1054 if (sii_logp > sii_log)
1055 sii_logp[-1].msg = msg;
1056 else
1057 sii_log[NLOG - 1].msg = msg;
1058 #endif
1059
1060 /* process message */
1061 switch (msg) {
1062 case MSG_CMDCOMPLETE:
1063 /* acknowledge last byte */
1064 regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1065 (comm & SII_STATE_MSK);
1066 SII_WAIT_UNTIL(dstat, regs->dstat,
1067 dstat & SII_DNE, SII_WAIT_COUNT, i);
1068 regs->dstat = SII_DNE;
1069 wbflush();
1070 msg = sc->sc_target;
1071 sc->sc_target = -1;
1072 /*
1073 * Wait a short time for disconnect.
1074 * Don't be fooled if SII_BER happens first.
1075 * Note: a reselect may happen here.
1076 */
1077 SII_WAIT_UNTIL(cstat, regs->cstat,
1078 cstat & (SII_RST | SII_SCH),
1079 SII_WAIT_COUNT, i);
1080 if ((cstat & (SII_RST | SII_SCH |
1081 SII_STATE_MSK)) == SII_SCH) {
1082 regs->cstat = SII_SCH | SII_BER;
1083 regs->comm = 0;
1084 wbflush();
1085 /*
1086 * Double check that we didn't miss a
1087 * state change between seeing it and
1088 * clearing the SII_SCH bit.
1089 */
1090 i = regs->cstat;
1091 if (!(i & SII_SCH) &&
1092 (i & SII_STATE_MSK) !=
1093 (cstat & SII_STATE_MSK))
1094 sii_StateChg(sc, i);
1095 }
1096 #ifdef DEBUG
1097 if (sii_debug > 4)
1098 printf("cs %x\n", cstat);
1099 #endif
1100 sii_CmdDone(sc, msg, 0);
1101 break;
1102
1103 case MSG_EXTENDED:
1104 /* acknowledge last byte */
1105 regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1106 (comm & SII_STATE_MSK);
1107 SII_WAIT_UNTIL(dstat, regs->dstat,
1108 dstat & SII_DNE, SII_WAIT_COUNT, i);
1109 regs->dstat = SII_DNE;
1110 wbflush();
1111 /* read the message length */
1112 msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 1);
1113 if (msg < 0) {
1114 dstat = regs->dstat;
1115 goto again;
1116 }
1117 sii_buf[1] = msg; /* message length */
1118 if (msg == 0)
1119 msg = 256;
1120 /*
1121 * We read and acknowlege all the bytes
1122 * except the last so we can assert ATN
1123 * if needed before acknowledging the last.
1124 */
1125 for (i = 0; i < msg; i++) {
1126 dstat = sii_GetByte(regs,
1127 SII_MSG_IN_PHASE, i < msg - 1);
1128 if ((int)dstat < 0) {
1129 dstat = regs->dstat;
1130 goto again;
1131 }
1132 sii_buf[i + 2] = dstat;
1133 }
1134
1135 switch (sii_buf[2]) {
1136 case MSG_EXT_MODIFY_DATA_PTR:
1137 /* acknowledge last byte */
1138 regs->comm = SII_INXFER |
1139 SII_MSG_IN_PHASE |
1140 (comm & SII_STATE_MSK);
1141 SII_WAIT_UNTIL(dstat, regs->dstat,
1142 dstat & SII_DNE,
1143 SII_WAIT_COUNT, i);
1144 regs->dstat = SII_DNE;
1145 wbflush();
1146 i = (sii_buf[3] << 24) |
1147 (sii_buf[4] << 16) |
1148 (sii_buf[5] << 8) |
1149 sii_buf[6];
1150 if (state->dmaPrevPhase >= 0) {
1151 state->dmaAddrL += i;
1152 state->dmaCnt -= i;
1153 }
1154 break;
1155
1156 case MSG_EXT_SDTR_LEN:
1157 /*
1158 * Acknowledge last byte and
1159 * signal a request for MSG_OUT.
1160 */
1161 regs->comm = SII_INXFER | SII_ATN |
1162 SII_MSG_IN_PHASE |
1163 (comm & SII_STATE_MSK);
1164 SII_WAIT_UNTIL(dstat, regs->dstat,
1165 dstat & SII_DNE,
1166 SII_WAIT_COUNT, i);
1167 regs->dstat = SII_DNE;
1168 wbflush();
1169 sii_DoSync(regs, state);
1170 break;
1171
1172 default:
1173 reject:
1174 /*
1175 * Acknowledge last byte and
1176 * signal a request for MSG_OUT.
1177 */
1178 regs->comm = SII_INXFER | SII_ATN |
1179 SII_MSG_IN_PHASE |
1180 (comm & SII_STATE_MSK);
1181 SII_WAIT_UNTIL(dstat, regs->dstat,
1182 dstat & SII_DNE,
1183 SII_WAIT_COUNT, i);
1184 regs->dstat = SII_DNE;
1185 wbflush();
1186
1187 /* wait for MSG_OUT phase */
1188 SII_WAIT_UNTIL(dstat, regs->dstat,
1189 dstat & SII_TBE,
1190 SII_WAIT_COUNT, i);
1191
1192 /* send a reject message */
1193 regs->data = MSG_MESSAGE_REJECT;
1194 regs->comm = SII_INXFER |
1195 (regs->cstat & SII_STATE_MSK) |
1196 SII_MSG_OUT_PHASE;
1197 SII_WAIT_UNTIL(dstat, regs->dstat,
1198 dstat & SII_DNE,
1199 SII_WAIT_COUNT, i);
1200 regs->dstat = SII_DNE;
1201 wbflush();
1202 }
1203 break;
1204
1205 case MSG_SAVEDATAPOINTER:
1206 case MSG_RESTOREPOINTERS:
1207 /* acknowledge last byte */
1208 regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1209 (comm & SII_STATE_MSK);
1210 SII_WAIT_UNTIL(dstat, regs->dstat,
1211 dstat & SII_DNE, SII_WAIT_COUNT, i);
1212 regs->dstat = SII_DNE;
1213 wbflush();
1214 /* wait a short time for another msg */
1215 SII_WAIT_UNTIL(dstat, regs->dstat,
1216 dstat & (SII_CI | SII_DI),
1217 SII_WAIT_COUNT, i);
1218 if (dstat & (SII_CI | SII_DI)) {
1219 #ifdef DEBUG
1220 if (sii_debug > 4)
1221 printf("cnt %d\n", i);
1222 #endif
1223 goto again;
1224 }
1225 break;
1226
1227 case MSG_DISCONNECT:
1228 /* acknowledge last byte */
1229 regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1230 (comm & SII_STATE_MSK);
1231 SII_WAIT_UNTIL(dstat, regs->dstat,
1232 dstat & SII_DNE, SII_WAIT_COUNT, i);
1233 regs->dstat = SII_DNE;
1234 wbflush();
1235 state->prevComm = comm;
1236 #ifdef DEBUG
1237 if (sii_debug > 4)
1238 printf("disconn %d ", sc->sc_target);
1239 #endif
1240 /*
1241 * Wait a short time for disconnect.
1242 * Don't be fooled if SII_BER happens first.
1243 * Note: a reselect may happen here.
1244 */
1245 SII_WAIT_UNTIL(cstat, regs->cstat,
1246 cstat & (SII_RST | SII_SCH),
1247 SII_WAIT_COUNT, i);
1248 if ((cstat & (SII_RST | SII_SCH |
1249 SII_STATE_MSK)) != SII_SCH) {
1250 #ifdef DEBUG
1251 if (sii_debug > 4)
1252 printf("cnt %d\n", i);
1253 #endif
1254 dstat = regs->dstat;
1255 goto again;
1256 }
1257 regs->cstat = SII_SCH | SII_BER;
1258 regs->comm = 0;
1259 wbflush();
1260 sc->sc_target = -1;
1261 /*
1262 * Double check that we didn't miss a state
1263 * change between seeing it and clearing
1264 * the SII_SCH bit.
1265 */
1266 i = regs->cstat;
1267 if (!(i & SII_SCH) && (i & SII_STATE_MSK) !=
1268 (cstat & SII_STATE_MSK))
1269 sii_StateChg(sc, i);
1270 break;
1271
1272 case MSG_MESSAGE_REJECT:
1273 /* acknowledge last byte */
1274 regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1275 (comm & SII_STATE_MSK);
1276 SII_WAIT_UNTIL(dstat, regs->dstat,
1277 dstat & SII_DNE, SII_WAIT_COUNT, i);
1278 regs->dstat = SII_DNE;
1279 wbflush();
1280 printf("%s: device %d: message reject.\n",
1281 sc->sc_dev.dv_xname, sc->sc_target);
1282 break;
1283
1284 default:
1285 if (!(msg & MSG_IDENTIFYFLAG)) {
1286 printf("%s: device %d: couldn't handle "
1287 "message 0x%x... rejecting.\n",
1288 sc->sc_dev.dv_xname, sc->sc_target,
1289 msg);
1290 #ifdef DEBUG
1291 sii_DumpLog();
1292 #endif
1293 goto reject;
1294 }
1295 /* acknowledge last byte */
1296 regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1297 (comm & SII_STATE_MSK);
1298 SII_WAIT_UNTIL(dstat, regs->dstat,
1299 dstat & SII_DNE, SII_WAIT_COUNT, i);
1300 regs->dstat = SII_DNE;
1301 wbflush();
1302 /* may want to check LUN some day */
1303 /* wait a short time for another msg */
1304 SII_WAIT_UNTIL(dstat, regs->dstat,
1305 dstat & (SII_CI | SII_DI),
1306 SII_WAIT_COUNT, i);
1307 if (dstat & (SII_CI | SII_DI)) {
1308 #ifdef DEBUG
1309 if (sii_debug > 4)
1310 printf("cnt %d\n", i);
1311 #endif
1312 goto again;
1313 }
1314 }
1315 break;
1316
1317 case SII_MSG_OUT_PHASE:
1318 #ifdef DEBUG
1319 if (sii_debug > 4)
1320 printf("MsgOut\n");
1321 #endif
1322 printf("MsgOut %x\n", state->flags); /* XXX */
1323
1324 /*
1325 * Check for parity error.
1326 * Hardware will automatically set ATN
1327 * to request the device for a MSG_OUT phase.
1328 */
1329 if (state->flags & PARITY_ERR) {
1330 state->flags &= ~PARITY_ERR;
1331 regs->data = MSG_PARITY_ERROR;
1332 } else
1333 regs->data = MSG_NOOP;
1334 regs->comm = SII_INXFER | (comm & SII_STATE_MSK) |
1335 SII_MSG_OUT_PHASE;
1336 wbflush();
1337
1338 /* wait a short time for XFER complete */
1339 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
1340 SII_WAIT_COUNT, i);
1341 #ifdef DEBUG
1342 if (sii_debug > 4)
1343 printf("ds %x i %d\n", dstat, i);
1344 #endif
1345 /* just clear the DNE bit and check errors later */
1346 if (dstat & SII_DNE) {
1347 regs->dstat = SII_DNE;
1348 wbflush();
1349 }
1350 break;
1351
1352 default:
1353 printf("%s: Couldn't handle phase %d... ignoring.\n",
1354 sc->sc_dev.dv_xname, dstat & SII_PHASE_MSK);
1355 }
1356 }
1357
1358 #ifdef DEBUG
1359 if (sii_debug > 3)
1360 printf("\n");
1361 #endif
1362 /*
1363 * Check to make sure we won't be interrupted again.
1364 * Deglitch dstat register.
1365 */
1366 msg = regs->dstat;
1367 while (msg != (dstat = regs->dstat))
1368 msg = dstat;
1369 if (dstat & (SII_CI | SII_DI))
1370 goto again;
1371
1372 if (sc->sc_target < 0) {
1373 /* look for another device that is ready */
1374 for (i = 0; i < SII_NCMD; i++) {
1375 /* don't restart a disconnected command */
1376 if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm)
1377 continue;
1378 sii_StartCmd(sc, i);
1379 break;
1380 }
1381 }
1382 return;
1383
1384 abort:
1385 /* jump here to abort the current command */
1386 printf("%s: device %d: current command terminated\n",
1387 sc->sc_dev.dv_xname, sc->sc_target);
1388 #ifdef DEBUG
1389 sii_DumpLog();
1390 #endif
1391
1392 if ((cstat = regs->cstat) & SII_CON) {
1393 /* try to send an abort msg for awhile */
1394 regs->dstat = SII_DNE;
1395 regs->data = MSG_ABORT;
1396 regs->comm = SII_INXFER | SII_ATN | (cstat & SII_STATE_MSK) |
1397 SII_MSG_OUT_PHASE;
1398 wbflush();
1399 SII_WAIT_UNTIL(dstat, regs->dstat,
1400 (dstat & (SII_DNE | SII_PHASE_MSK)) ==
1401 (SII_DNE | SII_MSG_OUT_PHASE),
1402 2 * SII_WAIT_COUNT, i);
1403 #ifdef DEBUG
1404 if (sii_debug > 0)
1405 printf("Abort: cs %x ds %x i %d\n", cstat, dstat, i);
1406 #endif
1407 if ((dstat & (SII_DNE | SII_PHASE_MSK)) ==
1408 (SII_DNE | SII_MSG_OUT_PHASE)) {
1409 /* disconnect if command in progress */
1410 regs->comm = SII_DISCON;
1411 wbflush();
1412 SII_WAIT_UNTIL(cstat, regs->cstat,
1413 !(cstat & SII_CON), SII_WAIT_COUNT, i);
1414 }
1415 } else {
1416 #ifdef DEBUG
1417 if (sii_debug > 0)
1418 printf("Abort: cs %x\n", cstat);
1419 #endif
1420 }
1421 regs->cstat = 0xffff;
1422 regs->dstat = 0xffff;
1423 regs->comm = 0;
1424 wbflush();
1425
1426 i = sc->sc_target;
1427 sc->sc_target = -1;
1428 sii_CmdDone(sc, i, EIO);
1429 #ifdef DEBUG
1430 if (sii_debug > 4)
1431 printf("sii_DoIntr: after CmdDone target %d\n", sc->sc_target);
1432 #endif
1433 }
1434
1435 static void
1436 sii_StateChg(struct siisoftc *sc, u_int cstat)
1437 {
1438 SIIRegs *regs = sc->sc_regs;
1439 State *state;
1440 int i;
1441
1442 #ifdef DEBUG
1443 if (sii_debug > 4)
1444 printf("SCH: ");
1445 #endif
1446
1447 switch (cstat & SII_STATE_MSK) {
1448 case 0:
1449 /* disconnect */
1450 i = sc->sc_target;
1451 sc->sc_target = -1;
1452 #ifdef DEBUG
1453 if (sii_debug > 4)
1454 printf("disconn %d ", i);
1455 #endif
1456 if (i >= 0 && !sc->sc_st[i].prevComm) {
1457 printf("%s: device %d: spurrious disconnect (%d)\n",
1458 sc->sc_dev.dv_xname, i, regs->slcsr);
1459 sc->sc_st[i].prevComm = 0;
1460 }
1461 break;
1462
1463 case SII_CON:
1464 /* connected as initiator */
1465 i = regs->slcsr;
1466 if (sc->sc_target == i)
1467 break;
1468 printf("%s: device %d: connect to device %d??\n",
1469 sc->sc_dev.dv_xname, sc->sc_target, i);
1470 sc->sc_target = i;
1471 break;
1472
1473 case SII_DST:
1474 /*
1475 * Wait for CON to become valid,
1476 * chip is slow sometimes.
1477 */
1478 SII_WAIT_UNTIL(cstat, regs->cstat,
1479 cstat & SII_CON, SII_WAIT_COUNT, i);
1480 if (!(cstat & SII_CON))
1481 panic("sii resel");
1482 /* FALLTHROUGH */
1483
1484 case SII_CON | SII_DST:
1485 /*
1486 * Its a reselection. Save the ID and wait for
1487 * interrupts to tell us what to do next
1488 * (should be MSG_IN of IDENTIFY).
1489 * NOTE: sc_target may be >= 0 if we were in
1490 * the process of trying to start a command
1491 * and were reselected before the select
1492 * command finished.
1493 */
1494 sc->sc_target = i = regs->destat;
1495 state = &sc->sc_st[i];
1496 regs->comm = SII_CON | SII_DST | SII_MSG_IN_PHASE;
1497 regs->dmctrl = state->dmaReqAck;
1498 wbflush();
1499 if (!state->prevComm) {
1500 printf("%s: device %d: spurious reselection\n",
1501 sc->sc_dev.dv_xname, i);
1502 break;
1503 }
1504 state->prevComm = 0;
1505 #ifdef DEBUG
1506 if (sii_debug > 4)
1507 printf("resel %d ", sc->sc_target);
1508 #endif
1509 break;
1510
1511 #ifdef notyet
1512 case SII_DST | SII_TGT:
1513 case SII_CON | SII_DST | SII_TGT:
1514 /* connected as target */
1515 printf("%s: Selected by device %d as target!!\n",
1516 sc->sc_dev.dv_xname, regs->destat);
1517 regs->comm = SII_DISCON;
1518 wbflush();
1519 SII_WAIT_UNTIL(!(regs->cstat & SII_CON),
1520 SII_WAIT_COUNT, i);
1521 regs->cstat = 0xffff;
1522 regs->dstat = 0xffff;
1523 regs->comm = 0;
1524 break;
1525 #endif
1526
1527 default:
1528 printf("%s: Unknown state change (cs %x)!!\n",
1529 sc->sc_dev.dv_xname, cstat);
1530 #ifdef DEBUG
1531 sii_DumpLog();
1532 #endif
1533 }
1534 }
1535
1536 /*
1537 * Read one byte of data.
1538 * If 'ack' is true, acknowledge the byte.
1539 */
1540 static int
1541 sii_GetByte(regs, phase, ack)
1542 SIIRegs *regs;
1543 int phase, ack;
1544 {
1545 u_int dstat;
1546 u_int state;
1547 int i;
1548 int data;
1549
1550 dstat = regs->dstat;
1551 state = regs->cstat & SII_STATE_MSK;
1552 i = -1;
1553 if (!(dstat & SII_IBF) || (dstat & SII_MIS)) {
1554 regs->comm = state | phase;
1555 wbflush();
1556 /* wait a short time for IBF */
1557 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_IBF,
1558 SII_WAIT_COUNT, i);
1559 #ifdef DEBUG
1560 if (!(dstat & SII_IBF))
1561 printf("status no IBF\n");
1562 #endif
1563 }
1564 if (dstat & SII_DNE) { /* XXX */
1565 printf("sii_GetByte: DNE set 5\n");
1566 #ifdef DEBUG
1567 sii_DumpLog();
1568 #endif
1569 regs->dstat = SII_DNE;
1570 }
1571 data = regs->data;
1572 /* check for parity error */
1573 if (dstat & SII_IPE) {
1574 #ifdef DEBUG
1575 if (sii_debug > 4)
1576 printf("cnt0 %d\n", i);
1577 #endif
1578 printf("sii_GetByte: data %x ?? ds %x cm %x i %d\n",
1579 data, dstat, regs->comm, i); /* XXX */
1580 data = -1;
1581 ack = 1;
1582 }
1583
1584 if (ack) {
1585 regs->comm = SII_INXFER | state | phase;
1586 wbflush();
1587
1588 /* wait a short time for XFER complete */
1589 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
1590 SII_WAIT_COUNT, i);
1591
1592 /* clear the DNE */
1593 if (dstat & SII_DNE) {
1594 regs->dstat = SII_DNE;
1595 wbflush();
1596 }
1597 }
1598
1599 return (data);
1600 }
1601
1602 /*
1603 * Exchange messages to initiate synchronous data transfers.
1604 */
1605 static void
1606 sii_DoSync(SIIRegs *regs, State *state)
1607 {
1608 u_int dstat, comm;
1609 int i, j;
1610 u_int len;
1611
1612 #ifdef DEBUG
1613 if (sii_debug)
1614 printf("sii_DoSync: len %d per %d req/ack %d\n",
1615 sii_buf[1], sii_buf[3], sii_buf[4]);
1616 #endif
1617
1618 /* SII chip can only handle a minimum transfer period of ??? */
1619 if (sii_buf[3] < 64)
1620 sii_buf[3] = 64;
1621 /* SII chip can only handle a maximum REQ/ACK offset of 3 */
1622 len = sii_buf[4];
1623 if (len > 3)
1624 len = 3;
1625
1626 sii_buf[0] = MSG_EXTENDED;
1627 sii_buf[1] = MSG_EXT_SDTR_LEN;
1628 sii_buf[2] = MSG_EXT_SDTR;
1629 sii_buf[4] = len;
1630 #if 1
1631 comm = SII_INXFER | SII_ATN | SII_MSG_OUT_PHASE |
1632 (regs->cstat & SII_STATE_MSK);
1633 regs->comm = comm & ~SII_INXFER;
1634 for (j = 0; j < 5; j++) {
1635 /* wait for target to request the next byte */
1636 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_TBE,
1637 SII_WAIT_COUNT, i);
1638 if (!(dstat & SII_TBE) ||
1639 (dstat & SII_PHASE_MSK) != SII_MSG_OUT_PHASE) {
1640 printf("sii_DoSync: TBE? ds %x cm %x i %d\n",
1641 dstat, comm, i); /* XXX */
1642 return;
1643 }
1644
1645 /* the last message byte should have ATN off */
1646 if (j == 4)
1647 comm &= ~SII_ATN;
1648
1649 regs->data = sii_buf[j];
1650 regs->comm = comm;
1651 wbflush();
1652
1653 /* wait a short time for XFER complete */
1654 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
1655 SII_WAIT_COUNT, i);
1656
1657 if (!(dstat & SII_DNE)) {
1658 printf("sii_DoSync: DNE? ds %x cm %x i %d\n",
1659 dstat, comm, i); /* XXX */
1660 return;
1661 }
1662
1663 /* clear the DNE, other errors handled later */
1664 regs->dstat = SII_DNE;
1665 wbflush();
1666 }
1667 #else /* 0 */
1668 sc->sii_copytobuf((u_short *)sii_buf,
1669 (volatile u_short *)SII_BUF_ADDR(sc), 5);
1670 printf("sii_DoSync: %x %x %x ds %x\n",
1671 ((volatile u_short *)SII_BUF_ADDR(sc))[0],
1672 ((volatile u_short *)SII_BUF_ADDR(sc))[2],
1673 ((volatile u_short *)SII_BUF_ADDR(sc))[4],
1674 regs->dstat); /* XXX */
1675 regs->dmaddrl = (u_short)(SII_BUF_ADDR(sc) >> 1);
1676 regs->dmaddrh = (u_short)(SII_BUF_ADDR(sc) >> 17) & 03;
1677 regs->dmlotc = 5;
1678 regs->comm = SII_DMA | SII_INXFER | SII_ATN |
1679 (regs->cstat & SII_STATE_MSK) | SII_MSG_OUT_PHASE;
1680 wbflush();
1681
1682 /* wait a short time for XFER complete */
1683 SII_WAIT_UNTIL(dstat, regs->dstat,
1684 (dstat & (SII_DNE | SII_TCZ)) == (SII_DNE | SII_TCZ),
1685 SII_WAIT_COUNT, i);
1686
1687 if ((dstat & (SII_DNE | SII_TCZ)) != (SII_DNE | SII_TCZ)) {
1688 printf("sii_DoSync: ds %x cm %x i %d lotc %d\n",
1689 dstat, regs->comm, i, regs->dmlotc); /* XXX */
1690 sii_DumpLog(); /* XXX */
1691 return;
1692 }
1693 /* clear the DNE, other errors handled later */
1694 regs->dstat = SII_DNE;
1695 wbflush();
1696 #endif /* 0 */
1697
1698 #if 0
1699 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & (SII_CI | SII_DI),
1700 SII_WAIT_COUNT, i);
1701 printf("sii_DoSync: ds %x cm %x i %d lotc %d\n",
1702 dstat, regs->comm, i, regs->dmlotc); /* XXX */
1703 #endif
1704
1705 state->dmaReqAck = len;
1706 }
1707
1708 /*
1709 * Issue the sequence of commands to the controller to start DMA.
1710 * NOTE: the data buffer should be word-aligned for DMA out.
1711 */
1712 static void
1713 sii_StartDMA(regs, phase, dmaAddr, size)
1714 SIIRegs *regs; /* which SII to use */
1715 int phase; /* phase to send/receive data */
1716 u_short *dmaAddr; /* DMA buffer address */
1717 int size; /* # of bytes to transfer */
1718 {
1719
1720 if (regs->dstat & SII_DNE) { /* XXX */
1721 regs->dstat = SII_DNE;
1722 printf("sii_StartDMA: DNE set\n");
1723 #ifdef DEBUG
1724 sii_DumpLog();
1725 #endif
1726 }
1727 regs->dmaddrl = ((u_long)dmaAddr >> 1);
1728 regs->dmaddrh = ((u_long)dmaAddr >> 17) & 03;
1729 regs->dmlotc = size;
1730 regs->comm = SII_DMA | SII_INXFER | (regs->cstat & SII_STATE_MSK) |
1731 phase;
1732 wbflush();
1733
1734 #ifdef DEBUG
1735 if (sii_debug > 5) {
1736 printf("sii_StartDMA: cs 0x%x, ds 0x%x, cm 0x%x, size %d\n",
1737 regs->cstat, regs->dstat, regs->comm, size);
1738 }
1739 #endif
1740 }
1741
1742 /*
1743 * Call the device driver's 'done' routine to let it know the command is done.
1744 * The 'done' routine may try to start another command.
1745 * To be fair, we should start pending commands for other devices
1746 * before allowing the same device to start another command.
1747 */
1748 static void
1749 sii_CmdDone(sc, target, error)
1750 struct siisoftc *sc; /* which SII to use */
1751 int target; /* which device is done */
1752 int error; /* error code if any errors */
1753 {
1754 ScsiCmd *scsicmd;
1755 int i;
1756
1757 scsicmd = sc->sc_cmd[target];
1758 #ifdef DIAGNOSTIC
1759 if (target < 0 || !scsicmd)
1760 panic("sii_CmdDone");
1761 #endif
1762 sc->sc_cmd[target] = (ScsiCmd *)0;
1763 #ifdef DEBUG
1764 if (sii_debug > 1) {
1765 printf("sii_CmdDone: %s target %d cmd %x err %d resid %d\n",
1766 sc->sc_dev.dv_xname,
1767 target, scsicmd->cmd[0], error, sc->sc_st[target].buflen);
1768 }
1769 #endif
1770
1771 /* look for another device that is ready */
1772 for (i = 0; i < SII_NCMD; i++) {
1773 /* don't restart a disconnected command */
1774 if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm)
1775 continue;
1776 sii_StartCmd(sc, i);
1777 break;
1778 }
1779
1780 sc->sc_xs[target]->status = sc->sc_st[target].statusByte;
1781 /*
1782 * Convert SII driver error code to MI SCSI XS_*.
1783 */
1784 switch (error) {
1785 case 0:
1786 sc->sc_xs[target]->error = XS_NOERROR;
1787 break;
1788 case ENXIO:
1789 sc->sc_xs[target]->error = XS_SELTIMEOUT;
1790 break;
1791 case EBUSY:
1792 sc->sc_xs[target]->error = XS_BUSY;
1793 break;
1794 case EIO:
1795 sc->sc_xs[target]->error = XS_DRIVER_STUFFUP;
1796 break;
1797 default:
1798 sc->sc_xs[target]->error = XS_DRIVER_STUFFUP;
1799 }
1800 sc->sc_xs[target]->resid = sc->sc_st[target].buflen;
1801 scsipi_done(sc->sc_xs[target]);
1802 }
1803
1804 #ifdef DEBUG
1805 static void
1806 sii_DumpLog()
1807 {
1808 struct sii_log *lp;
1809
1810 printf("sii: cmd %x bn %d cnt %d\n", sii_debug_cmd, sii_debug_bn,
1811 sii_debug_sz);
1812 lp = sii_logp;
1813 do {
1814 printf("target %d cs %x ds %x cm %x msg %x rlen %x dlen %x\n",
1815 lp->target, lp->cstat, lp->dstat, lp->comm, lp->msg,
1816 lp->rlen, lp->dlen);
1817 if (++lp >= &sii_log[NLOG])
1818 lp = sii_log;
1819 } while (lp != sii_logp);
1820 }
1821 #endif
1822