Non-PCI Probing Of ATA/IDE
Posted: Tue Aug 21, 2007 6:46 pm
Non-PCI Probing Of ATA/IDE
I have spent about a day in total tinkering with the ATA driver's disk detection routine in the Mattise kernel. It was actual a little tricky, and I am sure others have had problem.
Since I got it working I wanting to share it, and wondering if it actually works well with different hardware and maybe some of your views on better ways to do this.
The idea is to send a value which represents the head and drive to select on a controller, and check for the appropriate values.
Where here we have some defines and a data structure holding all the default controller addresses.
What I am doing here is going through each Tata_ctl_info structure. While in each info structure I check both controller base addresses. I simply issue a bit pattern to the controller's correct port using the base port for a drive and head selection (ATA_DRIVEHEAD). Then I delay, and finally read the status for a correct determination.
The trick was not just to check the ready bit, but also the:
I have spent about a day in total tinkering with the ATA driver's disk detection routine in the Mattise kernel. It was actual a little tricky, and I am sure others have had problem.
Since I got it working I wanting to share it, and wondering if it actually works well with different hardware and maybe some of your views on better ways to do this.
The idea is to send a value which represents the head and drive to select on a controller, and check for the appropriate values.
Where here we have some defines and a data structure holding all the default controller addresses.
Code: Select all
#define ATA_DATA 0
#define ATA_ERROR 1
#define ATA_SECTORCOUNT 2
#define ATA_SECTORNUMBER 3
#define ATA_CYLINDERLOW 4
#define ATA_CYLINDERHIGH 5
#define ATA_DRIVEHEAD 6
#define ATA_STATUS 7
#define ATA_COMMAND 8
typedef struct{
unsigned short base[2];
}Tata_ctl_info;
static Tata_ctl_info ata_ctl_info[] = {
{ .base = {0x1f0, 0x3f0} },
{ .base = {0x170, 0x370} },
{ .base = {0x1e8, 0x3e0} },
{ .base = {0x168, 0x360} }
};
Code: Select all
for(drvi = 0, x = 0; x < (sizeof(ata_ctl_info) / sizeof(Tata_ctl_info)); ++x)
{
for(z = 0; z < 2; ++z)
{
for(y = 0; y < 2; ++y)
{
outportb(ata_ctl_info[x].base[z] + ATA_DRIVEHEAD, (0xa0 | (y << 4)));
delay(ATA_DELAY_NORMAL);
printf("[ATA] ctl:%x alt:%x drv:%x (%02x)\n",
x, z, y, inportb(ata_ctl_info[x].base[z] + ATA_STATUS));
delay(ATA_DELAY_NORMAL);
if((((unsigned char)inportb(ata_ctl_info[x].base[z] + ATA_STATUS) & (0x40 | 0x10 | 0x20 | 0x01)) == 0x50))
{
printf("[ATA] present ata/%1x:%1x:%1x\n", x, z, y);
}
}
}
}
- drive seek completion bit.(TRUE)
- write fault. (FALSE)
- previous command was error. (FALSE)