1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
|
; SCCSID = @(#)mscode.asm 1.2 85/07/23
;
; MSCODE.ASM -- MSDOS code
;
.xlist
.xcref
include dossym.inc
include devsym.inc
include dosseg.asm
include ifssym.inc
include fastopen.inc
include fastxxxx.inc
.cref
.list
AsmVars <Kanji, Debug>
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
I_need InDos,BYTE ; TRUE => we are in dos, no interrupt
I_need OpenBuf,128 ; temp name buffer
I_need ExtErr,WORD ; extended error code
I_need User_SS,WORD ; stack segment from user
I_need User_SP,WORD ; stack pointer from user
I_need DskStack,BYTE ; stack segment inside DOS
I_need ThisCDS,DWORD ; Currently referenced CDS pointer
I_need ThisDPB,DWORD ; Currently referenced DPB pointer
I_need Err_Table_21 ; allowed return map table for errors
I_need FailErr,BYTE ; TRUE => system call is being failed
I_need ExtErr_Action,BYTE ; recommended action
I_need ExtErr_Class,BYTE ; error classification
I_need ExtErr_Locus,BYTE ; error location
I_need I21_Map_E_Tab,BYTE ; mapping extended error table
I_need User_In_AX,WORD ; initial input user AX
I_need FOO,WORD ; return address for dos 2f dispatch
I_need DTAB,WORD ; dos 2f dispatch table
I_need HIGH_SECTOR,WORD ; >32mb
I_need IFS_DRIVER_ERR,WORD ; >32mb
I_need FastOpenFlg,BYTE ;
I_need FastSeekFlg,BYTE ;
I_need CURSC_DRIVE,BYTE ;
BREAK <NullDev -- Driver for null device>
procedure SNULDEV,FAR
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
OR ES:[BX.REQSTAT],STDON ; Set done bit
entry INULDEV
RET ; MUST NOT BE A RETURN!
EndProc SNULDEV
BREAK <AbsDRD, AbsDWRT -- INT int_disk_read, int_disk_write handlers>
TABLE SEGMENT
Public MSC001S,MSC001E
MSC001S label byte
IF IBM
; Codes returned by BIOS
ERRIN:
DB 2 ; NO RESPONSE
DB 6 ; SEEK FAILURE
DB 12 ; GENERAL ERROR
DB 4 ; BAD CRC
DB 8 ; SECTOR NOT FOUND
DB 0 ; WRITE ATTEMPT ON WRITE-PROTECT DISK
ERROUT:
; DISK ERRORS RETURNED FROM INT 25 and 26
DB 80H ; NO RESPONSE
DB 40H ; Seek failure
DB 2 ; Address Mark not found
DB 10H ; BAD CRC
DB 4 ; SECTOR NOT FOUND
DB 3 ; WRITE ATTEMPT TO WRITE-PROTECT DISK
NUMERR EQU $-ERROUT
ENDIF
MSC001E label byte
TABLE ENDS
; AbsSetup - setup for abs disk functions
Procedure AbsSetup,NEAR
ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:DOSGroup
INC INDOS
STI
CLD
PUSH DS
Context DS
CALL GETBP
JC errdriv ;PM. error drive ;AN000;
MOV ES:[BP.dpb_free_cnt],-1 ; do not trust user at all.
errdriv:
POP DS
ASSUME DS:NOTHING
retc
MOV [HIGH_SECTOR],0 ;>32mb from API ;AN000;
CALL RW32_CONVERT ;>32mb convert 32bit format to 16bit ;AN000;
retc
invoke SET_RQ_SC_PARMS ;LB. set up SC parms ;AN000;
PUSH DS
PUSH SI
PUSH AX
Context DS
MOV SI,OFFSET DOSGROUP:OPENBUF
MOV [SI],AL
ADD BYTE PTR [SI],"A"
MOV WORD PTR [SI+1],003AH ; ":",0
MOV AX,0300H
CLC
INT int_IBM ; Will set carry if shared
POP AX
POP SI
POP DS
ASSUME DS:NOTHING
retnc
MOV ExtErr,error_not_supported
return
EndProc AbsSetup
; Interrupt 25 handler. Performs absolute disk read.
; Inputs: AL - 0-based drive number
; DS:BX point to destination buffer
; CX number of logical sectors to read
; DX starting logical sector number (0-based)
; Outputs: Original flags still on stack
; Carry set
; AH error from BIOS
; AL same as low byte of DI from INT 24
procedure ABSDRD,FAR
ASSUME CS:DOSGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING
CLI
MOV [user_SS],SS
MOV [user_SP],SP
PUSH CS
POP SS
ASSUME SS:DOSGROUP
MOV SP,OFFSET DOSGROUP:DSKSTACK
invoke Save_World ;>32mb save all regs ;AN000;
PUSH ES
CALL AbsSetup
JC ILEAVE
if not ibmcopyright
; Here is a gross temporary fix to get around a serious design flaw in
; the secondary cache. The secondary cache does not check for media
; changed (it should). Hence, you can change disks, do an absolute
; read, and get data from the previous disk. To get around this,
; we just won't use the secondary cache for absolute disk reads.
; -mw 8/5/88
EnterCrit critDisk
MOV [CURSC_DRIVE],-1 ; invalidate SC ;AN000;
LeaveCrit critDisk
endif
invoke DSKREAD
TLEAVE:
JZ ILEAVE
IF IBM
; Translate the error code to ancient 1.1 codes
PUSH ES
PUSH CS
POP ES
XOR AH,AH ; Nul error code
MOV CX,NUMERR ; Number of possible error conditions
MOV DI,OFFSET DOSGROUP:ERRIN ; Point to error conditions
REPNE SCASB
JNZ LEAVECODE ; Not found
MOV AH,ES:[DI+NUMERR-1] ; Get translation
LEAVECODE:
POP ES
ENDIF
MOV [IFS_DRIVER_ERR],AX ;>32mb save error
STC
ILEAVE:
POP ES
invoke Restore_World ;>32mb ;AN000;
CLI
DEC INDOS
MOV SS,[user_SS]
ASSUME SS:NOTHING
MOV SP,[user_SP]
MOV AX,[IFS_DRIVER_ERR] ;>32mb restore error ;AN000;
STI
RET ; This must not be a RETURN!
EndProc ABSDRD
; Interrupt 26 handler. Performs absolute disk write.
; Inputs: AL - 0-based drive number
; DS:BX point to source buffer
; CX number of logical sectors to write
; DX starting logical sector number (0-based)
; Outputs: Original flags still on stack
; Carry set
; AH error from BIOS
; AL same as low byte of DI from INT 24
procedure ABSDWRT,FAR
ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING
CLI
MOV [user_SS],SS
MOV [user_SP],SP
PUSH CS
POP SS
ASSUME SS:DOSGROUP
MOV SP,OFFSET DOSGROUP:DSKSTACK
invoke Save_World ;>32mb save all regs ;AN000;
PUSH ES
CALL AbsSetup
JC ILEAVE
EnterCrit critDisk
MOV [CURSC_DRIVE],-1 ; invalidate SC ;AN000;
CALL Fastxxx_Purge ; purge fatopen ;AN000;
LeaveCrit critDisk
invoke DSKWRITE
JMP TLEAVE
EndProc ABSDWRT
; Inputs:
; AL = Logical unit number (A = 0)
; Function:
; Find Drive Parameter Block
; Outputs:
; ES:BP points to DPB
; [THISDPB] = ES:BP
; Carry set if unit number bad or unit is a NET device.
; Later case sets extended error error_I24_not_supported
; No other registers altered
Procedure GETBP,NEAR
DOSAssume CS,<DS>,"GetBP"
ASSUME ES:NOTHING
PUSH AX
ADD AL,1 ; No increment; need carry flag
JC SkipGet
invoke GetThisDrv
JNC SkipGet ;PM. good drive ;AN000;
XOR AH,AH ;DCR. ax= error code ;AN000;
CMP AX,error_not_dos_disk ;DCR. is unknown media ? ;AN000;
JZ SkipGet ;DCR. yes, let it go ;AN000;
STC ;DCR. ;AN000;
MOV ExtErr,AX ;PM. invalid drive or Non DOS drive ;AN000;
MOV [IFS_DRIVER_ERR],0201H ;PM. other errors/unknown unit ;AN000;
SkipGet:
POP AX
retc
LES BP,[THISCDS]
TEST ES:[BP.curdir_flags],curdir_isnet ; Clears carry
JZ GETBP_CDS
LES BP,ES:[BP.curdir_ifs_hdr] ;IFS. if remote file ;AN000;
TEST ES:[BP.ifs_attribute],IFSREMOTE ;IFS. ;AN000;
LES BP,[THISCDS]
JZ GETBP_CDS ;IFS. then error ;AN000;
MOV ExtErr,error_not_supported
STC
return
GETBP_CDS:
LES BP,ES:[BP.curdir_devptr]
entry GOTDPB
DOSAssume CS,<DS>,"GotDPB"
; Load THISDPB from ES:BP
MOV WORD PTR [THISDPB],BP
MOV WORD PTR [THISDPB+2],ES
return
EndProc GetBP
BREAK <SYS_RET_OK SYS_RET_ERR CAL_LK ETAB_LK set system call returns>
ASSUME SS:DOSGROUP
;
; These are the general system call exit mechanisms. All internal system
; calls will transfer (jump) to one of these at the end. Their sole purpose
; is to set the user's flags and set his AX register for return.
;
procedure SYS_RETURN,NEAR
ASSUME DS:NOTHING,ES:NOTHING
entry SYS_RET_OK
invoke FETCHI_CHECK ; TAG checking for FETCHI
invoke get_user_stack
AND [SI.user_F],NOT f_Carry ; turn off user's carry flag
JMP SHORT DO_RET ; carry is now clear
entry SYS_RET_ERR
XOR AH,AH ; hack to allow for smaller error rets
invoke ETAB_LK ; Make sure code is OK, EXTERR gets set
CALL ErrorMap
entry From_GetSet
invoke get_user_stack
OR [SI.user_F],f_Carry ; signal carry to user
STC ; also, signal internal error
DO_RET:
MOV [SI.user_AX],AX ; Really only sets AH
return
entry FCB_RET_OK
entry CPMFunc
XOR AL,AL
return
entry FCB_RET_ERR
XOR AH,AH
mov exterr,AX
CALL ErrorMap
MOV AL,-1
return
entry errorMap
PUSH SI
MOV SI,OFFSET DOSGROUP:ERR_TABLE_21
CMP [FAILERR],0 ; Check for SPECIAL case.
JZ EXTENDED_NORMAL ; All is OK.
MOV [EXTERR],error_FAIL_I24 ; Ooops, this is the REAL reason
MOV SI,OFFSET DOSGROUP:ERR_TABLE_21
EXTENDED_NORMAL:
invoke CAL_LK ; Set CLASS,ACTION,LOCUS for EXTERR
POP SI
return
EndProc SYS_RETURN
; Inputs:
; SI is OFFSET in DOSGROUP of CLASS,ACTION,LOCUS Table to use
; (DS NEED not be DOSGROUP)
; [EXTERR] is set with error
; Function:
; Look up and set CLASS ACTION and LOCUS values for GetExtendedError
; Outputs:
; [EXTERR_CLASS] set
; [EXTERR_ACTION] set
; [EXTERR_LOCUS] set (EXCEPT on certain errors as determined by table)
; Destroys SI, FLAGS
procedure CAL_LK,NEAR
ASSUME DS:NOTHING,ES:NOTHING
PUSH DS
PUSH AX
PUSH BX
Context DS ; DS:SI -> Table
MOV BX,[EXTERR] ; Get error in BL
TABLK1:
LODSB
CMP AL,0FFH
JZ GOT_VALS ; End of table
CMP AL,BL
JZ GOT_VALS ; Got entry
ADD SI,3 ; Next table entry
JMP TABLK1
GOT_VALS:
LODSW ; AL is CLASS, AH is ACTION
CMP AH,0FFH
JZ NO_SET_ACT
MOV [EXTERR_ACTION],AH ; Set ACTION
NO_SET_ACT:
CMP AL,0FFH
JZ NO_SET_CLS
MOV [EXTERR_CLASS],AL ; Set CLASS
NO_SET_CLS:
LODSB ; Get LOCUS
CMP AL,0FFH
JZ NO_SET_LOC
MOV [EXTERR_LOCUS],AL
NO_SET_LOC:
POP BX
POP AX
POP DS
return
EndProc CAL_LK
; Inputs:
; AX is error code
; [USER_IN_AX] has AH value of system call involved
; Function:
; Make sure error code is appropriate to this call.
; Outputs:
; AX MAY be mapped error code
; [EXTERR] = Input AX
; Destroys ONLY AX and FLAGS
procedure ETAB_LK,NEAR
ASSUME DS:NOTHING,ES:NOTHING
PUSH DS
PUSH SI
PUSH CX
PUSH BX
Context DS
MOV [EXTERR],AX ; Set EXTERR with "real" error
MOV SI,OFFSET DOSGROUP:I21_MAP_E_TAB
MOV BH,AL ; Real code to BH
MOV BL,BYTE PTR [USER_IN_AX + 1] ; Sys call to BL
TABLK2:
LODSW
CMP AL,0FFH ; End of table?
JZ NOT_IN_TABLE ; Yes
CMP AL,BL ; Found call?
JZ GOT_CALL ; Yes
XCHG AH,AL ; Count to AL
XOR AH,AH ; Make word for add
ADD SI,AX ; Next table entry
JMP TABLK2
NOT_IN_TABLE:
MOV AL,BH ; Restore original code
JMP SHORT NO_MAP
GOT_CALL:
MOV CL,AH
XOR CH,CH ; Count of valid err codes to CX
CHECK_CODE:
LODSB
CMP AL,BH ; Code OK?
JZ NO_MAP ; Yes
LOOP CHECK_CODE
NO_MAP:
XOR AH,AH ; AX is now valid code
POP BX
POP CX
POP SI
POP DS
return
EndProc ETAB_LK
BREAK <DOS 2F Handler and default NET 2F handler>
IF installed
;
; SetBad sets up info for bad functions
;
Procedure SetBad,NEAR
ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
MOV AX,error_invalid_function ; ALL NET REQUESTS get inv func
MOV ExtErr_LOCUS,errLoc_UNK
STC
ret
EndProc SetBad
;
; BadCall is the initial routine for bad function calls
;
procedure BadCall,FAR
call SetBad
ret
EndProc BadCall
;
; OKCall always sets carry to off.
;
Procedure OKCall,FAR
ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
CLC
ret
EndProc OKCall
; INT 2F handler works as follows:
; PUSH AX
; MOV AX,multiplex:function
; INT 2F
; POP ...
; The handler itself needs to make the AX available for the various routines.
PUBLIC Int2F
INT2F PROC FAR
INT2FNT:
ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
STI
CMP AH,multNET
JNZ INT2FSHR
TestInstall:
OR AL,AL
JZ Leave2F
BadFunc:
CALL SetBad
entry Leave2F
RET 2 ; long return + clear flags off stack
INT2FSHR:
CMP AH,multSHARE ; is this a share request
JZ TestInstall ; yes, check for installation
INT2FNLS:
CMP AH,NLSFUNC ; is this a DOS 3.3 NLSFUNC request
JZ TestInstall ; yes check for installation
INT2FDOS:
ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
CMP AH,multDOS
JZ DispatchDOS
IRET ; This assume that we are at the head
; of the list
INT2F ENDP
DispatchDOS:
PUSH FOO ; push return address
PUSH DTab ; push table address
PUSH AX ; push index
PUSH BP
MOV BP,SP
; stack looks like:
; 0 BP
; 2 DISPATCH
; 4 TABLE
; 6 RETURN
; 8 LONG-RETURN
; c FLAGS
; e AX
MOV AX,[BP+0Eh] ; get AX value
POP BP
Invoke TableDispatch
JMP BadFunc ; return indicates invalid function
Procedure INT2F_etcetera,NEAR
entry DosGetGroup
PUSH CS
POP DS
return
entry DOSInstall
MOV AL,0FFh
return
EndProc INT2F_etcetera
ENDIF
;Input: same as ABSDRD and ABSDWRT
; ES:BP -> DPB
;Functions: convert 32bit absolute RW input parms to 16bit input parms
;Output: carry set when CX=-1 and drive is less then 32mb
; carry clear, parms ok
;
Procedure RW32_CONVERT,NEAR
ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
CMP CX,-1 ;>32mb new format ? ;AN000;
JZ new32format ;>32mb yes ;AN000;
PUSH AX ;>32mb save ax ;AN000;
PUSH DX ;>32mb save dx ;AN000;
MOV AX,ES:[BP.dpb_max_cluster] ;>32mb get max cluster # ;AN000;
MOV DL,ES:[BP.dpb_cluster_mask] ;>32mb ;AN000;
CMP DL,0FEH ;>32mb removable ? ;AN000;
JZ letold ;>32mb yes ;AN000;
INC DL ;>32mb ;AN000;
XOR DH,DH ;>32mb dx = sector/cluster ;AN000;
MUL DX ;>32mb dx:ax= max sector # ;AN000;
OR DX,DX ;>32mb > 32mb ? ;AN000;
letold:
POP DX ;>32mb retore dx ;AN000;
POP AX ;>32mb restore ax ;AN000;
JZ old_style ;>32mb no ;AN000;
MOV [IFS_DRIVER_ERR],0207H ;>32mb error ;AN000;
STC ;>32mb ;AN000;
return ;>32mb ;AN000;
new32format:
MOV DX,WORD PTR [BX.SECTOR_RBA+2];>32mb ;AN000;
MOV [HIGH_SECTOR],DX ;>32mb ;AN000;
MOV DX,WORD PTR [BX.SECTOR_RBA] ;>32mb ;AN000;
MOV CX,[BX.ABS_RW_COUNT] ;>32mb ;AN000;
LDS BX,[BX.BUFFER_ADDR] ;>32mb ;AN000;
old_style: ;>32mb ;AN000;
CLC ;>32mb ;AN000;
return ;>32mb ;AN000;
EndProc RW32_CONVERT
;Input: None
;Functions: Purge Fastopen/seek Cache Buffers
;Output: None
;
;
Procedure Fastxxx_Purge,NEAR
ASSUME CS:DOSGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
PUSH AX ; save regs. ;AN000;
PUSH SI ;AN000;
PUSH DX ;AN000;
TEST FastSeekflg,Fast_yes ; fastseek installed ? ;AN000;
JZ topen ; no ;AN000;
MOV AH,FastSeek_ID ; set fastseek id ;AN000;
JMP SHORT dofast ; ;AN000;
topen:
TEST FastOpenflg,Fast_yes ; fastopen installed ? ;AN000;
JZ nofast ; no ;AN000;
MOV AH,FastOpen_ID ; set fastseek installed ;AN000;
dofast:
MOV AL,FONC_purge ; purge ;AN000;
MOV DL,ES:[BP.dpb_drive] ; set up drive number ;AN000;
invoke Fast_Dispatch ; call fastopen/seek ;AN000;
nofast:
POP DX ;AN000;
POP SI ; restore regs ;AN000;
POP AX ; ;AN000;
return ; exit ;AN000;
EndProc Fastxxx_Purge
CODE ENDS
|