X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/32b9a6d76790c73d3d2d36d9081a2581cc65d184..28c176b668c841a3b7fb093faccf0efa39257603:/lunaix-os/arch/i386/hal/mc146818a.c diff --git a/lunaix-os/arch/i386/hal/mc146818a.c b/lunaix-os/arch/i386/hal/mc146818a.c deleted file mode 100644 index 96b95e1..0000000 --- a/lunaix-os/arch/i386/hal/mc146818a.c +++ /dev/null @@ -1,227 +0,0 @@ -/** - * @file rtc.c - * @author Lunaixsky - * @brief RTC & CMOS abstraction. Reference: MC146818A & Intel Series 500 PCH - * datasheet - * @version 0.1 - * @date 2022-03-07 - * - * @copyright Copyright (c) 2022 - * - */ - -#include -#include -#include -#include - -#include - -#include - -#include - -#define RTC_INDEX_PORT 0x70 -#define RTC_TARGET_PORT 0x71 - -#define WITH_NMI_DISABLED 0x80 - -#define RTC_CURRENT_CENTRY 20 - -#define RTC_REG_YRS 0x9 -#define RTC_REG_MTH 0x8 -#define RTC_REG_DAY 0x7 -#define RTC_REG_WDY 0x6 -#define RTC_REG_HRS 0x4 -#define RTC_REG_MIN 0x2 -#define RTC_REG_SEC 0x0 - -#define RTC_REG_A 0xA -#define RTC_REG_B 0xB -#define RTC_REG_C 0xC -#define RTC_REG_D 0xD - -#define RTC_SET 0x80 -#define RTC_BIN (1 << 2) -#define RTC_HOURFORM24 (1 << 1) - -#define RTC_BIN_ENCODED(reg) (reg & 0x04) -#define RTC_24HRS_ENCODED(reg) (reg & 0x02) - -#define RTC_TIMER_BASE_FREQUENCY 1024 -#define RTC_TIMER_ON 0x40 - -#define RTC_FREQUENCY_1024HZ 0b110 -#define RTC_DIVIDER_33KHZ (0b010 << 4) - -#define PC_AT_IRQ_RTC 8 - -struct mc146818 -{ - struct hwrtc* rtc_context; - u32_t rtc_iv; - u32_t tick_counts; -}; - -#define rtc_state(data) ((struct mc146818*)(data)) - -static u8_t -rtc_read_reg(u8_t reg_selector) -{ - port_wrbyte(RTC_INDEX_PORT, reg_selector); - return port_rdbyte(RTC_TARGET_PORT); -} - -static void -rtc_write_reg(u8_t reg_selector, u8_t val) -{ - port_wrbyte(RTC_INDEX_PORT, reg_selector); - port_wrbyte(RTC_TARGET_PORT, val); -} - -static void -rtc_enable_timer() -{ - u8_t regB = rtc_read_reg(RTC_REG_B); - rtc_write_reg(RTC_REG_B, regB | RTC_TIMER_ON); -} - -static void -rtc_disable_timer() -{ - u8_t regB = rtc_read_reg(RTC_REG_B); - rtc_write_reg(RTC_REG_B, regB & ~RTC_TIMER_ON); -} - -static void -rtc_getwalltime(struct hwrtc* rtc, datetime_t* datetime) -{ - datetime_t current; - - do { - while (rtc_read_reg(RTC_REG_A) & 0x80) - ; - memcpy(¤t, datetime, sizeof(datetime_t)); - - datetime->year = rtc_read_reg(RTC_REG_YRS); - datetime->month = rtc_read_reg(RTC_REG_MTH); - datetime->day = rtc_read_reg(RTC_REG_DAY); - datetime->weekday = rtc_read_reg(RTC_REG_WDY); - datetime->hour = rtc_read_reg(RTC_REG_HRS); - datetime->minute = rtc_read_reg(RTC_REG_MIN); - datetime->second = rtc_read_reg(RTC_REG_SEC); - } while (!datatime_eq(datetime, ¤t)); - - datetime->year += RTC_CURRENT_CENTRY * 100; -} - -static void -rtc_setwalltime(struct hwrtc* rtc, datetime_t* datetime) -{ - u8_t reg = rtc_read_reg(RTC_REG_B); - reg = reg & ~RTC_SET; - - rtc_write_reg(RTC_REG_B, reg | RTC_SET); - - rtc_write_reg(RTC_REG_YRS, datetime->year - RTC_CURRENT_CENTRY * 100); - rtc_write_reg(RTC_REG_MTH, datetime->month); - rtc_write_reg(RTC_REG_DAY, datetime->day); - rtc_write_reg(RTC_REG_WDY, datetime->weekday); - rtc_write_reg(RTC_REG_HRS, datetime->hour); - rtc_write_reg(RTC_REG_MIN, datetime->minute); - rtc_write_reg(RTC_REG_SEC, datetime->second); - - rtc_write_reg(RTC_REG_B, reg & ~RTC_SET); -} - -static int -mc146818_check_support(struct hwrtc* rtc) -{ -#if __ARCH__ == i386 - return 1; -#else - return 0; -#endif -} - -static void -__rtc_tick(const struct hart_state* hstate) -{ - struct mc146818* state = (struct mc146818*)isrm_get_payload(hstate); - - state->tick_counts++; - - (void)rtc_read_reg(RTC_REG_C); -} - -static void -rtc_set_mask(struct hwrtc* rtc) -{ - rtc->state = RTC_STATE_MASKED; - rtc_disable_timer(); -} - -static void -rtc_cls_mask(struct hwrtc* rtc) -{ - struct mc146818* state = rtc_state(rtc->data); - - rtc->state = 0; - state->tick_counts = 0; - rtc_enable_timer(); -} - -static int -rtc_chfreq(struct hwrtc* rtc, int freq) -{ - return ENOTSUP; -} - -static int -rtc_getcnt(struct hwrtc* rtc) -{ - struct mc146818* state = rtc_state(rtc->data); - return state->tick_counts; -} - -static int -rtc_init(struct device_def* devdef) -{ - u8_t reg = rtc_read_reg(RTC_REG_A); - reg = (reg & ~0x7f) | RTC_FREQUENCY_1024HZ | RTC_DIVIDER_33KHZ; - rtc_write_reg(RTC_REG_A, reg); - - reg = RTC_BIN | RTC_HOURFORM24; - rtc_write_reg(RTC_REG_B, reg); - - // Make sure the rtc timer is disabled by default - rtc_disable_timer(); - - struct hwrtc* rtc = hwrtc_alloc_new("mc146818"); - struct mc146818* state = valloc(sizeof(struct mc146818)); - - state->rtc_context = rtc; - state->rtc_iv = isrm_bindirq(PC_AT_IRQ_RTC, __rtc_tick); - isrm_set_payload(state->rtc_iv, (ptr_t)state); - - rtc->state = RTC_STATE_MASKED; - rtc->data = state; - rtc->base_freq = RTC_TIMER_BASE_FREQUENCY; - rtc->get_walltime = rtc_getwalltime; - rtc->set_walltime = rtc_setwalltime; - rtc->set_mask = rtc_set_mask; - rtc->cls_mask = rtc_cls_mask; - rtc->get_counts = rtc_getcnt; - rtc->chfreq = rtc_chfreq; - - hwrtc_register(&devdef->class, rtc); - - return 0; -} - -static struct device_def devrtc_mc146818 = { - .name = "MC146818 RTC", - .class = DEVCLASS(DEVIF_SOC, DEVFN_TIME, DEV_RTC), - .init = rtc_init -}; -EXPORT_DEVICE(mc146818, &devrtc_mc146818, load_timedev); \ No newline at end of file