Subversion Repositories Kolibri OS

Rev

Rev 8055 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 8055 Rev 9932
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
7
 
8
$Revision: 8055 $
8
$Revision: 9932 $
9
 
9
 
10
 
10
 
11
;**********************************************************
11
;**********************************************************
12
;  Direct work with floppy disk drive
12
;  Direct work with floppy disk drive
13
;**********************************************************
13
;**********************************************************
14
; Source code author -  Kulakov Vladimir Gennadievich.
14
; Source code author -  Kulakov Vladimir Gennadievich.
15
; Adaptation and improvement -  Mario79.
15
; Adaptation and improvement -  Mario79.
16
 
-
 
17
;give_back_application_data:  ; give back to application
-
 
18
;     mov edi,[TASK_BASE]
-
 
19
;     mov edi,[edi+TASKDATA.mem_start]
-
 
20
;     add edi,ecx
16
 
21
give_back_application_data_1:
17
give_back_application_data_1:
22
        mov     esi, FDD_BUFF;FDD_DataBuffer  ;0x40000
18
        mov     esi, FDD_BUFF;FDD_DataBuffer  ;0x40000
23
        mov     ecx, 128
19
        mov     ecx, 128
24
        cld
20
        cld
25
        rep movsd
21
        rep movsd
26
        ret
22
        ret
27
 
-
 
28
;take_data_from_application:   ; take from application
-
 
29
;     mov esi,[TASK_BASE]
-
 
30
;     mov esi,[esi+TASKDATA.mem_start]
-
 
31
;     add esi,ecx
23
 
32
take_data_from_application_1:
24
take_data_from_application_1:
33
        mov     edi, FDD_BUFF;FDD_DataBuffer  ;0x40000
25
        mov     edi, FDD_BUFF;FDD_DataBuffer  ;0x40000
34
        mov     ecx, 128
26
        mov     ecx, 128
35
        cld
27
        cld
36
        rep movsd
28
        rep movsd
37
        ret
29
        ret
38
 
30
 
39
; Controller operations result codes (FDC_Status)
31
; Controller operations result codes (FDC_Status)
40
FDC_Normal         = 0 ; normal finish
32
FDC_Normal         = 0 ; normal finish
41
FDC_TimeOut        = 1 ; time out error
33
FDC_TimeOut        = 1 ; time out error
42
FDC_DiskNotFound   = 2 ; no disk in drive
34
FDC_DiskNotFound   = 2 ; no disk in drive
43
FDC_TrackNotFound  = 3 ; track not found
35
FDC_TrackNotFound  = 3 ; track not found
44
FDC_SectorNotFound = 4 ; sector not found
36
FDC_SectorNotFound = 4 ; sector not found
45
 
37
 
46
; Maximum values of the sector coordinates (specified
38
; Maximum values of the sector coordinates (specified
47
; values correspond to the parameters of the standard
39
; values correspond to the parameters of the standard
48
; 3-inch 1.44 MB floppy disk)
40
; 3-inch 1.44 MB floppy disk)
49
MAX_Track   = 79
41
MAX_Track   = 79
50
MAX_Head    =  1
42
MAX_Head    =  1
51
MAX_Sector  = 18
43
MAX_Sector  = 18
52
 
44
 
53
uglobal
45
uglobal
54
; Timer tick counter
46
; Timer tick counter
55
TickCounter dd ?
47
TickCounter dd ?
56
; Operation completion code with the floppy disk drive controller
48
; Operation completion code with the floppy disk drive controller
57
FDC_Status  DB ?
49
FDC_Status  DB ?
58
; Interrupt flag from floppy disk drive
50
; Interrupt flag from floppy disk drive
59
FDD_IntFlag DB ?
51
FDD_IntFlag DB ?
60
; The moment of the beginning of the last operation with FDD
52
; The moment of the beginning of the last operation with FDD
61
FDD_Time    DD ?
53
FDD_Time    DD ?
62
; Drive number
54
; Drive number
63
FDD_Type    db 0
55
FDD_Type    db 0
64
; Sector coordinates
56
; Sector coordinates
65
FDD_Track   DB ?
57
FDD_Track   DB ?
66
FDD_Head    DB ?
58
FDD_Head    DB ?
67
FDD_Sector  DB ?
59
FDD_Sector  DB ?
68
 
60
 
69
; Operation result block
61
; Operation result block
70
FDC_ST0 DB ?
62
FDC_ST0 DB ?
71
FDC_ST1 DB ?
63
FDC_ST1 DB ?
72
FDC_ST2 DB ?
64
FDC_ST2 DB ?
73
FDC_C   DB ?
65
FDC_C   DB ?
74
FDC_H   DB ?
66
FDC_H   DB ?
75
FDC_R   DB ?
67
FDC_R   DB ?
76
FDC_N   DB ?
68
FDC_N   DB ?
77
; Read operation repetition counter
69
; Read operation repetition counter
78
ReadRepCounter  DB ?
70
ReadRepCounter  DB ?
79
; Recalibration operation repetition counter
71
; Recalibration operation repetition counter
80
RecalRepCounter DB ?
72
RecalRepCounter DB ?
81
endg
73
endg
82
; Memory area for storing the readed sector
74
; Memory area for storing the readed sector
83
;FDD_DataBuffer:  times 512 db 0   ;DB 512 DUP (?)
75
;FDD_DataBuffer:  times 512 db 0   ;DB 512 DUP (?)
84
fdd_motor_status db 0
76
fdd_motor_status db 0
85
timer_fdd_motor  dd 0
77
timer_fdd_motor  dd 0
86
 
78
 
87
;**************************************
79
;**************************************
88
;* INITIALIZATION OF DMA MODE FOR FDD *
80
;* INITIALIZATION OF DMA MODE FOR FDD *
89
;**************************************
81
;**************************************
90
Init_FDC_DMA:
82
Init_FDC_DMA:
91
        pushad
83
        pushad
92
        mov     al, 0
84
        mov     al, 0
93
        out     0x0c, al; reset the flip-flop to a known state.
85
        out     0x0c, al; reset the flip-flop to a known state.
94
        mov     al, 6           ; mask channel 2 so we can reprogram it.
86
        mov     al, 6           ; mask channel 2 so we can reprogram it.
95
        out     0x0a, al
87
        out     0x0a, al
96
        mov     al, [dmamode]; 0x46 -> Read from floppy - 0x4A Write to floppy
88
        mov     al, [dmamode]; 0x46 -> Read from floppy - 0x4A Write to floppy
97
        out     0x0b, al
89
        out     0x0b, al
98
        mov     al, 0
90
        mov     al, 0
99
        out     0x0c, al; reset the flip-flop to a known state.
91
        out     0x0c, al; reset the flip-flop to a known state.
100
        mov     eax, 0xD000
92
        mov     eax, 0xD000
101
        out     0x04, al; set the channel 2 starting address to 0
93
        out     0x04, al; set the channel 2 starting address to 0
102
        shr     eax, 8
94
        shr     eax, 8
103
        out     0x04, al
95
        out     0x04, al
104
        shr     eax, 8
96
        shr     eax, 8
105
        out     0x81, al
97
        out     0x81, al
106
        mov     al, 0
98
        mov     al, 0
107
        out     0x0c, al; reset flip-flop
99
        out     0x0c, al; reset flip-flop
108
        mov     al, 0xff;set count (actual size -1)
100
        mov     al, 0xff;set count (actual size -1)
109
        out     0x5, al
101
        out     0x5, al
110
        mov     al, 0x1;[dmasize]       ;(0x1ff = 511 / 0x23ff =9215)
102
        mov     al, 0x1;[dmasize]       ;(0x1ff = 511 / 0x23ff =9215)
111
        out     0x5, al
103
        out     0x5, al
112
        mov     al, 2
104
        mov     al, 2
113
        out     0xa, al
105
        out     0xa, al
114
        popad
106
        popad
115
        ret
107
        ret
116
 
108
 
117
;***********************************
109
;***********************************
118
;* WRITE BYTE TO FDC DATA PORT     *
110
;* WRITE BYTE TO FDC DATA PORT     *
119
;* Parameters:                     *
111
;* Parameters:                     *
120
;* AL - byte to write.             *
112
;* AL - byte to write.             *
121
;***********************************
113
;***********************************
122
FDCDataOutput:
114
FDCDataOutput:
123
;       DEBUGF 1,'K : FDCDataOutput(%x)',al
115
;       DEBUGF 1,'K : FDCDataOutput(%x)',al
124
;        pusha
116
;        pusha
125
        push    eax ecx edx
117
        push    eax ecx edx
126
        mov     AH, AL    ; remember byte to AH
118
        mov     AH, AL    ; remember byte to AH
127
; Reset controller state variable
119
; Reset controller state variable
128
        mov     [FDC_Status], FDC_Normal
120
        mov     [FDC_Status], FDC_Normal
129
; Check the readiness of the controller to receive data
121
; Check the readiness of the controller to receive data
130
        mov     DX, 3F4h  ; (FDC state port)
