?? jobc.c
字號:
/*
MMURTL Operating System Source Code
Copyright 1991,1992,1993, Richard A. Burgess
ALL RIGHTS RESERVED
Version x0.8
*/
/* This file contains functions and data used to support
loading or terminating jobs (or services).
It contains the public functions:
Chain() Loads new job run file in current JCB & PD
LoadNewJob() Loads a new job into a new JCB & PD
ExitJob() Exits current job, loads ExitJob if specified
GetExitStatus() Gets error set from ExitJob (the last guy's error)
GetExitJob() Gets run file name that will be loaded upon ExitJob
SetExitJob() Sets run file name to load upon ExitJob
SetCmdLine() Sets the command line for next job
GetCmdLine() Gets the command line for the current job
GetPath() Gets the path prefix for the current job
Setpath() Sets the path prefix for the current job
SetUserName() Sets the Username for the current job
GetUserName() Gets the Username for the current job
*/
#define U32 unsigned long
#define S32 long
#define U16 unsigned int
#define S16 int
#define U8 unsigned char
#define S8 char
#define TRUE 1
#define FALSE 1
#include "MKernel.h"
#include "MMemory.h"
#include "MData.h"
#include "MTimer.h"
#include "MVid.h"
#include "MKbd.h"
#include "MJob.h"
#include "MFiles.h"
#include "runfile.h"
#define MEMUSERD 7 /* User Writable (Data) */
#define ErcOutOfRange 10 /* Bad Exchange specified in OS call */
#define ErcNoExitJob 76 /* No ExitJob specified on ExitJob(n)*/
#define ErcBadRunFile 74 /* Couldn't load specified ExitRunFile */
/* Near Support Calls from OS */
extern long AllocJCB(long *pdJobNumRet, char *ppJCBRet);
extern long RemoveRdyJob(char *pJCB);
extern long GetExchOwner(long Exch, char *pJCBRet);
extern long SetExchOwner(long Exch, char *pNewJCB);
extern long SendAbort(long JobNum, long Exch);
/* Temporary NEAR externals from the monitor program for debugging */
extern long xprintf(char *fmt, ...);
extern U32 Dump(unsigned char *pb, long cb);
/* We switch to this stack when we claen out a user
PD before we rebuild it.
*/
long TmpStack[128]; /* 512 byte temporary stack */
/* Used for allocating/filling in new JCB */
struct JCBRec *pNewJCB; /* Used to access a JCB */
struct JCBRec *pTmpJCB;
struct JCBRec *pCrntJCB;
long JobNum;
/* For ExitJob cause he can't have local vars! */
long JobNumE, job_fhE;
long ExchE, ercE, iE;
long BogusMsg[2];
long *pPDE, cbFileE;
char *pExchJCBE, *pFileE;
long KeyCodeE;
long FileE[80];
extern unsigned long KillExch; /* From the Monitor */
/* Run file data */
char *pCode, *pData, *pStack; /* Ptrs in User mem to load to */
long sCode, sData, sStack; /* Size of segments */
unsigned long oCode, oData; /* Offset in file to Code & Data */
long offCode = 0, /* Virtual Offset for Code & Data Segs */
offData = 0;
unsigned long nCDFIX = 0,
oCDFIX = 0,
nCCFIX = 0,
oCCFIX = 0,
nDDFIX = 0,
oDDFIX = 0,
nDCFIX = 0,
oDCFIX = 0;
char *pStart, filetype;
struct tagtype tag;
/************* INTERNAL SUPPORT CALLS ******************/
/******************************************************
This deallocates all user memory in a PD. This is
used when we ExitJob to free up all the memory.
We get the pointer to the PD and "walk" through all
the User PTs deallocating linear memory. When all
PTs have been cleaned, we eliminate the user PDEs.
This leaves a blank PD for reuse if needed.
******************************************************/
void CleanUserPD(long *pPD)
{
long i, j, k, erc;
unsigned long *pPT;
char *pMem;
for (i=768; i<1024; i++) { /* Look at each shadow PDE */
if (pPD[i]) { /* If it's a linear address (non 0)*/
pPT = pPD[i] & 0xFFFFF000; /* Point to Page Table */
for (j=0; j<1024; j++) {
/* Get Beginning address for each run to deallocate */
k = 0; /* nPages to deallocate */
pMem = ((i-512) * 0x400000) + (j * 4096);
while ((pPT[j++]) && (j<1024))
k++; /* one more page */
if (k) { /* we have pages (one or more) */
erc = DeAllocPage(pMem, k);
}
}
if (i != 768) { /* save first PT! */
erc = DeAllocPage(pPT, 1); /* dealloc PT */
pPD[i] = 0; /* Wipe out shadow PDE */
pPD[i-512] = 0; /* Wipe out PDE */
}
}
}
}
/*********************************************************
This opens and reads and validates the run file.
If all is well, it leaves it open and returns the
file handle, else it closes the run file and returns
the error to the caller.
The caller is responsible for closing the file!!!
*********************************************************/
long GetRunFile(char *pFileName, long cbFileName, long *pfhRet)
{
long erc, i, fh, dret;
char fDone, junk;
offCode = 0;
offData = 0;
nCDFIX = 0;
oCDFIX = 0;
nCCFIX = 0;
oCCFIX = 0;
nDDFIX = 0;
oDDFIX = 0;
nDCFIX = 0;
oDCFIX = 0;
/* Mode Read, Stream type */
erc = OpenFile(pFileName, cbFileName, 0, 1, &fh);
if (!erc) { /* File opened OK */
fDone = 0;
while ((!erc) && (!fDone)) {
tag.id = 0;
erc = ReadBytes (fh, &tag, 5, &dret);
switch (tag.id) {
case IDTAG:
erc = ReadBytes (fh, &filetype, 1, &dret);
if ((filetype < 1) || (filetype > 3))
erc = ErcBadRunFile;
break;
case SEGTAG:
erc = ReadBytes (fh, &sStack, 4, &dret);
if (!erc) erc = ReadBytes (fh, &sCode, 4, &dret);
if (!erc) erc = ReadBytes (fh, &sData, 4, &dret);
break;
case DOFFTAG:
erc = ReadBytes (fh, &offData, 4, &dret);
break;
case COFFTAG:
erc = ReadBytes (fh, &offCode, 4, &dret);
break;
case STRTTAG:
erc = ReadBytes (fh, &pStart, 4, &dret);
break;
case CODETAG:
erc = GetFileLFA(fh, &oCode);
if (!erc)
erc = SetFileLFA(fh, oCode+tag.len); /* skip it */
break;
case DATATAG:
erc = GetFileLFA(fh, &oData);
if (!erc)
erc = SetFileLFA(fh, oData+tag.len); /* skip it */
break;
case CDFIXTAG:
erc = GetFileLFA(fh, &oCDFIX);
nCDFIX = tag.len/4;
if (!erc)
erc = SetFileLFA(fh, oCDFIX+tag.len); /* skip it */
break;
case CCFIXTAG:
erc = GetFileLFA(fh, &oCCFIX);
nCCFIX = tag.len/4;
if (!erc)
erc = SetFileLFA(fh, oCCFIX+tag.len); /* skip it */
break;
case DDFIXTAG:
erc = GetFileLFA(fh, &oDDFIX);
nDDFIX = tag.len/4;
if (!erc)
erc = SetFileLFA(fh, oDDFIX+tag.len); /* skip it */
break;
case DCFIXTAG:
erc = GetFileLFA(fh, &oDCFIX);
nDCFIX = tag.len/4;
if (!erc)
erc = SetFileLFA(fh, oDCFIX+tag.len); /* skip it */
break;
case ENDTAG:
fDone = TRUE;
break;
default:
erc = GetFileLFA(fh, &i);
xprintf("UNKNOWN TAG LFA: %d Size tag %d ErcGetLFA: %d \r\n",
i, tag.len, erc);
while ((tag.len--) && (!erc))
erc = ReadBytes (fh, &junk, 1, &dret);
break;
}
}
if (erc)
CloseFile(fh);
}
if (!erc)
*pfhRet = fh;
/*
xprintf("PAUSED - Erc reading run file: %d\r\n", erc);
xprintf("sStack: %08x\r\n", sStack);
xprintf("sCode: %08x\r\n", sCode);
xprintf("sData: %08x\r\n", sData);
xprintf("offData: %08x\r\n", offData);
xprintf("offCode: %08x\r\n", offCode);
ReadKbd(&KeyCodeE, 1);
*/
return (erc);
}
/********************************************************/
/********************************************************/
/*********** PUBLIC CALLS FOR JOB MANAGEMENT ************/
/********************************************************/
/********************************************************/
/**************************************************/
long far SetExitJob(char *pRunFile, long dcbRunFile)
{
long JobNum;
GetJobNum(&JobNum);
GetpJCB(JobNum, &pTmpJCB); /* Get pJCB to current Job */
if (dcbRunFile > 79)
return (ErcBadJobParam);
else if (!dcbRunFile)
pTmpJCB->JcbExitRF[0] = 0;
else {
CopyData(pRunFile, &pTmpJCB->JcbExitRF[1], dcbRunFile);
pTmpJCB->JcbExitRF[0] = dcbRunFile;
}
return(0);
}
/**************************************************/
long far GetExitJob(char *pRunRet, long *pdcbRunRet)
{
long JobNum, i;
GetJobNum(&JobNum);
GetpJCB(JobNum, &pTmpJCB); /* Get pJCB to current Job */
i = pTmpJCB->JcbExitRF[0];
if (i)
CopyData(&pTmpJCB->JcbExitRF[1], pRunRet, i);
*pdcbRunRet = i;
return(0);
}
/**************************************************/
long far SetPath(char *pPath, long dcbPath)
{
long JobNum;
GetJobNum(&JobNum);
GetpJCB(JobNum, &pTmpJCB); /* Get pJCB to current Job */
if (dcbPath > 69)
return (ErcBadJobParam);
else if (!dcbPath)
pTmpJCB->sbPath[0] = 0;
else {
CopyData(pPath, &pTmpJCB->sbPath[1], dcbPath);
pTmpJCB->sbPath[0] = dcbPath;
}
return(0);
}
/**************************************************/
long far GetPath(long JobNum, char *pPathRet, long *pdcbPathRet)
{
long i, erc;
erc = GetpJCB(JobNum, &pTmpJCB); /* Get pJCB to JobNum */
if (!erc) {
i = pTmpJCB->sbPath[0];
if (i)
CopyData(&pTmpJCB->sbPath[1], pPathRet, i);
*pdcbPathRet = i;
}
return(erc);
}
/**************************************************/
long far SetCmdLine(char *pCmd, long dcbCmd)
{
long JobNum;
GetJobNum(&JobNum);
GetpJCB(JobNum, &pTmpJCB); /* Get pJCB to current Job */
if (dcbCmd > 79)
return (ErcBadJobParam);
else if (!dcbCmd)
pTmpJCB->JcbCmdLine[0] = 0;
else {
CopyData(pCmd, &pTmpJCB->JcbCmdLine[1], dcbCmd);
pTmpJCB->JcbCmdLine[0] = dcbCmd;
}
return(0);
}
/**************************************************/
long far GetCmdLine(char *pCmdRet, long *pdcbCmdRet)
{
long JobNum, i;
GetJobNum(&JobNum);
GetpJCB(JobNum, &pTmpJCB); /* Get pJCB to current Job */
i = pTmpJCB->JcbCmdLine[0];
if (i)
CopyData(&pTmpJCB->JcbCmdLine[1], pCmdRet, i);
*pdcbCmdRet = i;
return(0);
}
/**************************************************/
long far SetUserName(char *pUser, long dcbUser)
{
long JobNum;
GetJobNum(&JobNum);
GetpJCB(JobNum, &pTmpJCB); /* Get pJCB to current Job */
if (dcbUser > 29)
return (ErcBadJobParam);
else if (!dcbUser)
pTmpJCB->sbUserName[0] = 0;
else {
CopyData(pUser, &pTmpJCB->sbUserName[1], dcbUser);
pTmpJCB->sbUserName[0] = dcbUser;
}
return(0);
}
/**************************************************/
long far GetUserName(char *pUserRet, long *pdcbUserRet)
{
long JobNum, i;
GetJobNum(&JobNum);
GetpJCB(JobNum, &pTmpJCB); /* Get pJCB to current Job */
i = pTmpJCB->sbUserName[0];
if (i)
CopyData(&pTmpJCB->sbUserName[1], pUserRet, i);
*pdcbUserRet = i;
return(0);
}
/**************************************************/
long far SetSysIn(char *pName, long dcbName)
{
long JobNum;
GetJobNum(&JobNum);
GetpJCB(JobNum, &pTmpJCB); /* Get pJCB to current Job */
if ((dcbName > 49) || (!dcbName))
return (ErcBadJobParam);
else {
CopyData(pName, &pTmpJCB->JcbSysIn[1], dcbName);
pTmpJCB->JcbSysIn[0] = dcbName;
}
return(0);
}
/**************************************************/
long far GetSysIn(char *pFileRet, long *pdcbFileRet)
{
long JobNum, i;
GetJobNum(&JobNum);
GetpJCB(JobNum, &pTmpJCB); /* Get pJCB to current Job */
i = pTmpJCB->JcbSysIn[0];
if (i)
CopyData(&pTmpJCB->JcbSysIn[1], pFileRet, i);
*pdcbFileRet = i;
return(0);
}
/**************************************************/
long far SetSysOut(char *pName, long dcbName)
{
long JobNum;
GetJobNum(&JobNum);
GetpJCB(JobNum, &pTmpJCB); /* Get pJCB to current Job */
if ((dcbName > 49) || (!dcbName))
return (ErcBadJobParam);
else {
CopyData(pName, &pTmpJCB->JcbSysOut[1], dcbName);
pTmpJCB->JcbSysOut[0] = dcbName;
}
return(0);
}
/**************************************************/
long far GetSysOut(char *pFileRet, long *pdcbFileRet)
{
long JobNum, i;
GetJobNum(&JobNum);
GetpJCB(JobNum, &pTmpJCB); /* Get pJCB to current Job */
i = pTmpJCB->JcbSysOut[0];
if (i)
CopyData(&pTmpJCB->JcbSysOut[1], pFileRet, i);
*pdcbFileRet = i;
return(0);
}
/*********************************************************
This creates and loads a new Job from a RUN file.
This returns ErcOK and new job number if loaded OK
else an error is returned.
*********************************************************/
long far LoadNewJob(char *pFileName, long cbFileName, long *pJobNumRet)
{
long erc, i, fh, dret, nPages;
unsigned long *pPD, *pPT, *pVid, *pOSPD;
long *pFix;
U32 PhyAdd;
/* FIX ME - Put Semaphore/Exch here to allow only a single user */
erc = GetRunFile(pFileName, cbFileName, &fh);
if (!erc) {
/* We set these to zero so we can tell if they have
been allocated in case we fail so we know what to deallocate
*/
JobNum = 0;
pNewJCB = 0;
pPD = 0;
pPT = 0;
pVid = 0;
erc = AllocJCB(&JobNum, &pNewJCB);
/* Alloc OS memory pages required for new job */
if (!erc)
erc = AllocOSPage(3, &pPD); /* Job's PD, PT * pVirtVid */
pPT = pPD + 4096; /* 1 page later */
pVid = pPD + 8192; /* 2 pages later */
if (!erc) {
FillData(pPT, 4096, 0); /* Zero user PT */
FillData(pVid, 4096, 0); /* Zero user video */
GetpJCB(1, &pTmpJCB); /* Get OS pJCB */
pOSPD = pTmpJCB->pJcbPD; /* Pointer to OS PD */
GetPhyAdd(1, pPT, &PhyAdd); /* Get Phy Add for new PT */
PhyAdd |= MEMUSERD; /* Set user code bits in PDE */
pOSPD[256] = PhyAdd; /* Make User PDE in OS PD */
pOSPD[768] = pPT; /* Shadow Linear Address of PT */
/*
xprintf("pOSPD : %08x\r\n", pOSPD);
xprintf("pUserPD: %08x\r\n", pPD);
xprintf("pUserPT: %08x\r\n", pPT);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -