25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

32KB

Developing Your Own 32-Bit Operating System — Chapter-11: The MMURTL Monitor Program

  • Source: /library/Developing Your Own 32-Bit Operating System/source-file.pdf
  • PDF pages: 181–202
  • Pages without text: 202

11 The MMURTL Monitor Program

I
160 Part III M MMURTL-Specific Details The Monitor program is included as part of the operating system. Many of the functions performed by the monitor are for testing the system. The monitor also serves as a context display controller by monitoring for global keys that indicate the user's desire to change, or terminate, the job he or she is currently viewing. When the user presses these global keys, the keyboard, as well as the video display, is assigned to the new job or is terminated. In future versions of MMURTL, many of the functions now performed by the monitor will be moved to external programs. If you intend to write an operating system, you will find a need for something similar to the monitor as an initial piece of code for testing built into the oper- ating system. Active job (Video and Keyboard) When multiple jobs are running in MMURTL, only one job at a time can be displayed or accept keyboard input. The Monitor program enables you to select the job with which you are currently interacting. You select a job by pressing the Ctrl-Alt-PageDown keys to move forward through the active jobs until you see the one you want. The current job may also be terminated by pressing Ctrl- Alt-Delete. Even when a job is not being displayed, it is still running unless it's waiting for something such as keyboard input or some other form of communication. If it's displaying video data, it con- tinues to run because a job never actually knows if it is displaying data to the real screen or to its own virtual screen, a buffer in memory. Initial jobs After all internal device drivers and services are loaded, the monitor attempts to open a text file, called Initial.Job, in the system directory. This file contains the filenames of one or more run files you want to execute automatically on boot up. The format is very simple. Each line lists the full file specification of a RUN file. The name must start in the first column of a line. No spaces, tabs or other characters are allowed before the RUN filename. A line that begins with a semicolon is ignored and considered a comment line. Listing 11.1 shows a sample Initial.Job file. Listing 11.1. Sample Initial.Job file.

;INITIAL.JOB - This is the initial jobs file. ;You may list the jobs that you wanted executed upon

Chapter 11 ■ The MMURTL Monitor Program jsystem boot in this file. One run file name per line, ;no spaces in front of the name and a proper end-of-line ;after each entry. Any spaces, tabs or comments after ;the run file name are ignored. No parameters are passed ;to the run file. The file name must contain the FULL ;file name including path, (e.g., Drive: \DIR\NAME. RUN) ;Comment lines begin with a semicolon ;Maximum line length is 80 characters total. C:\MSamples\Service\Service.run C:\MMSYS\CLI.RUN < this will be loaded on bootup ;End of file If the executable job listed is CLI.RUN, the video and keyboard will be assigned to this job and taken away from the monitor. Monitor Function Keys The monitor also provides other functions such as system resource display, job display, and access to the built-in debugger. The functions are provided by function keys that are labeled across the bottom of the display. Table 11.1 describes the function of each assigned key. Table 1 1 .1 . Monitor function keys. Key Label Function Fl LDCLI Load a command line interpreter F2 JOBS List jobs F3 STATS Show system resource status F8 BOOT Reboots the system (hard reset) F10 DEBUG Enter the debugger Monitor Program Theory After all internal static and dynamic structures are initialized, the monitor is reached with a JMP instruction. The first thing accomplished by the monitor is the initialization of all internal device drivers and system services. During this process, any errors returned are displayed. A status code of zero indicates successful initialization. The device drivers that are initialized include the hard disk, floppy disk, RS-232 serial com- munications port, and the parallel port (LPT) driver.