122
        mov     DX, 3F4h  ; (FDC state port)
131
        mov     ecx, 0x10000 ; set timeout counter
123
        mov     ecx, 0x10000 ; set timeout counter
132
@@TestRS:
124
@@TestRS:
133
        in      AL, DX    ; read the RS register
125
        in      AL, DX    ; read the RS register
134
        and     AL, 0C0h  ; get digits 6 and 7
126
        and     AL, 0C0h  ; get digits 6 and 7
135
        cmp     AL, 80h   ; check digits 6 and 7
127
        cmp     AL, 80h   ; check digits 6 and 7
136
        je      @@OutByteToFDC
128
        je      @@OutByteToFDC
137
        loop    @@TestRS
129
        loop    @@TestRS
138
; Time out error
130
; Time out error
139
;       DEBUGF 1,' timeout\n'
131
;       DEBUGF 1,' timeout\n'
140
        mov     [FDC_Status], FDC_TimeOut
132
        mov     [FDC_Status], FDC_TimeOut
141
        jmp     @@End_5
133
        jmp     @@End_5
142
; Write byte to data port
134
; Write byte to data port
143
@@OutByteToFDC:
135
@@OutByteToFDC:
144
        inc     DX
136
        inc     DX
145
        mov     AL, AH
137
        mov     AL, AH
146
        out     DX, AL
138
        out     DX, AL
147
;        DEBUGF 1,' ok\n'
139
;        DEBUGF 1,' ok\n'
148
@@End_5:
140
@@End_5:
149
;        popa
141
;        popa
150
        pop     edx ecx eax
142
        pop     edx ecx eax
151
        ret
143
        ret
152
 
144
 
153
;******************************************
145
;******************************************
154
;*   READ BYTE FROM FDC DATA PORT         *
146
;*   READ BYTE FROM FDC DATA PORT         *
155
;* Procedure doesnt have input params.    *
147
;* Procedure doesnt have input params.    *
156
;* Output :                               *
148
;* Output :                               *
157
;* AL - byte read.                        *
149
;* AL - byte read.                        *
158
;******************************************
150
;******************************************
159
FDCDataInput:
151
FDCDataInput:
160
        push    ECX
152
        push    ECX
161
        push    DX
153
        push    DX
162
; Reset controller state variable
154
; Reset controller state variable
163
        mov     [FDC_Status], FDC_Normal
155
        mov     [FDC_Status], FDC_Normal
164
; Check the readiness of the controller to receive data
156
; Check the readiness of the controller to receive data
165
        mov     DX, 3F4h  ;(FDC state port)
157
        mov     DX, 3F4h  ;(FDC state port)
166
        mov     ecx, 0x10000 ; set timeout counter
158
        mov     ecx, 0x10000 ; set timeout counter
167
@@TestRS_1:
159
@@TestRS_1:
168
        in      AL, DX    ; read the RS register
160
        in      AL, DX    ; read the RS register
169
        and     AL, 0C0h  ; get digits 6 and 7
161
        and     AL, 0C0h  ; get digits 6 and 7
170
        cmp     AL, 0C0h  ; check digits 6 and 7
162
        cmp     AL, 0C0h  ; check digits 6 and 7
171
        je      @@GetByteFromFDC
163
        je      @@GetByteFromFDC
172
        loop    @@TestRS_1
164
        loop    @@TestRS_1
173
; Time out error
165
; Time out error
174
;       DEBUGF 1,'K : FDCDataInput: timeout\n'
166
;       DEBUGF 1,'K : FDCDataInput: timeout\n'
175
        mov     [FDC_Status], FDC_TimeOut
167
        mov     [FDC_Status], FDC_TimeOut
176
        jmp     @@End_6
168
        jmp     @@End_6
177
; Get byte from data port
169
; Get byte from data port
178
@@GetByteFromFDC:
170
@@GetByteFromFDC:
179
        inc     DX
171
        inc     DX
180
        in      AL, DX
172
        in      AL, DX
181
;       DEBUGF 1,'K : FDCDataInput: %x\n',al
173
;       DEBUGF 1,'K : FDCDataInput: %x\n',al
182
@@End_6:
174
@@End_6:
183
        pop     DX
175
        pop     DX
184
        pop     ECX
176
        pop     ECX
185
        ret
177
        ret
186
 
178
 
187
;*********************************************
179
;*********************************************
188
;* FDC INTERRUPT HANDLER                     *
180
;* FDC INTERRUPT HANDLER                     *
189
;*********************************************
181
;*********************************************
190
FDCInterrupt:
182
FDCInterrupt:
191
;       dbgstr 'FDCInterrupt'
183
;       dbgstr 'FDCInterrupt'
192
; Set the interrupt flag
184
; Set the interrupt flag
193
        mov     [FDD_IntFlag], 1
185
        mov     [FDD_IntFlag], 1
194
        mov     al, 1
186
        mov     al, 1
195
        ret
187
        ret
196
 
188
 
197
;*******************************************
189
;*******************************************
198
;* WAIT FOR INTERRUPT FROM FDC             *
190
;* WAIT FOR INTERRUPT FROM FDC             *
199
;*******************************************
191
;*******************************************
200
WaitFDCInterrupt:
192
WaitFDCInterrupt:
201
        pusha
193
        pusha
202
; Reset operation status byte
194
; Reset operation status byte
203
        mov     [FDC_Status], FDC_Normal
195
        mov     [FDC_Status], FDC_Normal
204
; Zero out the tick counter
196
; Zero out the tick counter
205
        mov     eax, [timer_ticks]
197
        mov     eax, [timer_ticks]
206
        mov     [TickCounter], eax
198
        mov     [TickCounter], eax
207
; Wait for the floppy disk interrupt flag to be set
199
; Wait for the floppy disk interrupt flag to be set
208
@@TestRS_2:
200
@@TestRS_2:
209
        call    change_task
201
        call    change_task
210
        cmp     [FDD_IntFlag], 0
202
        cmp     [FDD_IntFlag], 0
211
        jnz     @@End_7           ; interrupt occured
203
        jnz     @@End_7           ; interrupt occured
212
        mov     eax, [timer_ticks]
204
        mov     eax, [timer_ticks]
213
        sub     eax, [TickCounter]
205
        sub     eax, [TickCounter]
214
        cmp     eax, 200;50 ;25   ;5 ; wait 5 ticks
206
        cmp     eax, 200;50 ;25   ;5 ; wait 5 ticks
215
        jb      @@TestRS_2
207
        jb      @@TestRS_2
216
;        jl      @@TestRS_2
208
;        jl      @@TestRS_2
217
; Time out error
209
; Time out error
218
;       dbgstr 'WaitFDCInterrupt: timeout'
210
;       dbgstr 'WaitFDCInterrupt: timeout'
219
        mov     [FDC_Status], FDC_TimeOut
211
        mov     [FDC_Status], FDC_TimeOut
220
@@End_7:
212
@@End_7:
221
        popa
213
        popa
222
        ret
214
        ret
223
 
215
 
224
;***********************************
216
;***********************************
225
;* Turn on the motor of drive "A:" *
217
;* Turn on the motor of drive "A:" *
226
;***********************************
218
;***********************************
227
FDDMotorON:
219
FDDMotorON:
228
;       dbgstr 'FDDMotorON'
220
;       dbgstr 'FDDMotorON'
229
        pusha
221
        pusha
230
;        cmp     [fdd_motor_status],1
222
;        cmp     [fdd_motor_status],1
231
;        je      fdd_motor_on
223
;        je      fdd_motor_on
232
        mov     al, [flp_number]
224
        mov     al, [flp_number]
233
        cmp     [fdd_motor_status], al
225
        cmp     [fdd_motor_status], al
234
        je      fdd_motor_on
226
        je      fdd_motor_on
235
; Reset the FDD controller
227
; Reset the FDD controller
236
        mov     DX, 3F2h  ; motor control port
228
        mov     DX, 3F2h  ; motor control port
237
        mov     AL, 0
229
        mov     AL, 0
238
        out     DX, AL
230
        out     DX, AL
239
; Select and turn on the drive motor
231
; Select and turn on the drive motor
240
        cmp     [flp_number], 1
232
        cmp     [flp_number], 1
241
        jne     FDDMotorON_B
233
        jne     FDDMotorON_B
242
;        call    FDDMotorOFF_B
234
;        call    FDDMotorOFF_B
243
        mov     AL, 1Ch   ; Floppy A
235
        mov     AL, 1Ch   ; Floppy A
244
        jmp     FDDMotorON_1
236
        jmp     FDDMotorON_1
245
FDDMotorON_B:
237
FDDMotorON_B:
246
;        call    FDDMotorOFF_A
238
;        call    FDDMotorOFF_A
247
        mov     AL, 2Dh   ; Floppy B
239
        mov     AL, 2Dh   ; Floppy B
248
FDDMotorON_1:
240
FDDMotorON_1:
249
        out     DX, AL
241
        out     DX, AL
250
; Zero out the tick counter
242
; Zero out the tick counter
251
        mov     eax, [timer_ticks]
