125 lines
3.8 KiB
C
125 lines
3.8 KiB
C
#include "rtc.h"
|
|
#include "../interrupts/multiprocessing.h"
|
|
#include "../lib/status_bar.h"
|
|
|
|
uint8_t rtc_global_counter = 0;
|
|
|
|
// Unified FS interface for RTC.
|
|
unified_fs_interface_t rtc_if = {
|
|
.open = rtc_open,
|
|
.read = rtc_read,
|
|
.write = rtc_write,
|
|
.ioctl = NULL,
|
|
.close = rtc_close
|
|
};
|
|
|
|
/* uint8_t rtc_init()
|
|
* @output: RTC set to 1024Hz
|
|
* @description: initializes virtualizing the RTC
|
|
*/
|
|
uint8_t rtc_init() {
|
|
// Initialization code, from https://wiki.osdev.org/RTC
|
|
outb(RTC_REG_B, RTC_PORT_CMD); // select register B, and disable NMI
|
|
char prev = inb(RTC_PORT_DATA); // read the current value of register B
|
|
outb(RTC_REG_B, RTC_PORT_CMD); // set the index again (a read will reset the index to register D)
|
|
outb(prev | 0x40, RTC_PORT_DATA); // write the previous value ORed with 0x40. This turns on bit 6 of register B
|
|
enable_irq(RTC_IRQ);
|
|
|
|
// set the RTC frequency to 1024 Hz
|
|
outb(RTC_REG_A, RTC_PORT_CMD);
|
|
outb(RTC_FREQ_1024, RTC_PORT_DATA);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* void rtc_interrupt()
|
|
* @description: function to be called when RTC generates an interrupt.
|
|
* Decreases offset for all RTC handles, as offsets are counters for timing.
|
|
*/
|
|
void rtc_interrupt() {
|
|
// Triggers global event every 256 ticks (0.25s)
|
|
rtc_global_counter++;
|
|
if(0 == rtc_global_counter) rtc_periodic_event();
|
|
|
|
// For all processes, find RTC handles and update their offset
|
|
int pid;
|
|
for(pid = 0; pid < MAX_PROGRAMS_NUM; pid++) {
|
|
process_t* process = process_get_pcb(pid);
|
|
if(!process->present) continue;
|
|
int fd;
|
|
for(fd = 0; fd < MAX_NUM_FD_ENTRY; fd++) {
|
|
if(process->fd_array[fd].interface != &rtc_if) continue;
|
|
|
|
// This is an RTC handle
|
|
if(process->fd_array[fd].pos > 0) {
|
|
process->fd_array[fd].pos--;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Read from RTC register C, so it can keep sending interrupts
|
|
outb(RTC_REG_C, RTC_PORT_CMD); // select register C
|
|
inb(RTC_PORT_DATA); // just throw away contents
|
|
|
|
send_eoi(RTC_IRQ); // And we're done
|
|
}
|
|
|
|
/* void rtc_periodic_event()
|
|
* @description: runs some global events triggered every 0.25s.
|
|
*/
|
|
void rtc_periodic_event() {
|
|
ONTO_DISPLAY_WRAP(status_bar_update_clock());
|
|
}
|
|
|
|
/* int32_t rtc_open(int32_t* inode, char* filename)
|
|
* @input: all ignored
|
|
* @output: 0 (SUCCESS)
|
|
* @description: initialize RTC, set freq to 2 Hz.
|
|
* using *inode to record the interval of rtc calls.
|
|
*/
|
|
int32_t rtc_open(int32_t* inode, char* filename) {
|
|
*inode = RTC_FREQ_BASE / RTC_FREQ_DEFAULT;
|
|
return 0;
|
|
}
|
|
|
|
/* int32_t rtc_read(int32_t* inode, uint32_t* offset, char* buf, uint32_t len)
|
|
* @input: all ignored
|
|
* @output: 0 (SUCCESS)
|
|
* @description: wait until the next RTC tick.
|
|
* using *offset to record how many ticks passed.
|
|
* *offset will be updated by RTC interrupt.
|
|
*/
|
|
int32_t rtc_read(int32_t* inode, uint32_t* offset, char* buf, uint32_t len)
|
|
{
|
|
*offset = *inode;
|
|
while(*offset > 0) wait_interrupt();
|
|
return 0;
|
|
}
|
|
|
|
/* int32_t rtc_write(int32_t* inode, uint32_t* offset, const char* buf, uint32_t len)
|
|
* @input: buf - value of new frequency for RTC
|
|
* len - length of buf, should be sizeof(uint16_t)
|
|
* @output: 0 (SUCCESS) / -1 (FAIL)
|
|
* @description: set the frequency of interrupts by RTC
|
|
*/
|
|
int32_t rtc_write(int32_t* inode, uint32_t* offset, const char* buf, uint32_t len) {
|
|
// invalid input
|
|
if(len != sizeof(uint32_t)) return -1; // Removed, otherwise fish won't work
|
|
if(buf == NULL) return -1;
|
|
// change the frequency of RTC
|
|
uint32_t freq = *(uint32_t *)buf;
|
|
*inode = RTC_FREQ_BASE / freq;
|
|
// quit critical section
|
|
return 0;
|
|
}
|
|
|
|
/* int32_t rtc_close(int32_t* inode)
|
|
* @input: inode - ignored
|
|
* @output: 0 (SUCCESS)
|
|
* @description: close RTC, currently does nothing
|
|
*/
|
|
int32_t rtc_close(int32_t* inode) {
|
|
*inode = 0;
|
|
return 0;
|
|
}
|