Page 1 of 1

pata read write

Posted: Sun Nov 25, 2012 12:46 pm
by har
I'm having some problems with the code below.
Read will put out garbage, but always the same garbage.
So I can't check if write is working.
I'm using virtualbox for testing.

Code: Select all

void read(uint32 LBA){
   unsigned short port = 0x1F0;
   unsigned short te;
   int teller = 0;
   outb(port + HDD_DRIVE_PORT, HDD_ADDRESSING_MODE);//Modo LBA addressing
   outb(port + HDD_ERROR_PORT, 0x00);
   outb(port + HDD_SECTORCOUNT_PORT, 1);//Sector count
   outb(port + HDD_SECTORNUMBER_PORT, (uint8)LBA);//Sector to read
   outb(port + HDD_CYLINDERLOW_PORT, (uint8)(LBA >> 8));//Cylinder low
   outb(port + HDD_CYLINDERHIGH_PORT, (uint8)(LBA >> 16));//Cylinder high
   outb(port + HDD_COMMAND_PORT, HDD_SINGLEREAD_COMMAND);//Read Sector(s) command
   
   printf("Reading bytes...\n");
   while ((inb(port+7)&0x08)!=0x08) ; // 0x08 <-- wait until DRQ bit is set : Data ReQuest bit
   while(teller != 256){
      te  = inw(0x1F0);
      readar[teller*2] = (unsigned char) te;
      readar[(teller*2)+1] = (unsigned char) (te>>8);
	  teller++; 
      while ((inb(port+7)&0x80)==0x80) ; //wait until BUS BUSY bit to be cleared
      while ((inb(port+7)&0x40)!=0x40) ; // wait for DRIVE READY bit to be set
   }
   while ((inb(port+7)&0x80)==0x80) ; //wait until BUS BUSY bit to be cleared
   while ((inb(port+7)&0x40)!=0x40) ; // wait for DRIVE READY bit to be set
}
void write(uint32 LBA){
  
   unsigned short port = 0x1F0;
   int teller = 0;
   outb(port + HDD_DRIVE_PORT, HDD_ADDRESSING_MODE);//LBA addressing
   outb(port + HDD_ERROR_PORT, 0x00);
   outb(port + HDD_SECTORCOUNT_PORT, 1);//Sector count
   outb(port + HDD_SECTORNUMBER_PORT, (uint8)LBA);//Sector to read
   outb(port + HDD_CYLINDERLOW_PORT, (uint8)(LBA >> 8));//Cylinder low
   outb(port + HDD_CYLINDERHIGH_PORT, (uint8)(LBA >> 16));//Cylinder high
   outb(port + HDD_COMMAND_PORT, HDD_SINGLEWRITE_COMMAND);//Write Sector(s) command
   printf("Writing bytes\n");
   while(teller != 256){
      while ((inb(port+7)&0x40)!=0x40) ; // wait for DRIVE READY bit to be set
      outw(0x1F0, (unsigned short)writear[teller*2]+(writear[(teller*2)+1]<<8));
      teller++;
       while ((inb(port+7)&0x80)==0x80) ; //wait until BUS BUSY bit to be cleared
        outb(0x1F0 + HDD_COMMAND_PORT, HDD_COMMAND_FLUSH);
     
   }
   while ((inb(port+7)&0x80)==0x80) ; //wait until BUS BUSY bit to be cleared
   while ((inb(port+7)&0x40)!=0x40) ; // wait for DRIVE READY bit to be set


the defines are higher in the code obviously.

#define HDD_PRIMARY_CONTROLLER 0x1F0

#define HDD_SECONDARY_CONTROLLER 0x170

#define HDD_PRIMARY_ALTERNATE_STATUS 0x3F6
#define HDD_SECONDARY_ALTERNATE_STATUS 0x376

#define HDD_DATA_PORT      0x000
#define HDD_ERROR_PORT      0x001
#define HDD_SECTORCOUNT_PORT   0x002
#define HDD_SECTORNUMBER_PORT   0x003
#define HDD_CYLINDERLOW_PORT   0x004
#define HDD_CYLINDERHIGH_PORT   0x005
#define HDD_DRIVE_PORT      0x006
#define HDD_COMMAND_PORT   0x007

#define HDD_COMMAND_FLUSH   0xE7
#define HDD_SINGLEREAD_COMMAND   0x20
#define HDD_SINGLEWRITE_COMMAND 0x30

#define HDD_ADDRESSING_MODE   0xE0  

}

Re: pata read write

Posted: Tue Nov 27, 2012 12:02 am
by bewing
I think that there are 4 bits that you are forgetting to OR onto your CYLINDER_HIGH value. The ATA_PIO_Mode article may help you.

Re: pata read write

Posted: Sun Dec 02, 2012 9:27 am
by har
I have in virtualbox added a drive as slave.
If I set the slavebit to 1, I get garbage including 9.1 (master is 5.1). I think both drives are read in sector 0 only.
I think I need a delay somewhere in both read and write functions, I read about it in the wiki.
:idea: But how do you make a delay?
I'm from the microcontroller world.
Please in C, if not possible then assembler.