243
        mov     eax, [timer_ticks]
252
        mov     [TickCounter], eax
244
        mov     [TickCounter], eax
253
; wait 0.5 s
245
; wait 0.5 s
254
@@dT:
246
@@dT:
255
        call    change_task
247
        call    change_task
256
        mov     eax, [timer_ticks]
248
        mov     eax, [timer_ticks]
257
        sub     eax, [TickCounter]
249
        sub     eax, [TickCounter]
258
        cmp     eax, 50 ;10
250
        cmp     eax, 50 ;10
259
        jb      @@dT
251
        jb      @@dT
260
; Read results of RESET command
252
; Read results of RESET command
261
        push    4
253
        push    4
262
;       DEBUGF 1,'K : floppy reset results:'
254
;       DEBUGF 1,'K : floppy reset results:'
263
@@:
255
@@:
264
        mov     al, 8
256
        mov     al, 8
265
        call    FDCDataOutput
257
        call    FDCDataOutput
266
        call    FDCDataInput
258
        call    FDCDataInput
267
;       DEBUGF 1,' %x',al
259
;       DEBUGF 1,' %x',al
268
        call    FDCDataInput
260
        call    FDCDataInput
269
;       DEBUGF 1,' %x',al
261
;       DEBUGF 1,' %x',al
270
        dec     dword [esp]
262
        dec     dword [esp]
271
        jnz     @b
263
        jnz     @b
272
;       DEBUGF 1,'\n'
264
;       DEBUGF 1,'\n'
273
        pop     eax
265
        pop     eax
274
        cmp     [flp_number], 1
266
        cmp     [flp_number], 1
275
        jne     fdd_motor_on_B
267
        jne     fdd_motor_on_B
276
        mov     [fdd_motor_status], 1
268
        mov     [fdd_motor_status], 1
277
        jmp     fdd_motor_on
269
        jmp     fdd_motor_on
278
fdd_motor_on_B:
270
fdd_motor_on_B:
279
        mov     [fdd_motor_status], 2
271
        mov     [fdd_motor_status], 2
280
fdd_motor_on:
272
fdd_motor_on:
281
        call    save_timer_fdd_motor
273
        call    save_timer_fdd_motor
282
        popa
274
        popa
283
        ret
275
        ret
284
 
276
 
285
;*****************************************
277
;*****************************************
286
;*  SAVING TIME STAMP                    *
278
;*  SAVING TIME STAMP                    *
287
;*****************************************
279
;*****************************************
288
save_timer_fdd_motor:
280
save_timer_fdd_motor:
289
        mov     eax, [timer_ticks]
281
        mov     eax, [timer_ticks]
290
        mov     [timer_fdd_motor], eax
282
        mov     [timer_fdd_motor], eax
291
        ret
283
        ret
292
 
284
 
293
;*****************************************
285
;*****************************************
294
;*  CHECK THE MOTOR SHUTDOWN DELAY       *
286
;*  CHECK THE MOTOR SHUTDOWN DELAY       *
295
;*****************************************
287
;*****************************************
296
proc check_fdd_motor_status_has_work?
288
proc check_fdd_motor_status_has_work?
297
        cmp     [fdd_motor_status], 0
289
        cmp     [fdd_motor_status], 0
298
        jz      .no
290
        jz      .no
299
        mov     eax, [timer_ticks]
291
        mov     eax, [timer_ticks]
300
        sub     eax, [timer_fdd_motor]
292
        sub     eax, [timer_fdd_motor]
301
        cmp     eax, 500
293
        cmp     eax, 500
302
        jb      .no
294
        jb      .no
303
.yes:
295
.yes:
304
        xor     eax, eax
296
        xor     eax, eax
305
        inc     eax
297
        inc     eax
306
        ret
298
        ret
307
.no:
299
.no:
308
        xor     eax, eax
300
        xor     eax, eax
309
        ret
301
        ret
310
endp
302
endp
311
 
303
 
312
align 4
304
align 4
313
check_fdd_motor_status:
305
check_fdd_motor_status:
314
        cmp     [fdd_motor_status], 0
306
        cmp     [fdd_motor_status], 0
315
        je      end_check_fdd_motor_status_1
307
        je      end_check_fdd_motor_status_1
316
        mov     eax, [timer_ticks]
308
        mov     eax, [timer_ticks]
317
        sub     eax, [timer_fdd_motor]
309
        sub     eax, [timer_fdd_motor]
318
        cmp     eax, 500
310
        cmp     eax, 500
319
        jb      end_check_fdd_motor_status
311
        jb      end_check_fdd_motor_status
320
        call    FDDMotorOFF
312
        call    FDDMotorOFF
321
        mov     [fdd_motor_status], 0
313
        mov     [fdd_motor_status], 0
322
end_check_fdd_motor_status_1:
314
end_check_fdd_motor_status_1:
323
end_check_fdd_motor_status:
315
end_check_fdd_motor_status:
324
        ret
316
        ret
325
 
317
 
326
;**********************************
318
;**********************************
327
;* TURN OFF MOTOR OF DRIVE        *
319
;* TURN OFF MOTOR OF DRIVE        *
328
;**********************************
320
;**********************************
329
FDDMotorOFF:
321
FDDMotorOFF:
330
;       dbgstr 'FDDMotorOFF'
322
;       dbgstr 'FDDMotorOFF'
331
        push    AX
323
        push    AX
332
        push    DX
324
        push    DX
333
        cmp     [flp_number], 1
325
        cmp     [flp_number], 1
334
        jne     FDDMotorOFF_1
326
        jne     FDDMotorOFF_1
335
        call    FDDMotorOFF_A
327
        call    FDDMotorOFF_A
336
        jmp     FDDMotorOFF_2
328
        jmp     FDDMotorOFF_2
337
FDDMotorOFF_1:
329
FDDMotorOFF_1:
338
        call    FDDMotorOFF_B
330
        call    FDDMotorOFF_B
339
FDDMotorOFF_2:
331
FDDMotorOFF_2:
340
        pop     DX
332
        pop     DX
341
        pop     AX
333
        pop     AX
342
        ; clearing caching flags due to information obsolescence
334
        ; clearing caching flags due to information obsolescence
343
        or      [floppy_media_flags+0], FLOPPY_MEDIA_NEED_RESCAN
335
        or      [floppy_media_flags+0], FLOPPY_MEDIA_NEED_RESCAN
344
        or      [floppy_media_flags+1], FLOPPY_MEDIA_NEED_RESCAN
336
        or      [floppy_media_flags+1], FLOPPY_MEDIA_NEED_RESCAN
345
        ret
337
        ret
346
 
338
 
347
FDDMotorOFF_A:
339
FDDMotorOFF_A:
348
        mov     DX, 3F2h  ; motor control port
340
        mov     DX, 3F2h  ; motor control port
349
        mov     AL, 0Ch   ; Floppy A
341
        mov     AL, 0Ch   ; Floppy A
350
        out     DX, AL
342
        out     DX, AL
351
        ret
343
        ret
352
 
344
 
353
FDDMotorOFF_B:
345
FDDMotorOFF_B:
354
        mov     DX, 3F2h  ; motor control port
346
        mov     DX, 3F2h  ; motor control port
355
        mov     AL, 5h    ; Floppy B
347
        mov     AL, 5h    ; Floppy B
356
        out     DX, AL
348
        out     DX, AL
357
        ret
349
        ret
358
 
350
 
359
;*******************************
351
;*******************************
360
;* RECALIBRATE DRIVE "A:"      *
352
;* RECALIBRATE DRIVE "A:"      *
361
;*******************************
353
;*******************************
362
RecalibrateFDD:
354
RecalibrateFDD:
363
;       dbgstr 'RecalibrateFDD'
355
;       dbgstr 'RecalibrateFDD'
364
        pusha
356
        pusha
365
        call    save_timer_fdd_motor
357
        call    save_timer_fdd_motor
366
; Clear the interrupt flag
358
; Clear the interrupt flag
367
        mov     [FDD_IntFlag], 0
359
        mov     [FDD_IntFlag], 0
368
; Send the "Recalibration" command
360
; Send the "Recalibration" command
369
        mov     AL, 07h
361
        mov     AL, 07h
370
        call    FDCDataOutput
362
        call    FDCDataOutput
371
        mov     AL, [flp_number]
363
        mov     AL, [flp_number]
372
        dec     AL
364
        dec     AL
373
        call    FDCDataOutput
365
        call    FDCDataOutput
374
; Wait for the operation to complete
366
; Wait for the operation to complete
375
        call    WaitFDCInterrupt
367
        call    WaitFDCInterrupt
376
        cmp     [FDC_Status], 0
368
        cmp     [FDC_Status], 0
377
        jne     .fail
369
        jne     .fail
378
; Read results of RECALIBRATE command
370
; Read results of RECALIBRATE command
379
;       DEBUGF 1,'K : floppy recalibrate results:'
371
;       DEBUGF 1,'K : floppy recalibrate results:'
380
        mov     al, 8
