-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathFLOPPY.ASM
791 lines (664 loc) · 37 KB
/
FLOPPY.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
$Title ('DTC/PC BIOS Floppy Disk Driver V1.0')
$Pagelength (80) Pagewidth (132) Debug Nogen
Name Floppy
; Author: Don K. Harrison
; Start date: November 17, 1983 Last edit: December 22, 1983
; ************************
; * Module Description *
; ************************
;
; This module contains the floppy disk driver routines and
; the floppy disk interrupt service routines. The driver is
; accessed via interrupt 14 (TrapFDisk). The interrupt service
; is via interrupt 19 (TrapFDDriver).
; (c) Display Telecommunications Corporation, 1983
; All Rights Reserved
$Eject
; **********************
; * Revision History *
; **********************
$Eject
; ********************
; * Public Symbols *
; ********************
Public FloppyDriver, FloppyHdwrInt, FloppyParamsPointer
; *************
; * Equates *
; *************
; *****************************
; * Stack Frame Definitions *
; *****************************
PointerSegment Equ [BP+12]
PointerOffset Equ [BP+10]
DTL Equ Byte Ptr [BP+9]
GapSize Equ Byte Ptr [BP+8]
EOT Equ Byte Ptr [BP+7]
SectorSize Equ Byte Ptr [BP+6]
SectorNumber Equ Byte Ptr [BP+5]
HeadNumber Equ Byte Ptr [BP+4]
TrackNumber Equ Byte Ptr [BP+3]
DriveNumber Equ Byte Ptr [BP+2]
FDCCommand Equ Byte Ptr [BP+1]
NumberOfSectors Equ Byte Ptr [BP]
; ********************************
; * Disk Parameter Definitions *
; ********************************
Specify1 Equ Es:Byte Ptr [Si]
Specify2 Equ Es:Byte Ptr [Si+1]
MotorWait Equ Es:Byte Ptr [Si+2]
FormatGap Equ Es:Byte Ptr [Si+7]
FormatFiller Equ Es:Byte Ptr [Si+8]
HeadSettle Equ Es:Byte Ptr [Si+9]
MotorStart Equ Es:Byte Ptr [Si+10]
SoftParams Equ Es:Byte Ptr [Si]
; *****************
; * Status Bits *
; *****************
OkStat Equ 000000000B ;Ok status
TimeOutStat Equ 10000000B ;Timeout
BadSeekStat Equ 01000000B ;Seek error
BadFDCStat Equ 00100000B ;Floppy controller bad
BadCrcStat Equ 00010000B ;CRC error
DMAPageStat Equ 00001001B ;Dma requested to cross 64k
BadDMAStat Equ 00001000B ;Dma probably bad
SectNotFndStat Equ 00000100B ;Sector not found
WriteProtStat Equ 00000011B ;Disk write protected
BadAddMarkStat Equ 00000010B ;Address mark not found
BadCmdStat Equ 00000001B ;Unrecognizable command
; ***********
; * Modes *
; ***********
DMAVerifyMode Equ 01000010B ;Channel 2 verify normal
DMAReadMode Equ 01000110B ;Channel 2 read normal
DMAWriteMode Equ 01001010B ;Channel 2 write normal
; **************
; * Commands *
; **************
FDCReadCMD Equ 11100110B ;Read command
FDCWriteCMD Equ 11000101B ;Write command
FDCFormatCMD Equ 01001101B ;Format command
FDCRecalCMD Equ 00000111B ;Recalibrate command
FDCSpecifyCMD Equ 00000011B ;Specify command (timers)
FDCSenseIntCMD Equ 00001000B ;Sense interrupt command
FDCSeekCMD Equ 00001111B ;Seek command
$Include (IbmInc)
$Eject
; *******************
; * Data Segments *
; *******************
IntSegment Segment Public
Extrn FloppyParamsTrapAddr:Dword
IntSegment Ends
BiosStack Segment Public
BiosStack Ends
BiosDataArea Segment Public
Extrn FDCStatus:Byte, DisketteStat:Byte, SeekStatus:Byte
Extrn MotorStatus:Byte, MotorCount:Byte
BiosDataArea Ends
$Eject
; **************************************
; * Stack Frame After Initialization *
; **************************************
; -------------------------------
; | Return Address | BP+22
; -------------------------------
; | BP | BP+20
; -------------------------------
; | SI | BP+18
; -------------------------------
; | DI | BP+16
; -------------------------------
; | DS | BP+14
; -------------------------------
; | DMA Memory Pointer (Segment) | BP+12
; -------------------------------
; | DMA Memory Pointer (Offset ) | BP+10
; -------------------------------
; | DTL | GAP | BP+8
; -------------------------------
; | EOT | Sector Size | BP+6
; -------------------------------
; | Sector # | Head # | BP+4
; -------------------------------
; | Track # | Drive # | BP+2
; -------------------------------
; | Command | # of Sectors |<- BP
; -------------------------------
$Eject
; ******************
; * Code Segment *
; ******************
Bios Segment Common
Assume Cs:Bios, Ds:BiosDataArea, SS:BiosStack
Org 0EC59H ;Align with PC / XT
; Initialization of stack frame
FloppyDriver Proc Far
Sti ;Restore higher interrupts
Push Bp ;Save Block pointers Bp
Push Si ;...Si
Push Di ;...Di
Push Ds ;...Data segment
Push Es ;...Memory pointer SEG
Push Bx ;......OFFSET
Mov Di,Ax ;Save accumulator
; Point ES:SI at disk parameters
Assume Ds:IntSegment ;DS refers to segment at zero
Xor Ax,Ax ;Fill Command block
Mov Ds,Ax ;...from data
Les Si,FloppyParamsTrapAddr ;...pointed to by int 30
Assume Ds:BiosDataArea ;Tell ASM86 to use bios data
Mov Ax,BiosDataArea ;...set segment register
Mov Ds,Ax ;...to bios data
; Move values from disk parameters
Mov Bx,5 ;...starting at byte 5
Mov Ax,Es:[Bx][Si] ;Load ax
Push Ax ;...and push (DTL & GAP)
Dec Bx ;Decrement index
Dec Bx ;...by 2 and
Mov Ax,Es:[Bx][Si] ;Load ax
Push Ax ;...and push (EOT & Sec Sz)
Xchg Cl,Dh ;Re-arrange for
Xchg Dl,Cl ;...command block
Push Dx ;Save Cl, Dh (Sec# & HD#)
Push Cx ;Save Ch, Dl (TK# & DV#)
Push Di ;Save Ah, Al (Cmd & #Sectors)
Mov Bp,Sp ;Point at base of stack frame
; Parse and dispatch command
Call ParseAndGo ;Parse command and execute
; Set the motor timer and affect carry with status
Mov Ah,MotorWait ;Plug timer to keep
Mov MotorCount,Ah ;...drives running
Mov Ah,DisketteStat ;Affect carry flag
Cmp Ah,1 ;if >1, carry will be clear
Cmc ;...not, if >1, carry set
; Dissolve stack frame
Pop Bx ;Pop Ah,Al (Cmd & #Sectors)
Pop Cx ;Pop TK# & DV&
Pop Dx ;Pop SEC# & HD#
Xchg Dl,Cl ;Restore back to
Xchg Cl,Dh ;...calling convention
Pop Bx ;Pop EOT & SEC SIZE
Pop Bx ;Pop DTL & GAP
Pop Bx ;Restore DMA offset pointer
Pop Es ;Restore DMA segment pointer
Pop Ds ;Restore data segment pointer
Pop Di ;Restore pointers Di
Pop Si ;...Si
Pop Bp ;...Bp
Ret 2 ;Return without restoring flags
FloppyDriver Endp
$Eject
; ***********************************
; * Command Parser and Dispatcher *
; ***********************************
ParseAndGo Proc Near
Mov Al,FDCCommand ;Parse the command
Or Al,Al ;...Command = reset?
Jz ResetCommand ;...jump if Ah=0
Dec Al ;...Command = status?
Jz StatusCommand ;...jump if Ah=1
Cmp DriveNumber,3 ;Drive # must be 0 1 2 or 3
Ja BadDriveRtn ;...jump if out of range
Cmp Al,DiskCmdFormat ;Command =< Format (highest)
Jbe DiskIOShort ;...jump if 2 thru 5
BadDriveRtn:
Mov DisketteStat,BadCmdStat ;...else, unrecognizable
Ret ;...return with bad status
DiskIOShort:
Jmp DiskIO ;Jump and execute r/w/v/f
ParseAndGo Endp
; *****************************
; * Diskette Status Command *
; *****************************
StatusCommand Proc Near
Mov Al,DisketteStat ;Return the status of
Ret ;...the last operation
StatusCommand Endp
$Eject
; ***********************************************************
; * Reset Command Handler *
; * Returns are via ResetReturn or error conditions in *
; * FDCOut, ProbeInterrupt, and GetStatus causing 2 level *
; * return from those procs. *
; ***********************************************************
ResetCommand Proc
Mov Dx,PortFDCAdptMode ;Point at adapter mode port
Cli ;Prevent int level motor change
And MotorStatus,00001111B ;Strip all but motor bits
Mov Al,MotorStatus ;...and get it in Al
Mov Cl,4 ;Shift motor to upper for i/o
Shl Al,Cl ;...to mode port
Test Al,00100000B ;Motor 1?
Jnz MotorOneBit ;...jump if yes
Test Al,01000000B ;Motor 2?
Jnz MotorTwoBit ;...jump if yes
Test Al,10000000B ;Motor 3?
Jz MotorZeroBit ;...jump if no (0 or no motor)
Inc Al ;Inc 3 times to sel drive 3
MotorTwoBit:
Inc Al ;Inc 2 times to sel drive 2
MotorOneBit:
Inc Al ;Inc 1 time to sel drive 1
MotorZeroBit:
Mov SeekStatus,0 ;Require resets on all drives
Mov DisketteStat,OkStat ;...set OK status
Or Al,00001000B ;Interrupt/dma bit
Out Dx,Al ;...turn on motor, select and reset
Or Al,00000100B ;...turn off reset bit
Out Dx,Al ;...FDC now reset
Sti ;Restore interrupts and
Call WaitForInt ;...wait for one
Call ProbeInterrupt ;Get status
Mov Al,FDCStatus ;Ready transition?
Cmp Al,11000000B ;...indicated by C0 status
Jz ResetContinue ;Jump if ok
; FDC Error Return
Mov DisketteStat,BadFDCStat ;...if not, FDC may be bad
Jmp ResetReturn ;...jump and error out
ResetContinue:
Mov Al,FDCSpecifyCmd ;Specify timer settings
Call FDCOut ;...to FDC
Mov Al,Specify1 ;Send SPT and HUT
Call FDCOut ;...send it to FDC
Mov Al,Specify2 ;Send HLT and ND
Call FDCOut ;...send it to FDC
ResetReturn:
Ret ;Return, FDC will not respond
ResetCommand Endp
$Eject
; ***********************************************************
; * Diskette I/O Commands (Read / Write / Verify / Format *
; * Returns are via ErrorReturn, ErrorRtnNum, OperationOk *
; * or error conditions in FDCOut, ProbeInterrupt, and *
; * GetStatus causing 2 level return from those procs. *
; * No matter where the return, Al will have the actual *
; * number of sectors transferred *
; ***********************************************************
; Command and Mode Table
TableStruc Struc
Command Db FDCSpecifyCMD ;0 Specify command
Db 0 ;1 No command for status
Db FDCReadCMD ;2 Read command
Db FDCWriteCMD ;3 Write command
Db FDCReadCMD ;4 Verify command
Db FDCFormatCMD ;5 Format command
DMAMode Db 0 ;0 Dma Not used
Db 0 ;1 Dma Not used
Db DMAReadMode ;2 Read command
Db DMAWriteMode ;3 Write command
Db DMAVerifyMode ;4 Verify command
Db DMAWriteMode ;5 Format command
Write Db 0 ;0 Reset
Db 0 ;1 Status
Db 0 ;2 Read
Db 80H ;3 Write
Db 0 ;4 Verify
Db 80H ;5 Format
Bit Db 1,2,4,8 ;Quick bits
TheirError Db 10000000B ;End of track
Db 00100000B ;Data error
Db 00010000B ;Overrun error
Db 00000100B ;Sector not found
Db 00000010B ;Write protect error
Db 00000001B ;Missing address mark
OurError Db SectNotFndStat ;Sector not found
Db BadCrcStat ;Crc error
Db BadDmaStat ;Dma error
Db SectNotFndStat ;Sector not found
Db WriteProtStat ;Write protect
Db BadAddMarkStat ;Address mark not found
Db BadFDCStat ;None of the above (??)
TableStruc Ends
$Nolist
Table TableStruc<> ;MISSING LINE
$List
DiskIO Proc Near
Cli ;Clear ints during I/O and
Mov DisketteStat,OkStat ;...set OK status
Mov Al,FDCCommand ;Get command
Xor Ah,Ah ;...into Ax
Mov Di,Ax ;...and then into Di
Out PortDmaToggle,Al ;Set first/last f/f = first
Mov Al,Table.DMAMode[Di] ;Get DMA mode byte
Out PortDmaMode,Al ;...and output it to DMA
; Translate SEG:OFF to physical address
Mov Ax,PointerSegment ;Get segment part of pointer
Mov Cl,4 ;Multiply by 16 (bytes
Rol Ax,Cl ;...in a paragraph)
Mov Ch,Al ;Save upper nibble
And Ch,00001111B ;...in Ch
And Al,11110000B ;Isolate upper nibble in Al
Add Ax,PointerOffset ;Add offset in
Adc Ch,0 ;...and carry into Ch
Mov Dx,Ax ;Save lower 16 bits of address
; Send address to DMAC
Out PortDMACh2Base,Al ;...and output it
Mov Al,Ah ;...to DMA
Out PortDmaCH2Base,Al ;...base registers
Mov Al,Ch ;Now output top
Out PortPageChan2,Al ;...address to page registers
; Calculate Word Count
Mov Ah,NumberOfSectors ;Form # of sectors
Xor Al,Al ;...times 128
Shr Ax,1 ;...in Ax
Mov Cl,SectorSize ;Multiply by the
Shl Ax,Cl ;...number of bytes in sector
Dec Ax ;Correct for dma requirement
; Output it to DMAC
Out PortDMACh2Count,Al ;...and output
Xchg Al,Ah ;...to the
Out PortDMACh2Count,Al ;...DMA controller
; Test for word count error
Xchg Al,Ah ;Restore count in Ax
Add Ax,Dx ;Set carry if crossing 64k
Jnc NoCrossing ;...and jump if so
; Crossed 64k, Error return
Sti ;Interrupts Ok now
Mov DisketteStat,DMAPageStat;...else loadup error code
Jmp ErrorReturn ;...and return
NoCrossing:
Mov Al,00000010B ;Get mask bit for DMAC
Out PortDMAMaskSngl,Al ;...and enable the transfer
; Turn on drive motor and select drive
Mov MotorCount,255 ;Set large value during I/O
; Calculate Drive Bit from Drive Number
Mov Bl,DriveNumber ;Get drive number in
Xor Bh,Bh ;...Bx
Mov Al,Table.Bit[Bx] ;...and calculate bit number
Mov Ch,Al ;...save in ch for seek
; Indicate on for compatibility
Or MotorStatus,Al ;Indicate in status byte
; Actually turn it on and select drive
Mov Cl,4 ;Move motor bit to
Shl Al,Cl ;...upper nibble
Or Al,Bl ;...then or in drive number
Or Al,00001100B ;Add enable and not reset
Mov Dx,PortFDCAdptMode ;...point at adapter I/O port
Out Dx,Al ;...and output the data
; Restore interrupts from DMA section above
Sti ;Restore interrupts from above
; If write, wait for motor up to speed
Mov Al,Table.Write[Di] ;Test if command involves write
Or MotorStatus,Al ;...(for compatibility)
Or Al,Al ;...and affect flags
Jns WaitDone ;...jump if read (upper bit=0)
; Write command, wait for motor up to speed
Mov Ah,MotorStart ;Ah=# of 125ms to wait
Or Ah,Ah ;Affect flags
Jz WaitDone ;...if no wait (??), comply
Push Cx ;Save bit position in Ch
OuterLoop:
Xor Cx,Cx ;Max count in Cx
EighthSecLoop:
Loop EighthSecLoop ;Loop for 125 ms
Dec Ah ;Decrement outer loop
Jnz OuterLoop ;...and jump to the top of it
Pop Cx ;Restore bit position in Ch
WaitDone:
; Seek to track Ch = Motor Bit, Bl = Drive #
Test SeekStatus,Ch ;Need recal?
Jnz NoRecalReqd ;...jump if no
Or SeekStatus,Ch ;Show as recal
Mov Al,FDCRecalCMD ;...and send recal
Call FDCOut ;...command to FDC
Mov Al,Bl ;Then send drive number
Call FDCOut ;...which is in Bl from above
Call WaitForInt ;Wait for results
Call ProbeInterrupt ;Get status
NoRecalReqd:
Mov Al,FDCSeekCMD ;Send seek command
Call FDCOut ;...to FDC
Mov Al,Bl ;Send drive number
Call FDCOut ;...to FDC
Mov Al,TrackNumber ;Send track number
Call FDCOut ;...to FDC
Call WaitForInt ;Wait for results
Call ProbeInterrupt ;Get status
Mov Al,HeadSettle ;Get head settling time
Or Al,Al ;...none (??), comply
Jz MSTimerDone ;...and end timer
MSOuterLoop:
Mov Cx,550 ;1 ms timer
OneMsLoop:
Loop OneMsLoop ;Loop for a ms
Dec Al ;Decrement outer loop
Jnz MSOuterLoop ;Loop till done
MSTimerDone:
; Perform the operation
Mov Al,Table.Command[Di] ;Get operation command
Call FDCOut ;...and send it
Mov Al,HeadNumber ;Get head number
And Al,00000001B ;...make sure 0 or 1
Shl Al,1 ;...move it into
Shl Al,1 ;...position
Or Al,Bl ;...Or in drive number
Call FDCOut ;...and output second byte
Cmp FDCCommand,DiskCmdFormat ;Are we formatting?
Jne NotFormatting ;...jump if not
; Load parameters for format
Mov Al,SectorSize ;FDC "N" parameter
Call FDCOut ;...send it out
Mov Al,EOT ;FDC "SC" parameter
Call FDCOut ;...send it out
Mov Al,FormatGap ;FDC "GPL" parameter
Call FDCOut ;...send it out
Mov Al,FormatFiller ;FDC "D" parameter
Call FDCOut ;...send it out
Jmp CommandLoaded ;Continue below
; Load parameters for read / write / verify
NotFormatting:
Mov Cx,7 ;Transfer 7 bytes from
Mov Di,3 ;...stack frame starting at 9
FrameLoop:
Mov Al,[Bp][Di] ;Get byte from frame
Call FDCOut ;...and send it
Inc Di ;...inc index to next byte
Loop FrameLoop ;Loop till 7 bytes moved
; Wait for interrupt
CommandLoaded:
Call WaitForInt ;Wait for end of op. interrupt
Call GetStatus ;...Read in the status
; Test for error
Mov Al,FDCStatus ;Get first status byte
And Al,11000000B ;...normal termination?
Jz OperationOk ;...jump if ok
Cmp Al,01000000B ;...abnormal termination?
Je Translate ;...jump if yes
Mov DisketteStat,BadFDCStat ;...else error return
Jmp ErrorRtnNum ;...actual transferred
; Translate FDC error to our error
Translate:
Mov Al,FDCStatus+1 ;Look at second byte
Mov Cx,6 ;6 bits to translate
Xor Bx,Bx ;...point at byte 0
ErrorLoop:
Test Al,Table.TheirError[Bx] ;Test a bit from table
Jnz ErrorFound ;...and jump if it is set
Inc Bx ;...bump pointer
Loop ErrorLoop ;...and loop till done
; Falling thru to here means no bits were set (FDC error)
ErrorFound:
Mov Al,Table.OurError[Bx] ;Translate from table
Mov DisketteStat,Al ;...and into DisketteStat
; Calculate # of sectors transferred and return in Al
ErrorRtnNum:
OperationOk:
Mov Al,FDCStatus[3] ;Get track we ended up on
Cmp Al,TrackNumber ;...compare it to starting tk
Mov Al,FDCStatus[5] ;...get last sector
Je OnSameTrack ;...jump if didn't roll over
Mov Al,EOT ;Get last track
Inc Al ;...plus 1 into Al
OnSameTrack:
Sub Al,SectorNumber ;Return end minus start
Ret ;...equals num transferred
; Return for pre-operation errors
ErrorReturn:
Mov Al,0 ;No sectors transferred
Ret ;Return, operation failed
DiskIO Endp
; ******************************************
; * Wait for Interrupt and Return Result *
; ******************************************
WaitForInt Proc Near
Sti ;Ints on
Xor Cx,Cx ;Setup for 2 second wait
Mov Al,2 ;...for interrupt
IntWaitLoop:
Test SeekStatus,10000000B ;Interrupt will set this
Clc ;...clear carry for return
Jnz IntOccurred ;...jump if interrupt
Loop IntWaitLoop ;Loop till int occurrs
Dec Al ;Decrement outer loop
Jnz IntWaitLoop ;...and loop some more
Mov DisketteStat,TimeOutStat;Set error status
Pop Ax ;Discard return address
Xor Al,Al ;Indicate 0 bytes xferred
Stc ;Set carry for error and
Ret ;...return 2 levels up
IntOccurred:
And SeekStatus,01111111B ;Turn off interrupt bit
Ret ;...return
WaitForInt Endp
; *******************************
; * Read Data from Controller *
; *******************************
FDCIn Proc Near
Push Cx ;Save Cx
Xor Cx,Cx ;Maximum timeout
Mov Dx,PortFDCStatus ;Pointer to FDC Status port
FDCInLoop1:
In Al,Dx ;Get status
Or Al,Al ;Affect flags
Js MasterReady ;If upper bit set, jump
Loop FDCInLoop1 ;Loop till master set or T.O.
Mov DisketteStat,TimeOutStat;FDC did not respond, error
Jmp Short FDCInRtn ;...return
MasterReady:
Test Al,01000000B ;Correct direction?
Jnz CorrectDir ;...jump if so
Mov DisketteStat,BadFDCStat ;...else chip is bad, error out
FDCInRtn:
Pop Cx
Stc ;Indicate error
Ret ;...and return
; Data ready
CorrectDir:
Inc Dx ;Point at data port
In Al,Dx ;Get a byte
Push Ax ;...and save it
Mov Cx,10 ;Pause and let FDC get another
PauseLoop:
Loop PauseLoop ;...byte ready if it has one
Dec Dx ;Point back at status
In Al,Dx ;...and get it
Test Al,00010000B ;...test if still busy. Return
Clc ;...carry clear and
Pop Ax ;...restore data
Pop Cx ;...and registers, return
Ret ;...Z=1 if last byte
FDCIn Endp
; ************************************
; * Disk Interrupt Service Routine *
; ************************************
Org 0EF57H
FloppyHdwrInt Proc Far
Sti ;Restore interrupts
Push Ds ;Save Data segment
Push Ax ;Save an intermediate register
Mov Ax,BiosDataArea ;Load data segment
Mov Ds,Ax ;...with bios segment
Or SeekStatus,10000000B ;Turn on indicator bit
Mov Al,PicEOI ;Interrupt ack to Pic
Out PortPICOCW2,Al ;...to restore higher ints
Pop Ax ;Restore
Pop Ds ;...registers
Iret ;Restore flags and return
FloppyHdwrInt Endp
; ***************************
; * Read Operation Result *
; ***************************
ResultProc Proc Near
ProbeInterrupt:
Mov Al,FDCSenseIntCMD ;Send command to sense int
Call FDCOut ;...to FDC
GetStatus:
Push Bx ;Save Bx
Push Cx ;...and Cx
Mov Cx,7 ;Get 7 bytes max from FDC
Mov Bx,0 ;...set pointer to first byte
ResultLoop:
Call FDCIn ;Get a byte
Jc StatErrRtn ;...jump if an error occurred
Mov FDCStatus[Bx],Al ;...and store it
Jz StatusReturn ;Jump if the FDC is empty
Inc Bx ;...else bump pointer and
Loop ResultLoop ;...loop
Mov DisketteStat,BadFDCStat ;More than 7 bytes is an error
StatErrRtn:
Stc ;Set carry for error return
Pop Cx ;Restore Cx
Pop Bx ;...and Bx
Pop Ax ;Discard return address
Xor Al,Al ;Indicate 0 bytes xferred
Ret ;...and return 2 levels up
StatusReturn:
Pop Cx ;Restore Cx
Pop Bx ;...and Bx
Ret ;and return error
ResultProc Endp
; ******************************
; * Write Data to Controller *
; ******************************
FDCOut Proc Near
Push Cx ;Save
Push Dx ;...registers
Push Ax ;...on stack
Xor Cx,Cx ;Maximum timeout
Mov Dx,PortFDCStatus ;Pointer to FDC Status port
FDCOutLoop1:
In Al,Dx ;Get status
Or Al,Al ;Affect flags
Js OutMasterRdy ;If upper bit set, jump
Loop FDCOutLoop1 ;Loop till master set or T.O.
Mov DisketteStat,TimeOutStat;FDC did not respond, error
Jmp Short OutErrRtn ;...jump and return error
OutMasterRdy:
Test Al,01000000B ;Correct direction?
Jz OutCorrectDir ;...jump if so
Mov DisketteStat,BadFDCStat ;...else chip is bad, error out
Jmp Short OutErrRtn ;...jump and return error
OutCorrectDir:
Inc Dx ;Point at data port
Pop Ax ;Restore data to output
Out Dx,Al ;...and output it
Clc ;Clear carry
Pop Dx ;Restore Dx
Pop Cx ;...and Cx
Ret ;...and return
OutErrRtn:
Pop Ax ;Restore Ax
Pop Dx ;Restore Dx
Pop Cx ;...and Cx
Pop Ax ;Discard return address
Xor Al,Al ;Indicate 0 bytes xferred
Stc ;...and set carry flag
Ret ;...and return 2 levels back
FDCOut Endp
; **************************
; * Disk Base Parameters *
; **************************
Org 0EFC7H ;Align with PC / XT
FloppyParamsPointer Db 11001111B ;Specify byte 1
Db 00000010B ;Specify byte 2
Db 37 ;Motor timeout wait
Db 2 ;512 bytes per sector
Db 8 ;Last sector on a track
Db 42 ;Gap length
Db 0FFH ;DTL
Db 80 ;Format gap length
Db 0F6H ;Format fill byte
Db 25 ;Head settle time
Db 4 ;Motor start time
Bios Ends
End