diff --git a/sw/kernel/filesystems/fat32.h b/sw/kernel/filesystems/fat32.h index 50b508d..e9c97ad 100644 --- a/sw/kernel/filesystems/fat32.h +++ b/sw/kernel/filesystems/fat32.h @@ -12,6 +12,7 @@ extern uint32_t data_start_sector; extern uint32_t fat_size; extern uint8_t* sd_buf; extern uint8_t sectors_per_cluster; +extern uint8_t log2_sectors_per_cluster; struct fat32_directory_entry { char file_name[8]; @@ -41,7 +42,7 @@ struct lfn_entry { }; int8_t fat32_get_cluster_by_name(const char* name, struct fat32_directory_entry* dentry); -int8_t fat32_read_cluster(uint32_t cluster, void* buf); +int8_t fat32_read_sector(uint32_t cluster, uint32_t sector, void* buf); uint32_t fat32_next_cluster(uint32_t cluster); int8_t fat32_file_open(const char* filename); diff --git a/sw/kernel/filesystems/fat32.s b/sw/kernel/filesystems/fat32.s index 9b62b85..6e6346f 100644 --- a/sw/kernel/filesystems/fat32.s +++ b/sw/kernel/filesystems/fat32.s @@ -10,7 +10,7 @@ .export _fat32_init .export _root_cluster, _fat_start_sector, _data_start_sector -.export _fat_size, _sd_buf, _sectors_per_cluster +.export _fat_size, _sd_buf, _sectors_per_cluster, _log2_sectors_per_cluster .data @@ -19,6 +19,7 @@ _fat_start_sector: .res 2 _data_start_sector: .res 4 _fat_size: .res 4 _sectors_per_cluster: .res 1 +_log2_sectors_per_cluster: .res 1 _sd_buf: .res 512 @@ -52,6 +53,16 @@ root_cluster_offs = _sd_buf + $2C lda sectors_per_cluster sta _sectors_per_cluster + ldx #$0 +@1: bit #$01 + bne L0 + inx + lsr + bra @1 + +L0: txa + sta _log2_sectors_per_cluster + ldx #$00 L1: lda root_cluster_offs,x sta _root_cluster,x diff --git a/sw/kernel/filesystems/fat32_c.c b/sw/kernel/filesystems/fat32_c.c index 433b6a6..a391212 100644 --- a/sw/kernel/filesystems/fat32_c.c +++ b/sw/kernel/filesystems/fat32_c.c @@ -80,9 +80,12 @@ size_t fat32_file_read(int8_t fd, void* buf, size_t nbytes) { size_t leftover_length; size_t bytes_read = 0; size_t clusters; + uint32_t sector; struct pcb* pcb = get_pcb_ptr(); struct file_desc* fdesc = &pcb->file_desc_array[fd]; - uint32_t cluster_seq = fdesc->file_pos >> 9; + + uint32_t cluster_seq = fdesc->file_pos >> (9 + log2_sectors_per_cluster); + uint32_t cluster = ((uint32_t)fdesc->f32_dentry.cluster_high << 16) | fdesc->f32_dentry.cluster_low; /* validate starting position isn't past end of file */ @@ -95,28 +98,30 @@ size_t fat32_file_read(int8_t fd, void* buf, size_t nbytes) { } + // This can stay for now, as long as cluster_seq is correct. for (i = 0; i < cluster_seq; i++) { cluster = fat32_next_cluster(cluster); } - // This is an upper bound. It is possible that a 512 chunk can span - // 2 clusters, but the first one will already be handled. - clusters = nbytes >> 9; + clusters = nbytes >> (9 + log2_sectors_per_cluster); /* Handle first unaligned block */ - offset = fdesc->file_pos % 512; + offset = fdesc->file_pos % 512; // This is the offset into the sector, not the cluster leftover_length = 512 - offset; + sector = (fdesc->file_pos >> 9) & (sectors_per_cluster-1); + if (leftover_length != 0) { if (nbytes <= leftover_length) { - fat32_read_cluster(cluster, sd_buf); + + fat32_read_sector(cluster, sector, sd_buf); memcpy(buf, sd_buf + offset, nbytes); bytes_read += nbytes; fdesc->file_pos += bytes_read; return bytes_read; } else { - fat32_read_cluster(cluster, sd_buf); + fat32_read_sector(cluster, sector, sd_buf); memcpy(buf, sd_buf + offset, leftover_length); bytes_read += leftover_length; fdesc->file_pos += bytes_read; @@ -137,7 +142,7 @@ size_t fat32_file_read(int8_t fd, void* buf, size_t nbytes) { leftover_length = nbytes - bytes_read; } - fat32_read_cluster(cluster, sd_buf); + fat32_read_sector(cluster, cluster, sd_buf); memcpy((uint8_t*)buf+bytes_read, sd_buf, leftover_length); bytes_read += leftover_length; fdesc->file_pos += bytes_read; @@ -149,9 +154,12 @@ size_t fat32_file_read(int8_t fd, void* buf, size_t nbytes) { return bytes_read; } -int8_t fat32_read_cluster(uint32_t cluster, void* buf) { +// Read the sector offset from a given cluster into buf +// Why do we need this though, this is just doing a single multiplication? +// No, it is also doing an addition +int8_t fat32_read_sector(uint32_t cluster, uint32_t sector, void* buf) { uint8_t error; - uint32_t addr = (cluster - 2) + data_start_sector; + uint32_t addr = (cluster - 2) * sectors_per_cluster + sector + data_start_sector; SD_readSingleBlock(addr, buf, &error); return error; } @@ -176,7 +184,7 @@ int8_t fat32_get_cluster_by_name(const char* name, struct fat32_directory_entry* cprintf("Sectors per cluster: %hhx\n", sectors_per_cluster); - fat32_read_cluster(root_cluster, sd_buf); + fat32_read_sector(root_cluster, 0, sd_buf); for (i = 0; i < 16; i++){ local_entry = (struct fat32_directory_entry*)(sd_buf + i*32); if (local_entry->attr1 == 0xf || local_entry->attr1 & 0x8 || !local_entry->attr1) { diff --git a/sw/kernel/process/process.c b/sw/kernel/process/process.c index 489b371..cbc5210 100644 --- a/sw/kernel/process/process.c +++ b/sw/kernel/process/process.c @@ -1,6 +1,9 @@ #include +struct pcb fake_pcb; + +//TODO struct pcb* get_pcb_ptr() { - return 0; + return &fake_pcb; } \ No newline at end of file diff --git a/sw/test_code/fs_test/main.c b/sw/test_code/fs_test/main.c index 974fa85..62042cf 100644 --- a/sw/test_code/fs_test/main.c +++ b/sw/test_code/fs_test/main.c @@ -12,6 +12,8 @@ int main(void) { size_t nbytes; fat32_init(); + cprintf("log2 sectors per cluster: %x\n", log2_sectors_per_cluster); + /* This is what is going to be part of open */ fd = fat32_file_open("VERYLA~1TXT"); cprintf("fd: %x\n", fd);