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