summaryrefslogtreecommitdiff
path: root/v4.0/src/BIOS/MSHARD.ASM
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/BIOS/MSHARD.ASM
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/BIOS/MSHARD.ASM')
-rw-r--r--v4.0/src/BIOS/MSHARD.ASM427
1 files changed, 427 insertions, 0 deletions
diff --git a/v4.0/src/BIOS/MSHARD.ASM b/v4.0/src/BIOS/MSHARD.ASM
new file mode 100644
index 0000000..51c0dc8
--- /dev/null
+++ b/v4.0/src/BIOS/MSHARD.ASM
@@ -0,0 +1,427 @@
1;***
2; Title: Disk
3; C: (C) Copyright 1988 by Microsoft corp.
4; Date: 1/11/85
5;
6; There is a bug in some versions of IBM's AT ROM BIOS.
7; Interrupts are not disabled during read operations.
8;
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.
15;
16
17
18 .286c ;Use 80286 non-protected mode
19
20BIOSEG = 040h ;Segment for ROM BIOS Data
21ROMSEG = 0F000h ;Segment of ROM
22
23
24BAD_DISK = 01
25
26HF_PORT = 01F0h
27HF_REG_PORT = 03F6h
28
29;* Offsets into Fixed disk parameter table
30FDP_PRECOMP = 5
31FDP_CONTROL = 8
32
33DATA SEGMENT AT BIOSEG ;ROM BIOS data segment
34
35 ORG 42h
36CMD_BLOCK DB 6 DUP (?)
37
38;* Offsets into CMD_BLOCK for registers
39PRE_COMP = 0 ;Write Pre-compensation
40SEC_CNT = 1 ;Sector count
41SEC_NUM = 2 ;Sector number
42CYL_LOW = 3 ;Cylinder number, low part
43CYL_HIGH = 4 ;Cylinder number, high part
44DRV_HEAD = 5 ;Drive/Head (Bit 7 = ECC mode, Bit 5 = 512 byte sectors,
45 ; Bit 4 = drive number, Bits 3-0 have head number)
46CMD_REG = 6 ;Command register
47
48
49 ORG 074h
50
51DISK_STATUS1 DB ?
52HF_NUM DB ?
53CONTROL_BYTE DB ?
54
55DATA ENDS
56
57
58
59;*** Define where the ROM routines are actually located
60ROM SEGMENT AT ROMSEG
61
62 ORG 02E1Eh
63ROMCOMMAND PROC FAR
64ROMCOMMAND ENDP
65
66 ORG 02E7Fh
67ROMWAIT PROC FAR
68ROMWAIT ENDP
69
70 ORG 02EE2h
71ROMWAIT_DRQ PROC FAR
72ROMWAIT_DRQ ENDP
73
74 ORG 02EF8h
75ROMCHECK_STATUS PROC FAR
76ROMCHECK_STATUS ENDP
77
78 ORG 02F69h
79ROMCHECK_DMA PROC FAR
80ROMCHECK_DMA ENDP
81
82 ORG 02F8Eh
83ROMGET_VEC PROC FAR
84ROMGET_VEC ENDP
85
86 ORG 0FF65h
87ROMFRET PROC FAR ;Far return at F000:FF65 in AT ROM.
88ROMFRET ENDP
89
90ROM ENDS
91
92
93CODE SEGMENT BYTE PUBLIC 'code'
94
95EXTRN OLD13:DWORD ;Link to AT bios int 13h
96
97PUBLIC IBM_DISK_IO
98
99
100 ASSUME CS:CODE
101 ASSUME DS:DATA
102
103
104;*** IBM_DISK_IO - main routine, fixes AT ROM bug
105;
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.
115;
116; EXIT: (AH) = status of current operation.
117; (CY) = 1 IF failed, 0 if successful.
118; For other register contents see ROM BIOS listing.
119;
120; USES:
121;
122;
123; WARNING: Uses OLD13 vector for non-read calls.
124; Does direct calls to the AT ROM.
125; Does segment arithmatic.
126;
127; EFFECTS: Performs DISK I/O operation.
128;
129IBM_DISK_IO PROC FAR
130 CMP DL, 80h
131 JB ATD1 ;Pass through floppy disk calls.
132 CMP AH, 02
133 JE ATD2 ;Intercept call 02 (read sectors).
134 CMP AH, 0Ah
135 JE ATD2 ;and call 0Ah (read long).
136ATD1:
137 JMP OLD13 ;Use ROM INT 13h handler.
138ATD2:
139 PUSH BX
140 PUSH CX
141 PUSH DX
142 PUSH DI
143 PUSH DS
144 PUSH ES
145 PUSH AX
146 MOV AX,BIOSEG ;Establish BIOS segment addressing.
147 MOV DS,AX
148 MOV DISK_STATUS1, 0 ;Initially no error code.
149 AND DL, 07fh ;Mask to hard disk number
150 CMP DL, HF_NUM
151 JB ATD3 ;Disk number in range
152 MOV DISK_STATUS1, BAD_DISK
153 JMP SHORT ATD4 ;Disk number out of range error, return
154
155ATD3:
156 PUSH BX
157 MOV AX, ES ;Make ES:BX to Seg:000x form.
158 SHR BX, 4
159 ADD AX, BX
160 MOV ES, AX
161 POP BX
162 AND BX,000Fh
163 PUSH CS
164 CALL CHECK_DMA
165 JC ATD4 ;Abort if DMA across segment boundary
166
167 POP AX ;Restore AX register for SETCMD
168 PUSH AX
169 CALL SETCMD ;Set up command block for disk op
170 MOV DX, HF_REG_PORT
171 OUT DX, AL ;Write out command modifier
172 CALL DOCMD ;Carry out command
173ATD4:
174;; Old code - Carry cleared after set by logical or opearation
175;; POP AX
176;; MOV AH,DISK_STATUS1 ;On return AH has error code
177;; STC
178;; OR AH,AH
179;; JNZ ATD5 ;Carry set if error
180;; CLC
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.
184 POP AX
185 MOV AH,DISK_STATUS1 ;On return AH has error code
186 OR AH,AH
187 JZ ATD5 ;Carry set if error
188 STC
189
190ATD5:
191 POP ES
192 POP DS
193 POP DI
194 POP DX
195 POP CX
196 POP BX
197 RET 2 ;Far return, dropping flags
198IBM_DISK_IO ENDP
199
200
201
202;*** SETCMD - Set up CMD_BLOCK for the disk operation
203;
204; ENTRY: (DS) = BIOS Data segment.
205; (ES:BX) in seg:000x form.
206; Other registers as in INT 13h call
207;
208; EXIT: CMD_BLOCK set up for disk read call.
209; CONTROL_BYTE set up for disk operation.
210; (AL) = Control byte modifier
211;
212;
213; Sets the fields of CMD_BLOCK using the register contents
214; and the contents of the disk parameter block for the given drive.
215;
216; WARNING: (AX) destroyed.
217; Does direct calls to the AT ROM.
218;
219SETCMD PROC NEAR
220 MOV CMD_BLOCK[SEC_CNT], AL
221 MOV CMD_BLOCK[CMD_REG], 020h ;Assume function 02
222 CMP AH, 2
223 JE SETC1 ;CMD_REG = 20h if function 02 (read)
224 MOV CMD_BLOCK[CMD_REG], 022h ;CMD_REG = 22h if function 0A (" long)
225SETC1: ;No longer need value in AX
226 MOV AL, CL
227 AND AL, 03fh ;Mask to sector number
228 MOV CMD_BLOCK[SEC_NUM], AL
229 MOV CMD_BLOCK[CYL_LOW], CH
230 MOV AL, CL
231 SHR AL, 6 ;Get two high bits of cylender number
232 MOV CMD_BLOCK[CYL_HIGH], AL
233 MOV AX, DX
234 SHL AL, 4 ;Drive number
235 AND AH, 0Fh
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
240 PUSH BX
241 PUSH CS
242 CALL GET_VEC
243 MOV AX, ES:FDP_PRECOMP[BX] ;Write pre-comp from disk parameters
244 SHR AX, 2
245 MOV CMD_BLOCK[PRE_COMP],AL ;Only use low part
246 MOV AL, ES:FDP_CONTROL[BX] ;Control byte modifier
247 POP BX
248 POP ES
249 MOV AH, CONTROL_BYTE
250 AND AH, 0C0h ;Keep disable retry bits
251 OR AH, AL
252 MOV CONTROL_BYTE, AH
253 RET
254SETCMD ENDP
255
256
257
258;*** DOCMD - Carry out READ operation to AT hard disk
259;
260; ENTRY: (ES:BX) = address for read in data.
261; CMD_BLOCK set up for disk read.
262;
263; EXIT: Buffer at (ES:BX) contains data read.
264; DISK_STATUS1 set to error code (0 if success).
265;
266;
267;
268; WARNING: (AX), (BL), (CX), (DX), (DI) destroyed.
269; No check is made for DMA boundary overrun.
270;
271; EFFECTS: Programs disk controller.
272; Performs disk input.
273;
274DOCMD PROC NEAR
275 MOV DI, BX ;(ES:DI) = data buffer addr.
276 PUSH CS
277 CALL COMMAND
278 JNZ DOC3
279DOC1:
280 PUSH CS
281 CALL WAITT ;Wait for controller to complete read
282 JNZ DOC3
283 MOV CX, 100h ;256 words per sector
284 MOV DX, HF_PORT
285 CLD ;String op goes up
286 CLI ;Disable interrupts (BUG WAS FORGETTING THIS)
287 REPZ INSW ;Read in sector
288 STI
289 TEST CMD_BLOCK[CMD_REG], 02
290 JZ DOC2 ;No ECC bytes to read.
291 PUSH CS
292 CALL WAIT_DRQ
293 JC DOC3
294 MOV CX, 4 ;4 bytes of ECC
295 MOV DX, HF_PORT
296 CLI
297 REPZ INSB ;Read in ECC
298 STI
299DOC2:
300 PUSH CS
301 CALL CHECK_STATUS
302 JNZ DOC3 ;Operation failed
303 DEC CMD_BLOCK[SEC_CNT]
304 JNZ DOC1 ;Loop while more sectors to read
305DOC3:
306 RET
307DOCMD ENDP
308
309
310
311;*** GET_VEC - Get pointer to hard disk parameters.
312;
313; ENTRY: (DL) = Low bit has hard disk number (0 or 1).
314;
315; EXIT: (ES:BX) = address of disk parameters table.
316;
317; USES: AX for segment computation.
318;
319; Loads ES:BX from interrupt table in low memory, vector 46h (disk 0)
320; or 70h (disk 1).
321;
322; WARNING: (AX) destroyed.
323; This does a direct call to the AT ROM.
324;
325GET_VEC PROC NEAR
326 PUSH OFFSET ROMFRET
327 JMP ROMGET_VEC
328GET_VEC ENDP
329
330
331
332;*** COMMAND - Send contents of CMD_BLOCK to disk controller.
333;
334; ENTRY: Control_byte
335; CMD_BLOCK - set up with values for hard disk controller.
336;
337; EXIT: DISK_STATUS1 = Error code.
338; NZ if error, ZR for no error.
339;
340;
341; WARNING: (AX), (CX), (DX) destroyed.
342; Does a direct call to the AT ROM.
343;
344; EFFECTS: Programs disk controller.
345;
346COMMAND PROC NEAR
347 PUSH OFFSET ROMFRET
348 JMP ROMCOMMAND
349COMMAND ENDP
350
351
352
353;*** WAITT - Wait for disk interrupt
354;
355; ENTRY: Nothing.
356;
357; EXIT: DISK_STATUS1 = Error code.
358; NZ if error, ZR if no error.
359;
360;
361; WARNING: (AX), (BL), (CX) destroyed.
362; Does a direct call to the AT ROM.
363;
364; EFFECTS: Calls int 15h, function 9000h.
365;
366WAITT PROC NEAR
367 PUSH OFFSET ROMFRET
368 JMP ROMWAIT
369WAITT ENDP
370
371
372
373;*** WAIT_DRQ - Wait for data request.
374;
375; ENTRY: Nothing.
376;
377; EXIT: DISK_STATUS1 = Error code.
378; CY if error, NC if no error.
379;
380;
381; WARNING: (AL), (CX), (DX) destroyed.
382; Does a direct call to the AT ROM.
383;
384WAIT_DRQ PROC NEAR
385 PUSH OFFSET ROMFRET
386 JMP ROMWAIT_DRQ
387WAIT_DRQ ENDP
388
389
390
391;*** CHECK_STATUS - Check hard disk status.
392;
393; ENTRY: Nothing.
394;
395; EXIT: DISK_STATUS1 = Error code.
396; NZ if error, ZR if no error.
397;
398;
399; WARNING: (AX), (CX), (DX) destroyed.
400; Does a direct call to the AT ROM.
401;
402CHECK_STATUS PROC NEAR
403 PUSH OFFSET ROMFRET
404 JMP ROMCHECK_STATUS
405CHECK_STATUS ENDP
406
407
408
409;*** CHECK_DMA - check for DMA overrun 64k segment.
410;
411; ENTRY: (ES:BX) = addr. of memory buffer in seg:000x form.
412; CMD_BLOCK set up for operation.
413;
414; EXIT: DISK_STATUS1 - Error code.
415; CY if error, NC if no error.
416;
417;
418; WARNING: Does a direct call to the AT ROM.
419;
420CHECK_DMA PROC NEAR
421 PUSH OFFSET ROMFRET
422 JMP ROMCHECK_DMA
423CHECK_DMA ENDP
424
425
426CODE ENDS
427 END