void
Z47Controller::commandComplete(void)
{
    debugss(ssH47, ALL, "state: %s\n", getStateStr(curState));

    curState     = st_None_c;
    curLinkState = st_Link_AwaitingReadyState_c;
    countDown_m  = 120;

    if (linkToHost_m)
    {
        linkToHost_m->setBusy(false);
        // linkToHost_m->setDTR(true);
    }

    debugss(ssH47, ALL, "=============END of CMD============\n");

}
void ProcessVariable::subscribe(Guard &guard)
{
    guard.check(__FILE__, __LINE__, mutex);
    if (dbr_type == 0)
        throw GenericException(__FILE__, __LINE__,
                               "Cannot subscribe to %s, never connected",
                               getName().c_str());
    // Prevent multiple subscriptions
    if (isSubscribed(guard))
        return;
    // While we were unlocked, a disconnect or stop() could have happend,
    // in which case we need to bail out.
    if (id == 0 || state != CONNECTED)
    {
        LOG_MSG("'%s': Skipped subscription, state %s, id 0x%lu.\n",
                getName().c_str(),  getStateStr(guard), (unsigned long) id);
        return;
    }
    chid     _id    = id;
    evid     _ev_id = 0;
    DbrType  _type  = dbr_type;
    DbrCount _count = dbr_count;
    {   // Release around CA call??
        // --  GuardRelease release(__FILE__, __LINE__, guard);
        // Right now, could a stop() and ca_clear_channel(id) happen,
        // so that ca_create_subscription() uses an invalid id?
        //
        // Task A, CAC client:
        // control_callback, pvConnected, subscribe
        //
        // Task B, Engine or HTTPD:
        // stop, clear_channel
        //
        // LockTest.cpp indicates that the clear_channel() will wait
        // for the CAC library to leabe the control_callback.
        // So even though we unlock the ProcessVariable and somebody
        // could invoke stop() and set id=0, we have the copied _id,
        // and the ca_clear_channel(id) won't happen until we leave
        // the control_callback.
        // This of course only handles the use case of the engine
        // where subscribe is invoked from control_callback & pvConnected.
        // to be on the safe side, we keep the guard and prevent a stop(),
        // until we find a deadlock that forces us to reconsider....
        {
            int status;
            try
            {
                status = ca_create_subscription(_type, _count, _id,
                                                DBE_LOG | DBE_ALARM,
                                                value_callback, this, &_ev_id);
            }
            catch (std::exception &e)
            {
                LOG_MSG("ProcessVariable::subscribe(%s): %s\n",
                        getName().c_str(), e.what());
            }
            catch (...)
            {
                LOG_MSG("ProcessVariable::subscribe(%s): Unknown Exception\n",
                        getName().c_str());
            } 
            if (status != ECA_NORMAL)
            {
                LOG_MSG("%s: ca_create_subscription failed: %s\n",
                        getName().c_str(), ca_message(status));
                return;
            }
            Guard ctx_guard(__FILE__, __LINE__, ctx);
            ctx.requestFlush(ctx_guard);
        }
    }
    ev_id = _ev_id;
    LOG_ASSERT(ev_id != 0);
#ifdef CHECK_EVID
    void *user = peek_evid_userptr(ev_id);
    LOG_ASSERT(user == this);
#endif
}
void
Z47Controller::processCmd(BYTE cmd)
{
    debugss(ssH47, ALL, "=============START of CMD=============\n");

    debugss(ssH47, ALL, "state - %s: cmd - 0x%02x\n", getStateStr(curState), cmd);

    countDown_m     = coundDown_Default_c;
    statePosition_m = 0;
    curLinkState    = st_Link_Ready_c;

    // first lower DTR, and set busy
    if (linkToHost_m)
    {
        linkToHost_m->setDTR(false);
        linkToHost_m->setBusy(true);
    }


    switch (cmd)
    {
        case cmd_Boot_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_Boot_c %d\n", cmd);
            // not sure if this is used by heathkit boot. Likes like they just read
            // the first 10 sectors.
            curState = st_Boot_c;
            break;

        case cmd_ReadCntrlStat_c:
            debugss(ssH47, INFO, "cmd_ReadCntrlStat_c\n");
            curState = st_ReadCntrlStat_c;
            processReadControlStatus();
            break;

        case cmd_ReadAuxStat_c:
            debugss(ssH47, INFO, "Read Aux Status\n");
            curState    = st_ReadAuxStat_c;
            processReadAuxStatus();
            countDown_m = 20;

            break;

        case cmd_LoadSectorCount_c:
            debugss(ssH47, INFO, "cmd_LoadSectorCount_c\n");
            curState    = st_LoadSectorCount_c;
            processLoadSectorCount();
            countDown_m = 20;

            break;

        case cmd_ReadLastAddr_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_ReadLastAddr_c %d\n", cmd);
            break;

        case cmd_ReadSectors_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_ReadSectors_c %d\n", cmd);
            break;

        case cmd_WriteSectors_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_WriteSectors_c %d\n", cmd);
            break;

        case cmd_ReadSectorsBuffered_c:
            debugss(ssH47, INFO, "cmd_ReadSectorsBuffered_c %d\n", cmd);
            curState        = st_ReadSectorsBuffered_c;
            bytesToTransfer = sectorSize;
            processReadSectorsBufffered();
            break;

        case cmd_WriteSectorsBuffered_c:
            debugss(ssH47, INFO, "cmd_WriteSectorsBuffered_c %d\n", cmd);
            curState        = st_WriteSectorsBuffered_c;
            bytesToTransfer = sectorSize;
            processReadSectorsBufffered();
            break;

        case cmd_WriteSectorsAndDelete_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_WriteSectorsAndDelete_c %d\n", cmd);
            break;

        case cmd_WriteSectorsBufferedAndDelete_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_WriteSectorsBufferedAndDelete_c %d\n", cmd);
            break;

        case cmd_Copy_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_Copy_c %d\n", cmd);
            break;

        case cmd_FormatIBM_SD_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_FormatIBM_SD_c %d\n", cmd);
            break;

        case cmd_Format_SD_c:
            debugss(ssH47, INFO, "cmd_Format_SD_c %d\n", cmd);
            curState = st_Format_SD_c;
            processFormatSingleDensity();
            break;

        case cmd_FormatIBM_DD_c:
            debugss(ssH47, INFO, "cmd_FormatIBM_DD_c %d\n", cmd);
            curState = st_FormatIBM_DD_c;
            processFormatIBMDoubleDensity();
            break;

        case cmd_Format_DD_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_Format_DD_c %d\n", cmd);
            curState = st_Format_DD_c;
            processFormatDoubleDensity();
            break;

        case cmd_ReadReadyStatus_c:
            debugss(ssH47, INFO, "Read Ready Status\n");
            curState = st_ReadReadyStatus_c;
            processReadReadyStatus();
            break;

        case cmd_SpecialFunction1_c:
        case cmd_SpecialFunction2_c:
        case cmd_SpecialFunction3_c:
        case cmd_SpecialFunction4_c:
        case cmd_SpecialFunction5_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_SpecialFunctionx_c %d\n", cmd);

            break;

        case cmd_SetDriveCharacteristics_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_SetDriveCharacteristics_c %d\n", cmd);
            break;

        case cmd_SeekToTrack_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_SeekToTrack_c %d\n", cmd);
            break;

        case cmd_DiskStatus_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_DiskStatus_c %d\n", cmd);
            break;

        case cmd_ReadLogical_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_ReadLogical_c %d\n", cmd);
            break;

        case cmd_WriteLogical_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_WriteLogical_c %d\n", cmd);
            break;

        case cmd_ReadBufferedLogical_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_ReadBufferedLogical_c %d\n",
                    cmd);
            break;

        case cmd_WriteBufferedLogical_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_WriteBufferedLogical_c %d\n", cmd);
            break;

        case cmd_WriteDeletedDataLogical:
            debugss(ssH47, ERROR, "Unsupported - cmd_WriteDeletedDataLogical %d\n", cmd);
            break;

        case cmd_WriteBufferedDeletedDataLogical_c:
            debugss(ssH47, ERROR, "Unsupported - cmd_WriteBufferedDeletedDataLogical_c %d\n", cmd);
            break;

        default:
            debugss(ssH47, ERROR, "Unknown command - default %d\n", cmd);
            invalidCommandReceived_m = true;

            if (linkToHost_m)
            {
                linkToHost_m->setError(true);
            }

            commandComplete();
            break;
    }

    switch (curLinkState)
    {
        case st_Link_Undefined_c:
            debugss(ssH47, ERROR, "Unexpected Undefined link state\n");
            break;

        case st_Link_Ready_c:
            debugss(ssH47, INFO, "link ready state - do nothing\n");
            break;

        case st_Link_AwaitingToReqReceive_c:
            debugss(ssH47, INFO, "link awaiting receive state\n");
            break;

        case st_Link_AwaitingToTransmit_c:
            debugss(ssH47, INFO, "link transmit state\n");
            break;

        default:
            debugss(ssH47, ERROR, "Unknown command - default %d\n",
                    curLinkState);

    }

}