forked from roelandjansen/pcmos386v501
/
MOSDDBLK.ASM
2771 lines (2526 loc) · 71.5 KB
/
MOSDDBLK.ASM
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
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
include page.inc
title mosddblk - mos device driver for drive i/o
comment ^==============================================================
development specification
program name: mos.com assigned to: david a. morrow
module name: mosddblk assign date: 04/24/86
entry points: blkintr, blkstrat completed: 02/14/87
entry from: todriver
entry method: far call
calls: n/a
purpose: mos block device driver (diskette and fixed disk)
refer to: n/a
last update: 03/09/87
=======================================================================
jsm 12/22/86 support 1.2 meg floppies in 1.2 meg drives
jsm 02/14/87 change a/b drive support
jsm 03/09/87 fix problems in getparms & setparms w/diskcopy
jsm 05/06/87 add new disk type, dtold, for 360k drives on pc's with
pre-at rom bios's. Change all tests for 360K vs. 1.2M
drives from comparisons with dtnochg (at 360k drive) to
comparisons with dtchg (at 1.2m drive), so dtold &
dtnochg will be treated almost equivalently. only
difference is that format track call won't set disk
type for dtold drives, but will set it for dtnochg.
rbr 07/08/87 did away with disk types: dtold, dtchg, dtnochg, etc.
substituted 3 new flags: dtsmall indicates 3.5" drive,
dthicap indicates 1.2m or 1.44m format, and dtchgln
indicates if there is a change line available. tables
and code were added/changed as necessary to support
the 3.5" formats. For an AT or PS/2 class machine,
we check cmos for diskette types because bios calls
can't always tell us if there's a 1.44m drive. for
the model 30, 720k drives are assumed. did away with
the "isat" flag, and added "dprmptr" to point to the
default diskette parameter table for the system.
rbr 07/11/87 removed some redundant code.
rbr 07/13/87 fixed a neg that should have been a not. my error.
rbr 07/18/87 fixed inability to write to 1.44m diskettes.
sah 01/20/88 change scbseg and zero seg to mgetxxxx macros
rbr 02/07/88 fixed problem with incorrect disk parms when formatting
the toshiba t3100 3.5" diskette drive.
sah 02/21/88 rbr/sah move ddt code to mo2 group.
rbr 03/13/88 see comment near beginning of "isdrive" proc.
mjs 4/11/88 added tests to skip retries if a disk operation fails
due to a time out error. this is to speed up the
response in the case where the drive door is open
(e.g. zenith/navy - took minutes to get a crit err).
made similar mods to mosfutil.asm.
jrb 05/02/88 get/set logical drive corrections. add word of 0 in
dib so hidden is a correct dd
jrb 06/03/88 changed sense of ibm bit - current dos drivers
(including us) are not ibm devices - that is, they
don't require the first fat sector on a build bpb call
sah 08/26/88 made corrections in handling of change line so that if
bios returns that disk line has change that we actually
return that it did change. ptr 120
sah 09/09/88 corrected problems with format with above addition
rkg 10/17/88 problems with format tracked to wrong error code
returned from int 13. expanded table and merged hard
and floppy code.
rkg 12/01/88 problems with secondary 360s and 3.5" drives caused
by inappropriate diskette parameter table. format now
uses the parm table returned by int 13, func 18 and
initialization code creates a compatible table for all
diskettes.
rkg 12/05/88 spurious problems caused by not reseting drives after
timeouts. changed mjs 4/11/88 to reset before return
rkg 12/07/88 problems with zenith corrected by format sequence
changes.
rkg 12/09/88 problems with toshiba corrected. int 13 function 17
may not be present but must always set sectors/track
in the disk parms. also reverted to executing funct 17
then 18 for zenith disk change line
rkg 12/12/88 change handling of func 17 and 18 for the last time
bwr 11/28/89 marked messages for foreign language translation.
bwr 03/01/90 minor bug fix for toshiba 5200 high density floppy
drive.
mjs 12/16/91 dlg mods: added support for i21f44s0ds0846,
i21f44s0ds0866 and i21f44s11. converted to use of
structures within dskstruc.inc.
======================================================================^
.xlist
include mosddblk.pub
include mosregs.inc
include group.inc
include dskstruc.inc
.list
tcb segment at 1234h
tcb ends
irq segment byte public 'data'
dw 1eh*4 ; diskette parm pointer
dd ? ; old pointer saved here (although not needed)
dw 0 ; do not save any application changes
dw grp:diskprm ; point vector to our disk parms
dw 0 ; no second level
irq ends
poll segment byte public 'data'
poll ends
ddt segment word public 'code2'
ddt ends
page
gdata segment word public 'data'
extrn media13:byte
public diskprm
; bits in the attribute byte in the dib block
dtsmall equ 01h ; set if 3.5" drive, 0 means 5.25" drive
dthicap equ 02h ; set if high capacity drive (1.2m or 1.44m)
dtchgln equ 04h ; set if change line is available
loadbpb equ 08h ; set if bpb should be loaded from media
bpberr equ 10h ; set if error loading bpb from media
dirtybpb equ 20h ; set when we have to load bpb from disk
diskswap equ 40h ; set if we just did a disk swap
firstbpb equ 80h ; set first time bpb is loaded
; command subcodes for generic i/o control
setparms equ 040h ; set device parameters
getparms equ 060h ; get device parameters
wrttrack equ 041h ; write track on logical device
rdtrack equ 061h ; read track on logical device
fvtrack equ 042h ; format and verify track on logical device
vertrack equ 062h ; verify track on logical device
setmedid equ 046h ; set media id
getmedid equ 066h ; get media id
lblsiz equ 11 ; size of mos volume label
;==== device information block
dbpb_size equ 25 ; bytes for 1 bpb section of the dib
dib struc
; real bpb for unit
dibBytesPerSec dw 512 ; bytes per sector
dibSecPerClust db 1 ; sectors per cluster
dibResSectors dw 1 ; # of reserved sectors
dibFATs db 2 ; # of FAT tables
dibRootDirEnts dw 224 ; # of root directory entries
dibSectors dw 2400 ; total # of sectors
dibMedia db 0f9h ; media descriptor
dibFATsecs dw 7 ; # of sectors per FAT
dibSecPerTrack dw 15 ; # of sectors per track
dibHeads dw 2 ; # of heads
dibHiddenSecs dd 0 ; # of hidden sectors
dibHugeSectors dd 0 ; # of sectors when dibSectors == 0
; default bpb for unit
dibdBytesPerSec dw 512 ; bytes per sector
dibdSecPerClust db 1 ; sectors per cluster
dibdResSectors dw 1 ; # of reserved sectors
dibdFATs db 2 ; # of FAT tables
dibdRootDirEnts dw 224 ; # of root directory entries
dibdSectors dw 2400 ; total # of sectors
dibdMedia db 0f9h ; media descriptor
dibdFATsecs dw 7 ; # of sectors per FAT
dibdSecPerTrack dw 15 ; # of sectors per track
dibdHeads dw 2 ; # of heads
dibdHiddenSecs dd 0 ; # of hidden sectors
dibdHugeSectors dd 0 ; # of sectors when dibdSectors == 0
; other dib data
dibHeadMask dw 1 ; head mask
dibSectsPerCyl dw 30 ; sectors/cylinder (30 for 1.2 meg floppy)
dibTimerLo dw 0 ; last holding timer value
dibTimerHi dw 0 ; " " "
dibLabel db 12 dup (0) ; disk label
dibAttributes db 0 ; drive attributes
dibRealDrive db 0 ; drive number this drive really should be
dibLastDriveNum db 0 ; last drive number used for this drive
dibRealDIB dw 0 ; pointer to real dib for this drive
dib ends
;==== bpb data area
bpbpntr dw bpb1 ; for 1st unit
dw bpb2 ; for 2nd unit
bpb1 dib <> ; use default values
bpb2 dib <>
fatarr db 0f9h, 0fch, 0fdh, 0feh, 0ffh
falen equ $ - fatarr
bpbarr label byte
bpb12 bpb <512,1,1,2,224,2400,0f9h,7,15,2,0,0> ; first 5 match fatarr
bpb180 bpb <512,1,1,2,112, 360,0fch,2, 9,1,0,0>
bpb360 bpb <512,2,1,2,112, 720,0fdh,2, 9,2,0,0>
bpb160 bpb <512,1,1,2, 64, 320,0feh,1, 8,1,0,0>
bpb320 bpb <512,2,1,2,112, 640,0ffh,1, 8,2,0,0>
bpb720 bpb <512,2,1,2,112,1440,0f9h,3, 9,2,0,0> ; 3.5" BPB's
bpb14 bpb <512,1,1,2,224,2880,0f0h,9,18,2,0,0>
;==== track layout table
even
badlayout dw 0 ; non-zero if funny track layout
tracktable label word
dw 15 ; 15 entries in the default table
dw 1
sec1size dw 512 ; sector 1, 512 bytes long
dw 2,512
dw 3,512
dw 4,512
dw 5,512
dw 6,512
dw 7,512
dw 8,512
dw 9,512
dw 10,512
dw 11,512
dw 12,512
dw 13,512
dw 14,512
dw 15,512
; extra space for funny user tables
dw 16,512
dw 17,512
dw 18,512
dw 19,512
dw 20,512
maxtrktbl equ (($ - tracktable) / 4)
formattable label byte
db (maxtrktbl * 4) dup (?) ; table for format call
;==== miscellaneous data
even
hdr dw 0,0 ; header pointer
drvnum db 0 ; disk drive to use 0 or 1
biosfun db 0 ; temp holding for next disk function
dircnt dw ? ; max directory entries in root dir
maxdrv db -1 ; maximum drive number in use (-1 means none)
typrtr db 3 ; retry count for drive type
sectcnt dw 0 ; total count of sectors for read or write
sectstr dw 0 ; starting sector for next disk i/o in loop
giobuf dd 0 ; buffer pointer for doint generic i/o
fghead db 0 ; head for generic read/write/format/verify
fgtrack db 0 ; track for generic read/write/format/verify
startd db 0 ; starting absolute drive number (1=a)
t3100 db 'N' ; y if toshiba t3100
;==== rom bios disk parameter block
diskparm struc
dpsb1 db 0dfh ; specify byte 1 (step-rate time, head-unload)
dpsb2 db 002h ; specify byte 2 (head-load time, dma mode)
dpmwait db 025h ; wait time until motor turned off
dpbps db 002h ; bytes per sector (2==512)
dpeot db 00fh ; last sector number in a track
dprwgap db 01bh ; gap length between sectors for read/write
dpdatln db 0ffh ; data length if no sector length
dpfmgap db 054h ; gap length between sectors for formatting
dpfmval db 0f6h ; data value stored in formatted sectors
dphdstl db 001h ; head settle time
dpmstrt db 008h ; motor start-up time
db 0 ; spare for alignment
diskparm ends
;==== disk parameter blocks
; int 1e points to diskprm
int1e equ (1eh * 4)
even
diskprm diskparm <0dfh, 2, 25h, 2, 15, 1bh, 0ffh, 50h, 0f6h, 15, 2>
atdprm diskparm <0dfh, 2, 25h, 2, 15, 1bh, 0ffh, 54h, 0f6h, 2, 8>
pcdprm diskparm <0dfh, 2, 25h, 2, 9, 2ah, 0ffh, 50h, 0f6h, 15, 2>
psdprm diskparm <0afh, 2, 25h, 2, 18, 1bh, 0ffh, 6ch, 0f6h, 15, 4>
even
ftypes db 1,1 ; disk type codes drives a and b
;==== pointer to buffer for bpb read
even
secbuf dw 2 dup (?) ; pointer to buffer for reading in disk info
lblbuf db 12 dup (?) ; buffer for disk label
;==== prompt for disk swap message
switchmsg db 0ah, 0dh, 0ah, 0dh, " Put in diskette for disk drive " ;@@xlat
drvn db "A and press any key ", 0ah, 0dh, 0ah, 0dh, 0 ;@@xlat
;==== function table
even
ffuntbl dw finitblk ; 0 init
dw fmedck ; 1 media check
dw fbldbpb ; 2 build bpb
dw 0 ; 3 i/o control input
dw finput ; 4 input (read)
dw 0 ; 5 nondestructive input no wait
dw 0 ; 6 input status
dw 0 ; 7 input flush
dw foutput ; 8 output (write)
dw foutput ; 9 output with verify
dw 0 ; 10 output status
dw 0 ; 11 output flush
dw 0 ; 12 i/o control output
dw fdevopen ; 13 device open
dw fdevclose ; 14 device close
dw fremove ; 15 removable media
dw 0 ; 16 illegal
dw 0 ; 17 illegal
dw 0 ; 18 illegal
dw fgenioctl ; 19 generic ioctl
dw 0 ; 20 illegal
dw 0 ; 21 illegal
dw 0 ; 22 illegal
dw fgetlog ; 23 get logical device
dw fsetlog ; 24 set logical device
dw fioquery ; 25 query ioctl
fmax_func equ (($-ffuntbl)/2)-1
gdata ends
subttl mos segment - mos module code and local data
page
mosseg segment word public 'code1'
assume cs:mos,ds:nothing,es:nothing,ss:nothing
extrn mosheman:near, sbios:word
extrn bugerror:near
;==== device header
public scbstdblk
scbstdblk label byte
dd -1
; block, non-fat-id, removeable,
; get/set logical & generic ioctl
; (and why bit 0?)
dw 0010100001000001b
dw mos:blkstrat
dw mos:blkintr
db 8 dup (0) ; # devices passed at init
subttl blkstrat - block strategy routine
page
;======================================================================
;,fs
; blkstrat - block strategy routine
;
; this routine is the block drivers strategy routine, it just
; queues the dword pointer to the request header.
;
; in: es:bx -> request header
;
; out: the request header pointer is saved.
;
;,fe
;======================================================================
assume ds:nothing,es:nothing,ss:nothing
blkstrat proc far
push ds
mgetscb ds
assume ds:grp
mov [hdr],bx
mov [hdr+2],es
pop ds
assume ds:nothing
ret
blkstrat endp
subttl blkintr - block interrupt routine
page
;======================================================================
;,fs
; blkintr - block interrupt routine
;
; this is the block device drivers interrupt routine which will
; process mos's requested function.
;
; in:
;
; out:
;
;,fe
;======================================================================
assume ds:nothing,es:nothing,ss:nothing
blkintr proc far
pushf
push ax
push bx
push cx
push dx
push si
push di
push es
push ds
mgetscb ds
assume ds:grp
les bx,dword ptr [hdr]
mov al,es:[bx].rhUnit ; get unit code
mov [drvnum],al ; set disk to use
cmp al,[maxdrv] ; good unit code?
ja err2 ; if unit code bad
xor ah,ah
shl ax,1 ; convert unit code to table offset
mov si,ax
mov si,[si].bpbpntr ; pointer to dib structure
mov bl,es:[bx].rhFunction ; get command code
cmp bl,fmax_func ; check for invalid call
ja ferr1 ; if bad command code
mov dl,[drvnum] ; keep drive number in dl
xor bh,bh
shl bx,1
mov bx,[bx+ffuntbl] ; get address of appropriate routine
or bx,bx ; legal code?
jz ferr1 ; if illegal code
call bx ; call the function
frexit:
pop ds
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
popf
ret
ferr1:
les bx,dword ptr [hdr]
mov es:[bx].rhStatus,8103h ; return 'Unknown Command'
jmp frexit
err2:
les bx,dword ptr [hdr]
mov es:[bx].rhStatus,8101h ; return 'Unknown Unit'
jmp frexit
blkintr endp
subttl logtrans - do logical drive reassignment
page
;======================================================================
;,fs
; logtrans - do logical drive reassignment
;
; this routine checks for drive redirection. if the dibRealDrive field
; in the dib is non-zero, moves the new drive number into dl.
; it decrements the number to produce the real drive number,
; puts the real drive number in drvnum, and points si to the real
; dib structure.
;
; if the unit is directed to a "different" drive, calls the
; rom bios to print a switch disk message, then waits for a key
; to be pressed. loads a new bpb if the command code was neither
; media check nor build bpb.
;
; in: ax == unit # * 2
; bx == address of subfunction code
; dl == drive number given to driver by caller
; si -> dib for drive
; ds -> grp
;
; out: return values are set in the request header
;
;,fe
;======================================================================
assume ds:grp,es:nothing,ss:nothing
logtrans proc near
mov ah,[si].dibRealDrive ; check for redirection
or ah,ah ; is it redirected?
jnz log10 ; if redirected
ret ; if not redirected
; translate input drive number into real drive number
log10:
mov dl,ah
dec dl ; 1 means drive 0, 2 means drive 1, etc.
mov [drvnum],dl ; dl has real drive number
mov si,[si].dibRealDIB ; get real dib pointer
shr al,1 ; get original unit number back
cmp al,[si].dibLastDriveNum
jne log20 ; if using different drive number
ret
; prompt user to put right disk in drive
log20:
mov [si].dibLastDriveNum,al ; set new "current" drive
or [si].dibAttributes,diskswap ; make sure we load a new bpb
mov ah,[drvn]
and ah,0f0h ; change drive number for message
add ah,al ; to the one in al
inc ah ; add 1 for 0/1 bias
mov [drvn],ah ; new drive number for message
mov ax,offset switchmsg
call prtstr ; print the switch message
xor ax,ax ; zero ah
int 16h ; wait for the key press
; don't return until one found
cmp bx,offset fbldbpb ; is this media check or bldbpb?
jbe log30 ; if no reason for settype call
call settype ; get the disk type
log30:
ret
logtrans endp
subttl prtstr -- print string on user's console
page
;======================================================================
;,fs
; prtstr -- print string on user's console
;
; print a string on user's console. Uses ROM BIOS call 0eh to print
; the string one character at a time. the string must be terminated
; by a null (0) byte. the character will be printed white on a black
; background on color systems, normal attributes on monochrome.
;
; in: ds:ax points to the string to print.
; ds -> grp
;
; out: string printed
;
;,fe
;======================================================================
assume ds:grp,es:nothing,ss:nothing
prtstr proc near
push ax
push bx
push si
cld
mov si,ax
mov bl,07h ; white foreground, black background
prt10:
lodsb
or al,al ; last character?
jz prt20 ; if end of string
mov ah,0eh ; function 0eh, write tty to current page
int 010h ; write the character
jmp prt10 ; do it again
prt20:
pop si
pop bx
pop ax
ret
prtstr endp
subttl medck - media check
page
;======================================================================
;,fs
; medck - media check
;
; this routine processes the media check call (=1)
;
; in:
; ds -> grp
;
; out:
;
;,fe
;======================================================================
assume ds:grp,es:nothing,ss:nothing
fmedck proc near
call logtrans ; do drive reassignment
les bx,dword ptr [hdr]
test [si].dibAttributes,dirtybpb
jnz med20 ; if we must load new bpb
test [si].dibAttributes,diskswap
jnz med35 ; if we should return "maybe"
call timetest ; return al = 0 or 1
les bx,dword ptr [hdr]
or al,al ; disk change?
jnz med40 ; if < 2 seconds after success
test [si].dibAttributes,dtchgln ; change line available?
jz med40 ; no, jump
mov ah,16h
mov dl,[drvnum] ; get drive number back
int 13h ; ask bios about change line
cmp ah,0
jz med05 ; if change line in-active
push bx
mov bl,[drvnum]
xor bh,bh
mov byte ptr [media13+bx],'N'
pop bx
jmp med10
med05:
mov al,1 ; return "no change"
push bx
mov bl,[drvnum]
xor bh,bh
cmp byte ptr [media13+bx],'Y' ; test to see if int 13 detect
jne med06
mov al,0 ; return "maybe"
mov byte ptr [media13+bx],'N' ; reset int 13 detection
med06:
pop bx
jmp short med40 ; exit
med10:
mov ah,es:[bx].mrMediaID ; old media descriptor
cmp ah,[si].dibMedia ; same as current one?
je med30 ; if still same
med20:
lea ax,[si].dibLabel
mov word ptr es:[bx].mrVolumeID,ax ; offset of volume id expected
mov word ptr es:[bx+2].mrVolumeID,ds
mov al,-1 ; we think media changed
jmp short med40 ; return "changed"
med30:
mov di,offset grp:lblbuf
call getlabel ; get current label
jnc med32 ; if no error
push di ; balance stack
jmp fdskerr ; return error code
med32:
push si
push es
push ds
pop es
lea si,[si].dibLabel ; old label address
mov cx,lblsiz
repe cmpsb ; look for match
pop es
pop si
jnz med20 ; if different labels
med35:
mov al,0 ; if same labels, not sure
med40:
and [si].dibAttributes,not (dirtybpb or diskswap)
; taken care of dirty bpb & disk swap
mov es:[bx].mrReturn,al ; 1=not changed, 0=not sure
mov es:[bx].mrStatus,0100h ; return with 'DONE'
ret
fmedck endp
subttl timeset - record 0040:006c
page
;======================================================================
;,fs
; timeset - record 0040:006c
;
; in:
;
; out:
;
;,fe
;======================================================================
assume ds:nothing,es:nothing,ss:nothing
timeset proc near
push es
push ax
mov ax,0040h ; access bios
mov es,ax
mov ax,es:[006ch]
mov [si].dibTimerLo,ax
mov ax,es:[006eh]
mov [si].dibTimerHi,ax
pop ax
pop es
ret
timeset endp
subttl timetest - check elapsed time
page
;======================================================================
;,fs
; timetest - check elapsed time
;
; in: si-> dib structure
; ds -> grp
;
; out: al = 1 if diskette could not have been changed
; al = 0 if it could have been
;
;,fe
;======================================================================
assume ds:grp,es:nothing,ss:nothing
timetest proc near
mov ax,0040h ; sah access bios
mov es,ax
mov ax,es:[006ch]
mov dx,es:[006eh]
sub ax,[si].dibTimerLo ; compute elapsed timer ticks
sbb dx,[si].dibTimerHi
jnz ttover
cmp ax,36 ; jump if more than 2 seconds
ja ttover
mov al,1 ; diskette cannot have been changed
ret
ttover:
mov al,0 ; diskette could have been changed
ret
timetest endp
subttl getlabel -- get label from current disk
page
;======================================================================
;,fs
; getlabel -- get label from current disk
;
; reads label from disk in specified drive. calculates directory
; sector number from information in dib. reads directory in one sector
; at a time until it finds the drive label entry. if the label is
; found, it is read into the buffer pointed to by di.
;
; in: dl contains disk number
; si->dib for drive
; di->buffer for label
; ds -> grp
;
; out: cy clear if no error searching for label
; cy set if error searching for label
; if cy set, ah contains error code from rom bios
;
;,fe
;======================================================================
assume ds:grp,es:nothing,ss:nothing
getlabel proc near
push bx
push cx
push dx
push es
mov [drvnum],dl ; save drive number
; how many entries in directory?
mov cx,[si].dibRootDirEnts ; max root directory entries allowed
mov [dircnt],cx
; where does directory start?
getl10:
mov al,[si].dibFATs ; number of file allocation tables
cbw
mul [si].dibFATsecs ; sectors of fat
add ax,[si].dibResSectors ; reserved sectors
; ax contains the first directory sector number.
; search the directory for the disk label.
push si ; save dib pointer
getl20:
call getsec ; get the indicated sector (in ax)
jc getl30 ; if we couldn't read the sector
call srchsec ; search the sector for the disk label
jc getl40 ; if label found (or we have given up)
inc ax ; try next sector
jmp getl20
; label search failed, return lblsiz null bytes for label.
getl30:
call zlbl ; zero out lblsiz bytes of sector buffer
stc ; indicate error
jmp short getl50 ; leave without clearing carry
getl40:
or ax,ax ; clear carry flag
getl50:
pop si ; restore dib pointer
pop es
pop dx
pop cx
pop bx
ret
getlabel endp
subttl getsec -- get sector from disk
page
;======================================================================
;,fs
; getsec -- get sector from disk
;
; get a sector from the disk into secbuf. the logical sector number to
; read is in ax. if an error occurs while reading, sets the carry flag.
;
; in: ax contains logical sector number.
; ds -> grp
;
; out: cy clear if sector read ok.
; cy set if sector could not be read.
; if error, ah contains error code from bios
;
;,fe
;======================================================================
assume ds:grp,es:nothing,ss:nothing
getsec proc near
push bx
push cx
push dx
push di
push es
les bx,dword ptr [secbuf] ; read into sector buffer
call calcabs ; get absolute disk location
mov dl,[drvnum] ; and drive number
mov [typrtr],3 ; 3 retries
gets10:
mov ax,0201h ; read 1 sector
int 13h
jnc gets40 ; if successfully read sector
push ax
xor ah,ah ; reset drive on timeout
int 13h
pop ax
test ah,80h ; no retires if time out
jnz gets20
dec [typrtr] ; through retries?
jnz gets10 ; no try to read one more sector
gets20: ; return with error after all retries
stc
gets40:
pop es
pop di
pop dx
pop cx
pop bx
ret
getsec endp
subttl srchsec -- search a directory sector for label
page
;======================================================================
;,fs
; srchsec -- search a directory sector for label
;
; search directory sector for volume label. directory entries are 32
; bytes long. the 12th byte (offset 11) in the entry is the attribute
; byte. if bit 3 of the attribute is set, the entry is a volume label.
; the routine will terminate on finding the volume label with the
; label in the first lblsiz bytes of the sector buffer.
;
; if the label is not found & directory entry starting in 0 is found,
; the routine will copy zeroes to the beginning of the sector buffer &
; act as if it had found a label (terminating search).
;
; in: if bx contains 1, secbuf -> sector to search for volume label.
; if bx is not 1, es:bx -> sector to search for volume label
; si -> dib for disk
; di -> buffer for label (assumed to be in ds).
; es same as cs & ds
; ds -> grp
;
; out: if cy clear, no label found.
; if cy set, label found & in first lblsiz bytes of secbuf.
;
;,fe
;======================================================================
assume ds:grp,es:nothing,ss:nothing
srchsec proc near
push ax
push bx
push cx
push di
push si
push es
les bx,dword ptr [secbuf] ; point es:bx at sector
mov ax,[si].dibBytesPerSec ; bytes per sector
mov cl,5
shr ax,cl ; directory entries per sector = bps/32
mov cx,ax ; cx is loop count
jcxz srch30 ; if no entries in sector
srch10:
test byte ptr es:[bx+11],08h ; is this the volume label?
jnz srch20 ; if really the label
cmp byte ptr es:[bx],0 ; is first byte a null?
jz srch30 ; pretend we found entry
add bx,32 ; next directory entry
dec [dircnt] ; take one out of total count
loopnz srch10
cmp [dircnt],0 ; end of search?
jz srch30 ; if end, return 0 label
clc
jmp short srch50 ; no label found, exit
srch20:
mov cx,lblsiz ; copy lblsiz bytes to wherever
mov si,bx ; now si points to the label
push ds
push es
pop ds
pop es
cld
rep movsb ; copy label into ds:di
push es
pop ds
jmp short srch40 ; exit & say label found
srch30:
call zlbl ; return with no label
srch40:
stc
srch50:
pop es
pop si
pop di
pop cx
pop bx
pop ax
ret
srchsec endp
subttl zlbl -- zero out first lblsiz bytes of label
page
;======================================================================
;,fs
; zlbl -- zero out first lblsiz bytes of label
;
; zeroes out first lblsiz bytes of label buffer pointed to by di.
; called by getlabel function.
;
; in: di->buffer containing label to zero.
; ds -> grp
;
; out:
;
;,fe
;======================================================================
assume ds:grp,es:nothing,ss:nothing
zlbl proc near
push ax
push di
push ds
pop es
xor ax,ax
cld
mov cx,lblsiz
rep stosb
pop di
pop ax
ret
zlbl endp
assume es:nothing
subttl bldbpb - build bios parm block
page
;======================================================================
;,fs
; bldbpb - build bios parm block
;
; this routine processes the build bios parameter block call (=2)
;
; in:
; ds -> grp
;
; out:
;
;,fe