ata: deal in pages, not sectors
This commit is contained in:
parent
32e99ff897
commit
7c0f882178
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user