PCI IDE Controller: Difference between revisions

m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
m (Bot: Replace deprecated source tag with syntaxhighlight)
m (Bot: Replace deprecated source tag with syntaxhighlight)
Line 253:
When we read a register in a channel, like STATUS Register, it is easy to execute:
 
<sourcesyntaxhighlight lang="c">
ide_read(channel, ATA_REG_STATUS);
 
Line 272:
return result;
}
</syntaxhighlight>
</source>
 
We also need a function for writing to registers:
<sourcesyntaxhighlight lang="c">
void ide_write(unsigned char channel, unsigned char reg, unsigned char data) {
if (reg > 0x07 && reg < 0x0C)
Line 290:
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
}
</syntaxhighlight>
</source>
 
To read the identification space, we should read the Data Register as a double word 128 times. We can then copy them to our buffer.
 
<sourcesyntaxhighlight lang="c">
void ide_read_buffer(unsigned char channel, unsigned char reg, unsigned int buffer,
unsigned int quads) {
Line 316:
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
}
</syntaxhighlight>
</source>
 
When we send a command, we should wait for 400 nanosecond, then read the Status port. If the Busy bit is on, we should read the status port again until the Busy bit is 0; then we can read the results of the command. This operation is called "Polling". We can also use IRQs instead of polling.
Line 322:
After many commands, if the Device Fault bit is set, there is a failure; if DRQ is not set, there is an error. If the ERR bit is set, there is an error which is described in Error port.
 
<sourcesyntaxhighlight lang="c">
unsigned char ide_polling(unsigned char channel, unsigned int advanced_check) {
 
Line 359:
 
}
</syntaxhighlight>
</source>
 
If there is an error, we have a function which prints errors on screen:
Line 417:
Notice that if bit 4 in HDDEVSEL is set to 1, we are selecting the slave drive, if set to 0, we are selecting the master drive.
 
<sourcesyntaxhighlight lang="c">
// 3- Detect ATA-ATAPI Devices:
for (i = 0; i < 2; i++)
Line 498:
}
}
</syntaxhighlight>
</source>
 
== Read/Write From ATA Drive ==
Line 677:
Lets write all these information to the register, while the obsolete bits are set (0xA0):
 
<sourcesyntaxhighlight lang="c">
// (IV) Select Drive from the controller;
if (lba_mode == 0)
Line 683:
else
ide_write(channel, ATA_REG_HDDEVSEL, 0xE0 | (slavebit << 4) | head); // Drive & LBA
</syntaxhighlight>
</source>
 
Let's write the parameters to registers:
Line 740:
Notice that after writing, we should execute the CACHE FLUSH command, and we should poll after it, but without checking for errors.
 
<sourcesyntaxhighlight lang="c">
if (dma)
if (direction == 0);
Line 775:
return 0; // Easy, isn't it?
}
</syntaxhighlight>
</source>
 
== Reading from an ATAPI Drive ==
Line 852:
Now we should select the drive:
 
<sourcesyntaxhighlight lang="c">
// (II): Select the drive:
// ------------------------------------------------------------------
ide_write(channel, ATA_REG_HDDEVSEL, slavebit << 4);
</syntaxhighlight>
</source>
 
400 nanoseconds delay after this select is a good idea:
 
<sourcesyntaxhighlight lang="c">
// (III): Delay 400 nanoseconds for select to complete:
// ------------------------------------------------------------------
for(int i = 0; i < 4; i++)
ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port wastes 100ns.
</syntaxhighlight>
</source>
 
<syntaxhighlight lang="c">
Line 900:
Here we cannot poll. We should wait for an IRQ, then read the sectors. These two operations should be repeated for each sector.
 
<sourcesyntaxhighlight lang="c">
// (IX): Receiving Data:
// ------------------------------------------------------------------
Line 913:
edi += (words * 2);
}
</syntaxhighlight>
</source>
 
Now we should wait for an IRQ and poll until the Busy and DRQ bits are clear:
Line 932:
 
== Reading from an ATA/ATAPI Drive ==
<sourcesyntaxhighlight lang="c">
void ide_read_sectors(unsigned char drive, unsigned char numsects, unsigned int lba,
unsigned short es, unsigned int edi) {
Line 958:
}
// package[0] is an entry of an array. It contains the Error Code.
</syntaxhighlight>
</source>
 
== Writing to an ATA drive ==
Line 987:
 
== Ejecting an ATAPI Drive ==
<sourcesyntaxhighlight lang="c">
void ide_atapi_eject(unsigned char drive) {
unsigned int channel = ide_devices[drive].Channel;
Line 1,053:
}
}
</syntaxhighlight>
</source>
 
When this method is invoked, the optical device on the given channel is ejected.