diff --git a/hw/fpga/sd_controller.sv b/hw/fpga/sd_controller.sv index b8f864f16f56a6193bbc118dfc449fee18171589..54b70019f109bd7a80d617d2549dce74b5d3aa61 100644 --- a/hw/fpga/sd_controller.sv +++ b/hw/fpga/sd_controller.sv @@ -24,7 +24,7 @@ logic [47:0] rxcmd_buf; logic [31:0] rx_val; logic [7:0] rxdata_buf [512]; -logic [9:0] data_count; +logic [8:0] data_count; logic [15:0] data_crc; @@ -89,7 +89,7 @@ always_ff @(posedge clk) begin end if (cs & addr == 4'h5 && sd_clk) begin - data_count <= data_count + 9'b1; + data_count <= data_count + 8'b1; end if (state.macro == RXCMD) begin @@ -102,6 +102,7 @@ always_ff @(posedge clk) begin if (state.macro == RXDCRC && ~sd_clk) begin data_crc[4'd15-state.count] <= i_sd_data; + data_count <= '0; end end @@ -135,6 +136,7 @@ always_comb begin end if (~i_sd_data) begin + next_state.d_bit_count = '1; next_state.macro = RXDATA; end diff --git a/sw/fat.h b/sw/fat.h new file mode 100644 index 0000000000000000000000000000000000000000..c61b1521e6201f2cf3a19cc74a5d53651468d6f2 --- /dev/null +++ b/sw/fat.h @@ -0,0 +1,77 @@ +#ifndef _FAT_H +#define _FAT_H + +#include <stdint.h> + +typedef struct { + uint16_t bytes_per_sector; + uint8_t sectors_per_cluster; + uint16_t reserved_sectors; + uint8_t fat_count; + uint16_t max_dir_entries; + uint16_t total_sector_count; + uint8_t media_descriptor; + uint16_t sectors_per_fat; +} dos_2_bpb_t; + +typedef struct { + dos_2_bpb_t bpb2; + uint16_t sectors_per_track; + uint16_t head_count; + uint32_t hidden_sector_count; + uint32_t logical_sector_count; + uint32_t sectors_per_fat; + uint16_t extended_flags; + uint16_t version; + uint32_t root_cluster; + uint16_t system_information; + uint16_t backup_boot_sector; + uint8_t reserved[12]; +} dos_3_bpb_t; + +typedef struct { + dos_3_bpb_t bpb3; + uint8_t drive_num; + uint8_t reserved; + uint8_t extended_signature; + uint32_t volume_id; + uint8_t partition_label[11]; + uint8_t filesystem_type[8]; +} ebpb_t; + +typedef struct { + uint32_t sig; + uint8_t reserved[480]; + uint32_t sig2; + uint32_t free_data_clusters; + uint32_t last_allocated_data_cluster; + uint32_t reserved2; + uint32_t sig3; +} fs_info_sector_t; + +typedef struct { + uint8_t sequence_number; + uint16_t filename0[5]; + uint8_t attributes; + uint8_t type; + uint8_t checksum; + uint16_t filename1[6]; + uint16_t reserved; + uint16_t filename[2]; +} vfat_dentry_t; + +typedef struct { + uint8_t filename[8]; + uint8_t extension[3]; + uint8_t attributes; + uint8_t reserved; + uint8_t create_time_10ms; + uint32_t create_date; + uint16_t access_date; + uint16_t first_cluster_h; + uint32_t modify_cluster; + uint16_t first_cluster_l; + uint32_t file_size; +} dos_dentry_t; + +#endif \ No newline at end of file diff --git a/sw/main.c b/sw/main.c index dc7182ba82ade5305fbf7b85ac715ae19e694e56..30332d048133507e5d77d973e1e58c01b22ca932 100644 --- a/sw/main.c +++ b/sw/main.c @@ -5,11 +5,84 @@ #include "uart.h" #include "mapper.h" #include "sd_card.h" +#include "fat.h" + +uint8_t buf[512]; + +void sd_readblock(uint32_t addr) { + uint32_t resp; + int i; + + sd_card_command(addr, 17); + sd_card_resp(&resp); + cprintf("CMD17: %lx\n", resp); + + sd_card_wait_for_data(); + + cprintf("Read data: \n"); + for (i = 0; i < 512; i++){ + buf[i] = sd_card_read_byte(); + } + + /* + for (i = 0; i < 512; i++){ + if (i % 16 == 0) + cprintf("\n %2x: ", i); + cprintf("%2x ", buf[i]); + } + */ + + cprintf("\n"); +} + +void print_pbp_info(ebpb_t* epbp){ + cprintf("Bytes per sector: %d\n", epbp->bpb3.bpb2.bytes_per_sector); + cprintf("Sectors per cluster: %d\n", epbp->bpb3.bpb2.sectors_per_cluster); + cprintf("Reserved Sectors: %d\n", epbp->bpb3.bpb2.reserved_sectors); + cprintf("Fat Count: %d\n", epbp->bpb3.bpb2.fat_count); + cprintf("Max Dir Entries: %d\n", epbp->bpb3.bpb2.max_dir_entries); + cprintf("Total Sector Count: %d\n", epbp->bpb3.bpb2.total_sector_count); + cprintf("Media Descriptor: 0x%x\n", epbp->bpb3.bpb2.media_descriptor); + cprintf("Sectors per Fat: %d\n", epbp->bpb3.bpb2.sectors_per_fat); + cprintf("\n"); + + cprintf("Sectors per track: %d\n", epbp->bpb3.sectors_per_track); + cprintf("Head Count: %d\n", epbp->bpb3.head_count); + cprintf("Hidden Sector Count: %ld\n", epbp->bpb3.hidden_sector_count); + cprintf("Logical Sector Count: %ld\n", epbp->bpb3.logical_sector_count); + cprintf("Sectors per Fat: %ld\n", epbp->bpb3.sectors_per_fat); + cprintf("Extended Flags: 0x%x\n", epbp->bpb3.extended_flags); + cprintf("Version: %d\n", epbp->bpb3.version); + cprintf("Root Cluster: 0x%lx\n", epbp->bpb3.root_cluster); + cprintf("System Information: 0x%x\n", epbp->bpb3.system_information); + cprintf("Backup Boot Sector: 0x%x\n", epbp->bpb3.backup_boot_sector); + cprintf("\n"); + + cprintf("Drive Number: %d\n", epbp->drive_num); + cprintf("Extended Signature: 0x%x\n", epbp->extended_signature); + cprintf("Volume ID: 0x%lx\n", epbp->volume_id); + cprintf("Partition Label: %.11s\n", &epbp->partition_label); + cprintf("Partition Label: %.8s\n", &epbp->filesystem_type); + cprintf("\n"); +} int main() { int i; uint8_t sw; uint32_t resp; + ebpb_t* epbp; + fs_info_sector_t* fsis; + vfat_dentry_t* vfat_dentry; + dos_dentry_t* dos_dentry; + uint32_t cluster; + + + uint16_t reserved_count; + uint32_t sectors_per_fat; + uint8_t fat_count; + + uint32_t data_region_start; + char s[16]; s[15] = 0; @@ -17,36 +90,13 @@ int main() { cprintf("Hello, world!\n"); for (i = 0; i < 16; i++){ - cprintf("Mapping %1xxxx to %2xxxx\n", i, i); + //cprintf("Mapping %1xxxx to %2xxxx\n", i, i); mapper_write(i, i); } cprintf("Enabling Mapper\n"); mapper_enable(1); - cprintf("Writing 0xcccc to 0x4000\n"); - *(unsigned int*)(0x4000) = 0xcccc; - - cprintf("Writing 0xdddd to 0x5000\n"); - *(unsigned int*)(0x5000) = 0xdddd; - - cprintf("Mapping %1xxxx to %2xxxx\n", 4, 16); - mapper_write(16, 4); - - cprintf("Mapping %1xxxx to %2xxxx\n", 5, 16); - mapper_write(16, 5); - - cprintf("Writing 0xa5a5 to 0x4000\n"); - *(unsigned int*)(0x4000) = 0xa5a5; - - cprintf("Reading from 0x5000: %x\n", *(unsigned int*)(0x5000)); - - cprintf("Resetting map\n"); - mapper_write(4, 4); - mapper_write(5, 5); - - cprintf("Reading from 0x4000: %x\n", *(unsigned int*)(0x4000)); - cprintf("Reading from 0x5000: %x\n", *(unsigned int*)(0x5000)); // This will read a 512 block from the sd card. // The RCA is hard coded for the one that I have on hand as responses @@ -83,19 +133,77 @@ int main() { sd_card_resp(&resp); cprintf("CMD13: %lx\n", resp); - sd_card_command(0, 17); - sd_card_resp(&resp); - cprintf("CMD17: %lx\n", resp); + sd_readblock(0); + epbp = (ebpb_t*)&buf[11]; - while(sw_read()); + print_pbp_info(epbp); - sd_card_wait_for_data(); + cprintf("Boot Signature: %x %x\n", buf[510], buf[511]); - cprintf("Read data: \n"); - for (i = 0; i < 512; i++){ - cprintf("%c", sd_card_read_byte()); + reserved_count = epbp->bpb3.bpb2.reserved_sectors; + fat_count = epbp->bpb3.bpb2.fat_count; + sectors_per_fat = epbp->bpb3.sectors_per_fat; + + sd_readblock(1); + + fsis = (fs_info_sector_t*)&buf[0]; + + cprintf("Free Data clusters: %ld\n", fsis->free_data_clusters); + cprintf("Last allocated data cluster: %ld\n", fsis->last_allocated_data_cluster); + + cprintf("32 reserved sectors, reading from sector 32...\n"); + sd_readblock(32); + cprintf("CLUST_0: %08lx\n", *(uint32_t*)&buf[0]); + cprintf("CLUST_1: %08lx\n", *(uint32_t*)&buf[1*4]); + + cprintf("Root cluster: %08lx\n", *(uint32_t*)&buf[2*4]); + + data_region_start = reserved_count + fat_count*sectors_per_fat; + cprintf("Data Region starting sector: %lx\n", data_region_start); + cprintf("Reading root directory entry...\n"); + + cprintf("%ld\n", data_region_start*512); + + sd_readblock(data_region_start); + + vfat_dentry = (vfat_dentry_t*)buf; + while(vfat_dentry->sequence_number == 0xe5) + vfat_dentry++; + + + cprintf("Sequence: %x\n", vfat_dentry->sequence_number); + cprintf("Name: "); + for (i = 0;; i++) { // this will not work for proper vfat names + if (i < 5) { + if (!vfat_dentry->filename0[i]) + break; + cprintf("%c", vfat_dentry->filename0[i]); + } else if (i < 11) { + if (!vfat_dentry->filename0[i]) + break; + cprintf("%c", vfat_dentry->filename1[i-5]); + } else { + break; + } } + cprintf("\n"); + dos_dentry = (dos_dentry_t*)(vfat_dentry + 1); + + cprintf("DOS name: %.8s.%.3s\n", &dos_dentry->filename, &dos_dentry->extension); + + cluster = (dos_dentry->first_cluster_h << 16) + dos_dentry->first_cluster_l; + cprintf("Cluster: %ld\n", cluster); + + cprintf("File location: %lx\n", data_region_start + (cluster - 2) * 8); + + sd_readblock(data_region_start + (cluster - 2) * 8); + + cprintf("File contents: %s\n", buf); + + cprintf("Done!\n"); + + while (1) {