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