void wd33c93Destroy(WD33C93* wd33c93) { int i; for (i = 0; i < 8; ++i) { if (wd33c93->dev[i]) scsiDeviceDestroy(wd33c93->dev[i]); } //boardTimerDestroy(wd33c93->timer); SCSILOG("WD33C93 destroy\n"); scsiDeviceLogClose(); archCdromBufferFree(wd33c93->buffer); free(wd33c93); }
static void wd33c93Disconnect(WD33C93* wd33c93) { if (wd33c93->phase != BusFree) { if ((wd33c93->targetId >= 0) && (wd33c93->targetId < wd33c93->maxDev)) { scsiDeviceDisconnect(TARGET); } if (wd33c93->regs[REG_SCSI_STATUS] != SS_XFER_END) { wd33c93->regs[REG_SCSI_STATUS] = SS_DISCONNECT; } wd33c93->regs[REG_AUX_STATUS] = AS_INT; wd33c93->phase = BusFree; //wd33c93->nextPhase = -1; } //wd33c93->mci = -1; wd33c93->tc = 0; //wd33c93->atn = 0; SCSILOG("busfree()\n\n"); scsiDeviceLogFlush(); }
static void mb89352Disconnect(MB89352* spc) { if (spc->phase != BusFree) { if ((spc->targetId >= 0) && (spc->targetId < 8)) { scsiDeviceDisconnect(TARGET); } spc->regs[REG_INTS] |= INTS_Disconnected; spc->phase = BusFree; spc->nextPhase = -1; } spc->regs[REG_PSNS] = 0; spc->isBusy = 0; spc->isTransfer = 0; spc->counter = 0; spc->tc = 0; spc->atn = 0; SCSILOG("busfree()\n\n"); scsiDeviceLogFlush(); }
void wd33c93Reset(WD33C93* wd33c93, int scsireset) { int i; SCSILOG("wd33c93 reset\n"); scsiDeviceLogFlush(); // initialized register memset(wd33c93->regs, 0, 0x1b); memset(wd33c93->regs + 0x1b, 0xff, 4); wd33c93->regs[REG_AUX_STATUS] = AS_INT; wd33c93->myId = 0; wd33c93->latch = 0; wd33c93->tc = 0; wd33c93->phase = BusFree; wd33c93->pBuf = wd33c93->buffer; if (scsireset) { for (i = 0; i < wd33c93->maxDev; ++i) { scsiDeviceReset(wd33c93->dev[i]); } } }
static int scsiDeviceDiskChanged(SCSIDEVICE* scsi) { FileProperties* pDisk; int changed = diskChanged(scsi->diskId); if (changed) { scsi->motor = 1; pDisk = &propGetGlobalProperties()->media.disks[scsi->diskId]; if (scsi->changeCheck2) { scsi->changeCheck2 = 0; if (scsi->inserted && (strcmp(scsi->disk.fileName, pDisk->fileName) == 0) && (strcmp(scsi->disk.fileNameInZip, pDisk->fileNameInZip) == 0)) { SCSILOG("Disk change invalidity\n\n"); return 0; } } scsi->changed = 1; scsi->disk = *pDisk; scsi->inserted = 1; SCSILOG1("hdd %d: disk change\n", scsi->scsiId); SCSILOG1("filename: %s\n", scsi->disk.fileName); SCSILOG1(" zip: %s\n", scsi->disk.fileNameInZip); } else { if (scsi->inserted & !diskPresent(scsi->diskId)) { scsi->inserted = 0; scsi->motor = 0; scsi->changed = 1; changed = 1; } } if (changed && (scsi->mode & MODE_UNITATTENTION)) { scsi->reset = 1; } return changed; }
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 mb89352WriteRegister(MB89352* spc, UInt8 reg, UInt8 value) { int err; int flag; int x; int i; int cmd; //SCSILOG2("SPC write register: %x %x\n", reg, value); switch (reg) { case REG_DREG: // write data Register mb89352WriteDREG(spc, value); break; case REG_SCMD: if (!spc->isEnabled) { break; } // bus reset if (value & 0x10) { if (((spc->regs[REG_SCMD] & 0x10) == 0) & (spc->regs[REG_SCTL] == 0)) { SCSILOG("SPC: bus reset\n"); spc->rst = 1; spc->regs[REG_INTS] |= INTS_ResetCondition; for (i = 0; i < 8; ++i) { scsiDeviceBusReset(spc->scsiDevice[i]); } mb89352Disconnect(spc); // alternative routine } } else { spc->rst = 0; } spc->regs[REG_SCMD] = value; cmd = value >> 5; //SCSILOG1("SPC command: %x\n", cmd); // execute spc command switch (cmd) { case CMD_Set_ACK_REQ: switch (spc->phase) { case DataIn: case Status: case MsgIn: mb89352SetACKREQ(spc, (UInt8*)&spc->regs[REG_TEMP]); break; default: mb89352SetACKREQ(spc, (UInt8*)&spc->regs[REG_TEMPWR]); } break; case CMD_Reset_ACK_REQ: mb89352ResetACKREQ(spc); break; case CMD_Select: if (spc->rst) { spc->regs[REG_INTS] |= INTS_TimeOut; break; } if (spc->regs[REG_PCTL] & 1) { SCSILOG1("reselection error %x", spc->regs[REG_TEMPWR]); spc->regs[REG_INTS] |= INTS_TimeOut; mb89352Disconnect(spc); break; } x = spc->regs[REG_BDID] & spc->regs[REG_TEMPWR]; if (spc->phase == BusFree && x && x != spc->regs[REG_TEMPWR]) { x = spc->regs[REG_TEMPWR] & ~spc->regs[REG_BDID]; // the targetID is calculated. // It is given priority that the number is large. for (spc->targetId = 0; spc->targetId < 8; ++spc->targetId) { x = x >> 1; if (x == 0) { break; } } if (!spc->devBusy && scsiDeviceSelection(TARGET)) { SCSILOG1("selection: %d OK\n", spc->targetId); spc->regs[REG_INTS] |= INTS_CommandComplete; spc->isBusy = 1; spc->msgin = 0; spc->counter = -1; err = 0; if (spc->atn) { spc->phase = MsgOut; spc->nextPhase = Command; spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_MSGOUT; } else { spc->phase = Command; spc->nextPhase = -1; spc->regs[REG_PSNS] = PSNS_REQ | PSNS_BSY | PSNS_COMMAND; } } else { err = 1; } } else { err = 1; #ifdef SCSIDEBUG spc->targetId = -1; #endif } if (err) { SCSILOG1("selection: %d error\n", spc->targetId); spc->regs[REG_INTS] |= INTS_TimeOut; mb89352Disconnect(spc); } break; // hardware transfer case CMD_Transfer: SCSILOG2("CMD_Transfer %d (%d)\n", spc->tc, spc->tc / 512); if ((spc->regs[FIX_PCTL] == (spc->regs[REG_PSNS] & 7)) && (spc->regs[REG_PSNS] & (PSNS_REQ | PSNS_BSY))) { spc->isTransfer = 1; // set Xfer in Progress } else { spc->regs[REG_INTS] |= INTS_ServiceRequited; SCSILOG("phase error\n"); } break; case CMD_BusRelease: SCSILOG("CMD_BusRelease\n"); mb89352Disconnect(spc); break; case CMD_SetATN: SCSILOG("CMD_SetATN\n"); spc->atn = PSNS_ATN; break; case CMD_ResetATN: SCSILOG("CMD_ResetATN\n"); spc->atn = 0; break; case CMD_TransferPause: // nothing is done in the initiator. SCSILOG("CMD_TransferPause\n"); break; }
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()
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()