Started RTC Support and Test CMDs

This commit is contained in:
Peter Weingartner 2021-10-05 15:51:53 -04:00
parent 37f96ce1d5
commit bfda2d4038
15 changed files with 7322 additions and 6194 deletions

View file

@ -6,10 +6,13 @@
#include <string.h>
#include "log.h"
#include "types.h"
#include "simpleio.h"
#include "syscalls.h"
#include "sys_general.h"
#include "cli/cli.h"
#include "cli/dos_cmds.h"
#include "cli/mem_cmds.h"
#include "dev/rtc.h"
#define MAX_COMMAND_SIZE 128
#define MAX_ARGC 32
@ -26,6 +29,10 @@ typedef struct s_cli_command {
cli_cmd_handler handler;
} t_cli_command, *p_cli_command;
extern short cmd_gettime(short channel, int argc, char * argv[]);
extern short cmd_settime(short channel, int argc, char * argv[]);
extern short cmd_sysinfo(short channel, int argc, char * argv[]);
/*
* Variables
*/
@ -45,6 +52,10 @@ const t_cli_command g_cli_commands[] = {
{ "POKE16", "POKE16 <address> <value> -- write the 16-bit word value to the address in memory", mem_cmd_poke16},
{ "POKE32", "POKE32 <address> <value> -- write the 32-bit long word value to the address in memory", mem_cmd_poke32},
{ "RUN", "RUN <path> -- execute a binary file", cmd_run },
{ "GETTIME", "GETTIME -- prints the current time", cmd_gettime },
{ "SETTIME", "SETTIME -- prints the current time", cmd_settime },
{ "SYSINFO", "SYSINFO -- prints information about the system", cmd_sysinfo },
{ "TESTIDE", "TESTIDE -- fetches and prints the IDE MBR repeatedly", cmd_testide},
{ "TYPE", "TYPE <path> -- print the contents of a text file", cmd_type },
{ 0, 0 }
};
@ -62,6 +73,62 @@ int cmd_help(short channel, int argc, char * argv[]) {
return 0;
}
/*
* Display information about the system
*/
short cmd_sysinfo(short channel, int argc, char * argv[]) {
t_sys_info info;
sys_get_info(&info);
print(channel, "System information:\nModel: ");
print(channel, info.model_name);
print(channel, "\nCPU: ");
print(channel, info.cpu_name);
print(channel, "\nGABE version: ");
print_hex_16(channel, info.gabe_number);
print(channel, ".");
print_hex_16(channel, info.gabe_version);
print(channel, ".");
print_hex_16(channel, info.gabe_subrev);
print(channel, "\nVICKY version: ");
print_hex_16(channel, info.vicky_rev);
print(channel, "\n");
return 0;
}
short cmd_gettime(short channel, int argc, char * argv[]) {
char time_string[128];
t_time time;
rtc_get_time(&time);
sprintf(time_string, "%04d-%02d-%02d %02d:%02d:%02d\n", time.year, time.month, time.day, time.hour, time.minute, time.second);
print(channel, time_string);
return 0;
}
short cmd_settime(short channel, int argc, char * argv[]) {
t_time time;
time.year = 2021;
time.month = 10;
time.day = 4;
time.hour = 9;
time.minute = 15;
time.second = 0;
time.is_24hours = 0;
time.is_pm = 1;
rtc_set_time(&time);
return 0;
}
//
// Attempt to execute a command
//

View file

