|
|
|
|
@@ -60,12 +60,21 @@
|
|
|
|
|
#define ATA_IDENT_COMMANDSETS 164
|
|
|
|
|
#define ATA_IDENT_MAX_LBA_EXT 200
|
|
|
|
|
|
|
|
|
|
#define ATA_CAP_LBA 0x200
|
|
|
|
|
|
|
|
|
|
#define ATA_LBA28_MAX 0x10000000
|
|
|
|
|
|
|
|
|
|
#define ATA_HDDDEVSEL_CHS 0b00000000
|
|
|
|
|
#define ATA_HDDDEVSEL_LBA 0b01000000
|
|
|
|
|
#define ATA_HDDDEVSEL_DEFAULT 0b10100000
|
|
|
|
|
|
|
|
|
|
#define IDE_ATA 0x00
|
|
|
|
|
#define IDE_ATAPI 0x01
|
|
|
|
|
|
|
|
|
|
#define ATA_MASTER 0x00
|
|
|
|
|
#define ATA_SLAVE 0x01
|
|
|
|
|
|
|
|
|
|
// base
|
|
|
|
|
#define ATA_REG_DATA 0x00
|
|
|
|
|
#define ATA_REG_ERROR 0x01
|
|
|
|
|
#define ATA_REG_FEATURES 0x01
|
|
|
|
|
@@ -76,13 +85,17 @@
|
|
|
|
|
#define ATA_REG_HDDEVSEL 0x06
|
|
|
|
|
#define ATA_REG_COMMAND 0x07
|
|
|
|
|
#define ATA_REG_STATUS 0x07
|
|
|
|
|
#define ATA_REG_SECCOUNT1 0x08
|
|
|
|
|
#define ATA_REG_LBA3 0x09
|
|
|
|
|
#define ATA_REG_LBA4 0x0A
|
|
|
|
|
#define ATA_REG_LBA5 0x0B
|
|
|
|
|
#define ATA_REG_CONTROL 0x0C
|
|
|
|
|
#define ATA_REG_ALTSTATUS 0x0C
|
|
|
|
|
#define ATA_REG_DEVADDRESS 0x0D
|
|
|
|
|
|
|
|
|
|
// ??
|
|
|
|
|
#define ATA_REG_SECCOUNT1 0x12
|
|
|
|
|
#define ATA_REG_LBA3 0x13
|
|
|
|
|
#define ATA_REG_LBA4 0x14
|
|
|
|
|
#define ATA_REG_LBA5 0x15
|
|
|
|
|
|
|
|
|
|
// ctrl
|
|
|
|
|
#define ATA_REG_CONTROL 0x22
|
|
|
|
|
#define ATA_REG_ALTSTATUS 0x22
|
|
|
|
|
#define ATA_REG_DEVADDRESS 0x23
|
|
|
|
|
|
|
|
|
|
// Channels:
|
|
|
|
|
#define ATA_PRIMARY 0x00
|
|
|
|
|
@@ -121,34 +134,50 @@ void ide_write(u8 channel, u8 reg, u8 data);
|
|
|
|
|
|
|
|
|
|
u8 ide_read(u8 channel, u8 reg) {
|
|
|
|
|
u8 result;
|
|
|
|
|
if (reg > 0x07 && reg < 0x0C)
|
|
|
|
|
if (reg & 0x10) {
|
|
|
|
|
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
|
|
|
|
if (reg < 0x08)
|
|
|
|
|
result = port_byte_in(channels[channel].base + reg - 0x00);
|
|
|
|
|
else if (reg < 0x0C)
|
|
|
|
|
result = port_byte_in(channels[channel].base + reg - 0x06);
|
|
|
|
|
else if (reg < 0x0E)
|
|
|
|
|
result = port_byte_in(channels[channel].ctrl + reg - 0x0A);
|
|
|
|
|
else if (reg < 0x16)
|
|
|
|
|
result = port_byte_in(channels[channel].bmide + reg - 0x0E);
|
|
|
|
|
if (reg > 0x07 && reg < 0x0C)
|
|
|
|
|
result = port_byte_in(channels[channel].base + (reg & 0xF));
|
|
|
|
|
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
|
|
|
|
} else if (reg & 0x20) {
|
|
|
|
|
result = port_byte_in(channels[channel].ctrl + (reg & 0xF));
|
|
|
|
|
} else {
|
|
|
|
|
result = port_byte_in(channels[channel].base + reg);
|
|
|
|
|
}
|
|
|
|
|
// if (reg < 0x08)
|
|
|
|
|
// result = port_byte_in(channels[channel].base + reg - 0x00);
|
|
|
|
|
// else if (reg < 0x0C)
|
|
|
|
|
// result = port_byte_in(channels[channel].base + reg - 0x06);
|
|
|
|
|
// else if (reg < 0x0E)
|
|
|
|
|
// result = port_byte_in(channels[channel].ctrl + reg - 0x0A);
|
|
|
|
|
// else if (reg < 0x16)
|
|
|
|
|
// result = port_byte_in(channels[channel].bmide + reg - 0x0E); // todo this case is not handled in new code
|
|
|
|
|
// if (reg > 0x07 && reg < 0x0C)
|
|
|
|
|
// ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ide_write(u8 channel, u8 reg, u8 data) {
|
|
|
|
|
if (reg > 0x07 && reg < 0x0C)
|
|
|
|
|
if (reg & 0x10) {
|
|
|
|
|
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
|
|
|
|
if (reg < 0x08)
|
|
|
|
|
port_byte_out(channels[channel].base + reg - 0x00, data);
|
|
|
|
|
else if (reg < 0x0C)
|
|
|
|
|
port_byte_out(channels[channel].base + reg - 0x06, data);
|
|
|
|
|
else if (reg < 0x0E)
|
|
|
|
|
port_byte_out(channels[channel].ctrl + reg - 0x0A, data);
|
|
|
|
|
else if (reg < 0x16)
|
|
|
|
|
port_byte_out(channels[channel].bmide + reg - 0x0E, data);
|
|
|
|
|
if (reg > 0x07 && reg < 0x0C)
|
|
|
|
|
port_byte_out(channels[channel].base + (reg & 0xF), data);
|
|
|
|
|
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
|
|
|
|
} else if (reg & 0x20) {
|
|
|
|
|
port_byte_out(channels[channel].ctrl + (reg & 0xF), data);
|
|
|
|
|
} else {
|
|
|
|
|
port_byte_out(channels[channel].base + reg, data);
|
|
|
|
|
}
|
|
|
|
|
// if (reg > 0x07 && reg < 0x0C)
|
|
|
|
|
// ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
|
|
|
|
// if (reg < 0x08)
|
|
|
|
|
// port_byte_out(channels[channel].base + reg - 0x00, data);
|
|
|
|
|
// else if (reg < 0x0C)
|
|
|
|
|
// port_byte_out(channels[channel].base + reg - 0x06, data);
|
|
|
|
|
// else if (reg < 0x0E)
|
|
|
|
|
// port_byte_out(channels[channel].ctrl + reg - 0x0A, data);
|
|
|
|
|
// else if (reg < 0x16)
|
|
|
|
|
// port_byte_out(channels[channel].bmide + reg - 0x0E, data); // todo this case is not handled
|
|
|
|
|
// if (reg > 0x07 && reg < 0x0C)
|
|
|
|
|
// ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ide_read_buffer(unsigned char channel, unsigned char reg, unsigned int *buffer, unsigned int quads) {
|
|
|
|
|
@@ -156,26 +185,36 @@ void ide_read_buffer(unsigned char channel, unsigned char reg, unsigned int* buf
|
|
|
|
|
* ESP for all of the code the compiler generates between the inline
|
|
|
|
|
* assembly blocks.
|
|
|
|
|
*/
|
|
|
|
|
if (reg > 0x07 && reg < 0x0C) {
|
|
|
|
|
if (reg & 0x10) {
|
|
|
|
|
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
|
|
|
|
}
|
|
|
|
|
// asm("pushw %es; movw %ds, %ax; movw %ax, %es" : : : "es", "esp");
|
|
|
|
|
if (reg < 0x08) {
|
|
|
|
|
port_double_word_in_repeat(channels[channel].base + reg - 0x00, buffer, quads);
|
|
|
|
|
} else if (reg < 0x0C) {
|
|
|
|
|
port_double_word_in_repeat(channels[channel].base + reg - 0x06, buffer, quads);
|
|
|
|
|
} else if (reg < 0x0E) {
|
|
|
|
|
port_double_word_in_repeat(channels[channel].ctrl + reg - 0x0A, buffer, quads);
|
|
|
|
|
} else if (reg < 0x16) {
|
|
|
|
|
port_double_word_in_repeat(channels[channel].bmide + reg - 0x0E, buffer, quads);
|
|
|
|
|
}
|
|
|
|
|
// asm("popw %es;");
|
|
|
|
|
if (reg > 0x07 && reg < 0x0C) {
|
|
|
|
|
port_double_word_in_repeat(channels[channel].base + (reg & 0xF), buffer, quads);
|
|
|
|
|
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
|
|
|
|
} else if (reg & 0x20) {
|
|
|
|
|
port_double_word_in_repeat(channels[channel].base + (reg & 0xF), buffer, quads);
|
|
|
|
|
} else {
|
|
|
|
|
port_double_word_in_repeat(channels[channel].base + reg, buffer, quads);
|
|
|
|
|
}
|
|
|
|
|
// if (reg > 0x07 && reg < 0x0C) {
|
|
|
|
|
// ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
|
|
|
|
// }
|
|
|
|
|
// this assembly is probably necessary when reading paging
|
|
|
|
|
// asm("pushw %es; movw %ds, %ax; movw %ax, %es" );
|
|
|
|
|
// if (reg < 0x08) {
|
|
|
|
|
// port_double_word_in_repeat(channels[channel].base + reg - 0x00, buffer, quads);
|
|
|
|
|
// } else if (reg < 0x0C) {
|
|
|
|
|
// port_double_word_in_repeat(channels[channel].base + reg - 0x06, buffer, quads);
|
|
|
|
|
// } else if (reg < 0x0E) {
|
|
|
|
|
// port_double_word_in_repeat(channels[channel].ctrl + reg - 0x0A, buffer, quads);
|
|
|
|
|
// } else if (reg < 0x16) {
|
|
|
|
|
// port_double_word_in_repeat(channels[channel].bmide + reg - 0x0E, buffer, quads);
|
|
|
|
|
// }
|
|
|
|
|
// asm("popw %es;");
|
|
|
|
|
// if (reg > 0x07 && reg < 0x0C) {
|
|
|
|
|
// ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned char ide_polling(unsigned char channel, unsigned int advanced_check) {
|
|
|
|
|
unsigned char ide_polling(unsigned char channel, u8 advanced_check) {
|
|
|
|
|
|
|
|
|
|
// (I) Delay 400 nanosecond for BSY to be set:
|
|
|
|
|
// -------------------------------------------------
|
|
|
|
|
@@ -297,14 +336,27 @@ u8 ide_pci_validate(const pci_device *device) {
|
|
|
|
|
return PCI_VALIDATE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8 ide_pci_initialize(pci_device *device) {
|
|
|
|
|
pci_config_write_byte(device->bus, device->slot, device->func, PCI_CONFIG_INTERRUPT_LINE, 0xFE);
|
|
|
|
|
if (pci_config_read_byte(device->bus, device->slot, device->func, PCI_CONFIG_INTERRUPT_LINE) == 0xFE) {
|
|
|
|
|
// todo
|
|
|
|
|
// k_panics("Interrupt line");
|
|
|
|
|
// return PCI_INIT_FAIL;
|
|
|
|
|
void ide_fix_bar(bar_info *bar, u32 default_address, u32 size) {
|
|
|
|
|
if (bar->address == 0x0) {
|
|
|
|
|
// no need to actually write ti back
|
|
|
|
|
bar->address = default_address;
|
|
|
|
|
bar->prefetchable = 0;
|
|
|
|
|
bar->type = 0;
|
|
|
|
|
bar->is_io_space = 1;
|
|
|
|
|
bar->size = size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ide_pci_init_channels(pci_device *device) {
|
|
|
|
|
pci_config_write_byte(device->bus, device->slot, device->func, PCI_CONFIG_INTERRUPT_LINE, 0xFE);
|
|
|
|
|
if (pci_config_read_byte(device->bus, device->slot, device->func, PCI_CONFIG_INTERRUPT_LINE) == 0xFE) {
|
|
|
|
|
#ifdef IDE_ENABLE_INTERRUPT
|
|
|
|
|
k_panics("NOT SUPPORTED");
|
|
|
|
|
#else
|
|
|
|
|
pci_config_write_byte(device->bus, device->slot, device->func, PCI_CONFIG_INTERRUPT_LINE,
|
|
|
|
|
PCI_INTERRUPT_LINE_DISABLED);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
pci_init_bar(device, 0);
|
|
|
|
|
pci_init_bar(device, 1);
|
|
|
|
|
pci_init_bar(device, 2);
|
|
|
|
|
@@ -317,15 +369,27 @@ u8 ide_pci_initialize(pci_device *device) {
|
|
|
|
|
|| !device->bar3.present
|
|
|
|
|
|| !device->bar4.present) {
|
|
|
|
|
k_panics("IDE Missing bars");
|
|
|
|
|
return PCI_INIT_FAIL;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
ide_fix_bar(&device->bar0, 0x1F0, 8);
|
|
|
|
|
ide_fix_bar(&device->bar1, 0x3F6, 4);
|
|
|
|
|
ide_fix_bar(&device->bar2, 0x170, 8);
|
|
|
|
|
ide_fix_bar(&device->bar3, 0x376, 4);
|
|
|
|
|
|
|
|
|
|
channels[ATA_PRIMARY].base = device->bar0.address + 0x1F0;
|
|
|
|
|
channels[ATA_PRIMARY].ctrl = device->bar1.address + 0x3F6;
|
|
|
|
|
channels[ATA_SECONDARY].base = device->bar2.address + 0x170;
|
|
|
|
|
channels[ATA_SECONDARY].ctrl = device->bar3.address + 0x376;
|
|
|
|
|
channels[ATA_PRIMARY].base = device->bar0.address;
|
|
|
|
|
channels[ATA_PRIMARY].ctrl = device->bar1.address;
|
|
|
|
|
channels[ATA_SECONDARY].base = device->bar2.address;
|
|
|
|
|
channels[ATA_SECONDARY].ctrl = device->bar3.address;
|
|
|
|
|
channels[ATA_PRIMARY].bmide = device->bar4.address + 0; // Bus Master IDE
|
|
|
|
|
channels[ATA_SECONDARY].bmide = device->bar4.address + 8; // Bus Master IDE
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8 ide_pci_initialize(pci_device *device) {
|
|
|
|
|
|
|
|
|
|
if (!ide_pci_init_channels(device)) {
|
|
|
|
|
return PCI_INIT_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// disable IRQ
|
|
|
|
|
ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2);
|
|
|
|
|
@@ -366,12 +430,13 @@ u8 ide_pci_initialize(pci_device *device) {
|
|
|
|
|
unsigned char cl = ide_read(i, ATA_REG_LBA1);
|
|
|
|
|
unsigned char ch = ide_read(i, ATA_REG_LBA2);
|
|
|
|
|
|
|
|
|
|
if (cl == 0x14 && ch == 0xEB)
|
|
|
|
|
if (cl == 0x14 && ch == 0xEB) {
|
|
|
|
|
type = IDE_ATAPI;
|
|
|
|
|
else if (cl == 0x69 && ch == 0x96)
|
|
|
|
|
} else if (cl == 0x69 && ch == 0x96) {
|
|
|
|
|
type = IDE_ATAPI;
|
|
|
|
|
else
|
|
|
|
|
} else {
|
|
|
|
|
continue; // Unknown Type (may not be a device).
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET);
|
|
|
|
|
sleep(1);
|
|
|
|
|
@@ -411,12 +476,12 @@ u8 ide_pci_initialize(pci_device *device) {
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
if (ide_devices[i].reserved == 1) {
|
|
|
|
|
char tmp[64];
|
|
|
|
|
itoa(ide_devices[i].size / 1024 / 1024 / 2, tmp, 10);
|
|
|
|
|
itoa(ide_devices[i].size / 1024 / 2, tmp, 10);
|
|
|
|
|
kprint("Found ");
|
|
|
|
|
kprint((const char *[]) {"ATA", "ATAPI"}[ide_devices[i].type]);
|
|
|
|
|
kprint(" Drive ");
|
|
|
|
|
kprint(tmp);
|
|
|
|
|
kprint(" - ");
|
|
|
|
|
kprint("MB - ");
|
|
|
|
|
kprint(ide_devices[i].model);
|
|
|
|
|
kprint("\n");
|
|
|
|
|
}
|
|
|
|
|
@@ -427,3 +492,141 @@ u8 ide_pci_initialize(pci_device *device) {
|
|
|
|
|
void ide_register() {
|
|
|
|
|
pci_register_driver(&ide_pci_driver);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8 ide_read_ata_access(u8 direction, u8 drive, u32 lba, u8 numsects, void *target) {
|
|
|
|
|
u8 lba_mode /* 0: CHS, 1:LBA28, 2: LBA48 */, dma /* 0: No DMA, 1: DMA */, cmd;
|
|
|
|
|
u8 lba_io[6];
|
|
|
|
|
u8 channel = ide_devices[drive].channel;
|
|
|
|
|
u8 slavebit = ide_devices[drive].drive;
|
|
|
|
|
u32 bus = channels[channel].base;
|
|
|
|
|
u32 words = 256;
|
|
|
|
|
u16 cyl, i;
|
|
|
|
|
u8 head, sect, err;
|
|
|
|
|
|
|
|
|
|
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN = (ide_irq_invoked = 0x0) + 0x02);
|
|
|
|
|
|
|
|
|
|
// setup LBA data
|
|
|
|
|
if (lba >= ATA_LBA28_MAX) { // Sure Drive should support LBA in this case, or you are
|
|
|
|
|
// giving a wrong LBA.
|
|
|
|
|
// LBA48:
|
|
|
|
|
lba_mode = 2;
|
|
|
|
|
lba_io[0] = (lba & 0x000000FF) >> 0;
|
|
|
|
|
lba_io[1] = (lba & 0x0000FF00) >> 8;
|
|
|
|
|
lba_io[2] = (lba & 0x00FF0000) >> 16;
|
|
|
|
|
lba_io[3] = (lba & 0xFF000000) >> 24;
|
|
|
|
|
lba_io[4] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.
|
|
|
|
|
lba_io[5] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.
|
|
|
|
|
head = 0; // Lower 4-bits of HDDEVSEL are not used here.
|
|
|
|
|
} else if (ide_devices[drive].capabilities & ATA_CAP_LBA) { // Drive supports LBA?
|
|
|
|
|
// LBA28:
|
|
|
|
|
lba_mode = 1;
|
|
|
|
|
lba_io[0] = (lba & 0x00000FF) >> 0;
|
|
|
|
|
lba_io[1] = (lba & 0x000FF00) >> 8;
|
|
|
|
|
lba_io[2] = (lba & 0x0FF0000) >> 16;
|
|
|
|
|
lba_io[3] = 0; // These Registers are not used here.
|
|
|
|
|
lba_io[4] = 0; // These Registers are not used here.
|
|
|
|
|
lba_io[5] = 0; // These Registers are not used here.
|
|
|
|
|
head = (lba & 0xF000000) >> 24;
|
|
|
|
|
} else {
|
|
|
|
|
// CHS:
|
|
|
|
|
lba_mode = 0;
|
|
|
|
|
sect = (lba % 63) + 1;
|
|
|
|
|
cyl = (lba + 1 - sect) / (16 * 63);
|
|
|
|
|
lba_io[0] = sect;
|
|
|
|
|
lba_io[1] = (cyl >> 0) & 0xFF;
|
|
|
|
|
lba_io[2] = (cyl >> 8) & 0xFF;
|
|
|
|
|
lba_io[3] = 0;
|
|
|
|
|
lba_io[4] = 0;
|
|
|
|
|
lba_io[5] = 0;
|
|
|
|
|
head = (lba + 1 - sect) % (16 * 63) / (63); // Head number is written to HDDEVSEL lower 4-bits.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if DMA is available
|
|
|
|
|
dma = 0; // maybe later
|
|
|
|
|
|
|
|
|
|
// wait for the drive to have time for us
|
|
|
|
|
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY) {}
|
|
|
|
|
|
|
|
|
|
// clear error
|
|
|
|
|
ide_write(channel, ATA_REG_ERROR, 0);
|
|
|
|
|
|
|
|
|
|
if (lba_mode == 0) {
|
|
|
|
|
ide_write(channel,
|
|
|
|
|
ATA_REG_HDDEVSEL,
|
|
|
|
|
ATA_HDDDEVSEL_DEFAULT | ATA_HDDDEVSEL_CHS | (slavebit << 4) | head); // Drive & CHS.
|
|
|
|
|
} else {
|
|
|
|
|
ide_write(channel,
|
|
|
|
|
ATA_REG_HDDEVSEL,
|
|
|
|
|
ATA_HDDDEVSEL_DEFAULT | ATA_HDDDEVSEL_LBA | (slavebit << 4) | head); // Drive & LBA
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// store data
|
|
|
|
|
if (lba_mode == 2) {
|
|
|
|
|
ide_write(channel, ATA_REG_SECCOUNT1, 0);
|
|
|
|
|
ide_write(channel, ATA_REG_LBA3, lba_io[3]);
|
|
|
|
|
ide_write(channel, ATA_REG_LBA4, lba_io[4]);
|
|
|
|
|
ide_write(channel, ATA_REG_LBA5, lba_io[5]);
|
|
|
|
|
}
|
|
|
|
|
ide_write(channel, ATA_REG_SECCOUNT0, numsects);
|
|
|
|
|
ide_write(channel, ATA_REG_LBA0, lba_io[0]);
|
|
|
|
|
ide_write(channel, ATA_REG_LBA1, lba_io[1]);
|
|
|
|
|
ide_write(channel, ATA_REG_LBA2, lba_io[2]);
|
|
|
|
|
|
|
|
|
|
// pick correct ccommand
|
|
|
|
|
if (lba_mode == 0 && dma == 0 && direction == 0) cmd = ATA_CMD_READ_PIO;
|
|
|
|
|
if (lba_mode == 1 && dma == 0 && direction == 0) cmd = ATA_CMD_READ_PIO;
|
|
|
|
|
if (lba_mode == 2 && dma == 0 && direction == 0) cmd = ATA_CMD_READ_PIO_EXT;
|
|
|
|
|
// if (lba_mode == 0 && dma == 1 && direction == 0) cmd = ATA_CMD_READ_DMA;
|
|
|
|
|
// if (lba_mode == 1 && dma == 1 && direction == 0) cmd = ATA_CMD_READ_DMA;
|
|
|
|
|
// if (lba_mode == 2 && dma == 1 && direction == 0) cmd = ATA_CMD_READ_DMA_EXT;
|
|
|
|
|
if (lba_mode == 0 && dma == 0 && direction == 1) cmd = ATA_CMD_WRITE_PIO;
|
|
|
|
|
if (lba_mode == 1 && dma == 0 && direction == 1) cmd = ATA_CMD_WRITE_PIO;
|
|
|
|
|
if (lba_mode == 2 && dma == 0 && direction == 1) cmd = ATA_CMD_WRITE_PIO_EXT;
|
|
|
|
|
// if (lba_mode == 0 && dma == 1 && direction == 1) cmd = ATA_CMD_WRITE_DMA;
|
|
|
|
|
// if (lba_mode == 1 && dma == 1 && direction == 1) cmd = ATA_CMD_WRITE_DMA;
|
|
|
|
|
// if (lba_mode == 2 && dma == 1 && direction == 1) cmd = ATA_CMD_WRITE_DMA_EXT;
|
|
|
|
|
ide_write(channel, ATA_REG_COMMAND, cmd); // Send the Command.
|
|
|
|
|
|
|
|
|
|
void* cur_addr = target;
|
|
|
|
|
// read response
|
|
|
|
|
if (dma) {
|
|
|
|
|
if (direction == 0);
|
|
|
|
|
// DMA Read.
|
|
|
|
|
else;
|
|
|
|
|
// DMA Write.
|
|
|
|
|
} else {
|
|
|
|
|
if (direction == 0) {
|
|
|
|
|
// PIO Read.
|
|
|
|
|
for (i = 0; i < numsects; i++) {
|
|
|
|
|
if ((err = ide_polling(channel, 1))) {
|
|
|
|
|
ide_print_error(drive, err);
|
|
|
|
|
return err; // Polling, set error and exit if there is.
|
|
|
|
|
}
|
|
|
|
|
port_word_in_repeat(bus, cur_addr, words);
|
|
|
|
|
cur_addr += (words * 2);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// PIO Write.
|
|
|
|
|
for (i = 0; i < numsects; i++) {
|
|
|
|
|
ide_polling(channel, 0); // Polling.
|
|
|
|
|
port_word_out_repeat(bus, cur_addr, words);
|
|
|
|
|
cur_addr += (words * 2);
|
|
|
|
|
}
|
|
|
|
|
ide_write(channel, ATA_REG_COMMAND, (char[]) {ATA_CMD_CACHE_FLUSH,
|
|
|
|
|
ATA_CMD_CACHE_FLUSH,
|
|
|
|
|
ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]);
|
|
|
|
|
ide_polling(channel, 0); // Polling.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8 ide_read_access(u8 direction, u8 drive, u32 lba, u8 numsects, void *target) {
|
|
|
|
|
if (drive > 3
|
|
|
|
|
|| ide_devices[drive].reserved == 1
|
|
|
|
|
|| ide_devices[drive].type == IDE_ATAPI) {
|
|
|
|
|
k_panics("Not supported device read operation");
|
|
|
|
|
}
|
|
|
|
|
return ide_read_ata_access(direction, drive, lba, numsects, target);
|
|
|
|
|
}
|
|
|
|
|
|