H Part III M MMURTL-Specific Details The initialized services include the keyboard and the file system. The initialization also includes starting two tasks inside the monitor code. The first additional task provides the context-switching capabilities by leaving a global key request with the keyboard service. It looks for the Ctrl-Alt-PageDown key combination, and shifts the keyboard and video to the next job in numerical order. This task also looks for the Ctrl- Alt-Delete key combination which terminates a job. The second task is used to recover resources when a job ends or is terminated for memory ac- cess or other protection violations. After the initialization is complete, user interaction is provided via the function keys discussed in Table 11.1. The monitor echoes other keys to the screen to show you it is working properly. They are displayed as typed. Performance Monitoring Performance monitoring is provided by sampling statistic-gathering public variables the oper- ating system maintains and updates. The statistics provide a snapshot of system resources every half second. These statistics include: Free 4K memory pages — This is the total number of 4K memory pages available for allocation by the memory-management code. Task switches total — This is the total count of task switches since boot up. Preemptive task switches — This is the total number of times a task was preempted for a higher priority task. CPU idle ticks (no work) — This is the number of times the operating system had nothing to do. There were no tasks ready to run. This number does not directly relate the timer ticks because all tasks can become idle several times between the time interrupt interval. Tasks Ready to Run — This is the number of tasks currently queued to run. If this number is greater than zero, you will see the preemptive task switch count increase. Free Task State Segments — These are task-management structures. The memory they occupy is dynamically allocated, but the count is fixed at OS build time. Each new task uses one of these. Free Job Control Blocks — This is the number of free job control blocks left. Job control blocks are also dynamically allocated with a fixed count at OS build time. Each job uses one. Free Request Blocks — Each time a request is made, a request block is allocated. When the response is made by the service, the request block is returned for re-use. These structures are also in dynamically allocated memory, but have a Cwcd count at OS build time.

Chapter 11 ■ The MMURTL Monitor Program Free link blocks — The link block is a small structure used by all messages sent and received, including requests. The number may seem a little high, but dozens of messages may be sent between tasks, even in the same job, that don't get picked up right away. Free link blocks are static and the count is determined at OS build time. Free exchanges — This is the number of free exchanges that can be allocated. Ex- changes are also dynamically allocated with a fixed count at OS build time. Monitor Source Listing Text-formatting functions are provided with the xprintf function defined in the monitor. I included no C library code in the operating system itself. In future versions, when a lot of the monitor functionality is moved out of the operating system, the C library code can be used. See Listing 11.2. Listing 1 1 .2. Monitor program source listing. #define U32 unsigned long #define S32 long #define U16 unsigned int #define S16 int #define U8 unsigned char #define S8 char #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 “MDevDrv.h” #define ok 0 #define ErcNoDevice 504 static char rgStatLine[] = “mm/dd/yy 00:00:00 MMURTL Monitor Tick:0 static char rgMonMenul [ ] = “LdCLI\xb3Jobs \xb3Stats \xb3 static char rgMonMenu2[] = " \xb3 \xb3 \xb3Reboot” static char rgMonMenu3[] = " \xb3Debug \xb3 \xb3 “; static char rgCPRI [ ] ="MMURTL (tm) - Message based, Multitasking, Real-Time kernel.” ; static char rgCPR2[ ] ="Copyright (c) R.A. Burgess, 1990-1995, All Rights Reserved”; static char CRLF = “\r\n\r\n”; static unsigned long Color = WHITE ;BGBLACK; / Color test for xprintf */

164 I Part III * MMURTL-Specific Details Listing 11.2. continued static long time, date, tick; unsigned long KillExch; /* Messaging for stat task KILL proc */ static unsigned long KillMsg[2]; static unsigned long KillError; static unsigned long KillJobNum; static unsigned char f Killed; static unsigned long MngrExch; static unsigned long MngrMsg[2]; static unsigned long MngrHndl; static unsigned long gcode; static unsigned long GPExch; static unsigned long GPMsg[2]; static unsigned long GPHndl; static unsigned long GPIExch; static unsigned long GP1Msg[2]; static unsigned long GPIHndl; /* First DWORD = TSSExch, second is ERROR */ /* Messaging for stat task */ /* Messaging for main */ /* Extra Messaging for main /* Structure for disk device driver status and setup */ static struct diskstattype { U32 ere; U32 blocks_done; U32 BlocksMax; U8 fNewMedia; U8 type_now; U8 resvd1[2]; U32 nCyl; U32 nHead; U32 nSectors; U32 nBPS; /* current disk type for drive selected */ /* padding for DWord align */ /* total physical cylinders */ /* total heads on device */ /* Sectors per track */ /* Number of bytes per sect */ U32 LastRecalErcO; U32 LastSeekErcO; U8 LastStatByteO; U8 LastErcByteO; U8 flntOnReset; / U8 filler0; U32 LastRecalErd ; U32 LastSeekErd; U8 LastStatBytel; U8 LastErcBytel ; U8 ResetStatByte; U8 fillerl; U32 resvd1(2] }; Interrupt was received on HDCRESET */ /* Status Byte immediately after RESET */ /* out to 64 bytes */ static struct diskstattype DiskStatus; #define nMaxJCBs 34 /* 32 dynamic plus 2 static */ static struct JCBRec *pJCB;

