1 ; MMURTL Operating System Source Code
\r
2 ; Copyright 1991,1992,1993,1994 Richard A. Burgess
\r
3 ; ALL RIGHTS RESERVED
\r
11 PUBLIC pFreeJCB DD 0 ; Ptr to free Job Control Blocks
\r
12 PUBLIC pJCBs DD 0 ; JCBs are in allocated memory
\r
13 PUBLIC _nJCBLeft DD nJCBs ; For Monitor stats
\r
15 EXTRN MonJCB DB ; Monitor JCB reference
\r
16 EXTRN _BootDrive DD ; From Main.asm
\r
18 ;======= End data,Begin Code ==================
\r
21 ;================================================================
\r
22 ;InitNewJCB is used initially by the OS to fill in the first two
\r
23 ;jobs (Monitor & Debugger)
\r
26 ; INPUT : EAX -- Ptr to JCB that is to be filled in
\r
27 ; EBX -- Linear Ptr to Page Directory for Job
\r
30 ; EDX -- Pointer to Job Virtual Video Buffer (all jobs have one!)
\r
32 ; OUTPUT : JOB Number in EAX
\r
33 ; USED : EAX, EBX, ECX, EDX, EDI, ESI, EFlags
\r
34 ; MODIFIES : JCB pointed to in EBX
\r
36 ; This fills in a JCB with new information. This is used to initilaize
\r
37 ; a new JCB during OS init and when a new Job is loaded and run.
\r
39 MOV [EAX+JcbPD],EBX ;Put Ptr to PD into JCB
\r
40 MOV EDI, EAX ;EDI points to JCB
\r
41 ADD EDI, sbJobName ;Now to JobName
\r
42 MOV BYTE PTR [EDI], CL ;size is filled in
\r
43 INC EDI ;first byte of name
\r
44 REP MOVSB ;Move it in
\r
45 MOV [EAX+pVirtVid], EDX ;Video number is in JCB
\r
46 MOV DWORD PTR [EAX+nCols], 80 ;
\r
47 MOV DWORD PTR [EAX+nLines], 25 ;
\r
48 MOV DWORD PTR [EAX+NormAttr], 7 ;
\r
49 MOV EAX, [EAX+JobNum]
\r
53 ;=============================================================================
\r
55 ; INPUT : EAX - Address of JCBs to be initialized
\r
56 ; ECX - Count of JCBs
\r
57 ; EDX - Size of JCBs
\r
59 ; USED: EAX,EBX,ECX,EDX,ESI EFLAGS
\r
60 ; MODIFIES: pFreeJCB, pJCBs
\r
62 ; This routine will initialize the free pool of Job Control Blocks (JCBs).
\r
63 ; EAX points to the first JCB,
\r
64 ; ECX is count of JCBs,
\r
65 ; EDX is size of each JCB.
\r
67 ; The pFreeJCB pointer is set to address the first element in rgJCBs.
\r
68 ; Each element of rgJCBs is set to point to the next element of rgJCBs.
\r
69 ; The last element of rgJCBs is set to point to nothing (NIL).
\r
70 ; The JCBs are also sequentially numbered. We can't use it's position
\r
71 ; in the array because some JCBs are static (Mon and Debugger), while
\r
72 ; others (the ones we are initializing now) are dynamicly allocated.
\r
75 MOV pFreeJCB,EAX ;Set up OS pointer to list
\r
76 MOV pJCBs, EAX ;Set up global ptr to first JCB
\r
77 MOV EBX, 3 ;1st number for Dynamic JCBs
\r
79 MOV ESI,EAX ;EBX has pointer to current one
\r
80 ADD EAX,EDX ;EAX points to next one
\r
81 MOV [ESI+NextJCB],EAX ;Make current point to next
\r
82 MOV [ESI+JobNum], EBX ;Number it
\r
84 LOOP JCB_Loop ;Go back till done
\r
85 MOV DWORD PTR [ESI+NextJCB], 0 ;Make last one NIL
\r
88 ;================================================================
\r
89 ; Allocate 4 pages (16384 bytes) for 32 Job Control Blocks (structures).
\r
90 ; Then call InitFreeJCB
\r
92 PUBLIC InitDynamicJCBs:
\r
93 PUSH 4 ; 4 pages for 32 JCBs (16384 bytes)
\r
94 MOV EAX, OFFSET pJCBs ; Returns ptr to allocated mem in pJCBs
\r
96 CALL FWORD PTR _AllocOSPage ; Get 'em!
\r
98 XOR EAX, EAX ; Clear allocated memory for JCBs
\r
99 MOV ECX, 4096 ; (4*4096=16384 - DWORDS!)
\r
100 MOV EDI, pJCBs ; where to store 0s
\r
103 MOV EAX, pJCBs ; Ptr to JCBs
\r
104 MOV ECX, nJCBs ; Count of Job Control Blocks
\r
105 MOV EDX, sJCB ; EDX is size of a JCB
\r
106 CALL InitFreeJCB ; Init the array of JCBs
\r
109 ;=============================================================================
\r
114 ; REGISTERS : EAX,EBX,FLAGS
\r
115 ; MODIFIES : pFreeJCB
\r
117 ; This routine will return to the caller a pointer to the next free jcb.
\r
118 ; The data used in this algorithm is the free jcb pointer (pFreeJCB).
\r
119 ; This routine will return in EAX register the address of the next free jcb.
\r
120 ; If none exists, then EAX will contain NIL (0). This routine will also
\r
121 ; update the value of pFreeJCB to point to the next "unused" JCB in
\r
124 MOV EAX,pFreeJCB ;Get OS pointer to JCBs
\r
125 CMP EAX,0 ;IF pFreeJCB=NIL THEN Return;
\r
127 MOV EBX,[EAX+NextJCB] ;Get pointer to next free one
\r
128 MOV pFreeJCB,EBX ;Put it in OS pointer
\r
129 DEC DWORD PTR _nJCBLeft ;
\r
133 ;=============================================================================
\r
138 ; REGISTERS : EBX,FLAGS
\r
139 ; MODIFIES : pFreeJCB
\r
141 ; This routine will place the jcb pointed to by EAX back into the free
\r
142 ; pool of JCBs pointed to by (pFreeJCB) if EAX is not NIL.
\r
143 ; This invalidates the JCB by placing 0 in JcbPD.
\r
145 CMP EAX, 0 ; If pJCBin = NIL THEN Return;
\r
147 MOV DWORD PTR [EAX+JcbPD], 0 ;Invalidate JCB
\r
148 MOV EBX,pFreeJCB ;EBX has OS ptr to free list
\r
149 MOV [EAX+NextJCB],EBX ;Move it into newly freed JCB
\r
150 MOV pFreeJCB,EAX ;Move ptr to newly frred JCB to OS
\r
151 INC DWORD PTR _nJCBLeft ;
\r
155 ;============================================================
\r
158 ; Returns a pointer to the current Job Control Block in EAX.
\r
159 ; This is based on which Task is executing. All TSSs are
\r
160 ; assigned to a Job. A Job may have more than one Task.
\r
163 ; OUTPUT: EAX -- Linear Address of current JCB
\r
164 ; USED: EAX, EFlags
\r
166 PUBLIC GetpCrntJCB:
\r
167 MOV EAX, pRunTSS ;Current Task State Segment
\r
168 MOV EAX, [EAX+TSS_pJCB] ;Pointer to JCB
\r
171 ;============================================================
\r
174 ; Many OS functions deal with the Job number. The Job number
\r
175 ; is a field in the JCB structure.
\r
176 ; Returns the Job number for the currently executing task.
\r
177 ; This is based on which Task is executing. All TSSs are
\r
178 ; assigned to a Job! A Job may have more than one Task.
\r
181 ; OUTPUT: EAX -- Current Job Number
\r
182 ; USED: EAX, EFlags
\r
184 PUBLIC GetCrntJobNum:
\r
186 MOV EAX, [EAX+JobNum] ;Current JCB
\r
189 ;============================================================
\r
192 ; Returns a pointer to a Job Control Block identified by number
\r
193 ; in EAX. All TSSs are assigned to a Job.
\r
195 ; INPUT: EAX -- Job Number of desired pJCB
\r
196 ; OUTPUT: EAX -- Linear Address of the JCB or 0 for invalid number
\r
197 ; USED: EAX, EFlags
\r
203 MOV EAX, OFFSET MonJCB
\r
209 MOV EAX, OFFSET DbgJCB
\r
213 CMP EAX, nJCBs+2 ;Add in two static JCBs
\r
214 JLE GetpJCB3 ;Within range of JCBs
\r
219 SUB EAX, 3 ;Take off static JCBs+1 (make it an offset)
\r
221 MUL EDX ;Times size of JCB
\r
222 ADD EAX, pJCBs ;Now points to desired JCB
\r
226 ;============================================================
\r
229 ; Many OS functions deal with the Job number. The Job number
\r
230 ; is a field in the JCB structure.
\r
231 ; Returns the Job number for the pJCB in EAX in EAX.
\r
233 ; INPUT: EAX pJCB we want job number from.
\r
234 ; OUTPUT: EAX -- Current Job Number
\r
235 ; USED: EAX, EFlags
\r
238 MOV EAX, [EAX+JobNum] ;Current JCB
\r
241 ;============================================================
\r
244 ; This allocates a new JCB (from the pool). This is a NEAR
\r
245 ; call to support the public job management calls in high level
\r
248 ; Procedureal Interface :
\r
250 ; AllocJCB(pdJobNumRet, ppJCBRet):ercType
\r
252 ; pdJobNumRet is the number of the new JCB.
\r
253 ; pJCBRet is a pointer where you want the pointer to the new JCB is returned.
\r
255 ; ErcNoMoreJCBs will be returned if no more JCBs are avaialble.
\r
257 ; pdJobNum EQU [EBP+12]
\r
258 ; pJCBRet EQU [EBP+8]
\r
260 PUBLIC _AllocJCB: ;
\r
264 CALL NewJCB ; Get a new JCB
\r
266 JNZ SHORT AJCB01 ; We got one!
\r
267 MOV EAX, ErcNoMoreJCBs ; Sorry, out of them!
\r
273 MOV ESI, [EBP+8] ;pJCBRet
\r
275 MOV ESI, [EBP+12] ;Job Num
\r
278 XOR EAX, EAX ;No error
\r
283 ;============================================================
\r
285 ; DeAllocJCB (NEAR)
\r
286 ; This Deallocates a JCB (returns it to the pool). This is a NEAR
\r
287 ; call to support the public job management calls in high level
\r
288 ; languages in the OS code.
\r
290 ; Procedureal Interface :
\r
292 ; DeAllocJCB(pJCB):ercType
\r
294 ; pJCB is a pointer the JCB to be deallocated.
\r
296 ; ErcNoMoreJCBs will be returned if no more JCBs are avaialble.
\r
300 PUBLIC _DeAllocJCB: ;
\r
304 MOV EAX, [EBP+8] ; pJCB
\r
305 CALL DisposeJCB ; Get a new JCB
\r
311 ;============================================================
\r
312 ;===== BEGIN PUBLIC FAR JOB CALLS ===========================
\r
313 ;============================================================
\r
316 ; This PUBLIC returns a pointer to the JCB for the JobNum
\r
319 ; Procedureal Interface :
\r
321 ; GetpJCB(dJobNum, pJCBRet):ercType
\r
323 ; dJobNum is the number of the JCB you want.
\r
324 ; pJCBRet is a pointer where you want the JCB returned.
\r
326 ; ErcBadJobNum will be returned if dJobNum is out of range
\r
328 ; ErcBadJobNum will be returned if dJobNum is invalid
\r
329 ; or 0 will be returned with the data.
\r
331 ; dJobNum EQU [EBP+16]
\r
332 ; pJCBRet EQU [EBP+12]
\r
334 PUBLIC __GetpJCB: ;
\r
338 MOV EAX, [EBP+16] ;Job Num
\r
340 JZ GetpJcbBad ;0 is invalid
\r
341 CMP EAX, nJCBs + 2; ;Dynamic + 2 static
\r
344 MOV EAX, ErcBadJobNum ;
\r
349 CALL GetpJCB ;puts address of JCB in EAX
\r
350 MOV ESI, [EBP+12] ;pJCBRet
\r
352 CMP DWORD PTR [EAX+JcbPD], 0 ;Is this a valid JCB
\r
354 MOV EAX, ErcInvalidJCB ;JCB we are pointing to is unused
\r
364 ;============================================================
\r
367 ; This PUBLIC returns the number for the current Job. This is
\r
368 ; the job that the task that called this belongs to.
\r
370 ; Procedureal Interface :
\r
372 ; GetJobNum(pJobNumRet):ercType
\r
374 ; pJCBRet is a pointer where you want the JCB returned.
\r
376 ; pJobNumRet EQU [EBP+12]
\r
378 PUBLIC __GetJobNum: ;
\r
381 CALL GetCrntJobNum ;Leave jobnum in EAX
\r
382 MOV ESI, [EBP+12] ;pJobNumRet
\r
384 XOR EAX, EAX ;No Error
\r
389 ;============================================================
\r
392 ; This PUBLIC returns a single byte which represents the
\r
393 ; disk that the system booted from. This is from the public
\r
394 ; variable _BootDrive defined in Main.asm.
\r
395 ; It return 0-n (which corresponds to A-x)
\r
396 ; This code is here for lack of a better place.
\r
397 ; It's really not a filesystem function either. And will
\r
398 ; still be needed if a loadable filesystem is installed.
\r
400 ; Procedureal Interface :
\r
402 ; GetSystemDisk(pSysDiskRet):ercType
\r
404 ; pSysDiskRet is a pointer to a byte where
\r
405 ; the number representing the system disk is returned.
\r
407 ; pSysDiskRet EQU [EBP+12]
\r
409 PUBLIC __GetSystemDisk ;
\r
412 MOV EAX, _BootDrive
\r
413 AND EAX, 7Fh ;get rid of high bits
\r
414 MOV ESI, [EBP+12] ;pJobNumRet
\r
416 XOR EAX, EAX ;No Error
\r
421 ;================= MODULE END =================================
\r