]> wirehaze git hosting - BOS.git/blob - kernel/krl_incs/fdc.inc

wirehaze git hosting

initial commit
[BOS.git] / kernel / krl_incs / fdc.inc
1 ;----------------------------------------------------------;
2 ; BOS kernel Christoffer Bubach, 2004-2005. ;
3 ;----------------------------------------------------------;
4 ; ;
5 ; floppy disk driver originally by Craig Bamford, Dex4u. ;
6 ; adjustments and for BOS by bubach. ;
7 ; ;
8 ;----------------------------------------------------------;
9
10 ; NOTE: I'm almost finished with a much improved version of
11 ; this code, that supports 2 drives of multiple types.
12 ; I'll wait with that until next version, so you won't
13 ; have to see a half finished mess here.
14
15 ;---------------------------;
16 ; variables and contants ;
17 ;---------------------------;
18 fdd_int_done dw 0 ; is the IRQ done?
19 fdd_motor_on db 0 ; fdd motor on=1, off=0
20 fdd_head db 0
21 fdd_driveno db 0
22 fdd_track db 0
23 fdd_sector db 0
24
25 fdd_errorcode db 0 ; this the error code 00 = no error
26 fdd_tries db 0 ; no. of times to try, before error.
27
28 ResultST0 db 0
29 ResultST1 db 0 ; or pcn
30 ResultST2 db 0
31 ResultST3 db 0
32 ResultC db 0
33 ResultH db 0
34 ResultR db 0
35 ResultN db 0
36 ResultExtra db 0
37
38
39
40 ;------------------------------------------------------;
41 ; initializes the floppy disk driver ;
42 ; ;
43 ;------------------------------------------------------;
44 fdc_init:
45 push ecx
46 push edi
47
48 mov cl, 0x26 ; hook interrupt 0x26 (IRQ6)
49 mov edi, floppy_irq
50 call set_int
51
52 mov cl, 6 ; enable IRQ6
53 call enable_irq
54
55 call fdd_reset ; reset FDC
56 call fdd_recalibrate
57
58 pop edi
59 pop ecx
60 ret
61
62
63
64 ;------------------------------------------------------;
65 ; floppy IRQ ;
66 ; ;
67 ;------------------------------------------------------;
68 floppy_irq:
69 pusha
70 push gs
71 push fs
72 push ds
73 push es
74 push esi
75
76 or [fdd_int_done], 1
77 mov al, 0x20
78 out 0x20, al
79
80 pop esi
81 pop es
82 pop ds
83 pop fs
84 pop gs
85 popa
86 iret
87
88
89
90 ;------------------------------------------------------;
91 ; wait for a floppy int ;
92 ; out: cf = 1 if timeout ;
93 ;------------------------------------------------------;
94 wait_int:
95 push eax
96 push ecx
97
98 mov ecx, 150 ; 150 = 1.5 seconds.
99 call active_delay ; timer.inc
100 .l1:
101 cmp dword [ecx], 0 ; timeup?
102 je .error
103 mov ax, [fdd_int_done] ; if not we check for int.
104 or ax, ax
105 jz .l1
106 pop ecx
107 pop eax
108 clc
109 ret
110 .error:
111 pop ecx
112 pop eax
113 stc
114 ret
115
116
117
118 ;------------------------------------------------------;
119 ; fdd motor off ;
120 ; out: nothing ;
121 ;------------------------------------------------------;
122 fdd_off:
123 push eax
124 push edx
125
126 mov dx, 0x3F2
127 mov al, 0 ; all motors off..
128 out dx, al
129 mov [fdd_motor_on], 0
130
131 pop edx
132 pop eax
133 ret
134
135
136
137
138 ;------------------------------------------------------;
139 ; fdd motor on ;
140 ; out: nothing ;
141 ;------------------------------------------------------;
142 fdd_on:
143 push eax
144 push edx
145
146 mov dx, 0x3F2 ; motor 0 on..
147 mov al, 0x1C
148 out dx, al
149
150 mov ecx, 20 ; 1/5 of a sec. to speed up
151 call delay ; in timer.inc
152 mov [fdd_motor_on], 1
153
154 pop edx
155 pop eax
156 ret
157
158
159
160 ;------------------------------------------------------;
161 ; send a data byte to the FDC ;
162 ; ;
163 ; in: al = data byte ;
164 ;------------------------------------------------------;
165 fdc_sendbyte:
166 push edx
167 push ecx
168 push eax
169
170 mov ecx, 150 ; 150 = 1.5 seconds.
171 call active_delay ; timer.inc
172 .l1:
173 cmp dword [ecx], 0 ; timeup?
174 je .error
175 mov dx, 0x3f4 ; check status reg
176 in al, dx
177 and al, 11000000b
178 cmp al, 10000000b ; are we ok to write
179 jnz .l1
180
181 pop eax
182 pop ecx
183 mov dx, 0x3F5 ; send byte
184 out dx, al
185 pop edx
186 clc
187 ret
188 .error:
189 pop eax
190 pop ecx
191 pop edx
192 stc
193 ret
194
195
196 ;------------------------------------------------------;
197 ; read a data byte from the FDC ;
198 ; ;
199 ; out: al = data byte ;
200 ;------------------------------------------------------;
201 fdc_getbyte:
202 push edx
203 push ecx
204 push eax
205
206 mov ecx, 150 ; 150 = 1.5 seconds.
207 call active_delay ; timer.inc
208 .l1:
209 cmp dword [ecx], 0 ; timeup?
210 je .error
211 mov dx, 0x3f4 ; check status reg
212 in al, dx
213 and al, 11000000b
214 cmp al, 11000000b ; are we ok to read
215 jnz .l1
216
217 pop eax
218 pop ecx
219 mov dx, 0x3F5 ; get the byte
220 in al, dx
221 pop edx
222 clc
223 ret
224 .error:
225 pop eax
226 pop ecx
227 pop edx
228 stc
229 ret
230
231
232
233
234 ;------------------------------------------------------;
235 ; reset controller ;
236 ; ;
237 ;------------------------------------------------------;
238 fdd_reset:
239 push eax
240 push ecx
241 push edx
242
243 mov dx, 0x3F2
244 mov al, 00001000b ; no motors enabled, DMA Enabled, held FDC at reset
245 out dx, al ; drive A selected.
246
247 mov ecx, 5
248 call delay ; in timer.inc
249
250 mov dx, 0x3F7
251 mov al, 00000000b ; 500Kb/sec mode
252 out dx, al
253
254 mov dx, 0x3F2
255 or al, 00001100b ; FDC completed reset, al =0x0c.
256 out dx, al
257
258 mov [fdd_int_done], 0 ; we need to wait
259 call wait_int ; for floppy int.
260 jc .error ; jump to error exit, if timeout.
261
262 mov cx, 0x04 ; after a reset, the interrupts must be
263 .status: ; cleared by (four) dummy-reads.
264 mov al, 0x08 ; sense interrupt status command
265 call fdc_sendbyte
266 call fdc_getbyte
267 call fdc_getbyte
268 loop .status
269
270 mov al, 0x03 ; specify command (includes next two bytes sent)
271 call fdc_sendbyte
272 mov al, 0xDF ; SRT = 3ms, HUT = 240ms
273 call fdc_sendbyte
274 mov al, 0x02 ; HLT = 16ms, ND = 0
275 call fdc_sendbyte
276 .ok:
277 pop edx
278 pop ecx
279 pop eax
280 clc
281 ret
282 .error:
283 pop edx
284 pop ecx
285 pop eax
286 stc
287 ret
288
289
290
291
292 ;------------------------------------------------------;
293 ; fdd seek ;
294 ; ;
295 ;------------------------------------------------------;
296 fdd_seek:
297 push eax
298
299 mov al, [ResultC] ; put what track/cylinder we are at in al
300 cmp [fdd_track], al ; is it the same as we want
301 je .ok ; yes, then leave.
302
303 mov al, 0x0F ; seek command
304 call fdc_sendbyte
305 mov al, [fdd_driveno] ; drive # (00 = A)
306 call fdc_sendbyte
307 mov al, [fdd_track] ; cylinder #
308 call fdc_sendbyte
309
310 mov [fdd_int_done], 0
311 call wait_int
312 jc .error
313
314 mov al, 0x08 ; sense interrupt status command
315 call fdc_sendbyte
316 call fdc_getbyte
317 mov ah, al ; save ST0 in ah
318 call fdc_getbyte ; should read PCN
319
320 test ah, 00100000b ; test sr0 is 0x20
321 jz .error ; if not we have a error :-(.
322 test ah,10000000b ; test sr0 is 0x80
323 jnz .error ; if not we have a error :-(.
324 .ok: ; succsess.. :-)
325 pop eax
326 clc
327 ret
328 .error:
329 pop eax
330 stc
331 ret
332
333
334 ;------------------------------------------------------;
335 ; fdd recalibrate ;
336 ; ;
337 ;------------------------------------------------------;
338 fdd_recalibrate:
339 push eax
340
341 test [fdd_motor_on], 1
342 jnz .l1
343 call fdd_on
344 .l1:
345 mov al, 0x07 ; recalibrate command
346 call fdc_sendbyte
347 mov al, 0x00 ; selects drive a:
348 call fdc_sendbyte
349
350 mov [fdd_int_done], 0
351 call wait_int
352 jc .error
353
354 mov al, 0x08 ; sense interrupt status command
355 call fdc_sendbyte
356 call fdc_getbyte ; read STO
357 mov ah, al ; save ST0 in ah
358 call fdc_getbyte
359
360 test ah, 00100000b ; test sr0 is 0x20
361 jz .error
362 test ah, 00010000b ; test sr0 is 0x80
363 jnz .error
364 .ok:
365 mov [ResultC], 0
366 pop eax
367 clc
368 ret
369 .error:
370 pop eax
371 stc
372 ret
373
374
375
376 ;------------------------------------------------------;
377 ; fdd read/write ;
378 ; input: bl = 0 read, 1 write ;
379 ; ch = track/cylinder ;
380 ; cl = sector ;
381 ; dh = head ;
382 ; dl = drive (only A: drive used, 00 ) ;
383 ; output: ah = status ;
384 ; al = sector number read ;
385 ; cf = 0 if ok, 1 if error ;
386 ;------------------------------------------------------;
387 fdd_read_write:
388 pushad
389 and dh, 00000001b ; is it set to fdd_head 0 or 1?
390 mov [fdd_head], dh ; store it.
391 shl dh, 2 ; make the first 2 bits = 00 for A:.
392 mov [fdd_driveno], dh ; store it.
393
394 mov [fdd_errorcode], 0x04 ; put error code in ah, just incase
395 cmp ch, 0x51 ; cmp if track number, is above 80 decimal (51 hex)?
396 jae .error ; if above jump error.
397 mov [fdd_track], ch ; if not above,store it.
398
399 cmp cl, 0x13 ; cmp if fdd_sector number, is above 18 decimal (12 hex) ?.
400 jae .error ; if above jump error.
401 mov [fdd_sector], cl ; if not above,store it.
402
403 test [fdd_motor_on], 1
404 jnz .l1
405 call fdd_on
406 .l1:
407 mov dx, 0x3F7
408 mov al, 00000000b ; 500Kb/sec mode
409 out dx, al
410 mov [fdd_errorcode], 0x80 ; put basic error code, just in case.
411
412 xor ecx, ecx
413 mov cx, 3 ; we want to try seek 3 times
414 .l2:
415 call fdd_seek ; we need to move to the right track.
416 jnc .l3 ; we should be on the right track.
417 loop .l2
418 jmp .error ; timeout.
419 .l3:
420 mov dx, 0x3f4 ; check status reg (to see if DMA bit set)
421 in al, dx
422 test al, 00100000b ; test sr0 is 0x80
423 jnz .error
424
425 cmp bl, 0
426 je .read_fdd
427
428 .write_fdd:
429 mov bl, 2 ; channel 2
430 mov esi, 512 ; bytes to write
431 mov ecx, 0x80000 ; page & offset
432 mov bh, 1 ; write floppy, "read DMA"
433 call dma_transfer
434
435 mov al, 0xC5 ; write fdd_sector command
436 call fdc_sendbyte
437 jmp .cont
438
439 .read_fdd:
440 mov bl, 2 ; channel 2
441 mov esi, 512 ; bytes to read
442 mov ecx, 0x80000 ; page & offset
443 mov bh, 0 ; read floppy, "write DMA"
444 call dma_transfer
445
446 mov al, 0xE6 ; read fdd_sector command
447 call fdc_sendbyte
448
449 .cont:
450 mov al, [fdd_driveno] ; fdd_head no. 0, drive A:
451 call fdc_sendbyte
452 mov al, [fdd_track] ; cylinder
453 call fdc_sendbyte
454
455 mov al, [fdd_head] ; head/side 0 or 1
456 call fdc_sendbyte
457 mov al, [fdd_sector] ; sector number,starts at 1
458 call fdc_sendbyte
459 mov al, 0x02 ; sector size - 512 bytes
460 call fdc_sendbyte
461
462 mov al, 0x12 ; 18 decimal sectors to a track
463 call fdc_sendbyte
464 mov al, 0x1B ; 27 should be the gap length for a 3.5" 1.44Mb
465 call fdc_sendbyte
466 mov al, 0xFF ; not used data length, because sector size has been filled
467 call fdc_sendbyte
468
469 mov [fdd_int_done], 0
470 call wait_int
471 jc .error
472
473 call fdc_getbyte
474 mov [ResultST0], al ; save result of ST0 in var
475 call fdc_getbyte
476 mov [ResultST1], al ; save result of ST1 in var
477 call fdc_getbyte
478 mov [ResultST2], al ; save result of ST2 in var
479 call fdc_getbyte
480 mov [ResultC], al ; save result of cylinder
481 call fdc_getbyte
482 mov [ResultH], al ; save result of head
483 call fdc_getbyte
484 mov [ResultR], al ; save result of sector number.
485 call fdc_getbyte
486 mov [ResultN], al ; save result of sector size
487
488 test [ResultST0], 11000000b ; test sr0 is 0xC0
489 jnz .error
490 mov [fdd_errorcode], 0x00
491 .ok:
492 popad
493 mov ah, [fdd_errorcode] ; move error status into ah
494 mov al, [ResultR]
495 clc
496 ret
497 .error:
498 popad
499 mov ah, [fdd_errorcode] ; move error status into ah
500 stc
501 ret