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.3 (Berkeley) 05/21/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 sii_DumpLog(); 718 panic("sc_target 2"); 719 } 720 } 721 state = &sc->sc_st[sc->sc_target]; 722 switch (dstat & SII_PHASE_MSK) { 723 case SII_CMD_PHASE: 724 if (state->dmaPrevPhase >= 0) { 725 /* restart DMA after disconnect/reconnect */ 726 if (state->dmaPrevPhase != SII_CMD_PHASE) { 727 printf("sii%d: device %d: dma reselect phase doesn't match\n", 728 sc - sii_softc, sc->sc_target); 729 goto abort; 730 } 731 state->dmaCurPhase = SII_CMD_PHASE; 732 state->dmaPrevPhase = -1; 733 regs->dmaddrl = state->dmaAddrL; 734 regs->dmaddrh = state->dmaAddrH; 735 regs->dmlotc = state->dmaCnt; 736 if (state->dmaCnt & 1) 737 regs->dmabyte = state->dmaByte; 738 regs->comm = SII_DMA | SII_INXFER | 739 (comm & SII_STATE_MSK) | SII_CMD_PHASE; 740 MachEmptyWriteBuffer(); 741 #ifdef DEBUG 742 if (sii_debug > 4) 743 printf("Cmd dcnt %d dadr %x ", 744 state->dmaCnt, 745 (state->dmaAddrH << 16) | 746 state->dmaAddrL); 747 #endif 748 } else { 749 /* send command data */ 750 i = state->cmdlen; 751 if (i == 0) { 752 printf("sii%d: device %d: cmd count exceeded\n", 753 sc - sii_softc, sc->sc_target); 754 goto abort; 755 } 756 CopyToBuffer((u_short *)state->cmd, 757 (volatile u_short *)state->dmaAddr[0], 758 i); 759 sii_StartDMA(regs, state->dmaCurPhase = 760 SII_CMD_PHASE, state->dmaAddr[0], 761 state->dmalen = i); 762 } 763 /* wait a short time for XFER complete */ 764 SII_WAIT_UNTIL(dstat, regs->dstat, 765 dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i); 766 if (dstat & (SII_CI | SII_DI)) { 767 #ifdef DEBUG 768 if (sii_debug > 4) 769 printf("cnt %d\n", i); 770 else if (sii_debug > 0) 771 printf("sii_DoIntr: cmd wait ds %x cnt %d\n", 772 dstat, i); 773 #endif 774 goto again; 775 } 776 break; 777 778 case SII_DATA_IN_PHASE: 779 case SII_DATA_OUT_PHASE: 780 if (state->cmdlen > 0) { 781 printf("sii%d: device %d: cmd %x: command data not all sent (%d) 1\n", 782 sc - sii_softc, sc->sc_target, 783 sc->sc_cmd[sc->sc_target]->cmd[0], 784 state->cmdlen); 785 state->cmdlen = 0; 786 #ifdef DEBUG 787 sii_DumpLog(); 788 #endif 789 } 790 if (state->dmaPrevPhase >= 0) { 791 /* restart DMA after disconnect/reconnect */ 792 if (state->dmaPrevPhase != 793 (dstat & SII_PHASE_MSK)) { 794 printf("sii%d: device %d: dma reselect phase doesn't match\n", 795 sc - sii_softc, sc->sc_target); 796 goto abort; 797 } 798 state->dmaCurPhase = state->dmaPrevPhase; 799 state->dmaPrevPhase = -1; 800 regs->dmaddrl = state->dmaAddrL; 801 regs->dmaddrh = state->dmaAddrH; 802 regs->dmlotc = state->dmaCnt; 803 if (state->dmaCnt & 1) 804 regs->dmabyte = state->dmaByte; 805 regs->comm = SII_DMA | SII_INXFER | 806 (comm & SII_STATE_MSK) | 807 state->dmaCurPhase; 808 MachEmptyWriteBuffer(); 809 #ifdef DEBUG 810 if (sii_debug > 4) 811 printf("Data %d dcnt %d dadr %x ", 812 state->dmaDataPhase, 813 state->dmaCnt, 814 (state->dmaAddrH << 16) | 815 state->dmaAddrL); 816 #endif 817 break; 818 } 819 if (state->dmaDataPhase != (dstat & SII_PHASE_MSK)) { 820 printf("sii%d: device %d: cmd %x: dma phase doesn't match\n", 821 sc - sii_softc, sc->sc_target, 822 sc->sc_cmd[sc->sc_target]->cmd[0]); 823 goto abort; 824 } 825 #ifdef DEBUG 826 if (sii_debug > 4) { 827 printf("Data %d ", state->dmaDataPhase); 828 if (sii_debug > 5) 829 printf("\n"); 830 } 831 #endif 832 i = state->buflen; 833 if (i == 0) { 834 printf("sii%d: device %d: data count exceeded\n", 835 sc - sii_softc, sc->sc_target); 836 goto abort; 837 } 838 if (i > SII_MAX_DMA_XFER_LENGTH) 839 i = SII_MAX_DMA_XFER_LENGTH; 840 if ((dstat & SII_PHASE_MSK) == SII_DATA_IN_PHASE) { 841 sii_StartDMA(regs, 842 state->dmaCurPhase = SII_DATA_IN_PHASE, 843 state->dmaAddr[state->dmaBufIndex], 844 state->dmalen = i); 845 break; 846 } 847 /* start first chunk */ 848 if (state->flags & FIRST_DMA) { 849 state->flags &= ~FIRST_DMA; 850 CopyToBuffer((u_short *)state->buf, 851 (volatile u_short *) 852 state->dmaAddr[state->dmaBufIndex], i); 853 } 854 sii_StartDMA(regs, 855 state->dmaCurPhase = SII_DATA_OUT_PHASE, 856 state->dmaAddr[state->dmaBufIndex], 857 state->dmalen = i); 858 i = state->buflen - SII_MAX_DMA_XFER_LENGTH; 859 if (i > 0) { 860 /* prepare for next chunk */ 861 if (i > SII_MAX_DMA_XFER_LENGTH) 862 i = SII_MAX_DMA_XFER_LENGTH; 863 CopyToBuffer((u_short *)(state->buf + 864 SII_MAX_DMA_XFER_LENGTH), 865 (volatile u_short *) 866 state->dmaAddr[!state->dmaBufIndex], i); 867 } 868 break; 869 870 case SII_STATUS_PHASE: 871 if (state->cmdlen > 0) { 872 printf("sii%d: device %d: cmd %x: command data not all sent (%d) 2\n", 873 sc - sii_softc, sc->sc_target, 874 sc->sc_cmd[sc->sc_target]->cmd[0], 875 state->cmdlen); 876 state->cmdlen = 0; 877 #ifdef DEBUG 878 sii_DumpLog(); 879 #endif 880 } 881 882 /* read amount transfered if DMA didn't finish */ 883 if (state->dmalen > 0) { 884 i = state->dmalen - regs->dmlotc; 885 state->dmalen = 0; 886 state->dmaCurPhase = -1; 887 regs->dmlotc = 0; 888 regs->comm = comm & 889 (SII_STATE_MSK | SII_PHASE_MSK); 890 MachEmptyWriteBuffer(); 891 regs->dstat = SII_DNE; 892 MachEmptyWriteBuffer(); 893 #ifdef DEBUG 894 if (sii_debug > 4) 895 printf("DMA amt %d ", i); 896 #endif 897 switch (comm & SII_PHASE_MSK) { 898 case SII_DATA_IN_PHASE: 899 /* copy in the data */ 900 CopyFromBuffer((volatile u_short *) 901 state->dmaAddr[state->dmaBufIndex], 902 state->buf, i); 903 904 case SII_CMD_PHASE: 905 case SII_DATA_OUT_PHASE: 906 state->buflen -= i; 907 } 908 } 909 910 /* read a one byte status message */ 911 state->statusByte = msg = 912 sii_GetByte(regs, SII_STATUS_PHASE, 1); 913 if (msg < 0) { 914 dstat = regs->dstat; 915 goto again; 916 } 917 #ifdef DEBUG 918 if (sii_debug > 4) 919 printf("Status %x ", msg); 920 if (sii_logp > sii_log) 921 sii_logp[-1].msg = msg; 922 else 923 sii_log[NLOG - 1].msg = msg; 924 #endif 925 926 /* do a quick wait for COMMAND_COMPLETE */ 927 SII_WAIT_UNTIL(dstat, regs->dstat, 928 dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i); 929 if (dstat & (SII_CI | SII_DI)) { 930 #ifdef DEBUG 931 if (sii_debug > 4) 932 printf("cnt2 %d\n", i); 933 #endif 934 goto again; 935 } 936 break; 937 938 case SII_MSG_IN_PHASE: 939 /* 940 * Save DMA state if DMA didn't finish. 941 * Be careful not to save state again after reconnect 942 * and see RESTORE_POINTER message. 943 * Note that the SII DMA address is not incremented 944 * as DMA proceeds. 945 */ 946 if (state->dmaCurPhase > 0) { 947 /* save dma registers */ 948 state->dmaPrevPhase = state->dmaCurPhase; 949 state->dmaCurPhase = -1; 950 state->dmaCnt = i = regs->dmlotc; 951 if (dstat & SII_OBB) 952 state->dmaByte = regs->dmabyte; 953 if (i == 0) 954 i = SII_MAX_DMA_XFER_LENGTH; 955 i = state->dmalen - i; 956 /* note: no carry from dmaddrl to dmaddrh */ 957 state->dmaAddrL = regs->dmaddrl + i; 958 state->dmaAddrH = regs->dmaddrh; 959 regs->comm = comm & 960 (SII_STATE_MSK | SII_PHASE_MSK); 961 MachEmptyWriteBuffer(); 962 regs->dstat = SII_DNE; 963 MachEmptyWriteBuffer(); 964 #ifdef DEBUG 965 if (sii_debug > 4) { 966 printf("SavP dcnt %d dadr %x ", 967 state->dmaCnt, 968 (state->dmaAddrH << 16) | 969 state->dmaAddrL); 970 if (((dstat & SII_OBB) != 0) ^ 971 (state->dmaCnt & 1)) 972 printf("OBB??? "); 973 } else if (sii_debug > 0) { 974 if (((dstat & SII_OBB) != 0) ^ 975 (state->dmaCnt & 1)) { 976 printf("sii_DoIntr: OBB??? ds %x cnt %d\n", 977 dstat, state->dmaCnt); 978 sii_DumpLog(); 979 } 980 } 981 #endif 982 } 983 984 /* read a one byte message */ 985 msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 0); 986 if (msg < 0) { 987 dstat = regs->dstat; 988 goto again; 989 } 990 #ifdef DEBUG 991 if (sii_debug > 4) 992 printf("MsgIn %x ", msg); 993 if (sii_logp > sii_log) 994 sii_logp[-1].msg = msg; 995 else 996 sii_log[NLOG - 1].msg = msg; 997 #endif 998 999 /* process message */ 1000 switch (msg) { 1001 case SCSI_COMMAND_COMPLETE: 1002 /* acknowledge last byte */ 1003 regs->comm = SII_INXFER | SII_MSG_IN_PHASE | 1004 (comm & SII_STATE_MSK); 1005 SII_WAIT_UNTIL(dstat, regs->dstat, 1006 dstat & SII_DNE, SII_WAIT_COUNT, i); 1007 regs->dstat = SII_DNE; 1008 MachEmptyWriteBuffer(); 1009 msg = sc->sc_target; 1010 sc->sc_target = -1; 1011 /* 1012 * Wait a short time for disconnect. 1013 * Don't be fooled if SII_BER happens first. 1014 * Note: a reselect may happen here. 1015 */ 1016 SII_WAIT_UNTIL(cstat, regs->cstat, 1017 cstat & (SII_RST | SII_SCH), 1018 SII_WAIT_COUNT, i); 1019 if ((cstat & (SII_RST | SII_SCH | 1020 SII_STATE_MSK)) == SII_SCH) { 1021 regs->cstat = SII_SCH | SII_BER; 1022 regs->comm = 0; 1023 MachEmptyWriteBuffer(); 1024 /* 1025 * Double check that we didn't miss a 1026 * state change between seeing it and 1027 * clearing the SII_SCH bit. 1028 */ 1029 i = regs->cstat; 1030 if (!(i & SII_SCH) && 1031 (i & SII_STATE_MSK) != 1032 (cstat & SII_STATE_MSK)) 1033 sii_StateChg(sc, i); 1034 } 1035 #ifdef DEBUG 1036 if (sii_debug > 4) 1037 printf("cs %x\n", cstat); 1038 #endif 1039 sii_CmdDone(sc, msg, 0); 1040 break; 1041 1042 case SCSI_EXTENDED_MSG: 1043 /* acknowledge last byte */ 1044 regs->comm = SII_INXFER | SII_MSG_IN_PHASE | 1045 (comm & SII_STATE_MSK); 1046 SII_WAIT_UNTIL(dstat, regs->dstat, 1047 dstat & SII_DNE, SII_WAIT_COUNT, i); 1048 regs->dstat = SII_DNE; 1049 MachEmptyWriteBuffer(); 1050 /* read the message length */ 1051 msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 1); 1052 if (msg < 0) { 1053 dstat = regs->dstat; 1054 goto again; 1055 } 1056 sii_buf[1] = msg; /* message length */ 1057 if (msg == 0) 1058 msg = 256; 1059 /* 1060 * We read and acknowlege all the bytes 1061 * except the last so we can assert ATN 1062 * if needed before acknowledging the last. 1063 */ 1064 for (i = 0; i < msg; i++) { 1065 dstat = sii_GetByte(regs, 1066 SII_MSG_IN_PHASE, i < msg - 1); 1067 if ((int)dstat < 0) { 1068 dstat = regs->dstat; 1069 goto again; 1070 } 1071 sii_buf[i + 2] = dstat; 1072 } 1073 1074 switch (sii_buf[2]) { 1075 case SCSI_MODIFY_DATA_PTR: 1076 /* acknowledge last byte */ 1077 regs->comm = SII_INXFER | 1078 SII_MSG_IN_PHASE | 1079 (comm & SII_STATE_MSK); 1080 SII_WAIT_UNTIL(dstat, regs->dstat, 1081 dstat & SII_DNE, 1082 SII_WAIT_COUNT, i); 1083 regs->dstat = SII_DNE; 1084 MachEmptyWriteBuffer(); 1085 i = (sii_buf[3] << 24) | 1086 (sii_buf[4] << 16) | 1087 (sii_buf[5] << 8) | 1088 sii_buf[6]; 1089 if (state->dmaPrevPhase >= 0) { 1090 state->dmaAddrL += i; 1091 state->dmaCnt -= i; 1092 } 1093 break; 1094 1095 case SCSI_SYNCHRONOUS_XFER: 1096 /* 1097 * Acknowledge last byte and 1098 * signal a request for MSG_OUT. 1099 */ 1100 regs->comm = SII_INXFER | SII_ATN | 1101 SII_MSG_IN_PHASE | 1102 (comm & SII_STATE_MSK); 1103 SII_WAIT_UNTIL(dstat, regs->dstat, 1104 dstat & SII_DNE, 1105 SII_WAIT_COUNT, i); 1106 regs->dstat = SII_DNE; 1107 MachEmptyWriteBuffer(); 1108 sii_DoSync(regs, state); 1109 break; 1110 1111 default: 1112 reject: 1113 /* 1114 * Acknowledge last byte and 1115 * signal a request for MSG_OUT. 1116 */ 1117 regs->comm = SII_INXFER | SII_ATN | 1118 SII_MSG_IN_PHASE | 1119 (comm & SII_STATE_MSK); 1120 SII_WAIT_UNTIL(dstat, regs->dstat, 1121 dstat & SII_DNE, 1122 SII_WAIT_COUNT, i); 1123 regs->dstat = SII_DNE; 1124 MachEmptyWriteBuffer(); 1125 1126 /* wait for MSG_OUT phase */ 1127 SII_WAIT_UNTIL(dstat, regs->dstat, 1128 dstat & SII_TBE, 1129 SII_WAIT_COUNT, i); 1130 1131 /* send a reject message */ 1132 regs->data = SCSI_MESSAGE_REJECT; 1133 regs->comm = SII_INXFER | 1134 (regs->cstat & SII_STATE_MSK) | 1135 SII_MSG_OUT_PHASE; 1136 SII_WAIT_UNTIL(dstat, regs->dstat, 1137 dstat & SII_DNE, 1138 SII_WAIT_COUNT, i); 1139 regs->dstat = SII_DNE; 1140 MachEmptyWriteBuffer(); 1141 } 1142 break; 1143 1144 case SCSI_SAVE_DATA_POINTER: 1145 case SCSI_RESTORE_POINTERS: 1146 /* acknowledge last byte */ 1147 regs->comm = SII_INXFER | SII_MSG_IN_PHASE | 1148 (comm & SII_STATE_MSK); 1149 SII_WAIT_UNTIL(dstat, regs->dstat, 1150 dstat & SII_DNE, SII_WAIT_COUNT, i); 1151 regs->dstat = SII_DNE; 1152 MachEmptyWriteBuffer(); 1153 /* wait a short time for another msg */ 1154 SII_WAIT_UNTIL(dstat, regs->dstat, 1155 dstat & (SII_CI | SII_DI), 1156 SII_WAIT_COUNT, i); 1157 if (dstat & (SII_CI | SII_DI)) { 1158 #ifdef DEBUG 1159 if (sii_debug > 4) 1160 printf("cnt %d\n", i); 1161 #endif 1162 goto again; 1163 } 1164 break; 1165 1166 case SCSI_DISCONNECT: 1167 /* acknowledge last byte */ 1168 regs->comm = SII_INXFER | SII_MSG_IN_PHASE | 1169 (comm & SII_STATE_MSK); 1170 SII_WAIT_UNTIL(dstat, regs->dstat, 1171 dstat & SII_DNE, SII_WAIT_COUNT, i); 1172 regs->dstat = SII_DNE; 1173 MachEmptyWriteBuffer(); 1174 state->prevComm = comm; 1175 #ifdef DEBUG 1176 if (sii_debug > 4) 1177 printf("disconn %d ", sc->sc_target); 1178 #endif 1179 /* 1180 * Wait a short time for disconnect. 1181 * Don't be fooled if SII_BER happens first. 1182 * Note: a reselect may happen here. 1183 */ 1184 SII_WAIT_UNTIL(cstat, regs->cstat, 1185 cstat & (SII_RST | SII_SCH), 1186 SII_WAIT_COUNT, i); 1187 if ((cstat & (SII_RST | SII_SCH | 1188 SII_STATE_MSK)) != SII_SCH) { 1189 #ifdef DEBUG 1190 if (sii_debug > 4) 1191 printf("cnt %d\n", i); 1192 #endif 1193 dstat = regs->dstat; 1194 goto again; 1195 } 1196 regs->cstat = SII_SCH | SII_BER; 1197 regs->comm = 0; 1198 MachEmptyWriteBuffer(); 1199 sc->sc_target = -1; 1200 /* 1201 * Double check that we didn't miss a state 1202 * change between seeing it and clearing 1203 * the SII_SCH bit. 1204 */ 1205 i = regs->cstat; 1206 if (!(i & SII_SCH) && (i & SII_STATE_MSK) != 1207 (cstat & SII_STATE_MSK)) 1208 sii_StateChg(sc, i); 1209 break; 1210 1211 case SCSI_MESSAGE_REJECT: 1212 /* acknowledge last byte */ 1213 regs->comm = SII_INXFER | SII_MSG_IN_PHASE | 1214 (comm & SII_STATE_MSK); 1215 SII_WAIT_UNTIL(dstat, regs->dstat, 1216 dstat & SII_DNE, SII_WAIT_COUNT, i); 1217 regs->dstat = SII_DNE; 1218 MachEmptyWriteBuffer(); 1219 printf("sii%d: device %d: message reject.\n", 1220 sc - sii_softc, sc->sc_target); 1221 break; 1222 1223 default: 1224 if (!(msg & SCSI_IDENTIFY)) { 1225 printf("sii%d: device %d: couldn't handle message 0x%x... rejecting.\n", 1226 sc - sii_softc, sc->sc_target, 1227 msg); 1228 #ifdef DEBUG 1229 sii_DumpLog(); 1230 #endif 1231 goto reject; 1232 } 1233 /* acknowledge last byte */ 1234 regs->comm = SII_INXFER | SII_MSG_IN_PHASE | 1235 (comm & SII_STATE_MSK); 1236 SII_WAIT_UNTIL(dstat, regs->dstat, 1237 dstat & SII_DNE, SII_WAIT_COUNT, i); 1238 regs->dstat = SII_DNE; 1239 MachEmptyWriteBuffer(); 1240 /* may want to check LUN some day */ 1241 /* wait a short time for another msg */ 1242 SII_WAIT_UNTIL(dstat, regs->dstat, 1243 dstat & (SII_CI | SII_DI), 1244 SII_WAIT_COUNT, i); 1245 if (dstat & (SII_CI | SII_DI)) { 1246 #ifdef DEBUG 1247 if (sii_debug > 4) 1248 printf("cnt %d\n", i); 1249 #endif 1250 goto again; 1251 } 1252 } 1253 break; 1254 1255 case SII_MSG_OUT_PHASE: 1256 #ifdef DEBUG 1257 if (sii_debug > 4) 1258 printf("MsgOut\n"); 1259 #endif 1260 printf("MsgOut %x\n", state->flags); /* XXX */ 1261 1262 /* 1263 * Check for parity error. 1264 * Hardware will automatically set ATN 1265 * to request the device for a MSG_OUT phase. 1266 */ 1267 if (state->flags & PARITY_ERR) { 1268 state->flags &= ~PARITY_ERR; 1269 regs->data = SCSI_MESSAGE_PARITY_ERROR; 1270 } else 1271 regs->data = SCSI_NO_OP; 1272 regs->comm = SII_INXFER | (comm & SII_STATE_MSK) | 1273 SII_MSG_OUT_PHASE; 1274 MachEmptyWriteBuffer(); 1275 1276 /* wait a short time for XFER complete */ 1277 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE, 1278 SII_WAIT_COUNT, i); 1279 #ifdef DEBUG 1280 if (sii_debug > 4) 1281 printf("ds %x i %d\n", dstat, i); 1282 #endif 1283 /* just clear the DNE bit and check errors later */ 1284 if (dstat & SII_DNE) { 1285 regs->dstat = SII_DNE; 1286 MachEmptyWriteBuffer(); 1287 } 1288 break; 1289 1290 default: 1291 printf("sii%d: Couldn't handle phase %d... ignoring.\n", 1292 sc - sii_softc, dstat & SII_PHASE_MSK); 1293 } 1294 } 1295 1296 #ifdef DEBUG 1297 if (sii_debug > 3) 1298 printf("\n"); 1299 #endif 1300 /* 1301 * Check to make sure we won't be interrupted again. 1302 * Deglitch dstat register. 1303 */ 1304 msg = regs->dstat; 1305 while (msg != (dstat = regs->dstat)) 1306 msg = dstat; 1307 if (dstat & (SII_CI | SII_DI)) 1308 goto again; 1309 1310 if (sc->sc_target < 0) { 1311 /* look for another device that is ready */ 1312 for (i = 0; i < SII_NCMD; i++) { 1313 /* don't restart a disconnected command */ 1314 if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm) 1315 continue; 1316 sii_StartCmd(sc, i); 1317 break; 1318 } 1319 } 1320 return; 1321 1322 abort: 1323 /* jump here to abort the current command */ 1324 printf("sii%d: device %d: current command terminated\n", 1325 sc - sii_softc, sc->sc_target); 1326 #ifdef DEBUG 1327 sii_DumpLog(); 1328 #endif 1329 1330 if ((cstat = regs->cstat) & SII_CON) { 1331 /* try to send an abort msg for awhile */ 1332 regs->dstat = SII_DNE; 1333 regs->data = SCSI_ABORT; 1334 regs->comm = SII_INXFER | SII_ATN | (cstat & SII_STATE_MSK) | 1335 SII_MSG_OUT_PHASE; 1336 MachEmptyWriteBuffer(); 1337 SII_WAIT_UNTIL(dstat, regs->dstat, 1338 (dstat & (SII_DNE | SII_PHASE_MSK)) == 1339 (SII_DNE | SII_MSG_OUT_PHASE), 1340 2 * SII_WAIT_COUNT, i); 1341 #ifdef DEBUG 1342 if (sii_debug > 0) 1343 printf("Abort: cs %x ds %x i %d\n", cstat, dstat, i); 1344 #endif 1345 if (dstat & (SII_DNE | SII_PHASE_MSK) == 1346 (SII_DNE | SII_MSG_OUT_PHASE)) { 1347 /* disconnect if command in progress */ 1348 regs->comm = SII_DISCON; 1349 MachEmptyWriteBuffer(); 1350 SII_WAIT_UNTIL(cstat, regs->cstat, 1351 !(cstat & SII_CON), SII_WAIT_COUNT, i); 1352 } 1353 } else { 1354 #ifdef DEBUG 1355 if (sii_debug > 0) 1356 printf("Abort: cs %x\n", cstat); 1357 #endif 1358 } 1359 regs->cstat = 0xffff; 1360 regs->dstat = 0xffff; 1361 regs->comm = 0; 1362 MachEmptyWriteBuffer(); 1363 1364 i = sc->sc_target; 1365 sc->sc_target = -1; 1366 sii_CmdDone(sc, i, EIO); 1367 #ifdef DEBUG 1368 if (sii_debug > 4) 1369 printf("sii_DoIntr: after CmdDone target %d\n", sc->sc_target); 1370 #endif 1371 } 1372 1373 static void 1374 sii_StateChg(sc, cstat) 1375 register struct siisoftc *sc; 1376 register u_int cstat; 1377 { 1378 register SIIRegs *regs = sc->sc_regs; 1379 register State *state; 1380 register int i; 1381 1382 #ifdef DEBUG 1383 if (sii_debug > 4) 1384 printf("SCH: "); 1385 #endif 1386 1387 switch (cstat & SII_STATE_MSK) { 1388 case 0: 1389 /* disconnect */ 1390 i = sc->sc_target; 1391 sc->sc_target = -1; 1392 #ifdef DEBUG 1393 if (sii_debug > 4) 1394 printf("disconn %d ", i); 1395 #endif 1396 if (i >= 0 && !sc->sc_st[i].prevComm) { 1397 printf("sii%d: device %d: spurrious disconnect (%d)\n", 1398 sc - sii_softc, i, regs->slcsr); 1399 sc->sc_st[i].prevComm = 0; 1400 } 1401 break; 1402 1403 case SII_CON: 1404 /* connected as initiator */ 1405 i = regs->slcsr; 1406 if (sc->sc_target == i) 1407 break; 1408 printf("sii%d: device %d: connect to device %d??\n", 1409 sc - sii_softc, sc->sc_target, i); 1410 sc->sc_target = i; 1411 break; 1412 1413 case SII_DST: 1414 /* 1415 * Wait for CON to become valid, 1416 * chip is slow sometimes. 1417 */ 1418 SII_WAIT_UNTIL(cstat, regs->cstat, 1419 cstat & SII_CON, SII_WAIT_COUNT, i); 1420 if (!(cstat & SII_CON)) 1421 panic("sii resel"); 1422 /* FALLTHROUGH */ 1423 1424 case SII_CON | SII_DST: 1425 /* 1426 * Its a reselection. Save the ID and wait for 1427 * interrupts to tell us what to do next 1428 * (should be MSG_IN of IDENTIFY). 1429 * NOTE: sc_target may be >= 0 if we were in 1430 * the process of trying to start a command 1431 * and were reselected before the select 1432 * command finished. 1433 */ 1434 sc->sc_target = i = regs->destat; 1435 state = &sc->sc_st[i]; 1436 regs->comm = SII_CON | SII_DST | SII_MSG_IN_PHASE; 1437 regs->dmctrl = state->dmaReqAck; 1438 MachEmptyWriteBuffer(); 1439 if (!state->prevComm) { 1440 printf("sii%d: device %d: spurrious reselection\n", 1441 sc - sii_softc, i); 1442 break; 1443 } 1444 state->prevComm = 0; 1445 #ifdef DEBUG 1446 if (sii_debug > 4) 1447 printf("resel %d ", sc->sc_target); 1448 #endif 1449 break; 1450 1451 #ifdef notyet 1452 case SII_DST | SII_TGT: 1453 case SII_CON | SII_DST | SII_TGT: 1454 /* connected as target */ 1455 printf("sii%d: Selected by device %d as target!!\n", 1456 sc - sii_softc, regs->destat); 1457 regs->comm = SII_DISCON; 1458 MachEmptyWriteBuffer(); 1459 SII_WAIT_UNTIL(!(regs->cstat & SII_CON), 1460 SII_WAIT_COUNT, i); 1461 regs->cstat = 0xffff; 1462 regs->dstat = 0xffff; 1463 regs->comm = 0; 1464 break; 1465 #endif 1466 1467 default: 1468 printf("sii%d: Unknown state change (cs %x)!!\n", 1469 sc - sii_softc, cstat); 1470 #ifdef DEBUG 1471 sii_DumpLog(); 1472 #endif 1473 } 1474 } 1475 1476 /* 1477 * Read one byte of data. 1478 * If 'ack' is true, acknowledge the byte. 1479 */ 1480 static int 1481 sii_GetByte(regs, phase, ack) 1482 register SIIRegs *regs; 1483 int phase, ack; 1484 { 1485 register u_int dstat; 1486 register u_int state; 1487 register int i; 1488 register int data; 1489 1490 dstat = regs->dstat; 1491 state = regs->cstat & SII_STATE_MSK; 1492 if (!(dstat & SII_IBF) || (dstat & SII_MIS)) { 1493 regs->comm = state | phase; 1494 MachEmptyWriteBuffer(); 1495 /* wait a short time for IBF */ 1496 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_IBF, 1497 SII_WAIT_COUNT, i); 1498 #ifdef DEBUG 1499 if (!(dstat & SII_IBF)) 1500 printf("status no IBF\n"); 1501 #endif 1502 } 1503 if (dstat & SII_DNE) { /* XXX */ 1504 printf("sii_GetByte: DNE set 5\n"); 1505 sii_DumpLog(); 1506 regs->dstat = SII_DNE; 1507 } 1508 data = regs->data; 1509 /* check for parity error */ 1510 if (dstat & SII_IPE) { 1511 #ifdef DEBUG 1512 if (sii_debug > 4) 1513 printf("cnt0 %d\n", i); 1514 #endif 1515 printf("sii_GetByte: data %x ?? ds %x cm %x i %d\n", 1516 data, dstat, regs->comm, i); /* XXX */ 1517 data = -1; 1518 ack = 1; 1519 } 1520 1521 if (ack) { 1522 regs->comm = SII_INXFER | state | phase; 1523 MachEmptyWriteBuffer(); 1524 1525 /* wait a short time for XFER complete */ 1526 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE, 1527 SII_WAIT_COUNT, i); 1528 1529 /* clear the DNE */ 1530 if (dstat & SII_DNE) { 1531 regs->dstat = SII_DNE; 1532 MachEmptyWriteBuffer(); 1533 } 1534 } 1535 1536 return (data); 1537 } 1538 1539 /* 1540 * Exchange messages to initiate synchronous data transfers. 1541 */ 1542 static void 1543 sii_DoSync(regs, state) 1544 register SIIRegs *regs; 1545 register State *state; 1546 { 1547 register u_int dstat, comm; 1548 register int i, j; 1549 u_int len; 1550 1551 #ifdef DEBUG 1552 if (sii_debug) 1553 printf("sii_DoSync: len %d per %d req/ack %d\n", 1554 sii_buf[1], sii_buf[3], sii_buf[4]); 1555 #endif 1556 1557 /* SII chip can only handle a minimum transfer period of ??? */ 1558 if (sii_buf[3] < 64) 1559 sii_buf[3] = 64; 1560 /* SII chip can only handle a maximum REQ/ACK offset of 3 */ 1561 len = sii_buf[4]; 1562 if (len > 3) 1563 len = 3; 1564 1565 sii_buf[0] = SCSI_EXTENDED_MSG; 1566 sii_buf[1] = 3; /* message length */ 1567 sii_buf[2] = SCSI_SYNCHRONOUS_XFER; 1568 sii_buf[4] = len; 1569 #if 1 1570 comm = SII_INXFER | SII_ATN | SII_MSG_OUT_PHASE | 1571 (regs->cstat & SII_STATE_MSK); 1572 regs->comm = comm & ~SII_INXFER; 1573 for (j = 0; j < 5; j++) { 1574 /* wait for target to request the next byte */ 1575 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_TBE, 1576 SII_WAIT_COUNT, i); 1577 if (!(dstat & SII_TBE) || 1578 (dstat & SII_PHASE_MSK) != SII_MSG_OUT_PHASE) { 1579 printf("sii_DoSync: TBE? ds %x cm %x i %d\n", 1580 dstat, comm, i); /* XXX */ 1581 return; 1582 } 1583 1584 /* the last message byte should have ATN off */ 1585 if (j == 4) 1586 comm &= ~SII_ATN; 1587 1588 regs->data = sii_buf[j]; 1589 regs->comm = comm; 1590 MachEmptyWriteBuffer(); 1591 1592 /* wait a short time for XFER complete */ 1593 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE, 1594 SII_WAIT_COUNT, i); 1595 1596 if (!(dstat & SII_DNE)) { 1597 printf("sii_DoSync: DNE? ds %x cm %x i %d\n", 1598 dstat, comm, i); /* XXX */ 1599 return; 1600 } 1601 1602 /* clear the DNE, other errors handled later */ 1603 regs->dstat = SII_DNE; 1604 MachEmptyWriteBuffer(); 1605 } 1606 #else 1607 CopyToBuffer((u_short *)sii_buf, (volatile u_short *)SII_BUF_ADDR, 5); 1608 printf("sii_DoSync: %x %x %x ds %x\n", 1609 ((volatile u_short *)SII_BUF_ADDR)[0], 1610 ((volatile u_short *)SII_BUF_ADDR)[2], 1611 ((volatile u_short *)SII_BUF_ADDR)[4], 1612 regs->dstat); /* XXX */ 1613 regs->dmaddrl = (u_short)(SII_BUF_ADDR >> 1); 1614 regs->dmaddrh = (u_short)(SII_BUF_ADDR >> 17) & 03; 1615 regs->dmlotc = 5; 1616 regs->comm = SII_DMA | SII_INXFER | SII_ATN | 1617 (regs->cstat & SII_STATE_MSK) | SII_MSG_OUT_PHASE; 1618 MachEmptyWriteBuffer(); 1619 1620 /* wait a short time for XFER complete */ 1621 SII_WAIT_UNTIL(dstat, regs->dstat, 1622 (dstat & (SII_DNE | SII_TCZ)) == (SII_DNE | SII_TCZ), 1623 SII_WAIT_COUNT, i); 1624 1625 if ((dstat & (SII_DNE | SII_TCZ)) != (SII_DNE | SII_TCZ)) { 1626 printf("sii_DoSync: ds %x cm %x i %d lotc %d\n", 1627 dstat, regs->comm, i, regs->dmlotc); /* XXX */ 1628 sii_DumpLog(); /* XXX */ 1629 return; 1630 } 1631 /* clear the DNE, other errors handled later */ 1632 regs->dstat = SII_DNE; 1633 MachEmptyWriteBuffer(); 1634 #endif 1635 1636 #if 0 1637 SII_WAIT_UNTIL(dstat, regs->dstat, dstat & (SII_CI | SII_DI), 1638 SII_WAIT_COUNT, i); 1639 printf("sii_DoSync: ds %x cm %x i %d lotc %d\n", 1640 dstat, regs->comm, i, regs->dmlotc); /* XXX */ 1641 #endif 1642 1643 state->dmaReqAck = len; 1644 } 1645 1646 /* 1647 * Issue the sequence of commands to the controller to start DMA. 1648 * NOTE: the data buffer should be word-aligned for DMA out. 1649 */ 1650 static void 1651 sii_StartDMA(regs, phase, dmaAddr, size) 1652 register SIIRegs *regs; /* which SII to use */ 1653 int phase; /* phase to send/receive data */ 1654 u_short *dmaAddr; /* DMA buffer address */ 1655 int size; /* # of bytes to transfer */ 1656 { 1657 1658 if (regs->dstat & SII_DNE) { /* XXX */ 1659 regs->dstat = SII_DNE; 1660 printf("sii_StartDMA: DNE set\n"); 1661 sii_DumpLog(); 1662 } 1663 regs->dmaddrl = ((u_long)dmaAddr >> 1); 1664 regs->dmaddrh = ((u_long)dmaAddr >> 17) & 03; 1665 regs->dmlotc = size; 1666 regs->comm = SII_DMA | SII_INXFER | (regs->cstat & SII_STATE_MSK) | 1667 phase; 1668 MachEmptyWriteBuffer(); 1669 1670 #ifdef DEBUG 1671 if (sii_debug > 5) { 1672 printf("sii_StartDMA: cs 0x%x, ds 0x%x, cm 0x%x, size %d\n", 1673 regs->cstat, regs->dstat, regs->comm, size); 1674 } 1675 #endif 1676 } 1677 1678 /* 1679 * Call the device driver's 'done' routine to let it know the command is done. 1680 * The 'done' routine may try to start another command. 1681 * To be fair, we should start pending commands for other devices 1682 * before allowing the same device to start another command. 1683 */ 1684 static void 1685 sii_CmdDone(sc, target, error) 1686 register struct siisoftc *sc; /* which SII to use */ 1687 int target; /* which device is done */ 1688 int error; /* error code if any errors */ 1689 { 1690 register ScsiCmd *scsicmd; 1691 register int i; 1692 1693 scsicmd = sc->sc_cmd[target]; 1694 #ifdef DIAGNOSTIC 1695 if (target < 0 || !scsicmd) 1696 panic("sii_CmdDone"); 1697 #endif 1698 sc->sc_cmd[target] = (ScsiCmd *)0; 1699 #ifdef DEBUG 1700 if (sii_debug > 1) { 1701 printf("sii_CmdDone: %s target %d cmd %x err %d resid %d\n", 1702 scsicmd->sd->sd_driver->d_name, target, 1703 scsicmd->cmd[0], error, sc->sc_st[target].buflen); 1704 } 1705 #endif 1706 1707 /* look for another device that is ready */ 1708 for (i = 0; i < SII_NCMD; i++) { 1709 /* don't restart a disconnected command */ 1710 if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm) 1711 continue; 1712 sii_StartCmd(sc, i); 1713 break; 1714 } 1715 1716 (*scsicmd->sd->sd_driver->d_done)(scsicmd->unit, error, 1717 sc->sc_st[target].buflen, sc->sc_st[target].statusByte); 1718 } 1719 1720 #ifdef DEBUG 1721 sii_DumpLog() 1722 { 1723 register struct sii_log *lp; 1724 1725 printf("sii: cmd %x bn %d cnt %d\n", sii_debug_cmd, sii_debug_bn, 1726 sii_debug_sz); 1727 lp = sii_logp; 1728 do { 1729 printf("target %d cs %x ds %x cm %x msg %x rlen %x dlen %x\n", 1730 lp->target, lp->cstat, lp->dstat, lp->comm, lp->msg, 1731 lp->rlen, lp->dlen); 1732 if (++lp >= &sii_log[NLOG]) 1733 lp = sii_log; 1734 } while (lp != sii_logp); 1735 } 1736 #endif 1737 #endif 1738