UInt8 wd33c93ReadAuxStatus(WD33C93* wd33c93, UInt16 port) { UInt8 rv = wd33c93->regs[REG_AUX_STATUS]; if (wd33c93->phase == Execute) { wd33c93->counter = scsiDeviceExecutingCmd(TARGET, &wd33c93->phase, &wd33c93->blockCounter); switch (wd33c93->phase) { case Status: wd33c93->regs[REG_TLUN] = scsiDeviceGetStatusCode(TARGET); scsiDeviceMsgIn(TARGET); wd33c93->regs[REG_SCSI_STATUS] = SS_XFER_END; wd33c93Disconnect(wd33c93); break; case Execute: break; default: wd33c93->regs[REG_AUX_STATUS] |= AS_DBR; } } return rv; }
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 wd33c93ExecCmd(WD33C93* wd33c93, UInt8 value) { int atn = 0; if (wd33c93->regs[REG_AUX_STATUS] & AS_CIP) { SCSILOG("wd33c93ExecCmd() CIP error\n"); return; } //wd33c93->regs[REG_AUX_STATUS] |= AS_CIP; wd33c93->regs[REG_CMD] = value; switch (value) { case 0x00: /* Reset controller (software reset) */ SCSILOG("wd33c93 [CMD] Reset controller\n"); memset(wd33c93->regs + 1, 0, 0x1a); wd33c93Disconnect(wd33c93); wd33c93->latch = 0; wd33c93->regs[REG_SCSI_STATUS] = (wd33c93->regs[REG_OWN_ID] & OWN_EAF) ? SS_RESET_ADV : SS_RESET; break; case 0x02: /* Assert ATN */ SCSILOG("wd33c93 [CMD] Assert ATN\n"); break; case 0x04: /* Disconnect */ SCSILOG("wd33c93 [CMD] Disconnect\n"); wd33c93Disconnect(wd33c93); break; case 0x06: /* Select with ATN (Lv2) */ atn = 1; case 0x07: /* Select Without ATN (Lv2) */ SCSILOG1("wd33c93 [CMD] Select (ATN %d)\n", atn); wd33c93->targetId = wd33c93->regs[REG_DST_ID] & 7; wd33c93->regs[REG_SCSI_STATUS] = SS_SEL_TIMEOUT; wd33c93->tc = 0; wd33c93->regs[REG_AUX_STATUS] = AS_INT; break; case 0x08: /* Select with ATN and transfer (Lv2) */ atn = 1; case 0x09: /* Select without ATN and Transfer (Lv2) */ SCSILOG1("wd33c93 [CMD] Select and transfer (ATN %d)\n", atn); wd33c93->targetId = wd33c93->regs[REG_DST_ID] & 7; if (!wd33c93->devBusy && wd33c93->targetId < wd33c93->maxDev && /* wd33c93->targetId != wd33c93->myId && */ scsiDeviceSelection(TARGET)) { if (atn) scsiDeviceMsgOut(TARGET, wd33c93->regs[REG_TLUN] | 0x80); wd33c93->devBusy = 1; wd33c93->counter = scsiDeviceExecuteCmd( TARGET, &wd33c93->regs[REG_CDB1], &wd33c93->phase, &wd33c93->blockCounter); switch (wd33c93->phase) { case Status: wd33c93->devBusy = 0; wd33c93->regs[REG_TLUN] = scsiDeviceGetStatusCode(TARGET); scsiDeviceMsgIn(TARGET); wd33c93->regs[REG_SCSI_STATUS] = SS_XFER_END; wd33c93Disconnect(wd33c93); break; case Execute: wd33c93->regs[REG_AUX_STATUS] = AS_CIP | AS_BSY; wd33c93->pBuf = wd33c93->buffer; break; default: wd33c93->devBusy = 0; wd33c93->regs[REG_AUX_STATUS] = AS_CIP | AS_BSY | AS_DBR; wd33c93->pBuf = wd33c93->buffer; } //wd33c93->regs[REG_SRC_ID] |= wd33c93->regs[REG_DST_ID] & 7; } else { //wd33c93->timeout = boardSystemTime() + boardFrequency() / 16384; //wd33c93->timerRunning = 1; //boardTimerAdd(wd33c93->timer, wd33c93->timeout); SCSILOG1("wd33c93 %d timeout\n", wd33c93->targetId); wd33c93->tc = 0; wd33c93->regs[REG_SCSI_STATUS] = SS_SEL_TIMEOUT; wd33c93->regs[REG_AUX_STATUS] = AS_INT; } break; case 0x18: /* Translate Address (Lv2) */ default: SCSILOG1("wd33c93 [CMD] unsupport command %x\n", value); break; } }
void wd33c93WriteCtrl(WD33C93* wd33c93, UInt16 port, UInt8 value) { //SCSILOG2("wd33c93 write #%X, %X\n", wd33c93->latch, value); switch (wd33c93->latch) { case REG_OWN_ID: wd33c93->regs[REG_OWN_ID] = value; wd33c93->myId = value & 7; SCSILOG1("wd33c93 myid = %X\n", wd33c93->myId); break; case REG_TCH: wd33c93->tc = (wd33c93->tc & 0x0000ffff) + (value << 16); break; case REG_TCM: wd33c93->tc = (wd33c93->tc & 0x00ff00ff) + (value << 8); break; case REG_TCL: wd33c93->tc = (wd33c93->tc & 0x00ffff00) + value; break; case REG_CMD_PHASE: SCSILOG1("wd33c93 CMD_PHASE = %X\n", value); wd33c93->regs[REG_CMD_PHASE] = value; break; case REG_CMD: wd33c93ExecCmd(wd33c93, value); return; case REG_DATA: wd33c93->regs[REG_DATA] = value; if (wd33c93->phase == DataOut) { *wd33c93->pBuf++ = value; --wd33c93->tc; if (--wd33c93->counter == 0) { wd33c93->counter = scsiDeviceDataOut(TARGET, &wd33c93->blockCounter); if (wd33c93->counter) { wd33c93->pBuf = wd33c93->buffer; return; } wd33c93->regs[REG_TLUN] = scsiDeviceGetStatusCode(TARGET); scsiDeviceMsgIn(TARGET); wd33c93->regs[REG_SCSI_STATUS] = SS_XFER_END; wd33c93Disconnect(wd33c93); } } return; case REG_AUX_STATUS: return; default: if (wd33c93->latch <= REG_SRC_ID) { wd33c93->regs[wd33c93->latch] = value; } break; } wd33c93->latch++; wd33c93->latch &= 0x1f; }
static void mb89352SetACKREQ(MB89352* spc, UInt8* value) { // REQ check if ((spc->regs[REG_PSNS] & (PSNS_REQ | PSNS_BSY)) != (PSNS_REQ | PSNS_BSY)) { SCSILOG("set ACK/REQ: REQ/BSY check error\n"); if (spc->regs[REG_PSNS] & PSNS_IO) { // SCSI -> SPC *value = 0xff; } return; } // phase check if (spc->regs[FIX_PCTL] != (spc->regs[REG_PSNS] & 7)) { SCSILOG("set ACK/REQ: phase check error\n"); if (spc->regs[REG_PSNS] & PSNS_IO) { // SCSI -> SPC *value = 0xff; } if (spc->isTransfer) { spc->regs[REG_INTS] |= INTS_ServiceRequited; } return; } switch (spc->phase) { // Transfer phase (data in) case DataIn: *value = *spc->pBuffer; ++spc->pBuffer; spc->regs[REG_PSNS] = PSNS_ACK | PSNS_BSY | PSNS_DATAIN; break; //Transfer phase (data out) case DataOut: *spc->pBuffer = *value; ++spc->pBuffer; spc->regs[REG_PSNS] = PSNS_ACK | PSNS_BSY | PSNS_DATAOUT; break; // Command phase case Command: if (spc->counter < 0) { //Initialize command routine spc->pCdb = spc->cdb; spc->counter = cdbLength(*value); } *spc->pCdb = *value; ++spc->pCdb; spc->regs[REG_PSNS] = PSNS_ACK | PSNS_BSY | PSNS_COMMAND; break; // Status phase case Status: *value = scsiDeviceGetStatusCode(TARGET); spc->regs[REG_PSNS] = PSNS_ACK | PSNS_BSY | PSNS_STATUS; break; // Message In phase case MsgIn: *value = scsiDeviceMsgIn(TARGET); spc->regs[REG_PSNS] = PSNS_ACK | PSNS_BSY | PSNS_MSGIN; break; // Message Out phase case MsgOut: spc->msgin |= scsiDeviceMsgOut(TARGET, *value); spc->regs[REG_PSNS] = PSNS_ACK | PSNS_BSY | PSNS_MSGOUT; break; default: SCSILOG("set ACK/REQ code error\n"); break; } } // end of mb89352SetACKREQ()