954,132 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Reading from hard disk

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?

mmiikkee12
Posting Whiz in Training
274 posts since Oct 2004
Reputation Points: 17
Solved Threads: 5
 

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);
mmiikkee12
Posting Whiz in Training
274 posts since Oct 2004
Reputation Points: 17
Solved Threads: 5
 

http://c-faq.com/struct/padding.html
How you specify a packed structure depends on your compiler.

Salem
Posting Sage
Team Colleague
11,531 posts since Dec 2005
Reputation Points: 5,862
Solved Threads: 953
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You