372
        mov     al, 8
381
        call    FDCDataOutput
373
        call    FDCDataOutput
382
        call    FDCDataInput
374
        call    FDCDataInput
383
        push    eax
375
        push    eax
384
;       DEBUGF 1,' %x',al
376
;       DEBUGF 1,' %x',al
385
        call    FDCDataInput
377
        call    FDCDataInput
386
;       DEBUGF 1,' %x',al
378
;       DEBUGF 1,' %x',al
387
;       DEBUGF 1,'\n'
379
;       DEBUGF 1,'\n'
388
        pop     eax
380
        pop     eax
389
        test    al, 0xC0
381
        test    al, 0xC0
390
        jz      @f
382
        jz      @f
391
        mov     [FDC_Status], FDC_DiskNotFound
383
        mov     [FDC_Status], FDC_DiskNotFound
392
@@:
384
@@:
393
.fail:
385
.fail:
394
        call    save_timer_fdd_motor
386
        call    save_timer_fdd_motor
395
        popa
387
        popa
396
        ret
388
        ret
397
 
389
 
398
;*****************************************************
390
;*****************************************************
399
;*                    TRACK SEARCH                   *
391
;*                    TRACK SEARCH                   *
400
;* Parameters are passed through global variables:   *
392
;* Parameters are passed through global variables:   *
401
;* FDD_Track - track number (0-79);                  *
393
;* FDD_Track - track number (0-79);                  *
402
;* FDD_Head - head number (0-1).                     *
394
;* FDD_Head - head number (0-1).                     *
403
;* Result of operation is written to FDC_Status.     *
395
;* Result of operation is written to FDC_Status.     *
404
;*****************************************************
396
;*****************************************************
405
SeekTrack:
397
SeekTrack:
406
;       dbgstr 'SeekTrack'
398
;       dbgstr 'SeekTrack'
407
        pusha
399
        pusha
408
        call    save_timer_fdd_motor
400
        call    save_timer_fdd_motor
409
; Clear the interrupt flag
401
; Clear the interrupt flag
410
        mov     [FDD_IntFlag], 0
402
        mov     [FDD_IntFlag], 0
411
; Send "Search" command
403
; Send "Search" command
412
        mov     AL, 0Fh
404
        mov     AL, 0Fh
413
        call    FDCDataOutput
405
        call    FDCDataOutput
414
        ; Send head / drive number byte
406
        ; Send head / drive number byte
415
        mov     AL, [FDD_Head]
407
        mov     AL, [FDD_Head]
416
        shl     AL, 2
408
        shl     AL, 2
417
        call    FDCDataOutput
409
        call    FDCDataOutput
418
        ; Send track number byte
410
        ; Send track number byte
419
        mov     AL, [FDD_Track]
411
        mov     AL, [FDD_Track]
420
        call    FDCDataOutput
412
        call    FDCDataOutput
421
; Wait for the operation to complete
413
; Wait for the operation to complete
422
        call    WaitFDCInterrupt
414
        call    WaitFDCInterrupt
423
        cmp     [FDC_Status], FDC_Normal
415
        cmp     [FDC_Status], FDC_Normal
424
        jne     @@Exit
416
        jne     @@Exit
425
; Save search result
417
; Save search result
426
        mov     AL, 08h
418
        mov     AL, 08h
427
        call    FDCDataOutput
419
        call    FDCDataOutput
428
        call    FDCDataInput
420
        call    FDCDataInput
429
        mov     [FDC_ST0], AL
421
        mov     [FDC_ST0], AL
430
        call    FDCDataInput
422
        call    FDCDataInput
431
        mov     [FDC_C], AL
423
        mov     [FDC_C], AL
432
; Check search result
424
; Check search result
433
        ; Is search finished?
425
        ; Is search finished?
434
        test    [FDC_ST0], 100000b
426
        test    [FDC_ST0], 100000b
435
        je      @@Err
427
        je      @@Err
436
        ; Is the specified track found?
428
        ; Is the specified track found?
437
        mov     AL, [FDC_C]
429
        mov     AL, [FDC_C]
438
        cmp     AL, [FDD_Track]
430
        cmp     AL, [FDD_Track]
439
        jne     @@Err
431
        jne     @@Err
440
        ; Does the head number match the specified one?
432
        ; Does the head number match the specified one?
441
; The H bit (Head Address) in ST0 will always return a "0" (c) 82077AA datasheet,
433
; The H bit (Head Address) in ST0 will always return a "0" (c) 82077AA datasheet,
442
; description of SEEK command. So we can not verify the proper head.
434
; description of SEEK command. So we can not verify the proper head.
443
;        mov     AL, [FDC_ST0]
435
;        mov     AL, [FDC_ST0]
444
;        and     AL, 100b
436
;        and     AL, 100b
445
;        shr     AL, 2
437
;        shr     AL, 2
446
;        cmp     AL, [FDD_Head]
438
;        cmp     AL, [FDD_Head]
447
;        jne     @@Err
439
;        jne     @@Err
448
        ; Operation completed successfully
440
        ; Operation completed successfully
449
;        dbgstr 'SeekTrack: FDC_Normal'
441
;        dbgstr 'SeekTrack: FDC_Normal'
450
        mov     [FDC_Status], FDC_Normal
442
        mov     [FDC_Status], FDC_Normal
451
        jmp     @@Exit
443
        jmp     @@Exit
452
@@Err:  ; Track not found
444
@@Err:  ; Track not found
453
;       dbgstr 'SeekTrack: FDC_TrackNotFound'
445
;       dbgstr 'SeekTrack: FDC_TrackNotFound'
454
        mov     [FDC_Status], FDC_TrackNotFound
446
        mov     [FDC_Status], FDC_TrackNotFound
455
@@Exit:
447
@@Exit:
456
        call    save_timer_fdd_motor
448
        call    save_timer_fdd_motor
457
        popa
449
        popa
458
        ret
450
        ret
459
 
451
 
460
;*******************************************************
452
;*******************************************************
461
;*               READING A DATA SECTOR                 *
453
;*               READING A DATA SECTOR                 *
462
;* Parameters are passed through global variables:     *
454
;* Parameters are passed through global variables:     *
463
;* FDD_Track - track number (0-79);                    *
455
;* FDD_Track - track number (0-79);                    *
464
;* FDD_Head - head number (0-1);                       *
456
;* FDD_Head - head number (0-1);                       *
465
;* FDD_Sector - sector number (1-18).                  *
457
;* FDD_Sector - sector number (1-18).                  *
466
;* Result of operation is written to FDC_Status.       *
458
;* Result of operation is written to FDC_Status.       *
467
;* If the read operation is successful, the contents   *
459
;* If the read operation is successful, the contents   *
468
;*  of the sector will be written to FDD_DataBuffer.   *
460
;*  of the sector will be written to FDD_DataBuffer.   *
469
;*******************************************************
461
;*******************************************************
470
ReadSector:
462
ReadSector:
471
;       dbgstr 'ReadSector'
463
;       dbgstr 'ReadSector'
472
        pushad
464
        pushad
473
        call    save_timer_fdd_motor
465
        call    save_timer_fdd_motor
474
; Clear the interrupt flag
466
; Clear the interrupt flag
475
        mov     [FDD_IntFlag], 0
467
        mov     [FDD_IntFlag], 0
476
; Set transmit speed to 500 Kb / s
468
; Set transmit speed to 500 Kb / s
477
        mov     AX, 0
469
        mov     AX, 0
478
        mov     DX, 03F7h
470
        mov     DX, 03F7h
479
        out     DX, AL
471
        out     DX, AL
480
; Initialize the DMA channel
472
; Initialize the DMA channel
481
        mov     [dmamode], 0x46
473
        mov     [dmamode], 0x46
482
        call    Init_FDC_DMA
474
        call    Init_FDC_DMA
483
; Send "Data read" command
475
; Send "Data read" command
484
        mov     AL, 0E6h ; reading in multi-track mode
476
        mov     AL, 0E6h ; reading in multi-track mode
485
        call    FDCDataOutput
477
        call    FDCDataOutput
486
        mov     AL, [FDD_Head]
478
        mov     AL, [FDD_Head]
487
        shl     AL, 2
479
        shl     AL, 2
488
        or      AL, [flp_number]
480
        or      AL, [flp_number]
489
        dec     AL
481
        dec     AL
490
        call    FDCDataOutput
482
        call    FDCDataOutput
491
        mov     AL, [FDD_Track]
483
        mov     AL, [FDD_Track]
492
        call    FDCDataOutput
484
        call    FDCDataOutput
493
        mov     AL, [FDD_Head]
485
        mov     AL, [FDD_Head]
494
        call    FDCDataOutput
486
        call    FDCDataOutput
495
        mov     AL, [FDD_Sector]
487
        mov     AL, [FDD_Sector]
496
        call    FDCDataOutput
488
        call    FDCDataOutput
497
        mov     AL, 2   ; sector size code (512 byte)
489
        mov     AL, 2   ; sector size code (512 byte)
