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

📄 cpmfs.hpp

📁 一个嵌入式系统的C代码
💻 HPP
📖 第 1 页 / 共 2 页
字号:
//*************************************************************************//  MODULE : CpmFs - A file system based on the old CP/M design           *//  AUTHOR : Ron Chernich                                                 *//  PURPOSE: Provides reudimentary (nonhierarachial) file system for RCOS *//  HISTORY:                                                              *//    13-AUG-94 First version                                             *//    17-AUG-84 DskDrv header file merged                                 *//*************************************************************************#ifndef __CPMFS__  #define __CPMFS__  #include "rcos.hpp"  #include "kernel.hpp"  #include "message.hpp"  #define MAX_DRIVES    3       // No real limit, but A: B: C: will do..  class CpmFs;                  // forward reference to File System  class CpmBdos;                // forward reference for Dos array  /////////////////////////////////////////////////////////////////////////  // structure describes salient physical characteristics of the  // disk disk drive being modelled.  //  typedef struct DskParmsTag {    UINT16 nSecs;               // sectors per track    UINT16 nTrks;               // total cylinders on disk    UINT16 nSides;              // no of tracks per cylinder    UINT16 nSecSize;            // bytes per sector    BYTE   nAngleInc;           // rotate speed (degrees per mS)    BYTE   nTrkInc;             // track-to-track access time (mS)    BYTE   nSettle;             // head settle adelay (mS)    UINT32 nErrRate;            // soft error rate (one every...)  } DPB, *PDPB;           /////////////////////  // This parameter list is equivalent to the Digital Research "MAC"  // macro that was used to build the required logical disk parameters..  //  typedef struct macTag {    BYTE   nLid;        // Logical unit ID (0 = "A:" ...)    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  } DPARAM, *PDPARAM;    //////////////////  // As I remember it, the CP/M directory entries went something like this.  // The m.s.b. of the name extension holds file attributes:  //   fextn[0] set = read only  //         1      = system (hidden)  //  #define PNAME_LEN     8  #define ENAME_LEN     3  #define BLOCK_LEN	128  #define FILENAME_LEN  (PNAME_LEN + ENAME_LEN)  //  typedef struct deTag {    BYTE nUsrNmbr;              // 0xe5 = erased, else user number (zero)    char fname[PNAME_LEN];      // File name    char fextn[ENAME_LEN];       // File extension    BYTE nExtent;               // logical extent of this entry    BYTE nRes1;                 // internal usage    BYTE nRes2;                 // internal usage    BYTE nRcnt;                 // BLOCK_LEN byte record num in use in last block    BYTE nAllocBlk[16];         // Disk blocks allocated to this extent  } DIRENT, *PDIRENT;     ///////////////  // constants define all intermediate operations in the CpmBdos (below)  // that are called via the CpmBdos::NxtFnc public member.  //  enum NXTFNC { LOG1,  STAT1, CLOSE1, CLOSE2,                OPEN1, OPEN2, CREAT1, CREAT2, CREAT3,                READ0, READ1, WRITE0, WRITE1, WRITE2,                FIND1, FIND2, RENAM1, RENAM2, REMOV1, REMOV2              };  /////////////  // Permissable high level commands for the Disk Units via their  // "channel" controller.  //  enum CHCMD { DD_CALIBRATE, DD_READ, DD_WRITE, DD_FORMAT };  ///////////////  // a CP/M File Control Block. While it "uses" the Directory entry struct,  // certain bytes have different meanings from those held on the disk.  // Note that the target buffer for the transfer is an extension of the  // original - added to permit totally encapsulated operation requests.  //  typedef struct fcbTag {    DIRENT de;                  // A.A. but nUsrNmbr = drive ID    BYTE   nCurRec;             // current record for sequential read/write    BYTE   nRandom[3];          // record number (0..65535)    char  *pBuf;                // address for transfer  } FCB, *PFCB;  //////////////////  // We plan to pass references to FCB's around using the asynchronous  // "post" mechanism, but this ends up "deleteing" the passed object  // if passed by reference, so this little double indirection thingy  // preserves the FCB (as far as TxPost is concerned) but allows the  // class <CpmDbos> to make changes back to the referenced item..  //  typedef struct fcbRefTag {    PFCB pFcbRef;  } FCBREF, *PFCBREF;      ///////////////  // A "Transfer Request" class; being an object created for each quantum  // of disk activity.  It gets posted to the appropriate drive unit and  // enters its FIFO queue.  When actioned, the CpmBdos pointer is used  // to call the member function that knows (via a constant placed in the  // object by the previous member function) which member function to pass  // the object along to next.  //  // Normally, the <pDma> pointer will be a copy of the buffer address in  // the FCB, but making it separate allows the BDOS to present the disk  // driver with the address of its internal buffers without danger of the  // user code accidentally gaining access to them.  //  // Note: stuff which class <DskModel> is not concerned with  //       is hidden away - including C::tor and D::tor.  //  class XfReq {    friend CpmFs;    friend CpmBdos;  protected:    PFCB   pFcb;                // instance of an FCB in the PCB or BDOS    NXTFNC ivec;                // what to do next (internal to CpmBdos)    BYTE   nRetry;              // error retry count    XfReq *pNxt;                // any "postponed" assosociated Xfer   ~XfReq (void) { }            // only friends can destroy    XfReq (UINT16 = 0);         //    or create one of these..    XfReq (UINT16, PFCB);  public:    UINT16   uProc;             // transfer initiator PID (or BDOS ID)    CHCMD    cmnd;              // What we want the disk channel to do    UINT16   nTrk, nSec, nSid;  // Cylinder, sector, head    char    *pDma;              // transfer buffer pointer    BOOL     bRes;              // Outcome of channel operation    CpmBdos *pFnCb;             // class that handeles completed xfers  };  /////////////////////////////////////////////////////////////////////  // Interface to the file system based on our old friend, the "port".  // Note how each file system operation takes a single XfReq pointer as  // input.  The Single instance of class CpmFs receives requests for  // FS operations from user processes as messages.  It merely creates  // a new XfReq object, filling in the originating PID and FCB pointer,  // determines which disk "unit" the request is for, checks that that  // unit is "on-line" and then calls the appropriate (protected) member  // function.  //   // ALL calls to the File System result in the caller process  // becomming blocked.  When the FS service is deemed to be complete,  // a result message will be posted to the PID (unblocking it) and the  // XfReq object killed off.  The last member function of CpmBdos to  // be passed the XfReq pointer does this.  //  // Note: it's each user process's responsibility to ensure the FCB  // is correctly initialised (by a successful call to FsOpen or FsCreat).  // The FS uses these FCB's to retain working data during file I/O  // operations.  Looks to me now (in hindsight) that if you diddle with  // these, and you can trash the file system, big time. Funny, I don't  // recall that ever happening though (?)  //  class CpmFs : public port {  private:    CpmBdos *pUnit[MAX_DRIVES];         // Disk File System instances  public:    CpmFs (UINT16, UINT16, Knl*);       // register with kernel   ~CpmFs (void);                       // murder all file systems    void RxPort (PMSG);                 // supply virtual member of "port"    void MountDrive (UINT16, char, DPB&, DPARAM&); // Instatiate new Bdos  };  ///////////////////////////////////////////////////////////////////////  // Here is the actual, re-entrant File System class.  In olden days  // (BC++), we would write this as a set of subroutines with lists and  // arrays to hold dynamic, unit variable data.  To-day, we make it a  // class and instantiate it once for each physical disk configured in.  // A more flexible scheme would have a list of devices rather than a  // simple array (as used in class CpmFs) permitting unlimited, dynamic  // mount and un-mount of devices at run time.  //  // Once a physical disk is determined to be "on-line" (ie, the host file  // emulating a disk unit, or a real disk unit, even, has started up ok),  // an instance of this class is created giving it the disk characteristics  // and some required file system parameters (number of directory entries,  // block size, etc..).  It is also given the Kernel message dispatcher  // address and the ID of the disk unit it will be responsible for.  //  // The sequence of events then goes like this:  // 1. A process invokes an FS operation and is blocked.  This results in  //    a message to the CpmFs instance.  // 2. The <CpmFs> creates an XfReq instance, fills in the FCB and PID

⌨️ 快捷键说明

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