1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
|
include MSBDS.INC ;include BDS struc ;an000; dms;
;=========================================================================
; I13_Handler - This routine is the main driver of the
; INT 13h hook.
;=========================================================================
I13_Handler proc far ; ;an000; dms;
jmp I13_Handler_Start
I13_Max_Head db ? ;max head count on drive ;an000; dms;
I13_SPT db ? ;max sectors/track count ;an000; dms;
I13_BPS dw ? ;max number bytes/sector ;an000; dms;
I13_Bytes_Per_Para dw 10h ;number of bytes per paragraph ;an000; dms;
I13_Bytes_Per_EMS_Page dw 4000h ;bytes per EMS page ;an000; dms;
I13_Paras_Per_Sector dw ? ;paras per sector ;an000; dms;
I13_DD_Per_Sector dw ? ;double words per sector ;an000; dms;
I13_Operation db ? ;INT 13h function ;an000; dms;
I13_Sector_Count db ? ;sector count ;an000; dms;
I13_Track_Number dw ? ;track number ;an000; dms;
I13_Sector_Number db ? ;sector number ;an000; dms;
I13_Head_Number db ? ;head number ;an000; dms;
I13_Drive_Number db ? ;drive number ;an000; dms;
I13_Sectors_To_Trf db 1 ;current sectors to trf ;an000; dms;
I13_Curr_Trf_Cnt db ? ;total transfer count in secs ;an000; dms;
I13_Trf_Off dw ? ;current address for trf ;an000; dms;
I13_Trf_Seg dw ? ;an000; dms;
I13_512_Byte_Buffer db 512 dup(0) ;buffer for sector ;an000; dms;
I13_Handler_Start:
sti ;ints on ;an000; dms;
cmp ah,02h ;read operation? ;an000; dms;
je I13_Handler_Get_Parms ;yes - get drive parms ;an000; dms;
cmp ah,03h ;write operation? ;an000; dms;
je I13_Handler_Get_Parms ;yes - get drive parms ;an000; dms;
jmp cs:IntV13 ;neither - go to old INT 13h ;an000; dms;
I13_Handler_Get_Parms:
call I13_Get_Dev_Parms ;get device parms for this drive;an000; dms;
jnc I13_Handler_Range_Ck ;we have device data ;an000; dms;
jmp cs:IntV13 ;go to old INT 13h vector ;an000; dms;
I13_Handler_Range_Ck:
call I13_Target_Source_Range_Ck ;crosses the 640k boundary? ;an000; dms;
jc I13_Handler_Request_Break ;break up the request ;an000; dms;
jmp cs:IntV13 ;go to old INT 13h vector ;an000; dms;
I13_Handler_Request_Break:
call I13_Request_Break_Up ;break up I13 request ;an000; dms;
ret 2 ;return to caller ;an000; dms;
;clear the flags from the stack
; and pass back ours
I13_Handler endp ; ;an000; dms;
;=========================================================================
; I13_Target_Source_Range_Ck - This routine determines if the
; target or source resides in an EMS
; page.
;
; Inputs : ES:BX - Source/target address
;
; Outputs : CY - if address resides in an EMS page
; NC - address not in an EMS page
;=========================================================================
I13_Target_Source_Range_Ck proc near ; ;an000; dms;
push ax ;save regs ;an000; dms;
push bx ; ;an000; dms;
push cx ; ;an000; dms;
push si ; ;an000; dms;
push ds ; ;an000; dms;
mov ax,cs ;get cs addressibility ;an000; dms;
mov ds,ax ; ;an000; dms;
mov si,offset cs:Map_Table ;point to the map table ;an000; dms;
mov cx,cs:Map_Count ;get the number of phys. pages ;an000; dms;
I13_Target_Source_Loop:
cmp cx,0 ;at end? ;an000; dms;
je I13_Target_Source_Not_EMS_Page ;yes - source/target not in pg ;an000; dms;
mov ax,ds:[si].Phys_Page_Segment ;get the segment value ;an000; dms;
mov bx,es ; ;an000; dms;
cmp bx,ax ;source/target > EMS page? ;an000; dms;
jb I13_Target_Source_Not_EMS_Page ;no - we are OK for old INT 13 ;an000; dms;
;must be >= EMS page
add ax,400h ;get end address of EMS page ;an000; dms;
cmp bx,ax ;source/target < end of EMS pg? ;an000; dms;
jb I13_Target_Source_In_EMS_Page ;yes - we are in a page ;an000; dms;
add si,type Mappable_Phys_Page_Struct ;adjust pointer to next page ;an000; dms;
dec cx ;dec counter ;an000; dms;
jmp I13_Target_Source_Loop ;continue loop ;an000; dms;
I13_Target_Source_Not_EMS_Page:
clc ;flag not in EMS page ;an000; dms;
jmp I13_Target_Source_Exit ;exit routine ;an000; dms;
I13_Target_Source_In_EMS_Page:
stc ;flag in an EMS page ;an000; dms;
I13_Target_Source_Exit:
pop ds ;restore regs ;an000; dms;
pop si ; ;an000; dms;
pop cx ; ;an000; dms;
pop bx ; ;an000; dms;
pop ax ; ;an000; dms;
ret ; ;an000; dms;
I13_Target_Source_Range_Ck endp ; ;an000; dms;
;=========================================================================
; I13_Request_Break_Up - Break up the INT 13h request onto 16k
; boundaries.
;
; Inputs : AH - 02 (Read)
; 03 (Write)
; AL - Sector count
; CH - Track number
; CL - Sector number
; DH - Head number
; DL - Drive number
; ES:BX - Buffer address
;
; Outputs : Data transferred
;=========================================================================
I13_Request_Break_Up proc near ; ;an000; dms;
push bx ;save regs ;an000; dms;
push cx ; ;an000; dms;
push dx ; ;an000; dms;
push di ; ;an000; dms;
push si ; ;an000; dms;
push ds ; ;an000; dms;
push es ; ;an000; dms;
mov cs:I13_Trf_Seg,es ;save segment ;an000; dms;
mov cs:I13_Trf_Off,bx ;save offset ;an000; dms;
mov cs:I13_Curr_Trf_Cnt,0 ;init transfer count ;an000; dms;
mov cs:I13_Operation,ah ;save operation ;an000; dms;
mov cs:I13_Sector_Count,al ;save sector count ;an000; dms;
mov byte ptr cs:I13_Track_Number,ch ;save starting track number ;an000; dms;
mov ch,cl ;xchg bytes ;an000; dms;
shr ch,1 ;shift 6 bits ;an000; dms;
shr ch,1 ; ;an000; dms;
shr ch,1 ; ;an000; dms;
shr ch,1 ; ;an000; dms;
shr ch,1 ; ;an000; dms;
shr ch,1 ; ;an000; dms;
mov byte ptr cs:I13_Track_Number[+1],ch ;high byte for cylinder ;an000; dms;
and cl,00111111b ;get bits 0-5 for sector number ;an000; dms;
mov cs:I13_Sector_Number,cl ;save starting sector number ;an000; dms;
mov cs:I13_Head_Number,dh ;save starting head number ;an000; dms;
mov cs:I13_Drive_Number,dl ;save drive number ;an000; dms;
mov cl,cs:I13_Sector_Count ;while sectors ;an000; dms;
cmp cs:I13_Operation,02h ;read? ;an000; dms;
jne I13_Request_Write ;must be a write ;an000; dms;
I13_Request_Read:
cmp cl,0 ;at end? ;an000; dms;
je I13_Request_Success ;exit we are done ;an000; dms;
lea bx,cs:I13_512_Byte_Buffer ;point to 512 byte buffer ;an000; dms;
mov ax,cs ;pass cs to es ;an000; dms;
mov es,ax ; ;an000; dms;
call I13_Invoke ;do the INT 13h to our buffer ;an000; dms;
jc I13_Request_Failed ;signal failure ;an000; dms;
mov ax,cs ;point to our buffer to the ;an000; dms;
mov ds,ax ; transfer ;an000; dms;
mov si,offset cs:I13_512_Byte_Buffer; ;an000; dms;
mov es,cs:I13_Trf_Seg ;restore seg to target ;an000; dms;
mov di,cs:I13_Trf_Off ;restore off to target ;an000; dms;
push cx ;save cx across move ;an000; dms;
cld ;do a forward move ;an000; dms;
mov cx,cs:I13_DD_Per_Sector ; for 128 dd's ;an000; dms;
db 66h ;op code for dd word move ;an000; dms;
rep movsw ;do the move - wow that was fast;an000; dms;
pop cx ;restore it ;an000; dms;
call I13_Adjust ;adjust our pointers ;an000; dms;
dec cl ;decrease sector counter ;an000; dms;
jmp I13_Request_Read ;continue loop ;an000; dms;
I13_Request_Write:
cmp cl,0 ;at end? ;an000; dms;
je I13_Request_Success ;exit we are done ;an000; dms;
mov ax,cs ;point to 512 byte buffer ;an000; dms;
mov es,ax ; ;an000; dms;
mov di,offset cs:I13_512_Byte_Buffer; ;an000; dms;
mov ds,cs:I13_Trf_Seg ;get source segment ;an000; dms;
mov si,cs:I13_Trf_Off ;get source offset ;an000; dms;
push cx ;save cx across move ;an000; dms;
cld ;do a forward move ;an000; dms;
mov cx,cs:I13_DD_Per_Sector ; for 128 dd's ;an000; dms;
db 66h ;op code for dd word move ;an000; dms;
rep movsw ;do the move - wow that was fast;an000; dms;
pop cx ;restore it ;an000; dms;
lea bx,cs:I13_512_Byte_Buffer ;point to 512 byte buffer ;an000; dms;
mov ax,cs ;pass cs to es ;an000; dms;
mov es,ax ; ;an000; dms;
call I13_Invoke ;do the INT 13h to our buffer ;an000; dms;
jc I13_Request_Failed ;signal failure ;an000; dms;
call I13_Adjust ;adjust our pointers ;an000; dms;
dec cl ;decrease sector counter ;an000; dms;
jmp I13_Request_Write ;continue loop ;an000; dms;
I13_Request_Failed:
jmp I13_Request_Exit ;exit on error ;an000; dms;
I13_Request_Success:
xor ax,ax ;clear status byte ;an000; dms;
I13_Request_Exit:
pop es ;restore regs ;an000; dms;
pop ds ; ;an000; dms;
pop si ; ;an000; dms;
pop di ; ;an000; dms;
pop dx ; ;an000; dms;
pop cx ; ;an000; dms;
pop bx ; ;an000; dms;
ret ; ;an000; dms;
I13_Request_Break_Up endp ; ;an000; dms;
;=========================================================================
; I13_Adjust - This routine adjusts the needed fields for
; the next iteration of INT 13h.
;
; Inputs : I13_Sectors_To_Trf - Sectors just read/written
; I13_Sector_Number - Starting sector number for trf
; I13_Head_Number - Starting head number for trf
; I13_Track_Number - Starting track number for trf
;
; Outputs : I13_Sector_Number - New starting sector for trf
; I13_Head_Number - New starting head for trf
; I13_Track_Number - New starting track for trf
;=========================================================================
I13_Adjust proc near ;adjust values ;an000; dms;
push ax ;save regs ;an000; dms;
inc cs:I13_Sector_Number ;next sector ;an000; dms;
mov al,cs:I13_Sector_Number ; ;an000; dms;
cmp al,cs:I13_SPT ;> sectors on track? ;an000; dms;
jna I13_Adjust_Exit ;no ;an000; dms;
mov cs:I13_Sector_Number,1 ;yes - start at next ;an000; dms;
inc cs:I13_Head_Number ;next head ;an000; dms;
mov al,cs:I13_Head_Number ; ;an000; dms;
cmp al,cs:I13_Max_Head ;> head count ;an000; dms;
jb I13_Adjust_Exit ;no ;an000; dms;
mov cs:I13_Head_Number,0 ;yes - head 0 ;an000; dms;
inc cs:I13_Track_Number ;next track ;an000; dms;
I13_Adjust_Exit:
mov ax,cs:I13_Paras_Per_Sector ;get bytes per sector ;an000; dms;
add cs:I13_Trf_Seg,ax ;adjust segment ;an000; dms;
pop ax ;restore regs ;an000; dms;
ret ; ;an000; dms;
I13_Adjust endp ; ;an000; dms;
;=========================================================================
; I13_Invoke - This routine sets up the regs for the INT 13h
; and invokes it for the sector we need.
;
; Inputs : I13_Operation - read/write
; I13_Track_Number - cylinder to read/write
; I13_Sector_Number - starting sector for read/write
; I13_Head_Number - starting head
; I13_Drive_Number - starting drive
;
; Outputs : NC - good read/write
; CY - bad read/write
;=========================================================================
I13_Invoke proc near ;invoke INT 13h ;an000; dms;
push bx ;save regs ;an000; dms;
push cx ; ;an000; dms;
push dx ; ;an000; dms;
mov ah,cs:I13_Operation ;get function call ;an000; dms;
mov al,cs:I13_Sectors_To_Trf ;get sectors to transfer ;an000; dms;
mov ch,byte ptr cs:I13_Track_Number ;get track number ;an000; dms;
mov cl,byte ptr cs:I13_Track_Number[+1] ;get high 2 bits ;an000; dms;
shl cl,1 ;put bit is positions 6&7 ;an000; dms;
shl cl,1 ; ;an000; dms;
shl cl,1 ; ;an000; dms;
shl cl,1 ; ;an000; dms;
shl cl,1 ; ;an000; dms;
shl cl,1 ; ;an000; dms;
or cl,cs:I13_Sector_Number ;place the sector number in cl ;an000; dms;
mov dh,cs:I13_Head_Number ;get head number ;an000; dms;
mov dl,cs:I13_Drive_Number ;get drive number ;an000; dms;
pushf
call cs:IntV13 ;go to old vector ;an000; dms;
inc cs:I13_Curr_Trf_Cnt ;increment counter ;an000; dms;
pop dx ;restore regs ;an000; dms;
pop cx ; ;an000; dms;
pop bx ; ;an000; dms;
ret ; ;an000; dms;
I13_Invoke endp ; ;an000; dms;
;=========================================================================
; I13_Get_Dev_Parms - This routine obtains the device parameters for
; the drive being accessed for the INT 13h.
;
; Inputs : DL - drive number
;
; Outputs : I13_Max_Head - max head count on drive
; I13_SPT - max sectors/track count for drive
; CY - error
; NC - no error
;=========================================================================
I13_Get_Dev_Parms proc near ;get sectors/track & head cnt. ;an000; dms;
push ax ;save regs ;an000; dms;
push bx ; ;an000; dms;
push cx ; ;an000; dms;
push dx ; ;an000; dms;
push di ; ;an000; dms;
push ds ; ;an000; dms;
mov ax,0803h ;get the BDS table ;an000; dms;
int 2fh ; ;an000; dms;
I13_Get_Dev_Next_Entry:
cmp ds:[di].Drivenum,dl ;do we have our drive? ;an000; dms;
je I13_Get_Dev_Save_Parms ;yes get data ;an000; dms;
cmp word ptr ds:[di].Link[+0],-1 ;last entry in list? ;an000; dms;
je I13_Get_Dev_Parms_Error_Exit ;yes - did not find drive ;an000; dms;
mov ax,word ptr ds:[di].Link[+0] ;get offset of next entry ;an000; dms;
mov bx,word ptr ds:[di].Link[+2] ;get segment of next entry ;an000; dms;
mov ds,bx ;stuff into ds:di ;an000; dms;
mov di,ax ; ;an000; dms;
jmp I13_Get_Dev_Next_Entry ;continue ;an000; dms;
I13_Get_Dev_Save_Parms:
mov ax,ds:[di].BytePerSec ;get byte count per sector ;an000; dms;
mov cs:I13_BPS,ax ; ;an000; dms;
xor dx,dx ;clear high word ;an000; dms;
div cs:I13_Bytes_Per_Para ;get number of paras in sector ;an000; dms;
mov cs:I13_Paras_Per_Sector,ax ;save it ;an000; dms;
shl ax,1 ;get DD's per sector ;an000; dms;
shl ax,1 ; ;an000; dms;
mov cs:I13_DD_Per_Sector,ax ; ;an000; dms;
mov ax,ds:[di].SecLim ;get sectors per track ;an000; dms;
mov cs:I13_SPT,al ; ;an000; dms;
mov ax,ds:[di].HdLim ;get max head count ;an000; dms;
mov cs:I13_Max_Head,al ; ;an000; dms;
clc ;flag data found ;an000; dms;
jmp I13_Get_Dev_Parms_Exit ; ;an000; dms;
I13_Get_Dev_Parms_Error_Exit:
stc ;flag no data found ;an000; dms;
I13_Get_Dev_Parms_Exit:
pop ds ;restore regs ;an000; dms;
pop di ; ;an000; dms;
pop dx ; ;an000; dms;
pop cx ; ;an000; dms;
pop bx ; ;an000; dms;
pop ax ; ;an000; dms;
ret ; ;an000; dms;
I13_Get_Dev_Parms endp ; ;an000; dms;
|