498
        call    FDCDataOutput
490
        call    FDCDataOutput
499
        mov     AL, 18 ;+1; 3Fh  ;number of sectors per track
491
        mov     AL, 18 ;+1; 3Fh  ;number of sectors per track
500
        call    FDCDataOutput
492
        call    FDCDataOutput
501
        mov     AL, 1Bh ; GPL value
493
        mov     AL, 1Bh ; GPL value
502
        call    FDCDataOutput
494
        call    FDCDataOutput
503
        mov     AL, 0FFh; DTL value
495
        mov     AL, 0FFh; DTL value
504
        call    FDCDataOutput
496
        call    FDCDataOutput
505
; Waiting for an interrupt at the end of the operation
497
; Waiting for an interrupt at the end of the operation
506
        call    WaitFDCInterrupt
498
        call    WaitFDCInterrupt
507
        cmp     [FDC_Status], FDC_Normal
499
        cmp     [FDC_Status], FDC_Normal
508
        jne     @@Exit_1
500
        jne     @@Exit_1
509
; Read the operation completion status
501
; Read the operation completion status
510
        call    GetStatusInfo
502
        call    GetStatusInfo
511
        test    [FDC_ST0], 11011000b
503
        test    [FDC_ST0], 11011000b
512
        jnz     @@Err_1
504
        jnz     @@Err_1
513
;        dbgstr 'ReadSector: FDC_Normal'
505
;        dbgstr 'ReadSector: FDC_Normal'
514
        mov     [FDC_Status], FDC_Normal
506
        mov     [FDC_Status], FDC_Normal
515
        jmp     @@Exit_1
507
        jmp     @@Exit_1
516
@@Err_1:
508
@@Err_1:
517
;       dbgstr 'ReadSector: FDC_SectorNotFound'
509
;       dbgstr 'ReadSector: FDC_SectorNotFound'
518
        mov     [FDC_Status], FDC_SectorNotFound
510
        mov     [FDC_Status], FDC_SectorNotFound
519
@@Exit_1:
511
@@Exit_1:
520
        call    save_timer_fdd_motor
512
        call    save_timer_fdd_motor
521
        popad
513
        popad
522
        ret
514
        ret
523
 
515
 
524
;*******************************************************
516
;*******************************************************
525
;*   READ SECTOR (WITH RETRY OF OPERATION ON FAILURE)  *
517
;*   READ SECTOR (WITH RETRY OF OPERATION ON FAILURE)  *
526
;* Parameters are passed through global variables:     *
518
;* Parameters are passed through global variables:     *
527
;* FDD_Track - track number (0-79);                    *
519
;* FDD_Track - track number (0-79);                    *
528
;* FDD_Head - head number (0-1);                       *
520
;* FDD_Head - head number (0-1);                       *
529
;* FDD_Sector - sector number (1-18).                  *
521
;* FDD_Sector - sector number (1-18).                  *
530
;* Result of operation is written to FDC_Status.       *
522
;* Result of operation is written to FDC_Status.       *
531
;* If the read operation is successful, the contents   *
523
;* If the read operation is successful, the contents   *
532
;*  of the sector will be written to FDD_DataBuffer.   *
524
;*  of the sector will be written to FDD_DataBuffer.   *
533
;*******************************************************
525
;*******************************************************
534
ReadSectWithRetr:
526
ReadSectWithRetr:
535
        pusha
527
        pusha
536
; Reset the recalibration repetition counter
528
; Reset the recalibration repetition counter
537
        mov     [RecalRepCounter], 0
529
        mov     [RecalRepCounter], 0
538
@@TryAgain:
530
@@TryAgain:
539
; Reset the read operation retry counter
531
; Reset the read operation retry counter
540
        mov     [ReadRepCounter], 0
532
        mov     [ReadRepCounter], 0
541
@@ReadSector_1:
533
@@ReadSector_1:
542
        call    ReadSector
534
        call    ReadSector
543
        cmp     [FDC_Status], 0
535
        cmp     [FDC_Status], 0
544
        je      @@Exit_2
536
        je      @@Exit_2
545
        cmp     [FDC_Status], 1
537
        cmp     [FDC_Status], 1
546
        je      @@Err_3
538
        je      @@Err_3
547
        ; Three times repeat reading
539
        ; Three times repeat reading
548
        inc     [ReadRepCounter]
540
        inc     [ReadRepCounter]
549
        cmp     [ReadRepCounter], 3
541
        cmp     [ReadRepCounter], 3
550
        jb      @@ReadSector_1
542
        jb      @@ReadSector_1
551
        ; Three times repeat recalibration
543
        ; Three times repeat recalibration
552
        call    RecalibrateFDD
544
        call    RecalibrateFDD
553
        call    SeekTrack
545
        call    SeekTrack
554
        inc     [RecalRepCounter]
546
        inc     [RecalRepCounter]
555
        cmp     [RecalRepCounter], 3
547
        cmp     [RecalRepCounter], 3
556
        jb      @@TryAgain
548
        jb      @@TryAgain
557
@@Exit_2:
549
@@Exit_2:
558
        popa
550
        popa
559
        ret
551
        ret
560
@@Err_3:
552
@@Err_3:
561
        popa
553
        popa
562
        ret
554
        ret
563
 
555
 
564
;*******************************************************
556
;*******************************************************
565
;*               WRITE DATA SECTOR                     *
557
;*               WRITE DATA SECTOR                     *
566
;* Parameters are passed through global variables:     *
558
;* Parameters are passed through global variables:     *
567
;* FDD_Track - track number (0-79);                    *
559
;* FDD_Track - track number (0-79);                    *
568
;* FDD_Head - head number (0-1);                       *
560
;* FDD_Head - head number (0-1);                       *
569
;* FDD_Sector - sector number (1-18).                  *
561
;* FDD_Sector - sector number (1-18).                  *
570
;* Result of operation is written to FDC_Status.       *
562
;* Result of operation is written to FDC_Status.       *
571
;* If the write operation is successful, the contents  *
563
;* If the write operation is successful, the contents  *
572
;* of FDD_DataBuffer will be written to the sector     *
564
;* of FDD_DataBuffer will be written to the sector     *
573
;*******************************************************
565
;*******************************************************
574
WriteSector:
566
WriteSector:
575
;       dbgstr 'WriteSector'
567
;       dbgstr 'WriteSector'
576
        pushad
568
        pushad
577
        call    save_timer_fdd_motor
569
        call    save_timer_fdd_motor
578
; Clear the interrupt flag
570
; Clear the interrupt flag
579
        mov     [FDD_IntFlag], 0
571
        mov     [FDD_IntFlag], 0
580
; Set transmit speed to 500 Kb / s
572
; Set transmit speed to 500 Kb / s
581
        mov     AX, 0
573
        mov     AX, 0
582
        mov     DX, 03F7h
574
        mov     DX, 03F7h
583
        out     DX, AL
575
        out     DX, AL
584
; Initialize the DMA channel
576
; Initialize the DMA channel
585
        mov     [dmamode], 0x4A
577
        mov     [dmamode], 0x4A
586
        call    Init_FDC_DMA
578
        call    Init_FDC_DMA
587
; Send "Write data" command
579
; Send "Write data" command
588
        mov     AL, 0xC5 ;0x45  ; write in multi-track mode
580
        mov     AL, 0xC5 ;0x45  ; write in multi-track mode
589
        call    FDCDataOutput
581
        call    FDCDataOutput
590
        mov     AL, [FDD_Head]
582
        mov     AL, [FDD_Head]
591
        shl     AL, 2
583
        shl     AL, 2
592
        or      AL, [flp_number]
584
        or      AL, [flp_number]
593
        dec     AL
585
        dec     AL
594
        call    FDCDataOutput
586
        call    FDCDataOutput
595
        mov     AL, [FDD_Track]
587
        mov     AL, [FDD_Track]
596
        call    FDCDataOutput
588
        call    FDCDataOutput
597
        mov     AL, [FDD_Head]
589
        mov     AL, [FDD_Head]
598
        call    FDCDataOutput
590
        call    FDCDataOutput
599
        mov     AL, [FDD_Sector]
591
        mov     AL, [FDD_Sector]
600
        call    FDCDataOutput
592
        call    FDCDataOutput
601
        mov     AL, 2   ; sector size code (512 bytes)
593
        mov     AL, 2   ; sector size code (512 bytes)
602
        call    FDCDataOutput
594
        call    FDCDataOutput
603
        mov     AL, 18; 3Fh  ; sectors per track
595
        mov     AL, 18; 3Fh  ; sectors per track
604
        call    FDCDataOutput
596
        call    FDCDataOutput
605
        mov     AL, 1Bh ; GPL value
597
        mov     AL, 1Bh ; GPL value
606
        call    FDCDataOutput
598
        call    FDCDataOutput
607
        mov     AL, 0FFh; DTL value
599
        mov     AL, 0FFh; DTL value
608
        call    FDCDataOutput
600
        call    FDCDataOutput
