Using floppy disc
Re:Using floppy disc
ok, I?ve tried and tried.. I cant find the DBA or the "specify command". this is how far I?ve got
void reset_floppy() {
???out(0x3f2, 0);
???out(0x3f2, 0x0C);
???out(0x3f7, 0);
???wait_for_floppy_irq();
???send_floppy_command(8);
but I cant send the command 4 times (even though I check the MRQ in between). And I cant find the specify command either. The error I get in Bochs when trying to send more than one "check interrupt" command is:
io: 3f5: receiving new comm, old one (08) pending
void reset_floppy() {
???out(0x3f2, 0);
???out(0x3f2, 0x0C);
???out(0x3f7, 0);
???wait_for_floppy_irq();
???send_floppy_command(8);
but I cant send the command 4 times (even though I check the MRQ in between). And I cant find the specify command either. The error I get in Bochs when trying to send more than one "check interrupt" command is:
io: 3f5: receiving new comm, old one (08) pending
Re:Using floppy disc
BDA= Bios Data AreaBrandon wrote: DPT, CCR? What kinda ports is this, cant find them in the documents..
DPT= disk parameter table
CCR == DIR =digital input register
read the intel manuals
Only Human
Re:Using floppy disc
Are you sending the EOI (End of Interrupt) signal?Brandon wrote: The error I get in Bochs when trying to send more than one "check interrupt" command is:
io: 3f5: receiving new comm, old one (08) pending
your code should look something like this
Code: Select all
void reset_floppy() {
out(0x3f2, 0);
out(0x3f2, 0x0C);
fdc_flag=1;
}
void init_floppy()
{
int i;
reset_floppy();
out(0x3f7,0);
while(fdc_flag);???// wait till it changes to 0
for(i=0;i<4;i++) {
check_int_status();
}
specify_FDC();
}
Only Human
Re:Using floppy disc
how should the check_int_status() look like?
And in the code you just wrote, I didnt see the using of the specify command?
and yes, this is my irq handler
void int_38(void)
{
out(0xA0, 0x20);
out(0x20, 0x20);
print("Floppy IRC\n", WHITE_TXT);
fdc_flag = 1;
}
And in the code you just wrote, I didnt see the using of the specify command?
and yes, this is my irq handler
void int_38(void)
{
out(0xA0, 0x20);
out(0x20, 0x20);
print("Floppy IRC\n", WHITE_TXT);
fdc_flag = 1;
}
Re:Using floppy disc
are u sure the EOI can be sent that way at the beginning in a C function? anybody knows?
Only Human
Re:Using floppy disc
It can as I have seen chris greise do it in his code. Just to be on the safe side, I use an asm wrapper for my IRQS that sends the End of interrupt (EOI). This way I know the c compiler isnt going to possibly crash my irq_handler code.
I suggest taking a look on the OS faq on how to do this. Hope this helps.
I suggest taking a look on the OS faq on how to do this. Hope this helps.
Re:Using floppy disc
Hi,
While most devices are slow compared to the CPU, you'd also need to be careful with IRQs that are shared by more than one device - PCI IRQs and serial ports for instance.
Cheers,
Brendan
If the device is capable of generating IRQ's with extremely short amounts of time inbetween, then the interrupt handler could interrupt itself and would need to be re-entrant (unless interrupts are completely disabled anyway - e.g. interrupt gate used).Neo wrote: are u sure the EOI can be sent that way at the beginning in a C function? anybody knows?
While most devices are slow compared to the CPU, you'd also need to be careful with IRQs that are shared by more than one device - PCI IRQs and serial ports for instance.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:Using floppy disc
Im pretty sure the IRQ handler works...
Bu the way. How do I read the status registers ST0, ST1 and so on.. cant find them..
Bu the way. How do I read the status registers ST0, ST1 and so on.. cant find them..
Re:Using floppy disc
why theBrandon wrote: and yes, this is my irq handler
void int_38(void)
{
???out(0xA0, 0x20);
???out(0x20, 0x20);
???print("Floppy IRC\n", WHITE_TXT);
???fdc_flag = 1;
}
Code: Select all
out(0xA0,0x20);
Code: Select all
FDCHandler:
ISR_HEAD
call FDC_CHandler
mov al,0x20
out 0x20,al
ISR_TAIL
iretd
Code: Select all
%macro ISR_HEAD 0
cli
pusha
push fs
push gs
push es
push ds
%endmacro
%macro ISR_TAIL 0
pop ds
pop es
pop gs
pop fs
popa
sti
%endmacro
Only Human
Re:Using floppy disc
Oh thought number 6 was on the slave, silly me..
anyways, I know that the ISR works.. what my problem is to do this things you told me about
"Issue the "Check Interrupt" command 4 times
your almost done now after this"
"Issue the "Specify" command now to set up step rate time etc.."
What is the Check interrupt sposed to do? and how do I do it.. I havent really understood how to use the data register. Do I have to, before sending a command, send how many bytes I will send? and how do I read the data registers.
anyways, I know that the ISR works.. what my problem is to do this things you told me about
"Issue the "Check Interrupt" command 4 times
your almost done now after this"
"Issue the "Specify" command now to set up step rate time etc.."
What is the Check interrupt sposed to do? and how do I do it.. I havent really understood how to use the data register. Do I have to, before sending a command, send how many bytes I will send? and how do I read the data registers.
Re:Using floppy disc
Yeah i guess i forgot the "Specify" command in that demo code above (I've changed it now)Brandon wrote: What is the Check interrupt sposed to do? and how do I do it.. I havent really understood how to use the data register. Do I have to, before sending a command, send how many bytes I will send? and how do I read the data registers.
how have you been sending out commands to the FDC and reading the results so far?
I suggest you read some tutorials on this first (if you haven't so far) because I don't have the time for a detailed explanation.
You have to check that the FDC's DR (Data Reg) is ready to receive your commands before issuing one. This is done by checking the MSR to see if the appropriate bits are set/reset.
Similarly you need to check to see if it is ready to receive data before reading from the DR.
The "Check Interrupt Status" IIRC is also known as the "Sense Interrupt Status" command . Look them up in your manual.
Only Human
Re:Using floppy disc
Alright.. this is how I?ve done. When trying to write to the data reg, I read the MRQ and all that. But I havent written anything (dont know if I have to specify how many bytes I will send). The thing I wonder about:
Before I send a command, do I have to send a line with the number of bytes to be sent? Spose I want to send command 3 and 1 argument (if we spose the command requires this). Should I then write
send(2) // Number of bytes comming
send(3)
send(1)
I also use if((in(0x3f4) & 0xC0) == 0xC0) ... to see if Im able to read from the data register. But How do I read the different status registers like ST0 and ST1 from the DR? And, when I issue the "sense command", do I have to read any of those registers in between (except for the MSR)?
Ive tried to find tutorials but the one I?ve found didnt make sense. I know the data register uses a stack, but I dont know how to "pop" the different status registers from it.
Before I send a command, do I have to send a line with the number of bytes to be sent? Spose I want to send command 3 and 1 argument (if we spose the command requires this). Should I then write
send(2) // Number of bytes comming
send(3)
send(1)
I also use if((in(0x3f4) & 0xC0) == 0xC0) ... to see if Im able to read from the data register. But How do I read the different status registers like ST0 and ST1 from the DR? And, when I issue the "sense command", do I have to read any of those registers in between (except for the MSR)?
Ive tried to find tutorials but the one I?ve found didnt make sense. I know the data register uses a stack, but I dont know how to "pop" the different status registers from it.
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Using floppy disc
@brendan: XOR in c is a '^', iirc.
@brandon: the chip does this as soon as you have performed the read operation on the data register: after in(port) it puts the next value in its internal buffer on the port.
so, you issue a series of in(port) commands, and check for each iteration: is there a value to be fetched? some flag in some status register tells this. If nothing is there to be fetched: exit the loop.
@brandon: the chip does this as soon as you have performed the read operation on the data register: after in(port) it puts the next value in its internal buffer on the port.
so, you issue a series of in(port) commands, and check for each iteration: is there a value to be fetched? some flag in some status register tells this. If nothing is there to be fetched: exit the loop.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
Re:Using floppy disc
no nothing of that sort, the command itself tells the FDC how manybytes are expected and you need to give it the correct number only, no need to specify how many bytes.Brandon wrote: Before I send a command, do I have to send a line with the number of bytes to be sent? Spose I want to send command 3 and 1 argument (if we spose the command requires this). Should I then write
send(2) // Number of bytes comming
send(3)
send(1)
I also use if((in(0x3f4) & 0xC0) == 0xC0) ... to see if Im able to read from the data register. But How do I read the different status registers like ST0 and ST1 from the DR? And, when I issue the "sense command", do I have to read any of those registers in between (except for the MSR)?
Ive tried to find tutorials but the one I?ve found didnt make sense. I know the data register uses a stack, but I dont know how to "pop" the different status registers from it.
The DR is the only register you need to read bytes from and write commands to. The MSR register should be read before each read/write to the DR to see that the DR is ready to accept or give data.
To check if the FDC is ready to receive commands the code in C is something like this
Code: Select all
void FDC_cmd_ready()
{
while( (in(0x3F4)&0xC0)!=0x80 );
}
Code: Select all
FDC_cmd_ready:
push???dx
.cont:
???mov???dx,FDCA_BASE+MSR ; // 0x3F4
???in???al,dx
???and???al,0xC0
???cmp???al,0x80
???je??? .end
???in???al,0x80 ???; delay
???jne??? .cont
.end:
pop???dx ; should probably push & pop ax too
retn
You dont need to pop anything from anywhere to get the resultant bytes. just read the DR consecutively for each byte you expect to receive.
For e.g. consider the "Check Interrupt Status" command it is represented by 0x08 and results in 2 bytes as output which are ST0 and Physical Cylinder Number (PCN).
The steps to be followed in executing this command are
- Check if the FDC is ready to receive commands and loop while its not (or sleep or something if you have multi-processing working)
- Write out the byte 0x08 (check int status) to the DR
- Check if the FDC is ready to be read and loop etc until its not.
- Now read the DR to get ST0
- Repeat the previous 2 steps to read in the PCN
Only Human
Re:Using floppy disc
Thank you very much =) I?ll play around with it Much clearer now
Edit: This is the code I got right now:
void FDC_cmd_ready(unsigned char code) {
while((in(0x3F4) & code) == 0);
}
void send_floppy_command(unsigned char command) {
FDC_cmd_ready(0x80);
out(0x3f5, command);
}
unsigned char get_floppy_command() {
FDC_cmd_ready(0xC0);
return in(0x3f5);
}
void reset_floppy() {
// Reset the floppy
out(0x3f2, 0);
out(0x3f2, 0x0C);
// Set the data rate = 500 kbps
out(0x3f7, 0);
wait_for_floppy_irq(); // Wait for IRC
int i;
for(i = 0;i<4;i++) {
send_floppy_command(0x8); // Send the check interrupt cmd
get_floppy_command(); // Read the data reg
get_floppy_command(); // Read the data reg
}
send_floppy_command(3); // The specify command
send_floppy_command(0); // And the arguments
send_floppy_command(0);
}
I run the function reset_floppy(). Then I send
out(0x3f2, 0x1C);
to start the motor. Then I wait for an IRQ. But that IRQ never occurs. So I suppose there?s something wrong with my reset-code
Edit: This is the code I got right now:
void FDC_cmd_ready(unsigned char code) {
while((in(0x3F4) & code) == 0);
}
void send_floppy_command(unsigned char command) {
FDC_cmd_ready(0x80);
out(0x3f5, command);
}
unsigned char get_floppy_command() {
FDC_cmd_ready(0xC0);
return in(0x3f5);
}
void reset_floppy() {
// Reset the floppy
out(0x3f2, 0);
out(0x3f2, 0x0C);
// Set the data rate = 500 kbps
out(0x3f7, 0);
wait_for_floppy_irq(); // Wait for IRC
int i;
for(i = 0;i<4;i++) {
send_floppy_command(0x8); // Send the check interrupt cmd
get_floppy_command(); // Read the data reg
get_floppy_command(); // Read the data reg
}
send_floppy_command(3); // The specify command
send_floppy_command(0); // And the arguments
send_floppy_command(0);
}
I run the function reset_floppy(). Then I send
out(0x3f2, 0x1C);
to start the motor. Then I wait for an IRQ. But that IRQ never occurs. So I suppose there?s something wrong with my reset-code