Floppy problem

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Andrew

Floppy problem

Post by Andrew »

Hi again,
now i'll try to explain my problem that you could help me. explanation will be in the code i'll provide.

Code: Select all


#define DOR 0x3f2;
#define MOTA 16;
#define DMA_IRQ 8;
#define RESET 4;

#define MAINSTATUS 0x3f4;

#define DATAREGISTER 0x3f5;

bool Floppy::Main_(){
    initFl();  // this is the main function where i want to initialize my floppy drive
Sf -> printf("initialiation ended \n");
}

bool Floppy::MRQ_(){
???getStatus();
???if(MRQ) return true;
???return false;
}

void Floppy::getStatus(){
???__u8 mainreg; __u16 adr = MAINSTATUS;
???__asm__("inb %%dx, %%al \t\n":"=a"(mainreg):"d"(adr));
???((mainreg&128) == 128)? MRQ = true : MRQ = false;
???((mainreg&64) == 64) ? DIO = true : DIO = false; // true: controller => CPU
???((mainreg&16) == 16) ?  BUSY = true : BUSY = false;
}

void Floppy::initFl(){
???motor = false;
???// stop the motor and disable irq's
???__u16 adr = DOR;
???outb(adr, 0);

???TickCounter = 0;

    //data rate 500(Kb/s)
???outb(0x3f4, 0);

???/* re-enable interrupts */
???outb(adr, 0x0c);

/* resetting triggered an interrupt - handle it */
???FDD_intFlag = 1;
???WaitFDCInterrupt(true);

//specify drive timings
???while(!MRQ_());
???Command_Byte = 0x03;
???send2CCommandByte();

???while(!MRQ_());
???Command_Byte = 0x0D + 0x0F;
???send2CCommandByte();

???while(!MRQ_());
???Command_Byte = 0x02;
???send2CCommandByte();

???while(!MRQ_());

???Sf -> printf("---------------------------------------------------- \n");
???FDD_Track = 1;
???seekparkTrack();  // now this is the place where i have problems
}

void Floppy::send2CCommandByte(){
???FDC_Status = FDC_Normal;

???for(int i =0; i<128; i++){
??????getStatus();
??????if(MRQ && !DIO ){
??????    __u16 adr = DATAREGISTER;
?????????__asm__("outb %%al, %%dx"::"a"(Command_Byte),"d"(adr));
?????????Sf -> printf("prinial\n");
?????????return;
??????}
??????inb(0x80);
???}
???FDC_Status = 1;
}

int Floppy::fromController(){
    FDC_Status = 0;
???for(int i=0; i<128; i++){
??????getStatus();
??????if(MRQ && DIO){
?????????__u16 adr = DATAREGISTER; __u8 mainreg;
?????????__asm__("inb %%dx, %%al \t\n":"=a"(mainreg):"d"(adr));
?????????Sf -> printf("wyslal\n");
?????????return mainreg;
??????}
??????__asm__("inb $80, %al \t\n");
???}
// time out
???FDC_Status = 1;
???return -1;
}

void Floppy::WaitFDCInterrupt(bool sensei){
???FDC_Status = FDC_Normal;
???TickCounter = 0;
/* wait for IRQ6 handler to signal command finished */
???while(!FDD_intFlag && TickCounter < 36){
???}
       /* read in command result bytes */
???int i = 0; getStatus();
???while((i<7) && BUSY){
??????status[i++] = fromController();
??????getStatus();
???}
???if(sensei){ // sence interrupt status
      /* send a "sense interrupt status" command */
??????Command_Byte = 0x08;
??????send2CCommandByte();
??????FDC_ST0 = fromController();
??????FDC_C = fromController();
???}

???FDD_intFlag = 0;

???if(TickCounter > 36){  // time out
??????FDC_Status = 1;
???}else{
?????????FDC_Status = 0;
?????? }
}

// buggy function
void Floppy::seekparkTrack(){ // 3 byte command

???while(!MRQ_());???
???startMotor();
// after starting the motor if i am trying to read MSR
// i get value 16 in Bochs and value 0 on real PC
// maybe there is smth i should do?

???Command_Byte = 0x0f;
???send2CCommandByte();
   //further code is useless cause i can't send this byte
   // i get time out
}
i tried waiting the MSR to change but it is useless, cause i get infinity loop. i just have no idea what to do to make that thing work. maybe i missed smth (although i think that everything is done from the manual). What is more, irq are working fine, cause timer and keyboard are in working stage.

