feat: implemented ide read write operations

This commit is contained in:
2021-02-05 23:23:26 +01:00
parent b156509da1
commit a4651ca9d9
9 changed files with 286 additions and 62 deletions

View File

@@ -18,6 +18,8 @@ FILE(GLOB_RECURSE kernel_src kernel/**.c)
FILE(GLOB_RECURSE kernel_asm kernel/**.S) FILE(GLOB_RECURSE kernel_asm kernel/**.S)
FILE(GLOB_RECURSE boot_asm boot/boot.S) FILE(GLOB_RECURSE boot_asm boot/boot.S)
#add_compile_definitions(IDE_ENABLE_INTERRUPT)
add_executable(my-kernel.bin ${kernel_src} ${kernel_asm} ${boot_asm}) add_executable(my-kernel.bin ${kernel_src} ${kernel_asm} ${boot_asm})
set_source_files_properties(${kernel_src} PROPERTIES LANGUAGE C COMPILE_FLAGS "") set_source_files_properties(${kernel_src} PROPERTIES LANGUAGE C COMPILE_FLAGS "")
set_target_properties(my-kernel.bin PROPERTIES LINKER_LANGUAGE C PREFIX "" SUFFIX "" LINK_FLAGS "") set_target_properties(my-kernel.bin PROPERTIES LINKER_LANGUAGE C PREFIX "" SUFFIX "" LINK_FLAGS "")

View File

@@ -7,6 +7,7 @@
#include <drivers/ports.h> #include <drivers/ports.h>
#include <cpu/isr.h> #include <cpu/isr.h>
#include <libc/libc.h> #include <libc/libc.h>
#include <libk.h>
#include <kprint.h> #include <kprint.h>
// https://wiki.osdev.org/PIT // https://wiki.osdev.org/PIT

View File

@@ -60,12 +60,21 @@
#define ATA_IDENT_COMMANDSETS 164 #define ATA_IDENT_COMMANDSETS 164
#define ATA_IDENT_MAX_LBA_EXT 200 #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_ATA 0x00
#define IDE_ATAPI 0x01 #define IDE_ATAPI 0x01
#define ATA_MASTER 0x00 #define ATA_MASTER 0x00
#define ATA_SLAVE 0x01 #define ATA_SLAVE 0x01
// base
#define ATA_REG_DATA 0x00 #define ATA_REG_DATA 0x00
#define ATA_REG_ERROR 0x01 #define ATA_REG_ERROR 0x01
#define ATA_REG_FEATURES 0x01 #define ATA_REG_FEATURES 0x01
@@ -76,13 +85,17 @@
#define ATA_REG_HDDEVSEL 0x06 #define ATA_REG_HDDEVSEL 0x06
#define ATA_REG_COMMAND 0x07 #define ATA_REG_COMMAND 0x07
#define ATA_REG_STATUS 0x07 #define ATA_REG_STATUS 0x07
#define ATA_REG_SECCOUNT1 0x08
#define ATA_REG_LBA3 0x09 // ??
#define ATA_REG_LBA4 0x0A #define ATA_REG_SECCOUNT1 0x12
#define ATA_REG_LBA5 0x0B #define ATA_REG_LBA3 0x13
#define ATA_REG_CONTROL 0x0C #define ATA_REG_LBA4 0x14
#define ATA_REG_ALTSTATUS 0x0C #define ATA_REG_LBA5 0x15
#define ATA_REG_DEVADDRESS 0x0D
// ctrl
#define ATA_REG_CONTROL 0x22
#define ATA_REG_ALTSTATUS 0x22
#define ATA_REG_DEVADDRESS 0x23
// Channels: // Channels:
#define ATA_PRIMARY 0x00 #define ATA_PRIMARY 0x00
@@ -121,61 +134,87 @@ void ide_write(u8 channel, u8 reg, u8 data);
u8 ide_read(u8 channel, u8 reg) { u8 ide_read(u8 channel, u8 reg) {
u8 result; u8 result;
if (reg > 0x07 && reg < 0x0C) if (reg & 0x10) {
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
if (reg < 0x08) result = port_byte_in(channels[channel].base + (reg & 0xF));
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)
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); 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; return result;
} }
void ide_write(u8 channel, u8 reg, u8 data) { 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); ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
if (reg < 0x08) port_byte_out(channels[channel].base + (reg & 0xF), data);
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)
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); 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) { 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 /* 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 * ESP for all of the code the compiler generates between the inline
* assembly blocks. * assembly blocks.
*/ */
if (reg > 0x07 && reg < 0x0C) { if (reg & 0x10) {
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
} port_double_word_in_repeat(channels[channel].base + (reg & 0xF), buffer, quads);
// 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) {
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); 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: // (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; return PCI_VALIDATE_OK;
} }
u8 ide_pci_initialize(pci_device *device) { 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); 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) { if (pci_config_read_byte(device->bus, device->slot, device->func, PCI_CONFIG_INTERRUPT_LINE) == 0xFE) {
// todo #ifdef IDE_ENABLE_INTERRUPT
// k_panics("Interrupt line"); k_panics("NOT SUPPORTED");
// return PCI_INIT_FAIL; #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, 0);
pci_init_bar(device, 1); pci_init_bar(device, 1);
pci_init_bar(device, 2); pci_init_bar(device, 2);
@@ -317,15 +369,27 @@ u8 ide_pci_initialize(pci_device *device) {
|| !device->bar3.present || !device->bar3.present
|| !device->bar4.present) { || !device->bar4.present) {
k_panics("IDE Missing bars"); 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].base = device->bar0.address;
channels[ATA_PRIMARY].ctrl = device->bar1.address + 0x3F6; channels[ATA_PRIMARY].ctrl = device->bar1.address;
channels[ATA_SECONDARY].base = device->bar2.address + 0x170; channels[ATA_SECONDARY].base = device->bar2.address;
channels[ATA_SECONDARY].ctrl = device->bar3.address + 0x376; channels[ATA_SECONDARY].ctrl = device->bar3.address;
channels[ATA_PRIMARY].bmide = device->bar4.address + 0; // Bus Master IDE channels[ATA_PRIMARY].bmide = device->bar4.address + 0; // Bus Master IDE
channels[ATA_SECONDARY].bmide = device->bar4.address + 8; // 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 // disable IRQ
ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2); ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2);
@@ -366,19 +430,20 @@ u8 ide_pci_initialize(pci_device *device) {
unsigned char cl = ide_read(i, ATA_REG_LBA1); unsigned char cl = ide_read(i, ATA_REG_LBA1);
unsigned char ch = ide_read(i, ATA_REG_LBA2); unsigned char ch = ide_read(i, ATA_REG_LBA2);
if (cl == 0x14 && ch == 0xEB) if (cl == 0x14 && ch == 0xEB) {
type = IDE_ATAPI; type = IDE_ATAPI;
else if (cl == 0x69 && ch == 0x96) } else if (cl == 0x69 && ch == 0x96) {
type = IDE_ATAPI; type = IDE_ATAPI;
else } else {
continue; // Unknown Type (may not be a device). continue; // Unknown Type (may not be a device).
}
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET); ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET);
sleep(1); sleep(1);
} }
// (V) Read Identification Space of the Device: // (V) Read Identification Space of the Device:
ide_read_buffer(i, ATA_REG_DATA, (unsigned int*) ide_buf, 128); ide_read_buffer(i, ATA_REG_DATA, (unsigned int *) ide_buf, 128);
// (VI) Read Device Parameters: // (VI) Read Device Parameters:
ide_devices[count].reserved = 1; ide_devices[count].reserved = 1;
@@ -411,12 +476,12 @@ u8 ide_pci_initialize(pci_device *device) {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (ide_devices[i].reserved == 1) { if (ide_devices[i].reserved == 1) {
char tmp[64]; 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("Found ");
kprint((const char *[]) {"ATA", "ATAPI"}[ide_devices[i].type]); kprint((const char *[]) {"ATA", "ATAPI"}[ide_devices[i].type]);
kprint(" Drive "); kprint(" Drive ");
kprint(tmp); kprint(tmp);
kprint(" - "); kprint("MB - ");
kprint(ide_devices[i].model); kprint(ide_devices[i].model);
kprint("\n"); kprint("\n");
} }
@@ -427,3 +492,141 @@ u8 ide_pci_initialize(pci_device *device) {
void ide_register() { void ide_register() {
pci_register_driver(&ide_pci_driver); 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);
}

View File

@@ -5,6 +5,10 @@
#ifndef NEW_KERNEL_IDE_H #ifndef NEW_KERNEL_IDE_H
#define NEW_KERNEL_IDE_H #define NEW_KERNEL_IDE_H
#include <types.h>
void ide_register(); void ide_register();
u8 ide_read_access(u8 direction, u8 drive, u32 lba, u8 numsects, void *target);
#endif //NEW_KERNEL_IDE_H #endif //NEW_KERNEL_IDE_H

View File

@@ -280,7 +280,7 @@ void pci_init_bar(pci_device *device, u8 bar_index) {
bar->address = original_address & 0xFFFFFFF0; bar->address = original_address & 0xFFFFFFF0;
bar->is_io_space = 0; bar->is_io_space = 0;
bar->type = (original_address & 0b110) >> 1; bar->type = (original_address & 0b110) >> 1;
bar->prefetchable = (original_address & 0b111000) >> 3; bar->prefetchable = (original_address & 0b1000) >> 3;
} }
// todo identify conflicts, move to different address // todo identify conflicts, move to different address
pci_config_write_double_word(device->bus, device->slot, device->func, offset, original_address); pci_config_write_double_word(device->bus, device->slot, device->func, offset, original_address);

View File

@@ -55,6 +55,8 @@
#define PCI_CONFIG_MAX_GRANT 0x3E #define PCI_CONFIG_MAX_GRANT 0x3E
#define PCI_CONFIG_MAX_LATENCY 0x3F #define PCI_CONFIG_MAX_LATENCY 0x3F
#define PCI_INTERRUPT_LINE_DISABLED 0xff
typedef struct pci_driver pci_driver; typedef struct pci_driver pci_driver;
typedef struct pci_device pci_device; typedef struct pci_device pci_device;
@@ -80,7 +82,7 @@ typedef struct {
u8 present: 1; u8 present: 1;
u8 is_io_space: 1; u8 is_io_space: 1;
u8 type: 2; u8 type: 2;
u8 prefetchable: 3; u8 prefetchable: 1;
} bar_info; } bar_info;
typedef struct pci_device { typedef struct pci_device {

View File

@@ -41,6 +41,13 @@ void port_double_word_out(unsigned short port, unsigned int data) {
__asm__("out %%eax, %%dx" : : "a" (data), "d" (port)); __asm__("out %%eax, %%dx" : : "a" (data), "d" (port));
} }
void port_word_out_repeat(unsigned short port, unsigned short *data, int buffer_size) {
asm("rep outsw"
: "+S"(data), "+c"(buffer_size)
: "d"(port)
: "memory");
}
void port_word_in_repeat(unsigned short port, unsigned short *data, int buffer_size) { void port_word_in_repeat(unsigned short port, unsigned short *data, int buffer_size) {
asm("rep insw" asm("rep insw"
: "+D"(data), "+c"(buffer_size) : "+D"(data), "+c"(buffer_size)

View File

@@ -56,6 +56,8 @@ unsigned int port_double_word_in(unsigned int port);
void port_double_word_out(unsigned short port, unsigned int data); void port_double_word_out(unsigned short port, unsigned int data);
void port_word_out_repeat(unsigned short port, unsigned short *data, int buffer_size);
void port_word_in_repeat(unsigned short port, unsigned short *data, int buffer_size); void port_word_in_repeat(unsigned short port, unsigned short *data, int buffer_size);
void port_double_word_in_repeat(unsigned short port, unsigned int *data, int buffer_size); void port_double_word_in_repeat(unsigned short port, unsigned int *data, int buffer_size);

View File

@@ -152,10 +152,13 @@ void kmain(multiboot_info_t *multiboot_info) {
// init done, enable interrupts // init done, enable interrupts
__asm__ __volatile__("sti"); __asm__ __volatile__("sti");
// init timer for future task switching // init timer for future task switching
init_timer(50); init_timer(1000);
// setup PS/2 keyboard // setup PS/2 keyboard
init_keyboard(); init_keyboard();
u8* tmp = malloc(4096);
ide_read_access(0, 0, 0, 16, tmp);
// enter main loop // enter main loop
while (true) { while (true) {
main_loop(); main_loop();