1/* $NetBSD: sii.c,v 1.9 2011/06/04 01:31:23 tsutsui 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.9 2011/06/04 01:31:23 tsutsui 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 <mips/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 70extern 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 101int sii_debug = 1; 102int sii_debug_cmd; 103int sii_debug_bn; 104int sii_debug_sz; 105#define NLOG 16 106struct 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 117static 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 135static void sii_Reset(struct siisoftc *sc, int resetbus); 136static void sii_StartCmd(struct siisoftc *sc, int target); 137static void sii_CmdDone(struct siisoftc *sc, int target, int error); 138static void sii_DoIntr(struct siisoftc *sc, u_int dstat); 139static void sii_StateChg(struct siisoftc *sc, u_int cstat); 140static int sii_GetByte(SIIRegs *regs, int phase, int ack); 141static void sii_DoSync(SIIRegs *regs, State *state); 142static void sii_StartDMA(SIIRegs *regs, int phase, u_short *dmaAddr, 143 int size); 144 145#ifdef DEBUG 146static void sii_DumpLog(void); 147#endif 148 149 150/* 151 * Match driver based on name 152 */ 153void 154siiattach(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 203void 204sii_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; 209 int target; 210 int s; 211 int count; 212 213 sc = device_private(chan->chan_adapter->adapt_dev); 214 215 switch (req) { 216 case ADAPTER_REQ_RUN_XFER: 217 xs = arg; 218 periph = xs->xs_periph; 219 target = periph->periph_target; 220 s = splbio(); 221 if (sc->sc_cmd[target]) { 222 splx(s); 223 xs->error = XS_RESOURCE_SHORTAGE; 224 scsipi_done(xs); 225 printf("[busy at start]\n"); 226 return; 227 } 228 /* 229 * Build a ScsiCmd for this command and start it. 230 */ 231 sc->sc_xs[target] = xs; 232 sc->sc_cmd[target] = &sc->sc_cmd_fake[target]; /* XXX */ 233 sc->sc_cmd[target]->unit = 0; 234 sc->sc_cmd[target]->flags = 0; 235 sc->sc_cmd[target]->buflen = xs->datalen; 236 sc->sc_cmd[target]->buf = xs->data; 237 sc->sc_cmd[target]->cmdlen = xs->cmdlen; 238 sc->sc_cmd[target]->cmd = (u_char *)xs->cmd; 239 sc->sc_cmd[target]->lun = xs->xs_periph->periph_lun; 240 sii_StartCmd(sc, target); 241 splx(s); 242 if ((xs->xs_control & XS_CTL_POLL) == 0) 243 return; 244 count = xs->timeout; 245 while (count) { 246 if ((xs->xs_status & XS_STS_DONE) != 0) 247 return; 248 siiintr(sc); 249 /* XXX schedule another command? */ 250 DELAY(1000); 251 --count; 252 } 253 xs->error = XS_TIMEOUT; 254 scsipi_done(xs); 255 return; 256 case ADAPTER_REQ_GROW_RESOURCES: 257 /* XXX Not supported. */ 258 return; 259 260 case ADAPTER_REQ_SET_XFER_MODE: 261 /* XXX Not supported. */ 262 return; 263 } 264} 265 266/* 267 * Check to see if any SII chips have pending interrupts 268 * and process as appropriate. 269 */ 270int 271siiintr(void *xxxsc) 272{ 273 struct siisoftc *sc = xxxsc; 274 u_int dstat; 275 276 /* 277 * Find which controller caused the interrupt. 278 */ 279 dstat = sc->sc_regs->dstat; 280 if (dstat & (SII_CI | SII_DI)) { 281 sii_DoIntr(sc, dstat); 282 return (0); /* XXX */ 283 } 284 285 return (1); /* XXX spurious interrupt? */ 286} 287 288/* 289 * Reset the SII chip and do a SCSI reset if 'reset' is true. 290 * NOTE: if !cold && reset, should probably probe for devices 291 * since a SCSI bus reset will set UNIT_ATTENTION. 292 */ 293static void 294sii_Reset(struct siisoftc* sc, int reset) 295 /* reset: TRUE => reset SCSI bus */ 296{ 297 SIIRegs *regs = sc->sc_regs; 298 299#ifdef DEBUG 300 if (sii_debug > 1) 301 printf("sii: RESET\n"); 302#endif 303 /* 304 * Reset the SII chip. 305 */ 306 regs->comm = SII_CHRESET; 307 /* 308 * Set arbitrated bus mode. 309 */ 310 regs->csr = SII_HPM; 311 /* 312 * Set host adapter ID (from PROM sciiidN variable). 313 */ 314 /* XXX device_unit() abuse */ 315 regs->id = SII_ID_IO | prom_scsiid(device_unit(sc->sc_dev)); 316 /* 317 * Enable SII to drive the SCSI bus. 318 */ 319 regs->dictrl = SII_PRE; 320 regs->dmctrl = 0; 321 322 if (reset) { 323 int i; 324 325 /* 326 * Assert SCSI bus reset for at least 25 Usec to clear the 327 * world. SII_DO_RST is self clearing. 328 * Delay 250 ms before doing any commands. 329 */ 330 regs->comm = SII_DO_RST; 331 wbflush(); 332 DELAY(250000); 333 334 /* rearbitrate synchronous offset */ 335 for (i = 0; i < SII_NCMD; i++) 336 sc->sc_st[i].dmaReqAck = 0; 337 } 338 339 /* 340 * Clear any pending interrupts from the reset. 341 */ 342 regs->cstat = regs->cstat; 343 regs->dstat = regs->dstat; 344 /* 345 * Set up SII for arbitrated bus mode, SCSI parity checking, 346 * Reselect Enable, and Interrupt Enable. 347 */ 348 regs->csr = SII_HPM | SII_RSE | SII_PCE | SII_IE; 349 wbflush(); 350} 351 352/* 353 * Start a SCSI command by sending the cmd data 354 * to a SCSI controller via the SII. 355 * Call the device done proceedure if it can't be started. 356 * NOTE: we should be called with interrupts disabled. 357 */ 358static void 359sii_StartCmd(struct siisoftc *sc, int target) 360 /* sc: which SII to use */ 361 /* target: which command to start */ 362{ 363 SIIRegs *regs; 364 ScsiCmd *scsicmd; 365 State *state; 366 u_int status; 367 int error, retval; 368 369 /* if another command is currently in progress, just wait */ 370 if (sc->sc_target >= 0) 371 return; 372 373 /* initialize state information for this command */ 374 scsicmd = sc->sc_cmd[target]; 375 state = &sc->sc_st[target]; 376 state->flags = FIRST_DMA; 377 state->prevComm = 0; 378 state->dmalen = 0; 379 state->dmaCurPhase = -1; 380 state->dmaPrevPhase = -1; 381 state->dmaBufIndex = 0; 382 state->cmd = scsicmd->cmd; 383 state->cmdlen = scsicmd->cmdlen; 384 if ((state->buflen = scsicmd->buflen) == 0) { 385 state->dmaDataPhase = -1; /* illegal phase. shouldn't happen */ 386 state->buf = (char *)0; 387 } else { 388 state->buf = scsicmd->buf; 389 } 390 391#ifdef DEBUG 392 if (sii_debug > 1) { 393 printf("sii_StartCmd: %s target %d cmd 0x%x addr %p size %d DMA %d\n", 394 device_xname(sc->sc_dev), 395 target, scsicmd->cmd[0], scsicmd->buf, scsicmd->buflen, 396 state->dmaDataPhase); 397 } 398 sii_debug_cmd = scsicmd->cmd[0]; 399 if (scsicmd->cmd[0] == READ_10 || 400 scsicmd->cmd[0] == WRITE_10) { 401 sii_debug_bn = (scsicmd->cmd[2] << 24) | 402 (scsicmd->cmd[3] << 16) | 403 (scsicmd->cmd[4] << 8) | 404 scsicmd->cmd[5]; 405 sii_debug_sz = (scsicmd->cmd[7] << 8) | scsicmd->cmd[8]; 406 } else { 407 sii_debug_bn = 0; 408 sii_debug_sz = 0; 409 } 410#endif 411 412 /* try to select the target */ 413 regs = sc->sc_regs; 414 415 /* 416 * Another device may have selected us; in which case, 417 * this command will be restarted later. 418 */ 419 if ((status = regs->dstat) & (SII_CI | SII_DI)) { 420 sii_DoIntr(sc, status); 421 return; 422 } 423 424 sc->sc_target = target; 425#if 0 426 /* seem to have problems with synchronous transfers */ 427 if (scsicmd->flags & SCSICMD_USE_SYNC) { 428 printf("sii_StartCmd: doing extended msg\n"); /* XXX */ 429 /* 430 * Setup to send both the identify message and the synchronous 431 * data transfer request. 432 */ 433 sii_buf[0] = MSG_IDENTIFYFLAG | MSG_IDENTIFY_DISCFLAG; 434 sii_buf[1] = MSG_EXTENDED; 435 sii_buf[2] = MSG_EXT_SDTR_LEN; 436 sii_buf[3] = MSG_EXT_SDTR; 437 sii_buf[4] = 0; 438 sii_buf[5] = 3; /* maximum SII chip supports */ 439 440 state->dmaCurPhase = SII_MSG_OUT_PHASE, 441 state->dmalen = 6; 442 sc->sii_copytobuf((u_short *)sii_buf, 443 (volatile u_short *)SII_BUF_ADDR(sc), 6); 444 regs->slcsr = target; 445 regs->dmctrl = state->dmaReqAck; 446 regs->dmaddrl = (u_short)(SII_BUF_ADDR(sc) >> 1); 447 regs->dmaddrh = (u_short)(SII_BUF_ADDR(sc) >> 17) & 03; 448 regs->dmlotc = 6; 449 regs->comm = SII_DMA | SII_INXFER | SII_SELECT | SII_ATN | 450 SII_CON | SII_MSG_OUT_PHASE; 451 } else 452#endif 453 { 454 /* do a chained, select with ATN and programmed I/O command */ 455 regs->data = MSG_IDENTIFYFLAG | MSG_IDENTIFY_DISCFLAG | 456 scsicmd->lun; 457 regs->slcsr = target; 458 regs->dmctrl = state->dmaReqAck; 459 regs->comm = SII_INXFER | SII_SELECT | SII_ATN | SII_CON | 460 SII_MSG_OUT_PHASE; 461 } 462 wbflush(); 463 464 /* 465 * Wait for something to happen 466 * (should happen soon or we would use interrupts). 467 */ 468 SII_WAIT_UNTIL(status, regs->cstat, status & (SII_CI | SII_DI), 469 SII_WAIT_COUNT/4, retval); 470 471 /* check to see if we are connected OK */ 472 if ((status & (SII_RST | SII_SCH | SII_STATE_MSK)) == 473 (SII_SCH | SII_CON)) { 474 regs->cstat = status; 475 wbflush(); 476 477#ifdef DEBUG 478 sii_logp->target = target; 479 sii_logp->cstat = status; 480 sii_logp->dstat = 0; 481 sii_logp->comm = regs->comm; 482 sii_logp->msg = -1; 483 sii_logp->rlen = state->buflen; 484 sii_logp->dlen = state->dmalen; 485 if (++sii_logp >= &sii_log[NLOG]) 486 sii_logp = sii_log; 487#endif 488 489 /* wait a short time for command phase */ 490 SII_WAIT_UNTIL(status, regs->dstat, status & SII_MIS, 491 SII_WAIT_COUNT, retval); 492#ifdef DEBUG 493 if (sii_debug > 2) 494 printf("sii_StartCmd: ds %x cnt %d\n", status, retval); 495#endif 496 if ((status & (SII_CI | SII_MIS | SII_PHASE_MSK)) != 497 (SII_MIS | SII_CMD_PHASE)) { 498 printf("sii_StartCmd: timeout cs %x ds %x cnt %d\n", 499 regs->cstat, status, retval); /* XXX */ 500 /* process interrupt or continue until it happens */ 501 if (status & (SII_CI | SII_DI)) 502 sii_DoIntr(sc, status); 503 return; 504 } 505 regs->dstat = SII_DNE; /* clear Msg Out DMA done */ 506 507 /* send command data */ 508 sc->sii_copytobuf((u_short *)state->cmd, 509 (volatile u_short *)state->dmaAddr[0], state->cmdlen); 510 sii_StartDMA(regs, state->dmaCurPhase = SII_CMD_PHASE, 511 state->dmaAddr[0], state->dmalen = scsicmd->cmdlen); 512 513 /* wait a little while for DMA to finish */ 514 SII_WAIT_UNTIL(status, regs->dstat, status & (SII_CI | SII_DI), 515 SII_WAIT_COUNT, retval); 516#ifdef DEBUG 517 if (sii_debug > 2) 518 printf("sii_StartCmd: ds %x, cnt %d\n", status, retval); 519#endif 520 if (status & (SII_CI | SII_DI)) 521 sii_DoIntr(sc, status); 522#ifdef DEBUG 523 if (sii_debug > 2) 524 printf("sii_StartCmd: DONE ds %x\n", regs->dstat); 525#endif 526 return; 527 } 528 529 /* 530 * Another device may have selected us; in which case, 531 * this command will be restarted later. 532 */ 533 if (status & (SII_CI | SII_DI)) { 534 sii_DoIntr(sc, regs->dstat); 535 return; 536 } 537 538 /* 539 * Disconnect if selection command still in progress. 540 */ 541 if (status & SII_SIP) { 542 error = ENXIO; /* device didn't respond */ 543 regs->comm = SII_DISCON; 544 wbflush(); 545 SII_WAIT_UNTIL(status, regs->cstat, 546 !(status & (SII_CON | SII_SIP)), 547 SII_WAIT_COUNT, retval); 548 } else 549 error = EBUSY; /* couldn't get the bus */ 550#ifdef DEBUG 551 if (sii_debug > 1) 552 printf("sii_StartCmd: Couldn't select target %d error %d\n", 553 target, error); 554#endif 555 sc->sc_target = -1; 556 regs->cstat = 0xffff; 557 regs->dstat = 0xffff; 558 regs->comm = 0; 559 wbflush(); 560 sii_CmdDone(sc, target, error); 561} 562 563/* 564 * Process interrupt conditions. 565 */ 566static void 567sii_DoIntr(struct siisoftc *sc, u_int dstat) 568{ 569 SIIRegs *regs = sc->sc_regs; 570 State *state; 571 u_int cstat; 572 int i, msg; 573 u_int comm; 574 575again: 576 comm = regs->comm; 577 578#ifdef DEBUG 579 if (sii_debug > 3) 580 printf("sii_DoIntr: cs %x, ds %x cm %x ", 581 regs->cstat, dstat, comm); 582 sii_logp->target = sc->sc_target; 583 sii_logp->cstat = regs->cstat; 584 sii_logp->dstat = dstat; 585 sii_logp->comm = comm; 586 sii_logp->msg = -1; 587 if (sc->sc_target >= 0) { 588 sii_logp->rlen = sc->sc_st[sc->sc_target].buflen; 589 sii_logp->dlen = sc->sc_st[sc->sc_target].dmalen; 590 } else { 591 sii_logp->rlen = 0; 592 sii_logp->dlen = 0; 593 } 594 if (++sii_logp >= &sii_log[NLOG]) 595 sii_logp = sii_log; 596#endif 597 598 regs->dstat = dstat; /* acknowledge everything */ 599 wbflush(); 600 601 if (dstat & SII_CI) { 602 /* deglitch cstat register */ 603 msg = regs->cstat; 604 while (msg != (cstat = regs->cstat)) 605 msg = cstat; 606 regs->cstat = cstat; /* acknowledge everything */ 607 wbflush(); 608#ifdef DEBUG 609 if (sii_logp > sii_log) 610 sii_logp[-1].cstat = cstat; 611 else 612 sii_log[NLOG - 1].cstat = cstat; 613#endif 614 615 /* check for a BUS RESET */ 616 if (cstat & SII_RST) { 617 printf("%s: SCSI bus reset!!\n", 618 device_xname(sc->sc_dev)); 619 /* need to flush disconnected commands */ 620 for (i = 0; i < SII_NCMD; i++) { 621 if (!sc->sc_cmd[i]) 622 continue; 623 sii_CmdDone(sc, i, EIO); 624 } 625 /* rearbitrate synchronous offset */ 626 for (i = 0; i < SII_NCMD; i++) 627 sc->sc_st[i].dmaReqAck = 0; 628 sc->sc_target = -1; 629 return; 630 } 631 632#ifdef notdef 633 /* 634 * Check for a BUS ERROR. 635 * According to DEC, this feature doesn't really work 636 * and to just clear the bit if it's set. 637 */ 638 if (cstat & SII_BER) { 639 regs->cstat = SII_BER; 640 wbflush(); 641 } 642#endif 643 644 /* check for state change */ 645 if (cstat & SII_SCH) { 646 sii_StateChg(sc, cstat); 647 comm = regs->comm; 648 } 649 } 650 651 /* check for DMA completion */ 652 if (dstat & SII_DNE) { 653 u_short *dma; 654 char *buf; 655 656 /* 657 * There is a race condition with SII_SCH. There is a short 658 * window between the time a SII_SCH is seen after a disconnect 659 * and when the SII_SCH is cleared. A reselect can happen 660 * in this window and we will clear the SII_SCH without 661 * processing the reconnect. 662 */ 663 if (sc->sc_target < 0) { 664 cstat = regs->cstat; 665 printf("%s: target %d DNE?? dev %d,%d cs %x\n", 666 device_xname(sc->sc_dev), sc->sc_target, 667 regs->slcsr, regs->destat, 668 cstat); /* XXX */ 669 if (cstat & SII_DST) { 670 sc->sc_target = regs->destat; 671 state = &sc->sc_st[sc->sc_target]; 672 state->prevComm = 0; 673 } else 674 panic("sc_target 1"); 675 } 676 state = &sc->sc_st[sc->sc_target]; 677 /* check for a PARITY ERROR */ 678 if (dstat & SII_IPE) { 679 state->flags |= PARITY_ERR; 680 printf("%s: Parity error!!\n", 681 device_xname(sc->sc_dev)); 682 goto abort; 683 } 684 /* dmalen = amount left to transfer, i = amount transfered */ 685 i = state->dmalen; 686 state->dmalen = 0; 687 state->dmaCurPhase = -1; 688#ifdef DEBUG 689 if (sii_debug > 4) { 690 printf("DNE: amt %d ", i); 691 if (!(dstat & SII_TCZ)) 692 printf("no TCZ?? (%d) ", regs->dmlotc); 693 } else if (!(dstat & SII_TCZ)) { 694 printf("%s: device %d: no TCZ?? (%d)\n", 695 device_xname(sc->sc_dev), 696 sc->sc_target, regs->dmlotc); 697 sii_DumpLog(); /* XXX */ 698 } 699#endif 700 switch (comm & SII_PHASE_MSK) { 701 case SII_CMD_PHASE: 702 state->cmdlen -= i; 703 break; 704 705 case SII_DATA_IN_PHASE: 706 /* check for more data for the same phase */ 707 dma = state->dmaAddr[state->dmaBufIndex]; 708 buf = state->buf; 709 state->buf += i; 710 state->buflen -= i; 711 if (state->buflen > 0 && !(dstat & SII_MIS)) { 712 int len; 713 714 /* start reading next chunk */ 715 len = state->buflen; 716 if (len > SII_MAX_DMA_XFER_LENGTH) 717 len = SII_MAX_DMA_XFER_LENGTH; 718 state->dmaBufIndex = !state->dmaBufIndex; 719 sii_StartDMA(regs, 720 state->dmaCurPhase = SII_DATA_IN_PHASE, 721 state->dmaAddr[state->dmaBufIndex], 722 state->dmaCnt = state->dmalen = len); 723 dstat &= ~(SII_IBF | SII_TBE); 724 } 725 /* copy in the data */ 726 sc->sii_copyfrombuf((volatile u_short *)dma, buf, i); 727 break; 728 729 case SII_DATA_OUT_PHASE: 730 state->dmaBufIndex = !state->dmaBufIndex; 731 state->buf += i; 732 state->buflen -= i; 733 734 /* check for more data for the same phase */ 735 if (state->buflen <= 0 || (dstat & SII_MIS)) 736 break; 737 738 /* start next chunk */ 739 i = state->buflen; 740 if (i > SII_MAX_DMA_XFER_LENGTH) { 741 sii_StartDMA(regs, state->dmaCurPhase = 742 SII_DATA_OUT_PHASE, 743 state->dmaAddr[state->dmaBufIndex], 744 state->dmaCnt = state->dmalen = 745 SII_MAX_DMA_XFER_LENGTH); 746 /* prepare for next chunk */ 747 i -= SII_MAX_DMA_XFER_LENGTH; 748 if (i > SII_MAX_DMA_XFER_LENGTH) 749 i = SII_MAX_DMA_XFER_LENGTH; 750 sc->sii_copytobuf((u_short *)(state->buf + 751 SII_MAX_DMA_XFER_LENGTH), 752 (volatile u_short *) 753 state->dmaAddr[!state->dmaBufIndex], i); 754 } else { 755 sii_StartDMA(regs, state->dmaCurPhase = 756 SII_DATA_OUT_PHASE, 757 state->dmaAddr[state->dmaBufIndex], 758 state->dmaCnt = state->dmalen = i); 759 } 760 dstat &= ~(SII_IBF | SII_TBE); 761 } 762 } 763 764 /* check for phase change or another MsgIn/Out */ 765 if (dstat & (SII_MIS | SII_IBF | SII_TBE)) { 766 /* 767 * There is a race condition with SII_SCH. There is a short 768 * window between the time a SII_SCH is seen after a disconnect 769 * and when the SII_SCH is cleared. A reselect can happen 770 * in this window and we will clear the SII_SCH without 771 * processing the reconnect. 772 */ 773 if (sc->sc_target < 0) { 774 cstat = regs->cstat; 775 printf("%s: target %d MIS?? dev %d,%d cs %x ds %x\n", 776 device_xname(sc->sc_dev), sc->sc_target, 777 regs->slcsr, regs->destat, 778 cstat, dstat); /* XXX */ 779 if (cstat & SII_DST) { 780 sc->sc_target = regs->destat; 781 state = &sc->sc_st[sc->sc_target]; 782 state->prevComm = 0; 783 } else { 784#ifdef DEBUG 785 sii_DumpLog(); 786#endif 787 panic("sc_target 2"); 788 } 789 } 790 state = &sc->sc_st[sc->sc_target]; 791 switch (dstat & SII_PHASE_MSK) { 792 case SII_CMD_PHASE: 793 if (state->dmaPrevPhase >= 0) { 794 /* restart DMA after disconnect/reconnect */ 795 if (state->dmaPrevPhase != SII_CMD_PHASE) { 796 printf("%s: device %d: DMA reselect phase doesn't match\n", 797 device_xname(sc->sc_dev), 798 sc->sc_target); 799 goto abort; 800 } 801 state->dmaCurPhase = SII_CMD_PHASE; 802 state->dmaPrevPhase = -1; 803 regs->dmaddrl = state->dmaAddrL; 804 regs->dmaddrh = state->dmaAddrH; 805 regs->dmlotc = state->dmaCnt; 806 if (state->dmaCnt & 1) 807 regs->dmabyte = state->dmaByte; 808 regs->comm = SII_DMA | SII_INXFER | 809 (comm & SII_STATE_MSK) | SII_CMD_PHASE; 810 wbflush(); 811#ifdef DEBUG 812 if (sii_debug > 4) 813 printf("Cmd dcnt %d dadr %x ", 814 state->dmaCnt, 815 (state->dmaAddrH << 16) | 816 state->dmaAddrL); 817#endif 818 } else { 819 /* send command data */ 820 i = state->cmdlen; 821 if (i == 0) { 822 printf("%s: device %d: cmd count exceeded\n", 823 device_xname(sc->sc_dev), 824 sc->sc_target); 825 goto abort; 826 } 827 sc->sii_copytobuf((u_short *)state->cmd, 828 (volatile u_short *)state->dmaAddr[0], 829 i); 830 sii_StartDMA(regs, state->dmaCurPhase = 831 SII_CMD_PHASE, state->dmaAddr[0], 832 state->dmaCnt = state->dmalen = i); 833 } 834 /* wait a short time for XFER complete */ 835 SII_WAIT_UNTIL(dstat, regs->dstat, 836 dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i); 837 if (dstat & (SII_CI | SII_DI)) { 838#ifdef DEBUG 839 if (sii_debug > 4) 840 printf("cnt %d\n", i); 841 else if (sii_debug > 0) 842 printf("sii_DoIntr: cmd wait ds %x cnt %d\n", 843 dstat, i); 844#endif 845 goto again; 846 } 847 break; 848 849 case SII_DATA_IN_PHASE: 850 case SII_DATA_OUT_PHASE: 851 if (state->cmdlen > 0) { 852 printf("%s: device %d: cmd %x: command data not all sent (%d) 1\n", 853 device_xname(sc->sc_dev), sc->sc_target, 854 sc->sc_cmd[sc->sc_target]->cmd[0], 855 state->cmdlen); 856 state->cmdlen = 0; 857#ifdef DEBUG 858 sii_DumpLog(); 859#endif 860 } 861 if (state->dmaPrevPhase >= 0) { 862 /* restart DMA after disconnect/reconnect */ 863 if (state->dmaPrevPhase != 864 (dstat & SII_PHASE_MSK)) { 865 printf("%s: device %d: DMA reselect phase doesn't match\n", 866 device_xname(sc->sc_dev), 867 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 device_xname(sc->sc_dev), 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 device_xname(sc->sc_dev), 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 device_xname(sc->sc_dev), 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 device_xname(sc->sc_dev), 1296 sc->sc_target, 1297 msg); 1298#ifdef DEBUG 1299 sii_DumpLog(); 1300#endif 1301 goto reject; 1302 } 1303 /* acknowledge last byte */ 1304 regs->comm = SII_INXFER | SII_MSG_IN_PHASE | 1305 (comm & SII_STATE_MSK); 1306 SII_WAIT_UNTIL(dstat, regs->dstat, 1307 dstat & SII_DNE, SII_WAIT_COUNT, i); 1308 regs->dstat = SII_DNE; 1309 wbflush(); 1310 /* may want to check LUN some day */ 1311 /* wait a short time for another msg */ 1312 SII_WAIT_UNTIL(dstat, regs->dstat, 1313 dstat & (SII_CI | SII_DI), 1314 SII_WAIT_COUNT, i); 1315 if (dstat & (SII_CI | SII_DI)) { 1316#ifdef DEBUG 1317 if (sii_debug > 4) 1318 printf("cnt %d\n", i); 1319#endif 1320 goto again; 1321 } 1322 } 1323 break; 1324 1325 case SII_MSG_OUT_PHASE: 1326#ifdef DEBUG 1327 if (sii_debug > 4) 1328 printf("MsgOut\n"); 1329#endif 1330 printf("MsgOut %x\n", state->flags); /* XXX */ 1331 1332 /* 1333 * Check for parity error. 1334 * Hardware will automatically set ATN 1335 * to request the device for a MSG_OUT phase. 1336 */ 1337 if (state->flags & PARITY_ERR) { 1338 state->flags &= ~PARITY_ERR; 1339 regs->data = MSG_PARITY_ERROR; 1340 } else 1341 regs->data = MSG_NOOP; 1342 regs->comm = SII_INXFER | (comm & SII_STATE_MSK) | 1343 SII_MSG_OUT_PHASE; 1344 wbflush(); 1345 1346 /* wait a short time for XFER complete */ 1347 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE, 1348 SII_WAIT_COUNT, i); 1349#ifdef DEBUG 1350 if (sii_debug > 4) 1351 printf("ds %x i %d\n", dstat, i); 1352#endif 1353 /* just clear the DNE bit and check errors later */ 1354 if (dstat & SII_DNE) { 1355 regs->dstat = SII_DNE; 1356 wbflush(); 1357 } 1358 break; 1359 1360 default: 1361 printf("%s: Couldn't handle phase %d... ignoring.\n", 1362 device_xname(sc->sc_dev), dstat & SII_PHASE_MSK); 1363 } 1364 } 1365 1366#ifdef DEBUG 1367 if (sii_debug > 3) 1368 printf("\n"); 1369#endif 1370 /* 1371 * Check to make sure we won't be interrupted again. 1372 * Deglitch dstat register. 1373 */ 1374 msg = regs->dstat; 1375 while (msg != (dstat = regs->dstat)) 1376 msg = dstat; 1377 if (dstat & (SII_CI | SII_DI)) 1378 goto again; 1379 1380 if (sc->sc_target < 0) { 1381 /* look for another device that is ready */ 1382 for (i = 0; i < SII_NCMD; i++) { 1383 /* don't restart a disconnected command */ 1384 if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm) 1385 continue; 1386 sii_StartCmd(sc, i); 1387 break; 1388 } 1389 } 1390 return; 1391 1392abort: 1393 /* jump here to abort the current command */ 1394 printf("%s: device %d: current command terminated\n", 1395 device_xname(sc->sc_dev), sc->sc_target); 1396#ifdef DEBUG 1397 sii_DumpLog(); 1398#endif 1399 1400 if ((cstat = regs->cstat) & SII_CON) { 1401 /* try to send an abort msg for awhile */ 1402 regs->dstat = SII_DNE; 1403 regs->data = MSG_ABORT; 1404 regs->comm = SII_INXFER | SII_ATN | (cstat & SII_STATE_MSK) | 1405 SII_MSG_OUT_PHASE; 1406 wbflush(); 1407 SII_WAIT_UNTIL(dstat, regs->dstat, 1408 (dstat & (SII_DNE | SII_PHASE_MSK)) == 1409 (SII_DNE | SII_MSG_OUT_PHASE), 1410 2 * SII_WAIT_COUNT, i); 1411#ifdef DEBUG 1412 if (sii_debug > 0) 1413 printf("Abort: cs %x ds %x i %d\n", cstat, dstat, i); 1414#endif 1415 if ((dstat & (SII_DNE | SII_PHASE_MSK)) == 1416 (SII_DNE | SII_MSG_OUT_PHASE)) { 1417 /* disconnect if command in progress */ 1418 regs->comm = SII_DISCON; 1419 wbflush(); 1420 SII_WAIT_UNTIL(cstat, regs->cstat, 1421 !(cstat & SII_CON), SII_WAIT_COUNT, i); 1422 } 1423 } else { 1424#ifdef DEBUG 1425 if (sii_debug > 0) 1426 printf("Abort: cs %x\n", cstat); 1427#endif 1428 } 1429 regs->cstat = 0xffff; 1430 regs->dstat = 0xffff; 1431 regs->comm = 0; 1432 wbflush(); 1433 1434 i = sc->sc_target; 1435 sc->sc_target = -1; 1436 sii_CmdDone(sc, i, EIO); 1437#ifdef DEBUG 1438 if (sii_debug > 4) 1439 printf("sii_DoIntr: after CmdDone target %d\n", sc->sc_target); 1440#endif 1441} 1442 1443static void 1444sii_StateChg(struct siisoftc *sc, u_int cstat) 1445{ 1446 SIIRegs *regs = sc->sc_regs; 1447 State *state; 1448 int i; 1449 1450#ifdef DEBUG 1451 if (sii_debug > 4) 1452 printf("SCH: "); 1453#endif 1454 1455 switch (cstat & SII_STATE_MSK) { 1456 case 0: 1457 /* disconnect */ 1458 i = sc->sc_target; 1459 sc->sc_target = -1; 1460#ifdef DEBUG 1461 if (sii_debug > 4) 1462 printf("disconn %d ", i); 1463#endif 1464 if (i >= 0 && !sc->sc_st[i].prevComm) { 1465 printf("%s: device %d: spurrious disconnect (%d)\n", 1466 device_xname(sc->sc_dev), i, regs->slcsr); 1467 sc->sc_st[i].prevComm = 0; 1468 } 1469 break; 1470 1471 case SII_CON: 1472 /* connected as initiator */ 1473 i = regs->slcsr; 1474 if (sc->sc_target == i) 1475 break; 1476 printf("%s: device %d: connect to device %d??\n", 1477 device_xname(sc->sc_dev), sc->sc_target, i); 1478 sc->sc_target = i; 1479 break; 1480 1481 case SII_DST: 1482 /* 1483 * Wait for CON to become valid, 1484 * chip is slow sometimes. 1485 */ 1486 SII_WAIT_UNTIL(cstat, regs->cstat, 1487 cstat & SII_CON, SII_WAIT_COUNT, i); 1488 if (!(cstat & SII_CON)) 1489 panic("sii resel"); 1490 /* FALLTHROUGH */ 1491 1492 case SII_CON | SII_DST: 1493 /* 1494 * Its a reselection. Save the ID and wait for 1495 * interrupts to tell us what to do next 1496 * (should be MSG_IN of IDENTIFY). 1497 * NOTE: sc_target may be >= 0 if we were in 1498 * the process of trying to start a command 1499 * and were reselected before the select 1500 * command finished. 1501 */ 1502 sc->sc_target = i = regs->destat; 1503 state = &sc->sc_st[i]; 1504 regs->comm = SII_CON | SII_DST | SII_MSG_IN_PHASE; 1505 regs->dmctrl = state->dmaReqAck; 1506 wbflush(); 1507 if (!state->prevComm) { 1508 printf("%s: device %d: spurious reselection\n", 1509 device_xname(sc->sc_dev), i); 1510 break; 1511 } 1512 state->prevComm = 0; 1513#ifdef DEBUG 1514 if (sii_debug > 4) 1515 printf("resel %d ", sc->sc_target); 1516#endif 1517 break; 1518 1519#ifdef notyet 1520 case SII_DST | SII_TGT: 1521 case SII_CON | SII_DST | SII_TGT: 1522 /* connected as target */ 1523 printf("%s: Selected by device %d as target!!\n", 1524 device_xname(sc->sc_dev), regs->destat); 1525 regs->comm = SII_DISCON; 1526 wbflush(); 1527 SII_WAIT_UNTIL(!(regs->cstat & SII_CON), 1528 SII_WAIT_COUNT, i); 1529 regs->cstat = 0xffff; 1530 regs->dstat = 0xffff; 1531 regs->comm = 0; 1532 break; 1533#endif 1534 1535 default: 1536 printf("%s: Unknown state change (cs %x)!!\n", 1537 device_xname(sc->sc_dev), cstat); 1538#ifdef DEBUG 1539 sii_DumpLog(); 1540#endif 1541 } 1542} 1543 1544/* 1545 * Read one byte of data. 1546 * If 'ack' is true, acknowledge the byte. 1547 */ 1548static int 1549sii_GetByte(SIIRegs *regs, int phase, int ack) 1550{ 1551 u_int dstat; 1552 u_int state; 1553 int i; 1554 int data; 1555 1556 dstat = regs->dstat; 1557 state = regs->cstat & SII_STATE_MSK; 1558 i = -1; 1559 if (!(dstat & SII_IBF) || (dstat & SII_MIS)) { 1560 regs->comm = state | phase; 1561 wbflush(); 1562 /* wait a short time for IBF */ 1563 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_IBF, 1564 SII_WAIT_COUNT, i); 1565#ifdef DEBUG 1566 if (!(dstat & SII_IBF)) 1567 printf("status no IBF\n"); 1568#endif 1569 } 1570 if (dstat & SII_DNE) { /* XXX */ 1571 printf("sii_GetByte: DNE set 5\n"); 1572#ifdef DEBUG 1573 sii_DumpLog(); 1574#endif 1575 regs->dstat = SII_DNE; 1576 } 1577 data = regs->data; 1578 /* check for parity error */ 1579 if (dstat & SII_IPE) { 1580#ifdef DEBUG 1581 if (sii_debug > 4) 1582 printf("cnt0 %d\n", i); 1583#endif 1584 printf("sii_GetByte: data %x ?? ds %x cm %x i %d\n", 1585 data, dstat, regs->comm, i); /* XXX */ 1586 data = -1; 1587 ack = 1; 1588 } 1589 1590 if (ack) { 1591 regs->comm = SII_INXFER | state | phase; 1592 wbflush(); 1593 1594 /* wait a short time for XFER complete */ 1595 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE, 1596 SII_WAIT_COUNT, i); 1597 1598 /* clear the DNE */ 1599 if (dstat & SII_DNE) { 1600 regs->dstat = SII_DNE; 1601 wbflush(); 1602 } 1603 } 1604 1605 return (data); 1606} 1607 1608/* 1609 * Exchange messages to initiate synchronous data transfers. 1610 */ 1611static void 1612sii_DoSync(SIIRegs *regs, State *state) 1613{ 1614 u_int dstat, comm; 1615 int i, j; 1616 u_int len; 1617 1618#ifdef DEBUG 1619 if (sii_debug) 1620 printf("sii_DoSync: len %d per %d req/ack %d\n", 1621 sii_buf[1], sii_buf[3], sii_buf[4]); 1622#endif 1623 1624 /* SII chip can only handle a minimum transfer period of ??? */ 1625 if (sii_buf[3] < 64) 1626 sii_buf[3] = 64; 1627 /* SII chip can only handle a maximum REQ/ACK offset of 3 */ 1628 len = sii_buf[4]; 1629 if (len > 3) 1630 len = 3; 1631 1632 sii_buf[0] = MSG_EXTENDED; 1633 sii_buf[1] = MSG_EXT_SDTR_LEN; 1634 sii_buf[2] = MSG_EXT_SDTR; 1635 sii_buf[4] = len; 1636#if 1 1637 comm = SII_INXFER | SII_ATN | SII_MSG_OUT_PHASE | 1638 (regs->cstat & SII_STATE_MSK); 1639 regs->comm = comm & ~SII_INXFER; 1640 for (j = 0; j < 5; j++) { 1641 /* wait for target to request the next byte */ 1642 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_TBE, 1643 SII_WAIT_COUNT, i); 1644 if (!(dstat & SII_TBE) || 1645 (dstat & SII_PHASE_MSK) != SII_MSG_OUT_PHASE) { 1646 printf("sii_DoSync: TBE? ds %x cm %x i %d\n", 1647 dstat, comm, i); /* XXX */ 1648 return; 1649 } 1650 1651 /* the last message byte should have ATN off */ 1652 if (j == 4) 1653 comm &= ~SII_ATN; 1654 1655 regs->data = sii_buf[j]; 1656 regs->comm = comm; 1657 wbflush(); 1658 1659 /* wait a short time for XFER complete */ 1660 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE, 1661 SII_WAIT_COUNT, i); 1662 1663 if (!(dstat & SII_DNE)) { 1664 printf("sii_DoSync: DNE? ds %x cm %x i %d\n", 1665 dstat, comm, i); /* XXX */ 1666 return; 1667 } 1668 1669 /* clear the DNE, other errors handled later */ 1670 regs->dstat = SII_DNE; 1671 wbflush(); 1672 } 1673#else /* 0 */ 1674 sc->sii_copytobuf((u_short *)sii_buf, 1675 (volatile u_short *)SII_BUF_ADDR(sc), 5); 1676 printf("sii_DoSync: %x %x %x ds %x\n", 1677 ((volatile u_short *)SII_BUF_ADDR(sc))[0], 1678 ((volatile u_short *)SII_BUF_ADDR(sc))[2], 1679 ((volatile u_short *)SII_BUF_ADDR(sc))[4], 1680 regs->dstat); /* XXX */ 1681 regs->dmaddrl = (u_short)(SII_BUF_ADDR(sc) >> 1); 1682 regs->dmaddrh = (u_short)(SII_BUF_ADDR(sc) >> 17) & 03; 1683 regs->dmlotc = 5; 1684 regs->comm = SII_DMA | SII_INXFER | SII_ATN | 1685 (regs->cstat & SII_STATE_MSK) | SII_MSG_OUT_PHASE; 1686 wbflush(); 1687 1688 /* wait a short time for XFER complete */ 1689 SII_WAIT_UNTIL(dstat, regs->dstat, 1690 (dstat & (SII_DNE | SII_TCZ)) == (SII_DNE | SII_TCZ), 1691 SII_WAIT_COUNT, i); 1692 1693 if ((dstat & (SII_DNE | SII_TCZ)) != (SII_DNE | SII_TCZ)) { 1694 printf("sii_DoSync: ds %x cm %x i %d lotc %d\n", 1695 dstat, regs->comm, i, regs->dmlotc); /* XXX */ 1696 sii_DumpLog(); /* XXX */ 1697 return; 1698 } 1699 /* clear the DNE, other errors handled later */ 1700 regs->dstat = SII_DNE; 1701 wbflush(); 1702#endif /* 0 */ 1703 1704#if 0 1705 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & (SII_CI | SII_DI), 1706 SII_WAIT_COUNT, i); 1707 printf("sii_DoSync: ds %x cm %x i %d lotc %d\n", 1708 dstat, regs->comm, i, regs->dmlotc); /* XXX */ 1709#endif 1710 1711 state->dmaReqAck = len; 1712} 1713 1714/* 1715 * Issue the sequence of commands to the controller to start DMA. 1716 * NOTE: the data buffer should be word-aligned for DMA out. 1717 */ 1718static void 1719sii_StartDMA(SIIRegs *regs, int phase, u_short *dmaAddr, int size) 1720 /* regs: which SII to use */ 1721 /* phase: phase to send/receive data */ 1722 /* dmaAddr: DMA buffer address */ 1723 /* size: # of bytes to transfer */ 1724{ 1725 1726 if (regs->dstat & SII_DNE) { /* XXX */ 1727 regs->dstat = SII_DNE; 1728 printf("sii_StartDMA: DNE set\n"); 1729#ifdef DEBUG 1730 sii_DumpLog(); 1731#endif 1732 } 1733 regs->dmaddrl = ((u_long)dmaAddr >> 1); 1734 regs->dmaddrh = ((u_long)dmaAddr >> 17) & 03; 1735 regs->dmlotc = size; 1736 regs->comm = SII_DMA | SII_INXFER | (regs->cstat & SII_STATE_MSK) | 1737 phase; 1738 wbflush(); 1739 1740#ifdef DEBUG 1741 if (sii_debug > 5) { 1742 printf("sii_StartDMA: cs 0x%x, ds 0x%x, cm 0x%x, size %d\n", 1743 regs->cstat, regs->dstat, regs->comm, size); 1744 } 1745#endif 1746} 1747 1748/* 1749 * Call the device driver's 'done' routine to let it know the command is done. 1750 * The 'done' routine may try to start another command. 1751 * To be fair, we should start pending commands for other devices 1752 * before allowing the same device to start another command. 1753 */ 1754static void 1755sii_CmdDone(struct siisoftc *sc, int target, int error) 1756 /* sc: which SII to use */ 1757 /* target: which device is done */ 1758 /* error: error code if any errors */ 1759{ 1760 ScsiCmd *scsicmd; 1761 int i; 1762 1763 scsicmd = sc->sc_cmd[target]; 1764#ifdef DIAGNOSTIC 1765 if (target < 0 || !scsicmd) 1766 panic("sii_CmdDone"); 1767#endif 1768 sc->sc_cmd[target] = (ScsiCmd *)0; 1769#ifdef DEBUG 1770 if (sii_debug > 1) { 1771 printf("sii_CmdDone: %s target %d cmd %x err %d resid %d\n", 1772 device_xname(sc->sc_dev), 1773 target, scsicmd->cmd[0], error, sc->sc_st[target].buflen); 1774 } 1775#endif 1776 1777 /* look for another device that is ready */ 1778 for (i = 0; i < SII_NCMD; i++) { 1779 /* don't restart a disconnected command */ 1780 if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm) 1781 continue; 1782 sii_StartCmd(sc, i); 1783 break; 1784 } 1785 1786 sc->sc_xs[target]->status = sc->sc_st[target].statusByte; 1787 /* 1788 * Convert SII driver error code to MI SCSI XS_*. 1789 */ 1790 switch (error) { 1791 case 0: 1792 sc->sc_xs[target]->error = XS_NOERROR; 1793 break; 1794 case ENXIO: 1795 sc->sc_xs[target]->error = XS_SELTIMEOUT; 1796 break; 1797 case EBUSY: 1798 sc->sc_xs[target]->error = XS_BUSY; 1799 break; 1800 case EIO: 1801 sc->sc_xs[target]->error = XS_DRIVER_STUFFUP; 1802 break; 1803 default: 1804 sc->sc_xs[target]->error = XS_DRIVER_STUFFUP; 1805 } 1806 sc->sc_xs[target]->resid = sc->sc_st[target].buflen; 1807 scsipi_done(sc->sc_xs[target]); 1808} 1809 1810#ifdef DEBUG 1811static void 1812sii_DumpLog(void) 1813{ 1814 struct sii_log *lp; 1815 1816 printf("sii: cmd %x bn %d cnt %d\n", sii_debug_cmd, sii_debug_bn, 1817 sii_debug_sz); 1818 lp = sii_logp; 1819 do { 1820 printf("target %d cs %x ds %x cm %x msg %x rlen %x dlen %x\n", 1821 lp->target, lp->cstat, lp->dstat, lp->comm, lp->msg, 1822 lp->rlen, lp->dlen); 1823 if (++lp >= &sii_log[NLOG]) 1824 lp = sii_log; 1825 } while (lp != sii_logp); 1826} 1827#endif 1828