Code reorganization

This commit is contained in:
Kyle J Cardoza 2024-07-12 02:24:54 -04:00
parent 635a7f58a7
commit 87534ab708
22 changed files with 255 additions and 550 deletions

28
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,28 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/local/bin/cc65816",
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64"
},
{
"name": "Calypsi",
"includePath": [
"${workspaceFolder}/**",
"/usr/local/lib/calypsi-65816/include/"
],
"defines": [],
"compilerPath": "/usr/local/bin/cc65816",
"cStandard": "c11",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-clang-x64"
}
],
"version": 4
}

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"C_Cpp.errorSquiggles": "disabled"
}

View File

@ -1,8 +1,9 @@
//*****************************************************************************
// 65X-DOS
// SPDX-License-Identifier: MIT
//
// include/config.h
//*****************************************************************************
// include/kernel/config.h
// Global configuration header for 65X-DOS kernel
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#pragma once

View File

@ -1,113 +0,0 @@
// SPDX-License-Identifier: MIT
//
// kernel/device.h
// Driver declarations.
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#pragma once
#ifdef __CALYPSI_CC__
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
// This symbol determines the maximum number of device drivers which
// can be in memory.
#ifndef DEVICE_MAX
#define DEVICE_MAX 32
#endif
// This symbol determines the maximum number of device map entries which
// ca be in memory.
#ifndef DEVICE_MAP_MAX
#define DEVICE_MAP_MAX 32
#endif
// Forward declaration.
struct file;
// A device, in this context, is a code module which exposes a defined set
// of functions for interacting with files and file-like data. It is not specific
// as to the nature of the underlying data storage. It is equally valid for a
// device to use a block of RAM or a serial device as it is a hard drive
// or SD card.
//
// None of these functions are required to actually do anyting if it is not
// sensible for the kind of device being used; for example, it is not
// sensible for an inherently read-only device to support moving or
// renaming files.
typedef struct {
// Initialize the device.
int (*init)(void);
// Opens a file, given a pathname.
int (*open)(struct file *file);
// Closes an open file, given a unique ID.
int (*close)(struct file *file);
// Seeks within an open file, given a unique ID and a length.
int (*seek)(struct file *file, long length);
// Reads data from the specified file.
int (*read)(struct file *file, void *dest, size_t length);
// Writes data to the specified file.
int (*write)(struct file *file, void *src, size_t length);
// Perform driver-specific operations.
int (*ioctl)(struct file *file,
unsigned short operation,
void *arg);
// Creates the specified file given a pathname.
int (*create)(struct file *file);
// Copies the specified file using the specified names.
int (*copy)(struct file *src,
struct file *dest);
// Moves the specified file using the specified names.
int (*move)(struct file *src,
struct file *dest);
// Gets the size of the file.
int (*get_file_size)(struct file *file, size_t *size);
// Fills out the metadata in the specified file from the pathname
// in the provided file.
int (*init_file)(struct file *file);
} Device;
// The device map is a table that maps device names, such as SD0: or
// TTY2: to the device driver that manages the device.
struct device_map {
char *name;
unsigned short major_number;
unsigned short minor_number;
};
// The global table of device drivers.
extern Device *device[DEVICE_MAX];
// The global map of device names to device modules.
extern struct device_map *device_map[DEVICE_MAP_MAX];
// Initialize all the device drivers. This is called once, at boot.
// It protects itself against being called again without a reset.
void device_init_all(void);
// Binds a device name to a device.
int device_bind_name(char *name,
unsigned short major_number,
unsigned short minor_number);
// Unbinds a bound device name.
int device_unbind_name(char *name);
// Get a bound device by its name.
int device_get_by_name(char *name, Device **device);
#endif

View File

