Merge branch '15-parse-the-read-only-file-system' into 'master'
Resolve "Parse the read-only file system" Closes #15 See merge request bslathi19/super6502!64
This commit is contained in:
@@ -140,6 +140,24 @@ mapper_code sim:
|
||||
- TEST_PROGRAM_NAME=mapper_test make mapper_code_tb
|
||||
- ./mapper_code_tb
|
||||
|
||||
multiplier_code sim:
|
||||
tags:
|
||||
- linux
|
||||
- iverilog
|
||||
stage: simulate
|
||||
needs:
|
||||
- job: build toolchain
|
||||
artifacts: true
|
||||
artifacts:
|
||||
paths:
|
||||
- hw/efinix_fpga/simulation/mapper_code_tb.vcd
|
||||
script:
|
||||
- source init_env.sh
|
||||
- cd hw/efinix_fpga/simulation
|
||||
- make clean
|
||||
- TEST_PROGRAM_NAME=multiplier_test make mapper_code_tb
|
||||
- ./mapper_code_tb
|
||||
|
||||
interrupt_controller sim:
|
||||
tags:
|
||||
- linux
|
||||
|
||||
2
sw/cc65
2
sw/cc65
Submodule sw/cc65 updated: 58518b6ff5...9824f6e3d4
1
sw/fsdir/test.txt
Normal file
1
sw/fsdir/test.txt
Normal file
@@ -0,0 +1 @@
|
||||
This is a text file, which is composed of text.
|
||||
33
sw/fsdir/verylargetextwithverylongname.txt
Normal file
33
sw/fsdir/verylargetextwithverylongname.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
very large text file with a very long name
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
|
||||
~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?~!@#$%^&*()_+`1234567890-=[]\{}|;':",./<>?
|
||||
@@ -11,3 +11,20 @@ SPI_INPUT = $efd9
|
||||
SPI_OUTPUT = $efda
|
||||
SPI_CTRL = $efdb
|
||||
SPI_STATUS = SPI_CTRL
|
||||
|
||||
MULTIPLIER_BASE = $eff0
|
||||
|
||||
MULTIPLIER_AL = MULTIPLIER_BASE + 0
|
||||
MULTIPLIER_AH = MULTIPLIER_BASE + 1
|
||||
MULTIPLIER_BL = MULTIPLIER_BASE + 2
|
||||
MULTIPLIER_BH = MULTIPLIER_BASE + 3
|
||||
|
||||
MULTIPLIER_OLL = MULTIPLIER_BASE + 4
|
||||
MULTIPLIER_OLH = MULTIPLIER_BASE + 5
|
||||
MULTIPLIER_OHL = MULTIPLIER_BASE + 6
|
||||
MULTIPLIER_OHH = MULTIPLIER_BASE + 7
|
||||
|
||||
GOLDEN_OUTPUT_0 = $03
|
||||
GOLDEN_OUTPUT_1 = $0a
|
||||
GOLDEN_OUTPUT_2 = $08
|
||||
GOLDEN_OUTPUT_3 = $00
|
||||
12
sw/kernel/devices/multiplier.h
Normal file
12
sw/kernel/devices/multiplier.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef _MULTIPLER_H
|
||||
#define _MULTIPLER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Multiply 2 integers into 1 long */
|
||||
uint32_t lmulii(uint16_t a, uint16_t b);
|
||||
|
||||
/* Multiply 2 integers into 1 integer, discarding upper bits. */
|
||||
uint16_t imulii(uint16_t a, uint16_t b);
|
||||
|
||||
#endif
|
||||
36
sw/kernel/devices/multiplier.s
Normal file
36
sw/kernel/devices/multiplier.s
Normal file
@@ -0,0 +1,36 @@
|
||||
.include "io.inc65"
|
||||
|
||||
.MACPACK generic
|
||||
|
||||
.import popax
|
||||
.importzp sreg
|
||||
|
||||
.export _lmulii, _imulii
|
||||
|
||||
.code
|
||||
|
||||
.proc _lmulii
|
||||
sta MULTIPLIER_BL
|
||||
stx MULTIPLIER_BH
|
||||
jsr popax
|
||||
sta MULTIPLIER_AL
|
||||
stx MULTIPLIER_AH
|
||||
lda MULTIPLIER_OHL
|
||||
sta sreg
|
||||
lda MULTIPLIER_OHH
|
||||
sta sreg+1
|
||||
lda MULTIPLIER_OLL
|
||||
ldx MULTIPLIER_OLH
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.proc _imulii
|
||||
sta MULTIPLIER_BL
|
||||
stx MULTIPLIER_BH
|
||||
jsr popax
|
||||
sta MULTIPLIER_AL
|
||||
stx MULTIPLIER_AH
|
||||
lda MULTIPLIER_OLL
|
||||
ldx MULTIPLIER_OLH
|
||||
rts
|
||||
.endproc
|
||||
53
sw/kernel/filesystems/fat32.h
Normal file
53
sw/kernel/filesystems/fat32.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef _FAT32_H
|
||||
#define _FAT32_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void fat32_init();
|
||||
|
||||
extern uint32_t root_cluster;
|
||||
extern uint16_t fat_start_sector;
|
||||
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];
|
||||
char file_ext[3];
|
||||
uint8_t attr1;
|
||||
uint8_t attr2;
|
||||
uint8_t create_time_10ms;
|
||||
uint16_t create_time;
|
||||
uint16_t create_date;
|
||||
uint16_t access_date;
|
||||
uint16_t cluster_high;
|
||||
uint16_t modified_time;
|
||||
uint16_t modified_date;
|
||||
uint16_t cluster_low;
|
||||
uint32_t file_size;
|
||||
};
|
||||
|
||||
struct lfn_entry {
|
||||
uint8_t sequence_number;
|
||||
uint16_t name_0[5];
|
||||
uint8_t attributes;
|
||||
uint8_t type;
|
||||
uint8_t checksum;
|
||||
uint16_t name_1[6];
|
||||
uint16_t cluster_low;
|
||||
uint16_t name_2[2];
|
||||
};
|
||||
|
||||
int8_t fat32_get_cluster_by_name(const char* name, struct fat32_directory_entry* dentry);
|
||||
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);
|
||||
size_t fat32_file_read(int8_t fd, void* buf, size_t nbytes);
|
||||
size_t fat32_file_write(int8_t fd, const void* buf, size_t nbytes);
|
||||
int8_t fat32_file_close(int8_t fd);
|
||||
|
||||
#endif
|
||||
112
sw/kernel/filesystems/fat32.s
Normal file
112
sw/kernel/filesystems/fat32.s
Normal file
@@ -0,0 +1,112 @@
|
||||
.MACPACK generic
|
||||
|
||||
.autoimport
|
||||
.feature string_escapes
|
||||
|
||||
.importzp ptr1, sreg
|
||||
|
||||
.import _SD_readSingleBlock
|
||||
|
||||
.export _fat32_init
|
||||
|
||||
.export _root_cluster, _fat_start_sector, _data_start_sector
|
||||
.export _fat_size, _sd_buf, _sectors_per_cluster, _log2_sectors_per_cluster
|
||||
|
||||
|
||||
.data
|
||||
_root_cluster: .res 4
|
||||
_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
|
||||
|
||||
data_start_sect_str: .asciiz "Data sector start: 0x%lx\n"
|
||||
starting_cluster_str: .asciiz "Root cluster num: %lx\n";
|
||||
value_str: .asciiz "Value: 0x%x\n"
|
||||
|
||||
.code
|
||||
|
||||
bytes_per_sector = _sd_buf + $0B
|
||||
sectors_per_cluster = _sd_buf + $0D
|
||||
reserved_sectors = _sd_buf + $0E
|
||||
fat_count = _sd_buf + $10
|
||||
sectors_per_fat = _sd_buf + $24
|
||||
root_cluster_offs = _sd_buf + $2C
|
||||
|
||||
.proc _fat32_init
|
||||
; load sector 0 into sd_buf
|
||||
lda #$00
|
||||
ldx #$00
|
||||
stz sreg
|
||||
stz sreg+1
|
||||
jsr pusheax
|
||||
lda #<_sd_buf
|
||||
ldx #>_sd_buf
|
||||
jsr pushax
|
||||
lda #<ptr1
|
||||
ldx #>ptr1
|
||||
jsr _SD_readSingleBlock
|
||||
|
||||
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
|
||||
inx
|
||||
cpx #$4
|
||||
blt L1
|
||||
|
||||
; Multiply reserved sectors and bytes per sector, then divide by 512 to get sd sectors
|
||||
lda reserved_sectors
|
||||
jsr pusha0
|
||||
lda bytes_per_sector
|
||||
ldx bytes_per_sector+1
|
||||
jsr _imulii
|
||||
txa
|
||||
lsr
|
||||
sta _fat_start_sector
|
||||
stz _fat_start_sector + 1
|
||||
|
||||
; multiply fat size and number of fats to get total fat size
|
||||
lda fat_count
|
||||
jsr pusha0
|
||||
lda sectors_per_fat
|
||||
ldx sectors_per_fat+1
|
||||
jsr _lmulii
|
||||
sta _fat_size
|
||||
stx _fat_size+1
|
||||
lda sreg
|
||||
sta _fat_size+2
|
||||
lda sreg+1
|
||||
sta _fat_size+3
|
||||
|
||||
|
||||
; Add fat size to starting fat sector to get data start sector
|
||||
clc
|
||||
lda _fat_size
|
||||
adc _fat_start_sector
|
||||
sta _data_start_sector
|
||||
lda _fat_size+1
|
||||
adc _fat_start_sector+1
|
||||
sta _data_start_sector+1
|
||||
lda _fat_size+2
|
||||
sta _data_start_sector+2
|
||||
lda _fat_size+3
|
||||
sta _data_start_sector+3
|
||||
|
||||
rts
|
||||
.endproc
|
||||
207
sw/kernel/filesystems/fat32_c.c
Normal file
207
sw/kernel/filesystems/fat32_c.c
Normal file
@@ -0,0 +1,207 @@
|
||||
#include <devices/sd_card.h>
|
||||
#include <process/process.h>
|
||||
#include <conio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fat32.h"
|
||||
#include "fs.h"
|
||||
|
||||
static struct fops fat32_file_ops = {fat32_file_open, fat32_file_close, fat32_file_read, fat32_file_write};
|
||||
|
||||
int8_t fd_val;
|
||||
|
||||
|
||||
//TODO
|
||||
size_t fat32_file_write(int8_t fd, const void* buf, size_t nbytes) {
|
||||
(void)fd;
|
||||
(void)buf;
|
||||
(void)nbytes;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* file_close
|
||||
* DESCRIPTION: close device abstracted as file
|
||||
* INPUTS: fd -- file descriptor for file to be closed
|
||||
* OUTPUTS: none
|
||||
* RETURN VALUE: none
|
||||
* SIDE EFFECTS: none
|
||||
*/
|
||||
int8_t fat32_file_close(int8_t fd) {
|
||||
struct pcb* pcb;
|
||||
pcb = get_pcb_ptr();
|
||||
|
||||
/* update pcb to remove process */
|
||||
pcb->file_desc_array[fd].flags = !IN_USE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t fat32_file_open(const char* filename) {
|
||||
int8_t ret;
|
||||
int8_t i;
|
||||
int8_t fd;
|
||||
|
||||
struct fat32_directory_entry dentry;
|
||||
|
||||
struct pcb* pcb = get_pcb_ptr();
|
||||
|
||||
ret = fat32_get_cluster_by_name(filename, &dentry);
|
||||
if (ret) {
|
||||
cprintf("Error finding cluster for filename");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* try to find an empty file desciptor, fail otherwise */
|
||||
//TODO We start at 3 here because 0, 1, 2 will be reserved later
|
||||
for (i = 3; i < FILE_DESC_SIZE; i++) {
|
||||
if (pcb->file_desc_array[i].flags == !IN_USE) {
|
||||
fd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fd == -1){
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* add process */
|
||||
pcb->file_desc_array[fd].f32_dentry = dentry;
|
||||
pcb->file_desc_array[fd].flags = IN_USE;
|
||||
pcb->file_desc_array[fd].file_pos = 0;
|
||||
|
||||
pcb->file_desc_array[fd].file_ops = &fat32_file_ops;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
size_t fat32_file_read(int8_t fd, void* buf, size_t nbytes) {
|
||||
uint16_t i;
|
||||
size_t offset;
|
||||
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 + 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 */
|
||||
if (fdesc->file_pos >= fdesc->f32_dentry.file_size){
|
||||
return 0;
|
||||
}
|
||||
/* validate final pos isn't past end of file */
|
||||
if (fdesc->file_pos+nbytes > fdesc->f32_dentry.file_size){
|
||||
nbytes = fdesc->f32_dentry.file_size - fdesc->file_pos;
|
||||
}
|
||||
|
||||
|
||||
// This can stay for now, as long as cluster_seq is correct.
|
||||
for (i = 0; i < cluster_seq; i++) {
|
||||
cluster = fat32_next_cluster(cluster);
|
||||
}
|
||||
|
||||
clusters = nbytes >> (9 + log2_sectors_per_cluster);
|
||||
|
||||
|
||||
/* Handle first unaligned block */
|
||||
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_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_sector(cluster, sector, sd_buf);
|
||||
memcpy(buf, sd_buf + offset, leftover_length);
|
||||
bytes_read += leftover_length;
|
||||
fdesc->file_pos += bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle middle aligned blocks */
|
||||
for (i = 0; i < clusters; i++) {
|
||||
cluster = fat32_next_cluster(cluster);
|
||||
if (cluster >= 0xffffff00) {
|
||||
// cprintf("Last cluster in file!\n");
|
||||
}
|
||||
|
||||
if (nbytes - bytes_read > 512) {
|
||||
leftover_length = 512;
|
||||
} else {
|
||||
leftover_length = nbytes - bytes_read;
|
||||
}
|
||||
|
||||
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;
|
||||
if (bytes_read == nbytes) {
|
||||
return bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
// 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) * sectors_per_cluster + sector + data_start_sector;
|
||||
SD_readSingleBlock(addr, buf, &error);
|
||||
return error;
|
||||
}
|
||||
|
||||
// This will not handle clusters numbers that leaves a sector
|
||||
uint32_t fat32_next_cluster(uint32_t cluster) {
|
||||
uint8_t error;
|
||||
uint32_t addr = fat_start_sector;
|
||||
uint32_t cluster_val;
|
||||
SD_readSingleBlock(addr, sd_buf, &error);
|
||||
cluster_val = ((uint32_t*)sd_buf)[cluster];
|
||||
return cluster_val;
|
||||
}
|
||||
|
||||
int8_t fat32_get_cluster_by_name(const char* name, struct fat32_directory_entry* dentry) {
|
||||
struct fat32_directory_entry* local_entry;
|
||||
int i = 0;
|
||||
|
||||
uint32_t cluster;
|
||||
|
||||
cluster = fat32_next_cluster(root_cluster);
|
||||
|
||||
cprintf("Sectors per cluster: %hhx\n", sectors_per_cluster);
|
||||
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
cprintf("Name: %.11s\n", local_entry->file_name, local_entry->file_ext);
|
||||
if (!strncmp(local_entry->file_name, name, 11)) {
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != -1) {
|
||||
cprintf("Failed to find file.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cprintf("Found file!\n");
|
||||
memcpy(dentry, local_entry, 32);
|
||||
return 0;
|
||||
}
|
||||
22
sw/kernel/filesystems/fs.h
Normal file
22
sw/kernel/filesystems/fs.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef _FS_H
|
||||
#define _FS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <process/process.h>
|
||||
|
||||
/* syscalls for files */
|
||||
size_t file_read(int8_t fd, void* buf, size_t nbytes);
|
||||
size_t file_write(int8_t fd, const void* buf, size_t nbytes);
|
||||
int8_t file_open(const char* filename);
|
||||
int8_t file_close(int8_t fd);
|
||||
|
||||
/* syscalls for directories */
|
||||
size_t directory_read(int8_t fd, void* buf, size_t nbytes);
|
||||
size_t directory_write(int8_t fd, const void* buf, size_t nbytes);
|
||||
int8_t directory_open(const char* filename);
|
||||
int8_t directory_close(int8_t fd);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -6,9 +6,10 @@
|
||||
#include "devices/mapper.h"
|
||||
#include "devices/rtc.h"
|
||||
#include "devices/serial.h"
|
||||
|
||||
#include "devices/terminal.h"
|
||||
|
||||
#include "filesystems/fat32.h"
|
||||
|
||||
|
||||
void handle_rtc_interrupt() {
|
||||
// cputs("In IRQ interrupt!\n");
|
||||
@@ -20,18 +21,21 @@ void handle_rtc_interrupt() {
|
||||
char buf[128];
|
||||
|
||||
int main() {
|
||||
int8_t fd;
|
||||
size_t nbytes, i;
|
||||
|
||||
cputs("Kernel\n");
|
||||
|
||||
// cputs("Init Mapper\n");
|
||||
cputs("Init Mapper\n");
|
||||
init_mapper();
|
||||
|
||||
// cputs("Initialize Interrupts\n");
|
||||
cputs("Initialize Interrupts\n");
|
||||
init_interrupts();
|
||||
|
||||
// cputs("Initialize Interrupt Controller\n");
|
||||
cputs("Initialize Interrupt Controller\n");
|
||||
init_interrupt_controller();
|
||||
|
||||
// cputs("Initialize RTC\n");
|
||||
cputs("Initialize RTC\n");
|
||||
init_rtc();
|
||||
|
||||
register_irq(&handle_rtc_interrupt, 0);
|
||||
@@ -41,22 +45,26 @@ int main() {
|
||||
|
||||
asm volatile("cli");
|
||||
|
||||
// cputs("Initialize Serial\n");
|
||||
cputs("Initialize Serial\n");
|
||||
serial_init();
|
||||
|
||||
serial_puts("Hello from serial!\n");
|
||||
|
||||
terminal_open(NULL);
|
||||
terminal_write(0, "Terminal Write\n", 15);
|
||||
fat32_init();
|
||||
|
||||
while(1) {
|
||||
if (terminal_read(0, buf, 128)) {
|
||||
cprintf("Fail\n");
|
||||
break;
|
||||
/* This is what is going to be part of open */
|
||||
fd = fat32_file_open("VERYLA~1TXT");
|
||||
cprintf("fd: %x\n", fd);
|
||||
|
||||
nbytes = fat32_file_read(fd, buf, 23);
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
cprintf("%c", buf[i]);
|
||||
}
|
||||
|
||||
while ((nbytes = fat32_file_read(fd, buf, 128))){
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
cprintf("%c", buf[i]);
|
||||
}
|
||||
terminal_write(0, "Got: ", 5);
|
||||
terminal_write(0, buf, strlen(buf));
|
||||
terminal_write(0, "\n", 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
9
sw/kernel/process/process.c
Normal file
9
sw/kernel/process/process.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <process/process.h>
|
||||
|
||||
|
||||
struct pcb fake_pcb;
|
||||
|
||||
//TODO
|
||||
struct pcb* get_pcb_ptr() {
|
||||
return &fake_pcb;
|
||||
}
|
||||
46
sw/kernel/process/process.h
Normal file
46
sw/kernel/process/process.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef _PROCESS_H
|
||||
#define _PROCESS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <filesystems/fat32.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define FILE_DESC_SIZE 8
|
||||
|
||||
|
||||
#define IN_USE 1
|
||||
|
||||
|
||||
struct fops {
|
||||
int8_t (*open)(const char* filename);
|
||||
int8_t (*close)(int8_t fd);
|
||||
size_t (*read)(int8_t fd, void* buf, size_t nbytes);
|
||||
size_t (*write)(int8_t fd, const void* buf, size_t nbytes);
|
||||
};
|
||||
|
||||
struct file_desc {
|
||||
struct fops* file_ops;
|
||||
uint8_t fs_type;
|
||||
union {
|
||||
struct fat32_directory_entry f32_dentry;
|
||||
};
|
||||
uint32_t file_pos;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
/* Process Control Block struct */
|
||||
struct pcb {
|
||||
struct file_desc file_desc_array[FILE_DESC_SIZE];
|
||||
int32_t is_vidmapped;
|
||||
uint8_t args[128];
|
||||
uint16_t execute_return;
|
||||
uint16_t pid;
|
||||
uint16_t parent_pid;
|
||||
uint16_t parent_esp;
|
||||
};
|
||||
|
||||
|
||||
struct pcb* get_pcb_ptr();
|
||||
|
||||
#endif
|
||||
@@ -35,6 +35,4 @@ udisksctl unmount -b $LOOP
|
||||
|
||||
udisksctl loop-delete -b $LOOP
|
||||
|
||||
echo "$(tput bold setaf 11)Converting Image to Verilog$(tput sgr 0)"
|
||||
objcopy --input-target=binary --output-target=verilog --verilog-data-width=1 $FILE $FILE.hex
|
||||
echo "$(tput bold setaf 10)Done!$(tput sgr 0)"
|
||||
|
||||
49
sw/test_code/fs_test/Makefile
Normal file
49
sw/test_code/fs_test/Makefile
Normal file
@@ -0,0 +1,49 @@
|
||||
CC=../../cc65/bin/cl65
|
||||
LD=../../cc65/bin/cl65
|
||||
SIM=../../cc65/bin/sim65
|
||||
CFLAGS=-T -t sim65c02 -I. -I $(REPO_TOP)/sw/kernel
|
||||
LDFLAGS=-m $(NAME).map
|
||||
|
||||
NAME=fs_test
|
||||
|
||||
SIMARGS=
|
||||
|
||||
BIN=$(NAME).bin
|
||||
|
||||
FS=$(REPO_TOP)/sw/script/fs.fat
|
||||
|
||||
LISTS=lists
|
||||
|
||||
EXT_SRCS=$(REPO_TOP)/sw/kernel/filesystems/fat32.s $(REPO_TOP)/sw/kernel/filesystems/fat32_c.c
|
||||
|
||||
SRCS=$(wildcard *.s) $(wildcard *.c)
|
||||
SRCS+=$(wildcard **/*.s) $(wildcard **/*.c)
|
||||
SRCS+=$(EXT_SRCS)
|
||||
OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS)))
|
||||
OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS)))
|
||||
|
||||
run: all
|
||||
$(SIM) $(SIMARGS) $(BIN)
|
||||
|
||||
all: fs.fat $(BIN)
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
|
||||
|
||||
%.o: %.c $(LISTS)
|
||||
$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
|
||||
|
||||
%.o: %.s $(LISTS)
|
||||
$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
|
||||
|
||||
fs.fat: $(FS)
|
||||
cp $^ .
|
||||
|
||||
|
||||
$(LISTS):
|
||||
mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS))))
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map
|
||||
|
||||
5
sw/test_code/fs_test/asm_harness.s
Normal file
5
sw/test_code/fs_test/asm_harness.s
Normal file
@@ -0,0 +1,5 @@
|
||||
.import _printf
|
||||
.export _cprintf
|
||||
|
||||
_cprintf:
|
||||
jmp _printf
|
||||
32
sw/test_code/fs_test/harness.c
Normal file
32
sw/test_code/fs_test/harness.c
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <process/process.h>
|
||||
|
||||
#define FILE_PATH "fs.fat"
|
||||
|
||||
struct pcb fake_pcb;
|
||||
|
||||
//TODO
|
||||
struct pcb* get_pcb_ptr() {
|
||||
return &fake_pcb;
|
||||
}
|
||||
|
||||
uint32_t lmulii(uint16_t a, uint16_t b) {
|
||||
printf("lmulii: %x * %x = %x\n", a, b, a*b);
|
||||
return a * b;
|
||||
}
|
||||
|
||||
uint16_t imulii(uint16_t a, uint16_t b) {
|
||||
printf("imulii: %x * %x = %x\n", a, b, a*b);
|
||||
return a * b;
|
||||
}
|
||||
|
||||
uint8_t SD_readSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *error) {
|
||||
FILE* f = fopen(FILE_PATH, "rb");
|
||||
(void)error;
|
||||
fseek(f, addr * 512, SEEK_SET);
|
||||
fread(buf, 512, 1, f);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
31
sw/test_code/fs_test/main.c
Normal file
31
sw/test_code/fs_test/main.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <stdio.h>
|
||||
#include <filesystems/fat32.h>
|
||||
#include <conio.h>
|
||||
|
||||
void fat32_init(void);
|
||||
|
||||
char data [256];
|
||||
|
||||
int main(void) {
|
||||
int8_t fd;
|
||||
size_t i;
|
||||
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);
|
||||
|
||||
nbytes = fat32_file_read(fd, data, 123);
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
cprintf("%c", data[i]);
|
||||
}
|
||||
|
||||
while ((nbytes = fat32_file_read(fd, data, 256))){
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
cprintf("%c", data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
sw/test_code/multiplier_test/Makefile
Normal file
39
sw/test_code/multiplier_test/Makefile
Normal file
@@ -0,0 +1,39 @@
|
||||
CC=../../cc65/bin/cl65
|
||||
LD=../../cc65/bin/cl65
|
||||
CFLAGS=-T -t none -I. --cpu "65C02"
|
||||
LDFLAGS=-C link.ld -m $(NAME).map
|
||||
|
||||
NAME=multiplier_test
|
||||
|
||||
BIN=$(NAME).bin
|
||||
HEX=$(NAME).hex
|
||||
|
||||
LISTS=lists
|
||||
|
||||
SRCS=$(wildcard *.s) $(wildcard *.c)
|
||||
SRCS+=$(wildcard **/*.s) $(wildcard **/*.c)
|
||||
OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS)))
|
||||
OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS)))
|
||||
|
||||
# Make sure the kernel linked to correct address, no relocation!
|
||||
all: $(HEX)
|
||||
|
||||
$(HEX): $(BIN)
|
||||
objcopy --input-target=binary --output-target=verilog $(BIN) $(HEX)
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
|
||||
|
||||
%.o: %.c $(LISTS)
|
||||
$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
|
||||
|
||||
%.o: %.s $(LISTS)
|
||||
$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
|
||||
|
||||
$(LISTS):
|
||||
mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS))))
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map
|
||||
|
||||
35
sw/test_code/multiplier_test/link.ld
Normal file
35
sw/test_code/multiplier_test/link.ld
Normal file
@@ -0,0 +1,35 @@
|
||||
MEMORY
|
||||
{
|
||||
ZP: start = $0, size = $100, type = rw, define = yes;
|
||||
SDRAM: start = $9200, size = $4d00, type = rw, define = yes;
|
||||
ROM: start = $F000, size = $1000, file = %O;
|
||||
}
|
||||
|
||||
SEGMENTS {
|
||||
ZEROPAGE: load = ZP, type = zp, define = yes;
|
||||
DATA: load = ROM, type = rw, define = yes, run = SDRAM;
|
||||
BSS: load = SDRAM, type = bss, define = yes;
|
||||
HEAP: load = SDRAM, type = bss, optional = yes;
|
||||
STARTUP: load = ROM, type = ro;
|
||||
ONCE: load = ROM, type = ro, optional = yes;
|
||||
CODE: load = ROM, type = ro;
|
||||
RODATA: load = ROM, type = ro;
|
||||
VECTORS: load = ROM, type = ro, start = $FFFA;
|
||||
}
|
||||
|
||||
FEATURES {
|
||||
CONDES: segment = STARTUP,
|
||||
type = constructor,
|
||||
label = __CONSTRUCTOR_TABLE__,
|
||||
count = __CONSTRUCTOR_COUNT__;
|
||||
CONDES: segment = STARTUP,
|
||||
type = destructor,
|
||||
label = __DESTRUCTOR_TABLE__,
|
||||
count = __DESTRUCTOR_COUNT__;
|
||||
}
|
||||
|
||||
SYMBOLS {
|
||||
# Define the stack size for the application
|
||||
__STACKSIZE__: value = $0200, type = weak;
|
||||
__STACKSTART__: type = weak, value = $0800; # 2k stack
|
||||
}
|
||||
73
sw/test_code/multiplier_test/main.s
Normal file
73
sw/test_code/multiplier_test/main.s
Normal file
@@ -0,0 +1,73 @@
|
||||
.MACPACK generic
|
||||
|
||||
.export _init, _nmi_int, _irq_int
|
||||
|
||||
MULTIPLIER_BASE = $eff0
|
||||
|
||||
MULTIPLIER_AL = MULTIPLIER_BASE + 0
|
||||
MULTIPLIER_AH = MULTIPLIER_BASE + 1
|
||||
MULTIPLIER_BL = MULTIPLIER_BASE + 2
|
||||
MULTIPLIER_BH = MULTIPLIER_BASE + 3
|
||||
|
||||
MULTIPLIER_OLL = MULTIPLIER_BASE + 4
|
||||
MULTIPLIER_OLH = MULTIPLIER_BASE + 5
|
||||
MULTIPLIER_OHL = MULTIPLIER_BASE + 6
|
||||
MULTIPLIER_OHH = MULTIPLIER_BASE + 7
|
||||
|
||||
GOLDEN_OUTPUT_0 = $03
|
||||
GOLDEN_OUTPUT_1 = $0a
|
||||
GOLDEN_OUTPUT_2 = $08
|
||||
GOLDEN_OUTPUT_3 = $00
|
||||
|
||||
.zeropage
|
||||
finish: .res 1
|
||||
|
||||
.data
|
||||
|
||||
output: .res 4
|
||||
|
||||
.code
|
||||
|
||||
_nmi_int:
|
||||
_irq_int:
|
||||
|
||||
_init:
|
||||
ldx #$ff
|
||||
txs
|
||||
|
||||
lda #$01
|
||||
sta MULTIPLIER_AL
|
||||
lda #$02
|
||||
sta MULTIPLIER_AH
|
||||
|
||||
lda #$03
|
||||
sta MULTIPLIER_BL
|
||||
lda #$04
|
||||
sta MULTIPLIER_BH
|
||||
|
||||
ldx #$00
|
||||
L1: lda MULTIPLIER_OLL,x
|
||||
sta output,x
|
||||
inx
|
||||
cpx #$4
|
||||
bne L1
|
||||
|
||||
lda output
|
||||
cmp #GOLDEN_OUTPUT_0
|
||||
bne fail
|
||||
lda output+1
|
||||
cmp #GOLDEN_OUTPUT_1
|
||||
bne fail
|
||||
lda output+2
|
||||
cmp #GOLDEN_OUTPUT_2
|
||||
bne fail
|
||||
lda output+3
|
||||
cmp #GOLDEN_OUTPUT_3
|
||||
bne fail
|
||||
|
||||
lda #$6d
|
||||
sta finish
|
||||
|
||||
fail:
|
||||
lda #$bd
|
||||
sta finish
|
||||
14
sw/test_code/multiplier_test/vectors.s
Normal file
14
sw/test_code/multiplier_test/vectors.s
Normal file
@@ -0,0 +1,14 @@
|
||||
; ---------------------------------------------------------------------------
|
||||
; vectors.s
|
||||
; ---------------------------------------------------------------------------
|
||||
;
|
||||
; Defines the interrupt vector table.
|
||||
|
||||
.import _init
|
||||
.import _nmi_int, _irq_int
|
||||
|
||||
.segment "VECTORS"
|
||||
|
||||
.addr _nmi_int ; NMI vector
|
||||
.addr _init ; Reset vector
|
||||
.addr _irq_int ; IRQ/BRK vector
|
||||
Reference in New Issue
Block a user