UInt8 wd33c93ReadCtrl(WD33C93* wd33c93, UInt16 port) { UInt8 rv; switch (wd33c93->latch) { case REG_SCSI_STATUS: rv = wd33c93->regs[REG_SCSI_STATUS]; //SCSILOG1("wd33c93 SCSI_STATUS = %X\n", rv); if (rv != SS_XFER_END) { wd33c93->regs[REG_AUX_STATUS] &= ~AS_INT; } else { wd33c93->regs[REG_SCSI_STATUS] = SS_DISCONNECT; wd33c93->regs[REG_AUX_STATUS] = AS_INT; } break; case REG_DATA: if (wd33c93->phase == DataIn) { rv = *wd33c93->pBuf++; wd33c93->regs[REG_DATA] = rv; --wd33c93->tc; if (--wd33c93->counter == 0) { if (wd33c93->blockCounter > 0) { wd33c93->counter = scsiDeviceDataIn(TARGET, &wd33c93->blockCounter); if (wd33c93->counter) { wd33c93->pBuf = wd33c93->buffer; return rv; } } wd33c93->regs[REG_TLUN] = scsiDeviceGetStatusCode(TARGET); scsiDeviceMsgIn(TARGET); wd33c93->regs[REG_SCSI_STATUS] = SS_XFER_END; wd33c93Disconnect(wd33c93); } } else { rv = wd33c93->regs[REG_DATA]; } return rv; case REG_TCH: rv = (UInt8)((wd33c93->tc >> 16) & 0xff); break; case REG_TCM: rv = (UInt8)((wd33c93->tc >> 8) & 0xff); break; case REG_TCL: rv = (UInt8)(wd33c93->tc & 0xff); break; case REG_AUX_STATUS: return wd33c93ReadAuxStatus(wd33c93, port); default: rv = wd33c93->regs[wd33c93->latch]; break; } //SCSILOG2("wd33c93 read #%X, %X\n", wd33c93->latch, rv); if (wd33c93->latch != REG_CMD) { wd33c93->latch++; wd33c93->latch &= 0x1f; } return rv; }
static void mb89352ResetACKREQ(MB89352* spc) { // ACK check if ((spc->regs[REG_PSNS] & (PSNS_ACK | PSNS_BSY)) != (PSNS_ACK | PSNS_BSY)) { SCSILOG("reset ACK/REQ: ACK/BSY check error\n"); return; } // phase check if (spc->regs[FIX_PCTL] != (spc->regs[REG_PSNS] & 7)) { SCSILOG("reset ACK/REQ: phase check error\n"); if (spc->isTransfer) { spc->regs[REG_INTS] |= INTS_ServiceRequited; } return; } switch (spc->phase) { // Transfer phase (data in) case DataIn: if (--spc->counter > 0) { spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_DATAIN; } else { if (spc->blockCounter > 0) { spc->counter = scsiDeviceDataIn(TARGET, &spc->blockCounter); if (spc->counter) { spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_DATAIN; spc->pBuffer = spc->buffer; break; } } spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_STATUS; spc->phase = Status; } break; // Transfer phase (data out) case DataOut: if (--spc->counter > 0) { spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_DATAOUT; } else { spc->counter = scsiDeviceDataOut(TARGET, &spc->blockCounter); if (spc->counter) { spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_DATAOUT; spc->pBuffer = spc->buffer; break; } spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_STATUS; spc->phase = Status; } break; // Command phase case Command: if (--spc->counter > 0) { spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_COMMAND; } else { spc->pBuffer = spc->buffer; // reset buffer pointer spc->devBusy = 1; spc->counter = scsiDeviceExecuteCmd(TARGET, spc->cdb, &spc->phase, &spc->blockCounter); switch (spc->phase) { case DataIn: spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_DATAIN; break; case DataOut: spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_DATAOUT; break; case Status: spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_STATUS; break; case Execute: spc->regs[REG_PSNS] = PSNS_BSY; return; default: SCSILOG("phase error\n"); break; } spc->devBusy = 0; } break; // Status phase case Status: spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_MSGIN; spc->phase = MsgIn; break; // Message In phase case MsgIn: if (spc->msgin <= 0) { mb89352Disconnect(spc); break; } spc->msgin = 0; // throw to MsgOut... // Message Out phase case MsgOut: if (spc->msgin == -1) { mb89352Disconnect(spc); return; } if (spc->atn) { if (spc->msgin & 2) { mb89352Disconnect(spc); return; } spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_MSGOUT; return; } if (spc->msgin & 1) { spc->phase = MsgIn; } else { if (spc->msgin & 4) { spc->phase = Status; spc->nextPhase = -1; } else { spc->phase = spc->nextPhase; spc->nextPhase = -1; } } spc->msgin = 0; switch (spc->phase) { case Command: spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_COMMAND; break; case DataIn: spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_DATAIN; break; case DataOut: spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_DATAOUT; break; case Status: spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_STATUS; break; case MsgIn: spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_MSGIN; break; default: SCSILOG("MsgOut code error\n"); break; } return; default: //assert(false); SCSILOG("reset ACK/REQ code error\n"); break; } if (spc->atn) { spc->nextPhase = spc->phase; spc->phase = MsgOut; spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_MSGOUT; } } // end of mb89352ResetACKREQ()