1 ; MMURTL Operating System Source Code
\r
2 ; Copyright 1991,1992,1993,1994 Richard A. Burgess
\r
3 ; ALL RIGHTS RESERVED Version 1.0
\r
8 ;These are the Equates and data are for the device
\r
9 ;driver entry and exit code.
\r
11 nDevices EQU 24 ;Number of Device Control Blocks
\r
13 ;Device Control Block. This structure defines the DCB layout for all
\r
14 ;device drivers. Each driver is responsible for creating and initially
\r
15 ;setting up a DCB prior to calling InitDevDr. The OS maintains an array
\r
16 ;of pointers to the device drivers. The physical device number
\r
17 ;(0-nDevices) is determined by the position in the array. An array
\r
18 ;position that contains a NULL pointer indicates a device is not installed.
\r
19 ;For instance, if the first pointer in the rgpDCBs is NULL, device "0"
\r
20 ;is not available. The DCB also maintains a 12 byte name for the device
\r
21 ;which the installer specifies. A PUBLIC call is provided to translate
\r
22 ;the name to a device number so callers and services can find the
\r
23 ;physical number from the name.
\r
24 ;The name of a device is case aware but NOT case sensitive
\r
26 ; The DCB structure layout follows:
\r
28 sDevCB EQU 64 ;size of the Device Control Block
\r
30 ;Define offsets into structure
\r
32 DevName EQU 0 ;DB 12 DUP (0) ;Device Name
\r
33 sbDevName EQU 12 ;DB 0 ;Length of Devname
\r
34 DevType EQU 13 ;DB 0 ;1 = RANDOM, 2 = SEQUENTIAL, 0 = No Device
\r
35 nBPB EQU 14 ;DW 0 ;Bytes per Block (1 to 65535 max)
\r
36 LastDevErc EQU 16 ;DD 0 ;Last error code from an operation
\r
37 nDevBlocks EQU 20 ;DD 0 ;Number of blocks in device (0 for sequential)
\r
39 pDevOp EQU 24 ;DD 0 ;Offset to device Operation handler
\r
40 pDevInit EQU 28 ;DD 0 ;Offset to device Init handler
\r
41 pDevSt EQU 32 ;DD 0 ;Offset to device Status handler
\r
43 fDevReent EQU 36 ;DB 0 ;Is device handler reentrant?
\r
44 fSingleUser EQU 37 ;DB 0 ;Is device assignable?
\r
45 wJob EQU 38 ;DW 0 ;If assignable, is it? (0 for no, else Job Num)
\r
46 DevSemExch EQU 40 ;DD 0 ;Exch for device semaphore (if not reentrant)
\r
47 DevSemMsg EQU 44 ;DD 0 ;Msg holder for msg from WAIT on queued Tasks
\r
48 DevSemMsg1 EQU 48 ;DD 0 ;Msg holder (second DWord)
\r
51 rgpDCBs DD nDevices DUP (0) ;
\r
52 rgReDIR DD nDevices DUP (0) ;For redirection of devices
\r
54 ;Standard Devices are:
\r
56 ;# Device Standard name
\r
58 ;0 NULL device NUL (OS built-in)
\r
59 ;1 Keyboard (sequential) KBD (OS built-in, ReadOnly)
\r
60 ;2 Video (sequential) VID (OS built-in, WriteOnly)
\r
61 ;3 Printer (parallel 1) LPT (OS built-in)
\r
62 ;4 Printer (parallel 2) LPT2 (OS built-in)
\r
63 ;5 RS-232 1 COM1 (OS built-in)
\r
64 ;6 RS-232 2 COM2 (OS built-in)
\r
65 ;7 RS-232 3 COM3 (OS built-in)
\r
66 ;8 RS-232 4 COM4 (OS built-in)
\r
68 ;10 Floppy FD0 (OS built-in)
\r
69 ;11 Floppy FD1 (OS built-in)
\r
70 ;12 Hard disk HD0 (OS built-in)
\r
71 ;13 Hard disk HD1 (OS built-in)
\r
82 ;------------- End Device Driver Data, Begin Code -----------------
\r
86 ;InitDevDr is called ONCE by a device driver after loading. pDCBs points to
\r
87 ;an array of DCBs (one for each device the driver handles). The devices
\r
88 ;will be numbered dDevNum, dDevNum+1, etc.
\r
89 ;For example, if the hard disk driver controls two disks it calls it once
\r
90 ;pointing to an array of two DCBs. The DCb must be contiguous in RAM!!
\r
92 ; InitDevDr(dDevNum, pDCBs, nDevices, dfReplace):dError
\r
93 ; EBP+24 EBP+20 EBP+16 EBP+12 sParam 16
\r
96 dDevX EQU DWORD PTR [EBP-4]
\r
97 prgDevs EQU DWORD PTR [EBP-8]
\r
98 nDevs EQU DWORD PTR [EBP-12]
\r
99 dExchTmp EQU DWORD PTR [EBP-16]
\r
101 PUBLIC __InitDevDr:
\r
105 MOV EAX, [EBP+24] ;Set up local vars
\r
113 CMP dDevX, nDevices ;Valid DCB num?
\r
115 MOV EAX, ErcBadDevNum ;Not valid DCB number
\r
118 InitDev01: ;Now check to see if device is already installed
\r
119 ;and whether it's to be replaced
\r
121 LEA EBX, rgpDCBs ;Point EBX to rgpDCB
\r
122 MOV EAX, dDevX ;dDevNum
\r
125 CMP DWORD PTR [EBX], 0 ;pDCBx = 0 if not used yet
\r
126 JZ InitDev02 ;Empty, OK to use
\r
127 CMP DWORD PTR [EBP+12], 0 ;OK to replace existing driver?
\r
129 MOV EAX, ErcDCBInUse ;No - error exit
\r
132 InitDev02: ;If we got here, we can check DCB items then move ptr
\r
134 MOV EAX, prgDevs ;EAX points to DCB
\r
135 CMP BYTE PTR [EAX+sbDevName],12 ;Check Device name size
\r
137 CMP BYTE PTR [EAX+sbDevName], 0 ;is Devname OK?
\r
140 MOV EAX, ErcBadDevName
\r
144 ;Now see if there are more devices for this driver
\r
146 DEC nDevs ;Decrement nDevices
\r
147 JZ InitDev05 ;NONE left
\r
148 ADD prgDevs, 64 ;Next caller DCB
\r
149 INC dDevX ;Next devnum
\r
150 JMP SHORT InitDev00 ;
\r
152 ;All error checking on DCB(s) should be done at this point
\r
154 InitDev05: ;Alloc Exch if driver in NOT reentrant
\r
155 MOV EBX, [EBP+20] ;pDCBs
\r
156 CMP BYTE PTR [EBX+fDevReent], 0
\r
157 JNZ InitDev06 ;device IS reentrant!
\r
158 LEA EAX, dExchTmp ;Allocate device Exchange
\r
159 PUSH EAX ;into temp storage
\r
160 CALL FWORD PTR _AllocExch
\r
162 JNZ SHORT InitDevEnd
\r
165 ;All went OK so far, now move the DCB pointer(s) into array
\r
166 ; and assign exchange from temp storage to each DCB
\r
168 MOV EAX, [EBP+16] ;nDevices
\r
169 MOV nDevs, EAX ;Set nDev to number of devices again
\r
170 LEA EBX, rgpDCBs ;Point EBX to OS rgpDCBs
\r
171 MOV EAX, [EBP+24] ;dDevNum
\r
173 ADD EBX, EAX ;EBX now points to correct pointer
\r
174 MOV EAX, [EBP+20] ;EAX points to first DCB
\r
175 MOV ECX, dExchTmp ;ECX has semaphore exchange
\r
177 ;Now that EBX, EAX and ECX are set up, loop through each
\r
178 ;DCB (if more than 1) and set up OS pointer to it, and
\r
179 ;also place Exchange into DCB. This is the same exchange
\r
180 ;for all devices that one driver controls.
\r
182 MOV [EAX+DevSemExch], ECX
\r
184 ADD EBX, 4 ;next p in rgp of DCBs
\r
185 ADD EAX, 64 ;next DCB
\r
187 JNZ InitDev07 ;Any more DCBs??
\r
188 XOR EAX, EAX ;Set up for no error
\r
190 ;If the device driver was NOT reentrant
\r
191 ;we send a semaphore message to the exchange for
\r
192 ;the first customer to use.
\r
194 MOV EBX, [EBP+20] ;pDCBs
\r
195 CMP BYTE PTR [EBX+fDevReent], 0
\r
196 JNZ InitDev06 ;device IS reentrant!
\r
197 PUSH ECX ;ECX is still the exchange
\r
198 PUSH 0FFFFFFFEh ;Dummy message
\r
200 CALL FWORD PTR _SendMsg ;Let erc in EAX fall through (Was ISend)
\r
207 ;=======================================================================
\r
208 ; Device Driver call for DeviceInit. Some up-front checking is done and
\r
209 ; then this call is forwarded to the destination driver
\r
211 ; DeviceInit(dDevNum, pInitData, sdInitData);
\r
212 ; EBP+20 EBP+16 EBP+12 Count = 12
\r
214 PUBLIC __DeviceInit: ;
\r
217 CMP DWORD PTR [EBP+20], nDevices ;Valid Device number?
\r
219 MOV EAX, ErcBadDevNum ;Sorry no valid DCB
\r
223 MOV EBX, [EBP+20] ;
\r
226 MOV EBX, [EAX] ;now EBX points to DCB (maybe)
\r
227 CMP EBX, 0 ;Is there a pointer to a DCB?
\r
229 MOV EAX, ErcNoDriver ;NO driver!
\r
232 CMP BYTE PTR [EBX+DevType], 0 ;Is there a physical device?
\r
234 MOV EAX, ErcNoDevice
\r
237 DevInit02: ;All looks good with device number
\r
238 ;so we check to see if driver is reentrant. If not we
\r
239 ;call WAIT to get semaphore ticket...
\r
241 CMP BYTE PTR [EBX+fDevReent], 0
\r
242 JNZ DevInit03 ;Device IS reentrant
\r
243 PUSH EBX ;save ptr to DCB
\r
244 PUSH DWORD PTR [EBX+DevSemExch] ;Push exchange number
\r
245 LEA EAX, [EBX+DevSemMsg] ;Ptr to message area
\r
247 CALL FWORD PTR _WaitMsg ;Get semaphore ticket
\r
248 POP EBX ;Get DCB ptr back
\r
250 JNE DevInitEnd ;Serious kernel error!
\r
253 PUSH EBX ;Save ptr to DCB
\r
254 PUSH DWORD PTR [EBP+20] ;Push all params for call to DD
\r
255 PUSH DWORD PTR [EBP+16]
\r
256 PUSH DWORD PTR [EBP+12]
\r
257 CALL DWORD PTR [EBX+pDevInit]
\r
258 POP EBX ;Get ptr to DCB back into EBX
\r
259 PUSH EAX ;save error (if any)
\r
261 CMP BYTE PTR [EBX+fDevReent], 0 ;Reentrant?
\r
264 PUSH DWORD PTR [EBX+DevSemExch] ;No, Send semaphore message to Exch
\r
265 PUSH 0FFFFFFFEh ;Bogus Message
\r
267 CALL FWORD PTR _SendMsg ;Ignore kernel error (unlikely)
\r
269 POP EAX ;Get device error back
\r
274 RETF 12 ;dump params
\r
277 ;=======================================================================
\r
278 ; Device Driver call for DeviceOp. Some up-front checking is done and
\r
279 ; then this call is forwarded to the destination driver
\r
281 ; DeviceOp(dDevice, dOpNum, dLBA, dnBlocks, pData);
\r
282 ; EBP+28 EBP+24 EBP+20 EBP+16 EBP+12 Count = 20
\r
287 CMP DWORD PTR [EBP+28], nDevices ;Valid Device number?
\r
289 MOV EAX, ErcBadDevNum ;Sorry no valid DCB
\r
293 MOV EBX, [EBP+28] ;
\r
296 MOV EBX, [EAX] ;EBX points to DCB (maybe)
\r
297 CMP EBX, 0 ;Is there a pointer to a DCB?
\r
299 MOV EAX, ErcNoDriver ;NO driver!
\r
302 CMP BYTE PTR [EBX+DevType], 0 ;Is it valid Device
\r
304 MOV EAX, ErcNoDevice
\r
307 DevOp02: ;All looks good with device number
\r
308 ;so we check to see if driver is reentrant. If not we
\r
309 ;call WAIT to get semaphore ticket...
\r
311 CMP BYTE PTR [EBX+fDevReent], 0
\r
312 JNZ DevOp03 ;Device IS reentrant
\r
313 PUSH EBX ;save ptr to DCB
\r
314 PUSH DWORD PTR [EBX+DevSemExch] ;Push exchange number
\r
315 LEA EAX, [EBX+DevSemMsg] ;Ptr to message area
\r
317 CALL FWORD PTR _WaitMsg ;Get semaphore ticket
\r
318 POP EBX ;Get DCB ptr back
\r
320 JNE DevOpEnd ;Serious kernel error!
\r
323 PUSH EBX ;Save ptr to DCB
\r
324 PUSH DWORD PTR [EBP+28] ;Push all params for call to DD
\r
325 PUSH DWORD PTR [EBP+24] ;
\r
326 PUSH DWORD PTR [EBP+20]
\r
327 PUSH DWORD PTR [EBP+16]
\r
328 PUSH DWORD PTR [EBP+12]
\r
329 CALL DWORD PTR [EBX+pDevOp]
\r
330 POP EBX ;Get ptr to DCB back into EBX
\r
331 PUSH EAX ;save error (if any)
\r
333 CMP BYTE PTR [EBX+fDevReent], 0 ;Reentrant?
\r
335 PUSH DWORD PTR [EBX+DevSemExch] ;Send semaphore message to Exch
\r
336 PUSH 0FFFFFFFEh ;Bogus Message
\r
338 CALL FWORD PTR _SendMsg ;Ignore kernel error
\r
340 POP EAX ;Get device error back
\r
345 RETF 20 ;dump params
\r
347 ;=======================================================================
\r
348 ; Device Driver call for DeviceStat. Some up-front checking is done and
\r
349 ; then this call is forwarded to the destination driver
\r
351 ; DeviceStat(dDevNum, pStatRet, dStatMax, pdStatRet);
\r
352 ; EBP+24 EBP+20 EBP+16 EBP+12 Count = 16
\r
354 PUBLIC __DeviceStat: ;
\r
357 CMP DWORD PTR [EBP+24], nDevices ;Valid Device number?
\r
359 MOV EAX, ErcBadDevNum ;Sorry no valid DCB
\r
362 LEA EAX, rgpDCBs ;Ptr to array of ptrs to DCBs
\r
363 MOV EBX, [EBP+24] ;Device number
\r
364 SHL EBX, 2 ;Times 4 (index into 4 byte ptrs)
\r
365 ADD EAX, EBX ;Add em up so EAX points to a pointer!
\r
366 MOV EBX, [EAX] ;now EBX points to DCB (maybe)
\r
367 CMP EBX, 0 ;Is there a pointer to a DCB?
\r
369 MOV EAX, ErcNoDriver ;NO driver!
\r
372 CMP BYTE PTR [EBX+DevType], 0 ;Is it valid Device
\r
374 MOV EAX, ErcNoDevice
\r
377 DevStat02: ;All looks good with device driver DCB
\r
378 ;so we check to see if driver is reentrant. If not we
\r
379 ;call WAIT to get semaphore ticket...
\r
381 CMP BYTE PTR [EBX+fDevReent], 0
\r
382 JNZ DevStat03 ;Device IS reentrant
\r
383 PUSH EBX ;save ptr to DCB
\r
384 PUSH DWORD PTR [EBX+DevSemExch] ;Push exchange number
\r
385 LEA EAX, [EBX+DevSemMsg] ;Ptr to message area
\r
387 CALL FWORD PTR _WaitMsg ;Get semaphore ticket
\r
388 POP EBX ;Get DCB ptr back
\r
390 JNE DevStatEnd ;Serious kernel error!
\r
393 PUSH EBX ;Save ptr to DCB
\r
394 PUSH DWORD PTR [EBP+24] ;Push all params for call to DD
\r
395 PUSH DWORD PTR [EBP+20]
\r
396 PUSH DWORD PTR [EBP+16]
\r
397 PUSH DWORD PTR [EBP+12]
\r
398 CALL DWORD PTR [EBX+pDevSt]
\r
399 POP EBX ;Get ptr to DCB back into EBX
\r
400 PUSH EAX ;save error (if any)
\r
401 CMP BYTE PTR [EBX+fDevReent], 0 ;Reentrant?
\r
403 PUSH DWORD PTR [EBX+DevSemExch] ;Send semaphore message to Exch
\r
404 PUSH 0FFFFFFFEh ;Bogus Message
\r
405 PUSH 0FFFFFFFEh ;Bogus Message
\r
406 CALL FWORD PTR _SendMsg ;Ignore kernel error (unlikely)
\r
408 POP EAX ;Get device error back
\r
413 RETF 16 ;dump params
\r
416 ;========= END of MODULE ================
\r