Beispiel #1
0
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);
}
Beispiel #2
0
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();
}
Beispiel #3
0
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();
}
Beispiel #4
0
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;
}
Beispiel #6
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;
    }
}
Beispiel #7
0
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;
        }
Beispiel #8
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()
Beispiel #9
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()