609
; Waiting for an interrupt at the end of the operation
601
; Waiting for an interrupt at the end of the operation
610
        call    WaitFDCInterrupt
602
        call    WaitFDCInterrupt
611
        cmp     [FDC_Status], FDC_Normal
603
        cmp     [FDC_Status], FDC_Normal
612
        jne     @@Exit_3
604
        jne     @@Exit_3
613
; Reading the completion status of the operation
605
; Reading the completion status of the operation
614
        call    GetStatusInfo
606
        call    GetStatusInfo
615
        test    [FDC_ST0], 11000000b ;11011000b
607
        test    [FDC_ST0], 11000000b ;11011000b
616
        jnz     @@Err_2
608
        jnz     @@Err_2
617
        mov     [FDC_Status], FDC_Normal
609
        mov     [FDC_Status], FDC_Normal
618
        jmp     @@Exit_3
610
        jmp     @@Exit_3
619
@@Err_2:
611
@@Err_2:
620
        mov     [FDC_Status], FDC_SectorNotFound
612
        mov     [FDC_Status], FDC_SectorNotFound
621
@@Exit_3:
613
@@Exit_3:
622
        call    save_timer_fdd_motor
614
        call    save_timer_fdd_motor
623
        popad
615
        popad
624
        ret
616
        ret
625
 
617
 
626
;*******************************************************
618
;*******************************************************
627
;*   WRITE SECTOR (WITH REPEAT ON FAILURE)             *
619
;*   WRITE SECTOR (WITH REPEAT ON FAILURE)             *
628
;* Parameters are passed through global variables:     *
620
;* Parameters are passed through global variables:     *
629
;* FDD_Track - track number (0-79);                    *
621
;* FDD_Track - track number (0-79);                    *
630
;* FDD_Head - head number (0-1);                       *
622
;* FDD_Head - head number (0-1);                       *
631
;* FDD_Sector - sector number (1-18).                  *
623
;* FDD_Sector - sector number (1-18).                  *
632
;* Result of operation is written to FDC_Status.       *
624
;* Result of operation is written to FDC_Status.       *
633
;* If the write operation is successful, the contents  *
625
;* If the write operation is successful, the contents  *
634
;* of FDD_DataBuffer will be written to the sector     *
626
;* of FDD_DataBuffer will be written to the sector     *
635
;*******************************************************
627
;*******************************************************
636
WriteSectWithRetr:
628
WriteSectWithRetr:
637
        pusha
629
        pusha
638
; Reset the recalibration repetition counter
630
; Reset the recalibration repetition counter
639
        mov     [RecalRepCounter], 0
631
        mov     [RecalRepCounter], 0
640
@@TryAgain_1:
632
@@TryAgain_1:
641
; Reset the read operation retry counter
633
; Reset the read operation retry counter
642
        mov     [ReadRepCounter], 0
634
        mov     [ReadRepCounter], 0
643
@@WriteSector_1:
635
@@WriteSector_1:
644
        call    WriteSector
636
        call    WriteSector
645
        cmp     [FDC_Status], 0
637
        cmp     [FDC_Status], 0
646
        je      @@Exit_4
638
        je      @@Exit_4
647
        cmp     [FDC_Status], 1
639
        cmp     [FDC_Status], 1
648
        je      @@Err_4
640
        je      @@Err_4
649
        ; Three times repeat writing
641
        ; Three times repeat writing
650
        inc     [ReadRepCounter]
642
        inc     [ReadRepCounter]
651
        cmp     [ReadRepCounter], 3
643
        cmp     [ReadRepCounter], 3
652
        jb      @@WriteSector_1
644
        jb      @@WriteSector_1
653
        ; Three times repeat recalibration
645
        ; Three times repeat recalibration
654
        call    RecalibrateFDD
646
        call    RecalibrateFDD
655
        call    SeekTrack
647
        call    SeekTrack
656
        inc     [RecalRepCounter]
648
        inc     [RecalRepCounter]
657
        cmp     [RecalRepCounter], 3
649
        cmp     [RecalRepCounter], 3
658
        jb      @@TryAgain_1
650
        jb      @@TryAgain_1
659
@@Exit_4:
651
@@Exit_4:
660
        popa
652
        popa
661
        ret
653
        ret
662
@@Err_4:
654
@@Err_4:
663
        popa
655
        popa
664
        ret
656
        ret
665
 
657
 
666
;*********************************************
658
;*********************************************
667
;* GET INFORMATION ABOUT THE RESULT OF THE OPERATION
659
;* GET INFORMATION ABOUT THE RESULT OF THE OPERATION
668
;*********************************************
660
;*********************************************
669
GetStatusInfo:
661
GetStatusInfo:
670
        push    AX
662
        push    AX
671
        call    FDCDataInput
663
        call    FDCDataInput
672
        mov     [FDC_ST0], AL
664
        mov     [FDC_ST0], AL
673
        call    FDCDataInput
665
        call    FDCDataInput
674
        mov     [FDC_ST1], AL
666
        mov     [FDC_ST1], AL
675
        call    FDCDataInput
667
        call    FDCDataInput
676
        mov     [FDC_ST2], AL
668
        mov     [FDC_ST2], AL
677
        call    FDCDataInput
669
        call    FDCDataInput
678
        mov     [FDC_C], AL
670
        mov     [FDC_C], AL
679
        call    FDCDataInput
671
        call    FDCDataInput
680
        mov     [FDC_H], AL
672
        mov     [FDC_H], AL
681
        call    FDCDataInput
673
        call    FDCDataInput
682
        mov     [FDC_R], AL
674
        mov     [FDC_R], AL
683
        call    FDCDataInput
675
        call    FDCDataInput
684
        mov     [FDC_N], AL
676
        mov     [FDC_N], AL
685
        pop     AX
677
        pop     AX
686
        ret
678
        ret
687
 
679
 
688
; Interface for disk subsystem.
680
; Interface for disk subsystem.
689
; Assume fixed capacity for 1.44M.
681
; Assume fixed capacity for 1.44M.
690
FLOPPY_CAPACITY = 2880  ; in sectors
682
FLOPPY_CAPACITY = 2880  ; in sectors
691
 
683
 
692
iglobal
684
iglobal
693
align 4
685
align 4
694
floppy_functions:
686
floppy_functions:
695
        dd      .size
687
        dd      .size
696
        dd      0       ; no close() function
688
        dd      0       ; no close() function
697
        dd      0       ; no closemedia() function
689
        dd      0       ; no closemedia() function
698
        dd      floppy_querymedia
690
        dd      floppy_querymedia
699
        dd      floppy_read
691
        dd      floppy_read
700
        dd      floppy_write
692
        dd      floppy_write
701
        dd      0       ; no flush() function
693
        dd      0       ; no flush() function
702
        dd      0       ; no adjust_cache_size() function
694
        dd      0       ; no adjust_cache_size() function
703
.size = $ - floppy_functions
695
.size = $ - floppy_functions
704
endg
696
endg
705
 
697
 
706
uglobal
698
uglobal
707
floppy_media_flags      rb      2
699
floppy_media_flags      rb      2
708
n_sector    dd 0  ; temporary save for sector value
700
n_sector    dd 0  ; temporary save for sector value
709
flp_number  db 0  ; 1- Floppy A, 2-Floppy B
701
flp_number  db 0  ; 1- Floppy A, 2-Floppy B
710
old_track   db 0  ; old value track
702
old_track   db 0  ; old value track
711
flp_label   rb 15*2 ; Label and ID of inserted floppy disk
703
flp_label   rb 15*2 ; Label and ID of inserted floppy disk
712
align 4
704
align 4
713
; Hardware does not allow to work with two floppies in parallel,
705
; Hardware does not allow to work with two floppies in parallel,
714
; so there is one mutex guarding access to any floppy.
706
; so there is one mutex guarding access to any floppy.
715
floppy_mutex    MUTEX
707
floppy_mutex    MUTEX
716
endg
708
endg
717
; Meaning of bits in floppy_media_flags
709
; Meaning of bits in floppy_media_flags
718
FLOPPY_MEDIA_PRESENT = 1        ; media was present when last asked
710
FLOPPY_MEDIA_PRESENT = 1        ; media was present when last asked
719
FLOPPY_MEDIA_NEED_RESCAN = 2    ; media was possibly changed, need to rescan
711
FLOPPY_MEDIA_NEED_RESCAN = 2    ; media was possibly changed, need to rescan
720
FLOPPY_MEDIA_LABEL_CHANGED = 4  ; temporary state
712
FLOPPY_MEDIA_LABEL_CHANGED = 4  ; temporary state
721
 
713
 
722
iglobal
714
iglobal
723
floppy1_name    db      'fd',0
715
floppy1_name    db      'fd',0
724
floppy2_name    db      'fd2',0
716
floppy2_name    db      'fd2',0
725
endg
717
endg
726
 
718
 
727
; This function is called in boot process.
719
; This function is called in boot process.
728
; It creates filesystems /fd and/or /fd2, if the system has one/two floppy drives.
720
; It creates filesystems /fd and/or /fd2, if the system has one/two floppy drives.
729
proc floppy_init
721
proc floppy_init
730
        mov     ecx, floppy_mutex
