Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

88KB

Developing Your Own 32-Bit Operating System — Chapter-15: API Specification

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

15 API Specification

I
222 | Part III ■ MMURTL-Specific Details This section describes all operating system public calls. They are listed by functional group first; then an alphabetical list provides details for each call and possibly an example of its use. If you are going to write your own operating system, you'll find the documentation to be al- most 30 percent of the work — and it's a very important part of the entire system, I might add. An improperly or poorly described function call can cause serious agony and hair loss in a pro- grammer. Function calls provided by system services (accessed with Request and Respond interface) are described in detail in the chapters of the book that apply to that service (Chapter 14, “File System Service,” for example). Public Calls Public calls are those accessible through a call gate and can be reached from “outside” programs. They are defined as far and require a 48-bit call address. The call address consists of a selector and an offset. The selector is the call gate entry in the global descriptor table (GDT), while the offset is ignored by the 386/486 processor. The offset should be 0. The descriptor for the call gate defines the actual address called and the number of dwords of stack parameters to be passed to the operating system call. Parameters to Calls (Args) All stack parameters are described by their names. The prefixes indicate the size and type of the data that is expected. Table 15.1 lists the prefixes. Table 15.1. Size and type prefixes. Prefix Description b Byte ( 1 byte unsigned) w Word (2 bytes unsigned) d Double Word (dword — 4 bytes unsigned) d is the default when b or w is not present, ib Integer byte (1 byte signed) iw Integer word (2 bytes signed) id Integer dword (4 bytes signed) p Pointer (4 bytes — 32-bit near pointer)

Chapter 15 ■ API Specification Additional descriptive prefixes may be used to help describe the parameter. These are known as compound descriptions. Table 15.2 lists these additional prefix characters. Table 15.2. Additional prefixes. Prefix Descripti Array (of) Count (of) Size (of) Offset (into) Number (of) Examples of compound prefixes are shown in Table 15.3. Table 15.3. Compound prefixes. Prefix Description pab Pointer to an array of bytes pad Pointer to an array of double words pdcb Pointer to a dword that is a count of bytes pib Pointer to a signed (integer) byte pb Pointer to a byte cb Dword that contains a count of bytes (defaults to size d if not preceded by another size prefix) n Dword that is a number of something ppd Pointer to a pointer that points to a double word Descriptive suffixes may also be used to help describe some parameters. Ret means Returned, Max means Maximum, and Min means Minimum. Each compound set of prefixes — and optionally, suffixes — accurately describes the provided or expected data types. Combine these prefixes with variable or parameter names and you have a complete description of the data. The following are examples of parameter names using pre- fixes and suffixes. dcbFileName — Dword that contains the count of bytes of a filename pdDataRet — Pointer to a dword where data is returned dcbDataRetMax — Dword with the maximum count of bytes that can, or should be, returned

H Part III M MMURTL-Specific Details Stack Conventions MMURTL keeps a dword (4 bytes) aligned stack. It is processor (hardware) enforced. Bytes and words (8- or 1 6-bit values) are pushed as dwords automatically. The caller need not worry about whether the upper pan of a dword on the stack is cleared or set when a value is pushed, because MMURTL will only use as much of it as is defined by the call. If a parameter is a byte, MMURTL procedures will only get the byte from the stack, while the upper three bytes of the dword are ignored. MMURTL high-level languages follow this convention. This information is provided for the assembly language programmers. Calls Grouped by Functionality The following is a list of all currently implemented operating system public calls, grouped by type. The parameter (argument) names follow the naming convention described earlier in this chapter. Many of these calls will not be used by the applications programmer. The operating-system calls are described in a generic fashion that does not directly correspond to a particular programming language such as C, Pascal, or Assembler. The function name is followed by the parameters, and finally, if a value is returned by the function, a colon with the returned value. The dError, the most common returned value shown, indicates a dword error or status code is returned from the function. Messaging AllocExch(pdExchRet) : dError DeAllocExch(dExch) : dError SendMsg (dExch, dMsgl , dMsg2): dError CheckMsg(dExch, pMsgsRet): dError ISendMsg (dExch, dMsgl, dMsg2): dError WaitMsg(dExch,pqMsgRet) : dError Request (pSvcName, wSvcCode, dRespExch, pRqHndlRet, npSend, pDatal , cbDatal , pData2, cbData2, dData0, dDatal , dData2 ) : dError MoveRequest(dRqBlkHndl, dDestExch): dError Respond(dRqHndl, dStatRet) : dError Job Management Chain (pFileName, dcbFileName, dExitError): dError ExitJob(dExitError) : dError LoadNewJob(pFileName, dcbFileName, pdJobNumRet) : dError GetpJCB(dJobNum, pJCBRet): dError

Chapter 15 ■ API Specific B GetJobNum(pdJobNumRet) : dError SetJobName(pJobName, dcbJobName): dError SetExitJob(pFileName, dcbFileName) : dError GetExitJob(pFileNameRet, pcbFileNameRet) : dError SetCmdl_ine(pCmdLine, dcbCmdLine) : dError GetCmdLine(pCmdLineRet, pdcbCmdLineRet) : dError SetPath(pPath, dcbPath): dError GetPath(dJobNum, pPathRet, pdcbPathRet) : dError SetUserName(pUserName, dcbUserName) : dError GetUserName(pUserNameRet, pdcbUserNameRet) : dError SetSysIn(pFileName, dcbFileName): dError GetSysIn(pFileNameRet, pdcbFileNameRet) : dError SetSysOut(pFileName, dcbFileName): dError GetSysOut(pFileNameRet, pdcbFileNameRet): dError Task Management NewTask(dJobNum, wCodeSeg, dPriority, dfDebug, dExch, dESP, dEIP): dError SpawnTask(pEntry, dPriority, fDebug, pStack, fOSCode) :dError SetPriority(bPriority) : dError GetTSSExch(pdExchRet) : dError System Service and Device Driver Management DeviceOp(dDevice, dOpNum, dLBA, dnBlocks, pData) : dError DeviceStat(dDevice, pStatRet, dStatusMax, dStatusRet) :dError DeviceInit(dDevice, plnitData, dlnitData): dError InitDevDr(dDevNum, pDCBs, nDevices, fReplace) : dError RegisterSvc(pSvcName, dExch): dError UnRegisterSvc(pSvcName) : dError Memory Management AllocPage(nPages, ppMemRet): dError AllocDMAPage(nPages, ppMemRet, pdPhyMemRet) : dError AllocOSPage(nPages, ppMemRet): dError DeAllocPage(pMem, dnPages): dError AliasMem(pMem, dcbMem, dJobNum, ppAliasRet): dError

I
226 Part III M MMURTL-Specific Details DeAliasMem(pAliasMem, dcbAliasBytes, JobNum) : dError GetPhyAdd(dJobNum, LinAdd, pPhyAddRet): dError QueryPages(pdnPagesRet) : dError High-Speed Data Movement FillData(pDest, cBytes, bFill) CompareNCS(pS1 , pS2, dSize): returned offset or -1 Compare(pS1, pS2, dSize) : returned offset or -1 CopyData(pSource, pDestination, dBytes) CopyDataR(pSource, pDestination, dBytes) Timer and Timb Alarm(dExchRet, dTicks): dError KillAlarm (dAlarmExch) : dError Sleep(nTicks) : dError MicroDelay (dn15us): dError GetCMOSTime(pdTimeRet) : dError GetCMOSDate(pdDateRet) : dError GetTimerTick(pdTickRet) : dError ISA Hardware Specific I/O DmaSetUp(dPhyMem, sdMem, dChannel, fdRead, dMode) : dError GetDMACount(dChannel, pwCountRet): dError InByte(dPort) : Byte InWord(dPort): Word InDWord(dPort) : DWord InWords(dPort, pDataln, dBytes) OutByte(Byte, dPort) OutWord(Word,dPort) OutDWord (DWord, dPort) OutWords(dPort, pDataOut, dBytes) ReadCMOS(bAddress) :Byte Interrupt and Call Gate Management AddCallGate: dError AddlDTGate: dError

