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