@ -1,79 +0,0 @@
// SPDX-License-Identifier: MIT
//
// kernel/file.h
// File related declarations
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "kernel/device.h"
enum file_type {
FILE_TYPE_NORMAL,
FILE_TYPE_DIRECTORY,
FILE_TYPE_DEVICE
};
struct file {
// The full path of the file, including its volume and basename.
char *pathname;
// The basename of the file. This usually points to
// the begining of the basename of the file in the
// pathname string.
char *basename;
// The type of the file.
enum file_type type;
bool open;
// Generic driver-specific data pointer
void *userdata;
// The major number identifies the device driver responsible for
// the file.
uint8_t major_number;
// The minor number identifies the device, among those the driver
// controls, which this file represents or is associated with.
uint8_t minor_number;
};
// Using the pathname in the provided file stucture, identify the device which manages
// the file and have that device populate the file structure.
int file_init(char *pathname, struct file *file);
int file_open(struct file *file);
int file_ioctl(struct file *file,
unsigned short operation,
void *arg);
// Closes an open file, given a unique ID.
int file_close(struct file *file);
// Seeks within an open file, given a unique ID and a length.
int file_seek(struct file *file, int32_t length);
// Reads data from the specified file.
int file_read(struct file *file, void *dest, size_t length);
// Writes data to the specified file.
int file_write(struct file *file, void *src, size_t length);
// Creates the specified file given a pathname.
int file_create(struct file *file);
// Copies the specified file using the specified names.
int file_copy(struct file *src, struct file *dest);
// Moves the specified file using the specified names.
int file_move(struct file *src, struct file *dest);
// Gets the size of the file.
int file_get_file_size(struct file *file, size_t *size);

View File

@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
//
// bios/main.c
// Sentinel 65X BIOS: main() function
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#pragma once
void led_init(void);
void led_red_off(void);
void led_red_on(void);
void led_green_off(void);
void led_green_on(void);
void led_blue_off(void);
void led_blue_on(void);

View File

@ -1,12 +1,10 @@
// SPDX-License-Identifier: MIT
//
// kernel/device/null.h
// NULL driver declaration.
// include/kernel/util/delay.k
// 65X-DOS Kernel: delay() function
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#pragma once
#include "kernel/device.h"
extern Device NullDevice;
void delay(uint16_t count);

View File

@ -1,3 +1,8 @@
// SPDX-License-Identifier: MIT
//
// include/macros.h
// Utility macros for Calypsi compiler and assembler
#ifndef __MACROS_H
#define __MACROS_H

View File

@ -1,16 +0,0 @@
// SPDX-License-Identifier: MIT
//
// boot/sentinel65x.h
// Toplevel header for Sentinel 65X ROM firmware boot module
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#pragma once
#define CPU_SPEED_HZ 8000000
#define UART3_BAUD_RATE 9600
#define UART3_TIMER_VALUE (CPU_SPEED_HZ / (16 * UART3_BAUD_RATE) - 1)
#include "65c816.h"
#include "w65c265s.h"
#include "vera.h"

View File

@ -1,3 +1,10 @@
; SPDX-License-Identifier: MIT
;
; src/kernel/cop_trampoline.s
; Trampoline function for COP interrupt handler
;
; Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#include "macros.h"
.section znear,bss

View File

@ -1,3 +1,10 @@
; SPDX-License-Identifier: MIT
;
; src/kernel/cstartup.s
; Critical boot and init code before calling main()
;
; Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
;;; Startup variant, change attribute value if you make your own
.rtmodel cstartup,"sentinel65x"
@ -18,9 +25,8 @@
#endif
#include "macros.h"
#include "65c816.h"
#include "w65c265s.h"
#include "65c816.h"
#include "kernel/hardware/65c816.h"
#include "kernel/hardware/w65c265s.h"
.section boot, noreorder
.pubweak __program_root_section
@ -45,6 +51,10 @@ w65c265s_init:
trb PD4
tsb PDD4
fclk_start
fclk_select
; Now we delay a while.
ldy ##0x0FFF
delay_y
@ -61,18 +71,6 @@ delay_y
; Disable the on-CPU RAM
w65c265s_sram_off
; Set P5.4 and P5.5 as output
lda #0b00110000
trb PDD5
tsb PDD5
trb PD5
; Set P6.1 as output
lda #0b00000010
trb PDD6
tsb PDD6
trb PD6
clc
xce ; native 16-bit mode
rep #0x38 ; 16-bit registers, no decimal mode

View File

