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