--- /dev/null
+; MMURTL Operating System Source Code\r
+; Copyright 1991,1992,1993,1994 Richard A. Burgess\r
+; ALL RIGHTS RESERVED\r
+; Version 1.0\r
+\r
+.DATA\r
+.INCLUDE MOSEDF.INC\r
+.INCLUDE JOB.INC\r
+.INCLUDE TSS.INC\r
+\r
+PUBLIC pFreeJCB DD 0 ; Ptr to free Job Control Blocks\r
+PUBLIC pJCBs DD 0 ; JCBs are in allocated memory\r
+PUBLIC _nJCBLeft DD nJCBs ; For Monitor stats\r
+\r
+EXTRN MonJCB DB ; Monitor JCB reference\r
+EXTRN _BootDrive DD ; From Main.asm\r
+\r
+;======= End data,Begin Code ==================\r
+\r
+.CODE\r
+;================================================================\r
+;InitNewJCB is used initially by the OS to fill in the first two\r
+;jobs (Monitor & Debugger)\r
+;\r
+PUBLIC InitNewJCB:\r
+; INPUT : EAX -- Ptr to JCB that is to be filled in\r
+; EBX -- Linear Ptr to Page Directory for Job\r
+; ESI -- pbJobName\r
+; ECX -- cbJobName\r
+; EDX -- Pointer to Job Virtual Video Buffer (all jobs have one!)\r
+;\r
+; OUTPUT : JOB Number in EAX\r
+; USED : EAX, EBX, ECX, EDX, EDI, ESI, EFlags\r
+; MODIFIES : JCB pointed to in EBX\r
+;\r
+; This fills in a JCB with new information. This is used to initilaize\r
+; a new JCB during OS init and when a new Job is loaded and run.\r
+;\r
+ MOV [EAX+JcbPD],EBX ;Put Ptr to PD into JCB\r
+ MOV EDI, EAX ;EDI points to JCB\r
+ ADD EDI, sbJobName ;Now to JobName\r
+ MOV BYTE PTR [EDI], CL ;size is filled in\r
+ INC EDI ;first byte of name\r
+ REP MOVSB ;Move it in\r
+ MOV [EAX+pVirtVid], EDX ;Video number is in JCB\r
+ MOV DWORD PTR [EAX+nCols], 80 ;\r
+ MOV DWORD PTR [EAX+nLines], 25 ;\r
+ MOV DWORD PTR [EAX+NormAttr], 7 ;\r
+ MOV EAX, [EAX+JobNum]\r
+ RETN\r
+\r
+\r
+;=============================================================================\r
+; InitFreeJCB\r
+; INPUT : EAX - Address of JCBs to be initialized\r
+; ECX - Count of JCBs\r
+; EDX - Size of JCBs\r
+; OUTPUT : NONE\r
+; USED: EAX,EBX,ECX,EDX,ESI EFLAGS\r
+; MODIFIES: pFreeJCB, pJCBs\r
+;\r
+; This routine will initialize the free pool of Job Control Blocks (JCBs).\r
+; EAX points to the first JCB,\r
+; ECX is count of JCBs,\r
+; EDX is size of each JCB.\r
+;\r
+; The pFreeJCB pointer is set to address the first element in rgJCBs.\r
+; Each element of rgJCBs is set to point to the next element of rgJCBs.\r
+; The last element of rgJCBs is set to point to nothing (NIL).\r
+; The JCBs are also sequentially numbered. We can't use it's position\r
+; in the array because some JCBs are static (Mon and Debugger), while\r
+; others (the ones we are initializing now) are dynamicly allocated.\r
+;\r
+PUBLIC InitFreeJCB:\r
+ MOV pFreeJCB,EAX ;Set up OS pointer to list\r
+ MOV pJCBs, EAX ;Set up global ptr to first JCB\r
+ MOV EBX, 3 ;1st number for Dynamic JCBs\r
+JCB_Loop:\r
+ MOV ESI,EAX ;EBX has pointer to current one\r
+ ADD EAX,EDX ;EAX points to next one\r
+ MOV [ESI+NextJCB],EAX ;Make current point to next\r
+ MOV [ESI+JobNum], EBX ;Number it\r
+ INC EBX\r
+ LOOP JCB_Loop ;Go back till done\r
+ MOV DWORD PTR [ESI+NextJCB], 0 ;Make last one NIL\r
+ RETN ;\r
+\r
+;================================================================\r
+; Allocate 4 pages (16384 bytes) for 32 Job Control Blocks (structures).\r
+; Then call InitFreeJCB\r
+\r
+PUBLIC InitDynamicJCBs:\r
+ PUSH 4 ; 4 pages for 32 JCBs (16384 bytes)\r
+ MOV EAX, OFFSET pJCBs ; Returns ptr to allocated mem in pJCBs\r
+ PUSH EAX ;\r
+ CALL FWORD PTR _AllocOSPage ; Get 'em!\r
+\r
+ XOR EAX, EAX ; Clear allocated memory for JCBs\r
+ MOV ECX, 4096 ; (4*4096=16384 - DWORDS!)\r
+ MOV EDI, pJCBs ; where to store 0s\r
+ REP STOSD ; Do it\r
+\r
+ MOV EAX, pJCBs ; Ptr to JCBs\r
+ MOV ECX, nJCBs ; Count of Job Control Blocks\r
+ MOV EDX, sJCB ; EDX is size of a JCB\r
+ CALL InitFreeJCB ; Init the array of JCBs\r
+ RETN\r
+\r
+;=============================================================================\r
+\r
+PUBLIC NewJCB:\r
+; INPUT : NONE\r
+; OUTPUT : EAX\r
+; REGISTERS : EAX,EBX,FLAGS\r
+; MODIFIES : pFreeJCB\r
+;\r
+; This routine will return to the caller a pointer to the next free jcb.\r
+; The data used in this algorithm is the free jcb pointer (pFreeJCB).\r
+; This routine will return in EAX register the address of the next free jcb.\r
+; If none exists, then EAX will contain NIL (0). This routine will also\r
+; update the value of pFreeJCB to point to the next "unused" JCB in\r
+; the free pool.\r
+;\r
+ MOV EAX,pFreeJCB ;Get OS pointer to JCBs\r
+ CMP EAX,0 ;IF pFreeJCB=NIL THEN Return;\r
+ JE NewJCBDone ;\r
+ MOV EBX,[EAX+NextJCB] ;Get pointer to next free one\r
+ MOV pFreeJCB,EBX ;Put it in OS pointer\r
+ DEC DWORD PTR _nJCBLeft ;\r
+NewJCBDone:\r
+ RETN ;\r
+\r
+;=============================================================================\r
+\r
+PUBLIC DisposeJCB:\r
+; INPUT : EAX\r
+; OUTPUT : NONE\r
+; REGISTERS : EBX,FLAGS\r
+; MODIFIES : pFreeJCB\r
+;\r
+; This routine will place the jcb pointed to by EAX back into the free\r
+; pool of JCBs pointed to by (pFreeJCB) if EAX is not NIL.\r
+; This invalidates the JCB by placing 0 in JcbPD.\r
+;\r
+ CMP EAX, 0 ; If pJCBin = NIL THEN Return;\r
+ JE DispJCBDone ;\r
+ MOV DWORD PTR [EAX+JcbPD], 0 ;Invalidate JCB\r
+ MOV EBX,pFreeJCB ;EBX has OS ptr to free list\r
+ MOV [EAX+NextJCB],EBX ;Move it into newly freed JCB\r
+ MOV pFreeJCB,EAX ;Move ptr to newly frred JCB to OS\r
+ INC DWORD PTR _nJCBLeft ;\r
+DispJCBDone:\r
+ RETN ;\r
+\r
+;============================================================\r
+;\r
+; GetpCrntJCB\r
+; Returns a pointer to the current Job Control Block in EAX.\r
+; This is based on which Task is executing. All TSSs are\r
+; assigned to a Job. A Job may have more than one Task.\r
+;\r
+; INPUT: Nothing\r
+; OUTPUT: EAX -- Linear Address of current JCB\r
+; USED: EAX, EFlags\r
+;\r
+PUBLIC GetpCrntJCB:\r
+ MOV EAX, pRunTSS ;Current Task State Segment\r
+ MOV EAX, [EAX+TSS_pJCB] ;Pointer to JCB\r
+ RETN\r
+\r
+;============================================================\r
+;\r
+; GetCrntJobNum\r
+; Many OS functions deal with the Job number. The Job number\r
+; is a field in the JCB structure.\r
+; Returns the Job number for the currently executing task.\r
+; This is based on which Task is executing. All TSSs are\r
+; assigned to a Job! A Job may have more than one Task.\r
+;\r
+; INPUT: Nothing\r
+; OUTPUT: EAX -- Current Job Number\r
+; USED: EAX, EFlags\r
+;\r
+PUBLIC GetCrntJobNum:\r
+ CALL GetpCrntJCB\r
+ MOV EAX, [EAX+JobNum] ;Current JCB\r
+ RETN\r
+\r
+;============================================================\r
+;\r
+; GetpJCB\r
+; Returns a pointer to a Job Control Block identified by number\r
+; in EAX. All TSSs are assigned to a Job.\r
+;\r
+; INPUT: EAX -- Job Number of desired pJCB\r
+; OUTPUT: EAX -- Linear Address of the JCB or 0 for invalid number\r
+; USED: EAX, EFlags\r
+;\r
+PUBLIC GetpJCB:\r
+ PUSH EDX\r
+ CMP EAX, 1\r
+ JNE GetpJCB1\r
+ MOV EAX, OFFSET MonJCB\r
+ POP EDX\r
+ RETN\r
+GetpJCB1:\r
+ CMP EAX, 2\r
+ JNE GetpJCB2\r
+ MOV EAX, OFFSET DbgJCB\r
+ POP EDX\r
+ RETN\r
+GetpJCB2:\r
+ CMP EAX, nJCBs+2 ;Add in two static JCBs\r
+ JLE GetpJCB3 ;Within range of JCBs\r
+ XOR EAX, EAX\r
+ POP EDX\r
+ RETN\r
+GetpJCB3:\r
+ SUB EAX, 3 ;Take off static JCBs+1 (make it an offset)\r
+ MOV EDX, sJCB\r
+ MUL EDX ;Times size of JCB\r
+ ADD EAX, pJCBs ;Now points to desired JCB\r
+ POP EDX\r
+ RETN ;\r
+\r
+;============================================================\r
+;\r
+; GetJobNum\r
+; Many OS functions deal with the Job number. The Job number\r
+; is a field in the JCB structure.\r
+; Returns the Job number for the pJCB in EAX in EAX.\r
+;\r
+; INPUT: EAX pJCB we want job number from.\r
+; OUTPUT: EAX -- Current Job Number\r
+; USED: EAX, EFlags\r
+;\r
+PUBLIC GetJobNum:\r
+ MOV EAX, [EAX+JobNum] ;Current JCB\r
+ RETN\r
+\r
+;============================================================\r
+;\r
+; AllocJCB (NEAR)\r
+; This allocates a new JCB (from the pool). This is a NEAR\r
+; call to support the public job management calls in high level\r
+; languages.\r
+;\r
+; Procedureal Interface :\r
+;\r
+; AllocJCB(pdJobNumRet, ppJCBRet):ercType\r
+;\r
+; pdJobNumRet is the number of the new JCB.\r
+; pJCBRet is a pointer where you want the pointer to the new JCB is returned.\r
+;\r
+; ErcNoMoreJCBs will be returned if no more JCBs are avaialble.\r
+;\r
+; pdJobNum EQU [EBP+12]\r
+; pJCBRet EQU [EBP+8]\r
+\r
+PUBLIC _AllocJCB: ;\r
+ PUSH EBP ;\r
+ MOV EBP,ESP ;\r
+\r
+ CALL NewJCB ; Get a new JCB\r
+ OR EAX, EAX ;\r
+ JNZ SHORT AJCB01 ; We got one!\r
+ MOV EAX, ErcNoMoreJCBs ; Sorry, out of them!\r
+ MOV ESP,EBP ;\r
+ POP EBP ;\r
+ RETN 8 ;\r
+\r
+AJCB01:\r
+ MOV ESI, [EBP+8] ;pJCBRet\r
+ MOV [ESI], EAX\r
+ MOV ESI, [EBP+12] ;Job Num\r
+ CALL GetJobNum ;\r
+ MOV [ESI], EAX ;\r
+ XOR EAX, EAX ;No error\r
+ MOV ESP,EBP ;\r
+ POP EBP ;\r
+ RETN 8 ;\r
+\r
+;============================================================\r
+;\r
+; DeAllocJCB (NEAR)\r
+; This Deallocates a JCB (returns it to the pool). This is a NEAR\r
+; call to support the public job management calls in high level\r
+; languages in the OS code.\r
+;\r
+; Procedureal Interface :\r
+;\r
+; DeAllocJCB(pJCB):ercType\r
+;\r
+; pJCB is a pointer the JCB to be deallocated.\r
+;\r
+; ErcNoMoreJCBs will be returned if no more JCBs are avaialble.\r
+;\r
+; pJCB EQU [EBP+8]\r
+\r
+PUBLIC _DeAllocJCB: ;\r
+ PUSH EBP ;\r
+ MOV EBP,ESP ;\r
+\r
+ MOV EAX, [EBP+8] ; pJCB\r
+ CALL DisposeJCB ; Get a new JCB\r
+ XOR EAX, EAX ;\r
+ MOV ESP,EBP ;\r
+ POP EBP ;\r
+ RETN 4 ;\r
+\r
+;============================================================\r
+;===== BEGIN PUBLIC FAR JOB CALLS ===========================\r
+;============================================================\r
+;\r
+; GetpJCB\r
+; This PUBLIC returns a pointer to the JCB for the JobNum\r
+; you specifiy.\r
+;\r
+; Procedureal Interface :\r
+;\r
+; GetpJCB(dJobNum, pJCBRet):ercType\r
+;\r
+; dJobNum is the number of the JCB you want.\r
+; pJCBRet is a pointer where you want the JCB returned.\r
+;\r
+; ErcBadJobNum will be returned if dJobNum is out of range\r
+;\r
+; ErcBadJobNum will be returned if dJobNum is invalid\r
+; or 0 will be returned with the data.\r
+;\r
+; dJobNum EQU [EBP+16]\r
+; pJCBRet EQU [EBP+12]\r
+\r
+PUBLIC __GetpJCB: ;\r
+ PUSH EBP ;\r
+ MOV EBP,ESP ;\r
+\r
+ MOV EAX, [EBP+16] ;Job Num\r
+ OR EAX, EAX\r
+ JZ GetpJcbBad ;0 is invalid\r
+ CMP EAX, nJCBs + 2; ;Dynamic + 2 static\r
+ JBE GetpJcbOK\r
+GetpJcbBad:\r
+ MOV EAX, ErcBadJobNum ;\r
+ MOV ESP,EBP ;\r
+ POP EBP ;\r
+ RETF 8 ;\r
+GetpJcbOk:\r
+ CALL GetpJCB ;puts address of JCB in EAX\r
+ MOV ESI, [EBP+12] ;pJCBRet\r
+ MOV [ESI], EAX\r
+ CMP DWORD PTR [EAX+JcbPD], 0 ;Is this a valid JCB\r
+ JNE GetpJCBOk1\r
+ MOV EAX, ErcInvalidJCB ;JCB we are pointing to is unused\r
+ MOV ESP,EBP ;\r
+ POP EBP ;\r
+ RETF 8 ;\r
+GetpJcbOk1:\r
+ XOR EAX, EAX\r
+ MOV ESP,EBP ;\r
+ POP EBP ;\r
+ RETF 8 ;\r
+\r
+;============================================================\r
+;\r
+; GetJobNum\r
+; This PUBLIC returns the number for the current Job. This is\r
+; the job that the task that called this belongs to.\r
+;\r
+; Procedureal Interface :\r
+;\r
+; GetJobNum(pJobNumRet):ercType\r
+;\r
+; pJCBRet is a pointer where you want the JCB returned.\r
+;\r
+; pJobNumRet EQU [EBP+12]\r
+\r
+PUBLIC __GetJobNum: ;\r
+ PUSH EBP ;\r
+ MOV EBP,ESP ;\r
+ CALL GetCrntJobNum ;Leave jobnum in EAX\r
+ MOV ESI, [EBP+12] ;pJobNumRet\r
+ MOV [ESI], EAX ;\r
+ XOR EAX, EAX ;No Error\r
+ POP EBP ;\r
+ RETF 4 ;\r
+\r
+\r
+;============================================================\r
+;\r
+; GetSystemDisk\r
+; This PUBLIC returns a single byte which represents the\r
+; disk that the system booted from. This is from the public\r
+; variable _BootDrive defined in Main.asm.\r
+; It return 0-n (which corresponds to A-x)\r
+; This code is here for lack of a better place.\r
+; It's really not a filesystem function either. And will\r
+; still be needed if a loadable filesystem is installed.\r
+;\r
+; Procedureal Interface :\r
+;\r
+; GetSystemDisk(pSysDiskRet):ercType\r
+;\r
+; pSysDiskRet is a pointer to a byte where\r
+; the number representing the system disk is returned.\r
+;\r
+; pSysDiskRet EQU [EBP+12]\r
+\r
+PUBLIC __GetSystemDisk ;\r
+ PUSH EBP ;\r
+ MOV EBP,ESP ;\r
+ MOV EAX, _BootDrive\r
+ AND EAX, 7Fh ;get rid of high bits\r
+ MOV ESI, [EBP+12] ;pJobNumRet\r
+ MOV [ESI], AL ;\r
+ XOR EAX, EAX ;No Error\r
+ POP EBP ;\r
+ RETF 4 ;\r
+\r
+\r
+;================= MODULE END =================================\r