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

📄 cpmfs.hpp

📁 一个嵌入式系统的C代码
💻 HPP
📖 第 1 页 / 共 2 页
字号:
  //    data from the message, identifies the target unit from the FCB  //    (placing a pointer to it in the XfReq), destroys the message and  //    calls the appropriate member of the array of the <CpmBdos> instances  //    with the XfReq pointer.  The <CpmFs> takes no further part in the  //    operation.  // 3. The <CpmBdos> instance formulates an appropriate disk transfer  //    (track, sector etc) inserting this into the <XfReq> object along  //    with a constant identifying which member function will deal with  //    the completed transfer.  It then posts the <XfReq> to "its" disk  //    channel handler.  // 4. The <XfReq> arrives at the channel handler and is placed in a FIFO  //    queue.  When it finally gets actioned, a result code is placed in  //    the <XfReq> object and the <NxtFnc> member of the <CpmBdos> instance  //    called with the <XfReq*> as parameter via the object pointer.  // 5. Using the constant placed in the XfReq by the previous member func,  //    CpmBdos::NxtFunc passes the XfReq to an internal, private function  //    which will do one off:  //      . Build a reply message and post it to the PID, then destroy the  //        XfReq object.  This completes the cycle, un-blocking the Proc.  //      . Alter the XfReq params (eg when a directory block just read  //        needs to be re-written) and post to the channel handler again.  //      . Spawn another XfReq (as in the case of a read/write operation  //        that needs to re-access the directory to fetch the next extent),  //        "attaching" the XfReq pointer to the new one, so that operations  //        on it can continue after the intermediate operation has finished.  //        This allows infinite (!?) nesting of channel calls.   // 6. A message arrives back at the originating process with the result  //    of the requested operation, effectively un-blocking it to continue  //    processing as dictated by internal logic.  The FCB it passed in the  //    first place has been updated and data transfered to/from the buffer  //    set in the FCB.  Simple, right?  //     class CpmBdos {    friend class CpmFs;  private:    Knl   *pTx;         // copy of CpmFs Message dispatcher    UINT16 nId;         // copy of CpmFs unique identifier    UINT16 nChan;       // Channel ID for XfReq messages    BYTE   nFsc;        // first physical sector number (0 or 1)    BYTE   nLsc;        // last sector number    BYTE   nSkf;        // optional sector skew factor    UINT16 nBls;        // data allocation block size    UINT16 nDks;        // number of blocks on disk    UINT16 nDir;        // number of directory entreies    UINT16 nCks;        // number of "checked" directory entries (for exchangable media)    BYTE   nOfs;        // track offset of logical track 00    BYTE   nAlb;        // No of allocation blkd/extent (8 or 16)    BYTE   DirBuf[BLOCK_LEN]; // buffer for directory operations    BYTE  *pAlv;        // Allocation Vector (dynamically allocated)    BYTE  *pCsv;        // Checksum vector (for exchangable disks)    BYTE  *pXlt;        // Sector skew table (NULL if no skew)    DPB   *pDpb;        // physical characteristics for this unit    void   Open1  (XfReq*);                     // looping step in Open    void   Open2  (XfReq*, BOOL);               // termination for Open    void   Close1 (XfReq*);                     // found file dir block    void   Close2 (XfReq*);                     // check update of dir blk    void   Creat1 (XfReq*);                     // end exist scan check    void   Creat2 (XfReq*);                     // looping step in Creat    void   Creat3 (XfReq*);                     // Success step in Creat    void   Stat1  (XfReq*);                     // looping step in Stat    void   Renam1 (XfReq*);                     // looping step in Rename    void   Renam2 (XfReq*);                     // success step in Rename    void   Remov1 (XfReq*);                     // looping step in Delete    void   Remov2 (XfReq*);                     // success step in Delete    void   Find1  (XfReq*);                     // first find success/fail    void   Find2  (XfReq*);                     // find next looping step    void   Read1  (XfReq*);                     // read complete step    void   Write1 (XfReq*);                     // write complete step    void   Write2 (XfReq*);                     // write open new extent step    void   Write3 (XfReq*);                     // write new extent intermediate    void   DoRetry(XfReq*);                     // disk error recovery    void   LogDisk  (void);                     // build Allocation and Checksum vectors    void   LogDisk1 (XfReq*);                   // loop building Allocation vector    UINT16 SecXlt (UINT16);                     // perform skew translation    UINT16 GetFreeBlk (void);                   // locate first unused allocation block of unit    void   AllocBlk (UINT16, BYTE = 1);         // set/reset numbered bit of disk allocation vector     void   ReGenerate (XfReq*, UINT16 = 0);	// copy passed request and post the copy    void   DeAllocBlk (UINT16 n) { AllocBlk(n, 0); }    void   DirScanPrep (FCB*, UINT16*, UINT16*);    void   BlkDecode (UINT16, UINT16, UINT16*, UINT16*);  protected:    void   Open  (XfReq*);                      // locate by name if exists (wildcard ok)    void   Creat (XfReq*);                      // Create if name unique and entry available    void   Close (XfReq*);                      // Close file, update Dir.    void   Renam (XfReq*);                      // name change (not open!)    void   Remov (XfReq*);                      // remove file from system    void   Stat  (XfReq*);                      // file size and protection    void   Find  (XfReq*, UINT16);              // directory name scanner    void   Read  (XfReq*, UINT16);              // Seq/Random read op.    void   Write (XfReq*, UINT16);              // Seq/Random write op.    CpmBdos (DPB&, DPARAM&, UINT16);            // only friends can create  public:   ~CpmBdos(void);    void   NxtFunc (XfReq*);                    // the only public entry point  };      /////////////////  // Disk transfer requests are held in a FIFO queue based on (guess what?)  // We will use what Taligent term "implemenmtation inheritance", ie a  // private base class.  Thie code rests with the Disk driver stuff..  //  class TreqstQ : private DblList {    UINT16 nInq;  public:    TreqstQ (void) : nInq(0) { }   ~TreqstQ (void) { }    XfReq   *Get   (UINT16 = 0);    XfReq   *Peek  (UINT16 = 0);    void     Purge (UINT16 = 0);    void     PurgeAll (void);    UINT16   GetLen (void)  { return nInq; }    void     Put (XfReq *p) { DblAppend((void*)p, sizeof(XfReq)); ++nInq; }  };    ////////////////  // for safety, we sub-class off the disk device transfer FIFO queue  // preventing the animator form doing anthing bad with queue data..  //  class TransQ {    TreqstQ *pTQ;    XfReq   *pX;  public:    TransQ (TreqstQ *p) : pTQ(p) { }   ~TransQ (void) { }    void   Peek (UINT16 n) { pX = pTQ->Peek(n);  }    UINT16 GetLen (void) { return pTQ->GetLen(); }    UINT16 GetPid (void) { return pX->uProc;     }    UINT16 GetTrk (void) { return pX->nTrk;      }    UINT16 GetSec (void) { return pX->nSec;      }    UINT16 GetSid (void) { return pX->nSid;      }    BOOL   IsRead (void) { return (pX->cmnd == DD_READ) ? TRUE : FALSE; }  };    ////////////  // This is the sequence of events in performing a disk transfer. Normally,  // we must perform all 4, in sequence unless the heads already happen to  // be on track, in which case we can go direct from IDEL to TRANSFER..  //  enum ddState { DD_IDLE, DD_SEEK, DD_SETTLE, DD_WAIT, DD_TRANSFER };    /////////////////  // This class simulates a disk drive using preset constants, based on the  // mS granularity system clock ticker, in terms of physical attributes of:  //  //    * Track to track seek time    //    * Head settle time  //    * Rotational Latency  //    * Soft error rate  //   // Channel requests arrive via the usual message service.  The model  // actions these in FIFO, moving the "head" missile to the specified  // "track", delaying for the head settle period, waiting until the  // required "sector" "arrives" under the "head", then calling the Read/  // Write routine to do the transfer to the specific address.  Finally,  // the CpmBdos::NxtFunc member is called (again via the Object pointer  // in the message), passing it the transfer request object pointer.  A  // parameter in the object indicates what routine is to precess the  // completed transfer.  If this is the end of the chain for the transfer,  // the XfReq object is destroyed and the blocked process sent a message  // to resume, otherwise the params are set for another transfer and the  // message re-posted to join the FIFO queue again.  //  // This sounds convoluted, but it enables us to implement a BDOS which  // is re-enterant, since all transfers are encapsulated totally in a  // XfReq object which rattles around independant of, and inter-leaved  // with, all other such objects without multi-threading or interrupts.  //  // One of these objects should be instantiated for each drive unit to be  // modelled, but NOTE that it is important to use the same parameter  // struct when initialising the corresponding File System object so that  // it "knows" the size of its "drive".  //  class DskModel : public port {  private:    ddState stage;              // stage of transfer (see enum type)    BYTE    nLid;               // logical unit ID (0 = "A:" etc)    BYTE    nAngleInc;          // rotate degrees per mS    BYTE    nTrkInc;            // mS per head step    BYTE    nSettle;            // mS to settle after step    BYTE    nSecAngle;          // degrees per sector    UINT16  nCurTrk;            // current head location    UINT16  nCurAngle;          // current angle of sector index "hole"    UINT32  nErrRate;           // soft error rate (one every...)    UINT32  nOpCnt;             // count of operations for error emulation    UINT32  lLastTime;          // gated clock state memory    UINT32  lHoldTime;          // state memory for delayed events    int     fd;                 // handle for host "disk" data file    BOOL    bOk;                // TRUE if disk is on-line and operational    UINT16  nBps;               // bytes per sector    UINT32  nBpt;               // bytes per cylinder    UINT32  nBpd;               // total bytes on "disk"    TreqstQ ChanQ;              // FIFO queue of requests for this unit    BOOL    Read (void);        // read to buffer BLOCK_LEN bytes    BOOL    Write (void);       // write from buffer BLOCK_LEN bytes    long    CalcOffset (void);  // get offset for host file transfer  public:     DskModel (UINT16, UINT16, Knl*, char*, DPB&, BYTE);   ~DskModel (void);    void Scheduler (void);               // called in "main loop"    void RxPort (PMSG);                  // incomming message handler    BOOL IsOnLine (void) { return bOk; } // check on c::tor success  };#endif/////////////////////////////////// eof ////////////////////////////////////  

⌨️ 快捷键说明

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