示例#1
0
文件: wd33c93.c 项目: imclab/CocoaMSX
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;
}
示例#2
0
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()