Chapter 15 ■ API Specific SetIRQVector(dIRQnum, pVector) GetlRQVector (dlRQnum, pVectorRet) : dError MasklRQ (dlRQnum): dError UnMasklQR (dlRQnum): dError EndOflRQ (dlRQnum) Keyboard, Speaker, and Video SetVidOwner(dJobNum) : dError GetVidOwner(pdJobNumRet) : dError GetNormVid(pdNormVidRet) : dError SetNormVid(dNormVidAttr) : dError Beep(): dError ClrScr(): dError GetXY(pdXRet, pdYRet): dError SetXY(dNewX, dNewY): dError PutVidChars(dCol, dLine, pbChars, nChars, dAttrib) : dError GetVidChar(dCol, ddLine, pbCharRet, pbAttrRet): dError PutVidAttrs(dCol, dLine, nChars, dAttr) : dError ScrollVid(dULCol, dULline, nCols, nLines, dfUp) : dError ReadKbd (pdKeyCodeRet, dfWait): dError Tone(dHz, dTicks10ms): dError TTYOut (pTextOut, dTextOut, dAttrib): dError EditLine( pStr, dCrntLen, dMaxLen, pdLenRet, pbExitChar, dEditAttr): dError Alphabetical Call Listing The remaining sections of this chapter describe each of the operating system calls available to programmers. AddCallGate AddCallGate: dError AddCallGate () makes an entry in the global descriptor table (GDT) for a publicly available operating-system function. AddCallGate ( ) is primarily for operating system use, but can be used by experienced systems programmers.

I 228 I Part III ■ MMURTL-Specific Details This call doesn't check to see if the GDT descriptor for the call is already defined. It assumes you know what you are doing and overwrites the descriptor if it is already there. The selector number is checked to make sure you're in range (40h through the maximum call gate num- ber). Unlike most other operating system calls, the parameters are not stack-based. They are passed in registers. AddCallGate ( ) can only be executed by code running at supervisor level (0). Parameters: AX — Word with call gate ID type as follows: DPL entry of 3 ECOx (most likely) DPLentryof2CC0x DPL entry of 1 ACOx DPL entry of 0 8C0x (x = count of dword parameters 0-F) CX — Selector number for call gate in GDT (these are constants) ESI — Offset of entry point in segment of code to execute EAX — Returns an error, or 0 if all went well. AddlDTGate AddlDTGate: dError AddlDTGate ( ) makes an entry in the Interrupt Descriptor Table for traps, exceptions, and in- terrupts. AddlDTGate ( ) is primarily for operating system use, but can be used by experienced systems programmers. AddlDTGate ( ) builds and adds an IDT entry for trap gates, exception gates and interrupt gates. This call doesn't check to see if the IDT descriptor for the call is already defined. It assumes you know what you are doing and overwrites the descriptor if already defined. Unlike most other operating system calls, the parameters are not stack based. They are passed in registers. AddlDTGate ( ) can only be executed by code running at supervisor level (0). The selector of the call is always 8 (operating-system code segment) for interrupt or trap, and is the TSS descriptor number of the task for a task gate. Parameters: AX — Word with Gate ID type as follows: Trap Gate with DPL of 3 8F00h Interrupt Gate with DPL of 3 8E00h Task Gate with DPL of 3 8500h

Chapter 15 ■ API Specification [229 BX — Selector of gate (08 or TSS selector for task gates) CX — Word with Interrupt Number (00-FF) ESI — Offset of entry point in operating system code to execute. This must be zero (0) for task gates. EAX — Returns Error, else 0 if all went OK Alarm Alarm (dExchRet, dnTicks): dError Alarm( ) is a public routine that will send a message to an exchange after a specified period of 10-millisecond increments has elapsed. Alarm ( ) can be used for a number of things. One im- portant use would be a time-out function for device drivers that wait for interrupts but may never get them due to hardware difficulties. Alarm ( ) is similar to Sleep ( ) , except it can be used asynchronously. This means you can set an alarm, do some other processing, and then “CheckMsg ( ) " on the exchange to see if it has gone off. In fact, you can set it to send a message to the same exchange where you are expecting another message, then see which one gets there first by simply waiting at the exchange. This would be for the time-out function described above. Alarm ( ) should not be called for extremely critical timing in applications. The overhead in- cluded in entry, exit and messaging code makes the alarm delay timing a little more than 1 0 milliseconds and is not precisely calculable, even though it's very close. The larger dnTicks is, the more precise the timing. Alarm ( ) is accomplished using the same timer blocks as Sleep ( ), except you provide the exchange, and don't get placed in a waiting condition. The message that is sent is two dwords, each containing OFFFFFFFF hex (-1). Parameters: dnTicks — Dword with the number of 10-millisecond periods to wait before sending a message the specified exchange AliasMem AliasMem (pMem, dcbMem, dJobNum, ppAliasRet): dError AliasMem ( ) provides an address conversion between application addresses. Each application has its own linear address space. Even addresses of identical numeric values are not the same ad- dresses when shared between applications. This procedure is used by the operating system to perform address conversions when passing data using the Request ( ) and Respond ( ) primitives. Parameters: pMem — Pointer to the memory address from the other application's space that needs to be aliased

Part III ■ MMURTL-Specific Details dcbMem — The count of bytes pMem is pointing to. You must not attempt to access more than this number of bytes from the other application's space. If you do, you will cause a fault and your application will be terminated. dJobNum — Job number from the other application ppAliasRet — Pointer to the pointer you want to use to access the other application's memory. (The address of the aliased memory pointer you will use). AllocDMAPage AllocDMAPage(nPages, ppMemRet, pdPhyMemRet) : dError AllocDMAPage () allocates one or more pages of memory and adds the entry(s) to the caller's page tables. Memory is guaranteed to be contiguous and will be within reach of the DMA- hardware. It will always begin on a page boundary. No cleanup is done on the caller's memory space. If the caller continuously allocates pages and then deallocates them, this could lead to fragmentation of the linear memory space. The allocation routine uses a first-fit algorithm. Parameters: n Pages — Dword (4 bytes). This is the count of 4K pages to allocate. ppRet — Pointer to 4-byte area where the pointer to the memory is returned pdPhyMemRet — A pointer to 4-byte area where the physical address of the memory is returned. This pointer is only valid when used with the DMA hardware. Using it as a normal pointer will surely cause horrible results. AllocExch AllocExch(pdExchRet) : dError The kernel Allocate Exchange primitive. This procedure allocates an exchange (message port) for the job to use. Exchanges are required in order to use the operating system messaging sys- tem (SendMsg, WaitMsg, and so on). Parameters: pdExchRet — Pointer to the dword where the exchange number is returned AllocOSPage AllocOSPage(nPages, ppMemRet): dError Allocate operating system page allocates one or more pages of memory and adds the entry to the operating system page tables. Memory is guaranteed to be contiguous and to always begin on a page boundary. No cleanup is done on the caller's memory space. If the caller continuously allocates pages and then deallocates them this could lead to fragmentation of the linear memory space. The allocation routine uses a first-fit algorithm.

Chapter 15 ■ API Specification Parameters: nPages — A dword (4-bytes). This is the count of 4K pages to allocate. ppRet — A pointer to 4-byte area where the pointer to the memory is returned. AllocPage AllocPage(nPages, ppMemRet): dError Allocate page allocates one or more pages of memory and adds the entry to the caller's page tables in upper linear memory. Memory is guaranteed to be contiguous and will always begin on a page boundary. No cleanup is done on the caller's memory space. If the caller continu- ously allocates pages and then deallocates them this could lead to fragmentation of the linear memory space. The allocation routine uses a first-fit algorithm. Parameters: n Pages — A dword (4 bytes). This is the count of 4K pages to allocate. ppRet — A pointer to 4-byte area where the pointer to the memory is returned. H Beep Beep: dError This is a public routine that sounds a 250-millisecond tone at 800Hz. Parameters: None Chain Chain (pFileName, dcbFileName, dExitError): dError Chain ( ) is called by applications and services to replace themselves with another application (as specified by the filename). Chain ( ) terminates all tasks belonging to the calling job and frees system resources that will not be used in the new job. If chain cannot open the new job or the new run file is corrupted, ErcBadRunFile, or similar errors, may be returned to the application and the chain operation will be canceled. If the chain is too far along, and running the new application fails, the Exit Job, if the JCB contained a valid one, will be loaded and run. If there is not an exit job specified, the job will be terminated as described in the ExitJob( ) call. Parameters: pFilename — This points to the name of a valid executable run file. dcbRunFilename — A dword containing the length of the run file name. dExitError — A dword containing an error code to place in the Error-Exit field of the JCB. The chained application may or may not use this error value.

I
232 Part III ■ MMURTI-Specific Details CheckMsg CheckMsg(dExch, pMsgsRet) : dError The kernel CheckMsg ( ) primitive allows a task to receive information from another task with- out blocking the caller. In other words, if no message is available, CheckMsg ( ) returns with an error to the caller. If a message is available, the message is returned to the caller immediately. The caller is never placed on an exchange and the Task Ready queue is not evaluated. This call is used to check for non-specific messages and responses from services. The first dword's value (dMsgHi) determines if it's a non-specific message or a response from a service. If the value is less than 80000000h (a positive-signed long integer in C) it is a response from a service, otherwise it is a non-specific message that was sent to this exchange by SendMsg ( ) or ISendMsg ( ) . If it was a response from a service, the second dword is the status code from the The value of the first dword is an agreed-upon convention. If you allocate an exchange that is only used for messaging between two of your own tasks within the same job, then the two dwords of the message can represent any two values you like, including pointers to your own memory area. If you intend to use the exchange for both mes- sages and responses to requests, you should use the numbering convention. The operating system follows this convention with the Alarm ( ) function by sending OFFFFFFFFh as the first and second dwords of the message. Parameters: dExch — The exchange to check for a waiting message. pMsgsRet — A pointer to two dwords in contiguous memory where the two dword messages should be returned if a message is waiting at this exchange. dError — Returns 0 if a message was waiting, and has been placed in qMsg, else ErcNoMsg is returned. ClrScr ClrScr() This clears the virtual screen for the current job. It may or may not be the one you are viewing (active screen). Parameters: None

Chapter 15 ■ API Specification Compare Compare(pS1 , pS2, dSize) : returned offset or -1 This is a high-speed string compare function using the Intel string instructions. This version is ASCII case sensitive. It returns the offset of the first byte that doesn't match between the pSl and pS2, or it returns -1 (OxFFFFFFFF) if all bytes match out to dSize. pSl and pS2 — Pointers to the data strings to compare. dSize — Number of bytes to compare in pSl and pS2. |
233 | CompareNCS CompareNCS(pS1 , pS2, dSize) : returned offset or -1 This is a high-speed string compare function using the Intel string instructions. This version is not case sensitive (NCS). It returns the offset of the first byte that doesn't match between the pS1 and pS2, or it returns -1 (OxFFFFFFFF) if all bytes match (ignoring case) out to dSize. Parameters: pSl and pS2 — Pointers to the data strings to compare. dSize — Number of bytes to compare in pSl and pS2. CopyData CopyData(pSource, pDestination, dBytes) This is a high-speed string move function using the Intel string move intrinsic instructions. Data is always moved as dwords if possible. Parameters: pSource — Pointer to the data you want moved. pDestination — Pointer to where you want the data moved. dBytes — Count of bytes to move. CopyDataR CopyDataR(pSource, pDestination, dBytes) This is a high-speed string move function using the Intel string move intrinsic instructions. This version should be called if the pSource and pDest address overlap. This moves the data from the highest address down so as not to overwrite pSource. Parameters: pSource — Pointer to the data you want moved.

H Part III M MMURTL-Specific Details pDestination — Pointer to where you want the data moved. dBytes — Count of bytes to move. DeAliasMem DeAliasMem(pAliasMem, dcbAliasBytes, dJobNum): dError This invalidates the an aliased pointer that you created using the AliasMem( ) call. This frees up pages in your linear address space. You should use this call for each aliased pointer when you no longer need them. Parameters: pAliasMem — The linear address you want to dealias. This should be the same value that was returned to you in the AliasMem( ) call. dcbAliasBytes — Size of the memory area to dealias. This must be the same value you used when you made the AliasMem( ) call. dJobNum — This is the job number of the application whose memory you had aliased. This should be the same job number you provided for the AliasMem( ) call. DeAllocExch DeAllocExch(dExch) : dError Deallocate exchange releases the exchange back to the operating system for reuse. If tasks or messages are waiting at the exchange they are released and returned as reusable system resources. Parameters: dExch — The exchange number that is being released. DeAllocPage DeAllocPage(pMem, dnPages) : dError Deallocate page deletes the memory from the job's page table. This call works for any memory, OS and DMA included. Access to this memory after this call will cause a page fault and termi- nate the job. Parameters: pMem — Pointer which should contain a valid memory address, rounded to a page boundary, for previously allocated pages of memory. dnPages — Dword with the count of pages to deallocate. If dnPages is greater than the existing span of pages allocated at this address, an error is returned, but as many pages as can be, willbe deallocated. If fewer pages are specified, only that number will be deallocated.

Chapter 15 ■ API Specification Devicelnit DeviceInit(dDevice, plnitData, dlnitData) : dError Some devices may require a call to initialize them before use, or to reset them after a catastro- phe. An example of initialization would be a comms port, for baud rate, parity, and so on. The size of the initializing data and its contents are device-specific and are defined with the docu- mentation for the specific device driver. Parameters: dDevice — Dword indicating device number. plnitData — Pointer to device-specific data for initialization. This is documented for each device driver. dlnitData — Total number of bytes in the initialization data. H DeviceOp DeviceOp(dDevice, dOpNum, dLBA, dnBlocks, pData): dError The DeviceOp ( ) function is used by services and programs to carry out normal operations such as Read and Write on all installed devices. The dOpNum parameter tells the driver which opera- tion is to be performed. The first 256 operation numbers, out of over 4 billion, are pre-defined or reserved. These reserved numbers correspond to standard device operations such as read, write, verify, and format. Each device driver documents all device operation numbers it sup- ports. All drivers must support dOpNum 0 (Null operation). It is used to verify the driver is installed. Most drivers will implement dOpNums 2 and 3 (Read and Write). Disk devices (DASD — Direct Access Storage Devices) will usually implement the first eight or more. Parameters: dDevice — The device number. dOpNum — Identifies which operation to perform 0 Null operation. 1 Read (receive data from the device) 2 Write (send data to the device) 3 Verify (compare data on the device) 4 Format Block 5 Format Track (disk devices only) 6 Seek Block 7 Seek Track (disk devices only) 8-255 RESERVED 256- n Driver Defined (driver specific)

236| Part III ■ MMURTI-Specific Details dLBA — Logical Block Address for I/O operation. For sequential devices, this parameter will usually be ignored. See the specific device driver documentation. dnBlocks — Number of contiguous blocks for the operation specified. For sequential devices, this will probably be the number of bytes (comms, for example). Block size is defined by the driver. Standard block size for disk devices is 5 1 2 bytes. pData — Pointer to data, or return buffer for reads, for specified operation. DeviceStat DeviceStat(dDevice, pStatRet, dStatusMax, dStatusRet) rdError The DeviceStat ( ) function returns device-specific status to the caller if needed. Not all devices will return status on demand. In cases where the driver doesn't, or can't, return status, ErcNoStatus will be returned. The status information will be in record or structure format that is defined by the specific device driver documentation. Parameters: dDevice — Device number to status. pStatBuf — Pointer to buffer where status will be returned. dStatusMax — This is the maximum number of bytes of status you will accept. pdStatusRet — Pointer to dword where the number of bytes of status returned to is reported. DMASetUp DMASetUp(dPhyMem, sdMem, dChannel, fdRead, dMode) : dError This is a routine used by device drivers to set up a DMA channel for a device Read or Write. Typical use would be for a disk or comms device, in which the driver would setup DMA for the move, then setup the device, which controls DMA through the DREQ/DACK lines, to actually control the data move. Parameters: dPhyMem — Physical memory address. Device drivers can call the GetPhyAdd( ) routine to convert linear addresses to physical memory addresses. sdMem — Number of bytes to move. dChannel — Legal values are 0, 1,2, 3, 5, 6, and 7. Channels 5, 6, and 7 are for 16-bit devices, and though they move words, you must specify the length in bytes using sdMem. fdRead — Any non-zero value sets DMA to read (Read is a read from memory which sends data ton device).

Chapter 15 ■ API Specification dMode — 0 is Demand mode, 1 is Single Cycle mode (disk I/O uses single cycle), 2 is Block mode, and 3 is Cascade mode, which is for operating system use only. EditLine EditLine( pStr, dCrntLen, dMaxLen, pdLenRet, pbExitChar, dEditAttr): dError This function displays a single line of text and allows it to be edited on screen. Display and keyboard input are handled inside of EditLine ( ). The line must be on a single row of the dis- play with no character wrap across lines. The first character of the line is displayed at the cur- rent X and Y cursor coordinates for the caller's video screen. Parameters: pStr — Pointer to the character string to be edited. dCrntLen — Current length of the string. The maximum is 80. dMaxlen — Maximum length of the string. The maximum is 80. pdLenRet — Pointer to a dword where the length of the string after editing will be returned. pbExitCharRet — Pointer to a byte where the exit key from the edit operation is returned. dEditAttr — Editing attribute. The display and keyboard are handled entirely inside EditLine ( ) . The following keys are rec- ognized and handled internally for editing features. Any other key causes EditLine ( ) to exit, and return the contents and length of the string in its current condition. 08 (Backspace) — Move cursor to left, replacing char with 20h, which is a destructive backspace. Left-Arrow — Same as Backspace (destructive) 20-7E Hex — Places character in current position and advances position. Special shift keys combination (Ctrl and Alt) are not interpreted (Ctrl-D = D, and so on). EndOflRQ EndOflRQ (dIRQnum) This call is made by an interrupt service routine to signify it has completed servicing the inter- rupt. End of Interrupt commands are sent to the proper PICU(s) for the caller. Parameter: dIRQnum — The hardware interrupt request number for the IRQ that your ISR has finished serving. For a description of hardware IRQs, see the call description for SetIRQVector(). H

I
238 Part III ■ MMURTL-Specific Details Exitjob ExilJob(dExitError) : dError Exit Job ( ) is called by applications and by services to terminate all tasks belonging to the job, and to free system resources. This is the usual method to terminate your application program. A high-level language's exit function would call Exit Job ( ). After freeing certain resources for the job, Exit Job ( ) attempts to load the Exit Job run file as specified in the SetExitJob( ) call. It is kept in the JCB. Applications can exit, and replace them- selves with another program of their choosing, by calling SetExitJob ( ) , and specifying the Run filename, before calling ExitJob ( ) . A command line interpreter, or executive, which runs your program from a command line, would normally call SetExitJob ( ), specifying itself so it will run again when your program is finished. If no ExitJob is specified, ExitJob() errors out with ErcNoExitJob and frees up all resources that were associated with that job, including, but not limited to, the JCB, TSSs, exchanges, link blocks, and communications channels. If this happens while video and keyboard are as- signed to this job, the video and keyboard are reassigned to the OS Monitor program. Parameters: dExitError — This is a dword that indicates the completion state of the application. The operating system does not interpret, or act on this value, in any way except to place it in the Job Control Block. FillData FillData(pDest, cBytes, bFill) This is used to fill a block of memory with a repetitive byte value such as zeroing a block of memory. This uses the Intel string intrinsic instructions. Parameters: pDest — A pointer to the block of memory to fill. cBytes — The size of the block. bFill — The byte value to fill it with. GetCmdLine GetCmdLine(pCmdLineRet , pdcbCmdLineRet) : dError Each Job Control Block has a field to store the command line that was set by the previous application or command line interpreter. This field is not directly used or interpreted by the operating system. This call retrieves the command line from the JCB. The complimentary call,

Chapter 15 ■ API Specification SetCmdLine( ), is provided to set the command line. The CmdLine is preserved across ExitJobs, and while chaining to another application. High-level language libraries may use this call to retrieve the command line and separate or expand parameters (arguments) for the applications main function. Parameters: pabCmdLineRet — Pointer to an array of bytes where the command line string will be returned. This array must be large enough to hold the largest CmdLine, which is 79 characters. pdcbCmdLineRet — A pointer to a dword where the length of the command line returned will be stored. GetCMOSTime GetCMOSTime(pdTimeRet) : dError This retrieves the time from the on-board CMOS battery backed up clock. The time is re- turned from the CMOS clock as a dword defined as: Low order byte is the seconds (BCD), Next byte is the minutes (BCD), Next byte is the hours (BCD 24 hour), High order byte is 0. Parameters: pdTimeRet — A pointer to a dword where the time is returned in the previously described format. GetCMOSDate GetCMOSDate(pdDateRet): dError This retrieves the date from the on-board CMOS battery backed up clock. The date is returned from the CMOS clock as a dword defined as: Low order byte is the Day of Week (BCD 0-6 0=Sunday), Next byte is the Day (BCD 1-31), Next byte is the Month (BCD 1-12), High order byte is Year (BCD 0-99). Parameters: pdTimeRet — A pointer to a dword where the date is returned in the previously de- scribed format.

I
240 Part III ■ MMURTL-Specific Details GetDMACount GetDMACount (dChannel, pwCountRet): dError A routine used by device drivers to get the count of bytes for 8-bit channels, or words for 16-bit DMA channels, left in the Count register for a specific DMA channel. Parameters: dChannel — Legal values are 0, 1, 2, 3, 5, 6, and 7. Channels 5, 6, and 7 are for 16-bit devices. pwCountRet — This is the value found in the DMA count register for the channel specified. Note that even though you specify bytes on 16-bit DMA channel to the DMASetUp( ) call, the count returned is always the exact value found in the count register for that channel. The values in the DMA count registers are always pro- grammed with one less than the count of the data to move. Zero (0) indicates one word or byte, 15 indicates 16 words or bytes. If you program a 16-bit DMA channel to move data from a device for 1024 words (2048 bytes) and you call GetDMACount ( ) , which returns 1 to you, this means all but two words were moved. GetExitfob GetExitJob(pabExitJobRet, pdcbExitJobRet) : dError Each Job Control Block has a field to store the ExitJob filename. This field is used by the op- erating system when an application exits, to see if there is another application to load in the context of this job (JCB). Applications may use this call to get the ExitJob filename. The com- plimentary call, SetExitJob(), is provided. The ExitJob remains set until it is reset. Calling SetExitJob( ) with a zero length value clears the exit job file name from the JCB. Parameters: pabExitJobRet — Points to an array of bytes where the ExitJob filename string will be returned. This array must be large enough to hold the largest ExitJob filename of 79 characters. pdcbExitJobRet — A pointer to a dword where the length of the ExitJob filename returned will be stored. GetlRQVector GetlRQVector (dIRQnum, pVectorRet): dError The get interrupt vector call returns the 32-bit offset address in operating system address space for the ISR that is currently serving dIRQnum.

Chapter 15 ■ API Specification Parameters: dlRQnum — The hardware interrupt request number for the vector you want returned. For a description oflRQs, see the call description for SetIRQVector( ). pVectorRet — A pointer where the address of the ISR will be returned. GetJobNum GetJobNum(pdJobNumRet) :dError This returns the job number for the task that called it. All tasks belong to a job. Parameters: pbJobNumRet — A pointer to a dword where the job number is returned. GetNormVid GetNormVid(pdNormVidAttrRet) : dError Each job is assigned a video screen, virtual or real. The normal video attributes used to display characters on the screen can be different for each job. The default foreground color, which is the color of the characters themselves, and background colors, may be changed by an applica- tion. The normal video attributes are used with the ClrScr( ) call, and are also used by stream output from high level language libraries. This returns the normal video attribute for the screen of the caller. See SetNormVid( ) for more information. Parameters: pdNormVidAttrRet — This points to a dword where the value of the normal video attribute will be returned. The attribute value is always a byte, but is returned as a dword for this, and some other operating system video calls. See Chapter 9, “Application Programming,” for a table containing values for video attributes. GetPath 6etPath(dJobNum, pPathRet, pdcbPathRet) : dError Each Job Control Block has a field to store an application's current path. The path is inter- preted and used by the file system. Refer to file system documentation. This call allows appli- cations and the file system to retrieve the current path string. Parameters: dJobNum-This is the job number for the path string you want. pPathRet —This points to an array of bytes where the path will be returned. This string must be long enough to contain the longest path of 69 characters. H

242 Part III M MMURTL-Specific Details pdcbPathRet — This points to a dword where the length of the path name returned is stored. GetPhyAdd GetPhyAdd(dJobNum, dLinAdd, pdPhyRet): dError This returns a physical address for the given linear address. It is used by device drivers for DMA operations on DSeg memory. Parameters: dJobNum — The job number of owner of dLinAdd. dLinAdd — The linear address you want the physical address for. This is the address itself, not a pointer to it. pdPhyRet — Points to the dword where the physical address is returned. GetplCB GetpJCB(dJobNum, ppJCBRet): dError This returns a pointer to the Job Control Block for the specified job number. Each job has a structure to control and track present job resources and attributes. The data in a JCB is read- only to applications and system services. Parameters: dJobNum — This is the job number for the Job Control Block you want a pointer to. ppJCBRet — This is a pointer that points to a pointer where the pJCB will be returned. GetSysIn GetSysIn(pFileNameRet, pdcbFileNameRet) : dError This returns the name of the standard output file, or device, from the application's Job Con- trol Block. Parameters: pFileNameRet — Pointer to an array where the name will be returned. This array must be at least 30 characters long. pdcbFileNameRet — Pointer to a dword where the length of the name will be returned.

Chapter 15 ■ API Specification GetSysOut GetSysOut(pFileNameRet, pdcbFileNameRet) : dError This returns the name of the standard output file or device from the application's Job Control Block. Parameter: pFileNameRet — Pointer to an array where the name will be returned. This array must be at least 30 characters long. pdcbFileNameRet — Pointer to a dword where the length of the name will be returned. GetTimerTick GetTimerTick( pdTickRet) : dError This returns the operating system tick counter value. When MMURTL is booted, it begins counting 10-millisecond intervals forever. This value wili roll over every 16 months or so. It is an unsigned dword. Parameter: pdTickRet — A pointer to a dword where the current tick is returned. H GetTSSExch GetTSSExch(pdExchRet) : dError This returns the exchange that belongs to the task as assigned by the operating system during SpawnTask ( ) or NewTask ( ) . This exchange is used by some direct calls, while blocking a thread on entry to non-reentrant portions of the operating system. It can also be used by system ser- vices or library code as an exchange for the request primitive for that task, as long as no timer functions will be used, such as Alarm ( ) or Sleep ( ) . Parameter: pdExchRet — A pointer to a dword where the TSS exchange will be returned. GetUserName GetUserName(pUserNameRet, pdcbUserNameRet) : dError The Job Control Block for an application has a field to store the current user's name of an application. This field is not directly used or interpreted by the operating system. This call retrieves the user name from the JCB. The complimentary call SetUserName( ) is provided to set the user name. The name is preserved across ExitJobs, and while chaining to another application.

I
244 Part III ■ MMURTL-Specific Details Parameters: pabUsernameRet — Points to an array of bytes where the user name will be returned. dcbUsername — The length of the string to store. GetVidChar GetVidChar(dCol, ddLine, pbCharRet, pbAttrRet): dError This returns a single character and its attribute byte from the caller's video screen. Parameters: dCol — The column location, or X position, of the character you want returned. dLine — The line location, or Y position, of the character you want returned. pbCharRet — Pointer to a byte where the character value will be returned. pbAttrRet — Pointer to a byte where the video attribute for the character is returned. GeMdOwner GetVidOwner(pdJobNumRet) : dError This returns the job number for the owner of the real video screen, the one you are viewing. Parameter: pdJobNumRet — Pointer to a dword where the current video owner will be returned. GetXY GetXY(pdXRet, pdYRet): dError This returns the current X and Y position of the cursor in your virtual video screen. Parameters: pdXRet — A pointer to where you want the current horizontal cursor position returned. pdYRet — A pointer to where you want the current vertical cursor position returned. InByte InByte(dPort) : Byte This reads a single byte from a port address, and returns it from the function. Parameter: dPort — The address of the port.

Chapter 15 ■ API Specification I 245 InDWord InDWord(dPort) : DWord This reads a single dword from a port address, and returns it from the function. Parameter: dPort — The address of the port. InWord InWord(dPort) : Word This reads a single word from a port address, and returns it from the function. Parameter: dPort — The address of the port. InWords InWords(dPort, pDataln, dBytes) InWords reads one or more words from a port using the Intel string read function. The data is read from dPort and returned to the address pDataln. dBytes is the total count of bytes to read (words X 2). This call is specifically designed for device drivers. Parameters: dPort — The address of the port. pDataln — The address where the data string will be returned. dBytes — The total number of bytes to be read. This number is the number of words you want to read from the port times two. InitDevDr InitDevDr(dDevNum, pDCBs, nDevices, fReplace) : dError InitDevDr ( ) is called from a device driver after it is first loaded, to let the operating system integrate it into the system. After the device driver has been loaded, it should allocate all sys- tem resources it needs to operate and control its devices, while providing the three standard entry points. A 64-byte DCB must be filled out for each device the driver controls before this call is made. When a driver controls more than one device, it must provide the device control blocks for each device. The DBCs must be contiguous in memory. If the driver is flagged as not re- entrant, then all devices controlled by the driver will be locked out when the driver is busy.

246 | Part III ■ MMURTL-Specific Details This is because one controller, such as a disk or SCSI controller, usually handles multiple de- vices through a single set of hardware ports, and one DMA channel if applicable, and can't handle more than one active transfer at a time. If this is not the case, and the driver can handle two devices simultaneously at different hardware ports, then it may be advantageous to make it two separate drivers. See Chapter 10, “Systems Programming,” for more detailed information on writing device drivers. Parameters: dDevNum — This is the device number that the driver is controlling. If the driver controls more than one device, this is the first number of the devices. This means the devices are numbered consecutively. pDCBs — This is a pointer to the DCB for the device. If more than one device is controlled, this is the pointer to the first in an array of DCBs for the devices. This means the second DCB would be located at pDCBs + 64, the third at pDCBs + 128, and so on. nDevices — This is the number of devices that the driver controls. It must equal the number of contiguous DCBs that the driver has filled out before the lnitDevDr( ) call is made. f Replace — If true, the driver will be substituted for the existing driver functions already in place. This does not mean that the existing driver will be replaced in memory, it only means the new driver will be called when the device is accessed. A driver must specify and control at least as many devices as the original driver handled. ISendMsg ISendMsg (dExch, dMsgHi, dMsgLo): dError This is the Interrupt Send primitive. It provides access to the operating system to allow an in- terrupt procedure to send information to another task via an exchange. This is the same as SendMsg( ) except no task switch is performed and interrupts remain cleared. If a task is waiting at the exchange, the message is associated with that task and it is moved to the Ready Queue. It will get a chance to run the next time the RdyQ is evaluated by the kernel. Interrupt tasks can use ISendMsg ( ) to send single or multiple messages to exchanges during their execution. Interrupts are cleared on entry in ISendMsg ( ) and will not be set on exit! It is the responsibility of the caller to set them if desired. This procedure should only be used by device drivers and interrupt service routines.

Chapter 15 ■ API Specification The message is two double words that must be pushed onto the stack independently. When WaitMsg( ), or CheckMsg( ), returns these to your intended receiver, it will be into an array of dwords, unsigned long msg [ 2 ] in C. dMsgLo will be in the lowest array index (msg [ 0 ] ), and dMsgHi will be in the highest memory address (msg[ 1 ]). Parameters: dExch — A dword (4 bytes) containing the exchange to where the message should be sent. dMsgHi — The upper dword of the message. dMsgLo — The lower dword of the message. KillAlarm KillAlarm (dAlarmExch) : dError A public routine that kills an alarm message that was set to be sent to an exchange by the Alarm ( ) operating-system function. All alarms set to fire off to the exchange you specify are killed. For instance, if you used the Alarm ( ) function to send a message to you in three seconds so you could time-out on a piece of hardware, and you didn't need it anymore, you would call KillAlarm ( ). If the alarm is already queued through the kernel, nothing will stop it, and you should expect the Alarm ( ) message at the exchange. Parameter: dAlarmExch — The exchange you specified in a previous Alarm ( ) operating system call. LoadNewjob LoadNewJob(pFileName, dcbFileName, pdJobNumRet) : dError This loads and executes a run file. This allocates all the system resources required for the new job including a Job Control Block, page descriptor, initial Task State Segment, virtual video, and the memory required to run code, stack, and data pages. Parameters: pFilename — Pointer to the filename to run. dcbFileName — Length of the run filename. pdJobNumRet — Pointer to a dword where the new job number will be returned.

248 | Part III ■ MMURTI-Specific Details MasklRQ MasklRQ (dIRQnum) : dError This masks the hardware Interrupt Request specified by dIRQnum. When an IRQ is masked in hardware, the CPU will not be interrupted by the particular piece of hardware even if inter- rupts are enabled. Parameter: dIRQnum — The hardware interrupt request number for the IRQ you want to mask. For a description of IRQs, see the call description for SetlRQVector( ). MicroDelay MicroDelay(dn15us) : dError MicroDelay is used for very small, precise, delays that may be required when interfacing with device hardware. It will delay further execution of your task by the number of 1 5-microsecond intervals you specify. You should be aware that your task does not go into a wait state, but in- stead is actually consuming CPU time for this interval. Interrupts are not disabled, so the time could be much longer, but a task switch will probably not occur during the delay even though this is possible. MicroDelay guarantees the time to be no less than n-l5us where n is the number of 1 5-microsecond intervals you specify. The tim- ing is tied directly to the 15us RAM refresh hardware timer. The recommended maximum length is 20-milliseconds, although longer periods will work. Interrupt latency of the system is not affected for greater delay values, but application speed or appearance may be affected if the priority of your task is high enough, and you call this often enough. Parameter: dnl5us — A dword containing the number of 1 5-microsecond intervals to delay your task. MoveRequest MoveRequest (dRqBlkHndl, DestExch) : dError The kernel primitive MoveRequest ( ) allows a system service to move a request to another ex- change it owns. An example of use is when a system service receives a request it can't answer immediately. It would move it to a second exchange until it can honor the request. This cannotbe used to forward a request to another service or job because the data pointers in the outstanding request block have been aliased for the service the request was destined for.

Chapter 15 ■ API Specification Parameters: dRqBlkHndl — Handle of the request block to forward. DestExch — Exchange where the request is to be sent. NewTask NewTask(dJobNum, dCodeSeg, dPriority, dfDebug, dExch, dESP, dEIP) : dError This allocates a new Task State Segment (TSS), then fills in the TSS from the parameters to this call and schedules it for execution. If the priority of this new task is greater than the run- ning task, it is made to run, else it's placed on the Ready Queue in priority order. Most applications will use SpawnTask() instead of NewTask () because it's easier to use. The operating system uses this to create the initial task for a newly loaded job. Parameters: JobNum — Job number the new task belongs to ( JCB) CodeSeg — Which code segment, OS=8 or User=18 Priority — 0-31 (Primary application tasks use 25) f Debug — Non-zero if you want the enter the debugger immediately upon execution. Exch — Exchange for TSS. ESP — Stack pointer (offset in DSeg) EIP — Initial instruction pointer (offset in CSeg) OutByte OutByte(Byte, dPort) This writes a single byte to a port address. No error is returned. Parameters: Byte — The byte value to write to the port. dPort — The address of the port. OutDWord OutDWord(DWord, dPort) This writes a single dword to a port address. DWord — The dword value to write to the port. dPort — The address of the port.

250 Pan III ■ MMURTL-Speeifie Details OutWord OutWord(Word, dPort) This writes a single word to a port address. Parameters: Word — The word value to write to the port. dPort — The address of the port. OutWords OutWords(dPort, pDataOut, dBytes) This uses the processor string intrinsic function OUTSW to write the words pointed to by pDataOut to dPort. You specify the number of bytes total (words x 2). Parameters: dPort — The address of the port. pDataOut — A pointer to one or more dwords to send out the port. dBytes — The count of bytes to write to the port address. This is the number of words x2. PuMdAttrs PutVidAttrs(dCol, dLine, dnChars, dAttr): dError This applies the video attribute specified to the characters at the column and line specified on the video screen, or if not displayed, the virtual screen. This is done independently of the current video stream which means X and Y cursor coordi- nates are not affected. Parameters: dCol — Column to start on (0-79) dLine — Line (0-24) dnChars — Dword with number of characters to apply the attribute to. dAttr — Number of characters pbChars is pointing to. The Basic Video section in Chapter 9, “Application Programming,” describes all of the attribute values. PutVidChars PutVidChars(dCol, dLine, pbChars, nChars, dAttrib): dError ;

Chapter 15 ■ API Specification This places characters with the specified attribute directly on the caller's video screen. It is in- dependent of the current video stream, which means X and Y cursor coordinates are not af- fected. Parameters: dCol — Column to start on (0-79) dLine— Line (0-24) pbChars — Pointer to the text to be displayed nChars — Number of characters pbChars is pointing to dAtrib — Color or attribute to use during display. The “Basic Video” section in Chapter 9 describes all of the attribute values. QueryPages QueryPages(pdnPagesRet) : dError This returns the number of free physical memory pages left in the entire operating system managed memory space. Each page of memory is 4096 bytes. Parameter: pdnPagesRet — A pointer to a dword where the current count of free pages will be returned. ReadCMOS ReadCMOS(bAddress) :Byte This reads a single byte value at the address specified in the CMOS RAM and returns it from the function. This is specific to the ISA/EISA PC architecture. Parameter: bAddress — The address of the byte you want from 0 to MaxCMOSSize ReadKbd ReadKbd (pdKeyCodeRet, fWait) : dError ReadKbd ( ) is provided by the keyboard system service as the easy way for an application to read keystrokes. Access to all other functions of the keyboard service are only available through the Request and Wait primitives. This call blocks your task until completion. If f Wait is true (non-zero), the call will wait until a key is available before returning. If fWait is false (0), the call will return the keycode to

I
252 Part III M MMURTL-Specific Details pdKeyCodeRet and return with no error. If no key was available, error ErcNoKeyAvailable will be returned. Parameters: pdKeyCodeRet — A pointer to a dword where the keycode will be returned. See the documentation on the keyboard service for a complete description of keycodes. fWait — If true (non-zero), the call will wait until a keycode (user keystroke) is avail- able before returning. RegisterSvc RegisterSvc(pSvcName, dExch) : dError This procedure registers a message-based system service with the operating system. This will identify a system service name with a particular exchange. This information allows the operat- ing system to direct requests for system services without the originator (Requester) having to know where the actual exchange is located, or on what machine the request is being serviced, if forwarded across a network. Parameters: pSvcName — A pointer to an 8-byte string. The string must be left justified, and padded with spaces (20h). Service names are case sensitive. Examples: “KEYBOARD” and “FILESYS " dExch — The exchange to be associated with the service name. Request Request ( pSvcName, SvcCode, dRespExch, pRqHndlRet, npSend, pDatal , cbDatal , pData2, cbData2, dDataO, dDatal, dData2 ) : dError This is the operating system Request primitive. It allows a caller to send a request for services to a message-based system service. With all kernel primitives, dError , the value returned from the Request ( ) call itself, is an indi- cation of whether or not the Request ( ) primitive functioned normally. Zero will be returned if the Request ( ) primitive was properly routed to the service, otherwise an operating system sta- tus code will be returned. For example, if you made a Request () to QUEUEMGR and no

Chapter 15 ■ API Specification service named QUEUEMGR was installed, a dError indicating this problem would be returned (ErcNoSuchService). This error is not the error returned by the service. An error from the ser- vice is returned to your exchange (dRespExch) in the response message. Parameters: pSvcName — A pointer to an 8-byte, left justified, space padded, service name. Service name examples are “QUEUEMGR” or “FAXIN “. The service must be registered with the operating system. It must be installed or included in the operating system at build time. wSvcCode — The service code is a 16-bit unsigned word that identifies the action the service will perform for you. Values for the service code are documented by each service. Function codes 0, 65534 (OFFFEh), and 65535 (OFFFFh) are always reserved by the operating system. dRespExch — The exchange you want the response message to be sent to upon comple- tion of the request. See Respond(). pRqHndlRet — A pointer to a dword that will hold the request handle the request call will fill in. This is how you identify the fact that it is a request and not a non-specific message when you receive a message after waiting or checking at an exchange. npSend — A number (0, 1, or 2) that indicates how many of the two pData pointers, 1 and 2, are sending data to the service. If pDatal and pData2 both point to data in your memory area that is going to the service, then npSend would be 2. What each service expects is documented by the service for each service code. The descriptions for each service code within a service will tell you the value of npSend. The service actually knows which pointers it's reading or writing. The npSend parameter is so network transport systems will know which way to move data on the request if it is routed over a network. Always assume it will be network-routed. pDatal — A pointer to your memory area that the service can access. This may be data sent to the service, or a memory area where data will be returned from the service. Use of pDatal and pData2 are documented by the system service for each service code it handles. cbDatal — The size of the memory area in pDatal being sent to, or received from, the service. This mustbe 0 if pDatal is not used. pData2 — Same as pDatal . This allows a service to access a second memory area in your space if needed. cbData2 — The size of the data being sent to the service. This mustbe 0 if pData2 is not used. dData0, dDatal, dData2 — These are dwords used to pass data to a service. These are strictly for data and cannot contain pointers to data. The reason for this is that the operating system does not provide alias memory addresses to the service for them. The use of dData0, dDatal , and dData2 is defined by each service code handled by a system service. H

[254 Part III ■ MMURTL-Specific Details Respond Respond(dRqHndl, dStatRet): dError Respond ( ) is used by message-based system services to respond to the caller that made a request to it. A service must respond to all requests using Respond ( ) . Do not use SendMsg ( ) or ISendMsg ( ) . With all kernel primitives, dError, the value returned from the Respond ( ) call itself, is an indi- cation of whether or not the Respond primitive functioned normally. Zero will be returned if all was well, otherwise an operating-system status code will be returned. Parameters: dRqHndl — This is the Request handle that was received by the service at WaitMsg ( ) or CheckMsg( ). It identifies a Request Block resource that was allocated by the operating system. dStatRet — This is the status or error code that will be placed in the second dword, dMsgLo, of the message sent back to the requester of the service. This is the error/status that the service passes back to you to let you know it has handled your request properly. ScrollVid ScrollVid(dULCol,dULline,dnCols, dnLines, dfUp) This scrolls the described square area on the screen either up or down dnLines. If dfUp is non- zero the scroll will be up. The line(s) left blank is filled with character 20h and the normal video attribute stored in the JCB. Parameters: dULCol — The upper left column on which to start (0-79). dULLine — The upper left line (0-24). dnCols — The number of columns to be scrolled. dnLines — The count of lines to be scrolled. df Up — This non-zero to cause the scroll to be up instead of down. To scroll the entire screen up one line, the parameters are ScrollVid (0,0 ,80, 25,1 ). In this case the top line is lost, and the bottom line would be blanked. SendMsg SendMsg (dExch, dMsgHi, dMsgLo): dError SendMsg ( ) allows a task to send information to another task. The two-dword message is placed on the specified exchange. If there was a task waiting at that exchange, the message is associ- ated, linked with that task, and it is moved to the Ready queue.

Chapter 15 ■ API Specification Users of SendMsg( ) should be aware that they can receive responses from services and messages at the same exchange. The proper way to ensure the receiver of the message doesn't assume it is a Response, is to set the high order bit of dMsgHi, which is the first dword pushed. If it were a response from a service, the first DWord would be less than 80000000h, which is a positive 32-bit signed value. This is an agreed-upon convention, and is not enforced by the operating system. If you never make a request that indicates exchange X is the response exchange, you will not receive a response at the X exchange unless the operating system has gone into an undefined state — a polite term for crashed. The message is two double words that must be pushed onto the stack independently. When WaitMsg ( ) or CheckMsg ( ) returns these to your intended receiver, it will be into an array of dwords. In C this is unsigned long msg [ 2 ] . dMsgLo will be in the lowest array index, msg [ 0 ] , and dMsgHi will be in the highest memory address, msg [ 1 ] . Parameters: dExch — A dword (4 bytes) containing the exchange where the message should be sent. dMsgHi — The upper dword of the message. dMsgLo — The lower dword of the message. SetCmdLine SetCmdLine(pCmdLine, dcbCmdLine) : dError Each Job Control Block has a field to store the command line that was set by the previous application or command line interpreter. This field is not directly used or interpreted by the operating system. This call stores the command line in the JCB. The complimentary call, GetCmdLine ( ) , is provided to retrieve the command line. The CmdLine is preserved across ExitJobs, and while chaining to another application. Command line interpreters may use this call to set the command line text in the JCB prior to ExitJob( ) or Chain ( ) calls running an application. Parameters: pCmdLine — Points to an array of bytes, the new command line string. dcbCmdLine — The length of the command line string to store. The command line field in the JCB is a maximum of 79 characters. Longer values will cause ErcBadJobParam to be returned. SetExitfob SetExitJob(pabExitJobRet, pdcbExitJobRet) : dError Each Job Control Block has a field to store the ExitJob filename. This call sets the ExitJob string in the JCB. This field is used by the operating system when an application exits to see if H

256 Part III ■ MMURTL-Specific Details there is another application to load in the context of this job (JCB). Applications may use this call to set the name of the next job they want to execute in this JCB. This is typically used by a command line interpreter. The complimentary call GetExitJob ( ) is provided. The Exit Job remains set until it is set again. Calling SetExitJob with a zero-length value clears the exit job filename from the JCB. When a job exits, and its ExitJob is zero length, the job is terminated and all resources are reclaimed by the operating system. Parameters: pExitJob — Points to an array of bytes containing the new ExitJob filename. The filename must not be longer than 79 characters. dcbExitJob — A dword with the length of the string the pExitJob points to. SetlRQVector SetIRQVector(dIRQnum, pVector) The Set Interrupt Vector call places the address, pVector, into the interrupt descriptor table and marks it as an interrupt procedure. pVector mustbe a valid address in the operating-system address space because the IDT descriptor makes a protection level transition to system level if the interrupt occurred in a user level task, which will happen most often. Initially, all unas- signed hardware interrupts are masked at the priority interrupt controller units (PICUs). After the interrupt vector is set, the caller should then call UnMaskIRQ( ) to allow the interrupts to occur. Parameters: dIRQnum — The hardware interrupt request number for the IRQ to be set. This will be 0-7 for interrupts on 8259 #1, and 8-15 for interrupts on 8259 #2. Table 1 5.4 shows the predetermined IRQ uses. Table 15.4. Hardware IRQs.

IRQO 8254 Timer IRQ 1 Keyboard (8042) IRQ 2 Cascade from PICU2 (handled internally) IRQ 3 COM2 serial port * IRQ 4 COM 1 serial port* IRQ 5 LPT2* IRQ 6 Floppy disk controller * IRQ7 LPT1 *

Chapter 15 ■ API Specification s IRQ 8 CMOS clock IRQ 9 Not pre-defined IRQ 10 Not pre-defined IRQ 1 1 Not pre-defined IRQ 12 Not pre-defined IRQ 13 Math coprocessor * IRQ 1 4 Hard disk controller * IRQ 15 Not pre-defined *If installed, these should follow ISA hardware conventions. Built-in device drivers assume these values. pVector — The 32-bit address in operating system protected address space, of the Interrupt Service Routine (ISR) that handles the hardware interrupt. SetJobName SetJobName(pJobName, dcbJobName): dError This sets the job name in the job control block. This is a maximum of 13 characters. It is used only for the display of job names and serves no other function. If no job name is set by the application, the last 13 characters of the complete path for the run file that is executing are used. Parameters: pJobName — Pointer to the job name you want to store in the job control block. dcbJobName — Count of bytes in the pJobName parameter. The maximum length is 13 bytes. Longer values will be truncated. A zero length, will clear the job name from the JCB. SetNormVid SetNormVid(dNormVidAttr) : dError Each job is assigned a video screen, either virtual or real. The normal video attributes used to display characters on the screen can be different for each job. The default foreground color, the color of the characters themselves, and background colors may be changed by an application. The normal video attributes are used with the ClrScr( ) call, and also used by stream output from high level language libraries. If you SetNormVid ( ) to Black On White, then call ClrScr ( ) , the entire screen will become black characters on a white background.

H Part III ■ MMURTL-Specific Details Parameters: dNormVidAttr — This is a dword containing the value of the video attribute to become the normal or default. The attribute value is always a byte, but passed in as a dword for this, and some other operating system video calls. See Chapter 9 for a table containing values for video attributes. SetPath SetPath(pPath, dcbPath): dError Each job control block has a field to store the application's current path, a text string. The path is interpreted and used by the file system. Refer to file system documentation. This call allows applications to set their path string in the JCB. Typically, a command line interpreter would use this call to set the current path. Parameters: pPath — This points to an array of bytes containing the new path string. dcbPath — This is a dword containing the length of the new path for the current job. The path is 79 characters maximum. SetPriority SetPriority(bPriority) : dError This changes the priority of the task that is currently executing. Because the task that is run- ning is the one that needs its priority changed, you can ensure it is rescheduled at the new pri- ority by making any operating-system call that causes this task to be suspended. The Sleep ( ) function with a value of 1 would have this effect. Parameter: bPriority — This is the new priority (0—31). SetSysIn SetSysIn(pFileName, dcbFileName) : dError This sets the name of the standard input file stored in the job control block. The default name, if none is set by the application, is KBD. The keyboard system service bypasses this mechanism when you use the request/respond interface. If you desire to read data from a file to drive your application, you should read stream data from the file system using the procedural

Chapter 15 ■ API Specific interface call ReadBytes( ). Only ASCII data is returned from this call. If the Sysln name is set to KDB, it has the same effect as calling ReadKbd( ) with fWait set to true, and only receiving the low-order byte which is the character code. Parameters: pFileName — A maximum of 30 characters with the file or device name. dcbFileName — The count of characters pFileName is pointing to. SetSysOut SetSysOut (pFileName, dcbFileName): dError This sets the name of the standard output file stored in the job control block. The default name, if none is set, is VID. The direct access video calls bypass this mechanism. If you desire to write data from your application to a file, you should write stream data using the file system proce- dural interface call, WriteBytes( ). Only ASCII data is saved to the file. If the SysOut name is VID, writing to the file VID with WriteBytes ( ) is the same as calling TTYOut ( ) . Parameters: pFileName — A maximum of 30 characters with the file or device name. dcbFileName — The count of characters pFileName is pointing to. SetUserName SetUserName(pUserName, dcbUserName) : dError The job control block for an application has a field to store the current user's application name. This field is not used or interpreted by the operating system. The complimentary call, GetUserName( ) , is provided to retrieve it from the JCB. The name is preserved across ExitJobs, and chaining to another application. Parameters: pUsername — Points to a text string, which is the user's name. dcbllsername — The length of the string to store. SetVidOwner SetVidOwner(dJobNum) : dError This selects which job screen will be displayed on the screen. This is used by the MMURTL Monitor and can be used by another user written program manager. 259

I
260 Part III ■ MMURTL-Specific Details Parameter: dJobNum — The job number for the new owner of the active screen, which is the one to be displayed. SetXY SetXY(dNewX, dNewY) : dError This positions the cursor for the caller's screen to the X and Y position specified. This applies to the virtual screen, or the real video screen if currently assigned. Parameters: dNewX — The new horizontal cursor position column. dNewY — The new vertical cursor position row. Sleep Sleep(nTicks) : dError A public routine that delays the calling process by putting it into a waiting state for the amount of time specified. Sleep ( ) should not be used for small, critical timing in applications less than 20 ms. The overhead included in entry and exit code makes the timing a little more than 10 ms, and is not precisely calculable. An example of the use of Sleep ( ) is inside a loop that performs a repetitive function, and you do not want to create a busy-wait condition, which may consume valuable CPU time causing lower priority tasks to become starved. If your task has a high enough priority, a busy-wait condition may cause the CPU to appear locked up, when it's actually doing exactly what it's told to do. Sleep sends -1 (OFFFFFFFF hex) for both dwords of the message. Sleep is accomplished internally by setting up a timer block with the countdown value, and an exchange to send a message when the countdown reaches zero. The timer interrupt sends the message, and clears the block when it reaches zero. The default exchange in the TSS is used so the caller doesn't need to provide a separate exchange. Parameter: dnTicks — Dword with the number of 10-millisecond periods to delay execution of the task, or make it sleep.

Chapter 15 ■ API Specification SpawnTask SpawnTask(pEntry, dPriority, fDebug, pStack, fOSCode) :dError This creates a new task, or thread of execution, with the instruction address pEntry. This allo- cates a new task state segment (TSS), then fills in the TSS from the parameters you passed. Many of the TSS fields will be inherited from the task that called this function. If the priority of this new task is greater than the running task, it is made to run; otherwise, it's placed on the Ready queue in priority order. Parameters: pEntry — This is a pointer to the function, procedure, or code section that will become an independent thread of execution from the task that spawned it. dPriority — This is a number from 0 to 31. Application programs should use priority 25. System services will generally be in the 12—24 region. Secondary tasks for device drivers will usually be lower than 12. Device drivers such as network frame handlers may even require priorities as high as 5, but testing will be required to ensure har- mony. Print spoolers and other tasks that may consume a fair amount of CPU time, and may cause applications to appear sluggish, should use priorities above 25. Certain system services are higher priority, lower numbers, such as the file system and key- board. fDebug — A non-zero value will cause the task to immediately enter the debugger upon execution. The instruction displayed in the debugger will be the first instruction that is to be executed for the task. pStack — A memory area in the data segment that will become the stack for this task. Operating system operation requires 512 bytes. Add the number of bytes your task will require to this value. f OSCode — If you are spawning a task from a device driver, or within the operating system code segment, you should specify a non-zero value, 1 is accepted. Tone Tone(dHz, dTicks10ms): dError A public routine that sounds a tone of the specified frequency on the system hardware speaker for the duration specified by dTicks. Each dTick10ms is 10 milliseconds.

I
262 Part III ■ MMURTL-Specific Details Parameters: dHz — Dword that is the frequency in Hertz, from 30 to 10,000. dTickslOms — The number of 10-millisecond increments to sound the tone. A value of 100 is one second. TTYOut TTYOut (pTextOut, dTextOut, dAttrib) This places characters on the caller's screen in a TTY (teletype) fashion at the current X and Y coordinates for the calling job. The following characters in the stream are interpreted as follows: 0A Line Feed — The cursor, next active character placement, will be moved down one line. If this line is below the bottom of the screen, the entire screen will be scrolled up on line, and the bottom line will be blanked 0D Carriage Return — The cursor will be moved to column zero on the current line. 08 BackSpace — The cursor will be moved one column to the left. If it is already at column 0, backspace will have no effect. The backspace is non-destructive, no characters are changed. For character placement, if the cursor is in the last column of a line, it will be moved to the first column of the next line. If the cursor is in the last column on the last line, the screen will be scrolled up one line, and the bottom line will be blank. The cursor will then be placed in the first column on the last line. Parameters: pTextOut — A near pointer to the text. dTextOut — The number of chars of text. dAttrib — The attribute or color you want. UnMasklRQ UnMasklQR (dIRQnum) : dError This unmasks the hardware interrupt request specified by dIRQnum. When an IRQ is masked in hardware, the CPU will not be interrupted by the particular piece of hardware even if inter- rupts are enabled.

Chapter 15 ■ API Specification s Parameter: dlRQnum — The hardware interrupt request number for the IRQ you want to unmask. For a description oflRQs see the call description for SetIRQVector( ). UnRegisterSvc UnRegisterSvc(pSvcName) : dError This procedure removes the service name from the operating system name registry. The ser- vice with that name will no longer be available to callers. They will receive an error. Parameter: pSvcName — A pointer to an 8-byte string. The string must be left justified and padded with spaces (20h). Service names are case, sensitive. Examples: “KEYBOARD” and “FILESYS " This name must exactly match the name supplied by the service when it was registered. WaitMsg WaitMsg (dExch.pqMsgRet) :dError This is the kernel WaitMsg () primitive. This procedure provides access to operating system messaging by allowing a task to receive information from another task. If no message is avail- able, the task will be placed on the exchange specified. Execution of the process is suspended until a message is received at that exchange. At that time, the caller's task will be placed on the Ready queue and executed in priority order with other ready tasks. If the first 4-byte value is a valid pointer, less than 8000000h, it is possibly a pointer to a request block that was responded to. This is an agreed upon convention for the convenience of the programmer. Of course, you would have had to make the request in the first place, so this would be obvious to you. You've got to send mail to get mail. Parameters: dError — Returns 0 unless a fatal kernel error occurs. dExch — The exchange to wait for a message. pqMsg — A pointer to where the message will be returned, an array of two dwords.

Powered by TurnKey Linux.