i would be really appreciated if someone took a look at my code and gave me an advice.

thank in advance.
nullify

Re:Floppy problem

Post by nullify »

Since you didn't show your code for timer and floppy ISR, I'm assuming that the timer ISR does

TickCounter++;

and the floppy ISR does

FDD_intFlag = 1;

If this isn't the case, then it should be :-)

Also, make sure that you declare FDD_intFlag and TickCounter as "volatile", so the compiler doesn't try to cache them in registers.
Andrew

Re:Floppy problem

Post by Andrew »

thank you for your reply.
nullify wrote: Since you didn't show your code for timer and floppy ISR, I'm assuming that the timer ISR does

TickCounter++;

and the floppy ISR does

FDD_intFlag = 1;
yes, you are right about mine isr.
Also, make sure that you declare FDD_intFlag and TickCounter as "volatile", so the compiler doesn't try to cache them in registers.
well i changed this in my code, and now it is

Code: Select all

      static __volatile__ __u8 FDD_intFlag;
      static __volatile__ __u16 TickCounter;

but it didn't help, 'cause i still get infinity loop.
any ideas?....
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Floppy problem

Post by Solar »

OK, let's see... for one, consider moving the "magic numbers" defines into a seperate header. Then, I assume you have correctly declared all the functions beforehand. I've found some not-so-nice constructs unrelated to your problem, which I have corrected / smoothed.

Code: Select all

bool Floppy::Main_(){
    initFl();  // this is the main function where i want to initialize my floppy drive
Sf -> printf("initialiation ended \n");
}
You don't return the announced bool.

Code: Select all

bool Floppy::MRQ_(){
   getStatus();
   if(MRQ) return true;
   return false;
}
Try "return (MRQ);", which does the same as the if-else.

Code: Select all

   ((mainreg&128) == 128)? MRQ = true : MRQ = false;
   ((mainreg&64) == 64) ? DIO = true : DIO = false; // true: controller => CPU
   ((mainreg&16) == 16) ?  BUSY = true : BUSY = false;
The ternary operator is not a replacement for if-else, and misplaced here. Try this:

Code: Select all

   MRQ =  mainreg & 128;
   DIO =  mainreg & 64;
   BUSY = mainreg & 16;
That's better, no? It does just the same.

Code: Select all

   while(!MRQ_());
Hm... busy-polling, not nice... you should think about a construct that does a proper notify, instead of polling the flag in a tight, endless loop.

Code: Select all

   Command_Byte = 0x03;
   send2CCommandByte();
You are doing a lot of this stuff - functions with side-effects, global variables etc. That's very bad mojo, and makes reading your code much harder. Use parameters and return values; that's why they are in the language.

Code: Select all

   for(int i =0; i<128; i++){
      getStatus();
      if(MRQ && !DIO ){
          __u16 adr = DATAREGISTER;
         __asm__("outb %%al, %%dx"::"a"(Command_Byte),"d"(adr));
         Sf -> printf("prinial\n");
         return;
      }
      inb(0x80);
   }
Hm. Are you sure the compiler doesn't just optimize this busy-loop away? Try compiling with -O0 (ooh-zero).

Sorry but my own floppy driver hasn't been made yet, so I can't really judge the validity of your register handling.
// buggy function
void Floppy::seekparkTrack(){ // 3 byte command

while(!MRQ_());
startMotor();
// after starting the motor if i am trying to read MSR
// i get value 16 in Bochs and value 0 on real PC
// maybe there is smth i should do?
Hmm... what's the code of startMotor()? That would be the stuff I'd look into, since send2CCommandByte() worked fine before.

Bottom line, I think you should improve on your coding style to rule out several error sources; and as a general hint, if something doesn't work, look for the last thing that worked - or seemed to work. ;-)
Every good solution is obvious once you've found it.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Floppy problem

Post by Pype.Clicker »

Andrew wrote: What is more, irq are working fine, cause timer and keyboard are in working stage.

i would be really appreciated if someone took a look at my code and gave me an advice.

thank in advance.
Sorry for being that suspicious, but do you have a visual confirmation of those interrupts ? Like having a character on screen changing everytime you receive irq 6 or irq0 or do you just assume that those will work as irq 1 works ?

It can occur (due to a misprogramming of the PIC) that irq1 will be fired while irq 0 and 6 are actually masked.

You also say that you have an "inifinite loop" ... did you manage to see where you're looping (e.g. breaking bochs' execution and running instruction by instruction, identifying the address range covered by the loop ?)
Andrew