@ -1,123 +0,0 @@
// SPDX-License-Identifier: MIT
//
// kernel/device.c
// Device drivers.
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "kernel/device.h"
#include "kernel/file.h"
#include "kernel/device/null.h"
static bool device_init_all_run = false;
Device *device[DEVICE_MAX] = {
&NullDevice
};
struct device_map *device_map[DEVICE_MAP_MAX] = {0};
static short get_lowest_free_device(void);
void device_init_all(void)
{
if (device_init_all_run == true) {
return;
}
for (int i = 0; i < DEVICE_MAX; i += 1) {
if (device[i] != NULL) {
if (device[i]->init != NULL) {
device[i]->init();
}
}
}
device_init_all_run = true;
}
int device_bind_name(char *name,
unsigned short major_number,
unsigned short minor_number)
{
if (name == NULL) {
return -1;
}
// It is not permissible to have the same name attached to two
// devices.
for (int i = 0; i < DEVICE_MAP_MAX; i += 1) {
if (strcmp(device_map[i]->name, name) == 0) {
return -1;
}
}
short device_index = get_lowest_free_device();
if (device_index == -1) {
return -1;
}
char *device_name = strdup(name);
if (name == NULL) {
return -1;
}
device_map[device_index] = calloc(1, sizeof(struct device_map));
if (device_map[device_index] == NULL) {
free(device_name);
return -1;
} else {
device_map[device_index]->major_number = major_number;
device_map[device_index]->minor_number = minor_number;
device_map[device_index]->name = device_name;
return 0;
}
}
int device_unbind_name(char *name)
{
if (name == NULL) {
return -1;
}
for (int i = 0; i < DEVICE_MAP_MAX; i += 1) {
if (strcmp(device_map[i]->name, name) == 0) {
free(device_map[i]->name);
free(device_map[i]);
device_map[i] = NULL;
return 0;
}
}
return -1;
}
int device_get_by_name(char *name, Device **device)
{
if (name == NULL || device == NULL) {
return -1;
}
for (int i = 0; i < DEVICE_MAP_MAX; i += 1) {
if (strcmp(device_map[i]->name, name) == 0) {
unsigned short major_number = device_map[i]->major_number;
*device = device[major_number];
return 0;
}
}
return -1;
}
static short get_lowest_free_device(void)
{
for (int i = 0; i < DEVICE_MAP_MAX; i += 1) {
if (device_map[i] == NULL) {
return i;
}
}
return -1;
}

View File

@ -1,126 +0,0 @@
// SPDX-License-Identifier: MIT
//
// kernel/device/null.c
// NULL device implementation.
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#include <string.h>
#include "kernel/device/null.h"
#include "kernel/device.h"
#include "kernel/file.h"
static int null_init(void);
static int null_open(struct file *file);
static int null_close(struct file *file);
static int null_read(struct file *file, void *dest, size_t length);
static int null_write(struct file *file, void *src, size_t length);
static int null_get_file_size(struct file *file, size_t *size);
static int null_init_file(struct file *file);
Device NullDevice = {
.init = null_init,
.open = null_open,
.close = null_close,
.read = null_read,
.write = null_write,
.get_file_size = null_get_file_size,
.init_file = null_init_file
};
static int null_init(void)
{
device_bind_name("zero", 0, 0);
device_bind_name("null", 0, 1);
return 0;
}
static int null_open(struct file *file)
{
switch (file->minor_number) {
case 0 ... 1:
file->open = true;
return 0;
default:
return -1;
}
}
static int null_close(struct file *file)
{
switch (file->minor_number) {
case 0 ... 1:
file->open = false;
return 0;
default:
return -1;
}
}
static int null_read(struct file *file,
void *dest,
size_t length)
{
if (file->open == false) {
return -1;
}
switch (file->minor_number) {
case 0:
memset(dest, 0x00, length);
return length;
default:
return -1;
}
}
static int null_write(struct file *file,
void *src,
size_t length)
{
if (file->open == false) {
return -1;
}
(void) src;
if (file->minor_number != 1) {
return -1;
} else {
return length;
}
}
static int null_get_file_size(struct file *file,
size_t *size)
{
switch (file->minor_number) {
case 0 ... 1:
*size = 0;
return 0;
default:
return -1;
}
}
static int null_init_file(struct file *file)
{
if (file->major_number != 0) {
return -1;
}
switch (file->minor_number) {
case 0 ... 1:
file->open = false;
file->type = FILE_TYPE_DEVICE;
return 0;
default:
return -1;
}
}

View File

