Code cleanup

This commit is contained in:
hippoz 2020-12-20 23:01:30 +02:00
parent c5cecbb450
commit 36ef9ec96e
Signed by untrusted user who does not match committer: hippoz
GPG key ID: 7C52899193467641

View file

@ -5,7 +5,7 @@
// Source: https://wiki.osdev.org/PCI_IDE_Controller
// NOTE(hippoz): The function below is actually a joke. It's temporary. I'll implement the timer soon.
void sleep(int h) {
uint8_t sleep(int h) {
if (h != 1) return 1;
for (unsigned long long i = 0; i < 99999999999; i++);
return 0;
@ -44,125 +44,125 @@ struct ide_device {
// ---- Functions ----
void ide_write(unsigned char channel, unsigned char reg, unsigned char data) {
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
if (reg < 0x08)
outportb(channels[channel].base + reg - 0x00, data);
else if (reg < 0x0C)
outportb(channels[channel].base + reg - 0x06, data);
else if (reg < 0x0E)
outportb(channels[channel].ctrl + reg - 0x0A, data);
else if (reg < 0x16)
outportb(channels[channel].bmide + reg - 0x0E, data);
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
if (reg < 0x08) outportb(channels[channel].base + reg - 0x00, data);
else if (reg < 0x0C) outportb(channels[channel].base + reg - 0x06, data);
else if (reg < 0x0E) outportb(channels[channel].ctrl + reg - 0x0A, data);
else if (reg < 0x16) outportb(channels[channel].bmide + reg - 0x0E, data);
if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
}
unsigned char ide_read(unsigned char channel, unsigned char reg) {
unsigned char result;
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
if (reg < 0x08)
result = inportb(channels[channel].base + reg - 0x00);
else if (reg < 0x0C)
result = inportb(channels[channel].base + reg - 0x06);
else if (reg < 0x0E)
result = inportb(channels[channel].ctrl + reg - 0x0A);
else if (reg < 0x16)
result = inportb(channels[channel].bmide + reg - 0x0E);
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
if (reg < 0x08) result = inportb(channels[channel].base + reg - 0x00);
else if (reg < 0x0C) result = inportb(channels[channel].base + reg - 0x06);
else if (reg < 0x0E) result = inportb(channels[channel].ctrl + reg - 0x0A);
else if (reg < 0x16) result = inportb(channels[channel].bmide + reg - 0x0E);
if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
return result;
}
void ide_read_buffer(unsigned char channel, unsigned char reg, unsigned int* buffer,
unsigned int quads) {
void ide_read_buffer(unsigned char channel, unsigned char reg, unsigned int* buffer, unsigned int quads) {
/* WARNING: This code contains a serious bug. The inline assembly trashes ES and
* ESP for all of the code the compiler generates between the inline
* assembly blocks.
*/
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
asm("pushw %es; movw %ds, %ax; movw %ax, %es");
if (reg < 0x08)
insl(channels[channel].base + reg - 0x00, buffer, quads);
else if (reg < 0x0C)
insl(channels[channel].base + reg - 0x06, buffer, quads);
else if (reg < 0x0E)
insl(channels[channel].ctrl + reg - 0x0A, buffer, quads);
else if (reg < 0x16)
insl(channels[channel].bmide + reg - 0x0E, buffer, quads);
if (reg > 0x07 && reg < 0x0C) ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
asm("pushw %es; movw %ds, %ax; movw %ax, %es");
if (reg < 0x08) insl(channels[channel].base + reg - 0x00, buffer, quads);
else if (reg < 0x0C) insl(channels[channel].base + reg - 0x06, buffer, quads);
else if (reg < 0x0E) insl(channels[channel].ctrl + reg - 0x0A, buffer, quads);
else if (reg < 0x16) insl(channels[channel].bmide + reg - 0x0E, buffer, quads);
asm("popw %es;");
if (reg > 0x07 && reg < 0x0C)
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
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) {
// (I) Delay 400 nanosecond for BSY to be set:
// -------------------------------------------------
for(int i = 0; i < 4; i++)
ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port wastes 100ns; loop four times.
// Delay 400 ns for BSY to be set:
for(int i = 0; i < 4; i++) ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port wastes 100ns; loop four times.
// (II) Wait for BSY to be cleared:
// -------------------------------------------------
// Wait for BSY to be 0:
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY)
; // Wait for BSY to be zero.
if (advanced_check) {
unsigned char state = ide_read(channel, ATA_REG_STATUS); // Read Status Register.
// (III) Check For Errors:
// -------------------------------------------------
if (state & ATA_SR_ERR)
return 2; // Error.
// Check For Errors:
if (state & ATA_SR_ERR) return 2; // Error
// (IV) Check If Device fault:
// -------------------------------------------------
if (state & ATA_SR_DF)
return 1; // Device Fault.
// Check If Device fault:
if (state & ATA_SR_DF) return 1; // Device Fault.
// (V) Check DRQ:
// -------------------------------------------------
// Check DRQ:
// BSY = 0; DF = 0; ERR = 0 so we should check for DRQ now.
if ((state & ATA_SR_DRQ) == 0)
return 3; // DRQ should be set
if ((state & ATA_SR_DRQ) == 0) return 3; // DRQ should be set
}
return 0; // No Error.
}
unsigned char ide_print_error(unsigned int drive, unsigned char err) {
if (err == 0)
return err;
if (err == 0) return err;
terminal_writestring("IDE:");
if (err == 1) {terminal_writestring("- Device Fault\n "); err = 19;}
else if (err == 2) {
if (err == 1) {
terminal_writestring("- Device Fault\n ");
err = 19;
} else if (err == 2) {
unsigned char st = ide_read(ide_devices[drive].Channel, ATA_REG_ERROR);
if (st & ATA_ER_AMNF) {terminal_writestring("- No Address Mark Found\n"); err = 7;}
if (st & ATA_ER_TK0NF) {terminal_writestring("- No Media or Media Error\n"); err = 3;}
if (st & ATA_ER_ABRT) {terminal_writestring("- Command Aborted\n"); err = 20;}
if (st & ATA_ER_MCR) {terminal_writestring("- No Media or Media Error\n"); err = 3;}
if (st & ATA_ER_IDNF) {terminal_writestring("- ID mark not Found\n"); err = 21;}
if (st & ATA_ER_MC) {terminal_writestring("- No Media or Media Error\n"); err = 3;}
if (st & ATA_ER_UNC) {terminal_writestring("- Uncorrectable Data Error\n"); err = 22;}
if (st & ATA_ER_BBK) {terminal_writestring("- Bad Sectors\n"); err = 13;}
} else if (err == 3) {terminal_writestring("- Reads Nothing\n"); err = 23;}
else if (err == 4) {terminal_writestring("- Write Protected\n"); err = 8;}
if (st & ATA_ER_AMNF) {
terminal_writestring("- No Address Mark Found\n");
err = 7;
}
if (st & ATA_ER_TK0NF) {
terminal_writestring("- No Media or Media Error\n");
err = 3;
}
if (st & ATA_ER_ABRT) {
terminal_writestring("- Command Aborted\n");
err = 20;
}
if (st & ATA_ER_MCR) {
terminal_writestring("- No Media or Media Error\n");
err = 3;
}
if (st & ATA_ER_IDNF) {
terminal_writestring("- ID mark not Found\n");
err = 21;
}
if (st & ATA_ER_MC) {
terminal_writestring("- No Media or Media Error\n");
err = 3;
}
if (st & ATA_ER_UNC) {
terminal_writestring("- Uncorrectable Data Error\n");
err = 22;
}
if (st & ATA_ER_BBK) {
terminal_writestring("- Bad Sectors\n");
err = 13;
}
} else if (err == 3) {
terminal_writestring("- Reads Nothing\n");
err = 23;
} else if (err == 4) {
terminal_writestring("- Write Protected\n");
err = 8;
}
terminal_writestring("- [");
terminal_writestring((const char *[]){"Primary", "Secondary"}[ide_devices[drive].Channel]);
terminal_writestring(" ");
terminal_writestring((const char *[]){"Master", "Slave"}[ide_devices[drive].Drive]);
terminal_writestring(" ");
terminal_writeline(ide_devices[drive].Model);
//printk("- [%s %s] %s\n",
// (const char *[]){"Primary", "Secondary"}[ide_devices[drive].channel], // Use the channel as an index into the array
// (const char *[]){"Master", "Slave"}[ide_devices[drive].drive], // Same as above, using the drive
// ide_devices[drive].model);
terminal_writestring("- [");
terminal_writestring((const char *[]){"Primary", "Secondary"}[ide_devices[drive].Channel]);
terminal_writestring(" ");
terminal_writestring((const char *[]){"Master", "Slave"}[ide_devices[drive].Drive]);
terminal_writestring(" ");
terminal_writeline(ide_devices[drive].Model);
return err;
}
@ -171,35 +171,34 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, uns
int j, k, count = 0;
// 1- Detect I/O Ports which interface IDE Controller:
channels[ATA_PRIMARY ].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0);
channels[ATA_PRIMARY ].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F6 * (!BAR1);
channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2);
channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x376 * (!BAR3);
channels[ATA_PRIMARY ].bmide = (BAR4 & 0xFFFFFFFC) + 0; // Bus Master IDE
// Detect I/O Ports which interface IDE Controller:
channels[ATA_PRIMARY].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0);
channels[ATA_PRIMARY].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F6 * (!BAR1);
channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2);
channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x376 * (!BAR3);
channels[ATA_PRIMARY].bmide = (BAR4 & 0xFFFFFFFC) + 0; // Bus Master IDE
channels[ATA_SECONDARY].bmide = (BAR4 & 0xFFFFFFFC) + 8; // Bus Master IDE
// 2- Disable IRQs:
// Disable IRQs:
ide_write(ATA_PRIMARY , ATA_REG_CONTROL, 2);
ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2);
// 3- Detect ATA-ATAPI Devices:
// Detect ATA-ATAPI Devices:
for (int i = 0; i < 2; i++)
for (j = 0; j < 2; j++) {
unsigned char err = 0, type = IDE_ATA, status;
ide_devices[count].Reserved = 0; // Assuming that no drive here.
// (I) Select Drive:
// Select Drive:
ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive.
sleep(1); // Wait 1ms for drive select to work.
// (II) Send ATA Identify Command:
// Send ATA Identify Command:
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
sleep(1); // This function should be implemented in your OS. which waits for 1 ms.
// it is based on System Timer Device Driver.
// (III) Polling:
// Polling:
if (ide_read(i, ATA_REG_STATUS) == 0) continue; // If Status = 0, No Device.
while(1) {
@ -208,13 +207,13 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, uns
if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) break; // Everything is right.
}
// (IV) Probe for ATAPI Devices:
// Probe for ATAPI Devices:
if (err != 0) {
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)
type = IDE_ATAPI;
@ -225,19 +224,19 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, uns
sleep(1);
}
// (V) Read Identification Space of the Device:
// Read Identification Space of the Device:
ide_read_buffer(i, ATA_REG_DATA, (unsigned int) ide_buf, 128);
// (VI) Read Device Parameters:
ide_devices[count].Reserved = 1;
ide_devices[count].Type = type;
ide_devices[count].Channel = i;
ide_devices[count].Drive = j;
ide_devices[count].Signature = *((unsigned short *)(ide_buf + ATA_IDENT_DEVICETYPE));
// Read Device Parameters:
ide_devices[count].Reserved = 1;
ide_devices[count].Type = type;
ide_devices[count].Channel = i;
ide_devices[count].Drive = j;
ide_devices[count].Signature = *((unsigned short *)(ide_buf + ATA_IDENT_DEVICETYPE));
ide_devices[count].Capabilities = *((unsigned short *)(ide_buf + ATA_IDENT_CAPABILITIES));
ide_devices[count].CommandSets = *((unsigned int *)(ide_buf + ATA_IDENT_COMMANDSETS));
ide_devices[count].CommandSets = *((unsigned int *)(ide_buf + ATA_IDENT_COMMANDSETS));
// (VII) Get Size:
// Get Size:
if (ide_devices[count].CommandSets & (1 << 26))
// Device uses 48-Bit Addressing:
ide_devices[count].Size = *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA_EXT));
@ -245,29 +244,26 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, uns
// Device uses CHS or 28-bit Addressing:
ide_devices[count].Size = *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA));
// (VIII) String indicates model of device (like Western Digital HDD and SONY DVD-RW...):
// String indicates model of device (like Western Digital HDD and SONY DVD-RW...):
for(k = 0; k < 40; k += 2) {
ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1];
ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k];}
ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k];
}
ide_devices[count].Model[40] = 0; // Terminate String.
count++;
}
// 4- Print Summary:
for (int i = 0; i < 4; i++)
// Print Summary:
for (int i = 0; i < 4; i++) {
if (ide_devices[i].Reserved == 1) {
terminal_writestring("IDE FOUND DEVICE-> ");
terminal_writestring((const char *[]){"ATA", "ATAPI"}[ide_devices[i].Type]);
terminal_writestring(" Drive ");
terminal_writestring(itoa(ide_devices[i].Size / 1024 / 1024 / 2));
terminal_writestring("GB - ");
terminal_writeline(ide_devices[i].Model);
//printk(" Found %s Drive %dGB - %s\n",
// (const char *[]){"ATA", "ATAPI"}[ide_devices[i].Type], /* Type */
// ide_devices[i].Size / 1024 / 1024 / 2, /* Size */
// ide_devices[i].Model);
terminal_writestring("IDE FOUND DEVICE-> ");
terminal_writestring((const char *[]){"ATA", "ATAPI"}[ide_devices[i].Type]);
terminal_writestring(" Drive ");
terminal_writestring(itoa(ide_devices[i].Size / 1024 / 2));
terminal_writestring("MB - ");
terminal_writeline(ide_devices[i].Model);
}
}
}
@ -303,27 +299,25 @@ void ide_irq() {
}
void ide_wait_irq() {
while (!ide_irq_invoked)
;
while (!ide_irq_invoked);
ide_irq_invoked = 0;
}
unsigned char ide_ata_access(unsigned char direction, unsigned char drive, unsigned int lba, uint8_t* buf) {
unsigned char lba_mode /* 0: CHS, 1:LBA28, 2: LBA48 */, dma /* 0: No DMA, 1: DMA */, cmd;
unsigned char lba_io[6];
unsigned int channel = ide_devices[drive].Channel; // Read the Channel.
unsigned int slavebit = ide_devices[drive].Drive; // Read the Drive [Master/Slave]
unsigned int bus = channels[channel].base; // Bus Base, like 0x1F0 which is also data port.
unsigned int words = 256; // Almost every ATA drive has a sector-size of 512-byte.
unsigned int channel = ide_devices[drive].Channel; // Read the Channel.
unsigned int slavebit = ide_devices[drive].Drive; // Read the Drive [Master/Slave]
unsigned int bus = channels[channel].base; // Bus Base, like 0x1F0 which is also data port.
unsigned int words = 256; // Almost every ATA drive has a sector-size of 512-byte.
unsigned short cyl, i;
unsigned char head, sect, err;
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN = (ide_irq_invoked = 0x0) + 0x02);
// Read parameters
// (I) Select one from LBA28, LBA48 or CHS;
if (lba >= 0x10000000) { // Sure Drive should support LBA in this case, or you are
// giving a wrong LBA.
// Read parameters
// Select one from LBA28, LBA48 or CHS;
if (lba >= 0x10000000) { // 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;
@ -357,19 +351,16 @@ unsigned char ide_ata_access(unsigned char direction, unsigned char drive, unsig
head = (lba + 1 - sect) % (16 * 63) / (63); // Head number is written to HDDEVSEL lower 4-bits.
}
// (II) See if drive supports DMA or not;
dma = 0; // We don't support DMA
dma = 0; // 0 = We don't support DMA
// (III) Wait if the drive is busy;
// Wait if the drive is busy...
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY); // Wait if busy.
// (IV) Select Drive from the controller;
if (lba_mode == 0)
ide_write(channel, ATA_REG_HDDEVSEL, 0xA0 | (slavebit << 4) | head); // Drive & CHS.
else
ide_write(channel, ATA_REG_HDDEVSEL, 0xE0 | (slavebit << 4) | head); // Drive & LBA
// Select Drive from the controller...
if (lba_mode == 0) ide_write(channel, ATA_REG_HDDEVSEL, 0xA0 | (slavebit << 4) | head); // Drive & CHS.
else ide_write(channel, ATA_REG_HDDEVSEL, 0xE0 | (slavebit << 4) | head); // Drive & LBA
// (V) Write Parameters;
// Write Parameters;
if (lba_mode == 2) {
ide_write(channel, ATA_REG_SECCOUNT1, 0);
ide_write(channel, ATA_REG_LBA3, lba_io[3]);
@ -381,7 +372,7 @@ unsigned char ide_ata_access(unsigned char direction, unsigned char drive, unsig
ide_write(channel, ATA_REG_LBA1, lba_io[1]);
ide_write(channel, ATA_REG_LBA2, lba_io[2]);
// (VI) Select the command and send it;
// Select the command and send it;
// Routine that is followed:
// If ( DMA & LBA48) DO_DMA_EXT;
// If ( DMA & LBA28) DO_DMA_LBA;
@ -390,7 +381,7 @@ unsigned char ide_ata_access(unsigned char direction, unsigned char drive, unsig
// If (!DMA & LBA28) DO_PIO_LBA;
// If (!DMA & !LBA#) DO_PIO_CHS;
if (lba_mode == 0 && dma == 0 && direction == 0) cmd = ATA_CMD_READ_PIO;
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;
@ -403,115 +394,107 @@ unsigned char ide_ata_access(unsigned char direction, unsigned char drive, unsig
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.
if (dma)
if (direction == 0);
// DMA Read.
else;
// DMA Write.
else
if (dma) {
if (direction == 0) {
// DMA read.
} else {
// DMA write.
}
} else {
if (direction == 0) {
// PIO Read.
if (err = ide_polling(channel, 1)) return err; // Polling, set error and exit if there is.
inportsm(bus, buf, words);
ide_write(channel, ATA_REG_COMMAND, (char []) { (char)ATA_CMD_CACHE_FLUSH,
(char)ATA_CMD_CACHE_FLUSH,
(char)ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]);
ide_polling(channel, 0); // Polling.
ide_write(channel, ATA_REG_COMMAND, (char []) { (char)ATA_CMD_CACHE_FLUSH, (char)ATA_CMD_CACHE_FLUSH, (char)ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]);
ide_polling(channel, 0); // Polling.
} else {
// PIO Write.
ide_polling(channel, 0); // Polling.
outportsm(bus, buf, words);
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);
}
}
return 0; // Easy, isn't it? no
}
unsigned char ide_atapi_read(unsigned char drive, unsigned int lba, unsigned char numsects, unsigned short selector, unsigned int edi) {
unsigned int channel = ide_devices[drive].Channel;
unsigned int slavebit = ide_devices[drive].Drive;
unsigned int bus = channels[channel].base;
unsigned int words = 1024; // Sector Size. ATAPI drives have a sector size of 2048 bytes.
unsigned char err;
unsigned char ide_atapi_read(unsigned char drive, unsigned int lba, uint8_t* buf) {
unsigned int channel = ide_devices[drive].Channel;
unsigned int slavebit = ide_devices[drive].Drive;
unsigned int bus = channels[channel].base;
unsigned int words = 1024; // Sector Size. ATAPI drives have a sector size of 2048 bytes.
unsigned char err;
int i;
// Enable IRQs:
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN = ide_irq_invoked = 0x0);
// (I): Setup SCSI Packet:
// ------------------------------------------------------------------
atapi_packet[ 0] = ATAPI_CMD_READ;
atapi_packet[ 1] = 0x0;
atapi_packet[ 2] = (lba >> 24) & 0xFF;
atapi_packet[ 3] = (lba >> 16) & 0xFF;
atapi_packet[ 4] = (lba >> 8) & 0xFF;
atapi_packet[ 5] = (lba >> 0) & 0xFF;
atapi_packet[ 6] = 0x0;
atapi_packet[ 7] = 0x0;
atapi_packet[ 8] = 0x0;
atapi_packet[ 9] = numsects;
// Setup SCSI Packet:
atapi_packet[0] = ATAPI_CMD_READ;
atapi_packet[1] = 0x0;
atapi_packet[2] = (lba >> 24) & 0xFF;
atapi_packet[3] = (lba >> 16) & 0xFF;
atapi_packet[4] = (lba >> 8) & 0xFF;
atapi_packet[5] = (lba >> 0) & 0xFF;
atapi_packet[6] = 0x0;
atapi_packet[7] = 0x0;
atapi_packet[8] = 0x0;
atapi_packet[9] = 1; // Number of sectors
atapi_packet[10] = 0x0;
atapi_packet[11] = 0x0;
// (II): Select the drive:
// ------------------------------------------------------------------
// Select the drive:
ide_write(channel, ATA_REG_HDDEVSEL, slavebit << 4);
// (III): Delay 400 nanoseconds for select to complete:
// ------------------------------------------------------------------
for(int i = 0; i < 4; i++)
ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port wastes 100ns.
// Delay 400 nanoseconds for select to complete:
for(int i = 0; i < 4; i++) ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port wastes 100ns.
// (IV): Inform the Controller that we use PIO mode:
// ------------------------------------------------------------------
// Inform the Controller that we use PIO mode:
ide_write(channel, ATA_REG_FEATURES, 0); // PIO mode.
// (V): Tell the Controller the size of buffer:
// ------------------------------------------------------------------
ide_write(channel, ATA_REG_LBA1, (words * 2) & 0xFF); // Lower Byte of Sector Size.
ide_write(channel, ATA_REG_LBA2, (words * 2) >> 8); // Upper Byte of Sector Size.
// Tell the Controller the size of buffer:
ide_write(channel, ATA_REG_LBA1, (words * 2) & 0xFF); // Lower Byte of Sector Size.
ide_write(channel, ATA_REG_LBA2, (words * 2) >> 8); // Upper Byte of Sector Size.
// (VI): Send the Packet Command:
// ------------------------------------------------------------------
ide_write(channel, ATA_REG_COMMAND, ATA_CMD_PACKET); // Send the Command.
// Send the Packet Command:
ide_write(channel, ATA_REG_COMMAND, ATA_CMD_PACKET); // Send the Command.
// (VII): Waiting for the driver to finish or return an error code:
// ------------------------------------------------------------------
if (err = ide_polling(channel, 1)) return err; // Polling and return if error.
terminal_writeline('1');
// Waiting for the driver to finish or return an error code:
if (err = ide_polling(channel, 1)) return err; // Polling and return if error.
// (VIII): Sending the packet data:
// ------------------------------------------------------------------
terminal_writeline('2');
// Sending the packet data:
asm("rep outsw" : : "c"(6), "d"(bus), "S"(atapi_packet)); // Send Packet Data
// (IX): Receiving Data:
// ------------------------------------------------------------------
for (i = 0; i < numsects; i++) {
ide_wait_irq(); // Wait for an IRQ.
if (err = ide_polling(channel, 1))
return err; // Polling and return if error.
asm("pushw %es");
asm("mov %%ax, %%es"::"a"(selector));
asm("rep insw"::"c"(words), "d"(bus), "D"(edi));// Receive Data.
asm("popw %es");
edi += (words * 2);
}
terminal_writeline('3');
// (X): Waiting for an IRQ:
// ------------------------------------------------------------------
// Receiving Data:
ide_wait_irq(); // Wait for an IRQ.
terminal_writeline('4');
if (err = ide_polling(channel, 1)) return err; // Polling and return if error.
terminal_writeline('5');
inportsm(bus, buf, words);
terminal_writeline('6');
// Waiting for an IRQ:
ide_wait_irq();
terminal_writeline('7');
// (XI): Waiting for BSY & DRQ to clear:
// ------------------------------------------------------------------
while (ide_read(channel, ATA_REG_STATUS) & (ATA_SR_BSY | ATA_SR_DRQ))
;
// Waiting for BSY & DRQ to clear:
while (ide_read(channel, ATA_REG_STATUS) & (ATA_SR_BSY | ATA_SR_DRQ));
return 0; // Easy, ... Isn't it? no
terminal_writeline('8');
return 0; // Easy, Isn't it? no
}
uint8_t ide_read_sectors(unsigned char drive, unsigned int lba, uint8_t* buf) {
@ -559,62 +542,51 @@ void ide_atapi_eject(unsigned char drive, unsigned char* package) {
unsigned char err = 0;
ide_irq_invoked = 0;
// 1: Check if the drive presents:
// ==================================
// Check if the drive presents:
if (drive > 3 || ide_devices[drive].Reserved == 0)
package[0] = 0x1; // Drive Not Found!
// 2: Check if drive isn't ATAPI:
// ==================================
package[0] = 0x1; // Drive Not Found!
// Check if drive isn't ATAPI:
else if (ide_devices[drive].Type == IDE_ATA)
package[0] = 20; // Command Aborted.
// 3: Eject ATAPI Driver:
// ============================================
package[0] = 20; // Command Aborted.
// Eject ATAPI Driver:
else {
// Enable IRQs:
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN = ide_irq_invoked = 0x0);
// (I): Setup SCSI Packet:
// ------------------------------------------------------------------
atapi_packet[ 0] = ATAPI_CMD_EJECT;
atapi_packet[ 1] = 0x00;
atapi_packet[ 2] = 0x00;
atapi_packet[ 3] = 0x00;
atapi_packet[ 4] = 0x02;
atapi_packet[ 5] = 0x00;
atapi_packet[ 6] = 0x00;
atapi_packet[ 7] = 0x00;
atapi_packet[ 8] = 0x00;
atapi_packet[ 9] = 0x00;
// Setup SCSI Packet:
atapi_packet[0] = ATAPI_CMD_EJECT;
atapi_packet[1] = 0x00;
atapi_packet[2] = 0x00;
atapi_packet[3] = 0x00;
atapi_packet[4] = 0x02;
atapi_packet[5] = 0x00;
atapi_packet[6] = 0x00;
atapi_packet[7] = 0x00;
atapi_packet[8] = 0x00;
atapi_packet[9] = 0x00;
atapi_packet[10] = 0x00;
atapi_packet[11] = 0x00;
// (II): Select the Drive:
// ------------------------------------------------------------------
// Select the Drive:
ide_write(channel, ATA_REG_HDDEVSEL, slavebit << 4);
// (III): Delay 400 nanosecond for select to complete:
// ------------------------------------------------------------------
for(int i = 0; i < 4; i++)
ide_read(channel, ATA_REG_ALTSTATUS); // Reading Alternate Status Port wastes 100ns.
// Delay 400 nanosecond for select to complete:
for(int i = 0; i < 4; i++) ide_read(channel, ATA_REG_ALTSTATUS); // Reading Alternate Status Port wastes 100ns.
// (IV): Send the Packet Command:
// ------------------------------------------------------------------
ide_write(channel, ATA_REG_COMMAND, ATA_CMD_PACKET); // Send the Command.
// Send the Packet Command:
ide_write(channel, ATA_REG_COMMAND, ATA_CMD_PACKET); // Send the Command.
// (V): Waiting for the driver to finish or invoke an error:
// ------------------------------------------------------------------
err = ide_polling(channel, 1); // Polling and stop if error.
// Waiting for the driver to finish or invoke an error:
err = ide_polling(channel, 1); // Polling and stop if error.
// (VI): Sending the packet data:
// ------------------------------------------------------------------
// Sending the packet data:
// NOTE(hippoz): The if below was not in the tutorial, there was just the else, idk if this is what i should add...
if (err) {
return 1;
}
else {
} else {
asm("rep outsw"::"c"(6), "d"(bus), "S"(atapi_packet));// Send Packet Data
ide_wait_irq(); // Wait for an IRQ.
err = ide_polling(channel, 1); // Polling and get error code.
ide_wait_irq(); // Wait for an IRQ.
err = ide_polling(channel, 1); // Polling and get error code.
if (err == 3) err = 0; // DRQ is not needed here.
}
package[0] = ide_print_error(drive, err); // Return;
@ -638,14 +610,14 @@ void ide_init() {
uint8_t outbuf[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
ide_read_sectors(0, 1, outbuf);
ide_atapi_read(1, 12, outbuf);
sleep(1);
sleep(1);
sleep(1);
for (uint8_t i = 0; i < 3; i++) {
for (uint8_t i = 0; i < 10; i++) {
terminal_writestring(itoa(i));
terminal_writeline(itoa(outbuf[i]));
}
}
}