C++ Learning Community Forum
September 09, 2010, 08:23:50 AM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: Hello. Smiley
 
   Home   Help Search Login Register  
Pages: [1]
  Print  
Author Topic: Floppy Drive Access w/out BIOS/DOS  (Read 1595 times)
mleveill
1337 L0LCoder
C++ Freak
***
Posts: 430


IM IN UR PROGRAMZ WRITIN UR CODEZ!


View Profile
« on: August 06, 2007, 05:22:31 AM »

i want to read the floppy drive without using BIOS/DOS etc. i have 2 crappy example programs, one in c and the other in asm. chances are i'm missing an instruction or i misspelled a register dispite repeatedly checking my code.

anyone have any links to floppy drive access examples? they can be in c or asm, but must not use bios/dos functions unless it is something like hooking an interrupt or IO functions. all i want to do is read a sector from a  3 1/2"  1.44MB  floppy. i've googled many times but haven't had any success.

if anyone wants to look at my code just ask and i'll post it.
Logged

Quote from: kohlrak
Common interests aren't always the best thing. Especially programming wise.
I could just picture a couple fighting over weather to "xor eax by eax" or "and eax by 0"...
Then kids'll come home and argue with their parents that readabilty is better than size and that "mov eax, 0" would be best because that's "more readable." (Even if it really isn't...)

LOLCode - http://lolcode.com/home
C-Man
Does anyone even read this ?
Global Moderator
Dr. of C++ology
*****
Posts: 988



View Profile WWW
« Reply #1 on: August 06, 2007, 05:49:21 AM »

http://osdever.net/documents/82077AA_FloppyControllerDatasheet.pdf?the_id=41
http://www.osdever.net/cottontail/#Floppy
Logged

mleveill
1337 L0LCoder
C++ Freak
***
Posts: 430


IM IN UR PROGRAMZ WRITIN UR CODEZ!


View Profile
« Reply #2 on: August 07, 2007, 01:25:25 AM »

thanks but man i hate disk access... Angry
communicating with pci devices is easier! Tongue
Logged

Quote from: kohlrak
Common interests aren't always the best thing. Especially programming wise.
I could just picture a couple fighting over weather to "xor eax by eax" or "and eax by 0"...
Then kids'll come home and argue with their parents that readabilty is better than size and that "mov eax, 0" would be best because that's "more readable." (Even if it really isn't...)

LOLCode - http://lolcode.com/home
C-Man
Does anyone even read this ?
Global Moderator
Dr. of C++ology
*****
Posts: 988



View Profile WWW
« Reply #3 on: August 07, 2007, 06:42:11 AM »

same here Tongue
Logged

mleveill
1337 L0LCoder
C++ Freak
***
Posts: 430


IM IN UR PROGRAMZ WRITIN UR CODEZ!


View Profile
« Reply #4 on: August 08, 2007, 08:05:35 AM »

well, after procratinating for a while, i finally got the balls to rewrite my entire floppy access routines -_- ...

and it still doesn't work Angry would anyone be nice enough to take some time out of their day and look over my code? PLEASE!!! ok, thanks! brace yourself, here it comes!

the code is also attached if you would rather download it

Code:
;********************************************************************************
; FLOPPY.inc *
;********************************************************************************


; predefined drive geometry
%define FDD_HEADS DG144_HEADS
%define FDD_TRACKS DG144_TRACKS
%define FDD_SPT DG144_SPT
%define FDD_GAP3FMT DG144_GAP3FMT
%define FDD_GAP3RW DG144_GAP3RW


; drive geometries
%define DG144_HEADS 2 ; HEADS per drive (1.44M)
%define DG144_TRACKS 80 ; number of TRACKS (1.44M)
%define DG144_SPT 18 ; Sectors Per Track (1.44M)
%define DG144_GAP3FMT 0x54 ; GAP3 while ForMaTting (1.44M)
%define DG144_GAP3RW 0x1B ; GAP3 while Reading/Writing (1.44M)

%define DG168_HEADS 2 ; HEADS per drive (1.68M)
%define DG168_TRACKS 80 ; number of TRACKS (1.68M)
%define DG168_SPT 21 ; Sectors Per Track (1.68M)
%define DG168_GAP3FMT 0x0C ; GAP3 while ForMaTting (1.68M)
%define DG168_GAP3RW 0x1C ; GAP3 while Reading/Writing (1.68M)


; fdc IO ports
%define FDC_DOR 0x3F2 ; Digital Output Register
%define FDC_MSR 0x3F4 ; Main Status Register (read)
%define FDC_DRS 0x3F4 ; Data Rate Select register (write)
%define FDC_DATA 0x3F5 ; DATA register
%define FDC_DIR 0x3F7 ; Digital Input Register (read)
%define FDC_CCR 0x3F7 ; Configuration Control Register (write)


; fdc command bytes (765 commands + options
%define FDC_CMD_SPECIFY 0x03 ; SPECIFY drive timings
%define FDC_CMD_WRITE 0xC5 ; WRITE data
%define FDC_CMD_READ 0xE6 ; READ data
%define FDC_CMD_RECAL 0x07 ; RECALibrate
%define FDC_CMD_SENSEI 0x08 ; SENSE Interrupt status
%define FDC_CMD_FORMAT 0x4D ; FORMAT track (+ MFM)
%define FDC_CMD_SEEK 0x0F ; SEEK track
%define FDC_CMD_VERSION 0x10 ; FDC version


%define DMA_ADDR 0x7000 ; DMA Address
%define DMA_PAGE_PORT 0x81
%define DMA_OFFSET_PORT 0x4
%define DMA_LENGTH_PORT 0x5


%define DMA_PAGE DMA_ADDR >> 16
%define DMA_OFFSET DMA_ADDR & 0xFFFF
%define DMA_LENGTH 511


fdc_fail db 0
fdc_status times 7 db 0
fdc_stat_index db 0
fdc_sr0 db 0
fdc_track db 0xFF



fdc_init:
push esi

call fdc_reset

mov al, FDC_CMD_VERSION
call fdc_outb
call fdc_inb ; al holds floppy controller version

cmp al, 0x80
jne .enhancedController

mov esi, NECFDCFound
call displayString
jmp .done

.enhancedController:
mov esi, enhancedFDCFound
call displayString

.done:
pop esi
ret



; al -> byte to send
fdc_outb:
push edx
push ecx
push eax

mov ecx, 129 ; try 128 times

.tryAgain:
mov dx, 0x80
in al, dx ; delay

dec ecx
cmp ecx, 0
je .fail ; operation timed out

mov dx, FDC_MSR
in al, dx
and al, 0xC0
cmp al, 0x80
jne .tryAgain ; fdc not ready

pop eax ; fdc ready
mov dx, FDC_DATA
out dx, al
jmp .successful ; already poped eax so skip it and don't set failure byte

.fail:
mov byte [fdc_fail], 1 ; inform of failure
pop eax

.successful:
pop ecx
pop edx
ret



; al -> byte recieved
fdc_inb:
push edx
push ecx

mov ecx, 129 ; try 128 times

.tryAgain:
mov dx, 0x80
in al, dx ; delay

dec ecx
cmp ecx, 0
je .fail ; operation timed out

mov dx, FDC_MSR
in al, dx
and al, 0xD0
cmp al, 0xD0
jne .tryAgain ; fdc not ready

mov dx, FDC_DATA ; fdc ready
in al, dx
jmp .successful ; don't set the failure byte

.fail:
mov byte [fdc_fail], 1 ; inform of failure

.successful:
pop ecx
pop edx
ret



; al -> NON-ZERO value WILL sense a fdc interrupt
fdc_wait:
push ebx
push ecx
push edx
push eax

;call getUserInput ; wait for IRQ6 handler to finish, this is HIGHLY reliable ;)
mov eax, 8
call waitTimerTicks ; changed it to wait 2 seconds

xor ebx, ebx
.readCMDBytes:
cmp ebx, 7
jge .doneReading ; read all 7 bytes

mov dx, FDC_MSR
in al, dx
and al, 1 << 4
cmp al, 0
je .doneReading ; stop reading

inc ebx ; next index
mov edx, fdc_status ; address of fdc_status[0]
add edx, ebx ; address of fdc_status[ebx]
call fdc_inb
mov [edx], al ; save status
jmp .readCMDBytes ; read another byte

.doneReading:
mov [fdc_stat_index], ebx ; save the amount of register statuses saved

pop eax
cmp al, 0
je .skipSenseI

mov al, FDC_CMD_SENSEI
call fdc_outb

call fdc_inb
mov [fdc_sr0], al

call fdc_inb
mov [fdc_track], al

.skipSenseI:

mov dx, FDC_DIR
and al, 0x80
cmp al, 0
je .noDiskChange

mov byte [fdc_fail], 1

.noDiskChange:
pop edx
pop ecx
pop ebx
ret



fdc_reset:
push eax
push edx

mov dx, FDC_DOR
mov al, 0
out dx, al ; stop motor

mov dx, FDC_DRS
mov al, 0
out dx, al ; 500K/s transfer rate

mov dx, FDC_DOR
mov al, 0xC
out dx, al ; re-enable interrupts

mov al, 1
call fdc_wait ; wait for the triggered interrupt

mov al, FDC_CMD_SPECIFY
call fdc_outb ; specify drive timings
mov al, 0xDF
call fdc_outb ; SRT = 3ms, HUT = 240ms
mov al, 2
call fdc_outb ; HLT = 16ms, ND = 0

mov al, 1
call fdc_seek

call fdc_recalibrate

pop edx
pop eax
ret



fdc_motor_on:
push eax
push edx

mov dx, FDC_DOR
mov al, 0x1C
out dx, al ; turn on

mov eax, 2
call waitTimerTicks ; wait 500ms for motor to speed up

pop edx
pop eax
ret



fdc_motor_off:
push eax
push edx

mov eax, 8
call waitTimerTicks ; wait 2 seconds for motor to turn off

mov dx, FDC_DOR
mov al, 0xC
out dx, al

pop edx
pop eax
ret



fdc_recalibrate:
push eax

call fdc_motor_on

mov al, FDC_CMD_RECAL
call fdc_outb ; tell fdc to recalibrate

mov al, 0
call fdc_outb ; ???

mov al, 1
call fdc_wait ; wait for triggered interrupt

call fdc_motor_off

pop eax
ret



; al -> track to seek
fdc_seek:
mov byte [fdc_fail], 0 ; clear fail byte

push eax
push ebx

mov ebx, eax ; store the track in ebx

cmp [fdc_track], bl
je .done ; the requested track is already selected

call fdc_motor_on

mov al, FDC_CMD_SEEK
call fdc_outb ; send seek command to fdc
mov al, 0
call fdc_outb ; ???
mov al, bl
call fdc_outb ; send track to seek

mov al, 1
call fdc_wait
cmp byte [fdc_fail], 0 ; check if it failed
jne .done

mov eax, 1
call waitTimerTicks ; wait 250ms

call fdc_motor_off

cmp byte [fdc_sr0], 0x20
jne .fail

cmp [fdc_track], bl ; check if the correct track is selected
jne .fail

jmp .done ; WORKED!!! :)

.fail:
mov byte [fdc_fail], 1

.done:
pop ebx
pop eax
ret



; eax -> head requested
; ebx -> track requested
; ecx -> sector requested
fdc_read:
mov byte [fdc_fail], 0 ; clear fail byte

push esi
push ebx
push edx
push ecx
push eax

call fdc_motor_on

mov ecx, 3
.tryAgain:
mov dx, FDC_DIR
in al, dx
and al, 0x80
cmp al, 0
jne near .diskChange ; disk change detected, exit

mov al, bl
call fdc_seek
cmp byte [fdc_fail], 0
jne near .seekFail ; seek failed, exit

mov dx, FDC_CCR
mov al, 0
out dx, al ; 500K/s transfer rate

call fdc_dma_xfer

mov al, FDC_CMD_READ
call fdc_outb

pop eax
push eax
shl eax, 2
call fdc_outb ; send (head << 2)

mov eax, ebx
call fdc_outb ; send track

pop eax
call fdc_outb ; send head

pop ebx ; -_-
push ebx ; -_-
push eax ; -_-
mov eax, ebx ; finally put the sector in eax
call fdc_outb ; and send it

mov al, 2
call fdc_outb ; 512 bytes/sector

mov al, FDD_SPT
call fdc_outb ; send disk geometry info

mov al, FDD_GAP3RW
call fdc_outb ; send disk geometry info

mov al, 0xFF
call fdc_outb ; DTL = unused

mov al, 0
call fdc_wait
cmp byte [fdc_fail], 0
jne .done ; TIMEOUT!!!

mov al, [fdc_status] ; mov fdc_status[0] into eax
and al, 0xC0
cmp al, 0
je .successful ; OMFG!!!! IT ACTUALLY WORKED!!!! ... well, i think so...

call fdc_recalibrate ; CRAP!!!
dec ecx
cmp ecx, 0
je .tryAgain ; BETTER WORK THIS TIME!!!

.successful:
call fdc_motor_off

mov esi, displayingStatus
call displayString

mov edx, fdc_status
mov ecx, [fdc_stat_index]
.iterate:
cmp ecx, 0
je .done

xor eax, eax
mov al, [edx]
call displayNum
mov ax, VK_SPACE
call displayChar

inc edx
dec ecx
jmp .iterate

.diskChange:
mov al, 1
call fdc_seek
call fdc_recalibrate

.seekFail:
call fdc_motor_off
mov byte [fdc_fail], 1

.done:
mov ax, VK_ENTER
call displayChar

pop eax
pop ecx
pop edx
pop ebx
pop esi
ret



; uses channel 2
; uses physical address: 0x7000 (is this a good/valid address???)
; uses length of 512
; only for transfering from device to memory
fdc_dma_xfer:
push eax
push edx

cli ; disable interrupts

mov dx, 0xA
mov al, 2 | 4 ; set mask bit for channel
out dx, al ; and send it

mov dx, 0xC
mov al, 0
out dx, al ; clear flipflop, whatever that is...

mov dx, 0xB
mov al, 0x48+2 ; set DMA read mode
out dx, al ; and send it

mov dx, DMA_PAGE_PORT ; is this right???
mov al, DMA_PAGE
out dx, al ; send page

mov dx, DMA_OFFSET_PORT
mov al, DMA_OFFSET & 0xFF
out dx, al ; send low byte of offset

mov dx, DMA_OFFSET_PORT
mov al, DMA_OFFSET >> 8
out dx, al ; send high byte of offset

mov dx, DMA_LENGTH_PORT
mov al, DMA_LENGTH & 0xFF
out dx, al ; send low byte of length

mov dx, DMA_LENGTH_PORT
mov al, DMA_LENGTH >> 8
out dx, al ; send high byte of length

mov dx, 0xA
mov al, 2
out dx, al ; clear DMA mask bit

sti ; enable interrupts

pop edx
pop eax
ret



enhancedFDCFound db "Enhanced Floppy Drive Controller Found", VK_ENTER, 0
NECFDCFound db "NEC765 Floppy Drive Controller Found", VK_ENTER, 0
displayingStatus db "FDC Register Statuses: ", 0

* FLOP.txt (9.51 KB - downloaded 43 times.)
Logged

Quote from: kohlrak
Common interests aren't always the best thing. Especially programming wise.
I could just picture a couple fighting over weather to "xor eax by eax" or "and eax by 0"...
Then kids'll come home and argue with their parents that readabilty is better than size and that "mov eax, 0" would be best because that's "more readable." (Even if it really isn't...)

LOLCode - http://lolcode.com/home
mleveill
1337 L0LCoder
C++ Freak
***
Posts: 430


IM IN UR PROGRAMZ WRITIN UR CODEZ!


View Profile
« Reply #5 on: August 08, 2007, 08:07:26 AM »

oh and BTW i don't think my waitTimerTicks subroutine is accurate >_>

but i don't SEEM to get any errors so...

oops! forgot to tell you what happens. basically i call fdc_read and it returns with [fdc_fail] as zero (which is good) but when i read the bytes at mem address DMA_ADDR, all i get is zeros

i call fdc_read with: eax = 0, ebx = 0, ecx = 0 and i've tried ecx = 1

i just changed the time waited with waitTimerTicks to ridiculus amounts and still doesn't work

at the end of fdc_read, the fdc statuses that are printed out are 0, 64, 4, 0, 0, 144, 1
i'm going to look into what these each of these means
« Last Edit: August 08, 2007, 08:23:25 AM by h4x » Logged

Quote from: kohlrak
Common interests aren't always the best thing. Especially programming wise.
I could just picture a couple fighting over weather to "xor eax by eax" or "and eax by 0"...
Then kids'll come home and argue with their parents that readabilty is better than size and that "mov eax, 0" would be best because that's "more readable." (Even if it really isn't...)

LOLCode - http://lolcode.com/home
mleveill
1337 L0LCoder
C++ Freak
***
Posts: 430


IM IN UR PROGRAMZ WRITIN UR CODEZ!


View Profile
« Reply #6 on: August 09, 2007, 04:26:42 AM »

 Cry didn't think anyone would want to help Cry
Logged

Quote from: kohlrak
Common interests aren't always the best thing. Especially programming wise.
I could just picture a couple fighting over weather to "xor eax by eax" or "and eax by 0"...
Then kids'll come home and argue with their parents that readabilty is better than size and that "mov eax, 0" would be best because that's "more readable." (Even if it really isn't...)

LOLCode - http://lolcode.com/home
C-Man
Does anyone even read this ?
Global Moderator
Dr. of C++ology
*****
Posts: 988



View Profile WWW
« Reply #7 on: August 09, 2007, 07:41:12 AM »

well h4x i wish i could help but i haven't tried to use raw floppy access yet , most of the time i just used the bios since i was only working on a bootloader (since performance doesn't really matter in a bootloader anyway)
you might try asking at http://flatassembler.net forums or http://osdever.net irc i bet thwey have soem ancwers
Logged

mleveill
1337 L0LCoder
C++ Freak
***
Posts: 430


IM IN UR PROGRAMZ WRITIN UR CODEZ!


View Profile
« Reply #8 on: August 09, 2007, 08:31:52 AM »

yeah i didn't even bother trying to write my own bootloader, i just used someone else's Grin bootloader = BORING Tongue

it's funny you gave me the flat assembler link, i used to go there a lot and just browse topics. HAHAHA! i just remembered that is where i got my sig. i'll ask around, thanks

i knew i had crossed the line of no return (asm programming wise) when i saw that post (where i got my sig) and couldn't stop laughing. i must be going insane... or at least just sick in the head
« Last Edit: August 09, 2007, 08:51:51 AM by h4x » Logged

Quote from: kohlrak
Common interests aren't always the best thing. Especially programming wise.
I could just picture a couple fighting over weather to "xor eax by eax" or "and eax by 0"...
Then kids'll come home and argue with their parents that readabilty is better than size and that "mov eax, 0" would be best because that's "more readable." (Even if it really isn't...)

LOLCode - http://lolcode.com/home
mleveill
1337 L0LCoder
C++ Freak
***
Posts: 430


IM IN UR PROGRAMZ WRITIN UR CODEZ!


View Profile
« Reply #9 on: August 16, 2007, 04:32:18 AM »

OOOOOOOOOOOOOOOOOOMMMMMMMMMMMMMMMMMMMMMMMFFFFFFFFFFFFFFFFFFFFFFGGGGGGGGGGGGGGGGGG!!!!!!!!!!!!!!!!!!!!!!111111111oneoneoneoneone
i finally got it to work!  Cool WOOOOOOT! the code is so beautiful Cry

that was liek, 100 times harder than multitasking (software) Tongue
« Last Edit: August 16, 2007, 04:34:47 AM by h4x » Logged

Quote from: kohlrak
Common interests aren't always the best thing. Especially programming wise.
I could just picture a couple fighting over weather to "xor eax by eax" or "and eax by 0"...
Then kids'll come home and argue with their parents that readabilty is better than size and that "mov eax, 0" would be best because that's "more readable." (Even if it really isn't...)

LOLCode - http://lolcode.com/home
C-Man
Does anyone even read this ?
Global Moderator
Dr. of C++ology
*****
Posts: 988



View Profile WWW
« Reply #10 on: August 16, 2007, 05:34:30 AM »

so what was the problem ?
Logged

mleveill
1337 L0LCoder
C++ Freak
***
Posts: 430


IM IN UR PROGRAMZ WRITIN UR CODEZ!


View Profile
« Reply #11 on: August 16, 2007, 01:42:35 PM »

eh, some small errors that were hard to see.
also, in the source i was using, there was a couple mistakes Tongue

i made a few assumptions too. such as, i assumed that the param: BOOL read, would perform a read operation if it was true.
upon further inspection, if read == true it actually writes. -_- WTF Huh
Quote
/*
 * this sets up a DMA trasfer between a device and memory.  Pass the DMA
 * channel number (0..3), the physical address of the buffer and transfer
 * length.  If 'read' is TRUE, then transfer will be from memory to device,
 * else from the device to memory.
 */
void dma_xfer(int channel,long physaddr,int length,BOOL read)
thats just retarded IMHO Undecided
Logged

Quote from: kohlrak
Common interests aren't always the best thing. Especially programming wise.
I could just picture a couple fighting over weather to "xor eax by eax" or "and eax by 0"...
Then kids'll come home and argue with their parents that readabilty is better than size and that "mov eax, 0" would be best because that's "more readable." (Even if it really isn't...)

LOLCode - http://lolcode.com/home
C-Man
Does anyone even read this ?
Global Moderator
Dr. of C++ology
*****
Posts: 988



View Profile WWW
« Reply #12 on: August 16, 2007, 07:18:38 PM »

the device is reading , not you  Tongue
Logged

mleveill
1337 L0LCoder
C++ Freak
***
Posts: 430


IM IN UR PROGRAMZ WRITIN UR CODEZ!


View Profile
« Reply #13 on: August 16, 2007, 09:01:12 PM »

yea, but switching from your (OS) point of view, to the FDC's point of view, ONCE, in the middle of the source is kinda wierd Undecided
Logged

Quote from: kohlrak
Common interests aren't always the best thing. Especially programming wise.
I could just picture a couple fighting over weather to "xor eax by eax" or "and eax by 0"...
Then kids'll come home and argue with their parents that readabilty is better than size and that "mov eax, 0" would be best because that's "more readable." (Even if it really isn't...)

LOLCode - http://lolcode.com/home
C-Man
Does anyone even read this ?
Global Moderator
Dr. of C++ology
*****
Posts: 988



View Profile WWW
« Reply #14 on: August 17, 2007, 03:52:46 AM »

details details
Logged

Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!