1 ;----------------------------------------------------------;
2 ; BOS kernel Christoffer Bubach, 2004-2005. ;
3 ;----------------------------------------------------------;
5 ; floppy disk driver originally by Craig Bamford, Dex4u. ;
6 ; adjustments and for BOS by bubach. ;
8 ;----------------------------------------------------------;
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.
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
25 fdd_errorcode db 0 ; this the error code 00 = no error
26 fdd_tries db 0 ; no. of times to try, before error.
29 ResultST1 db 0 ; or pcn
40 ;------------------------------------------------------;
41 ; initializes the floppy disk driver ;
43 ;------------------------------------------------------;
48 mov cl, 0x26 ; hook interrupt 0x26 (IRQ6)
52 mov cl, 6 ; enable IRQ6
55 call fdd_reset ; reset FDC
64 ;------------------------------------------------------;
67 ;------------------------------------------------------;
90 ;------------------------------------------------------;
91 ; wait for a floppy int ;
92 ; out: cf = 1 if timeout ;
93 ;------------------------------------------------------;
98 mov ecx, 150 ; 150 = 1.5 seconds.
99 call active_delay ; timer.inc
101 cmp dword [ecx], 0 ; timeup?
103 mov ax, [fdd_int_done] ; if not we check for int.
118 ;------------------------------------------------------;
121 ;------------------------------------------------------;
127 mov al, 0 ; all motors off..
129 mov [fdd_motor_on], 0
138 ;------------------------------------------------------;
141 ;------------------------------------------------------;
146 mov dx, 0x3F2 ; motor 0 on..
150 mov ecx, 20 ; 1/5 of a sec. to speed up
151 call delay ; in timer.inc
152 mov [fdd_motor_on], 1
160 ;------------------------------------------------------;
161 ; send a data byte to the FDC ;
163 ; in: al = data byte ;
164 ;------------------------------------------------------;
170 mov ecx, 150 ; 150 = 1.5 seconds.
171 call active_delay ; timer.inc
173 cmp dword [ecx], 0 ; timeup?
175 mov dx, 0x3f4 ; check status reg
178 cmp al, 10000000b ; are we ok to write
183 mov dx, 0x3F5 ; send byte
196 ;------------------------------------------------------;
197 ; read a data byte from the FDC ;
199 ; out: al = data byte ;
200 ;------------------------------------------------------;
206 mov ecx, 150 ; 150 = 1.5 seconds.
207 call active_delay ; timer.inc
209 cmp dword [ecx], 0 ; timeup?
211 mov dx, 0x3f4 ; check status reg
214 cmp al, 11000000b ; are we ok to read
219 mov dx, 0x3F5 ; get the byte
234 ;------------------------------------------------------;
237 ;------------------------------------------------------;
244 mov al, 00001000b ; no motors enabled, DMA Enabled, held FDC at reset
245 out dx, al ; drive A selected.
248 call delay ; in timer.inc
251 mov al, 00000000b ; 500Kb/sec mode
255 or al, 00001100b ; FDC completed reset, al =0x0c.
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.
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
270 mov al, 0x03 ; specify command (includes next two bytes sent)
272 mov al, 0xDF ; SRT = 3ms, HUT = 240ms
274 mov al, 0x02 ; HLT = 16ms, ND = 0
292 ;------------------------------------------------------;
295 ;------------------------------------------------------;
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.
303 mov al, 0x0F ; seek command
305 mov al, [fdd_driveno] ; drive # (00 = A)
307 mov al, [fdd_track] ; cylinder #
310 mov [fdd_int_done], 0
314 mov al, 0x08 ; sense interrupt status command
317 mov ah, al ; save ST0 in ah
318 call fdc_getbyte ; should read PCN
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.. :-)
334 ;------------------------------------------------------;
337 ;------------------------------------------------------;
341 test [fdd_motor_on], 1
345 mov al, 0x07 ; recalibrate command
347 mov al, 0x00 ; selects drive a:
350 mov [fdd_int_done], 0
354 mov al, 0x08 ; sense interrupt status command
356 call fdc_getbyte ; read STO
357 mov ah, al ; save ST0 in ah
360 test ah, 00100000b ; test sr0 is 0x20
362 test ah, 00010000b ; test sr0 is 0x80
376 ;------------------------------------------------------;
378 ; input: bl = 0 read, 1 write ;
379 ; ch = track/cylinder ;
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 ;------------------------------------------------------;
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.
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.
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.
403 test [fdd_motor_on], 1
408 mov al, 00000000b ; 500Kb/sec mode
410 mov [fdd_errorcode], 0x80 ; put basic error code, just in case.
413 mov cx, 3 ; we want to try seek 3 times
415 call fdd_seek ; we need to move to the right track.
416 jnc .l3 ; we should be on the right track.
418 jmp .error ; timeout.
420 mov dx, 0x3f4 ; check status reg (to see if DMA bit set)
422 test al, 00100000b ; test sr0 is 0x80
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"
435 mov al, 0xC5 ; write fdd_sector command
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"
446 mov al, 0xE6 ; read fdd_sector command
450 mov al, [fdd_driveno] ; fdd_head no. 0, drive A:
452 mov al, [fdd_track] ; cylinder
455 mov al, [fdd_head] ; head/side 0 or 1
457 mov al, [fdd_sector] ; sector number,starts at 1
459 mov al, 0x02 ; sector size - 512 bytes
462 mov al, 0x12 ; 18 decimal sectors to a track
464 mov al, 0x1B ; 27 should be the gap length for a 3.5" 1.44Mb
466 mov al, 0xFF ; not used data length, because sector size has been filled
469 mov [fdd_int_done], 0
474 mov [ResultST0], al ; save result of ST0 in var
476 mov [ResultST1], al ; save result of ST1 in var
478 mov [ResultST2], al ; save result of ST2 in var
480 mov [ResultC], al ; save result of cylinder
482 mov [ResultH], al ; save result of head
484 mov [ResultR], al ; save result of sector number.
486 mov [ResultN], al ; save result of sector size
488 test [ResultST0], 11000000b ; test sr0 is 0xC0
490 mov [fdd_errorcode], 0x00
493 mov ah, [fdd_errorcode] ; move error status into ah
499 mov ah, [fdd_errorcode] ; move error status into ah