722
        mov     ecx, floppy_mutex
731
        call    mutex_init
723
        call    mutex_init
732
; First floppy is present if [DRIVE_DATA] and 0xF0 is nonzero.
724
; First floppy is present if [DRIVE_DATA] and 0xF0 is nonzero.
733
        test    byte [DRIVE_DATA], 0xF0
725
        test    byte [DRIVE_DATA], 0xF0
734
        jz      .no1
726
        jz      .no1
735
        stdcall disk_add, floppy_functions, floppy1_name, 1, DISK_NO_INSERT_NOTIFICATION
727
        stdcall disk_add, floppy_functions, floppy1_name, 1, DISK_NO_INSERT_NOTIFICATION
736
.no1:
728
.no1:
737
; Second floppy is present if [DRIVE_DATA] and 0x0F is nonzero.
729
; Second floppy is present if [DRIVE_DATA] and 0x0F is nonzero.
738
        test    byte [DRIVE_DATA], 0x0F
730
        test    byte [DRIVE_DATA], 0x0F
739
        jz      .no2
731
        jz      .no2
740
        stdcall disk_add, floppy_functions, floppy2_name, 2, DISK_NO_INSERT_NOTIFICATION
732
        stdcall disk_add, floppy_functions, floppy2_name, 2, DISK_NO_INSERT_NOTIFICATION
741
.no2:
733
.no2:
742
        ret
734
        ret
743
endp
735
endp
744
 
736
 
745
; Returns information about disk media.
737
; Returns information about disk media.
746
; Floppy drives do not support insert notifications,
738
; Floppy drives do not support insert notifications,
747
; DISK_NO_INSERT_NOTIFICATION is set,
739
; DISK_NO_INSERT_NOTIFICATION is set,
748
; the disk subsystem calls this function before each filesystem operation.
740
; the disk subsystem calls this function before each filesystem operation.
749
; If the media has changed, return error for the first call as signal
741
; If the media has changed, return error for the first call as signal
750
; to finalize work with old media and the true geometry for the second call.
742
; to finalize work with old media and the true geometry for the second call.
751
; Assume that media is (possibly) changed anytime when motor is off.
743
; Assume that media is (possibly) changed anytime when motor is off.
752
proc floppy_querymedia
744
proc floppy_querymedia
753
  virtual at esp+4
745
  virtual at esp+4
754
    .userdata dd ?
746
    .userdata dd ?
755
    .info dd ?
747
    .info dd ?
756
  end virtual
748
  end virtual
757
; 1. Acquire the global lock.
749
; 1. Acquire the global lock.
758
        mov     ecx, floppy_mutex
750
        mov     ecx, floppy_mutex
759
        call    mutex_lock
751
        call    mutex_lock
760
        mov     edx, [.userdata]        ; 1 for /fd, 2 for /fd2
752
        mov     edx, [.userdata]        ; 1 for /fd, 2 for /fd2
761
; 2. If the media was reported and has been changed, forget it and report an error.
753
; 2. If the media was reported and has been changed, forget it and report an error.
762
        mov     al, [floppy_media_flags+edx-1]
754
        mov     al, [floppy_media_flags+edx-1]
763
        and     al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
755
        and     al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
764
        cmp     al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
756
        cmp     al, FLOPPY_MEDIA_PRESENT + FLOPPY_MEDIA_NEED_RESCAN
765
        jnz     .not_reported
757
        jnz     .not_reported
766
.no_media:
758
.no_media:
767
        mov     [floppy_media_flags+edx-1], 0
759
        mov     [floppy_media_flags+edx-1], 0
768
.return_no_media:
760
.return_no_media:
769
        mov     ecx, floppy_mutex
761
        mov     ecx, floppy_mutex
770
        call    mutex_unlock
762
        call    mutex_unlock
771
        mov     eax, DISK_STATUS_NO_MEDIA
763
        mov     eax, DISK_STATUS_NO_MEDIA
772
        retn    8
764
        retn    8
