From 7c0f8821781c2ddf5eeb2709020ba4e612514319 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Tue, 16 Nov 2021 08:56:14 +0900 Subject: [PATCH] ata: deal in pages, not sectors --- modules/ata.c | 83 +++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/modules/ata.c b/modules/ata.c index e9c9a029..798c49a2 100644 --- a/modules/ata.c +++ b/modules/ata.c @@ -197,6 +197,7 @@ static spin_lock_t atapi_cmd_lock = { 0 }; /* TODO support other sector sizes */ #define ATA_SECTOR_SIZE 512 +#define ATA_CACHE_SIZE 4096 static void ata_device_read_sector(struct ata_device * dev, uint64_t lba, uint8_t * buf); static void ata_device_read_sector_atapi(struct ata_device * dev, uint64_t lba, uint8_t * buf); @@ -283,8 +284,8 @@ static off_t atapi_max_offset(struct ata_device * dev) { static ssize_t read_ata(fs_node_t *node, off_t offset, size_t size, uint8_t *buffer) { struct ata_device * dev = (struct ata_device *)node->device; - unsigned int start_block = offset / ATA_SECTOR_SIZE; - unsigned int end_block = (offset + size - 1) / ATA_SECTOR_SIZE; + unsigned int start_block = offset / ATA_CACHE_SIZE; + unsigned int end_block = (offset + size - 1) / ATA_CACHE_SIZE; unsigned int x_offset = 0; @@ -297,13 +298,13 @@ static ssize_t read_ata(fs_node_t *node, off_t offset, size_t size, uint8_t *buf size = i; } - if (offset % ATA_SECTOR_SIZE || size < ATA_SECTOR_SIZE) { - unsigned int prefix_size = (ATA_SECTOR_SIZE - (offset % ATA_SECTOR_SIZE)); + if (offset % ATA_CACHE_SIZE || size < ATA_CACHE_SIZE) { + unsigned int prefix_size = (ATA_CACHE_SIZE - (offset % ATA_CACHE_SIZE)); if (prefix_size > size) prefix_size = size; - char * tmp = malloc(ATA_SECTOR_SIZE); + char * tmp = malloc(ATA_CACHE_SIZE); ata_device_read_sector(dev, start_block, (uint8_t *)tmp); - memcpy(buffer, (void *)((uintptr_t)tmp + ((uintptr_t)offset % ATA_SECTOR_SIZE)), prefix_size); + memcpy(buffer, (void *)((uintptr_t)tmp + ((uintptr_t)offset % ATA_CACHE_SIZE)), prefix_size); free(tmp); @@ -311,9 +312,9 @@ static ssize_t read_ata(fs_node_t *node, off_t offset, size_t size, uint8_t *buf start_block++; } - if ((offset + size) % ATA_SECTOR_SIZE && start_block <= end_block) { - unsigned int postfix_size = (offset + size) % ATA_SECTOR_SIZE; - char * tmp = malloc(ATA_SECTOR_SIZE); + if ((offset + size) % ATA_CACHE_SIZE && start_block <= end_block) { + unsigned int postfix_size = (offset + size) % ATA_CACHE_SIZE; + char * tmp = malloc(ATA_CACHE_SIZE); ata_device_read_sector(dev, end_block, (uint8_t *)tmp); memcpy((void *)((uintptr_t)buffer + size - postfix_size), tmp, postfix_size); @@ -325,7 +326,7 @@ static ssize_t read_ata(fs_node_t *node, off_t offset, size_t size, uint8_t *buf while (start_block <= end_block) { ata_device_read_sector(dev, start_block, (uint8_t *)((uintptr_t)buffer + x_offset)); - x_offset += ATA_SECTOR_SIZE; + x_offset += ATA_CACHE_SIZE; start_block++; } @@ -389,8 +390,8 @@ static ssize_t read_atapi(fs_node_t *node, off_t offset, size_t size, uint8_t *b static ssize_t write_ata(fs_node_t *node, off_t offset, size_t size, uint8_t *buffer) { struct ata_device * dev = (struct ata_device *)node->device; - unsigned int start_block = offset / ATA_SECTOR_SIZE; - unsigned int end_block = (offset + size - 1) / ATA_SECTOR_SIZE; + unsigned int start_block = offset / ATA_CACHE_SIZE; + unsigned int end_block = (offset + size - 1) / ATA_CACHE_SIZE; unsigned int x_offset = 0; @@ -403,13 +404,13 @@ static ssize_t write_ata(fs_node_t *node, off_t offset, size_t size, uint8_t *bu size = i; } - if (offset % ATA_SECTOR_SIZE) { - unsigned int prefix_size = (ATA_SECTOR_SIZE - (offset % ATA_SECTOR_SIZE)); + if (offset % ATA_CACHE_SIZE) { + unsigned int prefix_size = (ATA_CACHE_SIZE - (offset % ATA_CACHE_SIZE)); - char * tmp = malloc(ATA_SECTOR_SIZE); + char * tmp = malloc(ATA_CACHE_SIZE); ata_device_read_sector(dev, start_block, (uint8_t *)tmp); - memcpy((void *)((uintptr_t)tmp + ((uintptr_t)offset % ATA_SECTOR_SIZE)), buffer, prefix_size); + memcpy((void *)((uintptr_t)tmp + ((uintptr_t)offset % ATA_CACHE_SIZE)), buffer, prefix_size); ata_device_write_sector(dev, start_block, (uint8_t *)tmp); free(tmp); @@ -417,10 +418,10 @@ static ssize_t write_ata(fs_node_t *node, off_t offset, size_t size, uint8_t *bu start_block++; } - if ((offset + size) % ATA_SECTOR_SIZE && start_block <= end_block) { - unsigned int postfix_size = (offset + size) % ATA_SECTOR_SIZE; + if ((offset + size) % ATA_CACHE_SIZE && start_block <= end_block) { + unsigned int postfix_size = (offset + size) % ATA_CACHE_SIZE; - char * tmp = malloc(ATA_SECTOR_SIZE); + char * tmp = malloc(ATA_CACHE_SIZE); ata_device_read_sector(dev, end_block, (uint8_t *)tmp); memcpy(tmp, (void *)((uintptr_t)buffer + size - postfix_size), postfix_size); @@ -433,7 +434,7 @@ static ssize_t write_ata(fs_node_t *node, off_t offset, size_t size, uint8_t *bu while (start_block <= end_block) { ata_device_write_sector(dev, start_block, (uint8_t *)((uintptr_t)buffer + x_offset)); - x_offset += ATA_SECTOR_SIZE; + x_offset += ATA_CACHE_SIZE; start_block++; } @@ -613,7 +614,7 @@ static void ata_device_init(struct ata_device * dev) { dev->dma_prdt = (void *)kvmalloc_p(sizeof(prdt_t) * 1, &dev->dma_prdt_phys); dev->dma_start = (void *)kvmalloc_p(4096, &dev->dma_start_phys); dev->dma_prdt[0].offset = dev->dma_start_phys; - dev->dma_prdt[0].bytes = 512; + dev->dma_prdt[0].bytes = ATA_CACHE_SIZE; dev->dma_prdt[0].last = 0x8000; uint16_t command_reg = pci_read_field(ata_pci, PCI_COMMAND, 4); @@ -794,12 +795,12 @@ static int ata_device_detect(struct ata_device * dev) { static void ata_device_read_sector(struct ata_device * dev, uint64_t lba, uint8_t * buf) { /* Submit request */ struct DataRequest req; - ata_enqueue_request(&req, dev,lba,1,NULL); + ata_enqueue_request(&req, dev, lba * 8, 1, NULL); if (!req.resolved) { dprintf("ata: Unresolved request?\n"); } else { - memcpy(buf, req.buf, 512); + memcpy(buf, req.buf, ATA_CACHE_SIZE); free(req.buf); } } @@ -839,7 +840,7 @@ static void ata_device_read_sector_actual(struct ata_device * dev, uint64_t lba) outportb(bus + ATA_REG_LBA1, (lba & 0xff00000000) >> 32); outportb(bus + ATA_REG_LBA2, (lba & 0xff0000000000) >> 40); - outportb(bus + ATA_REG_SECCOUNT0, 1); + outportb(bus + ATA_REG_SECCOUNT0, 8); outportb(bus + ATA_REG_LBA0, (lba & 0x000000ff) >> 0); outportb(bus + ATA_REG_LBA1, (lba & 0x0000ff00) >> 8); outportb(bus + ATA_REG_LBA2, (lba & 0x00ff0000) >> 16); @@ -957,10 +958,10 @@ atapi_timeout: static void ata_device_write_sector(struct ata_device * dev, uint64_t lba, uint8_t * buf) { /* Submit request */ - char * tmp = malloc(512); - memcpy(tmp, buf, 512); + char * tmp = malloc(ATA_CACHE_SIZE); + memcpy(tmp, buf, ATA_CACHE_SIZE); struct DataRequest req; - ata_enqueue_request(&req, dev,lba,2,tmp); + ata_enqueue_request(&req, dev,lba * 8, 2, tmp); if (!req.resolved) { dprintf("ata: Unresolved write request?\n"); @@ -995,7 +996,7 @@ static void ata_device_write_sector_actual(struct ata_device * dev, uint64_t lba outportb(bus + ATA_REG_LBA1, (lba & 0xff00000000) >> 32); outportb(bus + ATA_REG_LBA2, (lba & 0xff0000000000) >> 40); - outportb(bus + ATA_REG_SECCOUNT0, 1); + outportb(bus + ATA_REG_SECCOUNT0, 8); outportb(bus + ATA_REG_LBA0, (lba & 0x000000ff) >> 0); outportb(bus + ATA_REG_LBA1, (lba & 0x0000ff00) >> 8); outportb(bus + ATA_REG_LBA2, (lba & 0x00ff0000) >> 16); @@ -1033,13 +1034,13 @@ struct CacheEntry { uint64_t flags; }; -#define CACHE_COUNT 10240 +#define CACHE_COUNT 4096 static void ata_scheduler(void * data) { /* Allocate some cache space */ struct CacheEntry * cache_entries = malloc(sizeof(struct CacheEntry) * CACHE_COUNT); memset(cache_entries, 0, sizeof(struct CacheEntry) * CACHE_COUNT); - char * cache_blocks = mmu_map_module(CACHE_COUNT * 512); + char * cache_blocks = mmu_map_module(CACHE_COUNT * ATA_CACHE_SIZE); uint64_t counter = 1; while (1) { @@ -1055,6 +1056,7 @@ static void ata_scheduler(void * data) { /* Is it in the cache? */ int found = 0; int oldest = 0; + uint64_t lu = -1; for (int i = 0; i < CACHE_COUNT; ++i) { if (cache_entries[i].dev == req->dev && cache_entries[i].lba == req->lba) { //dprintf("ata: cache hit\n"); @@ -1065,32 +1067,34 @@ static void ata_scheduler(void * data) { } else if (cache_entries[i].dev == NULL) { oldest = i; break; - } else if (cache_entries[i].last_use < cache_entries[oldest].last_use) { + } else if (cache_entries[i].last_use < lu) { oldest = i; + lu = cache_entries[oldest].last_use; } } if (!found) { miss_count++; if (cache_entries[oldest].dev && cache_entries[oldest].flags & 1) { eviction_count++; - memcpy(cache_entries[oldest].dev->dma_start, cache_blocks + oldest * 512, 512); + memcpy(cache_entries[oldest].dev->dma_start, cache_blocks + oldest * ATA_CACHE_SIZE, ATA_CACHE_SIZE); ata_device_write_sector_actual(cache_entries[oldest].dev, cache_entries[oldest].lba); } ata_device_read_sector_actual(req->dev, req->lba); cache_entries[oldest].dev = req->dev; cache_entries[oldest].lba = req->lba; cache_entries[oldest].flags = 0; - memcpy(cache_blocks + oldest * 512, req->dev->dma_start, 512); + memcpy(cache_blocks + oldest * ATA_CACHE_SIZE, req->dev->dma_start, ATA_CACHE_SIZE); } cache_entries[oldest].last_use = counter++; - req->buf = malloc(512); - memcpy(req->buf, cache_blocks + 512 * oldest, 512); + req->buf = malloc(ATA_CACHE_SIZE); + memcpy(req->buf, cache_blocks + ATA_CACHE_SIZE * oldest, ATA_CACHE_SIZE); ata_respond(req); break; } case 2: { int found = 0; int oldest = 0; + uint64_t lu = -1; for (int i = 0; i < CACHE_COUNT; ++i) { if (cache_entries[i].dev == req->dev && cache_entries[i].lba == req->lba) { //dprintf("ata: cache hit\n"); @@ -1101,15 +1105,16 @@ static void ata_scheduler(void * data) { } else if (cache_entries[i].dev == NULL) { oldest = i; break; - } else if (cache_entries[i].last_use < cache_entries[oldest].last_use) { + } else if (cache_entries[i].last_use < lu) { oldest = i; + lu = cache_entries[oldest].last_use; } } if (!found) { miss_count++; if (cache_entries[oldest].dev && cache_entries[oldest].flags & 1) { eviction_count++; - memcpy(cache_entries[oldest].dev->dma_start, cache_blocks + oldest * 512, 512); + memcpy(cache_entries[oldest].dev->dma_start, cache_blocks + oldest * ATA_CACHE_SIZE, ATA_CACHE_SIZE); ata_device_write_sector_actual(cache_entries[oldest].dev, cache_entries[oldest].lba); } cache_entries[oldest].dev = req->dev; @@ -1117,7 +1122,7 @@ static void ata_scheduler(void * data) { } write_count++; cache_entries[oldest].last_use = counter++; - memcpy(cache_blocks + oldest * 512, req->buf, 512); + memcpy(cache_blocks + oldest * ATA_CACHE_SIZE, req->buf, ATA_CACHE_SIZE); cache_entries[oldest].flags = 1; free(req->buf); ata_respond(req); @@ -1127,7 +1132,7 @@ static void ata_scheduler(void * data) { for (int i = 0; i < CACHE_COUNT; ++i) { if (cache_entries[i].dev == req->dev && cache_entries[i].flags & 1) { eviction_count++; - memcpy(cache_entries[i].dev->dma_start, cache_blocks + i * 512, 512); + memcpy(cache_entries[i].dev->dma_start, cache_blocks + i * ATA_CACHE_SIZE, ATA_CACHE_SIZE); ata_device_write_sector_actual(cache_entries[i].dev, cache_entries[i].lba); cache_entries[i].flags = 0; }