⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpmbdos.cpp

📁 一个嵌入式系统的C代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
  }  else {    DirScanPrep(pX->pFcb, &pX->nTrk, &pX->nSec);    pX->ivec = CREAT2;    pX->cmnd = DD_READ;    pX->pDma = (char*)DirBuf;    message msg(nId, 3, 3, (void*)pX);    pTx->PostMsg(nChan, &msg);  }}///////////////// At this point, the outer packet has the result of a directory// scan for the file we want to kill off.  If it was found, we can// simply set its flag char to "erased" and issue the rewrite.// If not found, it's only an error if we were looking for the// first extent - not found on subsequent extents is an Ok situation.//void CpmBdos::Remov1 (XfReq *pX){  if (FALSE == pX->bRes) {    message msg(nId, pX->pFcb->de.nExtent ? FS_Ok : FS_NotFound);    pTx->PostMsg(pX->uProc, &msg);  }  else {    DIRENT *pDir = (DIRENT*)(pX->pDma + pX->pFcb->de.nRes1);    pDir->nUsrNmbr = 0xF7;    pX->ivec = REMOV2;    pX->cmnd = DD_WRITE;    message msg(nId, 4, 4, (void*)pX);    pTx->PostMsg(nChan, &msg);  }}/////////////// If the rewrite worked, we must unallocate (in our in-memory bit map)// all blocks associated with this file.  If the extent was full, there// may be another which needs to be crossed off..//void CpmBdos::Remov2 (XfReq *pX){  if (FALSE == pX->bRes)    DoRetry(pX);  else {    BOOL bDone;    if (nAlb > 8) {      BYTE *pB = pX->pFcb->de.nAllocBlk;      int idx;      for (idx = 0; *pB && (idx < nAlb); pB++, idx++)        DeAllocBlk((UINT16)*pB);      bDone = ((idx < nAlb) && (pX->pFcb->de.nRcnt < 7)) ? TRUE : FALSE;    }    else {      UINT16 *pN = (UINT16*)pX->pFcb->de.nAllocBlk;      int idx;      for (idx = 0; *pN && (idx < nAlb); pN++, idx++)        DeAllocBlk(*pN);      bDone = ((idx < nAlb) && (pX->pFcb->de.nRcnt < 7)) ? TRUE : FALSE;    }    if (bDone) {      message msg(nId, FS_Ok);      pTx->PostMsg(pX->uProc, &msg);    }    else {      ++pX->pFcb->de.nExtent;      Remov(pX);    }  }}///////////////// we arrive here when the nested dir scan has located the dir block// (which was cunningly transferred to the inner XfReq sec/trk vars)// so from here we issue the re-write..//void CpmBdos::Close1 (XfReq *pX){  pX->ivec = CLOSE2;  pX->cmnd = DD_WRITE;  char *cp = (char*)pX->pDma;  memcpy(cp+pX->pFcb->de.nRes1, (char*)&pX->pFcb->de, sizeof(DIRENT));  message msg(nId, 5, 5, (void*)pX);  pTx->PostMsg(nChan, &msg);}///////////////// ..and we arrive here after the write attempt has taken place.//void CpmBdos::Close2 (XfReq *pX){  if (FALSE == pX->bRes)    DoRetry(pX);  else {    message msg(nId, FS_Ok);    pTx->PostMsg(pX->uProc, &msg);  }}  /////////////// This is the loop point for the scan for a free directory entry as// flagged by an 0xE5 (never used) or 0xF7 (erased) flag.  If one is// found, it is allocated as a zero length file.  <nRes1> of the FCB// is set to the logical entry number for convenience and the block// containing the entry rewritten.//// CAUTION: There should be a lock placed on the block someplace to// prevent the classic "lost update" scenario being enacted yet again.// this is left as an exercise for the user (ho, ho, ho).//void CpmBdos::Creat2 (XfReq *pX){  if (FALSE == pX->bRes)    DoRetry(pX);  else {    int idx;    for (idx = 0; idx < 4; idx++) {      DIRENT *pDir = (DIRENT*)(pX->pDma + (idx * 32));      if ((0xF7 == pDir->nUsrNmbr) || (0xE5 == pDir->nUsrNmbr)) {        memset((char*)pDir, 0, sizeof(DIRENT));        memcpy(pDir->fname, pX->pFcb->de.fname, FILENAME_LEN);        pX->ivec = CREAT3;        pX->cmnd = DD_WRITE;        ReGenerate(pX, 6);        //message msg(nId, 6, 6, (void*)pX);        //pTx->PostMsg(nChan, &msg);        return;      }    }    if (--(pX->pFcb->de.nRcnt) <= 0) {      message msg(nId, FS_DiskFull);      pTx->PostMsg(pX->uProc, &msg);    }    else {      ++(pX->pFcb->de.nRes2);      if (pX->pFcb->de.nRes2 >= (nBls / 128)) {        ++(pX->pFcb->de.nRes1);        pX->pFcb->de.nRes2 = 0;      }      BlkDecode(pX->pFcb->de.nRes1, pX->pFcb->de.nRes2,              &(pX->nTrk), &(pX->nSec));      ReGenerate(pX, 7);      //message msg(nId, 7, 7, (void*)pX);      //pTx->PostMsg(nChan, &msg);    }  }}////////////////// This is a common usage point for all operations that entail a rewrite// to the Directory. We check the return code, vectoring to the retry// code if needs be, otherwise check for attached transfers and act..//void CpmBdos::Creat3 (XfReq *pX){  if (FALSE == pX->bRes)    DoRetry(pX);  else {    if (NULL == pX->pNxt) {      pX->pFcb->nCurRec = 0;      message msg(nId, FS_Ok);      pTx->PostMsg(pX->uProc, &msg);    }    else {      XfReq *pInner = pX->pNxt;      memcpy((char*)&pInner->pFcb->de, (char*)&pX->pFcb->de, sizeof(DIRENT));      pInner->pFcb->nCurRec = 0;      delete pX;      NxtFunc(pInner);    }  }}//////////////////// arrive here after an attempted record read - retry on error, or// perform house keeping of FCB and tidy up.//void CpmBdos::Read1 (XfReq *pX){  if (FALSE == pX->bRes)    DoRetry(pX);  else {    ++pX->pFcb->nCurRec;    message msg(nId, FS_Ok);    pTx->PostMsg(pX->uProc, &msg);  }    }//////////////////// Arrive here after an attempted record write - retry on error, or// perform house keeping of FCB and reply to the caller. Scenarios://// 1.  A previously written record has been re-written://     No extra action.// 2.  The record was after the last used and://     - the current block is the cardinal last for the extent, or//     - is the last allocation block of the extent://       Increment <nRcnt> (range is 0..nRpb-1; 0..7 for IBM 3740).//// This will set <nRcnt> to nRpb-1 when the last record of the last// block of the extent is used - indicating to <Write> that a new// extent must be opened before further writes can take place.//// When a new allocation block is added, <nRcnt> is zeroed.//void CpmBdos::Write1 (XfReq *pX){  if (FALSE == pX->bRes)    DoRetry(pX);  else {    ++pX->pFcb->nCurRec;    BYTE nRpb = nBls / 128;    BYTE nAbs = pX->pFcb->nCurRec / nRpb;    BYTE nRec = pX->pFcb->nCurRec % nRpb;    if ((pX->pFcb->de.nRcnt < nRec) &&        ((nAbs == nAlb-1) || (0 == pX->pFcb->de.nAllocBlk[nAbs+1])))       pX->pFcb->de.nRcnt = nRec;    message msg(nId, FS_Ok);    pTx->PostMsg(pX->uProc, &msg);  }}///////////////////////////////////////////////////////////////////////////                      These Members are PROTECTED//----------------------------------------------------------------------// Scan the directory for the first file matching the name in the passed// FCB and extent matching the FCB extent number.  We start by requesting// the first record of block zero, setting <nRes1> as the block counter// <nRes2> as record of block counter and <nRcnt> as the total records// for the search. These will be replaced by the Dir entry detail, if found.// void CpmBdos::Open (XfReq *pX){  DirScanPrep(pX->pFcb, &pX->nTrk, &pX->nSec);  pX->ivec  = OPEN1;  pX->cmnd  = DD_READ;  pX->pDma = (char*)DirBuf;  message msg(nId, 8, 8, (void*)pX);  pTx->PostMsg(nChan, &msg);}/////////////// This activity must fail if the file exists - so we begin by nesting// this transfer request inside one that will try to open a file of the// same name.//void CpmBdos::Creat (XfReq *pX){  XfReq *pNew = new XfReq(nId);  if (pNew && (pNew->pFcb = new FCB)) {    memcpy((char*)pNew->pFcb, (char*)pX->pFcb, sizeof(FCB));    pX->ivec = CREAT1;    pNew->pNxt = pX;    pNew->ivec = OPEN1;    pNew->cmnd = DD_READ;    pNew->pDma = (char*)DirBuf;    pNew->pFnCb = this;    DirScanPrep(pNew->pFcb, &pNew->nTrk, &pNew->nSec);    message msg(nId, 9, 9, (void*)pNew);    pTx->PostMsg(nChan, &msg);  }}////////////////// Read a record sequentially (at this time random access is provisioned// for, but not implemented). There are 3 scenarios://// 1.  The record is within the scope of the current extent - we simply//     calculate its disk location and ask for a transfer.// 2.  The record is in the next extent (and there is one).  Open the next//     extent by upping the FCB extent number and callin Open1, then//     return here to continue as for (1) above.// 3.  We are at EOF - either in this extent (easy to test), or we need//     another extent and there isn't one.//void CpmBdos::Read (XfReq *pX, UINT16 nType){  pX->ivec  = READ1;  pX->cmnd  = DD_READ;  BYTE nRpb = nBls / 128;  BYTE nAbs = pX->pFcb->nCurRec / nRpb;  BYTE nRec = pX->pFcb->nCurRec % nRpb;  if ((nRec > pX->pFcb->de.nRcnt) &&      (0 == pX->pFcb->de.nAllocBlk[nAbs+1])) {    message msg(pX->uProc, FS_EOF);    pTx->PostMsg(nChan, &msg);    return;  }  if (pX->pFcb->de.nAllocBlk[nAbs]) {    BlkDecode(pX->pFcb->de.nAllocBlk[nAbs], nRec, &pX->nTrk, &pX->nSec);    message msg(nId, 10, 10, (void*)pX);    pTx->PostMsg(nChan, &msg);  }  else {    XfReq *pNew = new XfReq;    memcpy((char*)pNew->pFcb, (char*)pX->pFcb, sizeof(FCB));    pX->ivec = READ0;    pNew->pNxt = pX;    pNew->ivec = OPEN1;    pNew->cmnd = DD_READ;    pNew->pFcb->de.nExtent++;    pNew->pDma = (char*)DirBuf;    DirScanPrep(pNew->pFcb, &pNew->nTrk, &pNew->nSec);    message msg(nId, 11, 11, (void*)pNew);    pTx->PostMsg(nChan, &msg);  }}////////////////// Write a (sequential) record (random access is provisioned for, but not// implemented). This is VERY similar to read, but different enough to// warrant its own entry point. There are 3 scenarios://// 1.  The record is within the scope of the current extent://     Simply calculate its disk location and ask for a transfer.//     (we can't do any FCB housekeeping until we know the write worked).//// 2.  The record is beyond the current allocation block and the next//     allocation block is zero - get a free block (if possible) and//     use its first record.//// 3.  The record is beyond the last block of this extent. Here there are//     two sub-scenarios://       3a.  There is a next extent - open it and proceed as for (1).//       3b.  There is no next extent - create one and proceed as for (3).//     Note that (3b) may fail if there are no directory entries available,//     even though there may still be disk blocks available.//void CpmBdos::Write (XfReq *pX, UINT16 nType){  pX->ivec  = WRITE1;  pX->cmnd  = DD_WRITE;  BYTE nRpb = nBls / 128;  BYTE nAbs = pX->pFcb->nCurRec / nRpb;  BYTE nRec = pX->pFcb->nCurRec % nRpb;  //  // Scenario 1  //  if (pX->pFcb->de.nAllocBlk[nAbs]) {    BlkDecode(pX->pFcb->de.nAllocBlk[nAbs], nRec, &pX->nTrk, &pX->nSec);    message msg(nId, 12, 12, (void*)pX);    pTx->PostMsg(nChan, &msg);    return;  }  //  // Scenario 2  //  if (0 == pX->pFcb->de.nAllocBlk[nAbs]) {    pX->pFcb->de.nAllocBlk[nAbs] = GetFreeBlk();    if (0 == pX->pFcb->de.nAllocBlk[nAbs]) {      message msg(pX->uProc, FS_DiskFull);      pTx->PostMsg(nChan, &msg);      return;    }    else {      AllocBlk(pX->pFcb->de.nAllocBlk[nAbs]);      pX->pFcb->de.nRcnt = 0;      BlkDecode(pX->pFcb->de.nAllocBlk[nAbs], nRec, &pX->nTrk, &pX->nSec);      message msg(nId, 13, 13, (void*)pX);      pTx->PostMsg(nChan, &msg);      return;    }  }  //  // Scenario 3 (note temporary cop-out)  //   if (TRUE) {    message msg(pX->uProc, FS_DiskFull);    pTx->PostMsg(nChan, &msg);    return;  }}//////////////// A file Close operation needs to locate the Dir block containing the// current extent and update the record (if it's chaged)..//void CpmBdos::Close (XfReq *pX){  XfReq *pNew = new XfReq;  if (pNew && (pNew->pFcb = new FCB)) {    memcpy((char*)pNew->pFcb, (char*)pX->pFcb, sizeof(FCB));    pX->ivec = CLOSE1;    pNew->pNxt  = pX;    pNew->pFnCb = this;    pNew->ivec  = OPEN1;    pNew->cmnd  = DD_READ;    pNew->pDma  = (char*)DirBuf;    DirScanPrep(pNew->pFcb, &pNew->nTrk, &pNew->nSec);    message msg(nId, 14, 14, (void*)pNew);    pTx->PostMsg(nChan, &msg);  }}///////////////// delete a current file -  first we must be able to open it..//void CpmBdos::Remov (XfReq *pX){  XfReq *pNew = new XfReq;  if (pNew && (pNew->pFcb = new FCB)) {    memcpy((char*)pNew->pFcb, (char*)pX->pFcb, sizeof(FCB));    pX->ivec = REMOV1;    pNew->pNxt  = pX;    pNew->pFnCb = this;    pNew->ivec  = OPEN1;    pNew->cmnd  = DD_READ;    pNew->pDma  = (char*)DirBuf;    DirScanPrep(pNew->pFcb, &pNew->nTrk, &pNew->nSec);    message msg(nId, 15, 15, (void*)pNew);    pTx->PostMsg(nChan, &msg);  }}/////////////////////////////////// eof ////////////////////////////////////  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -