--- /dev/null
+; MMURTL Operating System Source Code\r
+; Copyright 1991,1992,1993,1994 Richard A. Burgess\r
+; ALL RIGHTS RESERVED Version 1.0\r
+;\r
+.DATA\r
+.INCLUDE MOSEDF.INC\r
+.ALIGN DWORD\r
+;These are the Equates and data are for the device\r
+;driver entry and exit code.\r
+\r
+nDevices EQU 24 ;Number of Device Control Blocks\r
+\r
+;Device Control Block. This structure defines the DCB layout for all\r
+;device drivers. Each driver is responsible for creating and initially\r
+;setting up a DCB prior to calling InitDevDr. The OS maintains an array\r
+;of pointers to the device drivers. The physical device number\r
+;(0-nDevices) is determined by the position in the array. An array\r
+;position that contains a NULL pointer indicates a device is not installed.\r
+;For instance, if the first pointer in the rgpDCBs is NULL, device "0"\r
+;is not available. The DCB also maintains a 12 byte name for the device\r
+;which the installer specifies. A PUBLIC call is provided to translate\r
+;the name to a device number so callers and services can find the\r
+;physical number from the name.\r
+;The name of a device is case aware but NOT case sensitive\r
+;\r
+; The DCB structure layout follows:\r
+;\r
+sDevCB EQU 64 ;size of the Device Control Block\r
+\r
+;Define offsets into structure\r
+\r
+DevName EQU 0 ;DB 12 DUP (0) ;Device Name\r
+sbDevName EQU 12 ;DB 0 ;Length of Devname\r
+DevType EQU 13 ;DB 0 ;1 = RANDOM, 2 = SEQUENTIAL, 0 = No Device\r
+nBPB EQU 14 ;DW 0 ;Bytes per Block (1 to 65535 max)\r
+LastDevErc EQU 16 ;DD 0 ;Last error code from an operation\r
+nDevBlocks EQU 20 ;DD 0 ;Number of blocks in device (0 for sequential)\r
+ ;24\r
+pDevOp EQU 24 ;DD 0 ;Offset to device Operation handler\r
+pDevInit EQU 28 ;DD 0 ;Offset to device Init handler\r
+pDevSt EQU 32 ;DD 0 ;Offset to device Status handler\r
+ ;36\r
+fDevReent EQU 36 ;DB 0 ;Is device handler reentrant?\r
+fSingleUser EQU 37 ;DB 0 ;Is device assignable?\r
+wJob EQU 38 ;DW 0 ;If assignable, is it? (0 for no, else Job Num)\r
+DevSemExch EQU 40 ;DD 0 ;Exch for device semaphore (if not reentrant)\r
+DevSemMsg EQU 44 ;DD 0 ;Msg holder for msg from WAIT on queued Tasks\r
+DevSemMsg1 EQU 48 ;DD 0 ;Msg holder (second DWord)\r
+ ;52\r
+\r
+rgpDCBs DD nDevices DUP (0) ;\r
+rgReDIR DD nDevices DUP (0) ;For redirection of devices\r
+\r
+;Standard Devices are:\r
+\r
+;# Device Standard name\r
+\r
+;0 NULL device NUL (OS built-in)\r
+;1 Keyboard (sequential) KBD (OS built-in, ReadOnly)\r
+;2 Video (sequential) VID (OS built-in, WriteOnly)\r
+;3 Printer (parallel 1) LPT (OS built-in)\r
+;4 Printer (parallel 2) LPT2 (OS built-in)\r
+;5 RS-232 1 COM1 (OS built-in)\r
+;6 RS-232 2 COM2 (OS built-in)\r
+;7 RS-232 3 COM3 (OS built-in)\r
+;8 RS-232 4 COM4 (OS built-in)\r
+;9\r
+;10 Floppy FD0 (OS built-in)\r
+;11 Floppy FD1 (OS built-in)\r
+;12 Hard disk HD0 (OS built-in)\r
+;13 Hard disk HD1 (OS built-in)\r
+;14\r
+;15\r
+;16\r
+;17\r
+;18\r
+;19\r
+;20\r
+;21\r
+;22\r
+;23\r
+;------------- End Device Driver Data, Begin Code -----------------\r
+.CODE\r
+;\r
+;\r
+;InitDevDr is called ONCE by a device driver after loading. pDCBs points to\r
+;an array of DCBs (one for each device the driver handles). The devices\r
+;will be numbered dDevNum, dDevNum+1, etc.\r
+;For example, if the hard disk driver controls two disks it calls it once\r
+;pointing to an array of two DCBs. The DCb must be contiguous in RAM!!\r
+;\r
+; InitDevDr(dDevNum, pDCBs, nDevices, dfReplace):dError\r
+; EBP+24 EBP+20 EBP+16 EBP+12 sParam 16\r
+;\r
+;Local vars\r
+dDevX EQU DWORD PTR [EBP-4]\r
+prgDevs EQU DWORD PTR [EBP-8]\r
+nDevs EQU DWORD PTR [EBP-12]\r
+dExchTmp EQU DWORD PTR [EBP-16]\r
+\r
+PUBLIC __InitDevDr:\r
+ PUSH EBP ;\r
+ MOV EBP,ESP ;\r
+ SUB ESP, 16\r
+ MOV EAX, [EBP+24] ;Set up local vars\r
+ MOV dDevX, EAX\r
+ MOV EAX, [EBP+20]\r
+ MOV prgDevs, EAX\r
+ MOV EAX, [EBP+16]\r
+ MOV nDevs, EAX\r
+\r
+InitDev00:\r
+ CMP dDevX, nDevices ;Valid DCB num?\r
+ JB InitDev01\r
+ MOV EAX, ErcBadDevNum ;Not valid DCB number\r
+ JMP InitDevEnd\r
+\r
+InitDev01: ;Now check to see if device is already installed\r
+ ;and whether it's to be replaced\r
+\r
+ LEA EBX, rgpDCBs ;Point EBX to rgpDCB\r
+ MOV EAX, dDevX ;dDevNum\r
+ SHL EAX, 2\r
+ ADD EBX, EAX\r
+ CMP DWORD PTR [EBX], 0 ;pDCBx = 0 if not used yet\r
+ JZ InitDev02 ;Empty, OK to use\r
+ CMP DWORD PTR [EBP+12], 0 ;OK to replace existing driver?\r
+ JNZ InitDev02 ;Yes\r
+ MOV EAX, ErcDCBInUse ;No - error exit\r
+ JMP InitDevEnd\r
+\r
+InitDev02: ;If we got here, we can check DCB items then move ptr\r
+\r
+ MOV EAX, prgDevs ;EAX points to DCB\r
+ CMP BYTE PTR [EAX+sbDevName],12 ;Check Device name size\r
+ JA InitDev03\r
+ CMP BYTE PTR [EAX+sbDevName], 0 ;is Devname OK?\r
+ JA InitDev04\r
+InitDev03:\r
+ MOV EAX, ErcBadDevName\r
+ JMP InitDevEnd\r
+\r
+InitDev04:\r
+ ;Now see if there are more devices for this driver\r
+\r
+ DEC nDevs ;Decrement nDevices\r
+ JZ InitDev05 ;NONE left\r
+ ADD prgDevs, 64 ;Next caller DCB\r
+ INC dDevX ;Next devnum\r
+ JMP SHORT InitDev00 ;\r
+\r
+ ;All error checking on DCB(s) should be done at this point\r
+\r
+InitDev05: ;Alloc Exch if driver in NOT reentrant\r
+ MOV EBX, [EBP+20] ;pDCBs\r
+ CMP BYTE PTR [EBX+fDevReent], 0\r
+ JNZ InitDev06 ;device IS reentrant!\r
+ LEA EAX, dExchTmp ;Allocate device Exchange\r
+ PUSH EAX ;into temp storage\r
+ CALL FWORD PTR _AllocExch\r
+ CMP EAX, 0\r
+ JNZ SHORT InitDevEnd\r
+\r
+InitDev06:\r
+ ;All went OK so far, now move the DCB pointer(s) into array\r
+ ; and assign exchange from temp storage to each DCB\r
+\r
+ MOV EAX, [EBP+16] ;nDevices\r
+ MOV nDevs, EAX ;Set nDev to number of devices again\r
+ LEA EBX, rgpDCBs ;Point EBX to OS rgpDCBs\r
+ MOV EAX, [EBP+24] ;dDevNum\r
+ SHL EAX, 2\r
+ ADD EBX, EAX ;EBX now points to correct pointer\r
+ MOV EAX, [EBP+20] ;EAX points to first DCB\r
+ MOV ECX, dExchTmp ;ECX has semaphore exchange\r
+InitDev07:\r
+ ;Now that EBX, EAX and ECX are set up, loop through each\r
+ ;DCB (if more than 1) and set up OS pointer to it, and\r
+ ;also place Exchange into DCB. This is the same exchange\r
+ ;for all devices that one driver controls.\r
+\r
+ MOV [EAX+DevSemExch], ECX\r
+ MOV [EBX], EAX\r
+ ADD EBX, 4 ;next p in rgp of DCBs\r
+ ADD EAX, 64 ;next DCB\r
+ DEC nDevs\r
+ JNZ InitDev07 ;Any more DCBs??\r
+ XOR EAX, EAX ;Set up for no error\r
+\r
+ ;If the device driver was NOT reentrant\r
+ ;we send a semaphore message to the exchange for\r
+ ;the first customer to use.\r
+\r
+ MOV EBX, [EBP+20] ;pDCBs\r
+ CMP BYTE PTR [EBX+fDevReent], 0\r
+ JNZ InitDev06 ;device IS reentrant!\r
+ PUSH ECX ;ECX is still the exchange\r
+ PUSH 0FFFFFFFEh ;Dummy message\r
+ PUSH 0FFFFFFFEh\r
+ CALL FWORD PTR _SendMsg ;Let erc in EAX fall through (Was ISend)\r
+\r
+InitDevEnd:\r
+ MOV ESP,EBP ;\r
+ POP EBP ;\r
+ RETF 16 ;\r
+;\r
+;=======================================================================\r
+; Device Driver call for DeviceInit. Some up-front checking is done and\r
+; then this call is forwarded to the destination driver\r
+;\r
+; DeviceInit(dDevNum, pInitData, sdInitData);\r
+; EBP+20 EBP+16 EBP+12 Count = 12\r
+;\r
+PUBLIC __DeviceInit: ;\r
+ PUSH EBP ;\r
+ MOV EBP,ESP ;\r
+ CMP DWORD PTR [EBP+20], nDevices ;Valid Device number?\r
+ JB DevInit01\r
+ MOV EAX, ErcBadDevNum ;Sorry no valid DCB\r
+ JMP DevInitEnd\r
+DevInit01:\r
+ LEA EAX, rgpDCBs\r
+ MOV EBX, [EBP+20] ;\r
+ SHL EBX, 2 ;\r
+ ADD EAX, EBX ;\r
+ MOV EBX, [EAX] ;now EBX points to DCB (maybe)\r
+ CMP EBX, 0 ;Is there a pointer to a DCB?\r
+ JNZ DevInit1A ;Yes\r
+ MOV EAX, ErcNoDriver ;NO driver!\r
+ JMP DevInitEnd\r
+DevInit1A:\r
+ CMP BYTE PTR [EBX+DevType], 0 ;Is there a physical device?\r
+ JNZ DevInit02\r
+ MOV EAX, ErcNoDevice\r
+ JMP DevInitEnd\r
+\r
+DevInit02: ;All looks good with device number\r
+ ;so we check to see if driver is reentrant. If not we\r
+ ;call WAIT to get semaphore ticket...\r
+\r
+ CMP BYTE PTR [EBX+fDevReent], 0\r
+ JNZ DevInit03 ;Device IS reentrant\r
+ PUSH EBX ;save ptr to DCB\r
+ PUSH DWORD PTR [EBX+DevSemExch] ;Push exchange number\r
+ LEA EAX, [EBX+DevSemMsg] ;Ptr to message area\r
+ PUSH EAX\r
+ CALL FWORD PTR _WaitMsg ;Get semaphore ticket\r
+ POP EBX ;Get DCB ptr back\r
+ CMP EAX, 0\r
+ JNE DevInitEnd ;Serious kernel error!\r
+\r
+DevInit03:\r
+ PUSH EBX ;Save ptr to DCB\r
+ PUSH DWORD PTR [EBP+20] ;Push all params for call to DD\r
+ PUSH DWORD PTR [EBP+16]\r
+ PUSH DWORD PTR [EBP+12]\r
+ CALL DWORD PTR [EBX+pDevInit]\r
+ POP EBX ;Get ptr to DCB back into EBX\r
+ PUSH EAX ;save error (if any)\r
+\r
+ CMP BYTE PTR [EBX+fDevReent], 0 ;Reentrant?\r
+ JNZ DevInit04 ;YES\r
+\r
+ PUSH DWORD PTR [EBX+DevSemExch] ;No, Send semaphore message to Exch\r
+ PUSH 0FFFFFFFEh ;Bogus Message\r
+ PUSH 0FFFFFFFEh ;\r
+ CALL FWORD PTR _SendMsg ;Ignore kernel error (unlikely)\r
+DevInit04:\r
+ POP EAX ;Get device error back\r
+\r
+DevInitEnd:\r
+ MOV ESP,EBP ;\r
+ POP EBP ;\r
+ RETF 12 ;dump params\r
+\r
+\r
+;=======================================================================\r
+; Device Driver call for DeviceOp. Some up-front checking is done and\r
+; then this call is forwarded to the destination driver\r
+;\r
+; DeviceOp(dDevice, dOpNum, dLBA, dnBlocks, pData);\r
+; EBP+28 EBP+24 EBP+20 EBP+16 EBP+12 Count = 20\r
+;\r
+PUBLIC __DeviceOp:\r
+ PUSH EBP ;\r
+ MOV EBP,ESP ;\r
+ CMP DWORD PTR [EBP+28], nDevices ;Valid Device number?\r
+ JB DevOp01\r
+ MOV EAX, ErcBadDevNum ;Sorry no valid DCB\r
+ JMP DevOpEnd\r
+DevOp01:\r
+ LEA EAX, rgpDCBs\r
+ MOV EBX, [EBP+28] ;\r
+ SHL EBX, 2 ;\r
+ ADD EAX, EBX ;\r
+ MOV EBX, [EAX] ;EBX points to DCB (maybe)\r
+ CMP EBX, 0 ;Is there a pointer to a DCB?\r
+ JNZ DevOp1A ;Yes\r
+ MOV EAX, ErcNoDriver ;NO driver!\r
+ JMP DevOpEnd\r
+DevOp1A:\r
+ CMP BYTE PTR [EBX+DevType], 0 ;Is it valid Device\r
+ JNZ DevOp02\r
+ MOV EAX, ErcNoDevice\r
+ JMP DevOpEnd\r
+\r
+DevOp02: ;All looks good with device number\r
+ ;so we check to see if driver is reentrant. If not we\r
+ ;call WAIT to get semaphore ticket...\r
+\r
+ CMP BYTE PTR [EBX+fDevReent], 0\r
+ JNZ DevOp03 ;Device IS reentrant\r
+ PUSH EBX ;save ptr to DCB\r
+ PUSH DWORD PTR [EBX+DevSemExch] ;Push exchange number\r
+ LEA EAX, [EBX+DevSemMsg] ;Ptr to message area\r
+ PUSH EAX\r
+ CALL FWORD PTR _WaitMsg ;Get semaphore ticket\r
+ POP EBX ;Get DCB ptr back\r
+ CMP EAX, 0\r
+ JNE DevOpEnd ;Serious kernel error!\r
+\r
+DevOp03:\r
+ PUSH EBX ;Save ptr to DCB\r
+ PUSH DWORD PTR [EBP+28] ;Push all params for call to DD\r
+ PUSH DWORD PTR [EBP+24] ;\r
+ PUSH DWORD PTR [EBP+20]\r
+ PUSH DWORD PTR [EBP+16]\r
+ PUSH DWORD PTR [EBP+12]\r
+ CALL DWORD PTR [EBX+pDevOp]\r
+ POP EBX ;Get ptr to DCB back into EBX\r
+ PUSH EAX ;save error (if any)\r
+\r
+ CMP BYTE PTR [EBX+fDevReent], 0 ;Reentrant?\r
+ JNZ DevOp04 ;YES\r
+ PUSH DWORD PTR [EBX+DevSemExch] ;Send semaphore message to Exch\r
+ PUSH 0FFFFFFFEh ;Bogus Message\r
+ PUSH 0FFFFFFFEh ;\r
+ CALL FWORD PTR _SendMsg ;Ignore kernel error\r
+DevOp04:\r
+ POP EAX ;Get device error back\r
+\r
+DevOpEnd:\r
+ MOV ESP,EBP ;\r
+ POP EBP ;\r
+ RETF 20 ;dump params\r
+\r
+;=======================================================================\r
+; Device Driver call for DeviceStat. Some up-front checking is done and\r
+; then this call is forwarded to the destination driver\r
+;\r
+; DeviceStat(dDevNum, pStatRet, dStatMax, pdStatRet);\r
+; EBP+24 EBP+20 EBP+16 EBP+12 Count = 16\r
+;\r
+PUBLIC __DeviceStat: ;\r
+ PUSH EBP ;\r
+ MOV EBP,ESP ;\r
+ CMP DWORD PTR [EBP+24], nDevices ;Valid Device number?\r
+ JB DevStat01\r
+ MOV EAX, ErcBadDevNum ;Sorry no valid DCB\r
+ JMP DevStatEnd\r
+DevStat01:\r
+ LEA EAX, rgpDCBs ;Ptr to array of ptrs to DCBs\r
+ MOV EBX, [EBP+24] ;Device number\r
+ SHL EBX, 2 ;Times 4 (index into 4 byte ptrs)\r
+ ADD EAX, EBX ;Add em up so EAX points to a pointer!\r
+ MOV EBX, [EAX] ;now EBX points to DCB (maybe)\r
+ CMP EBX, 0 ;Is there a pointer to a DCB?\r
+ JNZ DevStat1A ;Yes\r
+ MOV EAX, ErcNoDriver ;NO driver!\r
+ JMP DevStatEnd\r
+DevStat1A:\r
+ CMP BYTE PTR [EBX+DevType], 0 ;Is it valid Device\r
+ JNZ DevStat02\r
+ MOV EAX, ErcNoDevice\r
+ JMP DevStatEnd\r
+\r
+DevStat02: ;All looks good with device driver DCB\r
+ ;so we check to see if driver is reentrant. If not we\r
+ ;call WAIT to get semaphore ticket...\r
+\r
+ CMP BYTE PTR [EBX+fDevReent], 0\r
+ JNZ DevStat03 ;Device IS reentrant\r
+ PUSH EBX ;save ptr to DCB\r
+ PUSH DWORD PTR [EBX+DevSemExch] ;Push exchange number\r
+ LEA EAX, [EBX+DevSemMsg] ;Ptr to message area\r
+ PUSH EAX\r
+ CALL FWORD PTR _WaitMsg ;Get semaphore ticket\r
+ POP EBX ;Get DCB ptr back\r
+ CMP EAX, 0\r
+ JNE DevStatEnd ;Serious kernel error!\r
+\r
+DevStat03:\r
+ PUSH EBX ;Save ptr to DCB\r
+ PUSH DWORD PTR [EBP+24] ;Push all params for call to DD\r
+ PUSH DWORD PTR [EBP+20]\r
+ PUSH DWORD PTR [EBP+16]\r
+ PUSH DWORD PTR [EBP+12]\r
+ CALL DWORD PTR [EBX+pDevSt]\r
+ POP EBX ;Get ptr to DCB back into EBX\r
+ PUSH EAX ;save error (if any)\r
+ CMP BYTE PTR [EBX+fDevReent], 0 ;Reentrant?\r
+ JNZ DevStat04 ;YES\r
+ PUSH DWORD PTR [EBX+DevSemExch] ;Send semaphore message to Exch\r
+ PUSH 0FFFFFFFEh ;Bogus Message\r
+ PUSH 0FFFFFFFEh ;Bogus Message\r
+ CALL FWORD PTR _SendMsg ;Ignore kernel error (unlikely)\r
+DevStat04:\r
+ POP EAX ;Get device error back\r
+\r
+DevStatEnd:\r
+ MOV ESP,EBP ;\r
+ POP EBP ;\r
+ RETF 16 ;dump params\r
+\r
+\r
+;========= END of MODULE ================\r