|
|
|
@ -1,9 +1,17 @@
|
|
|
|
|
#include "alloc.h"
|
|
|
|
|
#include "ata.h"
|
|
|
|
|
#include "io.h"
|
|
|
|
|
#include "irq.h"
|
|
|
|
|
#include "kernel.h"
|
|
|
|
|
#include "klibc.h"
|
|
|
|
|
#include "list.h"
|
|
|
|
|
#include "thread.h"
|
|
|
|
|
|
|
|
|
|
#define PART_TABLE_OFFSET 0x1BE
|
|
|
|
|
|
|
|
|
|
static struct ata_partition *partitions;
|
|
|
|
|
static int nextPartitionId = 0;
|
|
|
|
|
|
|
|
|
|
// from
|
|
|
|
|
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ata/ns-ata-_identify_device_data
|
|
|
|
|
struct _IDENTIFY_DEVICE_DATA {
|
|
|
|
@ -378,6 +386,19 @@ struct _IDENTIFY_DEVICE_DATA {
|
|
|
|
|
uint16_t CheckSum : 8;
|
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
|
|
struct part_table_entry{
|
|
|
|
|
uint32_t status:8;
|
|
|
|
|
uint32_t head_start:8;
|
|
|
|
|
uint32_t sector_start:6;
|
|
|
|
|
uint32_t cyl_start:10;
|
|
|
|
|
uint32_t type:8;
|
|
|
|
|
uint32_t head_end:8;
|
|
|
|
|
uint32_t sector_end:6;
|
|
|
|
|
uint32_t cyl_end:10;
|
|
|
|
|
uint32_t lba;
|
|
|
|
|
uint32_t size;
|
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
|
|
static struct ata_controller controllers[MAX_ATA_CONTROLLER] = {{
|
|
|
|
|
.id = 0,
|
|
|
|
|
.base = 0x1F0,
|
|
|
|
@ -455,8 +476,91 @@ int ATAGetDeviceInfo(struct ata_device *dev)
|
|
|
|
|
dev->sectors = deviceInfo->NumSectorsPerTrack;
|
|
|
|
|
printf("Disk Detected[%d][%d]: %d Ko\n", ctl->id, dev->id,
|
|
|
|
|
(dev->heads * dev->cyls * dev->sectors * DISK_SECTOR_SIZE) / 1024);
|
|
|
|
|
ATAReadPartition(dev);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
const char *partTypeToStr(unsigned int type)
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
|
|
|
|
case PART_TYPE_EXTENDED:
|
|
|
|
|
return "Extended";
|
|
|
|
|
case PART_TYPE_FAT16:
|
|
|
|
|
case PART_TYPE_FAT16_LBA:
|
|
|
|
|
return "FAT16";
|
|
|
|
|
case PART_TYPE_FAT32:
|
|
|
|
|
case PART_TYPE_FAT32_LBA:
|
|
|
|
|
return "FAT32";
|
|
|
|
|
case PART_TYPE_LINUX_SWAP:
|
|
|
|
|
return "Linux Swap";
|
|
|
|
|
case PART_TYPE_LINUX:
|
|
|
|
|
return "Linux";
|
|
|
|
|
default:
|
|
|
|
|
return "Unknown";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ata_partition *ATAGetPartition(int id)
|
|
|
|
|
{
|
|
|
|
|
struct ata_partition *part;
|
|
|
|
|
int count;
|
|
|
|
|
list_foreach(partitions, part, count)
|
|
|
|
|
{
|
|
|
|
|
if (part->id == id)
|
|
|
|
|
return part;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ata_partition *ATAPartitionCreate(uint type, uint size, uint32_t lba,
|
|
|
|
|
struct ata_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct ata_partition *part =
|
|
|
|
|
(struct ata_partition *)malloc(sizeof(struct ata_partition));
|
|
|
|
|
if (part == NULL)
|
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
|
|
part->id = nextPartitionId++;
|
|
|
|
|
part->type = type;
|
|
|
|
|
part->size = size;
|
|
|
|
|
part->lba = lba;
|
|
|
|
|
part->device = dev;
|
|
|
|
|
|
|
|
|
|
uint32_t flags;
|
|
|
|
|
disable_IRQs(flags);
|
|
|
|
|
|
|
|
|
|
list_add_tail(partitions, part);
|
|
|
|
|
restore_IRQs(flags);
|
|
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
return part;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ATAReadPartition(struct ata_device *dev)
|
|
|
|
|
{
|
|
|
|
|
char buf[DISK_SECTOR_SIZE];
|
|
|
|
|
int ret = ATAReadSector(dev, 0, 1, buf);
|
|
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
struct part_table_entry *parts = (struct part_table_entry *)(buf + PART_TABLE_OFFSET);
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
if (parts[i].size == 0)
|
|
|
|
|
continue;
|
|
|
|
|
if (parts[i].type == PART_TYPE_EXTENDED) {
|
|
|
|
|
printf("Unsupported Partition extended\n");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
printf("Got partition %d type %s(0x%x) size %d kb lba 0x%x\n", i,
|
|
|
|
|
partTypeToStr(parts[i].type), parts[i].type, (parts[i].size * DISK_SECTOR_SIZE) >> 10, parts[i].lba);
|
|
|
|
|
ret++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ATADetectController(struct ata_controller *controller)
|
|
|
|
|
{
|
|
|
|
@ -488,12 +592,20 @@ int ATADetectController(struct ata_controller *controller)
|
|
|
|
|
|
|
|
|
|
int ATAInit()
|
|
|
|
|
{
|
|
|
|
|
list_init(partitions);
|
|
|
|
|
for (uint i = 0; i < MAX_ATA_CONTROLLER; i++) {
|
|
|
|
|
ATADetectController(&controllers[i]);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ATAReadPartitionSector(struct ata_partition *part, int offset, uint nbSector, void *buf)
|
|
|
|
|
{
|
|
|
|
|
int lba = part->lba + offset;
|
|
|
|
|
|
|
|
|
|
return ATAReadSector(part->device, lba, nbSector, buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ATAReadSector(struct ata_device *dev, int lba, uint nb_sector, void *buf)
|
|
|
|
|
{
|
|
|
|
|
struct ata_controller *ctl = dev->ctl;
|
|
|
|
|