/
partit.mac
6294 lines (5238 loc) · 109 KB
/
partit.mac
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
.z80
name('partit')
title MSX-DOS 2 KERNEL Copyright (1986) IS Systems Ltd.
subttl Disk partition management
;******************************************************************************
;
INCLUDE ../macros.inc
INCLUDE ../const.inc
INCLUDE ../bank0/b0labels.inc
;
EMU_RAM_ADDRESS equ 0A000h
DISKID equ 0FD99h
MBR_PSTART equ 01BEh ;Start of partition table in MBR
MBR_PSIZE equ 16 ;Size of partition table entry
POFF_STATUS equ 0 ;Offset of status byte in p. table entry
POFF_CHS_START equ 1
POFF_TYPE equ 4 ;Offset of partition type in p. table entry
POFF_CHS_END equ 5
POFF_PSTART equ 8 ;Offset of partition start in p. table entry
POFF_PSIZE equ 12 ;Offset of partition size in p. table entry
PT_FAT12 equ 1 ;Partition type code for FAT12
PT_FAT16_S equ 4 ;Partition type code for FAT16 (< 32M)
PT_EXT equ 5 ;Partition type code for extended partition (CHS)
PT_EXT_LBA equ 15 ;Partition type code for extended partition (LBA)
PT_FAT16 equ 6 ;Partition type code for FAT16
PT_FAT16_L equ 14 ;Partition type code for FAT16 (LBA)
CALLB0 equ 403Fh
CALBAS equ 0159h
PROCNM equ 0FD89h
DCOMPR equ 0020h
;CHPUT equ 00A2h
GETBYT equ 521Ch
CHRGTR equ 4666h
FRMEVL equ 4C64h
FRMQNT equ 542Fh
NLONLY equ 0F87CH
FLBMEM equ 0FCAEH
CKCNTC equ 00BDh ;check control-STOP
VALTYP equ 0F663h
DAC equ 0F7F6h
BUF equ 0F55Eh ;line input buffer (used as scratch)
CHPUT:
cp 10
jp nz,18h
rst 18h
push hl
ld hl,CKCNTC
ld (BK4_ADD##),hl
pop hl
jp CALLB0
;-----------------------------------------------------------------------------
; These routines are for disk partition management.
; They allow to locate partitions within a disk,
; and to decide which devices to map to drives at boot time.
; They work with device-based drivers only.
;-----------------------------------------------------------------------------
;
PROC F_GPART
;
; This is the code for the F_GPART function, which obtains the type
; and location of a given partition on a disk.
;
; Entry: C (A) = Driver slot
; B = Driver segment (FFh for ROM drivers), currently ignored
; D = Device index, 1 to 7
; E = LUN index, 1 to 7
; H = Primary partition number (1 to 4)
; bit 7: 0 = Get partition information
; 1 = Get partition table absolute sector
; L = Extended partition number (0 for primary entry in MBR)
; Returns: A = Error from DEV_RW or F_GDRVR, or .IPART; 0 if no error
; If "Get partition information":
; B = Partition type, 0 for non existing partition
; C = 80h if bootable partition
; HLDE = Starting sector of partition
; IXIY = Partition size
; If "Get partition table absolute sector":
; HLDE = Absolute sector that holds the partition table entry
; (0 for primary partitions)
;
; In case of disk error when reading the device, an error code will
; be returned. We cannot invoke the standard disk error handling routine,
; since it requires a unit descriptor, which we don't have here.
;
; A non existing partition is indicated by returning an .IPART error.
;--- Check that the driver exists and is a device-based driver
push bc
push de
push hl
ld d,c
ld e,b
ld c,0
ld hl,($SECBUF##) ; (BUF_3##)
call F_GDRVR
pop hl
pop de
pop bc
or a
ret nz
ld ix,($SECBUF##) ;(BUF_3##)
ld a,(ix+4)
and 10000001b
cp 10000001b
ld a,.IDRVR##
ret nz
;--- Check device, LUN and primary partition number
ld a,d
or a
jp z,UNEX_DEVL
cp 8
jp nc,UNEX_DEVL
ld a,e
or a
jp z,UNEX_DEVL
cp 8
jp nc,UNEX_DEVL
ld a,h
and 01111111b
;or a
jp z,UNEX_PART
cp 5
jp nc,UNEX_PART
;--- Read MBR
xor a
ld (TMP_SEC##),a
ld (TMP_SEC##+1),a
ld (TMP_SEC##+2),a
ld (TMP_SEC##+3),a
call DEV_READ
ret nz
;--- Get pointer to main partition table entry
push bc
ld bc,MBR_PSTART
ld ix,($SECBUF##)
add ix,bc
ld bc,MBR_PSIZE
ld a,h
and 01111111b
PTENTRY_LOOP:
dec a
jr z,OK_PENTRY
add ix,bc
jr PTENTRY_LOOP
OK_PENTRY:
pop bc
;--- If extended partition number is zero, return primary partition entry info
ld a,l
or a
jr nz,DO_EXTPAR
ld a,(ix+POFF_TYPE)
or a
jp z,UNEX_PART
ld b,a
bit 7,h ;Partition table entry sector requested: it's always 0 for primary partitions
ld hl,0
ld de,0
ld a,0
ret nz
ld e,(ix+POFF_PSIZE)
ld d,(ix+POFF_PSIZE+1)
ld l,(ix+POFF_PSIZE+2)
ld h,(ix+POFF_PSIZE+3)
push de
push hl
ld c,(ix+POFF_STATUS)
ld e,(ix+POFF_PSTART)
ld d,(ix+POFF_PSTART+1)
ld l,(ix+POFF_PSTART+2)
ld h,(ix+POFF_PSTART+3)
pop ix
pop iy
xor a
ret
DO_EXTPAR:
;--- If extended partition requested, first check that partition is actually extended
ld a,(ix+POFF_TYPE)
call IS_EXT_PART
jp nz,UNEX_PART
ld a,(ix+POFF_PSTART) ;Save the start sector number of the outer extended partition
ld iyl,a ;(the one that includes all other extended partitions).
ld a,(ix+POFF_PSTART+1) ;We need it to calculate the offsets of the inner
ld iyh,a ;extended partitions.
push iy
ld a,(ix+POFF_PSTART+2)
ld iyl,a
ld a,(ix+POFF_PSTART+3)
ld iyh,a
push iy
;=== Loop for extended partition search ===
;Input: L=Extended partitions left to skip, plus one
; IX=pointer to the extended partition entry in partition table
EXTP_LOOP:
;--- Read sector 0 of the extended partition entry
call UPDATE_SEC
call DEV_READ
jr nz,TWO_POPS_IY
dec l
ld a,l
or a
jr nz,EXTP_NEXT
;--- Desired extended partition reached:
; Get the base sector number for the primary entry
; and return
bit 7,h ;Partition table entry sector requested: return its sector
jr nz,EXTP_ENTRYADD
ld ix,($SECBUF##)
ld bc,MBR_PSTART
add ix,bc
call UPDATE_SEC
ld b,(ix+POFF_TYPE)
ld c,(ix+POFF_STATUS)
ld e,(ix+POFF_PSIZE)
ld d,(ix+POFF_PSIZE+1)
ld l,(ix+POFF_PSIZE+2)
ld h,(ix+POFF_PSIZE+3)
EXTP_ENTRYADD:
push de
push hl
ld ix,TMP_SEC##
ld e,(ix)
ld d,(ix+1)
ld l,(ix+2)
ld h,(ix+3)
xor a
pop ix
pop iy
jr TWO_POPS_IY
;--- Not there yet:
; check that the next extended entry exists, and read it
EXTP_NEXT:
pop iy ;Restore outer extended partition start sector
ld (TMP_SEC##+2),iy
pop ix
ld (TMP_SEC##),ix
push ix
push iy
ld ix,($SECBUF##)
push bc
ld bc,MBR_PSTART+MBR_PSIZE
add ix,bc
pop bc
ld a,(ix+POFF_TYPE)
call IS_EXT_PART
jr nz,TPIY_UNEX_PART
jr EXTP_LOOP
TWO_POPS_IY:
inc sp
inc sp
inc sp
inc sp
;pop iy
;pop iy
ret
;Return with non-existing partition or device indication
TPIY_UNEX_PART:
pop iy
pop iy
UNEX_PART:
ld a,.IPART##
ld b,0
ret
UNEX_DEVL:
ld a,.IDEVL##
ret
;Perform a 32-bit sector sum
;Input: (IX+POFF_PSTART) and (TMP_SEC##) hold the numbers to sum
;Output: (TMP_SEC##) holds the result
;Corrupts F
UPDATE_SEC:
push hl
push de
ld de,(TMP_SEC##)
ld l,(ix+POFF_PSTART)
ld h,(ix+POFF_PSTART+1)
add hl,de
ld (TMP_SEC##),hl
ld de,(TMP_SEC##+2)
ld l,(ix+POFF_PSTART+2)
ld h,(ix+POFF_PSTART+3)
adc hl,de
ld (TMP_SEC##+2),hl
pop de
pop hl
ret
;This routine reads one sector into SECBUF
;Input: C = Driver slot
; B = Driver segment (FFh for ROM drivers), currently ignored
; D = Device index, 1 to 7
; E = LUN index, 1 to 7
; (TMP_SEC##) = Sector number
;Output: A = Error code from DEV_RW
; NZ if A<>0
;Corrupts: AF, IX, IY
DEV_READ:
push bc
push de
push hl
ld iyh,c
ld ix,DEV_RW##
ld (BK4_ADD##),ix
ld ix,CALDRV##
ld a,d
ld c,e
ld b,1
ld hl,($SECBUF##)
ld de,TMP_SEC##
call CALSLT##
pop hl
pop de
pop bc
or a
ret
;-----------------------------------------------------------------------------
;
PROC GDRIVER
;
; This routine obtains the slot and segment number of a disk driver
; based on a index number.
;
; ROM driver slots are searched in both DRVTBL (the DOS 1/2.3x compatible
; drivers table) and KER250 (the new DOS 2.50 kernels table), taking
; care for duplicates. This is because ROM drivers can be registered in
; only one of these tables, or in both:
;
; - Drivers embedded in a DOS 1/2.3x kernel are registered in DRVTBL only.
; - Drivers embedded in a DOS 2.50 kernel, and which have at least one
; drive letter allocated at boot time, are registered in both tables.
; - Drivers embedded in a DOS 2.50 kernel, and which have no drive
; letters allocated at boot time, are registered in KER250 only.
;
; The latter may happen in two cases:
;
; 1) The driver does not request drives at boot time
; (drive-based drivers only).
; 2) No drive letters are free when the driver initialization routine
; is called (all drives have been allocated to other drivers already).
;
; Note that driver slots are not necessarily returned in increasing
; slot number.
;
; Entry: A = Driver index, starting at 1
; Returns: A = Driver slot, 0 if no driver found with that index
; B = Driver segment, FFh if ROM driver
or a ;Index 0 is invalid
ret z
;--- First search in DRVTBL
ld hl,DRVTBL##
ld d,a ;D=Driver index (entries to skip plus one)
ld b,4 ;B=Entries in DRVTBL
GDRV_LOOP:
ld a,(hl) ;Check number of drives (0=unused entry)
or a
inc hl
ld c,(hl) ;Get slot number
inc hl
jr z,GDRV_NEXT
ld a,d
dec a
ld d,a
jr z,GDRV_OK_ROM
GDRV_NEXT:
djnz GDRV_LOOP ;Loop for entries in DRVTBL
;--- Then search in KER250
ld b,4 ;D=Entries in KER250
ld ix,DRVTBL##
ld hl,KER250##
GDRV_LOOP3:
ld a,(hl)
inc hl
and 10001111b
jr z,GDRV_NEXT2 ;Check for unused entry
cp (ix+1)
jr z,GDRV_NEXT2 ;Check for entry repeated in DRVTBL
cp (ix+3)
jr z,GDRV_NEXT2
cp (ix+5)
jr z,GDRV_NEXT2
cp (ix+7)
jr z,GDRV_NEXT2
ld c,a
ld a,d
dec a
ld d,a
jr z,GDRV_OK_ROM
GDRV_NEXT2:
djnz GDRV_LOOP3 ;Loop for entries in KER250
;--- No driver found with that index
xor a
ret
;--- ROM driver found, C=slot number
GDRV_OK_ROM:
ld a,c
ld b,0FFh
ret
;-----------------------------------------------------------------------------
;
PROC AUTODRV
; This routine automatically assigns devices and partitions to drives for
; device-based Nextor drivers. There are two versions, one for DOS 1 and
; another one for DOS 2, since the processing done in both cases is
; quite different.
;
; In both DOS 1 and DOS 2 modes AUTO_ASSIGN (or AUTO_ASPART) is called with A=1.
; This causes the root directory of primary partitions to be scanned
; for a file named NEXT_DSK.DAT (only if the current controller is the
; primary controller); if found and its contents are valid, the whole
; assignment procedure is aborted and we enter disk emulation mode.
;We disable the PROMPT routine temporarily while AUTODRV runs,
;since we don't want it to be run when devices are read to search for partitions.
;The prompt routine is disabled by placing two INC SP instructions
;in the hook, so that the routine terminates immediately.
ld a,(H.PROMPT##)
push af
ld hl,(H.PROMPT##+1)
push hl
ld hl,3333h ;"INC SP" x 2
ld (H.PROMPT##),hl
ld a,0C9h ;"RET"
ld (H.PROMPT##+2),a
call _AUTODRV
pop hl
ld (H.PROMPT##+1),hl
pop af
ld (H.PROMPT##),a
ret
_AUTODRV:
ld hl,0
add hl,sp
ld (SPSAVE##),hl
ld a,(DOS_VER##)
or a
jp nz,AUTODRV_DOS2
; AUTODRV - DOS 1 version
;
; This routine is called at boot time, in the OLDDOS routine, when DOS 1
; is to be invoked because a DOS 1 boot sector has been detected or because
; the "1" key is pressed.
;
; It does the auto-assignment of all the appropriate drives and at the
; same time builds a table in the address stored in (DVB_TABLE), which contains
; information about the assigned device for each drive. Later, this
; table will be copied to an area allocated at page 3. This is necessary
; since DOS 1 does not allocate a data segment like DOS 2 does.
;
; The first byte of the table contains the number of entries. Then,
; there are the entries themselves. See the definition of these entries
; in kvar.mac (UD1_*)
;
; Device index will be zero if the drive is unmapped (for example if the
; autoassign procedure does not find any suitable device). Note that this
; is different from the drive simply missing from the table (in this case,
; the drive will be considered to belong to a device-based driver).
AUTODRV_DOS1:
call DRVS1
ld hl,(DVB_TABLE##)
ld (hl),0 ;start with zero entries in table
inc hl
push hl
pop ix
;--- Loop through all the available drivers, and for these
; of device-based type, perform an auto-assign
ld c,1 ;Driver index
AUTODRV_LOOP:
ld iy,($SECBUF##)
push bc
push ix
push iy
pop hl
push hl
call F_GDRVR
pop iy
pop ix
or a
jp nz,AUTODRV_END
;* Check driver type
ld a,(iy+1)
inc a
jp nz,AUTODRV_NEXT ;Skip if no ROM driver (should never occur)
ld a,(iy+2)
or a
jp z,AUTODRV_NEXT ;Skip if no drives assigned
ld a,(iy+4)
and 10000001b
cp 10000001b
jp nz,AUTODRV_NEXT ;Skip if no device-based driver
;* Perform auto-assign for each drive associated to the driver
ld e,(iy)
ld d,(iy+4)
ld b,(iy+2) ;Number of drives for this driver
push de
pop iy
xor a ;Relative drive for the driver
AUTODRV_DRVLOOP:
;Here, IX = Beginning of entry in DVB_TABLE
; IYh = Driver flags (bit 4: provides config)
; IYl = Slot number
; B = Remaining drives for this driver
; A = Relative drive for the driver
ld c,a
ld a,iyl
ld (ix+UD1_SLOT##),a ;Set slot number in table entry
ld a,c
ld (ix+UD1_RELATIVE_DRIVE##),a
push af
xor a
push bc
push iy
push ix
ld a,iyh ;ld a,(iy+4)
and 00000100b ;Driver provides config?
jr z,AUTODRV_DRVL2
push ix
push iy
ld b,1
ld a,b
call ASK_DRIVE_CONFIG
pop iy
pop ix
or a
jr z,AUTODRV_DRVL3
dec a
jr z,AUTODRV_DRVL2 ;Driver does not provide config for that drive
dec a
jp nz,AUTOD_EMU ;We entered disk emulation mode
AUTODRV_DRVL1:
pop ix
push ix
ld a,-1
ld (ix+UD1_FIRST_ABSOLUTE_SECTOR##),a
ld (ix+UD1_FIRST_ABSOLUTE_SECTOR##+1),a
ld (ix+UD1_FIRST_ABSOLUTE_SECTOR##+2),a
ld (ix+UD1_FIRST_ABSOLUTE_SECTOR##+3),a
inc a
jr AUTODRV_DRVL3
AUTODRV_DRVL2:
push ix
pop hl
ld d,1
call AUTO_ASSIGN
AUTODRV_DRVL3:
cp 2 ;Did we enter disk emulation mode?
jp z,AUTOD_EMU ;Yes: discard everything else and return
ld hl,(DVB_TABLE##)
inc (hl) ;Increment size of table
pop ix
ld de,8
add ix,de ;Point to next entry in table
pop iy
pop bc
;Go to next drive on a given driver
pop af
inc a
djpnz AUTODRV_DRVLOOP
AUTODRV_NEXT: ;Go to next driver
pop bc
inc c
jp AUTODRV_LOOP
;--- All drives on all drivers processed
AUTODRV_END:
pop bc
ret
; AUTODRV - DOS 2 version
;
; This routine is called at boot time, in the KINIT
; routine, after all drivers have been initialized and all unit descriptors
; have been created (INIT_UNITS invokation loop complete).
;
; Note that this routine calls AUTO_ASSIGN, which in turn asumes that
; UD_SLOT and UD_PHYSICAL_UNIT are set for the unit descriptor. This is true
; since these fields are set by INIT_UNITS.
AUTODRV_DOS2:
ld hl,UNIT_TAB##+2
ld b,MAX_UNITS
AUTOD_LOOP:
ld e,(hl)
inc hl
ld d,(hl) ;DE=Address of unit descriptor
dec hl
ld a,d
or e
jr nz,AUTOD_UDFND
inc hl
inc hl
djnz AUTOD_LOOP ;No unit descriptor found at that address
jp SETNUMDRV
AUTOD_UDFND:
;*** Unit descriptor found
push de
pop ix ;IX=Address of unit descriptor
;--- Check if it is assigned to a device based driver
ld a,(ix+UD_SLOT##)
ld iyh,a
ld c,a
ld a,(KER250##)
and 10001111b
cp c
jr z,AUTOD_OK250
ld a,(KER250##+1)
and 10001111b
cp c
jr z,AUTOD_OK250
ld a,(KER250##+2)
and 10001111b
cp c
jr z,AUTOD_OK250
ld a,(KER250##+3)
and 10001111b
cp c
jr z,AUTOD_OK250
inc hl
inc hl
djnz AUTOD_LOOP
jp SETNUMDRV
AUTOD_OK250:
push bc
push hl
push ix
call GET_DV_TYPE
pop ix
bit 0,a
jr nz,AUTOD_UDFND2
pop hl
pop bc
djnz AUTOD_LOOP ;Not associated to device-based driver
jp SETNUMDRV
AUTOD_UDFND2:
;--- If the driver provides configuration,
; try to get config from the driver itself
bit 2,a
jr z,AUTOD_UDFND3
ld b,0
ld c,(ix+UD_RELATIVE_UNIT_NUMBER##)
ld a,1
call ASK_DRIVE_CONFIG
cp 1
jr z,AUTOD_UDFND3 ;Driver did not provide config
pop hl
or a
jr z,AUTOD_OK
set UF_PAP,(ix+UD_DFLAGS##) ;Partition will be assigned on first access
jr AUTOD_OK
AUTOD_UDFND3:
;--- Call the auto-assign routine
push ix
pop hl
ld d,1
call AUTO_ASSIGN
cp 2 ;Did we enter disk emulation mode?
jp z,AUTOD_EMU ;Yes: discard everything else and return
;(note that we'll enter DOS 1 mode after returning)
pop hl ;Pointer in UNIT_TAB
or a
jr z,AUTOD_OK
;--- Auto-assign failed: destroy the unit descriptor
AUTOD_FAIL:
ld e,(hl)
inc hl
ld d,(hl)
ex de,hl
pcall FR_P2
ex de,hl
ld (hl),0
dec hl
ld (hl),0
;--- Auto-assign finished, go fot he next drive
AUTOD_OK:
inc hl
inc hl
pop bc
djpnz AUTOD_LOOP
jp SETNUMDRV
;--- We entered disk emulation mode, so return immediately
AUTOD_EMU:
ld hl,(SPSAVE##) ;(note that we'll enter DOS 1 mode after returning)
ld sp,hl
ret
;-----------------------------------------------------------------------------
;
; This routine sets the NUMDRV variable according to the number
; of existing unit descriptors. It is called after any drive letter to
; driver-device-LUN assignation is done, since new unit descriptors
; can be created and existing descriptors can be deleted.
;
; Preserves: AF
SETNUMDRV:
push af
ld hl,UNIT_TAB##+2
ld b,MAX_UNITS
ld c,0
SETNUMD_LOOP:
ld e,(hl)
inc hl
ld d,(hl) ;DE=Address of unit descriptor
dec hl
ld a,d
or e
jr z,SETNUMD_NOUD
inc c
SETNUMD_NOUD:
inc hl
inc hl
djnz SETNUMD_LOOP
ld a,c
ld ($NUMDRV##),a
pop af
ret
;-----------------------------------------------------------------------------
;
; AUTO_ASSIGN
;
; This routine automatically assigns the appropriate device and partition
; to a drive associated to a device-based Nextor driver. It does so by
; searching an available block device, then searching a FAT12 or FAT16
; partition (unless the MBR has no partition table), the checking the
; validity of the FAT boot sector. Other existing unit descriptors
; are checked to ensure that the same device and LUN is not assigned
; to more than one drive.
;
; If there is a device having a partition that is properly formatted in FAT12
; or FAT16 and has the "active" flag set (the MSB of the first byte
; of the partition table entry), then this device and that partition will be assigned
; regardless of the device number. If there are more than one devices matching this,
; the one with the smallest device number will be assigned. If there are multiple
; active partitions in the same device, the first one found will be assigned.
;
; There is also a second entry point, AUTO_ASPART.
; The difference is that this one searches for a suitable partition,
; but the device and LUN are fixed (passed as parameters).
; This one is used if the device provides its own configuration.
;
; Input: HL = DOS 2 mode:
; Address of unit descriptor, it must have UD_SLOT and UD_PHYSICAL_UNIT set
; DOS 1 mode:
; Address of entry in device-based drives table, must have UD_SLOT set
; B = Device index (AUTO_ASPART only)
; C = LUN index (AUTO_ASPART only)
; D = 0: Do NOT try to enter disk emulation mode
; 1: Enter disk emulation mode if possible
;
; Output: A = Error code
; 0: Ok
; 1: No suitable device/partition found
; 2: Disk emulation mode was entered
;CURR = current device/partition being examined
;CAND = candidate device/partition, will be assigned if no one has the active flag set in status byte
AAD_UNIT_DESCRIPTOR equ 0
AAD_LOOP_DEV_INDEX equ 2
AAD_LOOP_LUN_INDEX equ 3
AAD_DRIVER_SLOT equ 4
AAD_CURR_PART_DEVLUN equ 5
AAD_CURR_PART_INDEX equ 6 ;Bit 7 set when examining extended partitions, FFh when examining the MBR
AAD_CURR_PART_SECTOR equ 7
AAD_CURR_PART_STATUS_BYTE equ 11
AAD_CAND_PART_DEVLUN equ 12
AAD_CAND_PART_SECTOR equ 13
AAD_FLAGS equ 17
AAD_SIZE equ 18
AAFLAG_ENTER_EMU_MODE equ 0
AAFLAG_IS_AUTOASPART equ 7
PROC AUTO_ASPART
set AAFLAG_IS_AUTOASPART,d
AUTO_ASSIGN:
ld ix,-AAD_SIZE
add ix,sp
ld sp,ix
ld (ix+AAD_FLAGS),d
ld (ix+AAD_UNIT_DESCRIPTOR),l
ld (ix+AAD_UNIT_DESCRIPTOR+1),h
push hl
pop iy
ld a,(iy+UD_SLOT##)
ld (ix+AAD_DRIVER_SLOT),a
call AUTO_COMMON2
ld ix,AAD_SIZE
add ix,sp
ld sp,ix
ret
AUTO_COMMON2:
bit 0,d
jr z,AUTO_NOEMU
push bc
push de
push hl
xor a
call TRY_RAM_EMU
pop hl
pop de
pop bc
or a
ld a,2
ret nz
AUTO_NOEMU:
bit 7,d
jr z,AUTO_COMMON3
;AUTO_ASPART:
ld (ix+AAD_LOOP_DEV_INDEX),b
ld (ix+AAD_LOOP_LUN_INDEX),c
xor a
ld (ix+AAD_CAND_PART_DEVLUN),a
ld (ix+AAD_CURR_PART_DEVLUN),a
jp AA_CHKDUP_OK
;AUTO_ASSIGN:
AUTO_COMMON3:
xor a
ld (ix+AAD_CAND_PART_DEVLUN),a
ld (ix+AAD_CURR_PART_STATUS_BYTE),a
inc a ;Device index = 1
AA_DLOOP:
ld (ix+AAD_LOOP_DEV_INDEX),a
ld a,1 ;LUN index
AA_LLOOP:
ld (ix+AAD_LOOP_LUN_INDEX),a
xor a
ld (ix+AAD_CURR_PART_DEVLUN),a
;--- Check if the same slot+device+LUN has been assigned
; to other drive already
ld d,(ix+AAD_LOOP_DEV_INDEX)
ld e,(ix+AAD_LOOP_LUN_INDEX)
ld a,(DOS_VER##) ;Skip in DOS 1
or a
jr nz,AA_CHKDUP_DOS2
;--- DOS 1 version: check entry in DVB_TABLE against
; other entries in the table
AA_CHKDUP_DOS1:
ld iy,(DVB_TABLE##)
ld b,(iy)
or b
jr z,AA_CHKDUP_OK
inc iy