773
.not_reported:
765
.not_reported:
774
; 3. If we are in the temporary state LABEL_CHANGED, this is the second call
766
; 3. If we are in the temporary state LABEL_CHANGED, this is the second call
775
; after intermediate DISK_STATUS_NO_MEDIA due to media change;
767
; after intermediate DISK_STATUS_NO_MEDIA due to media change;
776
; clear the flag and return the current geometry without rereading the bootsector.
768
; clear the flag and return the current geometry without rereading the bootsector.
777
        cmp     [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
769
        cmp     [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
778
        jz      .report_geometry
770
        jz      .report_geometry
779
; 4. Try to read the bootsector.
771
; 4. Try to read the bootsector.
780
        mov     [flp_number], dl
772
        mov     [flp_number], dl
781
        mov     [FDC_Status], 0
773
        mov     [FDC_Status], 0
782
        call    floppy_read_bootsector
774
        call    floppy_read_bootsector
783
; 5. If reading bootsector failed, assume that media is not present.
775
; 5. If reading bootsector failed, assume that media is not present.
784
        mov     edx, [.userdata]
776
        mov     edx, [.userdata]
785
        cmp     [FDC_Status], 0
777
        cmp     [FDC_Status], 0
786
        jnz     .no_media
778
        jnz     .no_media
787
; 6. Check whether the previous status is "present". If not, go to 10.
779
; 6. Check whether the previous status is "present". If not, go to 10.
788
        push    esi edi
780
        push    esi edi
789
        imul    edi, edx, 15
781
        imul    edi, edx, 15
790
        add     edi, flp_label-15
782
        add     edi, flp_label-15
791
        mov     esi, FDD_BUFF+39
783
        mov     esi, FDD_BUFF+39
792
        mov     ecx, 15
784
        mov     ecx, 15
793
        test    [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
785
        test    [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
794
        jz      .set_label
786
        jz      .set_label
795
; 7. Compare the old label with the current one.
787
; 7. Compare the old label with the current one.
796
        rep cmpsb
788
        rep cmpsb
797
; 8. If the label has not changed, go to 11.
789
; 8. If the label has not changed, go to 11.
798
        jz      .ok
790
        jz      .ok
799
; 9. If the label has changed, store it, enter temporary state LABEL_CHANGED
791
; 9. If the label has changed, store it, enter temporary state LABEL_CHANGED
800
; and report DISK_STATUS_NO_MEDIA.
792
; and report DISK_STATUS_NO_MEDIA.
801
;       dbgstr 'floppy label changed'
793
;       dbgstr 'floppy label changed'
802
        add     esi, ecx
794
        add     esi, ecx
803
        add     edi, ecx
795
        add     edi, ecx
804
        mov     ecx, 15
796
        mov     ecx, 15
805
        sub     esi, ecx
797
        sub     esi, ecx
806
        sub     edi, ecx
798
        sub     edi, ecx
807
        rep movsb
799
        rep movsb
808
        mov     [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
800
        mov     [floppy_media_flags+edx-1], FLOPPY_MEDIA_LABEL_CHANGED
809
        pop     edi esi
801
        pop     edi esi
810
        jmp     .return_no_media
802
        jmp     .return_no_media
811
.set_label:
803
.set_label:
812
; 10. The previous state was "not present". Copy the label.
804
; 10. The previous state was "not present". Copy the label.
813
        rep movsb
805
        rep movsb
814
.ok:
806
.ok:
815
        pop     edi esi
807
        pop     edi esi
816
.report_geometry:
808
.report_geometry:
817
; 11. Fill DISKMEDIAINFO structure.
809
; 11. Fill DISKMEDIAINFO structure.
818
        mov     ecx, [.info]
810
        mov     ecx, [.info]
819
        and     [ecx+DISKMEDIAINFO.Flags], 0
811
        and     [ecx+DISKMEDIAINFO.Flags], 0
820
        mov     [ecx+DISKMEDIAINFO.SectorSize], 512
812
        mov     [ecx+DISKMEDIAINFO.SectorSize], 512
821
        mov     dword [ecx+DISKMEDIAINFO.Capacity], FLOPPY_CAPACITY
813
        mov     dword [ecx+DISKMEDIAINFO.Capacity], FLOPPY_CAPACITY
822
        and     dword [ecx+DISKMEDIAINFO.Capacity+4], 0
814
        and     dword [ecx+DISKMEDIAINFO.Capacity+4], 0
823
; 12. Update state: media is present, data are actual.
815
; 12. Update state: media is present, data are actual.
824
        mov     [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
816
        mov     [floppy_media_flags+edx-1], FLOPPY_MEDIA_PRESENT
825
; 13. Release the global lock and return successful status.
817
; 13. Release the global lock and return successful status.
826
        mov     ecx, floppy_mutex
818
        mov     ecx, floppy_mutex
827
        call    mutex_unlock
819
        call    mutex_unlock
828
        xor     eax, eax
820
        xor     eax, eax
829
        retn    8
821
        retn    8
830
endp
822
endp
831
 
823
 
832
proc floppy_read_bootsector
824
proc floppy_read_bootsector
833
        pushad
825
        pushad
834
        mov     [FDD_Track], 0  ; Cylinder
826
        mov     [FDD_Track], 0  ; Cylinder
835
        mov     [FDD_Head], 0   ; Head
827
        mov     [FDD_Head], 0   ; Head
836
        mov     [FDD_Sector], 1 ; Sector
828
        mov     [FDD_Sector], 1 ; Sector
837
        call    FDDMotorON
829
        call    FDDMotorON
838
        call    RecalibrateFDD
830
        call    RecalibrateFDD
839
        cmp     [FDC_Status], 0
831
        cmp     [FDC_Status], 0
840
        jne     .nothing
832
        jne     .nothing
841
        call    SeekTrack
833
        call    SeekTrack
842
        cmp     [FDC_Status], 0
834
        cmp     [FDC_Status], 0
843
        jne     .nothing
835
        jne     .nothing
844
        call    ReadSectWithRetr
836
        call    ReadSectWithRetr
845
.nothing:
837
.nothing:
846
        popad
838
        popad
847
        ret
839
        ret
848
endp
840
endp
849
 
841
 
850
read_chs_sector:
842
read_chs_sector:
851
        call    calculate_chs
843
        call    calculate_chs
852
        call    ReadSectWithRetr
844
        call    ReadSectWithRetr
853
        ret
845
        ret
854
 
846
 
855
save_chs_sector:
847
save_chs_sector:
856
        call    calculate_chs
848
        call    calculate_chs
857
        call    WriteSectWithRetr
849
        call    WriteSectWithRetr
858
        ret
850
        ret
859
 
851
 
860
calculate_chs:
852
calculate_chs:
861
        mov     bl, [FDD_Track]
853
        mov     bl, [FDD_Track]
862
        mov     [old_track], bl
854
        mov     [old_track], bl
863
        mov     ebx, 18
855
        mov     ebx, 18
864
        xor     edx, edx
856
        xor     edx, edx
865
        div     ebx
857
        div     ebx
866
        inc     edx
858
        inc     edx
867
        mov     [FDD_Sector], dl
859
        mov     [FDD_Sector], dl
868
        mov     edx, eax
860
        mov     edx, eax
869
        shr     eax, 1
861
        shr     eax, 1
870
        and     edx, 1
862
        and     edx, 1
871
        mov     [FDD_Track], al
863
        mov     [FDD_Track], al
872
        mov     [FDD_Head], dl
864
        mov     [FDD_Head], dl
873
        mov     dl, [old_track]
865
        mov     dl, [old_track]
874
        cmp     dl, [FDD_Track]
866
        cmp     dl, [FDD_Track]
875
        je      no_seek_track_1
867
        je      no_seek_track_1
876
        call    SeekTrack
868
        call    SeekTrack
877
no_seek_track_1:
869
no_seek_track_1:
878
        ret
870
        ret
879
 
871
 
880
; Writes one or more sectors to the device.
872
; Writes one or more sectors to the device.
881
proc floppy_write
873
proc floppy_write
882
        mov     dl, 1
874
        mov     dl, 1
883
        jmp     floppy_read_write
875
        jmp     floppy_read_write
884
endp
876
endp
885
 
877
 
886
; Reads one or more sectors from the device.
878
; Reads one or more sectors from the device.
887
proc floppy_read
879
proc floppy_read
888
        mov     dl, 0
880
        mov     dl, 0
889
endp
881
endp
890
 
882
 
891
; Common part of floppy_read and floppy_write.
883
; Common part of floppy_read and floppy_write.
892
proc floppy_read_write userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword
884
proc floppy_read_write userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword
893
virtual at ebp-8
885
virtual at ebp-8
894
.sectors_todo   dd      ?
886
.sectors_todo   dd      ?
895
.operation      db      ?
887
.operation      db      ?
896
end virtual
888
end virtual
897
        push    edx             ; save operation code to [.operation]
889
        push    edx             ; save operation code to [.operation]
898
; 1. Get number of sectors to read/write
890
; 1. Get number of sectors to read/write
899
; and zero number of sectors that were actually read/written.
891
; and zero number of sectors that were actually read/written.
900
        mov     eax, [numsectors_ptr]
892
        mov     eax, [numsectors_ptr]
901
        push    dword [eax]     ; initialize [.sectors_todo]
893
        push    dword [eax]     ; initialize [.sectors_todo]
902
        and     dword [eax], 0
894
        and     dword [eax], 0
903
        push    ebx esi edi     ; save used registers to be stdcall
895
        push    ebx esi edi     ; save used registers to be stdcall
904
; 2. Acquire the global lock.
896
; 2. Acquire the global lock.
905
        mov     ecx, floppy_mutex
897
        mov     ecx, floppy_mutex
906
        call    mutex_lock
898
        call    mutex_lock
907
; 3. Set floppy number for this operation.
899
; 3. Set floppy number for this operation.
908
        mov     edx, [userdata]
900
        mov     edx, [userdata]
909
        mov     [flp_number], dl
901
        mov     [flp_number], dl
910
; 4. Read/write sector-by-sector.
902
; 4. Read/write sector-by-sector.
911
.operation_loop:
903
.operation_loop:
912
; 4a. Check that the sector is inside the media.
904
; 4a. Check that the sector is inside the media.
913
        cmp     dword [start_sector+4], 0
905
        cmp     dword [start_sector+4], 0
914
        jnz     .end_of_media
906
        jnz     .end_of_media
915
        mov     eax, dword [start_sector]
907
        mov     eax, dword [start_sector]
916
        cmp     eax, FLOPPY_CAPACITY
908
        cmp     eax, FLOPPY_CAPACITY
917
        jae     .end_of_media
909
        jae     .end_of_media
918
; 4b. For read operation, call read_chs_sector and then move data from FDD_BUFF to [buffer].
910
; 4b. For read operation, call read_chs_sector and then move data from FDD_BUFF to [buffer].
919
; For write operation, move data from [buffer] to FDD_BUFF and then call save_chs_sector.
911
; For write operation, move data from [buffer] to FDD_BUFF and then call save_chs_sector.
920
        cmp     [.operation], 0
912
        cmp     [.operation], 0
921
        jz      .read
913
        jz      .read
922
        mov     esi, [buffer]
914
        mov     esi, [buffer]
923
        mov     edi, FDD_BUFF
915
        mov     edi, FDD_BUFF
924
        mov     ecx, 512/4
916
        mov     ecx, 512/4
925
        rep movsd
917
        rep movsd
926
        mov     [buffer], esi
918
        mov     [buffer], esi
927
        call    save_chs_sector
919
        call    save_chs_sector
928
        jmp     @f
920
        jmp     @f
929
.read:
921
.read:
930
        call    read_chs_sector
922
        call    read_chs_sector
931
        mov     esi, FDD_BUFF
923
        mov     esi, FDD_BUFF
932
        mov     edi, [buffer]
924
        mov     edi, [buffer]
933
        mov     ecx, 512/4
925
        mov     ecx, 512/4
934
        rep movsd
926
        rep movsd
935
        mov     [buffer], edi
927
        mov     [buffer], edi
936
@@:
928
@@:
937
; 4c. If there was an error, propagate it to the caller.
929
; 4c. If there was an error, propagate it to the caller.
938
        cmp     [FDC_Status], 0
930
        cmp     [FDC_Status], 0
939
        jnz     .fail
931
        jnz     .fail
940
; 4d. Otherwise, increment number of sectors processed and continue the loop.
932
; 4d. Otherwise, increment number of sectors processed and continue the loop.
941
        mov     eax, [numsectors_ptr]
933
        mov     eax, [numsectors_ptr]
942
        inc     dword [eax]
934
        inc     dword [eax]
943
        inc     dword [start_sector]
935
        inc     dword [start_sector]
944
        dec     [.sectors_todo]
936
        dec     [.sectors_todo]
945
        jnz     .operation_loop
937
        jnz     .operation_loop
946
; 5. Release the global lock and return with the correct status.
938
; 5. Release the global lock and return with the correct status.
947
        push    0
939
        push    0
948
.return:
940
.return:
949
        mov     ecx, floppy_mutex
941
        mov     ecx, floppy_mutex
950
        call    mutex_unlock
942
        call    mutex_unlock
951
        pop     eax
943
        pop     eax
952
        pop     edi esi ebx     ; restore used registers to be stdcall
944
        pop     edi esi ebx     ; restore used registers to be stdcall
953
        ret     ; this translates to leave/retn N and purges local variables
945
        ret     ; this translates to leave/retn N and purges local variables
954
.fail:
946
.fail:
955
        push    -1
947
        push    -1
956
        jmp     .return
948
        jmp     .return
957
.end_of_media:
949
.end_of_media:
958
        push    DISK_STATUS_END_OF_MEDIA
950
        push    DISK_STATUS_END_OF_MEDIA
959
        jmp     .return
951
        jmp     .return
960
endp
952
endp