Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
0
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;
    }
}
Exemple #4
0
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;
}
Exemple #5
0
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()