Chapter 11 ■ The MMUR TL Monitor Program |l63 static long StatStack[256] ; /* 1024 byte stack for Stat task */ static long MngrStack[256] ; /* 1024 byte stack for Mngr task */ static unsigned char Buffer[512]; static unsigned long nMemPages; extern unsigned long oMemMax; extern unsigned long nSwitches; extern unsigned long nSlices; extern unsigned long nHalts; extern unsigned long nReady; extern unsigned long nRQBLeft; extern unsigned long nJCBLeft; extern unsigned long nTSSLeft; extern unsigned long nLBLeft; extern unsigned long nEXCHLeft; extern unsigned long BootDrive; /*============ protos (NEAR MMURTL support calls) =============== extern long InitKBDService(void) ; /* From Keyboard. asm */ extern long fdisk_setup(void) ; /* From Floppy. c */ extern long hdisk_setup(void) ; /* From HardlDE.c */ extern long coms_setup(void) ; /* From RS232.C */ extern long lptsetup(void) ; /* From Parallel. c */ extern long InitFS(void) ; /* From Fsys.c */ extern long GetExchOwner(long Exch, char *pJCBRet); extern long DeAllocJCB(long *pdJobNumRet, char *ppJCBRet); /*=================== START OF CODE ====================*/ Formatted output routines for montitor program xprintf, xsprintf. #include <stdarg.h> #define S SIZE 100

  • Determine if a character is a numeric digit static long isdigit(long chr) { MOV EAX,[EBP+8] CMP AL, 30h 0 JL isdigit0 No CMP AL, 39h JLE isdigitl Yes isdigit0: XOR EAX.EAX ;No JMP SHORT isdigil :2

166 Part III ■ MMURTL-Specific Details Listing 11.2. continued isdigitl : MOV EAX, -1 isdigit2: #endasm } static long strlen(char *cs) { #asm XOR EAX, EAX MOV ESI,[EBP+8] _strlen0: CMP BYTE PTR [ESI],0 JE _strlen1 INC ESI INC EAX JMP SHORT _strlen0 _strlen1 : #endasm } This does the actual parsing of the format and also moves to the next arg(s) in the list from the passed in arg pointer. The number of chars written is returned (not incl \0). static long _ffmt(char *outptr, char *fmt, long *argptr) { char numstk[33], *ptr, justify, zero, minus, chr; unsigned long width, value, i, total; total = 0; while(chr = fmt++) { if(chr == ‘%') { / format code */ chr = *fmt++; ptr = &numstk[32] ; ptr = justify = minus = 0; width = value = i = 0; zero = ' ' ; if (chr == ' -') { / left justify */

  • -justify; chr = fmt++; } if (chr == ‘0’) / leading zeros / zero = ‘0’ ; while(isdigit(chr) ) { / field width specifier */ width = (width * 10) + (chr - ‘0’); chr = *fmt++; }

