-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdiskette.asm
2024 lines (1870 loc) · 69.4 KB
/
diskette.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
PAGE 118,121
TITLE DSKETTE - 06/10/85 DISKETTE BIOS
.286C
.LIST
CODE SEGMENT BYTE PUBLIC
PUBLIC DISK_INT_1
PUBLIC SEEK
PUBLIC DSKETTE_SETUP
PUBLIC DISKETTE_IO_1
EXTRN CMOS_READ:NEAR ; READ CMOS LOCATION ROUTINE
EXTRN DDS:NEAR ; LOAD (DS) WITH DATA SEGMENT SELECTOR
EXTRN DISK_BASE:NEAR ; DISKETTE PARAMETER TABLE LOCATION
EXTRN WAITF:NEAR ; FIXED WAIT ROUTINE - (CX)*15.086 US
;-- INT13H ---------------------------------------------------------------------
; DISKETTE I/O
; THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4" DISKETTE DRIVES
; 320/360K DISKETTE DRIVES AND 1.2M DISKETTE DRIVES SUPPORTED
; INPUT
; (AH) = 00H RESET DISKETTE SYSTEM
; HARD RESET TO NEC. PREPARE COMMAND, RECALIBRATE REQUIRED
; ON ALL DRIVES
;-------------------------------------------------------------------------------
; (AH)= 01H READ THE STATUS OF THE SYSTEM INTO (AH)
; @DISKETTE_STATUS FROM LAST OPERATION IS USED
;-------------------------------------------------------------------------------
; REGISTERS FOR READ/WRITE/VERIFY/FORMAT
; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
; (DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
; (CH) - TRACK NUMBER (NOT VALUE CHECKED)
; MEDIA DRIVE TRACK NUMBER
; 320/360 320/360 0-39
; 320/360 1.2M 0-39
; 1.2M 1.2M 0-79
; 720K 720K 0-79
; (CL) - SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
; MEDIA DRIVE SECTOR NUMBER
; 320/360 320/360 1-8/9
; 320/360 1.2M 1-8/9
; 1.2M 1.2M 1-15
; 720K 720K 1-9
; (AL) NUMBER OF SECTORS (NOT VALUE CHECKED)
; MEDIA DRIVE MAX NUMBER OF SECTORS
; 320/360 320/360 8/9
; 320/360 1.2M 8/9
; 1.2M 1.2M 15
; 720K 720K 9
;
; (ES:SX) - ADDREss OF BUFFER ( REQUIRED FOR VERIFY)
;
;-------------------------------------------------------------------------------
; (AH)= 02H READ THE DESIRED SECTORS INTO MEMORY
;-------------------------------------------------------------------------------
; (AH)= 03H WRITE THE DESIRED SECTORS FROM MEMORY
;-------------------------------------------------------------------------------
; (AH)= 04H VERIFY THE DESIRED SECTORS
;-------------------------------------------------------------------------------
; (AH)= 05H FORMAT THE DESIRED TRACK
; FOR THE FORMAT OPERATION. THE BUFFER POINTER (ES,BX) MUST
; POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS FOR THE
; TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N), WHERE
; C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, N= NUMBER
; OF BYTES PER SECTOR (00=128, 01=256, 02=512. 03=1024,)
; THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
; THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING
; READ/WRITE ACCESS.
; PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
; ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
; THEN "SET DASD TYPE" (INT 13H, AH = 17H) MUST BE CALLED TO
; SET THE DISKETTE TYPE THAT IS TO BE FORMATTED. IF "SET DASD
; TYPE" IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE
; MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
; IN ORDER TO FORMAT 320/360K MEDIA IN EITHER A 320/360K OR
; 1.2M DISKETTE DRIVE THE GAP LENGTH FOR FORMAT PARAMETER
; OF DISK BASE MUST BE CHANGE TO 050H. ALSO THE EOT
; PARAMETER (LAST SECTOR ON TRACK) MUST BE SET TO THE
; DESIRED NUMBER OF SECTORS/TRACK - 8 FOR 320K, 9 FOR 360K.
; DISK_BASE IS POINTED TO BY DISK POINTER LOCATED AT
; ABSOLUTE ADDRESS 0:78.
; WHEN 320/360K FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
; SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.
;-------------------------------------------------------------------------------
; (AH_= 08H READ DRIVE PARAMETERS
; REGISTERS
; INPUT
; (DL) - DRIVE NUMBER (0-1 ALLOWED. VALUE CHECKED)
; OUTPUT
; (ES:DI) POINTS TO DISK BASE
; (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
; (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
; BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
; (DH) - MAXIMUM HEAD NUMBER
; (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
; (BH) - 0
; (BL) - BITS 7 THRU 4 - 0
; BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
; (AX) - 0
; UNDER THE FOLLOWING CIRCUMSTANCES:
; (1) THE DRIVE NUMBER IS INVALID,
; (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT,
; (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
; (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
; THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES.
; IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
; @DISKETTE_STATUS = 0 AND CY IS RESET.
;-------------------------------------------------------------------------------
; (AH)= 15H READ DASD TYPE
; REGISTERS
; (AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR
; 00 - DRIVE NOT PRESENT
; 01 - DISKETTE, NO CHANGE LINE AVAILABLE
; 02 - DISKETTE, CHANGE LINE AVAILABLE
; 03 - FIXED DISK
; (DL) - DRIVE NUMBER (0-1 ALLOWED. VALUE CHECKED)
;
;-------------------------------------------------------------------------------
; (AH)= 16H DISK CHANGE LINE STATUS
; REGISTERS
; (AH)=00 - DISK CHANGE LINE NOT ACTIVE
; 06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
;
;-------------------------------------------------------------------------------
; (AH)= 17H SET DASD TYPE FOR FORMAT
; REGISTERS
; (AL) - 00 - NOT USED
; 01 - DISKETTE 320/360K IN 360K DRIVE
; 02 - DISKETTE 360K IN 1.2M DRIVE
; 03 - DISKETTE 1.2M IN 1.2M DRIVE
; 04 - DISKETTE 720K IN 720K DRIVE
; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
; DO NOT USE WHEN DISKETTE ATTACH CARD USED)
;-------------------------------------------------------------------------------
; DISK CHANGE STATUS IS ONLY CHECKED WHEN A 1.2M BYTE DISKETTE
; DRIVE IS SPECIFIED. IF THE DISK CHANGE LINE IS FOUND TO BE
; ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
; ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE.
; IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK
; CHANGE ERROR CODE
; IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE
; TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
; IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
;
; DATA VARIABLE -- @DISK_POINTER
; DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
;-------------------------------------------------------------------------------
; OUTPUT FOR ALL FUNCTIONS
; AH = STATUS OF OPERATION
; STATUS BITS ARE DEFINED IN THE EQUATES FOR @DSKETTE_STATUS
; VARIABLE IN THE DATA SEGMENT OF THIS MODULE
; CY = 0 SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
; TYPE AH=(15)).
; CY = 1 FAILED OPERATION (AH HAS ERROR REASON)
; FOR READ/WRITE/VERIFY
; DS,BX,DX,CX PRESERVED
; NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE
; ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
; ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT
; THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE
; PROBLEM IS NOT DUE TO MOTOR START-UP.
;-------------------------------------------------------------------------------
.LIST
: DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
.LIST
; -----------------------------------------------------------------
; | | | | | | | | |
; | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
; | | | | | | | | |
; -----------------------------------------------------------------
; | | | | | | | |
; | | | | | -----------------
; | | | | | |
; | | | | RESERVED |
; | | | | PRESENT STATE
; | | | | 000: 360K IN 360K DRIVE UNESTABLISHED
; | | | | 001: 360K IN 1.2M DRIVE UNESTABLISHED
; | | | | 010: 1.2M IN 1.2M DRIVE UNESTABLISHED
; | | | | 011: 360K IN 360K DRIVE ESTABLISHED
; | | | | 100: 360K IN 1.2M DRIVE ESTABLISHED
; | | | | 101: 1.2M IN 1.2M DRIVE ESTABLISHED
; | | | | 110: RESERVED
; | | | | 111: NONE OF THE ABOVE
; | | | |
; | | | ------> MEDIA/DRIVE ESTABLISHED
; | | |
; | | --------------> DOUBLE STEPPING REQUIRED (360K IN 1.2M
; | | DRIVE)
; | |
; ------------------------------> DATA TRANSFER RATE FOR THIS DRIVE:
;
; 00: 500 KBS
; 01: 300 KBS
; 10: 250 KBS
; 11: RESERVED
;
.LIST
;-------------------------------------------------------------------------------
; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
;-------------------------------------------------------------------------------
; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
;-------------------------------------------------------------------------------
ASSUME CS:CODE,DS:DATA,ES:DATA
.LIST
DISKETTE_IO_1 PROC FAR ;>>> ENTRY POINT FOR ORG 0EC59H
STI ; INTERRUPTS BACK ON
PUSH BP ; USER REGISTER
PUSH SI ; USER REGISTER
PUSH DX ; HEAD #, DRIVE # OR USER REGISTER
PUSH BX ; BUFFER OFFSET PARAMETER OR REGISTER
PUSH CX ; TRACK #-SECTOR # OR USER REGISTER
MOV BP,SP ; BP => PARAMETER LIST DEP. ON AH
; [BP] = SECTOR #
; [BP+1] = TRACK #
; [BP+2] = BUFFER OFFSET
; FOR RETURN OF DRIVE PARAMETERS:
; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
; BITS 0-5 MAX SECTORS/TRACK
; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
; BL/[BP+2] = BITS 7-4 = 0
; BITS 3-0 = VALID CMOS TYPE
; BH/[BP+3] = 0
; DL/[BP+4] = # DRIVES INSTALLED
; DH/[BP+5] = MAX HEAD #
; DI/[BP+6] = OFFSET TO DISK BASE
PUSH DS ; BUFFER SEGMENT PARM OR USER REGISTER
PUSH SI ; USER REGISTERS
CALL DDS ; SEGMENT OF BIOS DATA AREA TO DS
CMP AH,(FNC_TAE-FNC_TAB)/2 ; CHECK FOR > LARGEST FUNCTION
JS OK_FUNC ; FUNCTION OK
MOV AH,14H ; REPLACE WITH KNOWN INVALID FUNCTION
OK_FUNC:
CMP AH,L ; RESET OR STATUS ?
JBE OK_DRV ; IF RESET OR STATUS DRIVE ALWAYS OK
CMP AH,8 ; READ DRIVE PARMS ?
JZ OK_DRV ; IF SO DRIVE CHECKED LATER
CMP DL,1 ; DRIVES 0 AND 1 OK
JBE OK_DRV ; IF 0 OR 1 THEN JUMP
MOV AH,14H ; REPLACE WITH KNOWN INVALID FUNCTION
OK_DRV:
MOV CL,AH ; CL = FUNCTION
XOR CH,CH ; CX = FUNCTION
SHL CL,1 ; FUNCTION TIMES 2
MOV BX,OFFSET FNC_TAB ; LOAD START OF FUNCTION TABLE
ADD BX,CX ; ADD OFFSET INTO TABLE => ROUTINE
MOV AH,DH ; AX = HEAD #,# OF SECTORS OR DASD TYPE
XOR DH,DH ; DX = DRIVE #
MOV SI,AX ; SI = HEAD #,# OF SECTORS OR DASD TYPE
MOV DI,DX ; DI = DRIVE #
MOV AH,@DSKETTE_STATUS ; LOAD STATUS TO AH FOR STATUS FUNCTION
MOV @DSKETTE_STATUS,0 ; INITIALIZE FOR ALL OTHERS
; THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
; THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
; FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
;
; DI : DRIVE #
; SI-HI : HEAD #
; SI-LOW : # OF SECTORS OR DASD TYPE FOR FORMAT
; ES : BUFFER SEGMENT
; [BP] : SECTOR #
; [BP+1] : TRACK #
; [BP+2] : BUFFER OFFSET
;
; ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN
; SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR
; CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE
; SPECIFIC ERROR CODE.
;
; (AH) = @DSKETTE_STATUS
CALL WORD PTR CS:[BX] ; CALL THE REQUESTED FUNCTION
POP SI ; RESTORE ALL REGISTERS
POP DS
POP CX
POP BX
POP DX
POP DI
POP BP
RET 2 ; THROW AWAY SAVED FLAGS
;-------------------------------------------------------------------------------
FNC_TAB DW DISK_RESET ; AH = 00; RESET
DW DISK_STATUS ; AH = 01; STATUS
DW DISK_READ ; AH = 02; READ
DW DISK_WRITE ; AH = 03; WRITE
DW DISK_VERF ; AH = 04; VERIFY
DW DISK_FORMAT ; AH = 05; FORMAT
DW FNC_ERR ; AH = 06; INVALID
DW FNC_ERR ; AH = 07; INVALID
DW DISK_PARMS ; AH = 08; READ DRIVE PARAMETERS
DW FNC_ERR ; AH = 09; INVALID
DW FNC_ERR ; AH = 0A; INVALID
DW FNC_ERR ; AH = 0B; INVALID
DW FNC_ERR ; AH = 0C; INVALID
DW FNC_ERR ; AH = 0D; INVALID
DW FNC_ERR ; AH = 0E; INVALID
DW FNC_ERR ; AH = 0F; INVALID
DW FNC_ERR ; AH = 10; INVALID
DW FNC_ERR ; AH = 11; INVALID
DW FNC_ERR ; AH = 12; INVALID
DW FNC_ERR ; AH = 13; INVALID
DW FNC_ERR ; AH = 14; INVALID
DW DISK_TYPE ; AH = 15; READ DASD TYPE
DW DISK_CHANGE ; AH = 16; CHANGE STATUS
DW FORMAT_SET ; AH = 17; SET DASD TYPE
FNC_TAB EQU $ END
DISKETTE_IO_1 ENDP
;-------------------------------------------------------------------------------
; DISK_RESET: RESET THE DISKETTE SYSTEM
;
; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
;-------------------------------------------------------------------------------
DISK_RESET PROC NEAR
MOV DX,03F2H ; ADAPTER CONTROL PORT
CLI ; NO INTERRUPTS
MOV AL,@MOTOR_STATUS ; GET DIGITAL OUTPUT REGISTER REFLECTION
AND AL,00111111B ; KEEP SELECTED AND MOTOR ON BITS
ROL AL,4 ; MOTOR VALUE TO HIGH NIBBLE
; DRIVE SELECT TO LOW NIBBLE
OR AL,00001000B ; TURN ON INTERRUPT ENABLE
OUT DX,AL ; RESET THE ADAPTER
MOV @SEEK_STATUS,0 ; SET RECALIBRATE REQUIRED ON ALL DRIVES
JMP $+2 ; WAIT FOR I/O
OR AL,00000100B ; TURN OFF RESET BIT
OUT DX,AL ; RESET THE ADAPTER
STI ; ENABLE THE INTERRUPTS
CALL WAIT_INT ; WAIT FOR THE INTERRUPT
JC DR_ENR ; IF ERROR, RETURN IT
MOV CX,11000000B ; CL = EXPECTED @NEC_STATUS
NXT_DRV:
PUSH CX ; SAVE FOR CALL
MOV AX,OFFSET DR_POP_ERR ; LOAD NEC_OUTPUT ERROR ADDRESS
PUSH AX ; "
MOV AH,08H ; SENSE INTERRUPT STATUS COMMAND
CALL NEC_OUTPUT
POP AX ; THROW AWAY ERROR RETURN
CALL RESULTS ; READ IN THE RESULTS
POP CX ; RESTORE AFTER CALL
JC DR_ERR ; ERROR RETURN
CMP CL,@NEC_STATUS ; TEST FOR DRIVE READY TRANSITION
JNZ DR_ERR ; EVERYTHING OK
INC CL ; NEXT EXPECTED @NEC_STATUS
CMP CL,11000011B ; ALL POSSIBLE DRIVES CLEARED
JBE NXT_DRV ; FALL THRU IF 11000100B OR >
;----- SEND SPECIFY COMMAND TO NEC
MOV AX,OFFSET RESBAC ; LOAD ERROR ADDRESS
PUSH AX ; PUSH NEC_OUT ERROR RETURN
MOV AH,03H ; SPECIFY COMMAND
CALL NEC_OUTPUT ; OUTPUT THE COMMAND
SUB DL,DL ; FIRST SPECIFY BYTE
CALL GET_PARM ; GET PARAMETER TO AH
CALL NEC_OUTPUT ; OUTPUT THE COMMAND
MOV DL,1 ; SECOND SPECIFY BYTE
CALL GET_PARM ; GET PARAMETER TO AH
CALL NEC_OUTPUT ; OUTPUT THE COMMAND
POP AX ; POP ERROR RETURN
RESBAC:
CALL SETUP_END ; VARIOUS CLEANUPS
MOV BX,SI ; GET SAVED AL TO BL
MOV AL,BL ; PUT BACK FOR RETURN
RET
DR_POP_ERR:
POP CX ; CLEAR STACK
DR_ERR:
OR @DSKETTE_STATUS,BAD_NEC ; SET ERROR CODE
JMP SHORT RESBAC ; RETURN FROM RESET
DISK_RESET ENDP
;-------------------------------------------------------------------------------
; DISK_STATUS: DISKETTE STATUS.
;
; ON ENTRY: AH : STATUS OF PREVIOUS OPERATION
;
; ON EXIT: AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
;-------------------------------------------------------------------------------
OISK_STATUS PROC NEAR
MOV @DSKETTE_STATUS,AH ; PUT BACK FOR SETUP END
CALL SETUP_END ; VARIOUS CLEANUPS
MOV BX,SI ; GET SAVED AL TO BL
MOV AL,BL ; PUT BACK FOR RETURN
RET
DISK_STATUS ENDP
;-------------------------------------------------------------------------------
; DISK_READ: DISKETTE READ.
;
; ON ENTRY: DI : DRIVE #
; SI-HI : HEAD #
; SI-LOW : # OF SECTORS
; ES : BUFFER SEGMENT
; [BP] : SECTOR #
; [BP+1] : TRACK #
; [BP+2] : BUFFER OFFSET
;
; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
;-------------------------------------------------------------------------------
OISK_READ PROC NEAR
AND @MOTOR_STATUS,01111111B ; INDICATE A READ OPERATION
MOV AX,0E646H ; AX = NEC COMMAND, DMA COMMAND
CALL RD_WR_VF ; COMMON READ/WRITEIVERIFY
RET
DISK_READ ENDP
;-------------------------------------------------------------------------------
; DISK_WRITE: DISKETTE WRITE.
;
; ON ENTRY: DI : DRIVE #
; SI-HI : HEAD #
; SI-LOW : # OF SECTORS
; ES : BUFFER SEGMENT
; [BP] : SECTOR #
; [BP+1] : TRACK #
; [BP+2] : BUFFER OFFSET
;
; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
;-------------------------------------------------------------------------------
DISK_WRITE PROC NEAR
MOV AX,0C54AH ; AX = NEC COMMAND, DMA COMMAND
OR @MOTOR_STATUS,10000000B ; INDICATE WRITE OPERATION
CALL RD_WR_VF ; COMMON READ/WRITEIVERIFY
RET
DISK_WRITE ENDP
;-------------------------------------------------------------------------------
; DISK_VERF: DISKETTE VERIFY.
;
; ON ENTRY: DI : DRIVE #
; SI-HI : HEAD #
; SI-LOW : # OF SECTORS
; ES : BUFFER SEGMENT
; [BP] : SECTOR #
; [BP+1] : TRACK #
; [BP+2] : BUFFER OFFSET
;
; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
;-------------------------------------------------------------------------------
DISK_VERF PROC NEAR
AND @MOTOR_STATUS,01111111B ; INDICATE A READ OPERATION
MOV AX,0E642H ; AX = NEC COMMAND, DMA COMMAND
CALL RD_WR_VF ; COMMON READ/WRITEIVERIFY
RET
DISK_VERF ENDP
;-------------------------------------------------------------------------------
; DISK_FORMAT: DISKETTE FORMAT.
;
; ON ENTRY: DI : DRIVE #
; SI-HI : HEAD #
; SI-LOW : # OF SECTORS
; ES : BUFFER SEGMENT
; [BP] : SECTOR #
; [BP+1] : TRACK #
; [BP+2] : BUFFER OFFSET
;
; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
;-------------------------------------------------------------------------------
DISK_FORMAT PROC NEAR
CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH.
CALL FMT_INIT ; ESTABLISH STATE IF UNESTABLISHED
OR @MOTOR_STATUS,10000000B ; INDICATE WRITE OPERATION
CALL MED_CHANGE ; CHECK MEDIA CHANGE AND RESET IF SO
JC FM_DON ; MEDIA CHANGED, SKIP
CALL SEND_RATE ; SEND DATA RATE TO CONTROLLER
MOV AL,04AH ; WILL WRITE TO THE DISKETTE
CALL DMA_SETUP ; SET UP THE DMA
JC FM_DON ; RETURN WITH ERROR
MOV AH,04DH ; ESTABLISH THE FORMAT COMMAND
CALL NEC_INIT ; INITIALIZE THE NEC
MOV AX,OFFSET FM_DON ; LOAD ERROR ADDRESS
PUSH AX ; PUSH NEC_OUT ERROR RETURN
MOV DL,3 ; BYTES/SECTOR VALUE TO NEC
CALL GET_PARM
CALL NEC_OUTPUT
MOV DL,7 ; SECTORS/TRACK VALUE TO NEC
CALL GET_PARM
CALL NEC_OUTPUT
MOV DL,7 ; GAP LENGTH VALUE TO NEC
CALL GET_PARM
CALL NEC_OUTPUT
MOV DL,8 ; FILLER BYTE TO NEC
CALL GET_PARM
CALL NEC_OUTPUT
POP AX ; THROW AWAY ERROR
CALL NEC_TERM ; TERMINATE, RECEIVE STATUS, ETC,
FM_DON:
CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE
CALL SETUP_END ; VARIOUS CLEANUPS
MOV BX,SI ; GET SAVED AL TO BL
MOV AL,BL ; PUT BACK FOR RETURN
RET
DISK_FORMAT ENDP
;-------------------------------------------------------------------------------
; FNC_ERR: INVALID FUNCTION REQUESTED OR INVALID DRIVE: SET BAD COMMAND IN
; STATUS.
;
; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
;-------------------------------------------------------------------------------
FNC_ERR PROC NEAR ; INVALID FUNCTION REQUEST
MOV AX,SI ; RESTORE AL
MOV AH,BAD_CMD ; SET BAD COMMAND ERROR
MOV @DSKETTE_STATUS,AH ; STORE IN DATA AREA
STC ; SET CARRY INDICATING ERROR
RET
FNC_ERR ENDP
;-------------------------------------------------------------------------------
; DISK-PARMS: READ DRIVE PARAMETERS.
;
; ON ENTRY: DI : DRIVE #
;
; ON EXIT: CL/[BP] = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
; BITS 0-5 MAX SECTORS/TRACK
; CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
; BL/[BP+2] = BITS 7-4 = 0
; BITS 3-0 = VALID CMOS DRIVE TYPE
; BH/[BP+3] = 0
; DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
; DH/[BP+5] = MAX HEAD #
; DI/[BP+6] = OFFSET TO DISK_BASE
; ES = SEGMENT OF DISK_BASE
; AX = 0
;
; NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
; THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
; INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
; CALLER.
;-------------------------------------------------------------------------------
DISK_PARMS PROC NEAR
CMP DI,80H ; CHECK FOR FIXED MEDIA TYPE REQUEST
JB DISK_P2 ; CONTINUE IF NOT REQUEST FALL THROUGH
;----- FIXED DISK REQUEST FALL THROUGH ERROR
MOV AX,SI ; RESTORE AL WITH CALLERS VALUE
MOV AH,BAD_CMD ; SET BAD COMMAND ERROR IN TAH)
STC ; SET ERROR RETURN CODE
RET
DISK_P2:
CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH,
MOV WORD PTR [BP+2],0 ; DRIVE TYPE = 0
MOV AX,@EQUIP_FLAG ; LOAD EQUIPMENT FLAG FOR # DISKETTES
AND AL,11000011B ; KEEP DISKETTE DRIVE BITS
MOV DL,2 ; DISKETTE DRIVES = 2
CMP AL,01000001B ; 2 DRIVES INSTALLED ?
JZ DISK_P3 ; IF YES JUMP
DEC DL ; DISKETTE DRIVES = 1
CMP AL,00000001B ; 1 DRIVE INSTALLED ?
JNZ DISK_P8 ; IF NO JUMP
DISK_P3:
MOV [BP+4],DL ; STORE NUMBER OF DRIVES
CMP DI,1 ; CHECK FOR VALID DRIVE
JA DISK_P9 ; DRIVE INVALID
MOV BYTE PTR[BP+5],1 ; MAXIMUM HEAD NUMBER = 1
CALL CMOS_TYPE ; RETURN DRIVE TYPE IN AL
JC DISK_P4 ; IF CMOS BAD CHECKSUM ESTABLISHED
OR AL,AL ; TEST FOR NO DRIVE TYPE
JZ DISK_P4 ; JUMP IF SO
CMP AL,(DR_PTE-DR_PT)/2 ; > MAXIMUM
JA DISK_P4 ; IF SO JUMP
MOV [BP+2],AL ; STORE VALID CMOS DRIVE TYPE
DEC AL ; MAKE 0 ORIGIN
SHL AL,1 ; ACCOUNT FOR FIELD WIDTH
MOV BL,AL ; FINISH MAKING INDEX POINTER
XOR BH,BH ; CLEAR HIGH ORDER INDEX
MOV CX,CS;WORD PTR DR_PT[BX] ; GET MAX TRACK AND SECTOR
DISK_P4:
MOV AL,@DSK_STATE[DI] ; LOAD STATE FOR THIS DRIVE
TEST AL,MED_SET ; CHECK FOR ESTABLISHED STATE
JNZ DISK_P5 ; GO TO CMOS FOR DRIVE CHECK
CMP BYTE PTR [BP+2],0 ; CHECK FOR CMOS BAD/INVALID
JZ DISK_P9 ; CMCS BAD/INVALID AND UNESTABLISHED
JMP SHORT DISK_P6 ; CMOS GOOD AND UNESTABLISHED; USE CMOS
DISK_P5:
AND AL,RATE_MSK ; ISOLATE STATE
MOV CX,WORD PTR CS:DR_PT+2 ; GET DRIVE PARAMETERS FOR 1.2 M DRIVE
CMP AL,RATE_250 ; 1.2M DRIVE ?
JNE DISK_P6 ; 300 OR 500 RATE IS 1.2M DRIVE
MOV CX,WORD PTR CS:DR_PT ; GET DRIVE PARAMETERS 360K DRIVE
TEST @DSK_STATE[DI],TRK_CAPA ; 80 TRACK ?
JZ DISK_P6 ; MUST BE 360
MOV CX,WORD PTR CS:DR_PT,4 ; GET DRIVE PARAMETERS
OISK_P6:
MOV [BP],CX ; SAVE POINTER IN STACK FOR RETURN
LEA AX,DISK_BASE ; ADDRESS OF DISK_BASE
MOV [BP+6],AX ; SAVE IN STACK
MOV AX,CS ; SEGMENT DISK_BASE (SAME AS THIS ONE)
DISK_P7:
MOV ES,AX ; ES IS SEGMENT OF TABLE
CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE
XOR AX,AX ; CLEAR
CLC
RET
;----- NO DRIYE PRESENT HANDLER
DISK_P8:
MOV BYTE PTR [BP+4],0 ; CLEAR NUMBER OF DRIVES
OISK-P9:
XOR AX,AX ; CLEAR PARMS IF NO DRIVES OR CMOS BAD
MOV [BP],AX ; TRACKS, SECTORS/TRACK = 0
MOV [BP+5],AH ; HEAD = 0
MOV [BP+6],AX ; OFFSET TO DISK_BASE = 0
JMP DISK_P7 ; EXIT
DISK_PARMS ENDP
;-------------------------------------------------------------------------------
; DRIVE PARAMETER TABLE
;-------------------------------------------------------------------------------
DR_PT DB 09H,027H ; MAX. TRACKS, SECTORS/TRACK 360K
DB 0FH,04FH ; " " 1.2M
DB 09H,04FH ; " " 720K
DR_PTE EQU $
;-------------------------------------------------------------------------------
; DISK_TYPE: THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
;
; ON ENTRY: DI : DRIVE #
;
; ON EXIT: AH : DRIVE TYPE, CY=0
;-------------------------------------------------------------------------------
DISK_TYPE PROC NEAR
CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH.
MOV AL,@DSK_STATE[DI] ; GET PRESENT STATE INFORMATION
OR AL,AL ; CHECK FOR NO DRIVE
JZ NO_DRV
MOV AH,NOCHGLN ; NO CHANGE LINE FOR 40 TRACK DRIVE
TEST AL,TRK_CAPA ; IS THIS DRIVE AN 80 TRACK DRIVE?
JZ DT_BACK ; IF NO JUMP
MOV AH,CHGLN ; CHANGE LINE FOR 80 TRACK DRIVE
DT_BACK:
PUSH AX ; SAVE RETURN VALUE
CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE
POP AX ; RESTORE RETURN VALUE
CLC ; NO ERROR
MOV BX,SI ; GET SAVED AL TO BL
MOV AL,BL ; PUT BACK FOR RETURN
RET
NO_DRV: XOR AH,AH ; NO DRIVE PRESENT OR UNKNOWN
JMP SHORT DT_BACK
DISK_TYPE ENDP
;-------------------------------------------------------------------------------
; DISK_CHANGE : THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
;
; ON ENTRY: DI : DRIVE #
;
; ON EXIT: AH : @DSKETTE_STATUS
; 00 - DISK CHANGE LINE INACTIVE, CY = 0
; 06 - DISK CHANGE LINE ACTIVE, CY = 1
;-------------------------------------------------------------------------------
DISK_CHANGE PROC NEAR
CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH.
MOV AL,@DSK_STATE[DI] ; GET MEDIA STATE INFORMATION
OR AL,AL ; DRIVE PRESENT ?
JZ DC_NON ; JUMP IF NO DRIVE
TEST AL,TRK_CAPA ; 80 TRACK DRIVE ?
JZ SETIT ; IF SO , CHECK CHANGE LINE
CALL READ DSKCHNG ; GO CHECK STATE OF DISK CHANGE LINE
JZ FINIS ; CHANGE LINE NOT ACTIVE
SETIT: MOV @DSKETTE_STATUS,MEDIA_CHANGE ; INDICATE MEDIA REMOVED
FINIS: CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE
CALL SETUP_END ; VARIOUS CLEANUPS
MOV BX,SI ; GET SAVED AL TO BL
MOV AL,BL ; PUT BACK FOR RETURN
RET
DC_NON:
OR @DSKETTE_STATUS,TIME_OUT ; SET TIMEOUT, NO DRIVE
JMP SHORT FINIS
DISK_CHANGE ENDP
;-------------------------------------------------------------------------------
; FORMAT_SET : THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
; FOR THE FOLLOWING FORMAT OPERATION.
;
; ON ENTRY: SI LOW : DASD TYPE FOR FORMAT
; DI : DRIVE #
;
; ON EXIT: @DSKETTE_STATUS REFLECTS STATUS
; AH = @DSKETTE_STATUS
; CY = 1 IF ERROR
;-------------------------------------------------------------------------------
FORMAT-SET PROC NEAR
CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH.
PUSH SI ; SAVE DASD TYPE
MOV AX,SI ; AH = ? , AL , DASD TYPE
XOR AH,AH ; AH , 0 , AL , DASD TYPE
MOV SI,AX ; SI = DASD TYPE
AND @DSK_STATE[DI],NOT MED_DET+DBL_STEP+RATE_MSK ; CLEAR STATE
DEC SI ; CHECK FOR 320/360K MEDIA & DRIVE
JNZ NOT_320 ; BYPASS IF NOT
OR @DSK_STATE[DI],MED_DET+RATE_250 ; SET TO 320/360
JMP SHORT S0
NOT_320:
CALL MED_CHANGE ; CHECK FOR TIME_OUT
CMP @DSKETTE_STATUS,TIME_OUT
JZ S0 ; IF TIME OUT TELL CALLER
DEC SI ; CHECK FOR 320/360K IN 1.2M DRIVE
JNZ NOT_320_12 ; BYPASS IF NOT
OR @DSK_STATE[DI],MED_DET+DBL_STEP+RATE_300 ; SET STATE
JMP SHORT S0
NOT_320_12:
DEC SI ; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
JNZ NOT_12 ; BYPASS IF NOT
OR @DSK_STATE[DI],MED_DET+RATE_500 ; SET STATE VARIABLE
JMP SHORT S0 ; RETURN TO CALLER
NOT_12: DEC SI ; CHECK FOR SET DASD TYPE 04
JNZ FS_ERR ; BAD COMMAND EXIT IF NOT VALID TYPE
TEST @DSK_STATE[DI],DRV_DET ; DRIVE DETERMINED ?
JZ ASSUME ; IF STILL NOT DETERMINED ASSUME
MOV AL,MED_DET+RATE_300
TEST @DSK_STATE[DI],FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
JNZ OR_IT_IN ; IF 1.2 M THEN DATA RATE 300
ASSUME:
MOV AL,MED_DET+RATE_250 ; SET UP
OR-IT-IN:
OR @DSK_STATE[DI],AL ; OR IN THE CORRECT STATE
S0:
CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE
CALL SETUP_END ; VARIOUS CLEANUPS
POP BX ; GET SAVED AL TO BL
MOV AL,BL ; PUT BACK FOR RETURN
RET
FS_ERR
MOV @DSKETTE_STATUS,BAD_CMD ; UNKNOWN STATE,BAD COMMAND
JMP SHORT S0
FORMAT_SET ENDP
;-------------------------------------------------------------------------------
; XLAT_NEW: TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE MODE TO
; NEW ARCHITECTURE.
;
; ON ENTRY: DI : DRIVE
;-------------------------------------------------------------------------------
XLAT_NEW PROC NEAR
CMP DI,1 ; VALID DRIVE
JA XN_OUT ; IF INVALID BACK
CMP @DSK_STATE[DI],0 ; NO DRIVE ?
JZ DO_DET ; IF NO DRIVE ATTEMPT DETERMINE
MOV CX,DI ; CX = DRIVE NUMBER
SHL CL,2 ; CL = SHIFT COUNT, A=0, B=4
MOV AL,@HF_CNTRL ; DRIVE INFORMATION
ROR AL,CL ; TO LOW NIBBLE
AND AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
AND @DSK_STATE[DI],NOT DRV_DET+FMT_CAPA+TRK_CAPA
OR @DSK_STATE[DI],AL ; UPDATE DRIVE STATE
XN_OUT:
RET
DO_DET:
CALL DRIVE_DET ; TRY TO DETERMINE
RET
XLAT_NEW ENDP
;-------------------------------------------------------------------------------
; XLAT-OLD : TRANSLATES DISKETTE STATE LOCATIONS FROM NEW ARCHITECTURE TO
; COMPATIBLE MODE.
;
; ON ENTRY: DI : DRIVE
;-------------------------------------------------------------------------------
XLAT_OLD PROC NEAR
CMP DI,1 ; VALID DRIVE ?
JA XO_OUT ; IF INVALID BACK
CMP @DSK_STATE[DI],0 ; NO DRIVE ?
JZ XO_OUT ; IF NO DRIVE TRANSLATE DONE
;----- TEST FOR SAVED DRIVE INFORMATION ALREADY SET
MOV CX,DI ; CX = DRIVE NUMBER
SHL CL,2 ; CL = SHIFT COUNT, A=0, B=4
MOV AH,FMT_CAPA ; LOAD MULTIPLE DATA RATE BIT MASK
ROR AH,CL ; ROTATE BY MASK
TEST @HF_CNTRL,AH ; MULTIPLE-DATA RATE DETERMINED ?
JNZ SAVE_SET ; IF SO, NO NEED TO RE-SAVE
;----- ERASE DRIVE BITS IN OMF-CNTRL FOR THIS DRIVE
MOV AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
ROR AH,CL ; FIX MASK TO KEEP
NOT AH ; TRANSLATE MASK
AND @HF_CNTRL,AH ; KEEP BITS FROM OTHER DRIVE INTACT
;----- ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
MOV AL,@DSK_STATET[DI] ; ACCESS STATE
AND AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
ROR AL,CL ; FIX FOR THIS DRIVE
OR @HF_CNTRL,AL ; UPDATE SAVED DRIVE STATE
;----- TRANSLATE TO COMPATIBILITY MODE
SAVE_SET:
MOV AH,@DSK_STATE[DI] ; ACCESS STATE
MOV BH,AH ; TO BH FOR LATER
AND AH,RATE_MSK ; KEEP ONLY RATE
MOV AL,M1D1U ; AL = 1.2 IN 1.2 UNESTABLISHED
CMP AH,RATE_500 ; RATE 500 ?
JZ TST_DET ; JUMP IF 1.2 IN 1.2
MOV AL,M3D1U ; AL = 360 IN 1.2 UNESTABLISHEO
CMP AH,RATE_300 ; RATE 300 ?
JNZ CHK_250 ; IF SO FALL THRU
TEST BH,DBL_STEP ; CHECK FOR DOUBLE STEP
JNZ TST_DET ; MUST BE 360 IN 1.2
UNKNO:
MOV AL,MED_UNK ; NONE OF THE ABOVE
JMP SHORT AL_SET ; PROCESS COMPLETE
CHK_250:
MOV AL,M3D3U ; AL = 360 IN 360 UNESTABLISHED
CMP AH,RATE_250 ; RATE 250 ?
JNZ UNKNO ; IF SO FALL IHRU
TEST BH,TRK_CAPA ; 80 TRACK CAPABILITY ?
JNZ UNKNO ; IF SO JUMP, FALL THRU TEST DET
TST_DET:
TEST BH,MED_DET ; DETERMINED ?
JZ AL_SET ; IF NOT THEN SET
ADD AL,3 ; MAKE DETERMINED/ESTABLISHED
AL_SET:
AND @DSK_STATE[DI],NOT DRV_DET+FMT_CAPA+TRK_CARA ; CLEAR DRIVE
OR @DSK_STATE[DI],AL ; REPLACE WITH COMPATIBLE MODE
XO_OUT:
RET
XLAT_OLD ENDP
;-------------------------------------------------------------------------------
; RD_WR_VF : COMMON READ, WRITE AND VERIFY: MAIN LOOP FOR STATE RETRIES.
;
; ON ENTRY: AH : READ/WRITE/VERIFY DMA PARAMETER
; AL : READ/WRITE/VERIFY NEC PARAMETER
;
; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
;-------------------------------------------------------------------------------
RD_WR_VF PROC NEAR
PUSH AX ; SAVE DMA, NEC PARAMETERS
CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH.
CALL SETUP_STATE ; STATE INITIALIZATIONS
POP AX ; RESTORE DMA,NEC PARAMETERS
DO_AGAIN:
PUSH AX ; SAVE REAC/WRITEIVERIFY PARAMETER
CALL MED_CHANGE ; MEDIA CHANGE AND RESET IF CHANGED
POP AX ; RESTORE READIWRITE/VERIFY
JC RWV_END ; MEDIA CHANGE ERROR OR TIME-OUT
PUSH AX ; SAVE READ/WAIT/VERIFY PARAMETER
CALL SEND_RATE ; SEND DATA RATE TO NEC
CALL SETUP_DBL ; CHECK FOR DOUBLE STEP
JC CHK_RET ; ERROR FROM READ ID, POSSIBLE RETRY
POP AX ; RESTORE NEC,DMA COMMAND
PUSH AX ; SAVE NEC COMMAND
CALL DMA_SETUP ; SET UP THE DMA
POP AX ; RESTORE NEC COMMAND
JC RWV_BAC ; CHECK FOR DMA BOUNDARY ERROR
PUSH AX ; SAVE NEC COMMAND
CALL NEC_INIT ; INITIALIZE NEC
CALL RWV_COM ; OP CODE COMMON TO READ/WRITEIVERIFY
CALL NEC_TERM ; TERMINATE, GET STATUS, ETC.
CHK_RET:
CALL RETRY ; CHECK FOR, SETUP RETRY
POP AX ; RESTORE READ/WRITE/VIERIFY PARAMETER
JC DO_AGAIN ; CY = 1 MEANS RETRY
RWV_END:
CALL DSTATE ; ESTABLISH STATE IF SUCCESSFUL
CALL NUM_TRANS ; AL = NUMBER TRANSFERRED
RWV_BAC: ; BAD DMA ERROR ENTRY
PUSH AX ; SAVE NUMBER TRANSFERRED
CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE
POP AX ; RESTORE NUMBER TRANSFERRED
CALL SETUP_END ; VARIOUS CLEANUPS
RET
RD_WR_VF ENDP
;-------------------------------------------------------------------------------
; SETUP_STATE: INITIALIZES START AND END RATES.
;-------------------------------------------------------------------------------
SETUP_STATE PROC NEAR
TEST @DSK_STATE[DI],MED_DET ; MEDIA DETERMINED ?
JNZ J1C ; NO STATES IF DETERMINED
MOV AX,RATE_300*H+RATE_250 ; AH = START RATE, AL = END RATE
TEST @DSK_STATE[DI],DRV_DET ; DRIVE ?
JZ AX,SET ; DO NOT KNOW DRIVE
MOV AL,RATE_500 ; SET UP FOR 1.2 M END RATE
TEST @DSK_STATE[DI],FMT_CAPA ; 1.2 M ?
JNZ AX_SET ; JUMP WITH FIXED END RATE
MOV AX,RATE_250*X ; START A END RATE 250 FOR 360 DRIVE
AX_SET: AND @DSK_STATE[DI],NOT RATE_MSK+DBL_STEP ; TURN OFF THE RATE
OR @DSK_STATE[DI],AH ; RATE FIRST TO TRY
AND @LASTRATE,NOT STRT_MSK ; ERASE LAST TO TRY RATE BITS
ROR AL,4 ; TO OPERATION LAST RATE LOCATION
OR @LASTRATE,AL ; LAST RATE
J1C:
RET
SETUP_STATE ENDP
;-------------------------------------------------------------------------------
; FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
;-------------------------------------------------------------------------------
FMT_INIT PROC NEAR
TEST @DSK_STATE[DI],MED_DET ; IS MEDIA ESTABLISHED
JNZ F1_OUT ; IF SO RETURN
CALL CMOS_TYPE ; RETURN DRIVE TYPE IN AL
JC CL_DRV ; ERROR IN CMOS ASSUME NO DRIVE
DEC AL ; MAKE ZERO ORIGIN
JS CL_DRV ; NO DRIVE IF AL 0
MOV AH,@DSK_STATE[DI] ; AH = CURRENT STATE
AND AH,NOT MED_DET+DBL_STEP+RATE_MSK ; CLEAR
OR AL,AL ; CHECK FOR 360
JNZ N_360 ; IF 360 WILL BE 0
OR AH,MED_DET+RATE_250 ; ESTABLISH MEDIA
JMP SHORT SKP_STATE ; SKIP OTHER STATE PROCESSING
N_360: DEC AL ; 1.2 M DRIVE
JNZ N_12 ; JUMP IF NOT
OR AH,MED_DET+RATE_500 ; DEFAULT TO 1.2M FORMAT
JMP SHORT SKP_STATE ; SKIP OTHER STATE PROCESSING
N_12: DEC AL ; CHECK FOR TYPE 3
JNZ CL_DRV ; NO DRIVE, CMOS BAD
TEST AH,DRV_DET ; IS DRIVE DETERMINED
JZ ISNT_12 ; TREAT AS NON 1.2 DRIVE
TEST AH,FMT_CAPA ; 1S 1.2M
JZ ISNT_12 ; JUMP IF NOT
OR AH,MED_DET+RATE_300 ; RATE 300
JMP SHORT SKP_STATE ; CONTINUE
ISNT_12:
OR AH,MED_DET+RATE_250 ; MUST BE RATE 250
SKP_STATE:
MOV @DSK_STATE[DI],AH ; STORE AWAY
F1_OUT:
RET
CL_DRV; XOR AH,AH ; CLEAR STATE
JMP SHORT SKP_STATE ; SAVE IT
FMT_INIT ENDP
;-------------------------------------------------------------------------------
; MED_CHANGE: CHECKS FOR MEDIA CHANGE. RESETS MEDIA CHANGE, CHECKS MEDIA
; CHANGE AGAIN.
;
; ON EXIT: CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
; @DSKETTE_STATUS = ERROR CODE
;-------------------------------------------------------------------------------
MED_CHANGE PROC NEAR
CALL READ_DSKCHNG ; READ DISK CHANCE LINE STATE
JZ MED_C9 ; BYPASS HANDLING DISK CHANGE LINE
AND @DSK_STATE[DI],NOT MED_DET ; CLEAR STATE FOR THIS DRIVE
; THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
; ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
; BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
MOV CX,DI ; CL = DRIVE 0
MOV AL,1 ; MOTOR ON BIT MASK
SHL AL,CL ; TO APPROPRIATE POSITION
NOT AL ; KEEP ALL BUT MOTOR ON
CLI ; NO INTERRUPTS
AND @MOTOR_STATUS,AL ; TURN MOTOR OFF INDICATOR
STI ; INTERRUPTS ENABLED
CALL MOTOR_ON ; TURN MOTOR ON
;----- THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
CALL DISK_RESET ; RESET NEC
MOV CH,01H ; MOVE TO CYLINDER 1
CALL SEEK ; ISSUE SEEK
XOR CH,CH ; MOVE TO CYLINDER 0
CALL SEEK ; ISSUE SEEK
MOV @DSKETTE_STATUS,MEDIA_CHANGE ; STORE IN STATUS
CALL READ_DSKCHNG ; CHECK MEDIA CHANGED AGAIN
JZ MED_C8 ; IF ACTIVE, NO DISKETTE, TIMEOUT
MOV @DSKETTE_STATUS,TIME_OUT ; TIMEOUT IF DRIVE EMPTY
MED_C8:
STC ; MEDIA CHANGED, SET CY
RET
MED_C9:
CLC ; NO MEDIA CHANGED, CLEAR CY
RET
MED CHANGE ENDP
;-------------------------------------------------------------------------------