@ -1,57 +0,0 @@
// SPDX-License-Identifier: MIT
//
// kernel/file.c
// File definitions.
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#include <stdlib.h>
#include <string.h>
#include "kernel/file.h"
#include "kernel/device.h"
// Using the pathname string, identify the major/minor device for
// the file, and have that device initialize the file control
// block.
int file_init(char *pathname, struct file *file)
{
// First thing, we need to identify the device. The pathname
// is to be fully-qualified; this means it must have the
// device name, followed by a colon, followed by an optional
// file path. If the file path part is empty, then the file
// refers to the device itself. We perform the identification
// by first copying the pathname, then tokenizing the copy on
// the ":" character. The first token must be a string which
// matches a registered device in the device map.
// Then we populate the located major and minor numbers and copy
// the pathname into the FCB, and pass it along to the device
// driver for more initialization.
char *path = strdup(pathname);
if (path == NULL) {
return -1;
}
char *dev = strtok(path, ":");
for (unsigned short i = 0; i < DEVICE_MAP_MAX; i += 1) {
if (strcmp(dev, device_map[i]->name) == 0) {
file->pathname = strdup(pathname);
free(path);
if (file->pathname == NULL) {
return -1;
}
file->major_number = device_map[i]->major_number;
file->minor_number = device_map[i]->minor_number;
return device[file->major_number]->init_file(file);
}
}
free(path);
return -1;
}

126
src/kernel/hardware/led.s Normal file
View File

@ -0,0 +1,126 @@
; SPDX-License-Identifier: MIT
;
; src/kernel/hardware/led.s
; Defines for the VERA chip
;
; Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#include "macros.h"
#include "kernel/hardware/65c816.h"
#include "kernel/hardware/w65c265s.h"
.section code
.public led_init
.public led_red_off
.public led_red_on
.public led_green_off
.public led_green_on
.public led_blue_off
.public led_blue_on
led_init:
long_a
long_i
pha
short_a
; Set P5.4 and P5.5 as output
lda #0b00110000
trb PDD5
tsb PDD5
trb PD5
; Set P6.1 as output
lda #0b00000010
trb PDD6
tsb PDD6
trb PD6
long_a
long_i
pla
rtl
led_red_off:
long_a
long_i
pha
short_a
lda #(1 << 4)
trb PD5
long_a
long_i
pla
rtl
led_red_on:
long_a
long_i
pha
short_a
lda #(1 << 4)
tsb PD5
long_a
long_i
pla
rtl
led_green_off:
long_a
long_i
pha
short_a
lda #(1 << 5)
trb PD5
long_a
long_i
pla
rtl
led_green_on:
long_a
long_i
pha
short_a
lda #(1 << 5)
tsb PD5
long_a
long_i
pla
rtl
led_blue_off:
long_a
long_i
pha
short_a
lda #(1 << 1)
trb PD6
long_a
long_i
pla
rtl
led_blue_on:
long_a
long_i
pha
short_a
lda #(1 << 1)
tsb PD6
long_a
long_i
pla
rtl

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
//
// bios/stubs.c
// Stub functions for Calypsi's C library
// src/kernel/irq.c
// IRQ handlers
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>

View File

@ -1,19 +1,35 @@
// SPDX-License-Identifier: MIT
//
// bios/main.c
// src/kernel/main.c
// Sentinel 65X BIOS: main() function
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#include <limits.h>
#include <stdint.h>
#include "kernel/util/delay.h"
#include "kernel/hardware/led.h"
void main(void) {
// Light Red LED
__asm(
" sep #0x20\n"
" lda #0b00010000\n"
" tsb 0x00DF21\n"
" rep #0x20\n"
);
led_init();
for (;;) {
led_red_on();
delay(1);
led_red_off();
led_green_on();
delay(1);
led_green_off();
led_blue_on();
delay(1);
led_blue_off();
delay(1);
for (;;) {}
}
}

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
//
// bios/stubs.c
// src/kernel/stubs.c
// Stub functions for Calypsi's C library
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>

15
src/kernel/util/delay.c Normal file
View File

@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
//
// src/kernel/util/delay.c
// 65X-DOS Kernel: delay() function
//
// Copyright © 2024 Kyle J Cardoza <Kyle.Cardoza@icloud.com>
#include <limits.h>
#include <stdint.h>
void delay(uint16_t count) {
for (uint16_t i = 0; i < count; i += 1) {
for (uint16_t j = 0; j < 0xFFFF; j += 1) {}
}
}