pata read write

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
User avatar
har
Posts: 4
Joined: Sun Jan 29, 2012 4:36 am

pata read write

Post 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  

}
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: pata read write

Post 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.
User avatar
har
Posts: 4
Joined: Sun Jan 29, 2012 4:36 am

Re: pata read write

Post 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.
Post Reply