159 lines
3.8 KiB
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;
|
|
}
|