Chapter 11 ■ The MMURTL Monitor Program |
167 value argptr; /* get parameter value */ switch (chr) { case ‘d’ /* decimal number */ if (value & 0x80000000) { value = -value; ++minus; } case ‘u’ : /* unsigned number */ i = 10; break case ‘x’ /* hexidecimal number */ case ‘X’ i = 16; break case ‘o’ /* octal number */ i = 8 break case ‘b’ /* binary number */ i = 2 break case ‘c’ /* character data */ *- -ptr = value; break; case ‘s’ : /* string */ ptr = value; /* value is ptr to string */ break; default: /* all others */ *--ptr = chr; ++argf

tr; /* backup to last arg */ } if(i) /* for all numbers, generate the ASCII string */ do { if((chr = (value % i) + ‘0’) > ‘9’) chr += 7; *- -ptr = chr; } while(value /= i) ; /* output sign if any */ if (minus) { *outptr++ = ' - ' ; ++total; if (width)

  • -width; } I* pad with ‘zero’ value if right justify enabled */ if (width && ! justify) { for(i = strlen(ptr); i < width; ++i)

168 Part III ■ MMURTL-Specific Details Listing 11.2. continued outptr++ = zero; ++total; } / move in data */ i = 0; value = width - 1 ; while((*ptr) && (i <= value)) { *outptr++ = ptr++; ++total; ++i; } / pad with ‘zero’ value if left justify enabled */ if(width && justify) { while(i < width) { outptr++ = zero; ++total; ++i; } } } else { / not format char, just move into string */ *outptr++ = chr; ++total; } } *outptr = 0; return total Formatted print to screen ong xprintf(char fmt, ...) va_list ap; long total; char buffer[S_SIZE]; va_start(ap, fmt); / set up ap pointer total = _ffmt(buffer, fmt, ap); TTYOut( buffer, strlen(buffer) , Color); va_end(ap, fmt); return total;