Re:Floppy problem

Post by Andrew »

Pype.Clicker wrote: Sorry for being that suspicious, but do you have a visual confirmation of those interrupts ? Like having a character on screen changing everytime you receive irq 6 or irq0 or do you just assume that those will work as irq 1 works ?
yes i have that confirmation, during the irq0 i have mine tickcounter increasing, 'cause i print it on the screen. and what about irq1, i can see on the screen what i am typing. so i made the conclusion that everything is woking.
... but irq6 handler should change intFlag value from some value to 1. and this happens on real machine, but not in bochs, may be this is the hint to my problem ....
It can occur (due to a misprogramming of the PIC) that irq1 will be fired while irq 0 and 6 are actually masked.
all are unmasked.
You also say that you have an "inifinite loop" ... did you manage to see where you're looping (e.g. breaking bochs' execution and running instruction by instruction, identifying the address range covered by the loop ?)

well, yes i know where i get that infinity loop, i just forgot to post that startMotor function

Code: Select all

void Floppy::seekparkTrack(){ // 3 byte command

   while(!MRQ_());   
   startMotor();
// after starting the motor if i am trying to read MSR
// i get value 16 in Bochs and value 0 on real PC
// maybe there is smth i should do?

//   while(!MRQ_());  // this is where i get infinity loop

   Command_Byte = 0x0f;
   send2CCommandByte();
  //further code is useless cause i can't send this byte
  // i get time out
}

void Floppy::startMotor(){
   if(!motor){
      __u16 adr = DOR;
      __u8 set = MOTA + DMA_IRQ + RESET + 0;
      __asm__("outb %%al, %%dx \t\n"::"a"(set),"d"(adr));
      Floppy::TickCounter = 0;
      while(TickCounter < 150){ // 500ms
      }
      motor = true;
   }
}

on real machine motor starts, indicator is on and it is spinning :) but then MSR says that it is not busy, but can't accept the command, but in bochs it says that it is busy.
gino0631

Re:Floppy problem

Post by gino0631 »

heh, the source of the problem lies in the first few lines of your code:

#define DOR 0x3f2;
#define MOTA 16;
#define DMA_IRQ 8;
#define RESET 4;
...

Who puts semicolons in #define constants? :)

The actual error occurs in startMotor() :
__u8 set = MOTA + DMA_IRQ + RESET + 0;
produces not 28, as expected and should be, but 16, since MOTA is replaced with '16;', and the other constants are effectively ignored. The motor turns on, but the other bits remain incorrect.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Floppy problem

Post by Solar »

Hehe... ouch! ;-)

That's typical: You read over a statement too fast, assuming it's correct. "Oh, that's a couple of defines, next line please..."

Another case of the old rule:

Use -Wall!

;-)
Every good solution is obvious once you've found it.
Andrew

Re:Floppy problem

Post by Andrew »

thanks,
now i think everything should work, i'll test it a bit later.

P.S. noone doubts that the personal text of my profile is absolutly true, me either.
Schol-R-LEA

Re:Floppy problem

Post by Schol-R-LEA »

Oh, a few other small pieces of advice:

[*] When dealing with bit masks, it is usually clearer if you
use hex constants rather than decimal constants (even for values less than decimal 10); while it is a minor issue, since you are given them [tt]define[/tt]d names anyway, it would help make the intention clearer.

[*] Similarly, when using bit masks, it would make more sense to use | (logical or) instead of addition, as it makes the intended operation clearer (and, under certain circumstances, runs faster than addition).

[*] In C++, it is better to declare constants or enums rather than using defines, as a general rule; not only would it avoid a problem like the one you experienced, it would also enforce type checking and allow the compiler to do additional optimizations.

Modified to meet these suggestions, the code would read:

Code: Select all

const _u16 DOR      =  0x03f2;

// bit masks
const _u8 MOTA      = 0x10;   // binary 0001 0000
const _u8 DMA_IRQ = 0x08;  // binary 0000 1000
const _u8 RESET      = 0x04;  // binary 0000 0100

//  ...

__u8 set = MOTA | DMA_IRQ | RESET;
HTH.
Post Reply