@ -9,8 +9,40 @@
#include "cli/dos_cmds.h"
#include "dev/block.h"
#include "dev/fsys.h"
#include "dev/kbd_mo.h"
#include "fatfs/ff.h"
/*
* Test the IDE interface by reading the MBR
*/
short cmd_testide(short screen, int argc, char * argv[]) {
unsigned char buffer[512];
short i;
short scancode;
short n = 0;
while (1) {
n = bdev_read(BDEV_HDC, 0, buffer, 512);
if (n <= 0) {
log_num(LOG_ERROR, "Unable to read MBR: ", n);
return n;
}
for (i = 0; i < n; i++) {
if ((i % 16) == 0) {
print(screen, "\n");
}
print_hex_8(screen, buffer[i]);
print(screen, " ");
}
print(screen, "\n\n");
if (kbdmo_getc_poll()) break;
}
}
short cmd_run(short screen, int argc, char * argv[]) {
TRACE("cmd_run");

View file

@ -5,6 +5,11 @@
#ifndef __DOS_CMDS_H
#define __DOS_CMDS_H
/*
* Test the IDE interface by reading the MBR
*/
extern short cmd_testide(short screen, int argc, char * argv[]);
/*
* Execute a binary file
*/

View file

@ -36,7 +36,7 @@ short mem_cmd_dump(short channel, int argc, char * argv[]) {
print(channel, ": ");
}
print_hex(channel, address[i]);
print_hex_8(channel, address[i]);
print(channel, " ");
}
@ -81,7 +81,7 @@ short mem_cmd_peek8(short channel, int argc, char * argv[]) {
if (argc == 2) {
unsigned char * address = (unsigned char *)cli_eval_number(argv[1]);
unsigned char c = *address;
print_hex(channel, c);
print_hex_8(channel, c);
return c;
} else {

226
src/dev/rtc.c Normal file
View file

@ -0,0 +1,226 @@
/*
* Definitions for access the bq4802LY real time clock
*/
#include "log.h"
#include "interrupt.h"
#include "rtc.h"
#include "rtc_reg.h"
#include "simpleio.h"
static long rtc_ticks;
/*
* Interrupt handler for the real time clock
*/
void rtc_handle_int() {
unsigned char flags;
flags = *RTC_FLAGS;
if (flags | RTC_PF) {
/* Peridic interrupt: increment the ticks counter */
rtc_ticks++;
}
}
/*
* Initialize the RTC
*/
void rtc_init() {
unsigned char rates;
unsigned char enables;
// int_disable(INT_RTC);
//
// /* Reset the ticks counter */
// rtc_ticks = 0;
//
// /* Set the periodic interrupt to 976.5625 microseconds */
// *RTC_RATES = (*RTC_RATES & RTC_RATES_WD) | RTC_RATE_976us;
//
// /* Enable the periodic interrupt */
*RTC_RATES = 0;
*RTC_ENABLES = 0; // RTC_PIE;
/* Make sure the RTC is on */
*RTC_CTRL = RTC_STOP;
/* Register our interrupt handler and clear out any pending interrupts */
// int_register(INT_RTC, rtc_handle_int);
// int_clear(INT_RTC);
// int_enable(INT_RTC);
}
/*
* Set the time on the RTC
*
* Inputs:
* time = pointer to a t_time record containing the correct time
*/
void rtc_set_time(p_time time) {
unsigned char ctrl;
unsigned char century_bcd, year_bcd, month_bcd, day_bcd;
unsigned char hour_bcd, minute_bcd, second_bcd;
unsigned short century;
unsigned short year;
century = time->year / 100;
year = time->year - (century * 100);
/* Compute the BCD values for the time */
century_bcd = i_to_bcd(century);
year_bcd = i_to_bcd(year);
month_bcd = i_to_bcd(time->month);
day_bcd = i_to_bcd(time->day);
hour_bcd = i_to_bcd(time->hour);
minute_bcd = i_to_bcd(time->minute);
second_bcd = i_to_bcd(time->second);
log_num(LOG_INFO, "Century: ", century_bcd);
log_num(LOG_INFO, "Year: ", year_bcd);
log_num(LOG_INFO, "Month: ", month_bcd);
log_num(LOG_INFO, "Day: ", day_bcd);
log_num(LOG_INFO, "Hour: ", hour_bcd);
log_num(LOG_INFO, "Minute: ", minute_bcd);
log_num(LOG_INFO, "Second: ", second_bcd);
if (time->is_24hours) {
if (time->is_pm) {
hour_bcd = hour_bcd | 0x80;
}
}
minute_bcd = i_to_bcd(time->minute);
second_bcd = i_to_bcd(time->second);
/* Temporarily disable updates to the clock */
ctrl = *RTC_CTRL;
*RTC_CTRL = ctrl | RTC_UTI;
log(LOG_INFO, "RTC Disabled");
log_num(LOG_INFO, "RTC Rates: ", *RTC_RATES);
log_num(LOG_INFO, "RTC Enables: ", *RTC_ENABLES);
log_num(LOG_INFO, "RTC Flags: ", *RTC_FLAGS);
log_num(LOG_INFO, "RTC Control: ", *RTC_CTRL);
/* Set the time in the RTC */
*RTC_CENTURY = century_bcd;
*RTC_YEAR = year_bcd;
*RTC_MONTH = month_bcd;
*RTC_DAY = day_bcd;
*RTC_HOUR = hour_bcd;
*RTC_MIN = minute_bcd;
*RTC_SEC = second_bcd;
/* Verify */
century_bcd = *RTC_CENTURY;
year_bcd = *RTC_YEAR;
month_bcd = *RTC_MONTH;
day_bcd = *RTC_DAY;
hour_bcd = *RTC_HOUR;
minute_bcd = *RTC_MIN;
second_bcd = *RTC_SEC;
log_num(LOG_INFO, "REG Century: ", century_bcd);
log_num(LOG_INFO, "REG Year: ", year_bcd);
log_num(LOG_INFO, "REG Month: ", month_bcd);
log_num(LOG_INFO, "REG Day: ", day_bcd);
log_num(LOG_INFO, "REG Hour: ", hour_bcd);
log_num(LOG_INFO, "REG Minute: ", minute_bcd);
log_num(LOG_INFO, "REG Second: ", second_bcd);
/* Set the 24/12 hour control bit if needed */
if (time->is_24hours) {
ctrl = ctrl | RTC_2412;
}
/* Re-enable updates to the clock */
*RTC_CTRL = (ctrl & 0x7f) | RTC_STOP;
log(LOG_INFO, "RTC Enabled");
log_num(LOG_INFO, "RTC Rates: ", *RTC_RATES);
log_num(LOG_INFO, "RTC Enables: ", *RTC_ENABLES);
log_num(LOG_INFO, "RTC Flags: ", *RTC_FLAGS);
log_num(LOG_INFO, "RTC Control: ", *RTC_CTRL);
}
/*
* Get the time on the RTC
*
* Inputs:
* time = pointer to a t_time record in which to put the current time
*/
void rtc_get_time(p_time time) {
unsigned char ctrl;
unsigned char century_bcd, year_bcd, month_bcd, day_bcd;
unsigned char hour_bcd, minute_bcd, second_bcd;
/* Temporarily disable updates to the clock */
ctrl = *RTC_CTRL;
*RTC_CTRL = ctrl | RTC_UTI;
log(LOG_INFO, "RTC Disabled");
log_num(LOG_INFO, "RTC Rates: ", *RTC_RATES);
log_num(LOG_INFO, "RTC Enables: ", *RTC_ENABLES);
log_num(LOG_INFO, "RTC Flags: ", *RTC_FLAGS);
log_num(LOG_INFO, "RTC Control: ", *RTC_CTRL);
if (*RTC_CTRL & RTC_2412) {
time->is_24hours = 1;
} else {
time->is_24hours = 0;
}
century_bcd = *RTC_CENTURY;
year_bcd = *RTC_YEAR;
month_bcd = *RTC_MONTH;
day_bcd = *RTC_DAY;
hour_bcd = *RTC_HOUR;
minute_bcd = *RTC_MIN;
second_bcd = *RTC_SEC;
/* Re-enable updates to the clock */
*RTC_CTRL = ctrl;
log(LOG_INFO, "RTC Enabled");
log_num(LOG_INFO, "RTC Rates: ", *RTC_RATES);
log_num(LOG_INFO, "RTC Enables: ", *RTC_ENABLES);
log_num(LOG_INFO, "RTC Flags: ", *RTC_FLAGS);
log_num(LOG_INFO, "RTC Control: ", *RTC_CTRL);
log_num(LOG_INFO, "Century: ", century_bcd);
log_num(LOG_INFO, "Year: ", year_bcd);
log_num(LOG_INFO, "Month: ", month_bcd);
log_num(LOG_INFO, "Day: ", day_bcd);
log_num(LOG_INFO, "Hour: ", hour_bcd);
log_num(LOG_INFO, "Minute: ", minute_bcd);
log_num(LOG_INFO, "Second: ", second_bcd);
/* Fill out the time record */
time->year = bcd_to_i(century_bcd) * 100 + bcd_to_i(year_bcd);
time->month = bcd_to_i(month_bcd);
time->day = bcd_to_i(day_bcd);
time->hour = bcd_to_i(hour_bcd & 0x7f);
time->is_pm = ((hour_bcd & 0x80) == 0x80) ? 1 : 0;
time->minute = bcd_to_i(minute_bcd);
time->second = bcd_to_i(second_bcd);
}
/*
* Get the number of ticks since the system last booted.
*
* NOTE: a tick is almost, but not quite, 1ms. The RTC periodic interrupt
* period does not line up with a 1ms timer, but it comes close.
* Therefore, a tick will be 976.5625 microseconds... a little faster
* than 1ms.
*
* Returns:
* the number of ticks since the last reset
*/
long rtc_get_ticks() {
long result = 0;
int_disable(INT_RTC); /* Make sure we aren't changing the tick counter during the query */
result = rtc_ticks;
int_enable(INT_RTC);
return rtc_ticks;
}

53
src/dev/rtc.h Normal file
View file

@ -0,0 +1,53 @@
/*
* Declarations for access the bq4802LY real time clock
*/
#ifndef __RTC_H
#define __RTC_H
typedef struct s_time {
short year;
short month;
short day;
short hour;
short minute;
short second;
short is_pm;
short is_24hours;
} t_time, *p_time;
/*
* Initialize the RTC
*/
extern void rtc_init();
/*
* Set the time on the RTC
*
* Inputs:
* time = pointer to a t_time record containing the correct time
*/
extern void rtc_set_time(p_time time);
/*
* Get the time on the RTC
*
* Inputs:
* time = pointer to a t_time record in which to put the current time
*/
extern void rtc_get_time(p_time time);
/*
* Get the number of ticks since the system last booted.
*
* NOTE: a tick is almost, but not quite, 1ms. The RTC periodic interrupt
* period does not line up with a 1ms timer, but it comes close.
* Therefore, a tick will be 976.5625 microseconds... a little faster
* than 1ms.
*
* Returns:
* the number of ticks since the last reset
*/
extern long rtc_get_ticks();
#endif

View file

@ -170,7 +170,7 @@
/* Number of volumes (logical drives) to be used. (1-10) */
#define FF_STR_VOLUME_ID 1
#define FF_STR_VOLUME_ID 2
// #define FF_VOLUME_STRS "S,F,H"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive

View file

@ -17,6 +17,7 @@
#include "dev/pata.h"
#include "dev/ps2.h"
#include "dev/kbd_mo.h"
#include "dev/rtc.h"
#include "dev/sdc.h"
#include "dev/uart.h"
#include "snd/codec.h"
@ -25,7 +26,7 @@
#include "fatfs/ff.h"
#include "cli/cli.h"
const char* VolumeStr[FF_VOLUMES] = { "@S", "@F", "@H" };
const char* VolumeStr[FF_VOLUMES] = { "sdc", "fdc", "hdc" };
/*
* Initialize the SuperIO registers
@ -96,7 +97,7 @@ void initialize() {
text_init(); // Initialize the text channels
DEBUG("Foenix/MCP starting up...");
log_setlevel(LOG_ERROR);
log_setlevel(LOG_DEBUG);
/* Initialize the interrupt system */
int_init();
@ -132,6 +133,9 @@ void initialize() {
DEBUG("Console installed.");
}
/* Initialize the real time clock */
rtc_init();
if (res = pata_install()) {
print_error(0, "FAILED: PATA driver installation", res);
} else {

File diff suppressed because it is too large Load diff

50
src/include/rtc_reg.h Normal file
View file

@ -0,0 +1,50 @@
/*
* Define locations for the registers for the real time clock chip
*/
#ifndef __RTC_REG_H
#define __RTC_REG_H
#define RTC_BASE ((volatile unsigned char *)0x00C00080)
#define RTC_SEC ((volatile unsigned char *)0x00C00080)
#define RTC_ALRM_SEC ((volatile unsigned char *)0x00C00081)
#define RTC_MIN ((volatile unsigned char *)0x00C00082)
#define RTC_ALRM_MIN ((volatile unsigned char *)0x00C00083)
#define RTC_HOUR ((volatile unsigned char *)0x00C00084)
#define RTC_ALRM_HOUR ((volatile unsigned char *)0x00C00085)
#define RTC_DAY ((volatile unsigned char *)0x00C00086)
#define RTC_ALRM_DAY ((volatile unsigned char *)0x00C00087)
#define RTC_DAY_OF_WEEK ((volatile unsigned char *)0x00C00088)
#define RTC_MONTH ((volatile unsigned char *)0x00C00089)
#define RTC_YEAR ((volatile unsigned char *)0x00C0008A)
#define RTC_RATES ((volatile unsigned char *)0x00C0008B)
#define RTC_ENABLES ((volatile unsigned char *)0x00C0008C)
#define RTC_FLAGS ((volatile unsigned char *)0x00C0008D)
#define RTC_CTRL ((volatile unsigned char *)0x00C0008E)
#define RTC_CENTURY ((volatile unsigned char *)0x00C0008F)
/* Rate fields and settings */
#define RTC_RATES_WD 0xf0
#define RTC_RATES_RS 0x0f
#define RTC_RATE_976us 0x06
/* Enable bits */
#define RTC_AIE 0x08
#define RTC_PIE 0x04
#define RTC_PWRIE 0x02
#define RTC_ABE 0x01
/* Flag bits */
#define RTC_AF 0x08
#define RTC_PF 0x04
#define RTC_PWRF 0x02
#define RTC_BVF 0x01
/* Control bits */
#define RTC_UTI 0x08
#define RTC_STOP 0x04
#define RTC_2412 0x02
#define RTC_DSE 0x01
#endif

File diff suppressed because it is too large Load diff

View file

@ -43,7 +43,7 @@ unsigned char hex_digits[] = "0123456789ABCDEF";
* channel = the number of the channel
* n = the number to print
*/
void print_hex(short channel, unsigned short x) {
void print_hex_8(short channel, unsigned short x) {
short digit;
digit = (x & 0xf0) >> 4;
@ -104,3 +104,46 @@ void print_hex_32(short channel, long n) {
print(channel, number);
}
/*
* Convert a BCD byte to an integer
*
* Inputs:
* bcd = a byte containing a BCD number
*
* Returns:
* the binary form of the number
*/
unsigned short bcd_to_i(unsigned char bcd) {
short tens = (bcd >> 4) & 0xf0;
short ones = bcd & 0x0f;
if ((ones > 9) || (tens > 9)) {
/* Byte was not in BCD... just return a 0 */
return 0;
} else {
return tens * 10 + ones;
}
}
/*
* Convert a number from 0 to 99 to BCD
*
* Inputs:
* n = a binary number from 0 to 99
*
* Returns:
* a byte containing n as a BCD number
*/
unsigned char i_to_bcd(unsigned short n) {
if (n > 99) {
/* Input was out of range... just return 0 */
return 0;
} else {
unsigned short tens = n / 10;
unsigned short ones = n - (tens * 10);
return tens << 4 | ones;
}
}

View file

@ -50,4 +50,26 @@ extern void print_hex_16(short channel, short n);
*/
extern void print_hex_32(short channel, long n);
/*
* Convert a BCD byte to an integer
*
* Inputs:
* bcd = a byte containing a BCD number
*
* Returns:
* the binary form of the number
*/
extern unsigned short bcd_to_i(unsigned char bcd);
/*
* Convert a number from 0 to 99 to BCD
*
* Inputs:
* n = a binary number from 0 to 99
*
* Returns:
* a byte containing n as a BCD number
*/
extern unsigned char i_to_bcd(unsigned short n);
#endif

View file

@ -16,35 +16,48 @@ void sys_get_info(p_sys_info info) {
switch (machine_id & 0x000f) {
case 0x00:
info->model = MODEL_FOENIX_FMX;
info->model_name = "Foenix FMX";
info->cpu_name = "WDC 65816";
info->has_floppy = 1;
break;
case 0x01:
info->model = MODEL_FOENIX_C256U;
info->model_name = "Foenix C256U";
info->cpu_name = "WDC 65816";
break;
case 0x05:
info->model = MODEL_FOENIX_C256U_PLUS;
info->model_name = "Foenix C256U+";
info->cpu_name = "WDC 65816";
break;
case 0x0B:
info->model = MODEL_FOENIX_A2560K;
info->model_name = "Foenix A2560K";
info->cpu_name = "m68000";
info->has_floppy = 1;
break;
case 0x09:
info->model = MODEL_FOENIX_A2560U;
info->model_name = "Foenix A2560U";
info->cpu_name = "m68000";
break;
default:
/* Model is unknown */
info->model = 0xffff;
info->model_name = "Unknown";
info->cpu_name = "Unknown";
break;
}
switch ((machine_id & 0xf000) >> 12) {
case 0x00:
info->cpu = CPU_M68000;
info->cpu_name = "m68000";
break;
default:

View file

@ -33,7 +33,9 @@
*/
typedef struct s_sys_info {
unsigned short model; /* Code to say what model of machine this is */
const char * model_name; /* Human readable name of the model of the computer */
unsigned short cpu; /* Code to say which CPU is running */
const char * cpu_name; /* Human readable name for the CPU */
unsigned short gabe_number; /* GABE revision information */
unsigned short gabe_version;
unsigned short gabe_subrev;