aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/fs/ata_pio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/fs/ata_pio.c')
-rw-r--r--src/kernel/fs/ata_pio.c221
1 files changed, 119 insertions, 102 deletions
diff --git a/src/kernel/fs/ata_pio.c b/src/kernel/fs/ata_pio.c
index ef9a23e..1786e66 100644
--- a/src/kernel/fs/ata_pio.c
+++ b/src/kernel/fs/ata_pio.c
@@ -4,122 +4,139 @@
struct ata_interface *new_ata(uint8_t master, uint16_t port_base)
{
- struct ata_interface *ret = (struct ata_interface *) kmalloc(sizeof(struct ata_interface));
-
- ret->master = master;
- ret->data_port = port_base;
- ret->error_port = (uint16_t) (port_base + 0x1);
- ret->sector_count_port = (uint16_t) (port_base + 0x2);
- ret->lba_low_port = (uint16_t) (port_base + 0x3);
- ret->lba_mid_port = (uint16_t) (port_base + 0x4);
- ret->lba_high_port = (uint16_t) (port_base + 0x5);
- ret->device_port = (uint16_t) (port_base + 0x6);
- ret->command_port = (uint16_t) (port_base + 0x7);
- ret->control_port = (uint16_t) (port_base + 0x206);
-
- return ret;
+ struct ata_interface *ret = (struct ata_interface *)kmalloc(sizeof(struct ata_interface));
+
+ ret->master = master;
+ ret->data_port = port_base;
+ ret->error_port = (uint16_t)(port_base + 0x1);
+ ret->sector_count_port = (uint16_t)(port_base + 0x2);
+ ret->lba_low_port = (uint16_t)(port_base + 0x3);
+ ret->lba_mid_port = (uint16_t)(port_base + 0x4);
+ ret->lba_high_port = (uint16_t)(port_base + 0x5);
+ ret->device_port = (uint16_t)(port_base + 0x6);
+ ret->command_port = (uint16_t)(port_base + 0x7);
+ ret->control_port = (uint16_t)(port_base + 0x206);
+
+ return ret;
}
uint8_t ata_identify(struct ata_interface *interface, uint16_t *ret_data)
{
- outb(interface->device_port, (uint8_t) (interface->master ? 0xA0 : 0xB0));
- outb(interface->control_port, 0);
-
- outb(interface->device_port, 0xA0);
- uint8_t status = inb(interface->command_port);
- if (status == 0xFF) return 1;
-
- outb(interface->device_port, (uint8_t) (interface->master ? 0xA0 : 0xB0));
- outb(interface->sector_count_port, 0);
- outb(interface->lba_low_port, 0);
- outb(interface->lba_mid_port, 0);
- outb(interface->lba_high_port, 0);
- outb(interface->command_port, 0xEC); // Identify command
-
- status = inb(interface->command_port);
- if (!status) return 1;
-
- while (((status & 0x80) == 0x80) && ((status & 0x01) != 0x01)) {
- status = inb(interface->command_port);
- }
-
- if (status & 0x01) return 1;
-
- for (int i = 0; i < 256; i++) ret_data[i] = inw(interface->data_port);
- return 0;
+ outb(interface->device_port, (uint8_t)(interface->master ? 0xA0 : 0xB0));
+ outb(interface->control_port, 0);
+
+ outb(interface->device_port, 0xA0);
+ uint8_t status = inb(interface->command_port);
+ if (status == 0xFF)
+ return 1;
+
+ outb(interface->device_port, (uint8_t)(interface->master ? 0xA0 : 0xB0));
+ outb(interface->sector_count_port, 0);
+ outb(interface->lba_low_port, 0);
+ outb(interface->lba_mid_port, 0);
+ outb(interface->lba_high_port, 0);
+ outb(interface->command_port, 0xEC); // Identify command
+
+ status = inb(interface->command_port);
+ if (!status)
+ return 1;
+
+ while (((status & 0x80) == 0x80) && ((status & 0x01) != 0x01)) {
+ status = inb(interface->command_port);
+ }
+
+ if (status & 0x01)
+ return 1;
+
+ for (int i = 0; i < 256; i++)
+ ret_data[i] = inw(interface->data_port);
+ return 0;
}
uint8_t *ata_read28(struct ata_interface *interface, uint32_t sector)
{
- if (sector > 0x0FFFFFFF) return 0;
-
- outb(interface->device_port, (uint8_t) ((interface->master ? 0xE0 : 0xF0) | ((sector & 0x0F000000) >> 24)));
-
- uint8_t status = 0;
- for (int i = 0; i < 5; i++) status = inb(interface->command_port);
- if (status == 0xFF) return 0;
-
- outb(interface->error_port, 0);
- outb(interface->sector_count_port, 1);
- outb(interface->lba_low_port, (uint8_t) (sector & 0x000000FF));
- outb(interface->lba_mid_port, (uint8_t) ((sector & 0x0000FF00) >> 8));
- outb(interface->lba_high_port, (uint8_t) ((sector & 0x00FF0000) >> 16));
- outb(interface->command_port, 0x20); // Read command
-
- status = inb(interface->command_port);
- while ((status & 0x80) && !(status & 0x01)) status = inb(interface->command_port);
-
- uint8_t *ret = (uint8_t *) kmalloc(BYTES_PER_SECTOR);
- for (int i = 0; i < BYTES_PER_SECTOR; i += 2) {
- uint16_t data = inw(interface->data_port);
- ret[i] = (uint8_t) (data & 0xFF);
- ret[i + 1] = (uint8_t) ((data >> 8) & 0xFF);
- }
- return ret;
+ if (sector > 0x0FFFFFFF)
+ return 0;
+
+ outb(interface->device_port,
+ (uint8_t)((interface->master ? 0xE0 : 0xF0) | ((sector & 0x0F000000) >> 24)));
+
+ uint8_t status = 0;
+ for (int i = 0; i < 5; i++)
+ status = inb(interface->command_port);
+ if (status == 0xFF)
+ return 0;
+
+ outb(interface->error_port, 0);
+ outb(interface->sector_count_port, 1);
+ outb(interface->lba_low_port, (uint8_t)(sector & 0x000000FF));
+ outb(interface->lba_mid_port, (uint8_t)((sector & 0x0000FF00) >> 8));
+ outb(interface->lba_high_port, (uint8_t)((sector & 0x00FF0000) >> 16));
+ outb(interface->command_port, 0x20); // Read command
+
+ status = inb(interface->command_port);
+ while ((status & 0x80) && !(status & 0x01))
+ status = inb(interface->command_port);
+
+ uint8_t *ret = (uint8_t *)kmalloc(BYTES_PER_SECTOR);
+ for (int i = 0; i < BYTES_PER_SECTOR; i += 2) {
+ uint16_t data = inw(interface->data_port);
+ ret[i] = (uint8_t)(data & 0xFF);
+ ret[i + 1] = (uint8_t)((data >> 8) & 0xFF);
+ }
+ return ret;
}
uint8_t ata_write28(struct ata_interface *interface, uint32_t sector, const uint8_t *contents)
{
- if (sector > 0x0FFFFFFF) return 1;
- cli();
-
- outb(interface->device_port, (uint8_t) ((interface->master ? 0xE0 : 0xF0) | ((sector & 0x0F000000) >> 24)));
-
- uint8_t status = 0;
- for (int i = 0; i < 5; i++) status = inb(interface->command_port);
- if (status == 0xFF) return 1;
-
- outb(interface->error_port, 0);
- outb(interface->sector_count_port, 1);
- outb(interface->lba_low_port, (uint8_t) (sector & 0x000000FF));
- outb(interface->lba_mid_port, (uint8_t) ((sector & 0x0000FF00) >> 8));
- outb(interface->lba_high_port, (uint8_t) ((sector & 0x00FF0000) >> 16));
- outb(interface->command_port, 0x30); // Write command
-
- while ((status & 0x80) || !(status & 0x08)) status = inb(interface->command_port);
-
- if (status & (0x01 || 0x20)) return 2;
-
- for (int i = 0; i < BYTES_PER_SECTOR; i += 2) {
- uint16_t data = contents[i];
- data |= ((uint16_t) contents[i + 1]) << 8;
- outw(interface->data_port, data);
- }
-
- outb(interface->command_port, 0xE7); // Flush command
-
- for (int i = 0; i < 5; i++) status = inb(interface->command_port);
- if (!status) return 3;
-
- while ((status & 0x80) && !(status & 0x01)) {
- status = inb(interface->command_port);
- }
-
- return 0;
+ if (sector > 0x0FFFFFFF)
+ return 1;
+ cli();
+
+ outb(interface->device_port,
+ (uint8_t)((interface->master ? 0xE0 : 0xF0) | ((sector & 0x0F000000) >> 24)));
+
+ uint8_t status = 0;
+ for (int i = 0; i < 5; i++)
+ status = inb(interface->command_port);
+ if (status == 0xFF)
+ return 1;
+
+ outb(interface->error_port, 0);
+ outb(interface->sector_count_port, 1);
+ outb(interface->lba_low_port, (uint8_t)(sector & 0x000000FF));
+ outb(interface->lba_mid_port, (uint8_t)((sector & 0x0000FF00) >> 8));
+ outb(interface->lba_high_port, (uint8_t)((sector & 0x00FF0000) >> 16));
+ outb(interface->command_port, 0x30); // Write command
+
+ while ((status & 0x80) || !(status & 0x08))
+ status = inb(interface->command_port);
+
+ if (status & (0x01 || 0x20))
+ return 2;
+
+ for (int i = 0; i < BYTES_PER_SECTOR; i += 2) {
+ uint16_t data = contents[i];
+ data |= ((uint16_t)contents[i + 1]) << 8;
+ outw(interface->data_port, data);
+ }
+
+ outb(interface->command_port, 0xE7); // Flush command
+
+ for (int i = 0; i < 5; i++)
+ status = inb(interface->command_port);
+ if (!status)
+ return 3;
+
+ while ((status & 0x80) && !(status & 0x01)) {
+ status = inb(interface->command_port);
+ }
+
+ return 0;
}
uint8_t ata_clear28(struct ata_interface *interface, uint32_t sector)
{
- uint8_t empty_sector[512] = {0};
- return ata_write28(interface, sector, empty_sector);
+ uint8_t empty_sector[512] = { 0 };
+ return ata_write28(interface, sector, empty_sector);
}