diff --git a/include/sys/amd64/hw/ide/ahci.h b/include/sys/amd64/hw/ide/ahci.h index 58a8a4e..d35d851 100644 --- a/include/sys/amd64/hw/ide/ahci.h +++ b/include/sys/amd64/hw/ide/ahci.h @@ -222,8 +222,8 @@ struct ahci_command_table_entry { uint32_t ahci_irq(void *ctx); -// TODO: accept block device instead of port registers void ahci_sata_read(struct ahci_port_registers *port, void *buf, uint32_t nsect, uint64_t lba); +void ahci_sata_write(struct ahci_port_registers *port, const void *buf, uint32_t nsect, uint64_t lba); void ahci_port_start(struct ahci_port_registers *port); void ahci_port_stop(struct ahci_port_registers *port); diff --git a/include/sys/amd64/hw/ide/ata.h b/include/sys/amd64/hw/ide/ata.h index 5c9ef88..9a24cfd 100644 --- a/include/sys/amd64/hw/ide/ata.h +++ b/include/sys/amd64/hw/ide/ata.h @@ -26,6 +26,7 @@ #define ATA_CMD_READ_PIO_EX 0x24 #define ATA_CMD_READ_DMA 0xC8 #define ATA_CMD_READ_DMA_EX 0x25 +#define ATA_CMD_WRITE_DMA_EX 0x35 #define ATA_SR_BUSY (1 << 7) #define ATA_SR_DRQ (1 << 3) diff --git a/sys/amd64/grub.cfg b/sys/amd64/grub.cfg deleted file mode 100644 index 2edf696..0000000 --- a/sys/amd64/grub.cfg +++ /dev/null @@ -1,5 +0,0 @@ -menuentry "yggdrasil" { - multiboot /boot/loader - module /boot/kernel kernel - module /boot/initrd.img initrd -} diff --git a/sys/amd64/hw/ide/ahci.c b/sys/amd64/hw/ide/ahci.c index c220e82..aa8f560 100644 --- a/sys/amd64/hw/ide/ahci.c +++ b/sys/amd64/hw/ide/ahci.c @@ -48,6 +48,19 @@ static ssize_t ahci_blk_read(struct blkdev *blk, void *buf, size_t off, size_t c return count; } +static ssize_t ahci_blk_write(struct blkdev *blk, const void *buf, size_t off, size_t count) { + _assert(blk && blk->dev_data); + _assert(!(off & 511)); + _assert(!(count & 511)); + + size_t nsect = count / 512; + size_t lba = off / 512; + + ahci_sata_write((struct ahci_port_registers *) blk->dev_data, buf, nsect, lba); + + return count; +} + static int ahci_add_port_dev(struct ahci_port_registers *port) { void *buf = kmalloc(sizeof(struct blkdev) + sizeof(struct dev_entry)); struct dev_entry *ent = (struct dev_entry *) buf; @@ -56,6 +69,7 @@ static int ahci_add_port_dev(struct ahci_port_registers *port) { blk->dev_data = port; blk->read = ahci_blk_read; + blk->write = ahci_blk_write; ent->dev = blk; ent->dev_class = DEV_CLASS_BLOCK; @@ -84,7 +98,8 @@ uint32_t ahci_irq(void *ctx) { return IRQ_UNHANDLED; } -void ahci_sata_read(struct ahci_port_registers *port, void *buf, uint32_t nsect, uint64_t lba) { +static void ahci_sata_access(struct ahci_port_registers *port, void *buf, uint32_t nsect, uint64_t lba, uint8_t dir) { + kdebug("%s access to AHCI drive\n", dir ? "Write" : "Read"); port->p_is = -1; int cmd = ahci_alloc_cmd(port); @@ -101,7 +116,7 @@ void ahci_sata_read(struct ahci_port_registers *port, void *buf, uint32_t nsect, size_t prd_count = (byte_count + 8191) / 8192; if (prd_count > 8) { - panic("Read operation uses too many PRDT entries\n"); + panic("Too many PRDT entries\n"); } size_t bytes_left = byte_count; @@ -135,11 +150,11 @@ void ahci_sata_read(struct ahci_port_registers *port, void *buf, uint32_t nsect, _assert(!bytes_left); - // Prepare read command + // Prepare command struct ahci_fis_reg_h2d *fis_reg_h2d = &cmd_table->fis_reg_h2d; memset(fis_reg_h2d, 0, sizeof(struct ahci_fis_reg_h2d)); fis_reg_h2d->type = FIS_REG_H2D; - fis_reg_h2d->cmd = ATA_CMD_READ_DMA_EX; + fis_reg_h2d->cmd = dir ? ATA_CMD_WRITE_DMA_EX : ATA_CMD_READ_DMA_EX; fis_reg_h2d->cmd_port = 1 << 7; fis_reg_h2d->lba0 = lba & 0xFF; fis_reg_h2d->lba1 = (lba >> 8) & 0xFF; @@ -178,6 +193,14 @@ void ahci_sata_read(struct ahci_port_registers *port, void *buf, uint32_t nsect, } } +void ahci_sata_read(struct ahci_port_registers *port, void *buf, uint32_t nsect, uint64_t lba) { + ahci_sata_access(port, buf, nsect, lba, 0); +} + +void ahci_sata_write(struct ahci_port_registers *port, const void *buf, uint32_t nsect, uint64_t lba) { + ahci_sata_access(port, (void *) buf, nsect, lba, 1); +} + static void ahci_sata_port_identify(struct ahci_port_registers *port) { port->p_is = -1; diff --git a/sys/blk.c b/sys/blk.c index 8f1028c..77e1436 100644 --- a/sys/blk.c +++ b/sys/blk.c @@ -89,6 +89,20 @@ int blk_mount_auto(struct vfs_node *at, struct blkdev *blk, const char *opt) { return -1; } +static ssize_t blk_part_write(struct blkdev *dev, const void *buf, size_t off, size_t count) { + struct blk_part *part = (struct blk_part *) dev->dev_data; + size_t part_size_bytes = part->lba_size * 512; + size_t part_off_bytes = part->lba_start * 512; + + if (off >= part_size_bytes) { + return -1; + } + + size_t l = MIN(part_size_bytes - off, count); + + return blk_write(part->device, buf, off + part_off_bytes, l); +} + static ssize_t blk_part_read(struct blkdev *dev, void *buf, size_t off, size_t count) { struct blk_part *part = (struct blk_part *) dev->dev_data; size_t part_size_bytes = part->lba_size * 512; @@ -129,6 +143,7 @@ static int blk_enumerate_mbr(struct blkdev *dev, uint8_t *head) { blk->dev_data = part; blk->read = blk_part_read; + blk->write = blk_part_write; blk->ent_parent = dev->ent; ent->dev = blk; @@ -174,6 +189,7 @@ static int blk_enumerate_gpt(struct blkdev *dev, uint8_t *head) { blk->dev_data = part; blk->read = blk_part_read; + blk->write = blk_part_write; blk->ent_parent = dev->ent; ent->dev = blk; diff --git a/sys/vfs/ext2/ext2alloc.c b/sys/vfs/ext2/ext2alloc.c index 3780b13..87d267e 100644 --- a/sys/vfs/ext2/ext2alloc.c +++ b/sys/vfs/ext2/ext2alloc.c @@ -22,7 +22,7 @@ int ext2_alloc_block(fs_t *ext2, uint32_t *block_no) { for (size_t i = 0; i < sb->block_group_count; ++i) { if (sb->block_group_descriptor_table[i].free_blocks > 0) { // Found a free block here - kdebug("Allocating a block in group #%zu\n", i); + kdebug("Allocating a block in group #%u\n", i); if ((res = ext2_read_block(ext2, sb->block_group_descriptor_table[i].block_usage_bitmap_block, @@ -244,7 +244,7 @@ int ext2_alloc_inode(fs_t *ext2, uint32_t *ino) { for (size_t i = 0; i < sb->block_group_count; ++i) { if (sb->block_group_descriptor_table[i].free_inodes > 0) { // Found a block group with free inodes - kdebug("Allocating an inode inside block group #%zu\n", i); + kdebug("Allocating an inode inside block group #%u\n", i); // Read inode usage bitmap if ((res = ext2_read_block(ext2,