]>
wirehaze git hosting - MS-DOS.git/blob - v4.0/src/BIOS/MSHARD.ASM
3 ; C: (C) Copyright 1988 by Microsoft corp.
6 ; There is a bug in some versions of IBM's AT ROM BIOS.
7 ; Interrupts are not disabled during read operations.
9 ; Use: This program should be chained in line with the disk
10 ; interupt 13h, it intercepts read calls to the hard disk
11 ; and handles them appropriately. For other functions it
12 ; passes controll to OLD13, which should contain the
13 ; address of the AT ROM disk routine. The entry point for
14 ; this program is IBM_DISK_IO.
18 .286c
;Use 80286 non-protected mode
20 BIOSEG
= 040h ;Segment for ROM BIOS Data
21 ROMSEG
= 0F000h ;Segment of ROM
29 ;* Offsets into Fixed disk parameter table
33 DATA SEGMENT AT BIOSEG
;ROM BIOS data segment
36 CMD_BLOCK
DB 6 DUP (?
)
38 ;* Offsets into CMD_BLOCK for registers
39 PRE_COMP
= 0 ;Write Pre-compensation
40 SEC_CNT
= 1 ;Sector count
41 SEC_NUM
= 2 ;Sector number
42 CYL_LOW
= 3 ;Cylinder number, low part
43 CYL_HIGH
= 4 ;Cylinder number, high part
44 DRV_HEAD
= 5 ;Drive/Head (Bit 7 = ECC mode, Bit 5 = 512 byte sectors,
45 ; Bit 4 = drive number, Bits 3-0 have head number)
46 CMD_REG
= 6 ;Command register
59 ;*** Define where the ROM routines are actually located
75 ROMCHECK_STATUS PROC
FAR
87 ROMFRET PROC
FAR ;Far return at F000:FF65 in AT ROM.
93 CODE SEGMENT BYTE PUBLIC 'code'
95 EXTRN OLD13
:DWORD ;Link to AT bios int 13h
104 ;*** IBM_DISK_IO - main routine, fixes AT ROM bug
106 ; ENTRY: (AH) = function, 02 or 0A for read.
107 ; (DL) = drive number (80h or 81h).
108 ; (DH) = head number.
109 ; (CH) = cylinder number.
110 ; (CL) = Sector number (high 2 bits has cylinder number).
111 ; (AL) = number of sectors.
112 ; (ES:BX) = address of read buffer.
113 ; For more on register contents see ROM BIOS listing.
114 ; Stack set up for return by an IRET.
116 ; EXIT: (AH) = status of current operation.
117 ; (CY) = 1 IF failed, 0 if successful.
118 ; For other register contents see ROM BIOS listing.
123 ; WARNING: Uses OLD13 vector for non-read calls.
124 ; Does direct calls to the AT ROM.
125 ; Does segment arithmatic.
127 ; EFFECTS: Performs DISK I/O operation.
131 JB ATD1
;Pass through floppy disk calls.
133 JE ATD2
;Intercept call 02 (read sectors).
135 JE ATD2
;and call 0Ah (read long).
137 JMP OLD13
;Use ROM INT 13h handler.
146 MOV AX,BIOSEG
;Establish BIOS segment addressing.
148 MOV DISK_STATUS1
, 0 ;Initially no error code.
149 AND DL, 07fh ;Mask to hard disk number
151 JB ATD3
;Disk number in range
152 MOV DISK_STATUS1
, BAD_DISK
153 JMP SHORT ATD4
;Disk number out of range error, return
157 MOV AX, ES ;Make ES:BX to Seg:000x form.
165 JC ATD4
;Abort if DMA across segment boundary
167 POP AX ;Restore AX register for SETCMD
169 CALL SETCMD
;Set up command block for disk op
171 OUT DX, AL ;Write out command modifier
172 CALL DOCMD
;Carry out command
174 ;; Old code - Carry cleared after set by logical or opearation
176 ;; MOV AH,DISK_STATUS1 ;On return AH has error code
179 ;; JNZ ATD5 ;Carry set if error
181 ;;---------------------------------------------------
182 ;; New Code - Let Logical or clear carry and then set carry if ah!=0
183 ;; And save a couple bytes while were at it.
185 MOV AH,DISK_STATUS1
;On return AH has error code
187 JZ ATD5
;Carry set if error
197 RET 2 ;Far return, dropping flags
202 ;*** SETCMD - Set up CMD_BLOCK for the disk operation
204 ; ENTRY: (DS) = BIOS Data segment.
205 ; (ES:BX) in seg:000x form.
206 ; Other registers as in INT 13h call
208 ; EXIT: CMD_BLOCK set up for disk read call.
209 ; CONTROL_BYTE set up for disk operation.
210 ; (AL) = Control byte modifier
213 ; Sets the fields of CMD_BLOCK using the register contents
214 ; and the contents of the disk parameter block for the given drive.
216 ; WARNING: (AX) destroyed.
217 ; Does direct calls to the AT ROM.
220 MOV CMD_BLOCK
[SEC_CNT
], AL
221 MOV CMD_BLOCK
[CMD_REG
], 020h ;Assume function 02
223 JE SETC1
;CMD_REG = 20h if function 02 (read)
224 MOV CMD_BLOCK
[CMD_REG
], 022h ;CMD_REG = 22h if function 0A (" long)
225 SETC1: ;No longer need value in AX
227 AND AL, 03fh ;Mask to sector number
228 MOV CMD_BLOCK
[SEC_NUM
], AL
229 MOV CMD_BLOCK
[CYL_LOW
], CH
231 SHR AL, 6 ;Get two high bits of cylender number
232 MOV CMD_BLOCK
[CYL_HIGH
], AL
234 SHL AL, 4 ;Drive number
236 OR AL, AH ;Head number
237 OR AL, 0A0h ;Set ECC and 512 bytes per sector
238 MOV CMD_BLOCK
[DRV_HEAD
], AL
239 PUSH ES ;GET_VEC destroys ES:BX
243 MOV AX, ES:FDP_PRECOMP
[BX] ;Write pre-comp from disk parameters
245 MOV CMD_BLOCK
[PRE_COMP
],AL ;Only use low part
246 MOV AL, ES:FDP_CONTROL
[BX] ;Control byte modifier
250 AND AH, 0C0h ;Keep disable retry bits
258 ;*** DOCMD - Carry out READ operation to AT hard disk
260 ; ENTRY: (ES:BX) = address for read in data.
261 ; CMD_BLOCK set up for disk read.
263 ; EXIT: Buffer at (ES:BX) contains data read.
264 ; DISK_STATUS1 set to error code (0 if success).
268 ; WARNING: (AX), (BL), (CX), (DX), (DI) destroyed.
269 ; No check is made for DMA boundary overrun.
271 ; EFFECTS: Programs disk controller.
272 ; Performs disk input.
275 MOV DI, BX ;(ES:DI) = data buffer addr.
281 CALL WAITT
;Wait for controller to complete read
283 MOV CX, 100h
;256 words per sector
285 CLD ;String op goes up
286 CLI ;Disable interrupts (BUG WAS FORGETTING THIS)
287 REPZ INSW ;Read in sector
289 TEST CMD_BLOCK
[CMD_REG
], 02
290 JZ DOC2
;No ECC bytes to read.
294 MOV CX, 4 ;4 bytes of ECC
297 REPZ INSB ;Read in ECC
302 JNZ DOC3
;Operation failed
303 DEC CMD_BLOCK
[SEC_CNT
]
304 JNZ DOC1
;Loop while more sectors to read
311 ;*** GET_VEC - Get pointer to hard disk parameters.
313 ; ENTRY: (DL) = Low bit has hard disk number (0 or 1).
315 ; EXIT: (ES:BX) = address of disk parameters table.
317 ; USES: AX for segment computation.
319 ; Loads ES:BX from interrupt table in low memory, vector 46h (disk 0)
322 ; WARNING: (AX) destroyed.
323 ; This does a direct call to the AT ROM.
332 ;*** COMMAND - Send contents of CMD_BLOCK to disk controller.
334 ; ENTRY: Control_byte
335 ; CMD_BLOCK - set up with values for hard disk controller.
337 ; EXIT: DISK_STATUS1 = Error code.
338 ; NZ if error, ZR for no error.
341 ; WARNING: (AX), (CX), (DX) destroyed.
342 ; Does a direct call to the AT ROM.
344 ; EFFECTS: Programs disk controller.
353 ;*** WAITT - Wait for disk interrupt
357 ; EXIT: DISK_STATUS1 = Error code.
358 ; NZ if error, ZR if no error.
361 ; WARNING: (AX), (BL), (CX) destroyed.
362 ; Does a direct call to the AT ROM.
364 ; EFFECTS: Calls int 15h, function 9000h.
373 ;*** WAIT_DRQ - Wait for data request.
377 ; EXIT: DISK_STATUS1 = Error code.
378 ; CY if error, NC if no error.
381 ; WARNING: (AL), (CX), (DX) destroyed.
382 ; Does a direct call to the AT ROM.
391 ;*** CHECK_STATUS - Check hard disk status.
395 ; EXIT: DISK_STATUS1 = Error code.
396 ; NZ if error, ZR if no error.
399 ; WARNING: (AX), (CX), (DX) destroyed.
400 ; Does a direct call to the AT ROM.
402 CHECK_STATUS PROC
NEAR
409 ;*** CHECK_DMA - check for DMA overrun 64k segment.
411 ; ENTRY: (ES:BX) = addr. of memory buffer in seg:000x form.
412 ; CMD_BLOCK set up for operation.
414 ; EXIT: DISK_STATUS1 - Error code.
415 ; CY if error, NC if no error.
418 ; WARNING: Does a direct call to the AT ROM.