First let me point out that this is not homework, it's just something I'm doing because I'm bored ;-)
I'm trying to get my little hobby operating system to read from the hard disk. So far all I can get is the byte FF (255). I've tested this in both Bochs and QEMU and the same thing happens. Here's the hard disk reading part of my code:

#include <harddisk.h>
#include <types.h>

#define CMD_READ	0x20
#define CMD_WRITE	0x30
// NR = no retry
#define CMD_READ_NR	0x21
#define CMD_WRITE_NR	0x31

byte *read_sector(uint_8 drivenum, uint_8 sector, uint_16 cylinder, uint_8 *buffer)
{
	uint_8 drive;
	uint_16 port_base;
	// Yes, I know I could use some binary operations.
	// This is a lot easier to read though.
	switch (drivenum)
	{
		case 0:
			drive = 0xA0;
			port_base = (uint_8)0x1f0;
			break;
		case 1:
			drive = 0xB0;
			port_base = (uint_8)0x1f0;
			break;
		case 2:
			drive = 0xA0;
			port_base = (uint_8)0x170;
			break;
		case 3:
			drive = 0xB0;
			port_base = (uint_8)0x170;
		// If I ever get bored enough to add them, 0x1e8 for
		// ide2 and 0x168 for ide3.
	}
	
	// send some info to the IDE controller
	// drive to read from
	outportb(port_base + 6, drive);
	// just one sector
	outportb(port_base + 2, 1);
	// sector
	outportb(port_base + 3, sector);
	// extract low and high bytes from cylinder number
	uint_8 cyl_low = cylinder & 0xFF;
	uint_8 cyl_high = (cylinder & 0xFF00) >> 8;
	// ...then send them to the IDE controller
	outportb(port_base + 4, cyl_low);
	outportb(port_base + 5, cyl_high);
	// and now send the command
	outportb(port_base + 7, CMD_READ);

	

	// now read the data in from the buffer
	int i;
	for (i = 0; i < 256; i++)
	{
		buffer[i] = inportw(port_base);
		// debugging
		printf("%x\t| %d\t| %c\n", buffer[i], buffer[i], buffer[i]);
	}
	return buffer;
}

I'm calling it like this:

uint_8 *data = (uint_8 *)0x300000;
	read_sector(0, 1, 1, data);

The only thing the debug printf will print is "ff | 255 | ". Any ideas?

OK, just got that working. Turns out I was reading into the buffer wrong. Now I have another problem. This should be 512 bytes, I added it up myself. But sizeof() gives me 516, and I get some random, obviously incorrect values when I print out the partition info. (A byte with only the top bit set is never 192.) Any ideas?

typedef struct
{
    uint_8 active;
    uint_8 start_head;
    uint_8 start_sector;
    uint_8 start_cylinder;
    uint_8 partition_type;
    uint_8 end_head;
    uint_8 end_sector;
    uint_8 end_cylinder;
    uint_32 start_lba;
    uint_32 end_lba;
} partition;

typedef struct
{
    uint_8 useless_data[446];
    partition partitions[4];
    uint_16 signature;
} partition_table;

void *read_sector(uint_8 drivenum, uint_16 cylinder, uint_8 sector, uint_8 head, uint_8 *buffer);

Edited 3 Years Ago by Dani: Formatting fixed

This article has been dead for over six months. Start a new discussion instead.