Chapter 11 ■ The MMURTL Monitor Prograt Formatted print to string s long xsprintf (char *s, char fmt, { va_list ap; long total; va_start(ap, fmt); / set up ap pointer */ total = _ffmt(s, fmt, ap); va_end(ap, fmt); return total; Checks to ensure we don't scroll the function keys off the screen. void CheckScreen() { long iCol, iLine; GetXY(&iCol, &iLine); if (iLine >= 23) { ScrollVid (0,1 ,80,23,1); SetXY(0,22); } } This is called to initialize the screen. static void InitScreen(void) { ClrScr(); xsprintf (&rgStatLine[70] , “%d”, tick); PutVidChars(0,0, rgStatLine, 80, WHITE jBGBLUE) ; PutVidChars(0, 24, rgMonMenul , 26, BLUE;BGWHITE) ; PutVidChars(27, 24, rgMonMenu2, 26, BLUE|BGWHITE) ; PutVidChars(54, 24, rgMonMenu3, 25, BLUE|BGWHITE) ; SetXY(0,1); return; This is the status task for the Monitor. Besides displaying the top status line for the monitor, it has the job of looking for messages from the job code that indicate a job has terminated. When it gets one, it recovers the last of the resources and then notifies the user on the screen.

I
170 Part III ■ MMURTL-Specific Details Listing 11.2. continued static void StatTask(void) { unsigned long ere, i, Exch, Msg[2]; U8 *pPD, *pVid; for(;;) { GetCMOSTime(&time) ; rgStatLine[10] = ‘0

  • ((time » 20) & 0x0f) rgStatLine[11] = ‘0
  • ((time » 16) & 0x0f) rgStatLine[13] = ‘0
  • ((time » 12) & 0x0f) rgStatLine[l4] = ‘0
  • ((time » 8) & 0x0f); rgStatl_ine[16] = ‘0
  • ((time » 4) & 0x0f); /* seconds rgStatLine[17] = ‘0
  • (time & 0x0f ); GetCMOSDate(&date); rgStatLine[0] = ‘0’
  • ((date » 20) & 0x0f); /* month */ rgStatl_ine[1] = ‘0’
  • ((date » 16) & 0x0f); rgStatLine[3] = ‘0’
  • ((date » 12) & 0x0f); /* day */ rgStatLine[4] = ‘0’
  • ((date » 8) & 0x0f); rgStatLine[6] = ‘0’
  • ((date » 28) & 0x0f); /* year */ rgStatLine[7] = ‘0’
  • ((date » 24) & 0x0f); GetTimerTick(&tick) ; xsprintf (&rgStatLine[70] , “%d”, tick); PutVidChars(0,0, rgStatLine, 80, WHITE | BGBLUE) ; Sleep(50); /* sleep 0.5 second */ GetTimerTick(&tick) ; xsprintf (&rgStatLine[70] , “%d”, tick); PutVidChars(0,0, rgStatLine, 80, WHITE | BGBLUE) ; Sleep(50); /* sleep 0.5 second */ /* Now we check for tasks that are Jobs that are killing themselves (either due to fatal errors or no exitjob). The message has Error, TSSExch in it. ere = CheckMsg(KillExch, KillMsg); if (lerc) { /* someone's there wanting to terminate...’ /* Get and save the error (KillMsg[0]) •/ KillError = KillMsg[0]; /* Call GetExchOwner which gives us pJCB */ ere = GetExchOwner(KillMsg[1] , &pJCB); if (lerc) KillJobNum = pJCB->JobNum; Tone(440,50);

Chapter 11 ■ The MMURTL Monitor Program \m\ xprintf(“Job number %d terminated. Error: %d\r\n”, KillJobNum, KillError); CheckScreen( ) ; pPD = pJCB->pJcbPD; pVid = pJCB->pVirtVid; /* Must change video to monitor if this guy owned it */ GetVidOwner(&i) ; if (i == KillJobNum) { GetTSSExch(&Exch) ; /* Use our TSS exchange for Request */ SetVidOwner(l) ; ere = Request (“KEYBOARD”, 4, Exch, &i, 0, 0, 0, 0,0, 1 , 0, 0) ; ere = WaitMsg(Exch, Msg); } /* Now we deallocate the JCB and the TSSExch which will free the TSS automatically! */ DeAllocExch(KillMsg[1]); DeAllocJCB(pJCB) ; /* No error returned */ /* When the JCB was created, the PD and its 1st PDE (PT) were allocated as two pages next to each other in linear memory. So we can just deallocate both pages in one shot. Then we deallocate the single page for virtual video. */ DeAllocPage(pPD, 2); DeAllocPagejpVid, 1); f Killed = 1; /* We're done (and so is he...) */ } /* for EVER */ }


This is the Manager task for the Monitor. It allows us to switch jobs with the Ctrl-Alt -PageDown key. We don't actually switch jobs, we just ressign video and keyboard to the next active job (except the Debugger). Also, if the debugger has the video... we don't do it at all! This also looks for Ctrl -Alt -Delete which kills the job that owns the keyboard/video so long as it's not the Monitor or the Debugger.

j 72 I Part III ■ MMURTL-Specific Details Listing 1 1 .2. continued static void MngrTask(void) { long ere, i, j , fDone; char pJCB; / Leave a Global Key Request outstanding with KBD service for the status task / ere = Request ( “KEYBOARD” , 2, MngrExch, SMngrHndl, 0, &gcode, for(;;) { ere = WaitMsg(MngrExch, MngrMsg); if (!erc) { if ((gcode & 0xff) == 0x0C) { / Find next valid Job that is NOT the debugger and assign Vid and Keyboard to it. / ere = GetVidOwner(&j ) ; fDone = 0; i - j; while (IfDone) { i++; if (i==2) i = 3; else if (i>34) i = 1; ere = GetpJCB(i, &pJCB); / ere = 0 if valid JCB / if ((lerc) !| (i==j)) fDone = 1 ; } if (i != j) { SetVidOwner(i) ; ere = Request (“KEYBOARD”, 4, MngrExch, &MngrHndl, 0, 0, 0, 0, 0, i, 0, 0); ere = WaitMsg (MngrExch, MngrMsg); } } else if ((gcode & 0xff) == 0x7F) / CTRL-ALT-DEL (Kill)/ { ere = GetVidOwner(&j ) ; ere = KillJob(j); } / leave another global key request */ ere = Request( “KEYBOARD” , 2, MngrExch, &MngrHndl, 0, &gcode, 4, 0, 0, 0, 0, 0); }

Chapter 11 ■ The MMURTL Monitor Progra } /* for EVER */ } *******! This simply does a software interrupt 03 (Debugger) r******* *****! static void GoDebug(void) { #asm INT 03 ffendasm return; } r****** * i This strobes keyboard data port 60h with 00 after sending 0D1 command to Command port. We have to loop reading the status bit of the command port to make sure it's OK to send the command. This resets the processor which then executes the boot ROM. static void Reboot (void) { #asm CLI MOV ECX, 0FFFFh Reboot© IN AL,64h TEST AL,02h LOOPNZ Reboot0 MOV AL,0FEh OUT 64h,AL ST I #endasm return; ;first we clear interrupts ; check port up to 64K times ;Read Status Byte into AL ;Test The Input Buffer Full Bit ;Strobe bit 0 of keyboard crtlr output *******************; This reads a file called Initial. Job from the system directory and loads all jobs specified in the file. Video and keyboard are not assigned to any of these jobs unless it is cli.run and the last job loaded. r********i r********* ****/ void LoadJobFile(void) { long ere, fh, sjobfile, cbrunfile, i, j, job; unsigned char sdisk; char ajobfile[50] ; char arunfile[80] ; char fdone, fcli; GetSystemDisk(&sdisk)

Part III ■ MMURTL-Specific Details Listing 11.2. continued sdisk &= 0x7F; sdisk += 0x41; /* 0=A, 1=B, 2=C etc. */ ajobfile[0] = sdisk; CopyData(":\MMSYS\INITIAL.JOB\0”, &ajobf ile[ 1 ] , 20); sjobfile = strlen(ajobfile) ; ere = OpenFile(ajobfile, sjobfile, 0, 1, &fh); if (!erc) { fdone = 0; job = 0; fcli = 0; while (Ifdone) { i = 0; do { ere = ReadBytes(fh, &arunfile[i++] , 1, &j ) ; } while ((lerc) && (arunfile[i-1 ] != 0x0A) && (i < 80)) if ((!erc) && (i > 1)) { if (arunfile[0] ==’;') /* a comment line */ continue; cbrunfile = 0; while ( (arunfile[cbrunfile] (arunf ile[ cbrunfile] (arunf ile[ cbrunfile] (arunf ile [ cbrunfile] (arunf ile[cbrunf ile] ) ) cbrunfile++; = 0x0A) && = 0X0D) && = 0x20) && = 0x09) && if (cbrunfile > 2) { arunfilefcbrunf ile] ■ 0; /* null terminte for display */ if ((cbrunfile > 8) && (CompareNCS(&arunfile[ cbrunfile -7] , “cli.run”, 7) == -1)) fcli = 1; else fcli = 0; xprintf (“Loading: %s...\r\n”, arunf ile); CheckScreen( ) ; ere = LoadNewJob(arunfile, cbrunfile, &job); if (lerc) { xprintf (“Successfully loaded as job %d\r\n”, job); CheckScreen() ; Sleep(50); } else {

Chapter 11 ■ The MMURTL Monitor Program xprintf( “ERROR %d Loading job\r\n”, ere); CheckScreen( ) ; Sleep(50); job = 0; ere = 0; } } } else f done = 1 ; } CloseFile(fh); /* if the last succesfully loaded job was a CLI, assign the keybaord and video to it. */ if ((job > 2) && (fcli)) { SetVidOwner(job) ; ere = Request ( “KEYBOARD” , 4, GPlExch, &GP1Hndl, 0, 0, 0, 0, 0, job, 0, 0); if (!erc) ere = WaitMsg (GPlExch, GPIMsg); } } else { xprintf( “INITIAL. JOB file not found in system directory. \r\n” CheckScreen() ; } /♦A************************************************** This Loads the MMURTL Command Line Interpreter and switches video and keyboard to give the user access to it. static long LoadCLI(void) { long ere, job; unsigned char sdisk, acli[40]; GetSystemDisk(&sdisk) ; sdisk &= 0x7F; sdisk += 0x41; /* 0=A, 1=B, 2=C etc. */ acli[0] = sdisk; CopyData(":\MMSYS\CLI.RUN\0”, &acli[1], 16); xprintf (“Loading: %s...", acli) ; ere = LoadNewJob(acli, strlen(acli) , &job); if (!erc) { xprintf (“New CLI Job Number is: %d\r\n”, job) CheckScreen() ; Sleep(50); SetVidOwner( job) ;

I
176 Part III ■ MMURTL-Specific Details Listing 11.2. continued ere = Request (“KEYBOARD”, 4, GPIExch, &GP1Hndl, 0, 0, 0, 0, 0, job, 0, 0); if (!erc) ere = WaitMsg (GPIExch, GPIMsg); } return ere; } This is the main procedure called from the OS after all OS structures and memory are initialized. void Monitor(void) { long ere, i, j, k, iCol, iLine; unsigned long ccode, ccodel ; unsigned char c; char text[70] ; InitScreen() ; Tone(250,15); /* 250 Hz for 150ms */ Tone (1000, 33); /* 250 Hz for 330ms */ /* Allocate an exchange for the Manager task global keycode */ ere = AllocExch(&MngrExch) ; if (ere) xprintf (“AllocExch (Mngr Exch) Error: %d\r\n”, ere); ere = SpawnTask( &StatTask, 24, 0, &StatStack[255] , 1 ); /* Task 4 */ if (ere) xprintf (“SpawnTask (StatTask) Error: %d\r\n”, ere); ere = AllocExch(&KillExch) ; if (ere) xprintf (“AllocExch (Kill Exch) Error: %d\r\n”, ere); Color = YELLOW ;BGBLACK; xprintf (“MMURTL (tm) - Message based, Multitasking, Real-Time kerneL\r\n” ) ; xprintf (“Copyright (c) R. A. Burgess, 1991-1995 ALL RIGHTS RESERVED\r\n\r\n” ) Color = WHITE iBGBLACK; c = ((BootDrive & 0x7f) + 0x41); xprintf (“BootDrive: %c\r\n”, c); i = (oMemMax+1 )/1024; xprintf (“Total memory (Kb): %d\r\n”, i); ere = QueryPages(&nMemPages) ; i = (nMemPages*4096)/1024; xprintf ( “Free memory (Kb): %d\r\n”, i); ere = InitKBDService() ;

Chapter 11 ■ The MMURTL Monitor Program El xprintf ( “Init KBD Service Error: %d\r\n”, ere); ere = coms_setup( ) ; xprintf (“Init Serial Comms Device Driver Error: %d\r\n”, ere); ere = lpt_setup() ; xprintf (“Init Parallel LPT Device Driver Error: %d\r\n”, ere); /* Allocate general purpose exchanges to use in the monitor */ ere = AllocExch(&GPExch) ; if (ere) xprintf (“AllocExch Error: %d\r\n”, ere); ere = AllocExch(&GP1Exch); if (ere) xprintf (“AllocExch GP1 Error: %d\r\n”, ere); xprintf ( “Init floppy device driver... Error: “); ere = fdisk_setup() ; xprintf ( “%d\r\n” , ere); xprintf (“Init hard disk device driver, ere = hdisk_setup( ) ; xprintf ( “%d\r\n” , ere); Error: “) xprintf ( “Initializing file systen ere = InitFS() ; xprintf (“File System... Error: %d\r\n’ \r\n”); ere); /* Spawn manager task */ SpawnTask( &MngrTask, 10, 0, &MngrStack[255] , 1 ); Call LoadJobFile to read job file from system directory and execute and jobs listed there. LoadJobFile(); for (;;) /* Loop forEVER looking for user desires */ { /* Make a ReadKbd Key Request with KBD service. Tell it to wait for a key. */ ere = Request ( “KEYBOARD” , 1, GPExch, &GPHndl, 0, &ccode, 4, 0,0,1, 0, 0) ; if (ere) xprintf (“Kbd Svc Request KERNEL ERROR: %d\r\n”, ere) /* wait for the keycode to come back */ ere = WaitMsg (GPExch, GPMsg); if (ere) xprintf (“KERNEL Error from Wait msg: %d\r\n”, ere);

Part III M MMURTL-Specific Details Listing 11.2. continued c = ccode & 0xff ; /* lop off everything but the key value switch (c) { case 0x0F: /* F1 Run */ ere = LoadCLI() ; if (ere) xprintf( “Error from LoadCLI break; case 0x10: /* F2 Jobs */ InitScreen( ) ; l\r\n”, ere) 2; for (i=1 { if Line */ Col offset i<nMaxJCBs;

7 i++) ere = GetpJCB(i, &pJCB); if (!erc) { SetXY(k.j); xprintf (“Job: %d\r\n”, pJCB->JobNum) ; SetXY(k+10,j); CopyData(&pJCB->sbJobName[1 ] , text, 13); text[pJCB->sbJobName[0] ] = 0; xprintf (“Name: %s\r\n”, text); /* ere = 0 if valid JCB */ } } break: case 0x11 : /* F3 Stats - loops displaying status till key is hit */ InitScreen() ; while (ere = ReadKbd(&ccode1 , 0)) { /* ReadKbd no wait until no error */ SetXY(0,l); ere = QueryPages(&nMemPages) ; xprintf (“Any key to dismiss status... \r\n” ); xprintf ( “Free 4K memory pages: %d\r\n” , nMemPages) xprintf (“Task switches total: %d\r\n” , nSwitches) xprintf (“Preemptive task switches: %d\r\n” , nSlices); xprintf (“CPU idle ticks (no work): %d\r\n” , nHalts); xprintf (“Tasks Ready to Run: %d\r\n” , nReady); xprintf ( “Free Task State Segments: %d\r\n” , nTSSLeft); xprintf (“Free Job Control Blocks: %d\r\n” , nJCBLeft); xprintf (“Free Request Blocks: %d\r\n” , nRQBLeft); xprintf (“Free Link Blocks: %d\r\n” , nLBLeft) ; xprintf ( “Free Exchanges: %d\r\n” , nEXCHLeft) SetXY(0,1); PutVidChars(29, 1, “J”, 1, GREEN | BGBLACK) ; Sleep(9); PutVidChars(29, 1 “/", 1, GREENj BGBLACK); Sleep(9); PutVidChars(29, 1 “-', 1, GREEN ; BGBLACK) ; Sleep(12); PutVidChars(29, 1 “W, 1, GREEN; BGBLACK); Sleep(9); PutVidChars(29, 1 ■J’, 1, GREEN; BGBLACK); Sleep(9) ; PutVidChars(29, 1 ■/", 1, GREEN; BGBLACK); Sleep(9); PutVidChars(29, 1 ■•", 1, GREEN; BGBLACK); Sleep(l2) ;

Chapter 11 ■ The MMURTL Monitor Program |
179 PutVidChars(29, 1, “\\ 1, GREEN | BGBLACK) ; Sleep(9); PutVidChars(29, 1, " “, 1, GREEN | BGBLACK ) ; } SetXY(0,12); xprintf ("\r\n”); break; case 0x16: /* F8 Reboot */ xprintf ("\r\nF8 again to reboot, any other key to cancel”); ere = ReadKbd(&ccode1 , 1); if ((ccodel & 0xff) == 0x16) Reboot () ; xprintf ( " . . .Cancelled\r\n” ) ; break; case 0x18: /* F10 Debug */ GoDebugO ; break; case 0x00: /* No Key */ Sleep(3); /* Sleep for 30 ms */ break; case 0x12: /* F4 - future use * 1 case 0x13: /* F5 */ case 0x14: /* F6 */ case 0x15: /* F7 */ case 0x17: /* F9 */ case 0x19: /* F11 */ case 0x1A: /* F12 */ break; default: if (((c > 0x1F) && (C < 0x80)) (c= { =0x0D) !! (c==8)) if ( C==0X0D) TTYOut (CRLF, 2, white; else } 2 } TTYOut (4c, 1 , WHITE BGBLACK) ; GetXY(&iCol &iLine) ; if (iLine > i = 23) ScrollVid(0, 1,80,23,1); SetXY(0 } 22); } /* for EVER * } f

Powered by TurnKey Linux.