quinn-os/hd.c

159 lines
3.8 KiB
C

#include "pata.h"
#include "hd.h"
#include "vfs.h"
#include "memory.h"
#include "string.h"
struct hd_dev **hds;
unsigned char hd_count = 0;
int init_hd(struct ide_dev *ide) {
int i;
int j;
int k;
struct hd_dev *tmp_hd;
char *buffer;
struct partition_table *part;
char name[8];
struct vfs_device_t *hd_vdev;
int fstry;
buffer = (char *)malloc(512);
for (i=0;i<4;i++) {
if (ide->ide_devices[i].reserved == 1) {
if (ide->ide_devices[i].type == IDE_ATA) {
ide_read_sectors(ide, i, 1, 0, 0x10, (unsigned int)buffer);
for (j=0;j<4;j++) {
part = (struct partition_table *)(buffer + (0x1be + (j * 16)));
if (part->type == 0x1 || part->type == 0x4 || part->type == 0x6 || part->type == 0xb || part->type == 0xc || part->type == 0xe || part->type == 0xf || part->type == 0x83) {
tmp_hd = (struct hd_dev *)malloc(sizeof(struct hd_dev));
tmp_hd->ide_dev = ide;
tmp_hd->part = j;
tmp_hd->part_offset = part->relative_sector;
tmp_hd->part_len = part->total_sectors;
tmp_hd->drive = i;
if (hd_count == 0) {
hds = (struct hd_dev **)malloc(sizeof(struct hd_dev *));
} else {
hds = (struct hd_dev **)realloc(hds, sizeof(struct hd_dev *) * (hd_count + 1));
}
hds[hd_count] = tmp_hd;
strcpy(name, "disk");
k = hd_count;
if ((hd_count / 100) > 0) {
name[4] = (k / 100) + '0';
k = k % 100;
name[5] = (k / 10) + '0';
k = k % 10;
name[6] = k + '0';
name[7] = '\0';
} else if ((hd_count / 10) > 0) {
name[4] = (k / 10) + '0';
k = k % 10;
name[5] = k + '0';
name[6] = '\0';
} else {
name[4] = k + '0';
name[5] = '\0';
}
hd_count++;
hd_vdev = (void *)0;
fstry = 1;
while (hd_vdev == (void *)0 && fstry < 4) {
hd_vdev = vfs_register_device(0x100 + hd_count - 1, name, fstry);
fstry++;
}
}
}
}
}
}
free(buffer);
}
void hd_write_block(int hd, unsigned int blockno, char *source, unsigned int blocksize) {
if (hd < 0 || hd >= hd_count) {
return;
}
int count = blocksize / 512;
int lba = (blockno * count) + hds[hd]->part_offset;
if ((blockno * count) + count > hds[hd]->part_len) {
return;
}
ide_write_sectors(hds[hd]->ide_dev, hds[hd]->drive, count, lba, 0x10, (unsigned int)source);
}
char *hd_read_block(int hd, unsigned int blockno, char *dest, unsigned int blocksize) {
if (hd < 0 || hd >= hd_count) {
return (void *)0;
}
int count = blocksize / 512;
int lba = (blockno * count) + hds[hd]->part_offset;
if ((blockno * count) + count > hds[hd]->part_len) {
return (void *)0;
}
ide_read_sectors(hds[hd]->ide_dev, hds[hd]->drive, count, lba, 0x10, (unsigned int)dest);
return dest;
}
void hd_write_blocks(int hd, unsigned int blockstart, unsigned int blockcount, char *source, unsigned int blocksize) {
if (hd < 0 || hd >= hd_count) {
return;
}
int blocks;
int count = (blocksize * blockcount) / 512;
blocks = count;
while (blockstart * (blocksize / 512) + blocks > hds[hd]->part_len) {
blocks--;
if (blocks <= 0) {
return;
}
}
ide_write_sectors(hds[hd]->ide_dev, hds[hd]->drive, blocks, (blockstart * (blocksize / 512) + hds[hd]->part_offset), 0x10, (unsigned int)source);
return;
}
int hd_read_blocks(int hd, unsigned int blockstart, unsigned int blockcount, char *dest, unsigned int blocksize) {
if (hd < 0 || hd >= hd_count) {
return 0;
}
int blocks;
int count = (blocksize * blockcount) / 512;
blocks = count;
while (blockstart * (blocksize / 512) + blocks > hds[hd]->part_len) {
blocks--;
if (blocks <= 0) {
return 0;
}
}
ide_read_sectors(hds[hd]->ide_dev, hds[hd]->drive, blocks, (blockstart * (blocksize / 512) + hds[hd]->part_offset), 0x10, (unsigned int)dest);
return blocks;
}