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