-
Notifications
You must be signed in to change notification settings - Fork 0
/
fdc.asm
2252 lines (2067 loc) · 55.4 KB
/
fdc.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
;
fdc_start equ $
;-------------------------------------------------------------------------------
; test FDC command
;-------------------------------------------------------------------------------
f_flop nop
nop
call FD_INIT
scf
ret ; should go to return
MULT8 ; HL = H * L
push de
ld e, l
call mul8x8
pop de
ret
WRITESTR push hl
ld hl, de
call stdio_text
pop hl
ret
CPUSCL db 8 ; CPU MHZ-2
DELAY LD A,(CPUSCL)
.D1 DEC A
JR NZ,.D1
RET
VDELAY LD A,(CPUSCL)
.V1 DEC A
JR NZ,.V1
DEC DE
LD A,D
OR E
JP NZ, VDELAY
RET
LDELAY PUSH AF, DE
LD DE,31250
CALL VDELAY
POP DE, AF
RET
JPHL JP (HL)
; COMPUTE HL / DE = BC W/ REMAINDER IN HL & ZF
DIV16
LD A,H ; HL -> AC
LD C,L ; ...
LD HL,0 ; INIT HL
LD B,16 ; INIT LOOP COUNT
.DIV16A:
SCF
RL C
RLA
ADC HL,HL
SBC HL,DE
JR NC,.DIV16B
ADD HL,DE
DEC C
.DIV16B:
DJNZ .DIV16A ; LOOP AS NEEDED
LD B,A ; AC -> BC
LD A,H ; SET ZF
OR L ; ... BASED ON REMAINDER
RET ; DONE
;
TRUE equ 1
FALSE equ 0
;===============================================================================
FDMODE_DIO equ 1
FDMODE_DIO3 equ 2
FDMODE_DIDE equ 3
FDMODE_N8 equ 4
FDMODE_RCSMC equ 5
FDMODE_RCWDC equ 6
FDMODE_DYNO equ 7
FDMODE_ZETA equ 8
FDMODE_ZETA2 equ 9
FDMODE equ FDMODE_ZETA2
FDM720 equ 20
FDM144 equ 21
FDM360 equ 22
FDM120 equ 23
FDM111 equ 24
FDMEDIA equ FDM144 ; FD: DEFAULT MEDIA FORMAT FDM[720|144|360|120|111]
FDMEDIAALT equ FDM720 ; FD: ALTERNATE MEDIA FORMAT FDM[720|144|360|120|111]
MID_FD720 equ 5
BIOS_WBW equ 75
BIOS_UNA equ 76
BIOS equ BIOS_WBW
CPU_Z80 equ 20
CPU_Z180 equ 21
CPUFAM equ CPU_Z80
CPUMHZ equ 10
DIODEV_FD equ 0x10
FDMAUTO equ TRUE
FDTRACE equ 1
DSKYENABLE equ FALSE
define DIAGENABLE 0
define USEDELAY
LEDENABLE equ FALSE
DIAGDISKIO equ TRUE
LEDDISKIO equ TRUE
BID_BIOS equ 0xc0
BID_RAMN equ 31
BID_USR equ BID_RAMN-1
BF_SYS equ 0xF0
BF_SYSGET_CPUINFO equ 0xF0 ; GET CPU INFORMATION
BF_SYSGET .EQU BF_SYS + 8 ; GET HBIOS INFO
define FDC_LEN 13 ; table lengths
DIO_FNCNTx equ 12
; trash data
CB_CPUMHZ db CPUMHZ
;==================================================================================================
; FLOPPY DISK DRIVER
;==================================================================================================
;
; PORTS
; matches the WD37C65C
FDC_MSR equ 0x30 ; 8272 MAIN STATUS REGISTER
FDC_DATA equ 0x31 ; 8272 DATA PORT
FDC_DOR equ 0x38 ; DIGITAL OUTPUT REGISTER
FDC_DCR equ 0x28 ; CONFIGURATION CONTROL REGISTER
FDC_TC equ 0x38 ; TERMINAL COUNT (W/ DACK)
;
; DISK OPERATIONS
;
DOP_READ equ 0 ; READ OPERATION
DOP_WRITE equ 1 ; WRITE OPERATION
DOP_FORMAT equ 2 ; FORMAT OPERATION
DOP_READID equ 3 ; READ ID OPERATION
;
; FDC RESULT CODES
;
FRC_OK equ 0 ; 00
FRC_NOTIMPL equ -01H ; FF
FRC_CMDERR equ -02H ; FE
FRC_ERROR equ -03H ; FD
FRC_ABORT equ -04H ; FC
FRC_BUFMAX equ -05H ; FB
FRC_ABTERM equ -08H ; F8
FRC_INVCMD equ -09H ; F7
FRC_DSKCHG equ -0AH ; F6
FRC_ENDCYL equ -0BH ; F5
FRC_DATAERR equ -0CH ; F4
FRC_OVERRUN equ -0DH ; F3
FRC_NODATA equ -0EH ; F2
FRC_NOTWRIT equ -0FH ; F1
FRC_MISADR equ -10H ; F0
FRC_TOFDCRDY equ -11H ; EF
FRC_TOSNDCMD equ -12H ; EE
FRC_TOGETRES equ -13H ; ED
FRC_TOEXEC equ -14H ; EC
FRC_TOSEEKWT equ -15H ; EB
;
; FD DEVICE CONFIGURATION
;
FD_DEVCNT equ 2 ; 2 DEVICES SUPPORTED
FD_CFGSIZ equ 8 ; SIZE OF CFG TBL ENTRIES
;
; PER DEVICE DATA OFFSETS
; ; OFFSET OF...
FD_DEV equ 0 ; DEVICE NUMBER (BYTE)
FD_STAT equ 1 ; LAST STATUS (BYTE)
FD_MEDTYP equ 2 ; MEDIA TYPE FDM... (BYTE)
FD_CURTRK equ 3 ; CURRENT TRACK (BYTE)
FD_HST equ 4 ; HOSTS SEEK POSITION
FD_HSTTRK equ FD_HST + 0 ; HOST TRACK (WORD)
FD_HSTSEC equ FD_HST + 2 ; HOST SECTOR (BYTE)
FD_HSTHD equ FD_HST + 3 ; HOST HEAD (BYTE)
;
;
; FDC COMMAND DATA
;
FCD: ; FLOPPY CONFIGURATION DATA (PUBLIC) MANAGED AS A "BLOCK"
FCD_NUMCYL db 000H ; NUMBER OF CYLINDERS
FCD_NUMHD db 000H ; NUMBER OF HEADS
FCD_NUMSEC db 000H ; NUMBER OF SECTORS
FCD_SOT db 000H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
FCD_EOT ; END OF TRACK SECTOR (SAME AS SC SINCE SOT ALWAYS 1)
FCD_SC db 000H ; SECTOR COUNT
FCD_SECSZ dw 000H ; SECTOR SIZE IN BYTES
FCD_GPL db 000H ; GAP LENGTH (R/W)
FCD_GPLF db 000H ; GAP LENGTH (FORMAT)
FCD_SRTHUT db 000H ; STEP RATE, IBM PS/2 CALLS FOR 3ms, 0DH = 3ms SRT, HEAD UNLOAD TIME
FCD_HLTND db 000H ; HEAD LOAD TIME, IBM PS/2 CALLS FOR 15ms 08H = 16ms HUT
FCD_DOR db 000H ; DOR VALUE
FCD_DCR db 000H ; DCR VALUE
FCD_LEN equ $ - FCD
; DYNAMICALLY MANAGED (PUBLIC)
FCD_DS db 001H ; DRIVE SELECT (UNIT NUMBER 0-3)
FCD_C db 000H ; CYLINDER
FCD_H db 000H ; HEAD
FCD_R db 001H ; RECORD
FCD_D db 0E5H ; DATA FILL BYTE
; STATUS MANAGEMENT
FCD_DOP db 0FFH ; CURRENT OPERATION (SEE DOP_...)
FCD_IDLECNT dw 0 ; IDLE COUNT
FCD_TRACE db 0 ; TRACE LEVEL
FCD_TO db 0 ; TIMEOUT COUNTDOWN TIMER
FCD_FDCRDY db 0 ; FALSE MEANS FDC RESET NEEDED
;
;
FD_CFGTBL
; DEVICE 0, PRIMARY MASTER
db 0 ; DEVICE NUMBER
db 0 ; DEVICE STATUS
db FDMEDIA ; MEDIA TYPE
db 0xFF ; CURRENT TRACK
dw 0 ; HOST TRACK
db 0 ; HOST SECTOR
db 0 ; HOST HEAD
IF (FD_DEVCNT >= 2)
; DEVICE 1, PRIMARY SLAVE
db 1 ; DRIVER DEVICE NUMBER
db 0 ; DEVICE STATUS
db FDMEDIA ; MEDIA TYPE
db 0xFF ; CURRENT TRACK
dw 0 ; HOST TRACK
db 0 ; HOST SECTOR
db 0 ; HOST HEAD
ENDIF
;
IF ($ - FD_CFGTBL) != (FD_DEVCNT * FD_CFGSIZ)
display "*** INVALID FD CONFIG TABLE ***\n"
ENDIF
;
db 0xFF ; END MARKER
;
IF (FDTRACE > 0)
;
; FDC STATUS CODE STRINGS
;
FSS_OK db "OK",0
FSS_NOTIMPL db "NOT IMPLEMENTED",0
FSS_CMDERR db "COMMAND ERROR",0
FSS_ERROR db "ERROR",0
FSS_ABORT db "ABORT",0
FSS_BUFMAX db "BUFFER EXCEEDED",0
FSS_ABTERM db "ABNORMAL TERMINATION",0
FSS_INVCMD db "INVALID COMMAND",0
FSS_DSKCHG db "DISK CHANGE",0
FSS_ENDCYL db "END OF CYLINDER",0
FSS_DATAERR db "DATA ERROR",0
FSS_OVERRUN db "OVERRUN",0
FSS_NODATA db "NO DATA",0
FSS_NOTWRIT db "NOT WRITABLE",0
FSS_MISADR db "MISSING ADDRESS MARK",0
FSS_TOFDCRDY db "FDC READY TIMEOUT",0
FSS_TOSNDCMD db "SENDCMD TIMEOUT",0
FSS_TOGETRES db "GET RESULTS TIMEOUT",0
FSS_TOEXEC db "EXEC TIMEOUT",0
FSS_TOSEEKWT db "SEEK WAIT TIMEOUT",0
;
; FDC STATUS STRING TABLE
;
FSST: db FRC_OK : dw FSS_OK
FSST_ENTSIZ equ $ - FSST
db FRC_NOTIMPL : dw FSS_NOTIMPL
db FRC_CMDERR : dw FSS_CMDERR
db FRC_ERROR : dw FSS_ERROR
db FRC_ABORT : dw FSS_ABORT
db FRC_BUFMAX : dw FSS_BUFMAX
db FRC_ABTERM : dw FSS_ABTERM
db FRC_INVCMD : dw FSS_INVCMD
db FRC_DSKCHG : dw FSS_DSKCHG
db FRC_ENDCYL : dw FSS_ENDCYL
db FRC_DATAERR : dw FSS_DATAERR
db FRC_OVERRUN : dw FSS_OVERRUN
db FRC_NODATA : dw FSS_NODATA
db FRC_NOTWRIT : dw FSS_NOTWRIT
db FRC_MISADR : dw FSS_MISADR
db FRC_TOFDCRDY : dw FSS_TOFDCRDY
db FRC_TOSNDCMD : dw FSS_TOSNDCMD
db FRC_TOGETRES : dw FSS_TOGETRES
db FRC_TOEXEC : dw FSS_TOEXEC
db FRC_TOSEEKWT : dw FSS_TOSEEKWT
FSST_COUNT equ (($ - FSST) / FSST_ENTSIZ) ; # ENTRIES IN TABLE
ENDIF
;
; FDC COMMANDS
;
CFD_READ equ 00000110B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,DTL --> ST0,ST1,ST2,C,H,R,N
CFD_READDEL equ 00001100B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,DTL --> ST0,ST1,ST2,C,H,R,N
CFD_WRITE equ 00000101B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,DTL --> ST0,ST1,ST2,C,H,R,N
CFD_WRITEDEL equ 00001001B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,DTL --> ST0,ST1,ST2,C,H,R,N
CFD_READTRK equ 00000010B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,DTL --> ST0,ST1,ST2,C,H,R,N
CFD_READID equ 00001010B ; CMD,HDS/DS --> ST0,ST1,ST2,C,H,R,N
CFD_FMTTRK equ 00001101B ; CMD,HDS/DS,N,SC,GPL,D --> ST0,ST1,ST2,C,H,R,N
CFD_SCANEQ equ 00010001B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,STP --> ST0,ST1,ST2,C,H,R,N
CFD_SCANLOEQ equ 00011001B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,STP --> ST0,ST1,ST2,C,H,R,N
CFD_SCANHIEQ equ 00011101B ; CMD,HDS/DS,C,H,R,N,EOT,GPL,STP --> ST0,ST1,ST2,C,H,R,N
CFD_RECAL equ 00000111B ; CMD,DS --> <EMPTY>
CFD_SENSEINT equ 00001000B ; CMD --> ST0,PCN
CFD_SPECIFY equ 00000011B ; CMD,SRT/HUT,HLT/ND --> <EMPTY>
CFD_DRVSTAT equ 00000100B ; CMD,HDS/DS --> ST3
CFD_SEEK equ 00001111B ; CMD,HDS/DS --> <EMPTY>
CFD_VERSION equ 00010000B ; CMD --> ST0
;
;
; Specify Command:
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
; |Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
; | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
; | 1 | ----- STEP RATE ----- | -- HEAD UNLOAD TIME - |
; | 2 | ------------ HEAD LOAD TIME ----------- | NDM |
; +-----+-----+-----+-----+-----+-----+-----+-----+-----+
;
;
; Step Rate (milliseconds): Head Unload Time (milliseconds): Head Load Time (milliseconds):
; +------+------+------+------+------+ +------+------+------+------+------+ +------+------+------+------+------+
; | | BITRATE | | | BITRATE | | | BITRATE |
; | VAL | 1.0M | 500K | 300K | 250K | | VAL | 1.0M | 500K | 300K | 250K | | VAL | 1.0M | 500K | 300K | 250K |
; +------+------+------+------+------+ +------+------+------+------+------+ +------+------+------+------+------+
; | 0 | 8.0 | 16.0 | 26.7 | 32.0 | | 0 | 128 | 256 | 426 | 512 | | 0 | 128 | 256 | 426 | 512 |
; | 1 | 7.5 | 15.0 | 25.0 | 30.0 | | 1 | 8 | 16 | 26.7 | 32 | | 1 | 1 | 2 | 3.3 | 4 |
; | 2 | 7.0 | 14.0 | 23.3 | 28.0 | | 2 | 16 | 32 | 53.3 | 64 | | 2 | 2 | 4 | 6.7 | 8 |
; | ... | ... | ... | ... | ... | | ... | ... | ... | ... | ... | | ... | ... | ... | ... | ... |
; | 14 | 1.0 | 2.0 | 3.3 | 4.0 | | 14 | 112 | 224 | 373 | 448 | | 126 | 126 | 252 | 420 | 504 |
; | 15 | 0.5 | 1.0 | 1.7 | 2.0 | | 15 | 120 | 240 | 400 | 480 | | 127 | 127 | 254 | 423 | 508 |
; +------+------+------+------+------+ +------+------+------+------+------+ +------+------+------+------+------+
;
; IBM PS/2 CALLS FOR:
; STEP RATE: 3ms (6ms FOR ALL 41mm OR 720K DRIVES)
; HEAD LOAD TIME: 15ms
;
; STATIC CONFIGURATION, NEVER CHANGES (PRIVATE)
;
FCD_MT equ 000H ; MULTI-TRACK, WE DON'T USE, SET TO 0
FCD_MFM equ 001H ; MFM, 0=FM, 1=MFM, WE USE MFM ALWAYS
FCD_SK equ 000H ; SKIP MODE, WE DON'T USE, SET TO 0
FCD_N equ 002H ; SECTOR SIZE, N=2 FOR 512 BYTES
FCD_DTL equ 0FFH ; DATA LENGTH (WHEN N=0, SET TO FF OTHERWISE)
FCD_STP equ 001H ; SECTOR SCAN TYPE, 1=CONTIG, 2=ALTERNATING
;
FCD_PC720 db 050H ; NUMBER OF CYLINDERS
db 002H ; NUMBER OF HEADS
db 009H ; NUMBER OF SECTORS
db 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
db 009H ; SECTOR COUNT
dw 200H ; SECTOR SIZE IN BYTES
db 02AH ; GAP LENGTH (R/W)
db 050H ; GAP LENGTH (FORMAT)
db (13 << 4) | 0 ; SRT = 6ms, HUT = 512ms
db (4 << 1) | 1 ; HLT = 16ms, ND = YES
db DOR_BR250 ; DOR
db DCR_BR250 ; DCR
IF ($ - FCD_PC720) != FCD_LEN
display "*** FCD_PC720 SIZE ERROR!!! ***\n"
ENDIF
;
FCD_PC144 db 050H ; NUMBER OF CYLINDERS
db 002H ; NUMBER OF HEADS
db 012H ; NUMBER OF SECTORS
db 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
db 012H ; SECTOR COUNT
dw 200H ; SECTOR SIZE IN BYTES
db 01BH ; GAP LENGTH (R/W)
db 06CH ; GAP LENGTH (FORMAT)
db (13 << 4) | 0 ; SRT = 3ms, HUT = 256ms
db (8 << 1) | 1 ; HLT = 16ms, ND = YES
db DOR_BR500 ; DOR
db DCR_BR500 ; DCR
IF (($ - FCD_PC144) != FCD_LEN)
display "*** FCD_PC144 SIZE ERROR!!! ***\n"
ENDIF
FCD_PC360 db 028H ; NUMBER OF CYLINDERS
db 002H ; NUMBER OF HEADS
db 009H ; NUMBER OF SECTORS
db 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
db 009H ; SECTOR COUNT
dw 200H ; SECTOR SIZE IN BYTES
db 02AH ; GAP LENGTH (R/W)
db 050H ; GAP LENGTH (FORMAT)
db (13 << 4) | 0 ; SRT = 6ms, HUT = 512ms
db (4 << 1) | 1 ; HLT = 16ms, ND = YES
db DOR_BR250 ; DOR
db DCR_BR250 ; DCR
IF (($ - FCD_PC360) != FCD_LEN)
display "*** FCD_PC360 SIZE ERROR!!! ***\n"
ENDIF
FCD_PC120 db 050H ; NUMBER OF CYLINDERS
db 002H ; NUMBER OF HEADS
db 00FH ; NUMBER OF SECTORS
db 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
db 00FH ; SECTOR COUNT
dw 200H ; SECTOR SIZE IN BYTES
db 01BH ; GAP LENGTH (R/W)
db 054H ; GAP LENGTH (FORMAT)
db (10 << 4) | 0 ; SRT = 6ms, HUT = 256ms
db (8 << 1) | 1 ; HLT = 16ms, ND = YES
db DOR_BR500 ; DOR
db DCR_BR500 ; DCR
IF (($ - FCD_PC120) != FCD_LEN)
display "*** FCD_PC120 SIZE ERROR!!! ***\n"
ENDIF
FCD_PC111 db 04DH ; NUMBER OF CYLINDERS
db 002H ; NUMBER OF HEADS
db 00FH ; NUMBER OF SECTORS
db 001H ; START OF TRACK (ID OF FIRST SECTOR, USUALLY 1)
db 00FH ; SECTOR COUNT
dw 200H ; SECTOR SIZE IN BYTES
db 01BH ; GAP LENGTH (R/W)
db 054H ; GAP LENGTH (FORMAT)
db (13 << 4) | 0 ; SRT = 3ms, HUT = 256ms
db (25 << 1) | 1 ; HLT = 50ms, ND = YES
db DOR_BR500 ; DOR
db DCR_BR500 ; DCR
IF (($ - FCD_PC111) != FCD_LEN)
display "*** FCD_PC111 SIZE ERROR!!! ***\n"
ENDIF
; FCD LOOKUP TABLE (CALLED TO SET HL TO ADDRESS OF MEDIA DATA ABOVE)
; ENTRIES BELOW MUST MATCH COUNT AND VALUES OF FDMXXX IN STD.ASM
;
FCD_TBL:
LD HL,FCD_PC720 : RET ; FDM720 = 0
LD HL,FCD_PC144 : RET ; FDM144 = 1
LD HL,FCD_PC360 : RET ; FDM360 = 2
LD HL,FCD_PC120 : RET ; FDM120 = 3
LD HL,FCD_PC111 : RET ; FDM111 = 4
;
; DOR BITS (3AH)
;
; DISKIO 250KBPS 500KBPS
; ------- ------- -------
;D7 /DC/RDY 1 (N/A) 1 (N/A)
;D6 /REDWC (DENSITY) 0 (DD) 1 (HD)
;D5 P0* (PRECOMP BIT 0) 1 \ 0 \
;D4 P1* (PRECOMP BIT 1) 0 (125NS) 1 (125NS)
;D3 P2* (PRECOMP BIT 2) 0 / 0 /
;D2 MINI (BITRATE) 1 (250KBPS) 0 (500KBPS)
;D1 /MOTOR (ACTIVE LO) 1 (OFF) 1 (OFF)
;D0 TC (TERMINAL COUNT) 0 (OFF) 0 (OFF)
;
; *NOTE: FOR 9229 DATA SEPARATOR USED IN DISKIO, VALUE OF PRECOMP BITS CHANGES WITH MINI
; IF MINI=1 (250KBPS), USE 001 FOR 125NS PRECOMP, IF MINI=0, USE 010 FOR 125NS PRECOMP
;
IF (FDMODE == FDMODE_DIO)
DOR_BR250 equ 10100100B ; 250KBPS W/ MOTOR ON
DOR_BR500 equ 11010000B ; 500KBPS W/ MOTOR ON
DOR_INIT equ 11010010B ; INITIAL DEFAULT LATCH VALUE
ENDIF
;
; ZETA/DISKIO3 250KBPS 500KBPS
; ------------ ------- -------
;D7 /FDC_RST 1 (RUN) 1 (RUN)
;D6 DENSEL 1 (DD) 0 (HD)
;D5 P0 (PRECOMP BIT 0) 1 \ 1 \
;D4 P1 (PRECOMP BIT 1) 0 (125NS) 0 (125NS)
;D3 P2 (PRECOMP BIT 2) 0 / 0 /
;D2 MINI (BITRATE) 1 (250KBPS) 0 (500KBPS)
;D1 MOTOR 0 (OFF) 0 (OFF)
;D0 TC 0 (OFF) 0 (OFF)
;
; MOTOR AND DENSITY SELECT ARE INVERTED ON ZETA/DISKIO3 VS. DIO
;
IF ((FDMODE == FDMODE_ZETA) | (FDMODE == FDMODE_DIO3))
DOR_BR250 equ 11100110B ; 250KBPS W/ MOTOR ON
DOR_BR500 equ 10100010B ; 500KBPS W/ MOTOR ON
DOR_INIT equ 10100000B ; INITIAL DEFAULT LATCH VALUE
ENDIF
;
; RCSMC 250KBPS 500KBPS
; ------------ ------- -------
;D7 /FDC_RST 1 (RUN) 1 (RUN)
;D6 DENSEL 0 (DD) 1 (HD)
;D5 P0 (PRECOMP BIT 0) 1 \ 1 \
;D4 P1 (PRECOMP BIT 1) 0 (125NS) 0 (125NS)
;D3 P2 (PRECOMP BIT 2) 0 / 0 /
;D2 MOTORB 0 (OFF) 0 (OFF)
;D1 MOTORA 0 (OFF) 0 (OFF)
;D0 TC 0 (OFF) 0 (OFF)
;
; *** DIDE/N8/ZETA V2 ***
;
DOR_INIT equ 00001100B ; SOFT RESET INACTIVE, DMA ENABLED
DOR_BR250 equ DOR_INIT
DOR_BR500 equ DOR_INIT
;
; DCR (ONLY APPLIES TO DIDE, N8, AND ZETA V2)
;
DCR_BR250 equ 01H ; 250KBPS
DCR_BR500 equ 00H ; 500KBPS
;
IF (FDTRACE > 0)
;
; FDC COMMAND STRINGS
;
FCS_NOP db "NOP",0
FCS_READ db "READ",0
FCS_READDEL db "READDEL",0
FCS_WRITE db "WRITE",0
FCS_WRITEDEL db "WRITEDEL",0
FCS_READTRK db "READTRK",0
FCS_READID db "READID",0
FCS_FMTTRK db "FMTTRK",0
FCS_SCANEQ db "SCANEQ",0
FCS_SCANLOEQ db "SCANLOEQ",0
FCS_SCANHIEQ db "SCANHIEQ",0
FCS_RECAL db "RECAL",0
FCS_SENSEINT db "SENSEINT",0
FCS_SPECIFY db "SPECIFY",0
FCS_DRVSTAT db "DRVSTAT",0
FCS_SEEK db "SEEK",0
FCS_VERSION db "VER",0
;
; FDC COMMAND TABLE
;
FCT db CFD_READ : dw FCS_READ
FCT_ENTSIZ equ $ - FCT
db CFD_READDEL : dw FCS_READDEL
db CFD_WRITE : dw FCS_WRITE
db CFD_WRITEDEL : dw FCS_WRITEDEL
db CFD_READTRK : dw FCS_READTRK
db CFD_READID : dw FCS_READID
db CFD_FMTTRK : dw FCS_FMTTRK
db CFD_SCANEQ : dw FCS_SCANEQ
db CFD_SCANLOEQ : dw FCS_SCANLOEQ
db CFD_SCANHIEQ : dw FCS_SCANHIEQ
db CFD_RECAL : dw FCS_RECAL
db CFD_SENSEINT : dw FCS_SENSEINT
db CFD_SPECIFY : dw FCS_SPECIFY
db CFD_DRVSTAT : dw FCS_DRVSTAT
db CFD_SEEK : dw FCS_SEEK
db CFD_VERSION : dw FCS_VERSION
FCT_COUNT equ (($ - FCT) / FCT_ENTSIZ) ; # ENTRIES IN TABLE
ENDIF
;===============================================================================
; DRIVER FUNCTION TABLE
;===============================================================================
FD_FNTBL
dw FD_STATUS
dw FD_RESET
dw FD_SEEK
dw FD_READ
dw FD_WRITE
dw FD_VERIFY ;
dw FD_FORMAT ;
dw FD_DEVICE ;
dw FD_MEDIA ;
dw FD_DEFMED ;
dw FD_CAP ;
dw FD_GEOM ;
IF (($ - FD_FNTBL) != (DIO_FNCNTx * 2))
display "*** INVALID FD FUNCTION TABLE ***\n"
ENDIF
;===============================================================================
; Invalid functions
;===============================================================================
FD_VERIFY
FD_FORMAT
FD_DEFMED
jp bad_end ; INVALID SUB-FUNCTION
;===============================================================================
; FD_DEVICE
;===============================================================================
FD_DEVICE
LD D,DIODEV_FD ; D := DEVICE TYPE
LD E,(IY+FD_DEV) ; E := PHYSICAL DEVICE NUMBER
IF (FDMEDIA == FDM720)
LD C,%11010100 ; 3.5" DS/DD
ENDIF
IF (FDMEDIA == FDM144)
LD C,%11011000 ; 3.5" DS/HD
ENDIF
IF (FDMEDIA == FDM360)
LD C,%10110100 ; 5.25" DS/DD
ENDIF
IF (FDMEDIA == FDM120)
LD C,%10111000 ; 5.25" DS/HD
ENDIF
IF (FDMEDIA == FDM111)
LD C,%10010100 ; 8" DS/DD
ENDIF
XOR A ; SIGNAL SUCCESS
RET
;===============================================================================
; FD_MEDIA
;===============================================================================
FD_MEDIA:
LD A,E ; GET FLAGS
OR A ; SET FLAGS
JR Z, FD_MEDIA4 ; JUST REPORT CURRENT STATUS AND MEDIA
IF (FDMAUTO)
; SETUP TO READ TRK 0, HD 0, SEC 0
;LD A,C ; C STILL HAS REQUESTED DRIVE
LD A,(IY+FD_DEV) ; GET DRIVE UNIT
;AND 0FH
LD (FCD_DS),A
LD A,0
LD (FCD_C),A
LD (FCD_H),A
INC A
LD (FCD_R),A
LD A,DOP_READID
LD (FCD_DOP),A
IF (FDTRACE < 3)
; SUPPRESS TRACING FOR MEDIA TESTS
LD A,0
LD (FCD_TRACE),A
ENDIF
LD B,5
FD_MEDIARETRY:
; TRY PRIMARY MEDIA CHOICE FIRST
LD A,FDMEDIA
CALL FD_TESTMEDIA
JR Z,FD_MEDIA3 ; IF SUCCESS, WE ARE DONE
; TRY ALTERNATE MEDIA CHOICE
LD A,FDMEDIAALT
CALL FD_TESTMEDIA
JR Z,FD_MEDIA3 ; IF SUCCESS, WE ARE DONE
DJNZ FD_MEDIARETRY
; NO JOY, RETURN WITH E=0 (NO MEDIA)
;LD HL,(FDDS_MEDIAADR)
;LD (HL),0 ; SET TO NO MEDIA
LD (IY+FD_MEDTYP),0 ; SET DRIVE = NO MEDIA
LD E,0
OR 0xFF ; SIGNAL ERROR
RET
FD_TESTMEDIA:
;LD HL,(FDDS_MEDIAADR)
;LD (HL),A
LD (IY+FD_MEDTYP),A
PUSH BC
CALL FD_START
POP BC
RET
FD_MEDIA3:
IF (FDTRACE < 3)
; RESTORE TRACING FOR MEDIA TESTS
LD A,FDTRACE
LD (FCD_TRACE),A
ENDIF
ENDIF
FD_MEDIA4:
IF (FDTRACE >= 3)
LD DE,FDSTR_SELECT
CALL WRITESTR
;LD BC,(FDDS_MEDIAADR)
;CALL PRTHEXWORD
ENDIF
; LOAD THE MEDIA BYTE
;LD HL,(FDDS_MEDIAADR)
;LD A,(HL)
LD A,(IY+FD_MEDTYP) ; GET CURRENT MEDIA TYPE
ADD A,MID_FD720 ; ASSUMES MID_ VALUES ARE IN SAME ORDER AS FDM VALUES
IF (FDTRACE >= 3)
CALL PC_SPACE
CALL PRTHEXBYTE
ENDIF
LD E,A ; MOVE MEDIA VALUE TO E
XOR A ; SIGNAL SUCCESS
RET
;===============================================================================
; FD_CAP
;===============================================================================
FD_CAP:
CALL FD_GEOM ; GET GEOMETRY
; HL=TRACKS, D=HEADS, E=SECTORS
PUSH HL ; SAVE TRACK COUNT
LD H,D ; HEADS COUNT TO H
RES 7,H ; MAKE SURE LBA CAPABILITY BIT IS CLEARED
CALL MULT8 ; HL := H * E FOR SECTORS / CYL
POP DE ; RECOVER TRACKS, E == TRACK COUNT
LD H,L ; MOVE WORKING COUNT L --> H
CALL MULT8 ; HL := H * E FOR TOTAL SECTORS
LD DE,0 ; HI WORD ALWAYS ZERO
XOR A ; SIGNAL SUCCESS
RET ; DONE
;===============================================================================
; FD_GEOM
;===============================================================================
FD_GEOM
LD A,(IY+FD_MEDTYP) ; GET CURRENT MEDIA TYPE
RLCA ; TABLE IS 4 BYTE ENTRIES
RLCA ; A = A * 4
LD HL,FCD_TBL ; HL = START OF TABLE
LD D,0 ; SET DE TO TABLE OFFSET
LD E,A
ADD HL,DE ; OFFSET BASED ON DESIRED MEDIA
CALL JPHL ; CALL THE TABLE ENTRY (SEE FCD_TBL)
; HL NOW POINTS TO START OF DESIRED MEDIA INFO
LD A,(HL) ; GET TRACKS
INC HL ; POINT TO HEADS
LD D,(HL) ; GET HEADS
SET 7,D ; SET LBA CAPABILITY BIT
INC HL ; POINT TO SECTORS
LD E,(HL) ; GET SECTORS
LD L,A ; L := TRACKS
LD H,0 ; HI WORD OF TRACKS IS ALWAYS ZERO
XOR A ; SIGNAL SUCCESS
RET ; DONE
;===============================================================================
; FD_INIT
;===============================================================================
FD_INIT
call stdio_str
db "\r\nFD: IO=0x",0
LD A, FDC_MSR
CALL stdio_byte
call stdio_str
db " Units=2", 0
;
; SETUP THE DISPATCH TABLE ENTRIES
;
LD B,FD_DEVCNT ; LOOP CONTROL
LD IY,FD_CFGTBL ; START OF CFG TABLE
FD_INIT0:
PUSH BC ; SAVE LOOP CONTROL
LD BC,FD_FNTBL ; BC := FUNC TABLE ADR
PUSH IY ; CFG ENTRY POINTER
POP DE ; COPY TO DE
;;;;????? CALL DIO_ADDENT ; ADD ENTRY, BC IS NOT DESTROYED
CALL FD_INITUNIT ; DO UNIT INITIALIZATION
LD BC,FD_CFGSIZ ; SIZE OF CFG ENTRY
ADD IY,BC ; BUMP IY TO NEXT ENTRY
POP BC ; RESTORE BC
DJNZ FD_INIT0 ; LOOP AS NEEDED
;
LD A,FDTRACE
LD (FCD_TRACE),A
;
LD BC,0
LD (FCD_IDLECNT),BC
;
LD A,DOR_INIT
LD (FST_DOR),A
;
CALL FC_RESETFDC
CALL FD_CLRDSKCHG
;
LD A,TRUE
LD (FCD_FDCRDY),A
;
RET
;===============================================================================
; UNIT INITIALIZATION
;===============================================================================
FD_INITUNIT
LD (IY+FD_STAT),0 ; CLEAR STATUS
LD (IY+FD_MEDTYP),FDMEDIA ; SET DEFAULT MEDIA TYPE
LD (IY+FD_CURTRK),0xFE ; SPECIAL VALUE FOR CURTRK
RET
;===============================================================================
; FD_IDLE QUIESCES THE FLOPPY SUBSYSTEM (MOTOR OFF)
; AFTER BEING CALLED ENOUGH TIMES...
; SHOULD IT INVALIDATE THE BUFFER???
;===============================================================================
FD_IDLE
LD BC,(FCD_IDLECNT)
LD A,B
OR C
RET Z ; COUNTER ALREADY FIRED
DEC BC ; DECREMENT COUNTER
LD (FCD_IDLECNT),BC ; SAVE IT
LD A,B
OR C
RET NZ ; STILL COUNTING DOWN, RETURN
CALL FC_MOTOROFF ; COUNTER JUST EXPIRED, SHUTDOWN MOTOR!
RET
;===============================================================================
; FD_STATUS
;===============================================================================
FD_STATUS
LD A,(IY+FD_CURTRK) ; A = CURRENT TRACK
CP 0FFH ; IS CURRENT TRACK = $FF?
JR Z,FD_STATUS1 ; IF SO, NOT READY
XOR A ; A = 0 = OK
RET ; RETURN
FD_STATUS1:
OR A ; A ALREADY = $FF, JUST SET FLAGS
RET
;===============================================================================
; FD_RESET
;===============================================================================
FD_RESET:
XOR A ; ALWAYS OK
RET
;===============================================================================
; FD_CLRDSKCHG
;===============================================================================
FD_CLRDSKCHG
; PROCESS ANY PENDING DISK CHANGE NOTIFICATIONS
LD B,5
FD_CLRDSKCHG1:
PUSH BC
CALL FC_SENSEINT
POP BC
LD A,(FST_RC)
CP FRC_DSKCHG
RET NZ ; NO MORE DISK CHANGE NOTIFICATIONS
DJNZ FD_CLRDSKCHG1
;===============================================================================
; FD_WTSEEK
;
; WAIT FOR PENDING SEEK OPERATION TO COMPLETE BY POLLING SENSEINT
; AND WAITING FOR ABTERM OR OK.
;===============================================================================
FD_WTSEEK:
LD BC,1000H
FD_WTSEEKLOOP:
PUSH BC
CALL FC_SENSEINT
POP BC
LD A,(FST_RC) ; CHECK RC
CP FRC_ABTERM ; ABTERM = DONE/FAILED
JR Z,FD_RETRC
CP FRC_OK ; OK = DONE/SUCCESS
JR Z,FD_RETRC
DEC BC ; CHECK LOOP COUNTER IN BC
LD A,B ; "
OR C ; "
JR NZ,FD_WTSEEKLOOP ; LOOP UNTIL COUNTER EXHAUSTED
FD_RETRC:
LD A,(FST_RC)
OR A
RET ; TIMEOUT/FAILED
;===============================================================================
; FD_FDCRESET
;===============================================================================
FD_FDCRESET:
CALL FC_RESETFDC
CALL FD_CLRDSKCHG
LD A,TRUE
LD (FCD_FDCRDY),A
; MARK ALL DRIVES AS NEEDING RECALIBRATION
; NOTE THAT IF THE VALUE IS CURRENT $FF,
; WE NEED TO LEAVE IT ALONE, SO WE 'OR' IN THE
; 0xFE TO AVOID THIS SCENARIO.
PUSH IY ; SAVE CURRENT IY
LD B,FD_DEVCNT ; LOOP CONTROL
LD DE,FD_CFGSIZ ; SIZE OF CFG ENTRY
LD IY,FD_CFGTBL ; START OF CFG TABLE
FD_FDCRESET1:
LD A,(IY+FD_CURTRK) ; GET CURRENT TRACK
OR $FE ; APPLY NEW VALUE
LD (IY+FD_CURTRK),A ; UPDATE TRACK
ADD IY,DE ; BUMP IY TO NEXT ENTRY
DJNZ FD_FDCRESET1 ; LOOP AS NEEDED
POP IY ; RESTORE IY
RET
;===============================================================================
; FD_DRIVERESET
;
; ATTEMPT TO FULLY RESET FLOPPY DRIVE, PRIMARILY RECALIBRATE
;===============================================================================
FD_DRIVERESET:
CALL FC_SPECIFY
RET NZ ; ERROR, BAIL OUT
CALL FC_RECAL
RET NZ ; ERROR, BAIL OUT
; FIRST RECAL MAY FAIL TO REACH TRACK 0
; SO WE TRY ONCE MORE IN CASE OF A FAILURE
CALL FD_WTSEEK
RET Z
; SECOND TRY, ONLY IF NEEDED
CALL FC_RECAL
RET NZ ; ERROR, BAIL OUT
CALL FD_WTSEEK
RET
;===============================================================================
; FD_SEEK
;===============================================================================
FD_SEEK:
; DE:HL CONTAINS EITHER LBA OR CHS
BIT 7,D ; TEST LBA BIT
JR Z,FD_SEEK9 ; IF NOT LBA, JUST SAVE INCOMING VALUE
; NEED TO CONVERT LBA IN DE:HL TO CHS
; NOTE: FLOPPY LBA WILL NEVER EXCEED 16 BITS, SO WE IGNORE DE ENTIRELY
PUSH HL ; SAVE HL
CALL FD_GEOM ; E := SPT, D := HDS
POP HL ; RESTORE HL
RET NZ ; BAIL OUT ON ERROR
RES 7,D ; MAKE SURE LBA BIT IS CLEARED
LD (FD_CURGEOM),DE ; SAVE AS FD_CURSPT & FD_CURHDS
LD A,(FD_CURSPT) ; A := SECTORS PER TRACK
LD D,0 ; DE := SPT
LD E,A
CALL DIV16 ; DIVIDE, REMAINDER (SECTOR #) IN HL
PUSH HL ; SAVE SECTOR #
PUSH BC ; CYLINDERS AND HEADS BACK TO HL
POP HL
LD A,(FD_CURHDS) ; A := HEADS PER CYLINDER
LD D,0 ; DE : = HEADS PER CYLINDER
LD E,A
CALL DIV16 ; DIVIDE, BC := TRACK, REMAINDER (HEAD #) IN HL
PUSH HL ; SAVE HEAD #
PUSH BC ; COPY TRACK # TO HL
POP HL
POP BC ; RECOVER HEAD #
LD D,C ; HEAD # TO D
POP BC ; RECOVER SECTOR #
LD E,C ; SECTOR # TO E
FD_SEEK9: ; NOT LBA, JUST SAVE THE CHS VALUE IN CFG ENTRY
PUSH HL ; SAVE INCOMING HL TO (SP)
LD A,FD_HST ; A := HST OFFSET IN CFG ENTRY
CALL LDHLIYA ; HL := HST VALUE ADR
EX (SP),HL ; RESTORE INCOMING HL, HST ADR TO (SP)
POP BC ; HST ADR TO BC
CALL ST32 ; SAVE HST IN CFG ENTRY
XOR A ; SIGNAL SUCCESS
RET
;===============================================================================
; FD_READ
;===============================================================================
FD_READ
; CALL HB_DSKREAD ; HOOK HBIOS DISK READ SUPERVISOR
LD (FD_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
LD A,DOP_READ
JR FD_RW
;
FD_WRITE:
; CALL HB_DSKWRITE ; HOOK HBIOS DISK WRITE SUPERVISOR
LD (FD_DSKBUF),HL ; SAVE DISK BUFFER ADDRESS
LD A,DOP_WRITE
JR FD_RW
;
FD_RW:
LD (FCD_DOP),A ; SAVE REQUESTED DISK OPERATION
LD A,E ; BLOCK COUNT TO A
OR A ; SET FLAGS
RET Z ; ZERO SECTOR I/O, RETURN W/ E=0 & A=0
LD B,A ; INIT SECTOR DOWNCOUNTER
LD C,0 ; INIT SECTOR READ/WRITE COUNT
PUSH BC ; SAVE COUNTERS
CALL FD_GEOM ; E := SPT, D := HDS
POP BC ; RESTORE COUNTERS
JR NZ,FD_RW4 ; BAIL OUT ON ERROR
RES 7,D ; MAKE SURE LBA BIT IS CLEARED
LD (FD_CURGEOM),DE ; SAVE AS FD_CURSPT & FD_CURHDS
FD_RW1:
PUSH BC ; SAVE COUNTERS
CALL FD_RUN ; PERFORM SECTOR READ/WRITE
JR NZ,FD_RW3 ; IF ERROR, SKIP INCREMENT
; INCREMENT SECTOR AND CHECK FOR TRACK OVERFLOW
LD A,FD_HSTSEC ; HST SECTOR OFFSET IN CFG
CALL LDHLIYA ; HL := ADR OF HST SECTOR
INC (HL) ; INCREMENT SECTOR
LD A,(FD_CURSPT) ; A := SECTORS PER TRACK
CP (HL) ; COMPARE SPT TO CURRENT SECTOR
JR NZ,FD_RW2 ; IF NO OVERFLOW, DONE
; RESET SECTOR, INCREMENT HEAD, AND CHECK FOR CYLINDER OVERFLOW
LD (HL),0 ; RESET SECTOR TO ZERO