X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/a35bb9648f1a9eddb071a50ff6a4dcdb8f379f24..f89517343bf062d299d54408eea2f9387bfefb6d:/lunaix-os/arch/x86/hal/mc146818a.c diff --git a/lunaix-os/arch/x86/hal/mc146818a.c b/lunaix-os/arch/x86/hal/mc146818a.c index 9c788f9..fcb5d7f 100644 --- a/lunaix-os/arch/x86/hal/mc146818a.c +++ b/lunaix-os/arch/x86/hal/mc146818a.c @@ -15,17 +15,15 @@ #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 @@ -58,35 +56,34 @@ struct mc146818 { - struct hwrtc* rtc_context; - u32_t rtc_iv; - u32_t tick_counts; + struct hwrtc_potens* rtc_context; + irq_t irq; }; #define rtc_state(data) ((struct mc146818*)(data)) -static u8_t +static inline u8_t rtc_read_reg(u8_t reg_selector) { port_wrbyte(RTC_INDEX_PORT, reg_selector); return port_rdbyte(RTC_TARGET_PORT); } -static void +static inline 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 +static inline 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 +static inline void rtc_disable_timer() { u8_t regB = rtc_read_reg(RTC_REG_B); @@ -94,7 +91,7 @@ rtc_disable_timer() } static void -rtc_getwalltime(struct hwrtc* rtc, datetime_t* datetime) +rtc_getwalltime(struct hwrtc_potens* rtc, datetime_t* datetime) { datetime_t current; @@ -116,7 +113,7 @@ rtc_getwalltime(struct hwrtc* rtc, datetime_t* datetime) } static void -rtc_setwalltime(struct hwrtc* rtc, datetime_t* datetime) +rtc_setwalltime(struct hwrtc_potens* rtc, datetime_t* datetime) { u8_t reg = rtc_read_reg(RTC_REG_B); reg = reg & ~RTC_SET; @@ -134,60 +131,46 @@ rtc_setwalltime(struct hwrtc* rtc, datetime_t* datetime) 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) +__rtc_tick(irq_t irq, const struct hart_state* hstate) { - struct mc146818* state = (struct mc146818*)isrm_get_payload(hstate); + struct mc146818* state; - state->tick_counts++; + state = irq_payload(irq, struct mc146818); + state->rtc_context->live++; (void)rtc_read_reg(RTC_REG_C); } static void -rtc_set_mask(struct hwrtc* rtc) +rtc_set_proactive(struct hwrtc_potens* pot, bool proactive) { - 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(); + if (proactive) { + pot->state = 0; + rtc_enable_timer(); + } + else { + pot->state = RTC_STATE_MASKED; + rtc_disable_timer(); + } } static int -rtc_chfreq(struct hwrtc* rtc, int freq) +rtc_chfreq(struct hwrtc_potens* rtc, int freq) { return ENOTSUP; } static int -rtc_getcnt(struct hwrtc* rtc) +__rtc_calibrate(struct hwrtc_potens* pot) { - struct mc146818* state = rtc_state(rtc->data); - return state->tick_counts; -} + struct mc146818* state; + struct device* rtc_dev; + u8_t reg; -static int -rtc_init(struct device_def* devdef) -{ - u8_t reg = rtc_read_reg(RTC_REG_A); + rtc_dev = potens_dev(pot); + + reg = rtc_read_reg(RTC_REG_A); reg = (reg & ~0x7f) | RTC_FREQUENCY_1024HZ | RTC_DIVIDER_33KHZ; rtc_write_reg(RTC_REG_A, reg); @@ -197,31 +180,52 @@ rtc_init(struct device_def* devdef) // 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)); + pot->base_freq = RTC_TIMER_BASE_FREQUENCY; + + state = (struct mc146818*)rtc_dev->underlay; + + state->irq = irq_declare_line(__rtc_tick, PC_AT_IRQ_RTC); + irq_set_payload(state->irq, state); + + irq_assign(irq_owning_domain(rtc_dev), state->irq, NULL); + + return 0; +} + +static struct hwrtc_potens_ops ops = { + .get_walltime = rtc_getwalltime, + .set_walltime = rtc_setwalltime, + .set_proactive = rtc_set_proactive, + .chfreq = rtc_chfreq, + .calibrate = __rtc_calibrate +}; + +static int +rtc_load(struct device_def* devdef) +{ + struct device* dev; + struct mc146818* state; + struct hwrtc_potens* pot; + + state = valloc(sizeof(struct mc146818)); + dev = device_allocsys(NULL, state); - state->rtc_context = rtc; - state->rtc_iv = isrm_bindirq(PC_AT_IRQ_RTC, __rtc_tick); - isrm_set_payload(state->rtc_iv, (ptr_t)state); + pot = hwrtc_attach_potens(dev, &ops); + if (!pot) { + return 1; + } - 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; + pot->state = RTC_STATE_MASKED; + state->rtc_context = pot; - hwrtc_register(&devdef->class, rtc); + register_device(dev, &devdef->class, "mc146818"); return 0; } static struct device_def devrtc_mc146818 = { - .name = "MC146818 RTC", - .class = DEVCLASS(DEVIF_SOC, DEVFN_TIME, DEV_RTC), - .init = rtc_init + def_device_class(INTEL, TIME, RTC), + def_device_name("x86 legacy RTC"), + def_on_load(rtc_load) }; -EXPORT_DEVICE(mc146818, &devrtc_mc146818, load_timedev); \ No newline at end of file +EXPORT_DEVICE(mc146818, &devrtc_mc146818, load_sysconf); \ No newline at end of file