summaryrefslogtreecommitdiff
path: root/v4.0/src/BIOS/MSDISK.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/BIOS/MSDISK.ASM')
-rw-r--r--v4.0/src/BIOS/MSDISK.ASM2443
1 files changed, 2443 insertions, 0 deletions
diff --git a/v4.0/src/BIOS/MSDISK.ASM b/v4.0/src/BIOS/MSDISK.ASM
new file mode 100644
index 0000000..f132e7f
--- /dev/null
+++ b/v4.0/src/BIOS/MSDISK.ASM
@@ -0,0 +1,2443 @@
1 PAGE ,132 ;
2 TITLE MSDISK - BIOS
3 %OUT ...MSDISK.ASM
4
5;==============================================================================
6;REVISION HISTORY:
7;AN000 - New for DOS Version 4.00 - J.K.
8;AC000 - Changed for DOS Version 4.00 - J.K.
9;AN00x - PTM number for DOS Version 4.00 - J.K.
10;==============================================================================
11;AN001; d24 Multi Track enable/disable command in CONFIG.SYS 6/27/87 J.K.
12;AN002; d9 Double word MOV instruction 7/1/87 J.K.
13;AN003: d25 Change DASD ERP to that recommended by Storage systems 7/28/87 J.K.
14;AN004; D113 Disable I/O access to unformatted media 9/03/87 J.K.
15;AN005; P985 Allow I/O access to unformatted media 9/14/87 J.K.
16;AN006; P1535 Disallow I/O access to unformatted media. 10/15/87 J.K.
17; (Give the user to control this - Generic IOCTL subfunction 64h/44h
18;AN007; p2828 Do not retry for multi-track format request 12/08/87 J.K.
19;AC008; p3197 Should reset change line after BPB set in BDS table 01/21/88 J.K.
20;AN009; p3349 Should retry at hard file timeout error 02/03/88 J.K.
21;AN010; p4696 ECC error handler should cover PC ATs for CMC disks 05/04/88 J.K.
22;AN011; p5034 Possible virgin hard file problem with direct INT 13 06/03/88 J.K.
23;AN012; P5049 Attempt to write at DISK BASE table in ROM BIOS 06/06/88 J.K.
24;AN013; P5055 Diskcopy fails (Regression of P5049) 06/09/88 J.K.
25;==============================================================================
26
27;for testing, set itest to 1. So as MSBIO1.ASM.
28 itest=0
29 EXTRN NUMERR:ABS ;MSDATA
30
31 INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT
32 INCLUDE MSEQU.INC
33 INCLUDE PUSHPOP.INC
34 INCLUDE MSMACRO.INC
35 INCLUDE DEVSYM.INC
36 INCLUDE MSDSKPR.INC
37 include biostruc.inc
38
39 EXTRN INT2F_DISK:FAR ;MSBIO2
40 EXTRN MEDIACHECK:NEAR ;96TPI
41 EXTRN HASCHANGE:NEAR ;96TPI
42 EXTRN MEDIA_SET_VID:NEAR ;96TPI
43 EXTRN HIDENSITY:NEAR ;96TPI
44 EXTRN CHECKLATCHIO:NEAR ;96TPI
45 EXTRN CHECKIO:NEAR ;96TPI
46 EXTRN SET_CHANGED_DL:NEAR ;96TPI
47 EXTRN SET_VOLUME_ID:NEAR ;MSVOLID
48 EXTRN SWPDSK:NEAR ;MSBIO2
49 EXTRN CMDERR:NEAR ;MSBIO1
50 EXTRN STRATEGY:NEAR ;MSBIO1
51 EXTRN ERR$CNT:NEAR ;MSBIO1
52 EXTRN DSK$IN:NEAR ;MSBIO1
53 EXTRN EXIT:NEAR ;MSBIO1
54 EXTRN BUS$EXIT:NEAR ;MSBIO1
55 EXTRN ERR$EXIT:NEAR ;MSBIO1
56 extrn ResetChanged:near ;AN000; MS96TPI
57
58;DATA
59 EXTRN OLD13:DWORD ;MSBIO2
60 EXTRN PTRSAV:DWORD ;MSBIO1
61 EXTRN COM1DEV:WORD ;MSAUX
62 EXTRN DAYCNT:WORD ;MSCLOCK
63 EXTRN TIM_DRV:BYTE ;MSDATA
64 EXTRN ACCESSCOUNT:BYTE ;MSDATA
65 EXTRN SM92:BYTE ;MSDATA
66 EXTRN DISKSECTOR:BYTE ;MSDATA
67 EXTRN MEDIABYTE:BYTE ;MSDATA
68 EXTRN SECPERCLUSINSECTOR:BYTE ;MSDATA
69 EXTRN BPB_IN_SECTOR:WORD ;MSDATA
70 EXTRN DISKSECTOR:BYTE ;MSDATA
71 EXTRN STEP_DRV:BYTE ;MSDATA
72 EXTRN START_BDS:WORD ;MSDATA
73 EXTRN PHYS_DRV:BYTE ;MSDATA
74 EXTRN WRTVERIFY:WORD ;MSDATA
75 EXTRN FSETOWNER:BYTE ;MSDATA
76 EXTRN SINGLE:BYTE ;MSDATA
77 EXTRN RFLAG:BYTE ;MSDATA
78 EXTRN MEDBYT:BYTE ;MSDATA
79 EXTRN SPSAV:WORD ;MSDATA
80 EXTRN SECCNT:WORD ;MSDATA
81 EXTRN DPT:DWORD ;MSDATA
82 EXTRN CURSEC:BYTE,CURHD:BYTE ;MSDATA
83 EXTRN CURTRK:WORD ;MSDATA
84 EXTRN EOT:BYTE ;MSDATA
85 EXTRN MOTORSTARTUP:BYTE,SETTLECURRENT:BYTE,SETTLESLOW:BYTE ;MSDATA
86 EXTRN CURHD:BYTE ;MSDATA
87 EXTRN LSTERR:BYTE ;MSDATA
88 EXTRN ERRIN:BYTE,ERROUT:BYTE ;MSDATA
89 EXTRN PREVOPER:WORD ;MSDATA
90 EXTRN ORIG13:DWORD ;MSDATA
91 EXTRN FLAGBITS:WORD ;MSDATA
92 EXTRN NUMBER_OF_SEC:BYTE ;MSDATA
93 EXTRN FHAVE96:BYTE ;MSDATA
94 EXTRN NEW_ROM:BYTE ;MSDATA
95 EXTRN FORMT_EOT:BYTE,HDNUM:BYTE,TRKNUM:WORD,GAP_PATCH:BYTE ;MSDATA
96 EXTRN NEXT2F_13:WORD ;MSDATA
97 extrn Save_head_sttl:byte ;msbdata
98 extrn Secrete_Code:word ;msbdata J.K. 11/7/86 Secrete code for DOS 3.3 MSBIO
99 extrn Ext_Boot_Sig:byte ;AN000; msbdata
100 extrn Boot_Serial_L:word ;AN000; msbdata
101 extrn Boot_Serial_H:word ;AN000; msbdata
102 extrn Boot_Volume_Label:byte ;AN000; msbdata
103 extrn Boot_System_ID:byte ;AN000; msbdata
104 extrn Model_Byte:Byte ;MSBIO2
105 extrn Secondary_Model_Byte:Byte ;MSBIO2
106
107;-----------------------------------------------------------------
108;
109; DISK INTERFACE ROUTINES
110;
111; DEVICE ATTRIBUTE BITS:
112; BIT 6 - GET/SET MAP FOR LOGICAL DRIVES AND GENERIC IOCTL.
113;
114
115MAXERR = 5
116LSTDRV = 504H
117
118; SOME FLOPPIES DO NOT HAVE CHANGELINE. AS A RESULT, MEDIA-CHECK WOULD
119; NORMALLY RETURN I-DON'T-KNOW, THE DOS WOULD CONTINUALLY REREAD THE FAT, AND
120; DISCARD CACHED DATA. WE OPTIMIZE THIS BY IMPLEMENTING A LOGICAL DOOR-
121; LATCH: IT IS PHYSICALLY IMPOSSIBLE TO CHANGE A DISK IN UNDER 2 SECONDS. WE
122; RETAIN THE TIME OF THE LAST SUCCESSFUL DISK OPERATION AND COMPARE IT WITH
123; THE CURRENT TIME DURING MEDIA-CHECK. IF < 2 SECONDS AND AT LEAST 1 TIMER
124; TICK HAS PASSED, THE WE SAY NO CHANGE. IF > 2 SECONDS THEN WE SAY I-
125; DON'T-KNOW. FINALLY, SINCE WE CANNOT TRUST THE TIMER TO BE ALWAYS
126; AVAILABLE, WE RECORD THE NUMBER OF MEDIA CHECKS THAT HAVE OCCURRED WHEN NO
127; APPARENT TIME HAS ELAPSED. WHILE THIS NUMBER IS < A GIVEN THRESHOLD, WE SAY
128; NO CHANGE. WHEN IT EXCEEDS THAT THRESHOLD, WE SAY I-DON'T-KNOW AND RESET
129; THE COUNTER TO 0. WHEN WE STORE THE TIME OF LAST SUCCESSFUL ACCESS, IF WE
130; SEE THAT TIME HAS PASSED TOO, WE RESET THE COUNTER.
131;
132ACCESSMAX = 5
133;
134; DUE TO VARIOUS BOGOSITIES, WE NEED TO CONTINUALLY ADJUST WHAT THE HEAD
135; SETTLE TIME IS. THE FOLLOWING ALGORITHM IS USED:
136;
137; GET THE CURRENT HEAD SETTLE VALUE.
138; IF IT IS 0, THEN
139; SET SLOW = 15
140; ELSE
141; SET SLOW = VALUE
142; ...
143;*********************************************
144;************ OLD ALGORITHM ******************
145;* IF WE ARE SEEKING AND WRITING THEN
146;* USE SLOW
147;* ELSE
148;* USE FAST
149;*********************************************
150;*********** IBM'S REQUESTED LOGIC ***********
151; IF WE ARE SEEKING AND WRITING AND NOT ON AN AT THEN
152; USE SLOW
153; ELSE
154; USE FAST
155; ...
156; RESTORE CURRENT HEAD SETTLE VALUE
157;
158
159Set_ID_Flag db 0 ;AN000; If 1, GETBP routine will set the
160 ;Vol_Serial and FileSys_ID in BDS table
161 ;from the media Boot record, if it is > DOS 4.00
162 ;formatted one. Then Set_ID_flag will be set to 2
163 ;to signal that volume_label is set from the extended
164 ;boot record and do not set it from the root
165 ;directory as done in SET_VOLUME_ID routine.
166 ;For the old version, Vol_Serial
167 ;will be set to -1, and FileSys_ID will be set
168 ;to "FAT12 " if it is a floppy.
169
170 public Fat_12_ID
171Fat_12_ID DB "FAT12 ",0 ;AN000; Default System ID for floppy.
172 public Fat_16_ID
173Fat_16_ID DB "FAT16 ",0 ;AN000;
174 public Vol_No_Name
175Vol_No_Name db "NO NAME ",0 ;AN000;
176 public Temp_H
177Temp_H dw 0 ;AN000; Temporary for 32 bit calculation.
178
179 public Start_Sec_H
180Start_Sec_H dw 0 ;AN000; Starting sector number high word.
181 ;Used as an input to DISKIO subroutine.
182Saved_Word dw 0 ;AN000; Tempory saving place for a word.
183
184;---------------------------------------
185;J.K. 6/29/87 For Multi-track
186MULTRK_ON EQU 10000000B ;User spcified Mutitrack=on, or System turns
187 ; it on after handling CONFIG.SYS file as a
188 ; default value, if MulTrk_flag = MULTRK_OFF1.
189MULTRK_OFF1 EQU 00000000B ;initial value. No "Multitrack=" command entered.
190MULTRK_OFF2 EQU 00000001B ;User specified Multitrack=off.
191 public MulTrk_Flag
192MulTrk_Flag dw 0 ;AN001;
193;J.K. 6/29/87 End of Multi-track definition.
194;---------------------------------------------------------------------
195 public EC35_Flag
196EC35_Flag db 0 ; flags for electrically compatible 3.5 inch disk drives (mrw 4/88)
197;---------------------------------------------------------------------
198VRetry_Cnt dw 0 ;AN003;
199Soft_ECC_Cnt dw 0 ;AN003;
200;---------------------------------------------------------------------
201MultiTrk_Format_Flag db 0 ;AN007;Testing. If 1, then Multi track format request
202;---------------------------------------------------------------------
203;
204; IF ID IS F9, HAVE A 96TPI DISK ELSE
205; IF BIT 2 IS 0 THEN MEDIA IS NOT REMOVABLE AND COULD NOT HAVE CHANGED
206; OTHERWISE IF WITHIN 2 SECS OF LAST DISK OPERATION MEDIA COULD NOT
207; HAVE CHANGED, OTHERWISE DONT KNOW IF MEDIA HAS CHANGED
208;
209 PUBLIC MEDIA$CHK
210MEDIA$CHK PROC NEAR
211 MESSAGE FTESTDISK,<"DISK MEDIA CHECK ">
212 MNUM FTESTDISK,AX
213 MESSAGE FTESTDISK,<CR,LF>
214 CALL SETDRIVE
215
216 cmp cs:Secrete_Code, 'jk' ;J.K.11/7/86 Secrete code for DOS 3.3 IBMBIO.
217 jne media$done ;J.K.11/7/86
218
219; FOR NON-REMOVABLE DISKS ONLY RETURN CHANGED IF CHANGED BY FORMAT, OTHERWISE
220; RETURN 'NOT CHANGED'.
221 MOV SI,1 ; ASSUME NO CHANGE
222 TEST WORD PTR [DI].FLAGS,FCHANGED_BY_FORMAT
223 JZ WEARENOTFAKINGIT
224 AND WORD PTR [DI].FLAGS,NOT FCHANGED_BY_FORMAT ; RESET FLAG
225; IF MEDIA HAS BEEN CHANGED BY FORMAT, WE MUST ASK THE ROM. CANNOT RELY ON THE
226; 2 SECOND TIME CHECK.
227 MOV CS:[TIM_DRV],-1 ; ENSURE THAT WE ASK THE ROM IF MEDIA
228 ; HAS CHANGED
229 TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE
230 JZ WEHAVEAFLOPPY
231 MOV SI,-1 ; INDICATE MEDIA CHANGED
232 JMP SHORT MEDIA$DONE
233;
234; WE NEED TO RETURN 'NOT CHANGED' IF WE HAVE A HARD FILE.
235;
236WEARENOTFAKINGIT:
237 TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE
238 JNZ MEDIA$DONE
239WEHAVEAFLOPPY:
240 XOR SI,SI ; PRESUME "I DON'T KNOW"
241;
242; IF WE HAVE A FLOPPY WITH CHANGELINE SUPPORT, WE ASK THE ROM TO DETERMINE IF
243; MEDIA HAS CHANGED. WE DO NOT PERFORM THE 2 SECOND CHECK FOR THESE DRIVES.
244;----------------------------------------|
245; WARNING: DO NOT CHANGE THE FOLLOWING. ;|
246; IT GETS PATCHED IN MSINIT ;|
247 PUBLIC MEDIA_PATCH ;|
248MEDIA_PATCH: ;|
249 CALL MEDIACHECK ;|
250 JC ERR$EXITJ ;|
251 CALL HASCHANGE ;|
252 JNZ MEDIA$DONE ;|
253;----------------------------------------|
254; IF WE COME HERE, WE HAVE A FLOPPY WITH NO CHANGELINE SUPPORT
255 MOV SI,1 ; PRESUME NO CHANGE
256 MOV AL,CS:[TIM_DRV] ; LAST DRIVE ACCESSED
257 CMP AL,BYTE PTR [DI].DRIVENUM ;IS DRIVE OF LAST ACCESS THE SAME?
258 JNZ MEDIA$UNK ; NO, THEN "I DON'T KNOW"
259;
260; CHECK TO SEE IF THIS DRIVE HAS BEEN ACCESSED IN THE LAST 2 SECONDS.
261 CALL CHECK_TIME_OF_ACCESS ; SETS SI CORRECTLY
262 JMP SHORT MEDIA$DONE
263
264MEDIA$UNK:
265 DEC SI ; RETURN "I DON'T KNOW"
266;
267; SI NOW CONTAINS THE CORRECT VALUE FOR MEDIA CHANGE. CLEAN UP THE LEFT OVERS
268;
269MEDIA$DONE:
270 LES BX,CS:[PTRSAV] ; GET ORIGINAL PACKET
271 MOV WORD PTR ES:[BX].TRANS,SI
272 OR SI,SI
273 JS INIT_PATCH
274 JMP EXIT
275MEDIA$CHK ENDP
276;----------------------------------------|
277; WARNING: DO NOT CHANGE THE FOLLOWING. ;|
278; IT GETS PATCHED IN MSINIT ;|
279 PUBLIC INIT_PATCH ;|
280INIT_PATCH PROC NEAR ;|
281 CALL MEDIA_SET_VID ;|
282;----------------------------------------|
283 MOV CS:[TIM_DRV],-1 ; MAKE SURE WE ASK ROM FOR MEDIA CHECK
284VOLIDOK:
285 JMP EXIT
286INIT_PATCH ENDP
287
288ERR$EXITJ PROC NEAR
289
290 MESSAGE FTESTCOM,<"ERR$EXITJ: ">
291 MNUM FTESTCOM,AX
292 MESSAGE FTESTCOM,<" == ">
293 CALL MAPERROR
294 MNUM FTESTCOM,AX
295 MESSAGE FTESTCOM,<CR,LF>
296 JMP ERR$EXIT
297ERR$EXITJ ENDP
298
299;
300; PERFORM A CHECK ON THE TIME PASSED SINCE THE LAST ACCESS FOR THIS PHYSICEL
301; DRIVE.
302; WE ARE ACCESSING THE SAME DRIVE. IF THE TIME OF LAST SUCCESSFUL ACCESS WAS
303; LESS THAN 2 SECONDS AGO, THEN WE MAY PRESUME THAT THE DISK WAS NOT CHANGED.
304; RETURNS IN SI:
305; 0 - IF TIME OF LAST ACCESS WAS >= 2 SECONDS
306; 1 - IF TIME WAS < 2 SECONDS (I.E NO MEDIA CHANGE ASSUMED)
307; REGISTERS AFFECTED AX,CX,DX, FLAGS.
308;
309CHECK_TIME_OF_ACCESS PROC NEAR
310 PUBLIC CHECK_TIME_OF_ACCESS
311
312 MOV SI,1 ; PRESUME NO CHANGE.
313;SB33014*************************************************************
314 xor AH,AH ; set command to read time
315 int 1Ah ; call rom-bios clock routine
316;SB33014*************************************************************
317;
318; NOW THAT WE ARE READING THE TIME, WE MUST MAKE SURE THAT WE DO NOT LOSE A
319; DATE WRAP. THE ROM WILL RETURN THE VALUE ONLY ONCE, SO WE NEED TO NOTE THIS
320; FACT.
321;
322 SHR AL,1
323 ADC CS:[DAYCNT],0 ; ADD IT IN TO OUR REMEMBERED DAY COUNT
324;
325; COMPUTE ELAPSED TIME
326;
327 MOV AX,WORD PTR DS:[DI].TIM_LO ; GET STORED TIME
328 SUB DX,AX
329 MOV AX,WORD PTR DS:[DI].TIM_HI
330 SBB CX,AX
331;
332; CX:DX IS THE ELAPSED TIME
333;
334 JNZ TIMECHECK_UNK ; CX <> 0 => > 1 HOUR
335 OR DX,DX ; TIME MUST PASS
336 JNZ TIMEPASSED ; YES, EXAMINE MAX VALUE
337;
338; NO NOTICEABLE TIME HAS PASSED. WE CANNOT TRUST THE COUNTER TO BE ALWAYS
339; AVAILABLE AS THERE ARE BOGUS PROGRAMS THAT GO AND REPROGRAM THE THING. WE
340; KEEP A COUNT OF THE NUMBER OF MEDIA CHECKS THAT WE'VE SEEN THAT DO NOT HAVE
341; ANY TIME PASSING. IF WE EXCEED A GIVE THRESHOLD, WE GIVE UP ON THE TIMER.
342;
343 INC BYTE PTR CS:ACCESSCOUNT
344 CMP BYTE PTR CS:ACCESSCOUNT,ACCESSMAX
345 JB TIMECHECK_RET ; IF COUNT IS LESS THAN THRESHOLD, OK
346 DEC BYTE PTR CS:ACCESSCOUNT ; DON'T LET THE COUNT WRAP
347 JMP SHORT TIMECHECK_UNK ; "I DON'T KNOW" IF MEDIA CHANGED
348;
349; 18.2 TICS PER SECOND.
350;
351TIMEPASSED:
352 CMP DX,18 * 2 ; MIN ELAPSED TIME?
353 JBE TIMECHECK_RET ; YES, PRESUME NO CHANGE
354;
355; EVERYTHING INDICATES THAT WE DO NOT KNOW WHAT HAS HAPPENED.
356;
357TIMECHECK_UNK:
358 DEC SI ; PRESUME I DON'T KNOW
359TIMECHECK_RET:
360 RET
361CHECK_TIME_OF_ACCESS ENDP
362
363ERR$EXITJ2: JMP ERR$EXITJ
364;
365; BUILD A VALID BPB FOR THE DISK IN THE DRIVE.
366;
367 PUBLIC GET$BPB
368GET$BPB PROC NEAR
369 MESSAGE FTESTDISK,<"DISK BUILD BPB ">
370 MNUM FTESTDISK,AX
371 MESSAGE FTESTDISK,<CR,LF>
372 MOV AH,BYTE PTR ES:[DI] ;GET FAT ID BYTE READ BY DOS
373 CALL SETDRIVE ; GET THE CORRECT BDS FOR THE DRIVE
374 TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE
375 JNZ ALREADY_GOTBPB ; NO NEED TO BUILD FOR FIXED DISKS
376;J.K. Let's set the default value for VOLID,Vol_Serial,FileSys_ID in BDS table
377 call Clear_IDs ;AN000;
378 mov cs:[Set_ID_Flag],1 ;AN000; Indicate to set system id in BDS
379 CALL GETBP ;BUILD A BPB IF NECESSARY.
380 JC ERR$EXITJ2 ;AN000; If error, Set_ID_flag is set to 0 already.
381 cmp cs:[Set_ID_Flag],2 ;AN000; Already, volume_Label set from Boot record
382 mov cs:[Set_ID_Flag],0 ;AN000; to BDS table?
383 je Already_GotBPB ;AN000; Then do not set it again from Root directory.
384 ;AN000; Otherwise, conventional Boot record.
385GET$BPB ENDP
386;----------------------------------------|
387; WARNING: DO NOT CHANGE THE FOLLOWING. ;|
388; IT GETS PATCHED IN MSINIT ;|
389 PUBLIC SET_PATCH ;|
390SET_PATCH PROC NEAR ;|
391 CALL SET_VOLUME_ID ;|
392;----------------------------------------|
393 MESSAGE FTESTDISK,<"SET VOLUME ID">
394 MNUM FTESTDISK,DI
395 MESSAGE FTESTDISK,<" ">
396 MNUM FTESTDISK,DS
397 MESSAGE FTESTDISK,<CR,LF>
398
399ALREADY_GOTBPB:
400 ADD DI,BYTEPERSEC ; RETURN THE BPB THAT IS IN THE CURRENT BDS
401
402 PUBLIC SETPTRSAV
403SETPTRSAV: ; RETURN POINT FOR DSK$INIT
404 LES BX,CS:[PTRSAV]
405 MOV ES:[BX].MEDIA,AH
406 MOV ES:[BX].COUNT,DI
407 MOV ES:[BX].COUNT+2,DS
408 JMP EXIT
409SET_PATCH ENDP
410
411;J.K. Clear IDs in BDS table. Only applied for Floppies.
412;Input: DS:DI -> BDS table
413;Output: VOLID set to "NO NAME "
414; VOL_SERIAL set to 0.
415; FileSys_ID set to "FAT12 " or "FAT16 "
416; depending on the flag FATSIZE in BDS.
417;All registers saved.
418 public Clear_IDs
419Clear_IDs proc near ;AN000;
420 push ds ;AN000;
421 push di ;AN000;
422 push es ;AN000;
423 push si ;AN000;
424 push cx ;AN000;
425
426 push ds ;AN000;
427 pop es ;AN000; es -> bds
428 push cs ;AN000;
429 pop ds ;AN000; ds = cs
430
431 mov cx, 0 ;AN000; no serial number
432 mov word ptr es:[di.VOL_SERIAL],cx ;AN000;
433 mov word ptr es:[di.VOL_SERIAL]+2,cx ;AN000;
434
435 mov cx, BOOT_VOLUME_LABEL_SIZE ;AN000; =11
436 mov si, offset VOL_NO_NAME ;AN000;
437 push di ;AN000; save BDS pointer
438 add di, VOLID ;AN000; points to VOLID field
439 rep movsb ;AN000;
440 pop di ;AN000; restore BDS pointer
441 test es:[di.FATSIZ], FBIG ;AN000;
442 jnz CI_BigFat ;AN000; small fat
443 mov si, offset FAT_12_ID ;AN000;
444 jmp CI_Filesys ;AN000;
445CI_BigFat: ;AN000;
446 mov si, offset FAT_16_ID ;AN000; big fat
447CI_Filesys: ;AN000;
448 mov cx, BOOT_SYSTEM_ID_SIZE ;AN000; =8
449 add di, FILESYS_ID ;AN000; points to FILESYS_ID field
450 rep movsb ;AN000;
451
452 pop cx ;AN000;
453 pop si ;AN000;
454 pop es ;AN000;
455 pop di ;AN000;
456 pop ds ;AN000;
457 ret ;AN000;
458Clear_IDs endp ;AN000;
459
460
461; GETBP - RETURN BPB FROM THE DRIVE SPECIFIED BY THE BDS.
462; IF THE RETURN_FAKE_BPB FLAG IS SET, THEN IT DOES NOTHING.
463; NOTE THAT WE NEVER COME HERE FOR FIXED DISKS.
464; FOR ALL OTHER CASES,
465; - IT READS BOOT SECTOR TO PULL OUT THE BPB
466; - IF NO VALID BPB IS FOUND, IT THEN READS THE FAT SECTOR,
467; TO GET THE FAT ID BYTE TO BUILD THE BPB FROM THERE.
468;
469; INPUTS: DS:DI POINT TO CORRECT BDS.
470;
471; OUTPUTS: FILLS IN BPB IN CURRENT BDS IF VALID BPB OR FAT ID ON DISK.
472; CARRY SET, AND AL=7 IF INVALID DISK.
473; CARRY SET AND ERROR CODE IN AL IF OTHER ERROR.
474; If failed to recognize the Boot Record, then will set the
475; Set_ID_Flag to 0.
476; J.K. This routine will only work for a floppy diskette.
477; For a fixed disk, it will just return.
478
479 PUBLIC GETBP
480GETBP PROC NEAR
481; IF RETURNING FAKE BPB THEN RETURN BPB AS IS.
482 TEST WORD PTR [DI].FLAGS,RETURN_FAKE_BPB OR FNON_REMOVABLE
483 JZ GETBP1
484 JMP GETRET_EXIT
485
486GETBP1:
487 MESSAGE FTESTDISK,<"BUILDING BPB FROM SCRATCH",CR,LF>
488 SAVEREG <CX,DX,ES,BX>
489;
490; ATTEMPT TO READ IN BOOT SECTOR AND DETERMINE BPB.
491; WE ASSUME THAT THE 2.X AND GREATER DOS DISKS ALL HAVE A VALID BOOT SECTOR.
492;
493RDBOOT:
494 CALL READBOOTSEC
495 JC GETBP_ERR_RET_brdg ; CARRY SET IF THERE WAS ERROR.
496 CMP BX,0 ; BX IS 0 IF BOOT SECTOR IS VALID.
497 JNZ DOFATBPB
498
499 CALL MOVBPB ; MOVE BPB INTO REGISTERS.
500 JMP HAS1
501
502Getbp_err_ret_brdg: jmp Getbp_err_ret
503;
504; WE HAVE A 1.X DISKETTE.
505; IN THIS CASE READ IN THE FAT ID BYTE AND FILL IN BPB FROM THERE.
506;
507DOFATBPB:
508 CALL READFAT ; PUTS MEDIA DESCRIPTOR BYTE IN AH
509 JC GETBP_ERR_RET_Brdg
510;----------------------------------------|
511; WARNING: DO NOT CHANGE THE FOLLOWING. ;|
512; IT GETS PATCHED IN MSINIT ;|
513 PUBLIC GETBP1_PATCH ;|
514GETBP1_PATCH: ;|
515 CALL HIDENSITY ;|
516;----------------------------------------|
517;TEST FOR A VALID 3.5" MEDIUM
518 CMP [DI].FORMFACTOR,FFSMALL
519 JNZ IS_FLOPPY
520 CMP AH,0F9H ; IS IT A VALID FAT ID BYTE FOR 3.5" ?
521 JNZ GOT_UNKNOWN_MEDIUM
522 MOV BX,OFFSET SM92 ; POINTER TO CORRECT BPB
523 PUSH CS
524 POP ES
525
526 ASSUME ES:CODE
527;J.K. DS points to segment of BDS. The following should be modified
528;J.K. to get spf,csec,spa,spt correctly. It had been wrong if DRIVER.SYS
529;J.K. is loaded since the BDS is inside the driver.sys.
530 MOV AL,es:[BX.SPF]
531 MOV CX,es:[BX.CSEC]
532 MOV DX,WORD PTR es:[BX.SPA]
533 MOV BX,WORD PTR es:[BX.SPT]
534 JMP SHORT HAS1
535; MUST BE A 5.25" FLOPPY IF WE COME HERE
536IS_FLOPPY:
537 MOV CL,AH ;SAVE MEDIA
538 AND CL,0F8H ;NORMALIZE
539 CMP CL,0F8H ;COMPARE WITH GOOD MEDIA BYTE
540 JNZ GOT_UNKNOWN_MEDIUM
541
542GOODID:
543 MOV AL,1 ;SET NUMBER OF FAT SECTORS
544 MOV BX,64*256+8 ;SET DIR ENTRIES AND SECTOR MAX
545 MOV CX,40*8 ;SET SIZE OF DRIVE
546 MOV DX,01*256+1 ;SET HEAD LIMIT AND SEC/ALL UNIT
547 TEST AH,00000010B ;TEST FOR 8 OR 9 SECTOR
548 JNZ HAS8 ;NZ = HAS 8 SECTORS
549 INC AL ;INC NUMBER OF FAT SECTORS
550 INC BL ;INC SECTOR MAX
551 ADD CX,40 ;INCREASE SIZE
552HAS8:
553 TEST AH,00000001B ;TEST FOR 1 OR 2 HEADS
554 JZ HAS1 ;Z = 1 HEAD
555 ADD CX,CX ;DOUBLE SIZE OF DISK
556 MOV BH,112 ;INCREASE NUMBER OF DIRECTORY ENTRIES
557 INC DH ;INC SEC/ALL UNIT
558 INC DL ;INC HEAD LIMIT
559
560HAS1:
561 PUBLIC HAS1
562
563 MOV BYTE PTR DS:[DI].SECPERCLUS,DH
564 MOV BYTE PTR DS:[DI].CDIR,BH
565 MOV WORD PTR DS:[DI].DRVLIM,CX
566 MOV BYTE PTR DS:[DI].MEDIAD,AH
567 MOV BYTE PTR DS:[DI].CSECFAT,AL
568 MOV BYTE PTR DS:[DI].SECLIM,BL
569 MOV BYTE PTR DS:[DI].HDLIM,DL
570;SB34DISK001*******************************************************************
571;SB the HIDSEC_H field and DRVLIM_L field and the
572;SB DRVLIM_H fields need to be set to 0 since this code here is for floppies
573;SB 3 LOCS
574
575 mov word ptr ds:[di].HIDSEC_H,0
576 mov word ptr ds:[di].HIDSEC_L,0
577 mov word ptr ds:[di].DRVLIM_H,0
578
579;SB34DISK001*******************************************************************
580GETRET:
581 POP BX
582 RESTOREREG <ES,DX,CX>
583
584 ASSUME ES:NOTHING
585
586GETRET_EXIT:
587 RET
588
589GETBP_ERR_RET:
590;J.K. Before doing anything else, set Set_ID_Flag to 0.
591 mov cs:Set_ID_Flag, 0 ;AN000;
592 CALL MAPERROR
593 JMP SHORT GETRET
594;
595; WE HAVE A 3.5" DISKETTE FOR WHICH WE CANNOT BUILD A BPB. WE DO NOT ASSUME ANY
596; TYPE OF BPB FOR THIS MEDIUM.
597;
598GOT_UNKNOWN_MEDIUM:
599 mov cs:Set_ID_Flag, 0 ;AN000;
600 MOV AL,ERROR_UNKNOWN_MEDIA
601 STC
602 JMP SHORT GETRET
603GETBP ENDP
604
605BPBTYPE STRUC
606SPF DB ?
607SPT DB ?
608CDIRE DB ?
609CSEC DW ?
610SPA DB ?
611CHEAD DB ?
612BPBTYPE ENDS
613
614;
615; READ IN THE BOOT SECTOR. SET CARRY IF ERROR IN READING SECTOR.
616; BX IS SET TO 1 IF THE BOOT SECTOR IS INVALID, OTHERWISE IT IS 0.
617;
618READBOOTSEC PROC NEAR
619 MOV DH,0 ;HEAD 0
620 MOV CX,0001 ;CYLINDER 0, SECTOR 1
621 CALL READ_SECTOR
622 JC ERR_RET
623 XOR BX,BX ; ASSUME VALID BOOT SECTOR.
624
625;*******************************************************************************
626; PUT A SANITY CHECK FOR THE BOOT SECTOR IN HERE TO DETECT BOOT SECTORS THAT
627; DO NOT HAVE VALID BPBS.
628; WE EXAMINE THE FIRST TWO BYTES - THEY MUST CONTAIN A LONG JUMP (69H) OR A
629; SHORT JUMP (EBH) FOLLOWED BY A NOP (90H), OR A SHORT JUMP (E9H).
630; IF THIS TEST IS PASSED, WE FURTHER CHECK BY EXAMINING THE SIGNATURE AT
631; THE END OF THE BOOT SECTOR FOR THE WORD AA55H.
632; IF THE SIGNATURE IS NOT PRESENT, WE EXAMINE THE MEDIA DESCRIPTOR BYTE TO
633; SEE IF IT IS VALID.
634;J.K. 10/15/86 DCR00012. For DOS 3.3, this logic is modified a little bit.
635; We are not going to check Signature. Instead we are going to sanity
636; check the media byte in BPB regardless of the validity of signature.
637; This is to save the already developed commercial products that have
638; good jump instruction and signature but with the false BPB informations
639; that will crash the diskette drive operation. (For example, Symphony diskette).
640;******************************************************************************
641 CMP BYTE PTR CS:[DISKSECTOR],069H ; IS IT A DIRECT JUMP?
642 JE Check_bpb_MediaByte ; DON'T NEED TO FIND A NOP
643 CMP BYTE PTR CS:[DISKSECTOR],0E9H ; DOS 2.0 JUMP?
644 JE Check_bpb_MediaByte ; NO NEED FOR NOP
645 CMP BYTE PTR CS:[DISKSECTOR],0EBH ; HOW ABOUT A SHORT JUMP.
646 JNE INVALIDBOOTSEC
647 CMP BYTE PTR CS:[DISKSECTOR]+2,090H ; IS NEXT ONE A NOP?
648 JNE INVALIDBOOTSEC
649
650
651;J.K. 10/15/86 Don't have to perform the following signature check since
652; we need to check the media byte even with the good signatured diskette.
653;CHECK_SIGNATURE:
654; CMP WORD PTR CS:[DISKSECTOR+1FEH],0AA55H ; SEE IF NON-IBM DISK OR 1.X
655; ; MEDIA.
656; JZ CHECKSINGLESIDED ; GO SEE IF SINGLE SIDED MEDIUM. MAY
657; ; NEED SOME SPECIAL HANDLING
658;
659; CHECK FOR NON-IBM DISKS WHICH DO NOT HAVE THE SIGNATURE AA55 AT THE
660; END OF THE BOOT SECTOR, BUT STILL HAVE A VALID BOOT SECTOR. THIS IS DONE
661; BY EXAMINING THE MEDIA DESCRIPTOR IN THE BOOT SECTOR.
662;
663
664Check_bpb_MediaByte:
665
666 MOV AL,BYTE PTR CS:MEDIABYTE
667 AND AL,0F0H
668 CMP AL,0F0H ; ALLOW FOR STRANGE MEDIA
669 JNZ INVALIDBOOTSEC
670;
671; THERE WERE SOME (APPARENTLY A LOT OF THEM) DISKETTES THAT HAD BEEN FORMATTED
672; UNDER DOS 3.1 AND EARLIER VERSIONS WHICH HAVE INVALID BPBS IN THEIR BOOT
673; SECTORS. THESE ARE SPECIFICALLY DISKETTES THAT WERE FORMATTED IN DRIVES
674; WITH ONE HEAD, OR WHOSE SIDE 0 WAS BAD. THESE CONTAIN BPBS IN THE BOOT
675; SECTOR THAT HAVE THE SEC/CLUS FIELD SET TO 2 INSTEAD OF 1, AS IS STANDARD
676; IN DOS. IN ORDER TO SUPPORT THEM, WE HAVE TO INTRODUCE A "HACK" THAT WILL
677; HELP OUR BUILD BPB ROUTINE TO RECOGNISE THESE SPECIFIC CASES, AND TO
678; SET UP OUT COPY OF THE BPB ACCORDINGLY.
679; WE DO THIS BY CHECKING TO SEE IF THE BOOT SECTOR IS OFF A DISKETTE THAT
680; IS SINGLE-SIDED AND IS A PRE-DOS 3.20 DISKETTE. IF IT IS, WE SET THE
681; SEC/CLUS FIELD TO 1. IF NOT, WE CARRY ON AS NORMAL.
682CHECKSINGLESIDED:
683 MOV AL,BYTE PTR CS:MEDIABYTE
684 TEST AL,0001H ; IS LOW BIT SET? - INDICATES DOUBLE SIDED
685 JNZ GOODDSK
686 CMP WORD PTR CS:[DISKSECTOR+8],"." SHL 8 + "3"
687 JNZ MUSTBEEARLIER
688 CMP BYTE PTR CS:[DISKSECTOR+10],"2"
689 JAE GOODDSK
690
691; WE MUST HAVE A PRE-3.20 DISKETTE. SET THE SEC/CLUS FIELD TO 1
692MUSTBEEARLIER:
693 MOV BYTE PTR CS:[SECPERCLUSINSECTOR],1
694 JMP SHORT GOODDSK
695;******************************************************************************
696
697INVALIDBOOTSEC:
698 INC BX ; INDICATE THAT BOOT SECTOR INVALID
699GOODDSK: ; CARRY ALREADY RESET
700 CLC
701 RET
702
703ERR_RET: ; CARRY IS ALREADY SET ON ENTRY HERE
704 MESSAGE FTESTDISK,<"ERROR IN READBOOT",CR,LF>
705 RET
706READBOOTSEC ENDP
707
708; MOVES THE BPB READ FROM THE BOOT SECTOR INTO REGISTERS FOR USE BY
709; GETBP ROUTINE AT HAS1
710;J.K.-
711; If the Set_ID_Flag is 1, and if an extended Boot Record, then set Volume
712; Serial Number, Volume Label, File System ID in BDS according to
713; the BOOT reocrd. After that, this routine will set the Set_ID_Flag to 2
714; to signal that VOLUME Label is set already from the Extended BOOT record
715; (so, don't set it again by calling "SET_VOLUME_ID" routine which uses
716; the volume label in the root directory.
717
718MOVBPB PROC NEAR
719 SAVEREG <DS,DI>
720 PUSH CS
721 POP DS
722 MOV DI,OFFSET BPB_IN_SECTOR
723 MOV DH,BYTE PTR [DI].SECALL ;SECTORS PER UNIT
724 MOV BH,BYTE PTR [DI].DIRNUM ;NUMBER OF DIRECTORY ENTRIES
725 MOV CX,WORD PTR [DI].SECNUM ;SIZE OF DRIVE
726 MOV AH,BYTE PTR [DI].FATID ;MEDIA DESCRIPTOR
727 MOV AL,BYTE PTR [DI].FATSIZE ;NUMBER OF FAT SECTORS
728 MOV BL,BYTE PTR [DI].SLIM ;SECTORS PER TRACK
729 MOV DL,BYTE PTR [DI].HLIM ;NUMBER OF HEADS
730 RESTOREREG <DI,DS>
731 cmp cs:[Set_ID_Flag], 1 ;AC008 called by GET$BPB?
732 jne MovBPB_Ret ;AC008
733 call Mov_Media_IDs ;AC008
734 jc MovBPB_Conv ;AC008 Conventional boot record?
735 mov cs:[Set_ID_Flag],2 ;AC008 signals that Volume ID is set.
736MovBPB_Conv: ;AC008
737 cmp cs:fHave96, 1 ;AC008
738 jne MovBPB_Ret ;AC008
739 call ResetChanged ;AC008 Reset Flags in BDS to NOT fCHANGED.
740MovBPB_Ret: ;AC008
741 clc ;AC008
742 ret ;AC008
743MOVBPB ENDP ;AC008
744
745
746;
747 public Mov_Media_IDs
748Mov_Media_IDs Proc near ;AN000;
749;copy the boot_serial number, Volume id, and Filesystem id from the
750;***Extended Boot record*** in cs:DiskSector to the BDS table pointed
751;by DS:DI.
752;In.) DS:DI -> BDS
753; CS:DiskSector = Valid extended boot record.
754;Out.) Vol_Serial, Volid and System_Id in BDS are set according to
755; the boot record information.
756; Carry flag set if not an extended BPB.
757; All registers saved except the flag.
758
759 cmp cs:[Ext_Boot_Sig], EXT_BOOT_SIGNATURE ;AN000; = 41
760 jne MMI_Not_Ext ;AN000;
761 push cx ;AN000;
762 mov cx, cs:[Boot_Serial_L] ;AN000;
763 mov word ptr ds:[di.VOL_SERIAL],cx ;AN000;
764 mov cx, cs:[Boot_Serial_H] ;AN000;
765 mov word ptr ds:[di.VOL_SERIAL+2],cx ;AN000;
766 push ds ;AN000; Save regs.
767 push di ;AN000;
768 push es ;AN000;
769 push si ;AN000;
770
771 push ds ;AN000; ds-> cs, es-> bds
772 pop es ;AN000;
773 push cs ;AN000;
774 pop ds ;AN000;
775
776 mov cx, BOOT_VOLUME_LABEL_SIZE ;AN000;
777 mov si, offset Boot_Volume_Label;AN000;
778 push di
779 add di, VOLID ;AN000;
780 rep movsb ;AN000;
781 pop di
782 mov cx, BOOT_SYSTEM_ID_SIZE ;AN000; =8
783 mov si, offset Boot_System_ID ;AN000;
784 add di, FILESYS_ID ;AN000;
785 rep movsb ;AN000;
786
787 pop si ;AN000;
788 pop es ;AN000;
789 pop di ;AN000;
790 pop ds ;AN000;
791 pop cx ;AN000;
792 clc ;AN000;
793MMI_Ret: ;AN000;
794 ret ;AN000;
795MMI_Not_Ext: ;AN000;
796 stc ;AN000;
797 ret ;AN000;
798Mov_Media_IDs endp ;AN000;
799
800
801; READ IN THE FAT SECTOR AND GET THE MEDIA BYTE FROM IT.
802; INPUT : AL CONTAINS LOGICAL DRIVE.
803; OUTPUT:
804; CARRY SET IF AN ERROR OCCURS, AX CONTAINS ERROR CODE.
805; OTHERWISE, AH CONTAINS MEDIA BYTE ON EXIT. AL IS PRESERVED.
806
807READFAT PROC NEAR
808 PUSH AX ; PRESERVE LOGICAL DRIVE IN AL
809 MOV DH,0 ; HEAD 0
810 MOV CX,0002 ; CYLINDER 0, SECTOR 2
811 CALL READ_SECTOR ; CS:BX POINTS TO FAT SECTOR
812 JC BAD_FAT_RET
813 POP AX ; RESET LOGICAL DRIVE
814 MOV AH,BYTE PTR CS:[BX] ; MEDIA BYTE
815 RET
816
817BAD_FAT_RET: ; CARRY SET ON ENTRY
818 MESSAGE FTESTDISK,<"ERROR IN FAT READ",CR,LF>
819 POP CX ; CLEAR STACK
820 RET
821READFAT ENDP
822
823; READ A SINGLE SECTOR INTO THE TEMP BUFFER.
824; PERFORM THREE RETRIES IN CASE OF ERROR.
825; INPUTS: DRIVE HAS PHYSICAL DRIVE TO USE
826; CX HAS SECTOR AND CYLINDER
827; DH HAS HEAD
828; OUTPUTS: CARRY CLEAR
829; CS:BX POINT TO SECTOR
830; CARRY SET
831; AX HAS ROM ERROR CODE
832; REGISTERS ES AND BP ARE PRESERVED.
833
834READ_SECTOR PROC NEAR
835 PUBLIC READ_SECTOR
836
837 PUSH BP
838 MOV BP,3 ; MAKE 3 ATTEMPTS
839 PUSH ES
840;SB33015*****************************************************************
841 mov DL, byte ptr ds:[di].DriveNum ;SB;3.30*
842 mov BX, offset DiskSector ; Get ES:BX to point to buffer ;SB;3.30*
843 push CS ; get the segment right ;SB;3.30*
844 pop ES ; now ES:BX is correct ;SB;3.30*
845;SB33015*****************************************************************
846RD_RET:
847;SB33016*****************************************************************
848 mov AX, 0201h ; number of sectors to 1 (AL=1);SB;3.30*
849 int 13h ; call rom-bios disk routines ;SB;3.30*
850
851;SB33016*****************************************************************
852 JNC OKRET2
853Rd_rty:
854 CALL AGAIN ; RESET DISK, DECREMENT BP, PRESERVE AX
855 jz Err_RD_RET
856 test word ptr ds:[di].flags,fNon_Removable
857 JNZ RD_RET
858 cmp cs:[Media_Set_For_Format], 0 ;AN012;
859 jne Rd_Skip1_DPT ;AN012;
860 push ds ;J.K. 11/7/86 For retry, set the head settle time
861 push ax ;to 0Fh. PTM845.
862 lds si,cs:DPT
863 mov al, ds:[si].disk_head_sttl
864 mov cs:[save_head_sttl],al
865 mov byte ptr ds:[si].disk_head_sttl, NormSettle
866 pop ax
867 pop ds
868Rd_Skip1_DPT: ;AN012;
869;SB33017*****************************************************************
870 ; SET CMD TO READ (AH=2) AND ;SB ;3.30
871 MOV AX, 0201h ; NUM OF SECTORS TO 1 (AL=1) ;SB ;3.30
872 INT 13h ; CALL ROM-BIOS DISK ROUTINES ;SB ;3.30
873;SB33017*****************************************************************
874 pushf ;AN012;
875 cmp cs:[Media_Set_For_Format], 0 ;AN012;
876 jne Rd_Skip2_DPT ;AN012;
877 push ds
878 push ax
879 lds si,cs:DPT
880 mov al, cs:[save_head_sttl]
881 mov byte ptr ds:[si].disk_head_sttl, al
882 pop ax
883 pop ds
884Rd_Skip2_DPT: ;AN012;
885 popf ;AN012;
886 jnc OKRET2
887 jmp Rd_rty
888ERR_RD_RET:
889 MOV DL,-1 ; MAKE SURE WE ASK ROM IF MEDIA HAS CHANGED
890 STC ; RETURN ERROR
891; UPDATE INFORMATION PERTAINING TO LAST DRIVE ACCESSED, TIME OF ACCESS, LAST
892; TRACK ACCESSED IN THAT DRIVE.
893OKRET2:
894 MOV CS:[STEP_DRV],DL ; SET UP FOR HEAD SETTLE LOGIC IN DISK.
895 MOV CS:[TIM_DRV],DL ;SAVE DRIVE LAST ACCESSED
896 MOV BYTE PTR [DI].TRACK,CH ; SAVE LAST TRACK ACCESSED ON THIS DRIVE
897 PUSHF ; PRESERVE FLAGS IN CASE ERROR OCCURRED
898 CALL SET_TIM
899 POPF ; RESTORE FLAGS
900 POP ES
901 POP BP
902 RET
903READ_SECTOR ENDP
904
905;-----------------------------------------------------------
906;
907; DISK REMOVABLE ROUTINE ARR 2.41
908;
909
910DSK$REM PROC NEAR ;ARR 2.41
911 PUBLIC DSK$REM
912
913 MESSAGE FTESTDISK,<"DISK REMOVABLE ">
914 MNUM FTESTDISK,AX
915 MESSAGE FTESTDISK,<CR,LF>
916; AL IS UNIT #
917 CALL SETDRIVE ; GET BDS FOR THIS DRIVE
918 TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE
919 JNZ NON_REM
920 JMP EXIT
921
922NON_REM:
923 JMP BUS$EXIT ;ARR 2.41
924DSK$REM ENDP
925
926; SETDRIVE SCANS THROUGH THE DATA STRUCTURE OF BDSS, AND RETURNS A POINTER TO
927; THE ONE THAT BELONGS TO THE DRIVE SPECIFIED. CARRY IS SET IF NONE EXISTS FOR
928; THE DRIVE.
929; IF THE BYTE [PHYS_DRV] IS 0 THEN
930; ON ENTRY, AL CONTAINS THE LOGICAL DRIVE NUMBER.
931; ON EXIT, DS:DI POINTS TO CORRECT BDS FOR THE DRIVE IF CARRY CLEAR.
932
933; ELSE IF THE BYTE [PHYS_DRV] IS 1 THEN (ONLY USED FOR FIXED DISKS WHEN AN ECC
934; ERROR OCCURS)
935; ON ENTRY, DL CONTAINS THE PYHSICAL DRIVE NUMBER.
936; ON EXIT, DS:DI POINTS TO CORRECT BDS FOR THE DRIVE IF CARRY CLEAR.
937
938 PUBLIC SETDRIVE
939SETDRIVE PROC NEAR
940 MESSAGE FTESTDISK,<"SETDRIVE",CR,LF>
941 PUSH BX
942 PUSH CS
943 POP DS
944 ASSUME DS:CODE
945
946; ASSUME FIRST BDS IS IN THIS SEGMENT
947 MOV DI,WORD PTR START_BDS
948SCAN_LOOP:
949 CMP BYTE PTR CS:[PHYS_DRV],1 ; DOES AL HAVE PHYSICAL DRIVE?
950 JB USE_LOGICAL_DRV
951 CMP BYTE PTR [DI].DRIVENUM,AL
952 JE SETDRV
953 JMP SHORT GET_NXT_BDS
954USE_LOGICAL_DRV:
955 CMP BYTE PTR [DI].DRIVELET,AL
956 JE SETDRV
957GET_NXT_BDS:
958 MOV BX,WORD PTR [DI].LINK+2 ; GO TO NEXT BDS
959 MOV DI,WORD PTR [DI].LINK
960 MOV DS,BX
961 ASSUME DS:NOTHING
962
963 CMP DI,-1
964 JNZ SCAN_LOOP
965 STC
966SETDRV:
967 POP BX
968 RET
969SETDRIVE ENDP
970
971;-----------------------------------------------------------
972;
973; DISK I/O ROUTINES
974;
975
976DSK$WRITV PROC NEAR
977 PUBLIC DSK$WRITV
978
979 MESSAGE FTESTDISK,<"DISK WRITE WITH VERIFY ">
980 MNUM FTESTDISK,AX
981 MESSAGE FTESTDISK,<" ">
982 MNUM FTESTDISK,DX
983 MESSAGE FTESTDISK,<" FOR ">
984 MNUM FTESTDISK,CX
985 MESSAGE FTESTDISK,<CR,LF>
986 MOV CS:[WRTVERIFY],103H
987 JMP SHORT DSK$CL
988
989DSK$WRIT:
990 PUBLIC DSK$WRIT
991 MESSAGE FTESTDISK,<"DISK WRITE ">
992 MNUM FTESTDISK,AX
993 MESSAGE FTESTDISK,<" ">
994 MNUM FTESTDISK,DX
995 MESSAGE FTESTDISK,<" FOR ">
996 MNUM FTESTDISK,CX
997 MESSAGE FTESTDISK,<CR,LF>
998 MOV CS:[WRTVERIFY],ROMWRITE
999
1000DSK$CL:
1001 CALL DISKIO
1002DSK$IO:
1003 JC DSKBAD
1004 JMP EXIT
1005DSKBAD:
1006 JMP ERR$CNT
1007DSK$WRITV ENDP
1008
1009DSK$READ PROC NEAR
1010 PUBLIC DSK$READ
1011 MESSAGE FTESTDISK,<"DISK READ ">
1012 MNUM FTESTDISK,AX
1013 MESSAGE FTESTDISK,<" ">
1014 MNUM FTESTDISK,DX
1015 MESSAGE FTESTDISK,<" FOR ">
1016 MNUM FTESTDISK,CX
1017 MESSAGE FTESTDISK,<CR,LF>
1018 CALL DISKRD
1019 JMP DSK$IO
1020DSK$READ ENDP
1021
1022; MISCELLANEOUS ODD JUMP ROUTINES. MOVED OUT OF MAINLINE FOR SPEED.
1023
1024
1025; IF WE HAVE A SYSTEM WHERE WE HAVE VIRTUAL DRIVES, WE NEED TO PROMPT THE
1026; USER TO PLACE THE CORRECT DISK IN THE DRIVE.
1027
1028CHECKSINGLE PROC NEAR
1029 PUBLIC CHECKSINGLE
1030
1031 PUSH AX
1032 PUSH BX
1033 MOV BX,WORD PTR DS:[DI].FLAGS
1034 ; IF HARD DRIVE, CANNOT CHANGE DISK.
1035 ; IF CURRENT OWNER OF PHYSICAL DRIVE, NO NEED TO CHANGE DISKETTE.
1036 TEST BL,FNON_REMOVABLE OR FI_OWN_PHYSICAL
1037 JNZ SINGLERET
1038 TEST BL,FI_AM_MULT ; IS THERE A DRIVE SHARING THIS
1039 ; PHYSICAL DRIVE?
1040 JZ SINGLERET
1041; LOOK FOR THE PREVIOUS OWNER OF THIS PHYSICAL DRIVE AND RESET ITS OWNERSHIP
1042; FLAG.
1043 MOV AL,DS:[DI].DRIVENUM ; GET PHYSICAL DRIVE NUMBER
1044 PUSH DS ; PRESERVE POINTER TO CURRENT BDS
1045 PUSH DI
1046 PUSH CS
1047 POP DS
1048 ASSUME DS:CODE
1049
1050 MOV DI,OFFSET START_BDS
1051SCAN_LIST:
1052 MOV BX,WORD PTR [DI].LINK+2 ; GO TO NEXT BDS
1053 MOV DI,WORD PTR [DI].LINK
1054 MOV DS,BX
1055 ASSUME DS:NOTHING
1056
1057 CMP DI,-1 ; END OF LIST?
1058 JZ SINGLE_ERR_RET ; MUST BE ERROR
1059 CMP BYTE PTR [DI].DRIVENUM,AL
1060 JNZ SCAN_LIST
1061
1062CHECK_OWN:
1063 MOV BX,WORD PTR [DI].FLAGS
1064 TEST BL,FI_OWN_PHYSICAL
1065 JZ SCAN_LIST
1066 XOR BL,FI_OWN_PHYSICAL ; RESET OWNERSHIP FLAG
1067 MOV WORD PTR DS:[DI].FLAGS,BX
1068 POP DI ; RESTORE POINTER TO CURRENT BDS
1069 POP DS
1070 XOR BX,BX
1071 OR BL,FI_OWN_PHYSICAL ; ESTABLISH CURRENT BDS AS OWNER
1072 OR WORD PTR [DI].FLAGS,BX
1073
1074;
1075; WE EXAMINE THE FSETOWNER FLAG. IF IT IS SET, THEN WE ARE USING THE CODE IN
1076; CHECKSINGLE TO JUST SET THE OWNER OF A DRIVE. WE MUST NOT ISSUE THE PROMPT
1077; IN THIS CASE.
1078;
1079 CMP BYTE PTR CS:[FSETOWNER],1
1080 JZ SINGLERET
1081; TO SUPPORT "BACKWARD" COMPATIBILITY WITH IBM'S "SINGLE DRIVE STATUS BYTE"
1082; WE NOW CHECK TO SEE IF WE ARE IN A SINGLE DRIVE SYSTEM AND THE APPLICATION
1083; HAS "CLEVERLY" DIDDLED THE SDSB
1084 CMP CS:[SINGLE],2 ; IF (SINGLE_DRIVE_SYSTEM)
1085 JNE SHORT IGNORE_SDSB
1086
1087 SAVEREG <DS,DI,AX> ; THEN
1088 MOV AL,DS:[DI].DRIVELET ; IF (CURR_DRV == REQ_DRV)
1089 MOV AH,AL
1090 XOR DI,DI
1091 MOV DS,DI
1092 XCHG AL,DS:BYTE PTR LSTDRV ; THEN SWAP(CURR_DRV,REQ_DRV)
1093 CMP AH,AL ; ELSE
1094 RESTOREREG <AX,DI,DS> ; SWAP(CURR_DRV,REQ_DRV)
1095 JE SINGLERET ; ISSUE SWAP_DSK_MSG
1096
1097IGNORE_SDSB:
1098 CALL SWPDSK ; ASK USER FOR CORRECT DISK
1099SINGLERET:
1100 POP BX
1101 POP AX
1102 RET
1103
1104SINGLE_ERR_RET:
1105 STC
1106 POP DI ; RESTORE CURRENT BDS
1107 POP DS
1108 JMP SHORT SINGLERET
1109
1110BADDRIVE:
1111 MOV AL,8 ;Sector not found
1112 jmp short BadDrive_Ret ;AN004;AN005;AN006;
1113UnformattedDrive: ;AN004;AN005;AN006;
1114 mov al,7 ;AN004;Unknown media;AN005;AN006;
1115BadDrive_Ret:
1116 STC
1117IORET: RET
1118
1119BOGUSSETTLE:
1120 MOV AL,NORMSETTLE ; SOMEONE HAS DIDDLED THE SETTLE
1121 JMP GOTSLOWSETTLE
1122CHECKSINGLE ENDP
1123;------------------------------------------------------------
1124;
1125; DISK I/O HANDLER
1126;
1127; AL = DRIVE NUMBER (0-6)
1128; AH = MEDIA DESCRIPTOR
1129; CX = SECTOR COUNT
1130; DX = FIRST SECTOR (low)
1131; [Start_Sec_H] = FIRST SECTOR (high) ;J.K. 32 bit calculation.
1132; DS = CS
1133; ES:DI = TRANSFER ADDRESS
1134; [RFLAG]=OPERATION (2=READ, 3=WRITE)
1135; [VERIFY]=1 FOR VERIFY AFTER WRITE
1136;
1137; IF SUCCESSFUL CARRY FLAG = 0
1138; ELSE CF=1 AND AL CONTAINS ERROR CODE
1139;
1140 PUBLIC DISKRD
1141DISKRD PROC NEAR
1142 MOV CS:[RFLAG],ROMREAD
1143
1144DISKIO:
1145 MOV BX,DI ; ES:BX = TRANSFER ADDRESS
1146 CALL SETDRIVE ; MAP LOGICAL AND PHYSICAL
1147 MOV AL,BYTE PTR DS:[DI].MEDIAD
1148 MOV CS:MEDBYT,AL ; PRESERVE MEDIA BYTE FOR DRIVE FOR USE
1149 ; IN DETERMINING MEDIA CHANGE.
1150 JCXZ IORET
1151;SB34DISK006******************************************************************
1152;SB See if the Media is formatted or not by checking the flags field in
1153;SB in the BDS. If it is unformatted we cannot allow I/O, so we should
1154;SB go to the error exit at label UnformattedDrive. 2LOCS
1155
1156 test word ptr ds:[di].FLAGS, UNFORMATTED_MEDIA
1157 jnz UnformattedDrive
1158;SB34DISK006******************************************************************
1159 mov cs:[SECCNT],CX ;save sector count
1160 MOV CS:[SPSAV],SP ; SAVE SP
1161
1162; ENSURE THAT WE ARE TRYING TO ACCESS VALID SECTORS ON THE DRIVE
1163;
1164
1165 mov ax,dx ;AN000; save DX to AX
1166 xor si,si ;AN000;
1167 add dx,cx ;AN000;
1168 adc si,0 ;AN000;
1169 cmp [di].DrvLim, 0 ;AN000; Is this drive > 32 bit sector ?
1170 je Sanity32 ;AN000;
1171 cmp si,0 ;AN000;
1172 jne BADDRIVE ;AN000;
1173 cmp dx, [di].DrvLim ;AN000;
1174 ja BADDRIVE ;AN000;
1175 jmp short SanityOK ;AN000;
1176Sanity32: ;AN000;
1177 add si, cs:[Start_Sec_H] ;AN000;
1178 cmp si, [di].DrvLim_H ;AN000;
1179 jb SanityOK ;AN000;
1180 ja BADDRIVE ;AN000;
1181 cmp dx, [di].DrvLim_L ;AN000;
1182 ja BADDRIVE ;AN000;
1183SanityOK: ;AN000;
1184 mov dx,cs:[Start_Sec_H] ;AN000;
1185 add ax,word ptr [di].HIDSEC_L ;AN000;
1186 adc dx,word ptr [di].Hidsec_H ;AN000;
1187;J.K. Now DX;AX have the physical first sector.
1188;Since the following procedures is going to destroy AX, let's
1189;save it temporarily to SAVED_WORD.
1190 mov cs:[Saved_Word], ax ;AN000; Save the sector number (low)
1191
1192; MOV SI,DX
1193; ADD SI,CX
1194; ADD DX,WORD PTR [DI].HIDSEC ; ADD IN THE HIDDEN SECTORS
1195; CMP SI,WORD PTR [DI].DRVLIM ; COMPARE AGAINST DRIVE MAX
1196; JA BADDRIVE
1197
1198; SET UP POINTER TO DISK BASE TABLE IN [DPT]. WE CANNOT ASSUME THAT IOSETUP
1199; WILL DO IT BECAUSE WE WILL SKIP THE SET UP STUFF WITH HARD DISKS.
1200 PUSH DS
1201 XOR AX,AX
1202 MOV DS,AX
1203 LDS SI,DWORD PTR DS:[DSKADR]; CURRENT DISK PARM TABLE
1204 MOV WORD PTR CS:DPT,SI
1205 MOV WORD PTR CS:DPT+2,DS
1206 POP DS
1207 TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE
1208 JNZ SKIP_SETUP
1209 CALL CHECKSINGLE
1210;
1211; CHECK TO SEE IF WE HAVE PREVIOUSLY NOTED A CHANGE LINE. THE ROUTINE
1212; RETURNS IF EVERYTHING IS OK. OTHERWISE, IT POPS OFF THE STACK AND RETURNS
1213; THE PROPER ERROR CODE.
1214;
1215;----------------------------------------|
1216; WARNING: DO NOT CHANGE THE FOLLOWING. ;|
1217; IT GETS PATCHED IN MSINIT ;|
1218 PUBLIC DISKIO_PATCH ;|
1219DISKIO_PATCH: ;|
1220 CALL CHECKLATCHIO ;|
1221;----------------------------------------|
1222;
1223; SET UP TABLES AND VARIABLES FOR I/O
1224 CALL IOSETUP
1225;
1226; NOW THE SETTLE VALUES ARE CORRECT FOR THE FOLLOWING CODE
1227;
1228SKIP_SETUP:
1229;J.K. 32 bit sector calculation.
1230; DX;[Saved_Word] = starting sector number.
1231 mov ax,dx ;AN000;
1232 xor dx,dx ;AN000;
1233 DIV WORD PTR [DI].SECLIM ;DIVIDE BY SEC PER TRACK
1234 mov cs:[Temp_H],ax ;AN000;
1235 mov ax, cs:[Saved_Word] ;AN000; Restore the lower word
1236 div word ptr [di].SecLim ;AN000;
1237;Now, [Temp_H],AX = track #, DX = sector
1238 INC DL ;Sector number is 1 based.
1239 MOV CS:[CURSEC],DL ;SAVE CURRENT SECTOR
1240 MOV CX,WORD PTR [DI].HDLIM ;GET NUMBER OF HEADS
1241
1242 push ax ;AN000;
1243 XOR DX,DX ;DIVIDE TRACKS BY HEADS PER CYLINDER
1244 mov ax, cs:[Temp_H] ;AN000;
1245 DIV CX
1246 mov cs:[Temp_H],ax ;AN000;
1247 pop ax ;AN000;
1248 div cx ;AN000;
1249;Now, [Temp_H],AX = cyliner #, DX = head
1250 cmp cs:[Temp_H],0 ;AN000;
1251 ja BADDRIVE_brdg ;AN000;
1252 cmp AX, 1024 ;AN000; 2**10 currently maxium for track #.
1253 ja BADDRIVE_brdg ;AN000;
1254 MOV CS:[CURHD],DL ;SAVE CURRENT HEAD
1255 MOV CS:[CURTRK],AX ;SAVE CURRENT TRACK
1256
1257;
1258; WE ARE NOW SET UP FOR THE I/O. NORMALLY, WE CONSIDER THE DMA BOUNDARY
1259; VIOLATIONS HERE. NOT TRUE. WE PERFORM THE OPERATION AS IF EVERYTHING IS
1260; SYMMETRIC; LET THE INT 13 HANDLER WORRY ABOUT THE DMA VIOLATIONS.
1261;
1262 MOV AX, CS:[SECCNT]
1263 CALL BLOCK
1264 CALL DONE
1265 RET
1266DISKRD ENDP
1267
1268;
1269BADDRIVE_Brdg:jmp Baddrive
1270;
1271
1272; SET THE DRIVE-LAST-ACCESSED FLAG FOR DISKETTE ONLY. WE KNOW THAT THE HARD
1273; DISK WILL NOT BE REMOVED.
1274; DS:DI -> CURRENT BDS.
1275; AX,CX,SI ARE DESTROYED.
1276;
1277 PUBLIC IOSETUP
1278IOSETUP PROC NEAR
1279 MOV AL,[DI].DRIVENUM
1280 MOV CS:[TIM_DRV],AL ; SAVE DRIVE LETTER
1281;
1282; DETERMINE PROPER HEAD SETTLE VALUES
1283;
1284 cmp cs:[Media_Set_For_Format], 0 ;AN012;
1285 jne Skip_DPT_Setting ;AN012;
1286 MOV CX,DS
1287 LDS SI,DWORD PTR CS:[DPT] ; GET POINTER TO DISK BASE TABLE
1288 MOV AL,CS:[EOT]
1289 MOV [SI].DISK_EOT,AL ; BUMP FOR US
1290 MOV AL,[SI].DISK_MOTOR_STRT ; PRESERVE OLD MOTOR START TIME
1291 MOV CS:MOTORSTARTUP,AL
1292;
1293; FOR 3.5" DRIVES, BOTH EXTERNAL AS WELL AS ON THE K09, WE NEED TO SET THE
1294; MOTOR START TIME TO 4. THIS CHECKING FOR EVERY I/O IS GOING TO AFFECT
1295; PERFORMANCE ACROSS THE BOARD, BUT IS NECESSARY!! - RS
1296;
1297 PUSH ES
1298 MOV ES,CX ; ES:DI -> TO CURRENT BDS
1299 CMP BYTE PTR ES:[DI].FORMFACTOR,FFSMALL
1300 JNZ MOTOR_START_OK
1301 MOV AL,4
1302 XCHG AL,[SI].DISK_MOTOR_STRT
1303MOTOR_START_OK:
1304 POP ES
1305;
1306; DS:SI NOW POINTS TO DISK PARAMETER TABLE. GET CURRENT SETTLE AND SET FAST
1307; SETTLE
1308;
1309 XOR AL,AL
1310 INC AL ; IBM WANTS FAST SETTLE TO BE 1 - RS.
1311 XCHG AL,[SI].DISK_HEAD_STTL ; GET SETTLE AND SET UP FOR FAST
1312 MOV CS:SETTLECURRENT,AL
1313 MOV AL,NORMSETTLE ; SOMEONE HAS DIDDLED THE SETTLE
1314GOTSLOWSETTLE:
1315 MOV DS,CX
1316 MOV CS:SETTLESLOW,AL
1317Skip_DPT_Setting: ;AN012;
1318 RET
1319;
1320; SET TIME OF LAST ACCESS, AND RESET DEFAULT VALUES IN THE DPT.
1321;
1322DONE:
1323 TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE
1324 JNZ RETZ ; DO NOT SET FOR NON-REMOVABLE MEDIA
1325 CALL SET_TIM ; SET TIME OF LAST ACCESS FOR DRIVE
1326;
1327; RESTORE HEAD SETTLE AND EOT VALUES
1328;
1329DIDDLEBACK:
1330 pushf ;AN013;Save flag
1331 cmp cs:[Media_Set_For_Format], 0 ;AN012;
1332 jne NoDiddleBack ;AN012;
1333 PUSH AX
1334 MOV DX,DS
1335 MOV AL,CS:SETTLECURRENT
1336 MOV AH,CS:MOTORSTARTUP
1337 LDS SI,CS:DPT
1338; MOV [SI].DISK_EOT,9 ;J.K. 4/25/86. Should not change the EOT value
1339 ;of diskbase to 9. This cause a problem
1340 ;with 1.44M diskette in Polaris when the user
1341 ;issue INT 13 with the default system
1342 ;diskbase.
1343 mov [si].DISK_EOT,9 ;J.K. 11/5/86. For compatibility reason, return
1344 ;back to set it to 9 ( PTM826 ).
1345 MOV [SI].DISK_HEAD_STTL,AL
1346 MOV [SI].DISK_SECTOR_SIZ,2
1347 MOV [SI].DISK_MOTOR_STRT,AH
1348 MOV DS,DX
1349 POP AX
1350NoDiddleBack: ;AN013;
1351 popf ;AN013;Restore flag
1352RETZ:
1353 RET
1354
1355;READ THE NUMBER OF SECTORS SPECIFIED IN AX, HANDLING TRACK BOUNDARIES
1356;DS:DI -> BDS FOR THIS DRIVE
1357BLOCK:
1358 OR AX,AX ;SEE IF ANY SECTORS TO READ
1359 JZ RETZ
1360;Fixed disk will not be restricted to the track-by-track basis. -J.K.4/10/86
1361 test word ptr [di].Flags, fNon_Removable ;J.K. Fixed disk?
1362 jz BLOCK_FLOPPY ;J.K.
1363;SB34DISK002*****************************************************************
1364;SB Check to see if multi track operation is allowed. If not
1365;SB we have to go to the block_floppy below to break up the operation.
1366;SB 2 LOCS
1367 test word ptr CS:MulTrk_Flag, MulTrk_ON
1368 jz BLOCK_FLOPPY
1369;SB34DISK002*****************************************************************
1370 call DISK ;J.K.
1371 xor ax,ax
1372 RET ;J.K.
1373BLOCK_FLOPPY: ;J.K.4/10/86
1374;
1375; READ AT MOST 1 TRACK WORTH. PERFORM MINIMIZATION AT SECTOR / TRACK
1376;
1377 MOV CL,BYTE PTR [DI].SECLIM
1378 INC CL
1379 SUB CL,CS:CURSEC ; LEEAC 3.20 ADD SEGMENT OVERRIDE
1380 XOR CH,CH
1381 CMP AX,CX
1382 JAE GOTMIN
1383 MOV CX,AX
1384GOTMIN:
1385;
1386; AX IS THE REQUESTED NUMBER OF SECTORS TO READ
1387; CX IS THE NUMBER THAT WE CAN DO ON THIS TRACK
1388;
1389 PUSH AX
1390 PUSH CX
1391 MOV AX,CX ; AL IS NUMBER OF SECTORS TO READ
1392 CALL DISK
1393 POP CX
1394 POP AX
1395;
1396; CX IS THE NUMBER OF SECTORS JUST TRANSFERRED
1397;
1398 SUB AX,CX ; REDUCE SECTORS-REMAINING BY LAST I/O
1399 SHL CL,1
1400 ADD BH,CL ; ADJUST TRANSFER ADDRESS
1401 JMP BLOCK
1402IOSETUP ENDP
1403
1404DskErr_Brdg: jmp DskErr ;AN003;
1405
1406;
1407;PERFORM DISK I/O WITH RETRIES
1408; AL = NUMBER OF SECTORS (1-8, ALL ON ONE TRACK)
1409; DI POINT TO DRIVE PARAMETERS
1410; ES:BX = TRANSFER ADDRESS (MUST NOT CROSS A 64K PHYSICAL BOUNDARY)
1411; [RFLAG] = 2 IF READ, 3 IF WRITE
1412; [VERIFY] = 0 FOR NORMAL, 1 FOR VERIFY AFTER WRITE
1413
1414 PUBLIC DISK
1415DISK PROC NEAR
1416 MOV BP,MAXERR ; SET UP RETRY COUNT
1417 mov cs:VRetry_Cnt, BP ;AN003;Verify op. retry cnt for Write-Verify.
1418 mov cs:Soft_ECC_Cnt, BP ;AN003;Soft ECC error retry count.
1419 MOV AH,CS:RFLAG ;GET READ/WRITE INDICATOR
1420
1421RETRY:
1422 PUSH AX
1423
1424 MOV DX,CS:[CURTRK] ;LOAD CURRENT CYLINDER
1425
1426 test word ptr [di].FLAGS, fNon_Removable ;Fixed disk? - J.K. 4/7/86
1427 jz DISK_NOT_MINI ;no, skip this. - J.K. 4/7/86
1428 cmp [di].IsMini, 1 ;Is this a mini disk? - J.K. 4/7/86
1429 jnz DISK_NOT_MINI ;No. continue to next.- J.K. 4/7/86
1430 add dx, [di].Hidden_Trks ;else add hidden trks.- J.K. 4/7/86
1431DISK_NOT_MINI: ;J.K. 4/7/86
1432 ROR DH,1
1433 ROR DH,1
1434
1435 OR DH,CS:[CURSEC]
1436 MOV CX,DX
1437 XCHG CH,CL ; CL = SECTOR, CH = CYLINDER
1438 MOV DH,BYTE PTR CS:[CURHD] ; LOAD CURRENT HEAD NUMBER AND
1439 MOV DL,BYTE PTR [DI].DRIVENUM ; PHYSICAL DRIVE NUMBER
1440 CMP BYTE PTR [DI].FORMFACTOR,FFHARDFILE
1441 JZ DO_FAST ; HARD FILES USE FAST SPEED
1442; IF WE HAVE [STEP_DRV] SET TO -1, WE USE THE SLOW SETTLE TIME.
1443; THIS HELPS WHEN WE HAVE JUST DONE A RESED DISK OPERATION AND THE HEAD HAS
1444; BEEN MOVED TO ANOTHER CYLINDER - THE PROBLEM CROPS UP WITH 3.5" DRIVES.
1445 CMP CS:[STEP_DRV],-1
1446 JZ DO_WRITEJ
1447 CMP AH,ROMREAD ; ARR 2.20
1448 JE DO_FAST
1449 CMP AH, ROMVERIFY
1450 JE DO_FAST
1451DO_WRITEJ:
1452; READS ALWAYS FAST, UNLESS WE HAVE JUST DONE A DISK RESET OPERATION
1453 JMP DO_WRITE ; ARR 2.20 READS ALWAYS FAST
1454DO_FAST: ; ARR 2.20
1455 CALL FASTSPEED ; MZ 2.21 CHANGE SETTLE MODE
1456TESTERR: ; MZ 2.21
1457 JC DSKERR_brdg
1458; SET DRIVE AND TRACK OF LAST ACCESS
1459 MOV CS:[STEP_DRV],DL ; ARR 2.20 SET DRIVE
1460 MOV BYTE PTR [DI].TRACK,CH ; ARR 2.20 SAVE TRACK
1461NO_SET:
1462 CMP CS:WRTVERIFY,103H ; CHECK FOR WRITE AND VERIFY
1463 JZ DOVERIFY
1464NOVERIFY:
1465 POP AX
1466
1467;SB34DISK003*****************************************************************
1468;SB Check the flags word in the BDS to see if the drive is non removable
1469;SB If not we needn't do anything special
1470;SB If it is a hard disk then check to see if multi-track operation
1471;SB is specified. If specified we don't have to calculate for the next
1472;SB track since we are already done. So we can go to the exit of this
1473;SB routine. 5 LOCS
1474
1475 test word ptr [di].FLAGS, fNON_REMOVABLE
1476 jz ITS_REMOVABLE
1477 test CS:MulTrk_Flag, MulTrk_ON
1478 jnz DISK_RET
1479ITS_REMOVABLE:
1480;SB34DISK003*****************************************************************
1481 AND CL,03FH ; ELIMINATE CYLINDER BITS FROM SECTOR
1482 XOR AH,AH
1483 SUB CS:[SECCNT],AX ; REDUCE COUNT OF SECTORS TO GO
1484 ADD CL,AL ; NEXT SECTOR
1485 MOV CS:[CURSEC],CL
1486 CMP CL,BYTE PTR [DI].SECLIM ; SEE IF SECTOR/TRACK LIMIT REACHED
1487 JBE DISK_RET
1488NEXTTRACK:
1489 MOV CS:[CURSEC],1 ; START WITH FIRST SECTOR OF NEXT TRACK
1490 MOV DH,CS:[CURHD]
1491 INC DH
1492 CMP DH,BYTE PTR [DI].HDLIM
1493 JB NOXOR
1494 XOR DH,DH
1495 INC CS:[CURTRK] ;NEXT TRACK
1496NOXOR:
1497 MOV CS:[CURHD],DH
1498DISK_RET:
1499 CLC ; LEEAC
1500 RET
1501DISK ENDP
1502
1503
1504; THE REQUEST IS FOR WRITE. DETERMINE IF WE ARE TALKING ABOUT THE SAME
1505; TRACK AND DRIVE. IF SO, USE THE FAST SPEED.
1506
1507DO_WRITE PROC NEAR
1508 CMP DL,CS:[STEP_DRV] ; ARR 2.20
1509 JNZ DO_NORM ; WE HAVE CHANGED DRIVES
1510
1511 CMP CH,BYTE PTR [DI].TRACK ; ARR 2.20
1512 JZ DO_FAST ; WE ARE STILL ON THE SAME TRACK
1513
1514DO_NORM:
1515 CALL NORMSPEED
1516 JMP SHORT TESTERR ; MZ 2.21 TEST FOR ERROR
1517DO_WRITE ENDP
1518;
1519; WE HAVE A VERIFY REQUEST ALSO. GET STATE INFO AND GO VERIFY
1520;
1521
1522DOVERIFY PROC NEAR
1523 POP AX ; RESTORE SECTOR COUNT
1524 PUSH AX
1525 MOV AH,ROMVERIFY ; REQUEST VERIFY
1526 CALL FASTSPEED ; MZ 2.21 CHANGE SETTLE MODE
1527 JNC NOVERIFY
1528
1529;SB34DISK004**************************************************************
1530;SB check the error returned in AH to see if it is a SOFT ECC error.
1531;SB If it is not we needn't do anything special. If it is a SOFT
1532;SB ECC error then decrement the SOFT_ECC_CNT error retry count. If
1533;SB this retry count becomes 0 then we just ignore the error and go to
1534;SB No_verify but if we can still try then we call the routine to reset
1535;SB the disk and go to DSKerr1 to retry the operation. 6 LOCS
1536
1537 cmp ah,11h ;SOFT ECC error ?
1538 jnz Not_SoftECC_Err
1539 dec SOFT_ECC_CNT
1540 jz NoVerify ;no more retry
1541 call ResetDisk ;reset disk
1542 jmp DskErr1 ;retry
1543
1544;SB34DISK004**************************************************************
1545
1546Not_SoftECC_Err: ;AN003;Other error.
1547 call ResetDisk ;AN003;
1548 dec VRetry_Cnt ;AN003;
1549 jmp DskErr0 ;AN003;
1550DOVERIFY ENDP
1551;
1552; NEED TO SPECIAL CASE THE CHANGE-LINE ERROR AH=06H. IF WE GET THIS, WE
1553; NEED TO RETURN IT.
1554;
1555;----------------------------------------|
1556; WARNING: DO NOT CHANGE THE FOLLOWING. ;|
1557; IT GETS PATCHED IN MSINIT ;|
1558 PUBLIC DSKERR ;|
1559DSKERR PROC NEAR ;|
1560 CALL CHECKIO ;|
1561;---------------------------------------;|
1562
1563 cmp cs:MultiTrk_Format_Flag, 1 ;AN007;Multi trk format request?
1564 jne DoChkAgain ;AN007;
1565 mov bp, 1 ;AN007;No more retry.
1566 mov cs:MultiTrk_Format_Flag, 0 ;AN007;Clear the flag.
1567DoChkAgain: ;AN007;
1568 CALL AGAIN
1569DskErr0: ;AN003;
1570 JZ HARDERR
1571 test word ptr [di].FLAGS, fNon_Removable ;AN009;
1572 jnz Skip_TimeOut_Chk ;AN009;
1573 CMP AH,80H ;TIMEOUT?
1574 JZ HARDERR ;***
1575Skip_TimeOut_Chk: ;AN009;
1576 cmp ah, 0cch ;AN003;Write Fault error?
1577 jz Write_Fault_Err ;AN003; Then, don't retry.
1578 mov cs:Soft_ECC_Cnt, MAXERR ;AN003;Set Soft_ECC_Cnt back to MAXERR
1579DSKERR1:
1580 POP AX ;RESTORE SECTOR COUNT
1581 JMP RETRY
1582
1583Write_Fault_Err: ;AN003;
1584 mov bp, 1 ;AN003;Just retry only once for Write Fault error.
1585 jmp DskErr1 ;AN003;
1586
1587HARDERR:
1588 PUBLIC HARDERR
1589
1590 CALL MAPERROR
1591
1592HARDERR2: ; FOR ROUTINES THAT CALL MAPERROR THEMSELVES
1593 PUBLIC HARDERR2
1594
1595 MOV CS:[TIM_DRV],-1 ;FORCE A MEDIA CHECK THROUGH ROM
1596 MOV CX,CS:SECCNT ;GET COUNT OF SECTORS TO GO
1597 MOV SP,CS:[SPSAV] ;RECOVER ENTRY STACK POINTER
1598;
1599; SINCE WE ARE PERFORMING A NON-LOCAL GOTO, RESTORE THE DISK PARAMETERS
1600;
1601MEDBYT_OK:
1602 CALL DIDDLEBACK
1603 RET ;AND RETURN
1604DSKERR ENDP
1605
1606;
1607; CHANGE SETTLE VALUE FROM SETTLECURRENT TO WHATEVER IS APPROPRIATE
1608; NOTE THAT THIS ROUTINE IS NEVER CALLED FOR A FIXED DISK.
1609;
1610NORMSPEED PROC NEAR
1611 cmp cs:[Media_Set_For_Format], 0 ;AN012;
1612 jne FASTSPEED ;AN012;
1613 PUSH DS
1614 PUSH AX
1615 MOV AL,CS:SETTLESLOW
1616 LDS SI,CS:DPT ; CURRENT DISK PARM TABLE
1617 MOV [SI].DISK_HEAD_STTL,AL
1618 POP AX
1619 POP DS
1620 CALL FASTSPEED
1621 PUSH DS
1622 LDS SI,CS:DPT
1623 MOV [SI].DISK_HEAD_STTL,1 ; 1 IS FAST SETTLE VALUE
1624 POP DS
1625 RET
1626NORMSPEED ENDP
1627
1628FASTSPEED PROC NEAR
1629;
1630; IF THE DRIVE HAS BEEN MARKED AS TOO BIG (I.E. STARTING SECTOR OF THE
1631; PARTITION IS > 16 BITS, THEN ALWAYS RETURN DRIVE NOT READY.
1632;
1633 TEST BYTE PTR [DI].FATSIZ,FTOOBIG
1634 IF iTEST
1635 JZ READY
1636 JMP NOTREADY
1637READY:
1638 ELSE
1639 JNZ NOTREADY
1640 ENDIF
1641
1642 MESSAGE FTESTINIT,<"<">
1643 MNUM FTESTINIT,AX
1644 MESSAGE FTESTINIT,<",">
1645 MNUM FTESTINIT,ES
1646 MESSAGE FTESTINIT,<":">
1647 MNUM FTESTINIT
1648 MESSAGE FTESTINIT,<",">
1649 MNUM FTESTINIT,CX
1650 MESSAGE FTESTINIT,<",">
1651 MNUM FTESTINIT,DX
1652 MESSAGE FTESTINIT,<">">
1653 INT 13H
1654DEATH:
1655 RET
1656NOTREADY:
1657 STC
1658 MOV AH,80H
1659 JMP DEATH
1660FASTSPEED ENDP
1661
1662; MAP ERROR RETURNED BY ROM IN AH INTO CORRESPONDING CODE TO BE RETURNED TO
1663; DOS IN AL.
1664;
1665MAPERROR PROC NEAR
1666 PUBLIC MAPERROR
1667
1668 PUSH CX ; SAVE CX
1669 PUSH CS
1670 POP ES ;MAKE ES THE LOCAL SEGMENT
1671 MOV AL,AH ;PUT ERROR CODE IN AL
1672 MOV CS:[LSTERR],AL ;TERMINATE LIST WITH ERROR CODE
1673 MOV CX,NUMERR ;NUMBER OF POSSIBLE ERROR CONDITIONS
1674 MOV DI,OFFSET ERRIN ;POINT TO ERROR CONDITIONS
1675 REPNE SCASB
1676 MOV AL,CS:[DI + NUMERR - 1] ;GET TRANSLATION
1677 POP CX ; RESTORE CX
1678 STC ;FLAG ERROR CONDITION
1679 RET
1680MAPERROR ENDP
1681
1682; SET THE TIME OF LAST ACCESS FOR THIS DRIVE. THIS IS DONE ONLY FOR REMOVABLE
1683; MEDIA.
1684
1685 PUBLIC SET_TIM
1686SET_TIM PROC NEAR
1687 PUSH AX
1688;SB33018******************************************************************
1689 xor AH, AH ; set command to get time ;SB;3.30*
1690 int 1Ah ; call rom-bios timer function ;SB;3.30*
1691;SB33018******************************************************************
1692 OR AL,AL
1693 JZ NOROLL3
1694 INC CS:[DAYCNT] ; CATCH ROLLOVER
1695NOROLL3:
1696; WE HAVE THE NEW TIME. IF WE SEE THAT THE TIME HAS PASSED, THEN WE RESET
1697; THE THRESHOLD COUNTER...
1698 CMP DX,WORD PTR [DI].TIM_LO
1699 JNZ SETACCESS
1700 CMP CX,WORD PTR [DI].TIM_HI
1701 JZ DONE_SET
1702SETACCESS:
1703 MOV BYTE PTR CS:[ACCESSCOUNT],0
1704 MOV WORD PTR [DI].TIM_LO,DX ;SAVE IT
1705 MOV WORD PTR [DI].TIM_HI,CX
1706DONE_SET:
1707 CLC
1708 POP AX
1709 RET
1710SET_TIM ENDP
1711
1712 ASSUME CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING
1713
1714;
1715; THIS IS THE TRUE INT 13 HANDLER. WE PARSE THE REQUEST TO SEE IF THERE IS
1716; A DMA VIOLATION. IF SO, DEPENDING ON THE FUNCTION, WE:
1717; READ/WRITE BREAK THE REQUEST INTO THREE PIECES AND MOVE THE MIDDLE ONE
1718; INTO OUR INTERNAL BUFFER.
1719; FORMAT COPY THE FORMAT TABLE INTO THE BUFFER
1720; VERIFY POINT THE TRANSFER ADDRESS INTO THE BUFFER
1721;
1722; THIS IS THE BIGGEST BOGOSITY OF ALL. THE IBM CONTROLLER DOES NOT HANDLE
1723; OPERATIONS THAT CROSS PHYSICAL 64K BOUNDARIES. IN THESE CASES, WE COPY
1724; THE OFFENDING SECTOR INTO THE BUFFER BELOW AND DO THE I/O FROM THERE.
1725;
1726INT13FRAME STRUC
1727OLDBP DW ?
1728OLDAX DW ?
1729OLDBX DW ?
1730OLDCX DW ?
1731OLDDX DW ?
1732OLDDD DD ?
1733OLDF DW ?
1734INT13FRAME ENDS
1735
1736;J.K. 1/30/87 To handle the ps2_30 machine INT 13h, AH = 8 Problem.
1737;Save Registers here.
1738Save_AX DW ?
1739Save_BX DW ?
1740Save_CX DW ?
1741Save_DX DW ?
1742Save_DI DW ?
1743Save_SI DW ?
1744Save_BP DW ?
1745Save_DS DW ?
1746Save_ES DW ?
1747Prev_DX DW ?
1748Save_Flag DW ?
1749
1750
1751; ENTRY CONDITIONS:
1752; AH = FUNCTION
1753; AL = NUMBER OF SECTORS
1754; ES:BX = DMA ADDRESS
1755; CX = PACKED TRACK AND SECTOR
1756; DX = HEAD AND DRIVE
1757; OUTPUT CONDITIONS:
1758; NO DMA VIOLATION.
1759;
1760 PUBLIC BLOCK13
1761BLOCK13 PROC FAR
1762;
1763; LET THE OPPERATION PROCEED. IF THERE IS A DMA VIOLATION, THEN WE DO THINGS.
1764;
1765 MOV CS:PREVOPER,AX ; SAVE REQUEST
1766 PUSHF
1767 CMP AH,ROMFORMAT
1768 JNZ NOT_FORMAT
1769; SET CHANGED BY FORMAT BIT FOR ALL LOGICAL DRIVES USING THIS PHYSICAL DRIVE
1770;---------------------------------------------------------|
1771; WARNING: DO NOT CHANGE THE FOLLOWING.
1772; IT GETS PATCHED IN AT INIT TIME |
1773 PUBLIC CHANGED_PATCH
1774CHANGED_PATCH:
1775 MOV WORD PTR CS:[FLAGBITS],FCHANGED_BY_FORMAT+FCHANGED
1776 CALL SET_CHANGED_DL ; INDICATE THAT MEDIA CHANGED BY FORMAT
1777; |
1778;---------------------------------------------------------|
1779NOT_FORMAT:
1780 test dl, 80h ; floppy or hard disk?
1781 jnz not_floppy ; if hard, skip this nonsense
1782 cmp cs:EC35_Flag, 0 ; any electrically compat. drives?
1783 jz not_floppy ; no; proceed unhindered
1784 SAVEREG <ax, bx, cx>
1785 mov cl, dl ; turn drive number into bit map:
1786 mov al, 1 ; assume drive 0
1787 shl al, cl ; shift over correct number of times
1788 test al, cs:EC35_Flag ; is THIS drive an electrically compatible 3.5 incher?
1789 jz not_EC35 ; no; don't change anything
1790 mov bl, dl ; which drive was it?
1791 xor bh, bh ; need only one byte of index
1792 push es ; need a segment register
1793 mov ax, 40h ; the machine state byte is in the...
1794 mov es, ax ; ...segment at 40h
1795 mov byte ptr es:[90h+bx], 93H ; establish drive type as: (360k disk in 360k drive, no double-stepping, 250 kbs transfer rate)
1796 pop es ; fix up register again
1797not_EC35:
1798 RESTOREREG <cx, bx, ax>
1799not_floppy:
1800 cmp cs:[model_byte], mdl_ps2_30 ; is this a ps2/30?
1801 jne not_ps2_30 ; if not, just do normal call
1802 cmp ah, 8 ;J.K. 1/30/87 Read Driver Parm ?
1803 je ps2_30_Problem ;J.K. 1/30/87
1804 cmp ah, 15h
1805 je ps2_30_Problem
1806not_ps2_30:
1807 CALL ORIG13 ; SIMULATE INT 13
1808 JC GOTERR13_br ; ERROR?
1809 RET 2 ; NO, RETURN AND CLEAR FLAGS
1810
1811GOTERR13_br: jmp Goterr13
1812
1813;J.K.1/30/87 ps2_30 machine has some problem with AH=8h(Read Drive Parm), Int 13h.
1814;This function does not reset the common buses after the execution.
1815;To solve this problem, when we detect AH=8h, then we will save the result and
1816;will issue AH=1 (Read Status) call to reset the buses.
1817
1818ps2_30_Problem: ;J.K. 1/30/87; ps2_30 = PS2 Model 30.
1819 mov cs:Prev_DX, DX ;save orignal drive number
1820 call Orig13 ;Do "Read drive parm"
1821
1822 mov cs:Save_AX, AX ;Save registers,flag
1823 mov cs:Save_BX, BX
1824 mov cs:Save_CX, CX
1825 mov cs:Save_DX, DX
1826 mov cs:Save_DI, DI
1827 mov cs:Save_SI, SI
1828 mov cs:Save_BP, BP
1829 mov cs:Save_DS, DS
1830 mov cs:Save_ES, ES
1831 pushf
1832 pop cs:Save_Flag
1833
1834 mov dx, cs:Prev_DX ;restore orignal drive
1835 pushf
1836 mov ah, 1 ;Read Status.
1837 call Orig13 ;Reset the bus as a side effect of this call.
1838
1839 mov AX, cs:Save_AX ;restore registers,flag
1840 mov BX, cs:Save_BX
1841 mov CX, cs:Save_CX
1842 mov DX, cs:Save_DX
1843 mov DI, cs:Save_DI
1844 mov SI, cs:Save_SI
1845 mov BP, cs:Save_BP
1846 mov DS, cs:Save_DS
1847 mov ES, cs:Save_ES
1848 push cs:Save_Flag
1849 popf
1850 jc GotErr13 ;AH=8 had been an error?
1851 ret 2
1852
1853;
1854; SOME KIND OF ERROR OCCURRED. SEE IF IT IS DMA VIOLATION
1855;
1856GOTERR13:
1857 PUSHF
1858 cmp ah, 09h ;AN011; DMA error?
1859 je Chk_ValidMedia_ERR13 ;AN011;
1860 cmp ah, 11h ;AN011; ECC error?
1861 je Chk_ValidMedia_ERR13 ;AN011;
1862 jmp Skip_Ecc_Check ;AN011; Other error. Just return back.
1863
1864Chk_ValidMedia_ERR13: ;AN011;If SetDrive fails, then just
1865 push ds ;AN011; return back to INT 13h caller,
1866 push di ;AN011; without performing ECC, DMA
1867 push ax ;AN011; error handling.
1868 mov byte ptr cs:[Phys_Drv], 1 ;AN011;
1869 mov al, dl ;AN011;
1870 call SetDrive ;AN011;
1871 mov byte ptr cs:[Phys_Drv], 0 ;AN011;
1872 pop ax ;AN011;
1873 pop di ;AN011;
1874 pop ds ;AN011;
1875 jc Skip_Ecc_Check ;AN011;
1876
1877; TEST OF BIT PATTERN 08H LET OTHER ERRORS BE PASSED AS DMA ERRORS - PTR 32D0519
1878; TEST AH,08H ; DMA BIT
1879 CMP AH, 09H ; DMA ERROR CODE
1880 JNZ CHECK_ECC
1881 JMP GOTDMAERR
1882CHECK_ECC:
1883;J.K. AN003; Soft ECC bug is only applied to PC1 and PC-XT. So, we will enforce
1884;this ECC error handler for them. Also, since CMC hardfiles in PC AT also
1885;generate a lot of unnecessary ECC errors, we will still cover PC ATs as
1886;it is done in the earlier version of MSBIO.
1887;During Format/Verify operation, we are going to consider any Soft Ecc as a
1888;hard error.
1889
1890;SB34DISK005*****************************************************************
1891;SB See if the machine we are operating on is a PC, XT or AT by checking
1892;SB the model byte. The soft ECC bug is only on these machines and if
1893;SB the machine we are operating on is not one of these three then we
1894;SB needn't do anything special. If we are operating one these however
1895;SB we check to see if the error occured during format by checking
1896;SB media_set_for_format. If it did occur during format we cannot do
1897;SB anything but if not during format then check to see if the error
1898;SB returned in AH is the SOFT_ECC error and if so go to OK11 since
1899;SB the error can be ignored. 6 LOCS
1900
1901 cmp cs:[Media_Set_For_Format], 1 ; formatting?
1902 je Skip_Ecc_Check
1903 cmp cs:[Model_Byte], 0FEh ; PC or XT?
1904 jae Go_Chk_Ecc
1905 cmp cs:[Model_Byte], 0FBh ; XT?
1906 je Go_Chk_Ecc
1907 cmp cs:[Model_Byte], 0FCh
1908 jne Skip_Ecc_Check
1909 cmp cs:[Secondary_Model_Byte], 2 ; AT?
1910 ja Skip_Ecc_Check
1911Go_Chk_Ecc: ; for PC, XT, AT
1912 CMP AH,11H
1913 JZ OK11
1914Skip_Ecc_Check: ;AN003; Just return back to INT 13h caller.
1915
1916;SB34DISK005*****************************************************************
1917
1918 POPF
1919 RET 2
1920;
1921; WE HAVE AN ERROR STATUS 11H. THIS INDICATES AN ECC-CORRECTED ERROR. NOTE
1922; THAT THIS INDICATES THAT THE DATA IS PROBABLY CORRECT BUT NOT CERTAINLY
1923; CORRECT. THE ROMS ON PC-1S AND PC_XTS HAVE A 'BUG' IN THAT IF AN ECC ERROR
1924; OCCURS FOR A MULTI-SECTOR READ, ONLY THE SECTORS UP TO THE ONE WHERE THE
1925; ERROR OCCURRED ARE READ IN. WE HAVE NO WAY OF KNOWING HOW MANY WERE READ IN
1926; THIS CASE, SO WE REDO THE OPERATION, READING ONE SECTOR AT A TIME. IF WE
1927; GET AN ECC ERROR ON READING ONE SECTOR, WE IGNORE THE ERROR BECAUSE THE
1928; SECTOR HAS BEEN READ IN.
1929;
1930 PUBLIC OK11
1931OK11:
1932; POPF
1933;J.K. 8/29/86 Here, it is better reset the system. So, we are going to
1934;call Orig13 again
1935
1936 xor ah, ah
1937 call Orig13 ;reset. Don't care about the result
1938
1939 MOV AX,CS:[PREVOPER] ; RETRIEVE REQUEST
1940;
1941; THIS WILL PROVIDE A TERMINATION POINT.
1942;
1943 CMP AL,1 ; IF REQUEST FOR ONE SECTOR, ASSUME OK
1944 JNZ ECC_ERR_HANDLE
1945 XOR AH,AH ; CLEAR CARRY TOO!
1946 RET 2
1947
1948 PUBLIC ECC_ERR_HANDLE
1949ECC_ERR_HANDLE:
1950 SAVEREG <BX,CX,DX>
1951 MOV CS:[NUMBER_OF_SEC],AL
1952LOOP_ECC:
1953 MOV AX,CS:[PREVOPER]
1954 MOV AL,1 ; REQUEST FOR ONE SECTOR ONLY
1955;
1956; WE DO READS ONE SECTOR AT A TIME. THIS ENSURES THAT WE WILL EVENTUALLY
1957; FINISH THE REQUEST SINCE ECC ERRORS ON ONE SECTOR DO READ IN THAT SECTOR.
1958;
1959; WE NEED TO PUT IN SOME "INTELLIGENCE" INTO THE ECC HANDLER TO HANDLE READS
1960; THAT ATTEMPT TO READ MORE SECTORS THAN ARE AVAILABLE ON A PARTICULAR
1961; TRACK.
1962; WE CALL CHECK_WRAP TO SET UP THE SECTOR #, HEAD # AND CYLINDER # FOR
1963; THIS REQUEST.
1964; AT THIS POINT, ALL REGISTERS ARE SET UP FOR THE CALL TO ORIG13, EXCEPT
1965; THAT THERE MAY BE A STARTING SECTOR NUMBER THAT IS BIGGER THAN THE NUMBER
1966; OF SECTORS ON A TRACK.
1967;
1968 CALL CHECK_WRAP ; GET CORRECT PARAMETERS FOR INT 13
1969 PUSHF
1970 CALL ORIG13
1971 JNC OK11_OP
1972 CMP AH,11H ; ONLY ALLOW ECC ERRORS
1973 JNZ OK11_EXIT_err ;J.K. 8/26/86 Other error?
1974 mov ah, 0 ;J.K. ECC error. Reset the system again.
1975 pushf
1976 call Orig13
1977 xor ax, ax ; clear the error code so that if this
1978 ; was the last sector, no error code
1979 ; will be returned for the corrected
1980 ; read. (clear carry too.)
1981OK11_OP:
1982 DEC CS:[NUMBER_OF_SEC]
1983 JZ OK11_EXIT ; ALL DONE?
1984 INC CL ; ADVANCE SECTOR NUMBER
1985 INC BH ; ADD 200H TO ADDRESS
1986 INC BH
1987 JMP SHORT LOOP_ECC
1988OK11_EXIT_err:
1989 stc ;J.K. 8/28/86 Set carry bit again.
1990OK11_EXIT:
1991 RESTOREREG <DX,CX,BX>
1992 RET 2
1993;
1994; WE TRULY HAVE A DMA VIOLATION. RESTORE REGISTER AX AND RETRY THE
1995; OPERATION AS BEST WE CAN.
1996;
1997GOTDMAERR:
1998 POP AX ; CLEAN UP STACK
1999 MOV AX,CS:PREVOPER
2000 STI
2001 CMP AH,ROMREAD ; SAVE USER FLAGS
2002 JB INTDONE
2003 CMP AH,ROMVERIFY
2004 JZ INTVERIFY
2005 CMP AH,ROMFORMAT
2006 JZ INTFORMAT
2007 JA INTDONE
2008;
2009; WE ARE DOING A READ/WRITE CALL. CHECK FOR DMA PROBLEMS
2010;
2011 SAVEREG <DX,CX,BX,AX>
2012 PUSH BP
2013 MOV BP,SP
2014 MOV DX,ES ; CHECK FOR 64K BOUNDARY ERROR
2015
2016 SHL DX,1
2017 SHL DX,1
2018 SHL DX,1
2019 SHL DX,1 ; SEGMENT CONVERTED TO ABSOLUTE ADDRESS
2020
2021 ADD DX,BX ; COMBINE WITH OFFSET
2022 ADD DX,511 ; SIMULATE A TRANSFER
2023;
2024; IF CARRY IS SET, THEN WE ARE WITHIN 512 BYTES OF THE END OF THE SEGMENT.
2025; WE SKIP THE FIRST TRANSFER AND PERFORM THE REMAINING BUFFERING AND TRANSFER
2026;
2027 JNC NO_SKIP_FIRST
2028 MOV DH,BYTE PTR [BP.OLDDX+1] ; SET UP HEAD NUMBER
2029 JMP BUFFER ;J.K. 4/10/86
2030; JMP SHORT BUFFER
2031;
2032; DX IS THE PHYSICAL 16 BITS OF START OF TRANSFER. COMPUTE REMAINING
2033; SECTORS IN SEGMENT.
2034;
2035NO_SKIP_FIRST:
2036 SHR DH,1 ; DH = NUMBER OF SECTORS BEFORE ADDRESS
2037 MOV AH,128 ; AH = MAX NUMBER OF SECTORS IN SEGMENT
2038 SUB AH,DH
2039;
2040; AH IS NOW THE NUMBER OF SECTORS THAT WE CAN SUCCESSFULLY WRITE IN THIS
2041; SEGMENT. IF THIS NUMBER IS ABOVE OR EQUAL TO THE REQUESTED NUMBER, THEN WE
2042; CONTINUE THE OPERATION AS NORMAL. OTHERWISE, WE BREAK IT INTO PIECES.
2043;
2044 CMP AH,AL ; CAN WE FIT IT IN?
2045 JB DOBLOCK ; NO, PERFORM BLOCKING.
2046;
2047; YES, THE REQUEST FITS. LET IT HAPPEN
2048;
2049 MOV DH,BYTE PTR [BP.OLDDX+1] ; SET UP HEAD NUMBER
2050 CALL DOINT
2051 JMP BAD13
2052;
2053; VERIFY THE GIVEN SECTORS. PLACE THE BUFFER POINTER INTO OUR SPACE.
2054;
2055INTVERIFY:
2056 SAVEREG <ES,BX>
2057 PUSH CS
2058 POP ES
2059DOSIMPLE:
2060 MOV BX,OFFSET DISKSECTOR
2061 PUSHF
2062 CALL ORIG13
2063 RESTOREREG <BX,ES>
2064 RET 2
2065
2066;
2067; FORMAT OPERATION. COPY THE PARAMETER TABLE INTO MEMORY
2068;
2069INTFORMAT:
2070 SAVEREG <ES,BX>
2071 SAVEREG <SI,DI,DS>
2072 PUSH ES
2073 PUSH CS
2074 POP ES
2075 POP DS
2076 MOV SI,BX
2077 MOV DI,OFFSET DISKSECTOR
2078 CALL MOVE
2079 RESTOREREG <DS,DI,SI>
2080 JMP DOSIMPLE
2081;
2082; INLINE CONTINUATION OF OPERATION
2083;
2084INTDONE:
2085 JMP ORIG13
2086
2087;
2088; We can't fit the request into the entire block. Perform the operation on
2089; the first block.
2090;
2091; DoBlock is modified to correctly handle multi-sector disk I/O. -J.K. 4/10/86
2092; Old DoBlock had added the number of sectors I/Oed (Ah in Old DoBlock) after
2093; the DoInt call to CL. Observing only the lower 6 bits of CL(=max. 64) can
2094; represent a starting sector, if AH was big, then CL would be clobbered.
2095; By the way, we still are going to use CL for this purpose since Checkwrap
2096; routine will use it as an input. To prevent CL from being clobbered, a
2097; safe number of sectors should be calculated like "63 - # of sectors/track".
2098; DoBlock will handle the first block of requested sectors within the
2099; boundary of this safe value. - J.K. 2/28/86
2100
2101DoBlock:
2102;Try to get the # of sectors/track from BDS via Rom drive number.
2103;For any mini disks installed, here we have to pray that they have the
2104;same # of sector/track as the main DOS partition disk drive.
2105
2106 Message ftestDisk,<"!!!DMA DoBlock!!!">
2107
2108 mov dx, word ptr [bp.olddx] ;set head #
2109 push di
2110 push ds
2111 push ax ;AH - # of sectors before DMA boundary
2112 ;AL - User requeseted # of sectors for I/O.
2113 mov byte ptr CS:[phys_drv],1
2114 mov al, dl
2115 call SetDrive ;get BDS pointer for this DISK.
2116 pop ax
2117 mov byte ptr CS:[phys_drv],0
2118 test word ptr [DI].Flags, fNon_Removable ;don't have to worry
2119 jnz DoBlockHard ;about floppies. They are track by track operation.
2120 mov al, ah ;set al = ah for floppies
2121 jmp short DoBlockCont
2122DoBlockHard:
2123 push cx
2124 xor cx, cx
2125 mov cx, [DI].SecLim ;# of sectors/track
2126 mov ch, 63
2127 sub ch, cl
2128 mov al, ch
2129 xchg ah, al ;now ah - safe # of sectors
2130 ;al - # of sectors before DMA boundary
2131 pop cx
2132DoBlockCont:
2133 pop ds
2134 pop di
2135DoBlockContinue:
2136 Message ftestDisk,<"%%DMA DoBlock Loop%%">
2137 cmp ah, al ;if safe_# >= #_of_sectors_to_go_before DMA,
2138 jae DoBlocklast ;then #_of_sectors_to_go as it is for DoInt.
2139 push ax ;save AH, AL
2140 mov al, ah ;Otherwise, set al to ah to operate.
2141 jmp short DoBlockDoInt ;DoInt will set AH to a proper function in [BP.Oldax]
2142DoBlocklast:
2143 mov ah, al
2144 push ax ;save AH
2145DoBlockDoInt: ;let AH = AL = # of sectors for this shot
2146 CALL DoInt
2147 JC BAD13 ;something happened, bye!
2148 pop ax
2149 SUB BYTE PTR [BP.oldax], AH ;decrement by the successful operation
2150 ADD CL,AH ;advance sector number. Safety gauranteed.
2151 ADD BH,AH ;advance DMA address
2152 ADD BH,AH ;twice for 512 byte sectors.
2153 cmp ah, al ;check the previous value
2154 je Buffer ;if #_of_sectors_to_go < safe_#, then we are done already.
2155 sub al, ah ;otherwise, #_sector_to_go = #_of_sector_to_go - safe_#
2156 call Check_Wrap ;get new CX, DH for the next operation.
2157 jmp short DoBlockContinue ;handles next sectors left.
2158;End of modificaion of DoBlock - J.K. 2/28/86
2159;The following is the original one.
2160; PUSH AX
2161; MOV AL,AH ; get max to operate on
2162; MOV AH,BYTE PTR [BP.oldax+1]; get function
2163; mov dh,byte ptr [BP.olddx+1] ; set up head number
2164; CALL DoInt
2165; JC Bad13 ; something happened, bye!
2166; POP AX
2167; SUB BYTE PTR [BP.oldax],AH ; decrement by the successful operation
2168; ADD CL,AH ; advance sector number
2169; ADD BH,AH ; advance DMA address
2170; ADD BH,AH ; twice for 512 byte sectors.
2171
2172;
2173; THE NEXT REQUEST WILL WRAP THE 64K BOUNDARY. IF WE ARE WRITING, THEN COPY
2174; THE OFFENDING SECTOR INTO OUR SPACE.
2175;
2176; ES:BX POINTS TO THE SECTOR
2177; CX,DX CONTAIN THE CORRECT TRACK/SECTOR/HEAD/DRIVE INFO
2178; [BP.OLDAX] HAS CORRECT FUNCTION CODE
2179;
2180BUFFER:
2181 PUSH BX
2182 MOV AH,BYTE PTR [BP.OLDAX+1]
2183 CMP AH,ROMWRITE
2184 JNZ DOREAD
2185;
2186; COPY THE OFFENDING SECTOR INTO LOCAL BUFFER
2187;
2188 SAVEREG <DS,ES,SI,DI>
2189 PUSH CS ; EXCHANGE SEGMENT REGISTERS
2190 PUSH ES
2191 POP DS
2192 POP ES
2193 MOV DI,OFFSET DISKSECTOR ; WHERE TO MOVE
2194 PUSH DI ; SAVE IT
2195 MOV SI,BX ; SOURCE
2196 CALL MOVE
2197 POP BX ; NEW TRANSFER ADDRESS
2198 RESTOREREG <DI,SI>
2199 MOV AL,1
2200; SEE IF WE ARE WRAPPING AROUND A TRACK OR HEAD
2201 MOV DL,BYTE PTR [BP.OLDDX] ; GET DRIVE NUMBER
2202 CALL CHECK_WRAP ; SETS UP REGISTERS IF WRAP-AROUND
2203;
2204; AH IS FUNCTION
2205; AL IS 1 FOR SINGLE SECTOR TRANSFER
2206; ES:BX IS LOCAL TRANSFER ADDRES
2207; CX IS TRACK/SECTOR NUMBER
2208; DX IS HEAD/DRIVE NUMBER
2209; SI,DI UNCHANGED
2210;
2211 CALL DOINT
2212 RESTOREREG <ES,DS>
2213 JC BAD13 ; GO CLEAN UP
2214 JMP SHORT DOTAIL
2215;
2216; READING A SECTOR. DO INT FIRST, THEN MOVE THINGS AROUND
2217;
2218DOREAD:
2219 SAVEREG <ES,BX>
2220 PUSH CS
2221 POP ES
2222 MOV BX,OFFSET DISKSECTOR
2223 MOV AL,1
2224; SEE IF OUR REQUEST WILL WRAP A TRACK OR HEAD BOUNDARY
2225 MOV DL,BYTE PTR [BP.OLDDX] ; GET DRIVE NUMBER
2226 CALL CHECK_WRAP ; SETS UP REGISTERS IF WRAP-AROUND
2227;
2228; AH = FUNCTION
2229; AL = 1 FOR SINGLE SECTOR
2230; ES:BX POINTS TO LOCAL BUFFER
2231; CX, DX ARE TRACK/SECTOR, HEAD/DRIVE
2232;
2233 CALL DOINT
2234 RESTOREREG <BX,ES>
2235 JC BAD13 ; ERROR => CLEAN UP
2236 SAVEREG <DS,SI,DI>
2237 PUSH CS
2238 POP DS
2239 MOV DI,BX
2240 MOV SI,OFFSET DISKSECTOR
2241 CALL MOVE
2242 RESTOREREG <DI,SI,DS>
2243;
2244; NOTE THE FACT THAT WE'VE DONE 1 MORE SECTOR
2245;
2246DOTAIL:
2247 POP BX ; RETRIEVE NEW DMA AREA
2248 ADD BH,2 ; ADVANCE OVER SECTOR
2249 INC CX
2250 MOV AL,BYTE PTR [BP.OLDAX]
2251 CLC
2252 DEC AL
2253 JZ BAD13 ; NO MORE I/O
2254; SEE IF WE WRAP AROUND A TRACK OR HEAD BOUNDARY WITH STARTING SECTOR
2255; WE ALREADY HAVE THE CORRECT HEAD NUMBER TO PASS TO CHECK_WRAP
2256 MOV DL,BYTE PTR [BP.OLDDX] ; GET DRIVE NUMBER
2257 CALL CHECK_WRAP ; SETS UP REGISTERS IF WRAP-AROUND
2258 CALL DOINT
2259;
2260; WE ARE DONE. AX HAS THE FINAL CODE; WE THROW AWAY WHAT WE GOT BEFORE
2261;
2262BAD13:
2263 MOV SP,BP
2264 RESTOREREG <BP,BX,BX,CX,DX>
2265 RET 2
2266BLOCK13 ENDP
2267 PAGE
2268 INCLUDE MSIOCTL.INC
2269 PAGE
2270; CHECK_WRAP IS A ROUTINE THAT ADJUSTS THE STARTING SECTOR, STARTING HEAD
2271; AND STARTING CYLINDER FOR AN INT 13 REQUEST THAT REQUESTS I/O OF A LOT
2272; OF SECTORS. IT ONLY DOES THIS FOR FIXED DISKS. IT IS USED IN THE SECTIONS
2273; OF CODE THAT HANDLE ECC ERRORS AND DMA ERRORS. IT IS NECESSARY, BECAUSE
2274; ORDINARILY THE ROM WOULD TAKE CARE OF WRAPS AROUND HEADS AND CYLINDERS,
2275; BUT WE BREAK DOWN A REQUEST WHEN WE GET AN ECC OR DMA ERROR INTO SEVERAL
2276; I/O OF ONE OR MORE SECTORS. IN THIS CASE, WE MAY ALREADY BE BEYOND THE
2277; NUMBER OF SECTORS ON A TRACK ON THE MEDIUM, AND THE REQUEST WOULD FAIL.
2278;
2279; INPUT CONDITIONS:
2280; ALL REGISTERS SET UP FOR AN INT 13 REQUEST.
2281;
2282; OUTPUT:
2283; DH - CONTAINS STARTING HEAD NUMBER FOR REQUEST
2284; CX - CONTAINS STARTING SECTOR AND CYLINDER NUMBERS
2285; (THE ABOVE MAY OR MAY NOT HAVE BEEN CHANGED, AND ARE 0-BASED)
2286; ALL OTHER REGISTERS PRESERVED.
2287;
2288 PUBLIC CHECK_WRAP
2289CHECK_WRAP:
2290 Message ftestDisk,<"Entering Check_Wrap...",cr,lf>
2291 SAVEREG <AX,BX,DS,DI>
2292 MOV BYTE PTR CS:[PHYS_DRV],1; USE PHYSICAL DRIVE IN AL TO GET BDS
2293 MOV AL,DL ; AL HAS PHYSICAL DRIVE NUMBER
2294 CALL SETDRIVE ; GET POINTER TO BDS FOR DRIVE
2295 MOV BYTE PTR CS:[PHYS_DRV],0; RESTORE FLAG TO USE LOGICAL DRIVE
2296 JC NO_WRAP ; DO NOTHING IF WRONG PHYSICAL DRIVE
2297 TEST WORD PTR [DI].FLAGS,FNON_REMOVABLE
2298 JZ NO_WRAP ; NO WRAPPING FOR REMOVABLE MEDIA
2299 MOV BX,[DI].SECLIM
2300 MOV AX,CX
2301 AND AX,003FH ; EXTRACT SECTOR NUMBER
2302 CMP AX,BX ; ARE WE GOING TO WRAP?
2303 JBE NO_WRAP
2304 DIV BL ; AH=NEW SECTOR #, AL=# OF HEAD WRAPS
2305; WE NEED TO BE CAREFUL HERE. IF THE NEW SECTOR # IS 0, THEN WE ARE ON THE
2306; LAST SECTOR ON THAT TRACK.
2307 OR AH,AH
2308 JNZ NOT_ON_BOUND
2309 MOV AH,BL ; SET SECTOR=SECLIM IF ON BOUNDARY
2310 DEC AL ; ALSO DECREMENT # OF HEAD WRAPS
2311NOT_ON_BOUND:
2312 AND CL,0C0H ; ZERO OUT SECTOR #
2313 OR CL,AH ; OR IN NEW SECTOR #
2314 XOR AH,AH ; AX = # OF HEAD WRAPS
2315 INC AX
2316 ADD AL,DH ; ADD IN STARTING HEAD #
2317 ADC AH,0 ; CATCH ANY CARRY
2318 CMP AX,[DI].HDLIM ; ARE WE GOING TO WRAP AROUND A HEAD?
2319 JBE NO_WRAP_HEAD ; DO NOT LOSE NEW HEAD NUMBER!!
2320 PUSH DX ; PRESERVE DRIVE NUMBER AND HEAD NUMBER
2321 XOR DX,DX
2322 MOV BX,[DI].HDLIM
2323 DIV BX ; DX=NEW HEAD #, AX=# OF CYLINDER WRAPS
2324; CAREFUL HERE! IF NEW HEAD # IS 0, THEN WE ARE ON THE LAST HEAD.
2325 OR DX,DX
2326 JNZ NO_HEAD_BOUND
2327 MOV DX,BX ; ON BOUNDARY. SET TO HDLIM
2328; IF WE HAD SOME CYLINDER WRAPS, WE NEED TO REDUCE THEM BY ONE!!
2329 OR AX,AX
2330 JZ NO_HEAD_BOUND
2331 DEC AX ; REDUCE NUMBER OF CYLINDER WRAPS
2332NO_HEAD_BOUND:
2333 MOV BH,DL ; BH HAS NEW HEAD NUMBER
2334 POP DX ; RESTORE DRIVE NUMBER AND HEAD NUMBER
2335 DEC BH ; GET IT 0-BASED
2336 MOV DH,BH ; SET UP NEW HEAD NUMBER IN DH
2337 MOV BH,CL
2338 AND BH,3FH ; PRESERVE SECTOR NUMBER
2339 MOV BL,6
2340 XCHG CL,BL
2341 SHR BL,CL ; GET MS CYLINDER BITS TO LS END
2342 ADD CH,AL ; ADD IN CYLINDER WRAP
2343 ADC BL,AH ; ADD IN HIGH BYTE
2344 SHL BL,CL ; MOVE UP TO MS END
2345 XCHG BL,CL ; RESTORE CYLINDER BITS INTO CL
2346 OR CL,BH ; OR IN SECTOR NUMBER
2347
2348NO_WRAP:
2349 CLC ; RESET CARRY
2350 RESTOREREG <DI,DS,BX,AX>
2351 RET
2352
2353NO_WRAP_HEAD:
2354 MOV DH,AL ; DO NOT LOSE NEW HEAD NUMBER
2355 DEC DH ; GET IT 0-BASED
2356 JMP SHORT NO_WRAP
2357
2358;
2359; INT_2F_13:
2360; THIS CODE IS CHAINED INTO THE INT_2F INTERRUPT DURING BIOS
2361; INITIALIZATION. IT ALLOWS THE USER TO CHANGE THE ORIG13 INT_13 VECTOR
2362; AFTER BOOTING. THIS ALLOWS TESTING AND IMPLEMENTATION OF CUSTOM INT_13
2363; HANDLERS, WITHOUT GIVING UP MS-DOS ERROR RECOVERY
2364;
2365; ENTRY CONDITIONS
2366; AH == RESET_INT_13 (13H)
2367; DS:DX == ADDRESS OF NEW INT_13 HANDLER
2368; ES:BX == ADDRESS OF NEW INT_13 VECTOR USED BY WARM BOOT
2369; (INT 19)
2370;
2371; EXIT CONDITIONS
2372; ORIG13 == ADDRESS OF NEW INT_13 HANDLER
2373; DS:DX == OLD ORIG13 VALUE
2374; ES:BX == OLD OLD13 VALUE
2375
2376 ASSUME CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING
2377
2378 PUBLIC INT_2F_13
2379INT_2F_13 PROC FAR
2380
2381 CMP AH,13H ; IF (INTERRUPT_VALUE != RESET_INT_13)
2382 JE CHG_ORIG13
2383 JMP CS:[NEXT2F_13] ; THEN CONTINUE ON INT_2F CHAIN
2384
2385CHG_ORIG13: ; ELSE
2386 PUSH WORD PTR CS:[ORIG13] ; SAVE OLD VALUE OF OLD13 AND
2387 PUSH WORD PTR CS:[ORIG13 + 2]; ORIG13 SO THAT WE CAN
2388
2389 PUSH WORD PTR CS:[OLD13] ; RETURN THEM TO CALLER
2390 PUSH WORD PTR CS:[OLD13 + 2]
2391
2392 MOV WORD PTR CS:[ORIG13],DX ; ORIG13 := ADDR. OF NEW INT_13
2393 ; VECTOR
2394 MOV WORD PTR CS:[ORIG13+2],DS
2395
2396 MOV WORD PTR CS:[OLD13],BX ; OLD13 := ADDR. OF NEW
2397 ; BOOT_13 VECTOR
2398 MOV WORD PTR CS:[OLD13+2],ES
2399
2400 POP ES ; ES:BX := OLD OLD13 VECTOR
2401 POP BX
2402
2403 POP DS ; DS:DX := OLD ORIG13 VECTOR
2404 POP DX
2405
2406 IRET ; END ELSE
2407
2408INT_2F_13 ENDP
2409
2410MOVE PROC NEAR
2411 CLD
2412 PUSH CX
2413 MOV CX,512/2
2414;J.K. Warning!!! Do not change the position of this label.
2415; The following three bytes will be NOPed out by MSINIT if the system
2416; does not support the DOUBLE WORD MOV instruction, i.e., (if
2417; not 386 base machine.)
2418;----------------------------------------------------------------------------
2419 public DoubleWordMov
2420DoubleWordMov: ;AN002;
2421 shr cx, 1 ;AN002;Make it a double word.
2422 db 66h ;AN002;Machine code for double word mov
2423;----------------------------------------------------------------------------
2424 REP MOVSW
2425 POP CX
2426 RET
2427MOVE ENDP
2428
2429DOINT PROC NEAR
2430 MOV DL,BYTE PTR [BP.OLDDX] ; GET PHYSICAL DRIVE NUMBER
2431 XOR AH,AH
2432 OR AL,AL
2433 JZ DOINTDONE
2434 MOV AH,BYTE PTR [BP.OLDAX+1] ; GET REQUEST CODE
2435 PUSH [BP.OLDF]
2436 CALL ORIG13
2437 PUSHF
2438 POP [BP.OLDF]
2439DOINTDONE:
2440 RET
2441DOINT ENDP
2442CODE ENDS
2443 END