5 ;==============================================================================
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 ;==============================================================================
27 ;for testing, set itest to 1. So as MSBIO1.ASM.
29 EXTRN NUMERR
:ABS
;MSDATA
31 INCLUDE MSGROUP
.INC ;DEFINE CODE SEGMENT
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
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
107 ;-----------------------------------------------------------------
109 ; DISK INTERFACE ROUTINES
111 ; DEVICE ATTRIBUTE BITS:
112 ; BIT 6 - GET/SET MAP FOR LOGICAL DRIVES AND GENERIC IOCTL.
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.
134 ; DUE TO VARIOUS BOGOSITIES, WE NEED TO CONTINUALLY ADJUST WHAT THE HEAD
135 ; SETTLE TIME IS. THE FOLLOWING ALGORITHM IS USED:
137 ; GET THE CURRENT HEAD SETTLE VALUE.
143 ;*********************************************
144 ;************ OLD ALGORITHM ******************
145 ;* IF WE ARE SEEKING AND WRITING THEN
149 ;*********************************************
150 ;*********** IBM'S REQUESTED LOGIC ***********
151 ; IF WE ARE SEEKING AND WRITING AND NOT ON AN AT THEN
156 ; RESTORE CURRENT HEAD SETTLE VALUE
159 Set_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.
171 Fat_12_ID
DB "FAT12 ",0 ;AN000; Default System ID for floppy.
173 Fat_16_ID
DB "FAT16 ",0 ;AN000;
175 Vol_No_Name db "NO NAME ",0 ;AN000;
177 Temp_H dw 0 ;AN000; Temporary for 32 bit calculation.
180 Start_Sec_H dw 0 ;AN000; Starting sector number high word.
181 ;Used as an input to DISKIO subroutine.
182 Saved_Word dw 0 ;AN000; Tempory saving place for a word.
184 ;---------------------------------------
185 ;J.K. 6/29/87 For Multi-track
186 MULTRK_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.
189 MULTRK_OFF1 EQU
00000000B ;initial value. No "Multitrack=" command entered.
190 MULTRK_OFF2 EQU
00000001B ;User specified Multitrack=off.
192 MulTrk_Flag dw 0 ;AN001;
193 ;J.K. 6/29/87 End of Multi-track definition.
194 ;---------------------------------------------------------------------
196 EC35_Flag db 0 ; flags for electrically compatible 3.5 inch disk drives (mrw 4/88)
197 ;---------------------------------------------------------------------
198 VRetry_Cnt dw 0 ;AN003;
199 Soft_ECC_Cnt dw 0 ;AN003;
200 ;---------------------------------------------------------------------
201 MultiTrk_Format_Flag db 0 ;AN007;Testing. If 1, then Multi track format request
202 ;---------------------------------------------------------------------
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
211 MESSAGE FTESTDISK
,<"DISK MEDIA CHECK ">
213 MESSAGE FTESTDISK
,<CR
,LF
>
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
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
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
229 TEST WORD PTR [DI].FLAGS
,FNON_REMOVABLE
231 MOV SI,-1 ; INDICATE MEDIA CHANGED
234 ; WE NEED TO RETURN 'NOT CHANGED' IF WE HAVE A HARD FILE.
237 TEST WORD PTR [DI].FLAGS
,FNON_REMOVABLE
240 XOR SI,SI ; PRESUME "I DON'T KNOW"
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
;|
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"
260 ; CHECK TO SEE IF THIS DRIVE HAS BEEN ACCESSED IN THE LAST 2 SECONDS.
261 CALL CHECK_TIME_OF_ACCESS
; SETS SI CORRECTLY
265 DEC SI ; RETURN "I DON'T KNOW"
267 ; SI NOW CONTAINS THE CORRECT VALUE FOR MEDIA CHANGE. CLEAN UP THE LEFT OVERS
270 LES BX,CS:[PTRSAV
] ; GET ORIGINAL PACKET
271 MOV WORD PTR ES:[BX].TRANS
,SI
276 ;----------------------------------------|
277 ; WARNING: DO NOT CHANGE THE FOLLOWING. ;|
278 ; IT GETS PATCHED IN MSINIT ;|
280 INIT_PATCH PROC
NEAR ;|
281 CALL MEDIA_SET_VID
;|
282 ;----------------------------------------|
283 MOV CS:[TIM_DRV
],-1 ; MAKE SURE WE ASK ROM FOR MEDIA CHECK
290 MESSAGE FTESTCOM
,<"ERR$EXITJ: ">
292 MESSAGE FTESTCOM
,<" == ">
295 MESSAGE FTESTCOM
,<CR
,LF
>
300 ; PERFORM A CHECK ON THE TIME PASSED SINCE THE LAST ACCESS FOR THIS PHYSICEL
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.
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.
309 CHECK_TIME_OF_ACCESS PROC
NEAR
310 PUBLIC CHECK_TIME_OF_ACCESS
312 MOV SI,1 ; PRESUME NO CHANGE.
313 ;SB33014*************************************************************
314 xor AH,AH ; set command to read time
315 int 1
Ah ; call rom-bios clock routine
316 ;SB33014*************************************************************
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
323 ADC CS:[DAYCNT
],0 ; ADD IT IN TO OUR REMEMBERED DAY COUNT
325 ; COMPUTE ELAPSED TIME
327 MOV AX,WORD PTR DS:[DI].TIM_LO
; GET STORED TIME
329 MOV AX,WORD PTR DS:[DI].TIM_HI
332 ; CX:DX IS THE ELAPSED TIME
334 JNZ TIMECHECK_UNK
; CX <> 0 => > 1 HOUR
335 OR DX,DX ; TIME MUST PASS
336 JNZ TIMEPASSED
; YES, EXAMINE MAX VALUE
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.
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
349 ; 18.2 TICS PER SECOND.
352 CMP DX,18 * 2 ; MIN ELAPSED TIME?
353 JBE TIMECHECK_RET
; YES, PRESUME NO CHANGE
355 ; EVERYTHING INDICATES THAT WE DO NOT KNOW WHAT HAS HAPPENED.
358 DEC SI ; PRESUME I DON'T KNOW
361 CHECK_TIME_OF_ACCESS ENDP
363 ERR$EXITJ2
: JMP ERR$EXITJ
365 ; BUILD A VALID BPB FOR THE DISK IN THE DRIVE.
369 MESSAGE FTESTDISK
,<"DISK BUILD BPB ">
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.
386 ;----------------------------------------|
387 ; WARNING: DO NOT CHANGE THE FOLLOWING. ;|
388 ; IT GETS PATCHED IN MSINIT ;|
390 SET_PATCH PROC
NEAR ;|
391 CALL SET_VOLUME_ID
;|
392 ;----------------------------------------|
393 MESSAGE FTESTDISK
,<"SET VOLUME ID">
395 MESSAGE FTESTDISK
,<" ">
397 MESSAGE FTESTDISK
,<CR
,LF
>
400 ADD DI,BYTEPERSEC
; RETURN THE BPB THAT IS IN THE CURRENT BDS
403 SETPTRSAV: ; RETURN POINT FOR DSK$INIT
407 MOV ES:[BX].COUNT
+2,DS
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.
419 Clear_IDs proc
near ;AN000;
427 pop es ;AN000; es -> bds
429 pop ds ;AN000; ds = cs
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;
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
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;
446 mov si, offset FAT_16_ID
;AN000; big fat
448 mov cx, BOOT_SYSTEM_ID_SIZE
;AN000; =8
449 add di, FILESYS_ID
;AN000; points to FILESYS_ID field
458 Clear_IDs endp
;AN000;
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.
469 ; INPUTS: DS:DI POINT TO CORRECT BDS.
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
476 ; J.K. This routine will only work for a floppy diskette.
477 ; For a fixed disk, it will just return.
481 ; IF RETURNING FAKE BPB THEN RETURN BPB AS IS.
482 TEST WORD PTR [DI].FLAGS
,RETURN_FAKE_BPB
OR FNON_REMOVABLE
487 MESSAGE FTESTDISK
,<"BUILDING BPB FROM SCRATCH",CR
,LF
>
488 SAVEREG
<CX,DX,ES,BX>
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.
495 JC GETBP_ERR_RET_brdg
; CARRY SET IF THERE WAS ERROR.
496 CMP BX,0 ; BX IS 0 IF BOOT SECTOR IS VALID.
499 CALL MOVBPB
; MOVE BPB INTO REGISTERS.
502 Getbp_err_ret_brdg: jmp Getbp_err_ret
504 ; WE HAVE A 1.X DISKETTE.
505 ; IN THIS CASE READ IN THE FAT ID BYTE AND FILL IN BPB FROM THERE.
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
;|
516 ;----------------------------------------|
517 ;TEST FOR A VALID 3.5" MEDIUM
518 CMP [DI].FORMFACTOR
,FFSMALL
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
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.
532 MOV DX,WORD PTR es:[BX.SPA
]
533 MOV BX,WORD PTR es:[BX.SPT
]
535 ; MUST BE A 5.25" FLOPPY IF WE COME HERE
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
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
553 TEST AH,00000001B ;TEST FOR 1 OR 2 HEADS
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
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
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
579 ;SB34DISK001*******************************************************************
582 RESTOREREG
<ES,DX,CX>
590 ;J.K. Before doing anything else, set Set_ID_Flag to 0.
591 mov cs:Set_ID_Flag
, 0 ;AN000;
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.
599 mov cs:Set_ID_Flag
, 0 ;AN000;
600 MOV AL,ERROR_UNKNOWN_MEDIA
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.
618 READBOOTSEC PROC
NEAR
620 MOV CX,0001 ;CYLINDER 0, SECTOR 1
623 XOR BX,BX ; ASSUME VALID BOOT SECTOR.
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.
647 CMP BYTE PTR CS:[DISKSECTOR
]+2,090H ; IS NEXT ONE A NOP?
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.
654 ; CMP WORD PTR CS:[DISKSECTOR+1FEH],0AA55H ; SEE IF NON-IBM DISK OR 1.X
656 ; JZ CHECKSINGLESIDED ; GO SEE IF SINGLE SIDED MEDIUM. MAY
657 ; ; NEED SOME SPECIAL HANDLING
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.
666 MOV AL,BYTE PTR CS:MEDIABYTE
668 CMP AL,0F0H ; ALLOW FOR STRANGE MEDIA
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.
683 MOV AL,BYTE PTR CS:MEDIABYTE
684 TEST AL,0001H ; IS LOW BIT SET? - INDICATES DOUBLE SIDED
686 CMP WORD PTR CS:[DISKSECTOR
+8],"." SHL 8 + "3"
688 CMP BYTE PTR CS:[DISKSECTOR
+10],"2"
691 ; WE MUST HAVE A PRE-3.20 DISKETTE. SET THE SEC/CLUS FIELD TO 1
693 MOV BYTE PTR CS:[SECPERCLUSINSECTOR
],1
695 ;******************************************************************************
698 INC BX ; INDICATE THAT BOOT SECTOR INVALID
699 GOODDSK: ; CARRY ALREADY RESET
703 ERR_RET: ; CARRY IS ALREADY SET ON ENTRY HERE
704 MESSAGE FTESTDISK
,<"ERROR IN READBOOT",CR
,LF
>
708 ; MOVES THE BPB READ FROM THE BOOT SECTOR INTO REGISTERS FOR USE BY
709 ; GETBP ROUTINE AT HAS1
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.
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
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.
737 cmp cs:fHave96
, 1 ;AC008
738 jne MovBPB_Ret
;AC008
739 call ResetChanged
;AC008 Reset Flags in BDS to NOT fCHANGED.
748 Mov_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
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.
759 cmp cs:[Ext_Boot_Sig
], EXT_BOOT_SIGNATURE
;AN000; = 41
760 jne MMI_Not_Ext
;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.
771 push ds ;AN000; ds-> cs, es-> bds
776 mov cx, BOOT_VOLUME_LABEL_SIZE
;AN000;
777 mov si, offset Boot_Volume_Label
;AN000;
779 add di, VOLID
;AN000;
782 mov cx, BOOT_SYSTEM_ID_SIZE
;AN000; =8
783 mov si, offset Boot_System_ID
;AN000;
784 add di, FILESYS_ID
;AN000;
798 Mov_Media_IDs endp
;AN000;
801 ; READ IN THE FAT SECTOR AND GET THE MEDIA BYTE FROM IT.
802 ; INPUT : AL CONTAINS LOGICAL DRIVE.
804 ; CARRY SET IF AN ERROR OCCURS, AX CONTAINS ERROR CODE.
805 ; OTHERWISE, AH CONTAINS MEDIA BYTE ON EXIT. AL IS PRESERVED.
808 PUSH AX ; PRESERVE LOGICAL DRIVE IN AL
810 MOV CX,0002 ; CYLINDER 0, SECTOR 2
811 CALL READ_SECTOR
; CS:BX POINTS TO FAT SECTOR
813 POP AX ; RESET LOGICAL DRIVE
814 MOV AH,BYTE PTR CS:[BX] ; MEDIA BYTE
817 BAD_FAT_RET: ; CARRY SET ON ENTRY
818 MESSAGE FTESTDISK
,<"ERROR IN FAT READ",CR
,LF
>
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
828 ; OUTPUTS: CARRY CLEAR
829 ; CS:BX POINT TO SECTOR
831 ; AX HAS ROM ERROR CODE
832 ; REGISTERS ES AND BP ARE PRESERVED.
834 READ_SECTOR PROC
NEAR
838 MOV BP,3 ; MAKE 3 ATTEMPTS
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*****************************************************************
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*
851 ;SB33016*****************************************************************
854 CALL AGAIN
; RESET DISK, DECREMENT BP, PRESERVE AX
856 test word ptr ds:[di].flags
,fNon_Removable
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.
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
868 Rd_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*****************************************************************
875 cmp cs:[Media_Set_For_Format
], 0 ;AN012;
876 jne Rd_Skip2_DPT
;AN012;
880 mov al, cs:[save_head_sttl
]
881 mov byte ptr ds:[si].disk_head_sttl
, al
884 Rd_Skip2_DPT: ;AN012;
889 MOV DL,-1 ; MAKE SURE WE ASK ROM IF MEDIA HAS CHANGED
891 ; UPDATE INFORMATION PERTAINING TO LAST DRIVE ACCESSED, TIME OF ACCESS, LAST
892 ; TRACK ACCESSED IN THAT DRIVE.
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
905 ;-----------------------------------------------------------
907 ; DISK REMOVABLE ROUTINE ARR 2.41
910 DSK$REM PROC
NEAR ;ARR 2.41
913 MESSAGE FTESTDISK
,<"DISK REMOVABLE ">
915 MESSAGE FTESTDISK
,<CR
,LF
>
917 CALL SETDRIVE
; GET BDS FOR THIS DRIVE
918 TEST WORD PTR [DI].FLAGS
,FNON_REMOVABLE
923 JMP BUS$EXIT
;ARR 2.41
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
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.
933 ; ELSE IF THE BYTE [PHYS_DRV] IS 1 THEN (ONLY USED FOR FIXED DISKS WHEN AN ECC
935 ; ON ENTRY, DL CONTAINS THE PYHSICAL DRIVE NUMBER.
936 ; ON EXIT, DS:DI POINTS TO CORRECT BDS FOR THE DRIVE IF CARRY CLEAR.
940 MESSAGE FTESTDISK
,<"SETDRIVE",CR
,LF
>
946 ; ASSUME FIRST BDS IS IN THIS SEGMENT
947 MOV DI,WORD PTR START_BDS
949 CMP BYTE PTR CS:[PHYS_DRV
],1 ; DOES AL HAVE PHYSICAL DRIVE?
951 CMP BYTE PTR [DI].DRIVENUM
,AL
953 JMP SHORT GET_NXT_BDS
955 CMP BYTE PTR [DI].DRIVELET
,AL
958 MOV BX,WORD PTR [DI].LINK
+2 ; GO TO NEXT BDS
959 MOV DI,WORD PTR [DI].LINK
971 ;-----------------------------------------------------------
979 MESSAGE FTESTDISK
,<"DISK WRITE WITH VERIFY ">
981 MESSAGE FTESTDISK
,<" ">
983 MESSAGE FTESTDISK
,<" FOR ">
985 MESSAGE FTESTDISK
,<CR
,LF
>
986 MOV CS:[WRTVERIFY
],103H
991 MESSAGE FTESTDISK
,<"DISK WRITE ">
993 MESSAGE FTESTDISK
,<" ">
995 MESSAGE FTESTDISK
,<" FOR ">
997 MESSAGE FTESTDISK
,<CR
,LF
>
998 MOV CS:[WRTVERIFY
],ROMWRITE
1011 MESSAGE FTESTDISK
,<"DISK READ ">
1013 MESSAGE FTESTDISK
,<" ">
1015 MESSAGE FTESTDISK
,<" FOR ">
1017 MESSAGE FTESTDISK
,<CR
,LF
>
1022 ; MISCELLANEOUS ODD JUMP ROUTINES. MOVED OUT OF MAINLINE FOR SPEED.
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.
1028 CHECKSINGLE PROC
NEAR
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
1038 TEST BL,FI_AM_MULT
; IS THERE A DRIVE SHARING THIS
1041 ; LOOK FOR THE PREVIOUS OWNER OF THIS PHYSICAL DRIVE AND RESET ITS OWNERSHIP
1043 MOV AL,DS:[DI].DRIVENUM
; GET PHYSICAL DRIVE NUMBER
1044 PUSH DS ; PRESERVE POINTER TO CURRENT BDS
1050 MOV DI,OFFSET START_BDS
1052 MOV BX,WORD PTR [DI].LINK
+2 ; GO TO NEXT BDS
1053 MOV DI,WORD PTR [DI].LINK
1057 CMP DI,-1 ; END OF LIST?
1058 JZ SINGLE_ERR_RET
; MUST BE ERROR
1059 CMP BYTE PTR [DI].DRIVENUM
,AL
1063 MOV BX,WORD PTR [DI].FLAGS
1064 TEST BL,FI_OWN_PHYSICAL
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
1071 OR BL,FI_OWN_PHYSICAL
; ESTABLISH CURRENT BDS AS OWNER
1072 OR WORD PTR [DI].FLAGS
,BX
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
1079 CMP BYTE PTR CS:[FSETOWNER
],1
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
1087 SAVEREG
<DS,DI,AX> ; THEN
1088 MOV AL,DS:[DI].DRIVELET
; IF (CURR_DRV == REQ_DRV)
1092 XCHG AL,DS:BYTE PTR LSTDRV
; THEN SWAP(CURR_DRV,REQ_DRV)
1094 RESTOREREG
<AX,DI,DS> ; SWAP(CURR_DRV,REQ_DRV)
1095 JE SINGLERET
; ISSUE SWAP_DSK_MSG
1098 CALL SWPDSK
; ASK USER FOR CORRECT DISK
1106 POP DI ; RESTORE CURRENT BDS
1111 MOV AL,8 ;Sector not found
1112 jmp short BadDrive_Ret
;AN004;AN005;AN006;
1113 UnformattedDrive: ;AN004;AN005;AN006;
1114 mov al,7 ;AN004;Unknown media;AN005;AN006;
1120 MOV AL,NORMSETTLE
; SOMEONE HAS DIDDLED THE SETTLE
1123 ;------------------------------------------------------------
1127 ; AL = DRIVE NUMBER (0-6)
1128 ; AH = MEDIA DESCRIPTOR
1130 ; DX = FIRST SECTOR (low)
1131 ; [Start_Sec_H] = FIRST SECTOR (high) ;J.K. 32 bit calculation.
1133 ; ES:DI = TRANSFER ADDRESS
1134 ; [RFLAG]=OPERATION (2=READ, 3=WRITE)
1135 ; [VERIFY]=1 FOR VERIFY AFTER WRITE
1137 ; IF SUCCESSFUL CARRY FLAG = 0
1138 ; ELSE CF=1 AND AL CONTAINS ERROR CODE
1142 MOV CS:[RFLAG
],ROMREAD
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.
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
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
1162 ; ENSURE THAT WE ARE TRYING TO ACCESS VALID SECTORS ON THE DRIVE
1165 mov ax,dx ;AN000; save DX to AX
1169 cmp [di].DrvLim
, 0 ;AN000; Is this drive > 32 bit sector ?
1172 jne BADDRIVE
;AN000;
1173 cmp dx, [di].DrvLim
;AN000;
1175 jmp short SanityOK
;AN000;
1177 add si, cs:[Start_Sec_H
] ;AN000;
1178 cmp si, [di].DrvLim_H
;AN000;
1181 cmp dx, [di].DrvLim_L
;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)
1194 ; ADD DX,WORD PTR [DI].HIDSEC ; ADD IN THE HIDDEN SECTORS
1195 ; CMP SI,WORD PTR [DI].DRVLIM ; COMPARE AGAINST DRIVE MAX
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.
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
1207 TEST WORD PTR [DI].FLAGS
,FNON_REMOVABLE
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.
1215 ;----------------------------------------|
1216 ; WARNING: DO NOT CHANGE THE FOLLOWING. ;|
1217 ; IT GETS PATCHED IN MSINIT ;|
1218 PUBLIC DISKIO_PATCH
;|
1220 CALL CHECKLATCHIO
;|
1221 ;----------------------------------------|
1223 ; SET UP TABLES AND VARIABLES FOR I/O
1226 ; NOW THE SETTLE VALUES ARE CORRECT FOR THE FOLLOWING CODE
1229 ;J.K. 32 bit sector calculation.
1230 ; DX;[Saved_Word] = starting sector number.
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
1243 XOR DX,DX ;DIVIDE TRACKS BY HEADS PER CYLINDER
1244 mov ax, cs:[Temp_H
] ;AN000;
1246 mov cs:[Temp_H
],ax ;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
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.
1269 BADDRIVE_Brdg:jmp Baddrive
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.
1279 MOV AL,[DI].DRIVENUM
1280 MOV CS:[TIM_DRV
],AL ; SAVE DRIVE LETTER
1282 ; DETERMINE PROPER HEAD SETTLE VALUES
1284 cmp cs:[Media_Set_For_Format
], 0 ;AN012;
1285 jne Skip_DPT_Setting
;AN012;
1287 LDS SI,DWORD PTR CS:[DPT
] ; GET POINTER TO DISK BASE TABLE
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
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
1298 MOV ES,CX ; ES:DI -> TO CURRENT BDS
1299 CMP BYTE PTR ES:[DI].FORMFACTOR
,FFSMALL
1302 XCHG AL,[SI].DISK_MOTOR_STRT
1306 ; DS:SI NOW POINTS TO DISK PARAMETER TABLE. GET CURRENT SETTLE AND SET FAST
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
1316 MOV CS:SETTLESLOW
,AL
1317 Skip_DPT_Setting: ;AN012;
1320 ; SET TIME OF LAST ACCESS, AND RESET DEFAULT VALUES IN THE DPT.
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
1327 ; RESTORE HEAD SETTLE AND EOT VALUES
1330 pushf ;AN013;Save flag
1331 cmp cs:[Media_Set_For_Format
], 0 ;AN012;
1332 jne NoDiddleBack
;AN012;
1335 MOV AL,CS:SETTLECURRENT
1336 MOV AH,CS:MOTORSTARTUP
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
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
1350 NoDiddleBack: ;AN013;
1351 popf ;AN013;Restore flag
1355 ;READ THE NUMBER OF SECTORS SPECIFIED IN AX, HANDLING TRACK BOUNDARIES
1356 ;DS:DI -> BDS FOR THIS DRIVE
1358 OR AX,AX ;SEE IF ANY SECTORS TO READ
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.
1367 test word ptr CS:MulTrk_Flag
, MulTrk_ON
1369 ;SB34DISK002*****************************************************************
1373 BLOCK_FLOPPY: ;J.K.4/10/86
1375 ; READ AT MOST 1 TRACK WORTH. PERFORM MINIMIZATION AT SECTOR / TRACK
1377 MOV CL,BYTE PTR [DI].SECLIM
1379 SUB CL,CS:CURSEC
; LEEAC 3.20 ADD SEGMENT OVERRIDE
1386 ; AX IS THE REQUESTED NUMBER OF SECTORS TO READ
1387 ; CX IS THE NUMBER THAT WE CAN DO ON THIS TRACK
1391 MOV AX,CX ; AL IS NUMBER OF SECTORS TO READ
1396 ; CX IS THE NUMBER OF SECTORS JUST TRANSFERRED
1398 SUB AX,CX ; REDUCE SECTORS-REMAINING BY LAST I/O
1400 ADD BH,CL ; ADJUST TRANSFER ADDRESS
1404 DskErr_Brdg: jmp DskErr
;AN003;
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
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
1424 MOV DX,CS:[CURTRK
] ;LOAD CURRENT CYLINDER
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
1431 DISK_NOT_MINI: ;J.K. 4/7/86
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
1447 CMP AH,ROMREAD
; ARR 2.20
1452 ; READS ALWAYS FAST, UNLESS WE HAVE JUST DONE A DISK RESET OPERATION
1453 JMP DO_WRITE
; ARR 2.20 READS ALWAYS FAST
1455 CALL FASTSPEED
; MZ 2.21 CHANGE SETTLE MODE
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
1462 CMP CS:WRTVERIFY
,103H
; CHECK FOR WRITE AND VERIFY
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
1475 test word ptr [di].FLAGS
, fNON_REMOVABLE
1477 test CS:MulTrk_Flag
, MulTrk_ON
1480 ;SB34DISK003*****************************************************************
1481 AND CL,03FH ; ELIMINATE CYLINDER BITS FROM SECTOR
1483 SUB CS:[SECCNT
],AX ; REDUCE COUNT OF SECTORS TO GO
1484 ADD CL,AL ; NEXT SECTOR
1486 CMP CL,BYTE PTR [DI].SECLIM
; SEE IF SECTOR/TRACK LIMIT REACHED
1489 MOV CS:[CURSEC
],1 ; START WITH FIRST SECTOR OF NEXT TRACK
1492 CMP DH,BYTE PTR [DI].HDLIM
1495 INC CS:[CURTRK
] ;NEXT TRACK
1504 ; THE REQUEST IS FOR WRITE. DETERMINE IF WE ARE TALKING ABOUT THE SAME
1505 ; TRACK AND DRIVE. IF SO, USE THE FAST SPEED.
1508 CMP DL,CS:[STEP_DRV
] ; ARR 2.20
1509 JNZ DO_NORM
; WE HAVE CHANGED DRIVES
1511 CMP CH,BYTE PTR [DI].TRACK
; ARR 2.20
1512 JZ DO_FAST
; WE ARE STILL ON THE SAME TRACK
1516 JMP SHORT TESTERR
; MZ 2.21 TEST FOR ERROR
1519 ; WE HAVE A VERIFY REQUEST ALSO. GET STATE INFO AND GO VERIFY
1523 POP AX ; RESTORE SECTOR COUNT
1525 MOV AH,ROMVERIFY
; REQUEST VERIFY
1526 CALL FASTSPEED
; MZ 2.21 CHANGE SETTLE MODE
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
1537 cmp ah,11h
;SOFT ECC error ?
1540 jz NoVerify
;no more retry
1541 call ResetDisk
;reset disk
1544 ;SB34DISK004**************************************************************
1546 Not_SoftECC_Err: ;AN003;Other error.
1547 call ResetDisk
;AN003;
1548 dec VRetry_Cnt
;AN003;
1552 ; NEED TO SPECIAL CASE THE CHANGE-LINE ERROR AH=06H. IF WE GET THIS, WE
1553 ; NEED TO RETURN IT.
1555 ;----------------------------------------|
1556 ; WARNING: DO NOT CHANGE THE FOLLOWING. ;|
1557 ; IT GETS PATCHED IN MSINIT ;|
1561 ;---------------------------------------;|
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.
1571 test word ptr [di].FLAGS
, fNon_Removable
;AN009;
1572 jnz Skip_TimeOut_Chk
;AN009;
1573 CMP AH,80H
;TIMEOUT?
1575 Skip_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
1580 POP AX ;RESTORE SECTOR COUNT
1583 Write_Fault_Err: ;AN003;
1584 mov bp, 1 ;AN003;Just retry only once for Write Fault error.
1592 HARDERR2: ; FOR ROUTINES THAT CALL MAPERROR THEMSELVES
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
1599 ; SINCE WE ARE PERFORMING A NON-LOCAL GOTO, RESTORE THE DISK PARAMETERS
1607 ; CHANGE SETTLE VALUE FROM SETTLECURRENT TO WHATEVER IS APPROPRIATE
1608 ; NOTE THAT THIS ROUTINE IS NEVER CALLED FOR A FIXED DISK.
1611 cmp cs:[Media_Set_For_Format
], 0 ;AN012;
1612 jne FASTSPEED
;AN012;
1615 MOV AL,CS:SETTLESLOW
1616 LDS SI,CS:DPT
; CURRENT DISK PARM TABLE
1617 MOV [SI].DISK_HEAD_STTL
,AL
1623 MOV [SI].DISK_HEAD_STTL
,1 ; 1 IS FAST SETTLE VALUE
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.
1633 TEST BYTE PTR [DI].FATSIZ
,FTOOBIG
1642 MESSAGE FTESTINIT
,<"<">
1644 MESSAGE FTESTINIT
,<",">
1646 MESSAGE FTESTINIT
,<":">
1648 MESSAGE FTESTINIT
,<",">
1650 MESSAGE FTESTINIT
,<",">
1652 MESSAGE FTESTINIT
,<">">
1662 ; MAP ERROR RETURNED BY ROM IN AH INTO CORRESPONDING CODE TO BE RETURNED TO
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
1676 MOV AL,CS:[DI + NUMERR
- 1] ;GET TRANSLATION
1678 STC ;FLAG ERROR CONDITION
1682 ; SET THE TIME OF LAST ACCESS FOR THIS DRIVE. THIS IS DONE ONLY FOR REMOVABLE
1688 ;SB33018******************************************************************
1689 xor AH, AH ; set command to get time ;SB;3.30*
1690 int 1
Ah ; call rom-bios timer function ;SB;3.30*
1691 ;SB33018******************************************************************
1694 INC CS:[DAYCNT
] ; CATCH ROLLOVER
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
1700 CMP CX,WORD PTR [DI].TIM_HI
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
1712 ASSUME
CS:CODE,DS:NOTHING
,ES:NOTHING
,SS:NOTHING
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
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.
1736 ;J.K. 1/30/87 To handle the ps2_30 machine INT 13h, AH = 8 Problem.
1737 ;Save Registers here.
1753 ; AL = NUMBER OF SECTORS
1754 ; ES:BX = DMA ADDRESS
1755 ; CX = PACKED TRACK AND SECTOR
1756 ; DX = HEAD AND DRIVE
1757 ; OUTPUT CONDITIONS:
1763 ; LET THE OPPERATION PROCEED. IF THERE IS A DMA VIOLATION, THEN WE DO THINGS.
1765 MOV CS:PREVOPER
,AX ; SAVE REQUEST
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
1775 MOV WORD PTR CS:[FLAGBITS
],FCHANGED_BY_FORMAT
+FCHANGED
1776 CALL SET_CHANGED_DL
; INDICATE THAT MEDIA CHANGED BY FORMAT
1778 ;---------------------------------------------------------|
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
1798 RESTOREREG
<cx, bx, ax>
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
1807 CALL ORIG13
; SIMULATE INT 13
1808 JC GOTERR13_br
; ERROR?
1809 RET 2 ; NO, RETURN AND CLEAR FLAGS
1811 GOTERR13_br: jmp Goterr13
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.
1818 ps2_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"
1822 mov cs:Save_AX
, AX ;Save registers,flag
1834 mov dx, cs:Prev_DX
;restore orignal drive
1836 mov ah, 1 ;Read Status.
1837 call Orig13
;Reset the bus as a side effect of this call.
1839 mov AX, cs:Save_AX
;restore registers,flag
1850 jc GotErr13
;AH=8 had been an error?
1854 ; SOME KIND OF ERROR OCCURRED. SEE IF IT IS DMA VIOLATION
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.
1864 Chk_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;
1870 call SetDrive
;AN011;
1871 mov byte ptr cs:[Phys_Drv
], 0 ;AN011;
1875 jc Skip_Ecc_Check
;AN011;
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
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
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
1901 cmp cs:[Media_Set_For_Format
], 1 ; formatting?
1903 cmp cs:[Model_Byte
], 0FEh ; PC or XT?
1905 cmp cs:[Model_Byte
], 0FBh ; XT?
1907 cmp cs:[Model_Byte
], 0FCh
1909 cmp cs:[Secondary_Model_Byte
], 2 ; AT?
1911 Go_Chk_Ecc: ; for PC, XT, AT
1914 Skip_Ecc_Check: ;AN003; Just return back to INT 13h caller.
1916 ;SB34DISK005*****************************************************************
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.
1933 ;J.K. 8/29/86 Here, it is better reset the system. So, we are going to
1937 call Orig13
;reset. Don't care about the result
1939 MOV AX,CS:[PREVOPER
] ; RETRIEVE REQUEST
1941 ; THIS WILL PROVIDE A TERMINATION POINT.
1943 CMP AL,1 ; IF REQUEST FOR ONE SECTOR, ASSUME OK
1945 XOR AH,AH ; CLEAR CARRY TOO!
1948 PUBLIC ECC_ERR_HANDLE
1951 MOV CS:[NUMBER_OF_SEC
],AL
1953 MOV AX,CS:[PREVOPER
]
1954 MOV AL,1 ; REQUEST FOR ONE SECTOR ONLY
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.
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
1962 ; WE CALL CHECK_WRAP TO SET UP THE SECTOR #, HEAD # AND CYLINDER # FOR
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.
1968 CALL CHECK_WRAP
; GET CORRECT PARAMETERS FOR INT 13
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.
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.)
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
1989 stc ;J.K. 8/28/86 Set carry bit again.
1991 RESTOREREG
<DX,CX,BX>
1994 ; WE TRULY HAVE A DMA VIOLATION. RESTORE REGISTER AX AND RETRY THE
1995 ; OPERATION AS BEST WE CAN.
1998 POP AX ; CLEAN UP STACK
2001 CMP AH,ROMREAD
; SAVE USER FLAGS
2009 ; WE ARE DOING A READ/WRITE CALL. CHECK FOR DMA PROBLEMS
2011 SAVEREG
<DX,CX,BX,AX>
2014 MOV DX,ES ; CHECK FOR 64K BOUNDARY ERROR
2019 SHL DX,1 ; SEGMENT CONVERTED TO ABSOLUTE ADDRESS
2021 ADD DX,BX ; COMBINE WITH OFFSET
2022 ADD DX,511 ; SIMULATE A TRANSFER
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
2028 MOV DH,BYTE PTR [BP.OLDDX
+1] ; SET UP HEAD NUMBER
2029 JMP BUFFER
;J.K. 4/10/86
2032 ; DX IS THE PHYSICAL 16 BITS OF START OF TRANSFER. COMPUTE REMAINING
2033 ; SECTORS IN SEGMENT.
2036 SHR DH,1 ; DH = NUMBER OF SECTORS BEFORE ADDRESS
2037 MOV AH,128 ; AH = MAX NUMBER OF SECTORS IN SEGMENT
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.
2044 CMP AH,AL ; CAN WE FIT IT IN?
2045 JB DOBLOCK
; NO, PERFORM BLOCKING.
2047 ; YES, THE REQUEST FITS. LET IT HAPPEN
2049 MOV DH,BYTE PTR [BP.OLDDX
+1] ; SET UP HEAD NUMBER
2053 ; VERIFY THE GIVEN SECTORS. PLACE THE BUFFER POINTER INTO OUR SPACE.
2060 MOV BX,OFFSET DISKSECTOR
2067 ; FORMAT OPERATION. COPY THE PARAMETER TABLE INTO MEMORY
2077 MOV DI,OFFSET DISKSECTOR
2079 RESTOREREG
<DS,DI,SI>
2082 ; INLINE CONTINUATION OF OPERATION
2088 ; We can't fit the request into the entire block. Perform the operation on
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
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.
2106 Message ftestDisk
,<"!!!DMA DoBlock!!!">
2108 mov dx, word ptr [bp.olddx
] ;set head #
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
2115 call SetDrive
;get BDS pointer for this DISK.
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
2125 mov cx, [DI].SecLim
;# of sectors/track
2129 xchg ah, al ;now ah - safe # of sectors
2130 ;al - # of sectors before DMA boundary
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]
2145 DoBlockDoInt: ;let AH = AL = # of sectors for this shot
2147 JC BAD13
;something happened, bye!
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.
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
2165 ; JC Bad13 ; something happened, bye!
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.
2173 ; THE NEXT REQUEST WILL WRAP THE 64K BOUNDARY. IF WE ARE WRITING, THEN COPY
2174 ; THE OFFENDING SECTOR INTO OUR SPACE.
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
2182 MOV AH,BYTE PTR [BP.OLDAX
+1]
2186 ; COPY THE OFFENDING SECTOR INTO LOCAL BUFFER
2188 SAVEREG
<DS,ES,SI,DI>
2189 PUSH CS ; EXCHANGE SEGMENT REGISTERS
2193 MOV DI,OFFSET DISKSECTOR
; WHERE TO MOVE
2197 POP BX ; NEW TRANSFER ADDRESS
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
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
2213 JC BAD13
; GO CLEAN UP
2216 ; READING A SECTOR. DO INT FIRST, THEN MOVE THINGS AROUND
2222 MOV BX,OFFSET DISKSECTOR
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
2229 ; AL = 1 FOR SINGLE SECTOR
2230 ; ES:BX POINTS TO LOCAL BUFFER
2231 ; CX, DX ARE TRACK/SECTOR, HEAD/DRIVE
2235 JC BAD13
; ERROR => CLEAN UP
2240 MOV SI,OFFSET DISKSECTOR
2242 RESTOREREG
<DI,SI,DS>
2244 ; NOTE THE FACT THAT WE'VE DONE 1 MORE SECTOR
2247 POP BX ; RETRIEVE NEW DMA AREA
2248 ADD BH,2 ; ADVANCE OVER SECTOR
2250 MOV AL,BYTE PTR [BP.OLDAX
]
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
2260 ; WE ARE DONE. AX HAS THE FINAL CODE; WE THROW AWAY WHAT WE GOT BEFORE
2264 RESTOREREG
<BP,BX,BX,CX,DX>
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.
2280 ; ALL REGISTERS SET UP FOR AN INT 13 REQUEST.
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.
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
2301 AND AX,003FH ; EXTRACT SECTOR NUMBER
2302 CMP AX,BX ; ARE WE GOING TO 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.
2309 MOV AH,BL ; SET SECTOR=SECLIM IF ON BOUNDARY
2310 DEC AL ; ALSO DECREMENT # OF HEAD WRAPS
2312 AND CL,0C0H ; ZERO OUT SECTOR #
2313 OR CL,AH ; OR IN NEW SECTOR #
2314 XOR AH,AH ; AX = # OF HEAD WRAPS
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
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.
2327 MOV DX,BX ; ON BOUNDARY. SET TO HDLIM
2328 ; IF WE HAD SOME CYLINDER WRAPS, WE NEED TO REDUCE THEM BY ONE!!
2331 DEC AX ; REDUCE NUMBER OF CYLINDER WRAPS
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
2338 AND BH,3FH
; PRESERVE SECTOR NUMBER
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
2350 RESTOREREG
<DI,DS,BX,AX>
2354 MOV DH,AL ; DO NOT LOSE NEW HEAD NUMBER
2355 DEC DH ; GET IT 0-BASED
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
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
2372 ; ORIG13 == ADDRESS OF NEW INT_13 HANDLER
2373 ; DS:DX == OLD ORIG13 VALUE
2374 ; ES:BX == OLD OLD13 VALUE
2376 ASSUME
CS:CODE,DS:NOTHING
,ES:NOTHING
,SS:NOTHING
2381 CMP AH,13H
; IF (INTERRUPT_VALUE != RESET_INT_13)
2383 JMP CS:[NEXT2F_13
] ; THEN CONTINUE ON INT_2F CHAIN
2386 PUSH WORD PTR CS:[ORIG13
] ; SAVE OLD VALUE OF OLD13 AND
2387 PUSH WORD PTR CS:[ORIG13
+ 2]; ORIG13 SO THAT WE CAN
2389 PUSH WORD PTR CS:[OLD13
] ; RETURN THEM TO CALLER
2390 PUSH WORD PTR CS:[OLD13
+ 2]
2392 MOV WORD PTR CS:[ORIG13
],DX ; ORIG13 := ADDR. OF NEW INT_13
2394 MOV WORD PTR CS:[ORIG13
+2],DS
2396 MOV WORD PTR CS:[OLD13
],BX ; OLD13 := ADDR. OF NEW
2398 MOV WORD PTR CS:[OLD13
+2],ES
2400 POP ES ; ES:BX := OLD OLD13 VECTOR
2403 POP DS ; DS:DX := OLD ORIG13 VECTOR
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
2420 DoubleWordMov: ;AN002;
2421 shr cx, 1 ;AN002;Make it a double word.
2422 db 66h
;AN002;Machine code for double word mov
2423 ;----------------------------------------------------------------------------
2430 MOV DL,BYTE PTR [BP.OLDDX
] ; GET PHYSICAL DRIVE NUMBER
2434 MOV AH,BYTE PTR [BP.OLDAX
+1] ; GET REQUEST CODE