[SeaBIOS] [PATCH 2/4] Rename hw/cmos.h to hw/rtc.h and copy RTC code from clock.c to hw/rtc.c.

Kevin O'Connor kevin at koconnor.net
Thu Sep 19 03:58:52 CEST 2013


Group the Real Time Clock code into hw/rtc.[ch].

Also, use rtc_read/write/mask function naming (instead of
inb/outb_cmos) to be more consistent with other register accessors.

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 Makefile                 |   2 +-
 src/block.c              |   4 +-
 src/boot.c               |   8 +--
 src/clock.c              | 139 ++++++++++++-----------------------------------
 src/fw/paravirt.c        |  16 +++---
 src/fw/smp.c             |   4 +-
 src/hw/ata.c             |   1 -
 src/hw/floppy.c          |   4 +-
 src/hw/rtc.c             |  93 +++++++++++++++++++++++++++++++
 src/hw/{cmos.h => rtc.h} |  53 ++++++++----------
 src/post.c               |   4 +-
 src/resume.c             |   6 +-
 src/romlayout.S          |   2 +-
 src/stacks.c             |   5 +-
 src/util.h               |   2 -
 15 files changed, 177 insertions(+), 166 deletions(-)
 create mode 100644 src/hw/rtc.c
 rename src/hw/{cmos.h => rtc.h} (67%)

diff --git a/Makefile b/Makefile
index 70ba8d9..0cdb6d3 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ OUT=out/
 SRCBOTH=misc.c stacks.c output.c string.c x86.c block.c cdrom.c mouse.c kbd.c \
     serial.c clock.c resume.c pnpbios.c vgahooks.c pcibios.c apm.c \
     fw/smp.c \
-    hw/pci.c hw/timer.c hw/pic.c hw/ps2port.c \
+    hw/pci.c hw/timer.c hw/rtc.c hw/pic.c hw/ps2port.c \
     hw/usb.c hw/usb-uhci.c hw/usb-ohci.c hw/usb-ehci.c \
     hw/usb-hid.c hw/usb-msc.c hw/usb-uas.c \
     hw/blockcmd.c hw/floppy.c hw/ata.c hw/ahci.c hw/ramdisk.c \
diff --git a/src/block.c b/src/block.c
index 4560b24..cbcf9e1 100644
--- a/src/block.c
+++ b/src/block.c
@@ -10,8 +10,8 @@
 #include "bregs.h" // struct bregs
 #include "hw/ata.h" // process_ata_op
 #include "hw/ahci.h" // process_ahci_op
-#include "hw/cmos.h" // inb_cmos
 #include "hw/blockcmd.h" // cdb_*
+#include "hw/rtc.h" // rtc_read
 #include "hw/virtio-blk.h" // process_virtio_blk_op
 #include "malloc.h" // malloc_low
 #include "output.h" // dprintf
@@ -72,7 +72,7 @@ get_translation(struct drive_s *drive_g)
         // Emulators pass in the translation info via nvram.
         u8 ataid = GET_GLOBAL(drive_g->cntl_id);
         u8 channel = ataid / 2;
-        u8 translation = inb_cmos(CMOS_BIOS_DISKTRANSFLAG + channel/2);
+        u8 translation = rtc_read(CMOS_BIOS_DISKTRANSFLAG + channel/2);
         translation >>= 2 * (ataid % 4);
         translation &= 0x03;
         return translation;
diff --git a/src/boot.c b/src/boot.c
index a2851b2..b14ced9 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -9,8 +9,8 @@
 #include "bregs.h" // struct bregs
 #include "config.h" // CONFIG_*
 #include "fw/paravirt.h" // qemu_cfg_show_boot_menu
-#include "hw/cmos.h" // inb_cmos
 #include "hw/pci.h" // pci_bdf_to_*
+#include "hw/rtc.h" // rtc_read
 #include "hw/usb.h" // struct usbdevice_s
 #include "list.h" // hlist_node
 #include "malloc.h" // free
@@ -257,10 +257,10 @@ boot_init(void)
 
     if (CONFIG_QEMU) {
         // On emulators, get boot order from nvram.
-        if (inb_cmos(CMOS_BIOS_BOOTFLAG1) & 1)
+        if (rtc_read(CMOS_BIOS_BOOTFLAG1) & 1)
             CheckFloppySig = 0;
-        u32 bootorder = (inb_cmos(CMOS_BIOS_BOOTFLAG2)
-                         | ((inb_cmos(CMOS_BIOS_BOOTFLAG1) & 0xf0) << 4));
+        u32 bootorder = (rtc_read(CMOS_BIOS_BOOTFLAG2)
+                         | ((rtc_read(CMOS_BIOS_BOOTFLAG1) & 0xf0) << 4));
         DefaultFloppyPrio = DefaultCDPrio = DefaultHDPrio
             = DefaultBEVPrio = DEFAULT_PRIO;
         int i;
diff --git a/src/clock.c b/src/clock.c
index e54944b..9ab0ac0 100644
--- a/src/clock.c
+++ b/src/clock.c
@@ -7,64 +7,19 @@
 
 #include "biosvar.h" // SET_BDA
 #include "bregs.h" // struct bregs
-#include "hw/cmos.h" // inb_cmos
 #include "hw/pic.h" // pic_eoi1
+#include "hw/rtc.h" // rtc_read
 #include "hw/usb-hid.h" // usb_check_event
 #include "output.h" // debug_enter
 #include "stacks.h" // yield
 #include "string.h" // memset
 #include "util.h" // clock_setup
 
-// RTC register flags
-#define RTC_A_UIP 0x80
-
-#define RTC_B_SET  0x80
-#define RTC_B_PIE  0x40
-#define RTC_B_AIE  0x20
-#define RTC_B_UIE  0x10
-#define RTC_B_BIN  0x04
-#define RTC_B_24HR 0x02
-#define RTC_B_DSE  0x01
-
 
 /****************************************************************
  * Init
  ****************************************************************/
 
-static int
-rtc_updating(void)
-{
-    // This function checks to see if the update-in-progress bit
-    // is set in CMOS Status Register A.  If not, it returns 0.
-    // If it is set, it tries to wait until there is a transition
-    // to 0, and will return 0 if such a transition occurs.  A -1
-    // is returned only after timing out.  The maximum period
-    // that this bit should be set is constrained to (1984+244)
-    // useconds, but we wait for longer just to be sure.
-
-    if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0)
-        return 0;
-    u32 end = timer_calc(15);
-    for (;;) {
-        if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0)
-            return 0;
-        if (timer_check(end))
-            // update-in-progress never transitioned to 0
-            return -1;
-        yield();
-    }
-}
-
-static void
-rtc_setup(void)
-{
-    outb_cmos(0x26, CMOS_STATUS_A);    // 32,768Khz src, 976.5625us updates
-    u8 regB = inb_cmos(CMOS_STATUS_B);
-    outb_cmos((regB & RTC_B_DSE) | RTC_B_24HR, CMOS_STATUS_B);
-    inb_cmos(CMOS_STATUS_C);
-    inb_cmos(CMOS_STATUS_D);
-}
-
 static u32
 bcd2bin(u8 val)
 {
@@ -81,18 +36,18 @@ clock_setup(void)
 
     rtc_setup();
     rtc_updating();
-    u32 seconds = bcd2bin(inb_cmos(CMOS_RTC_SECONDS));
-    u32 minutes = bcd2bin(inb_cmos(CMOS_RTC_MINUTES));
-    u32 hours = bcd2bin(inb_cmos(CMOS_RTC_HOURS));
+    u32 seconds = bcd2bin(rtc_read(CMOS_RTC_SECONDS));
+    u32 minutes = bcd2bin(rtc_read(CMOS_RTC_MINUTES));
+    u32 hours = bcd2bin(rtc_read(CMOS_RTC_HOURS));
     u32 ticks = ticks_from_ms(((hours * 60 + minutes) * 60 + seconds) * 1000);
     SET_BDA(timer_counter, ticks % TICKS_PER_DAY);
 
     // Setup Century storage
     if (CONFIG_QEMU) {
-        Century = inb_cmos(CMOS_CENTURY);
+        Century = rtc_read(CMOS_CENTURY);
     } else {
         // Infer current century from the year.
-        u8 year = inb_cmos(CMOS_RTC_YEAR);
+        u8 year = rtc_read(CMOS_RTC_YEAR);
         if (year > 0x80)
             Century = 0x19;
         else
@@ -142,10 +97,10 @@ handle_1a02(struct bregs *regs)
         return;
     }
 
-    regs->dh = inb_cmos(CMOS_RTC_SECONDS);
-    regs->cl = inb_cmos(CMOS_RTC_MINUTES);
-    regs->ch = inb_cmos(CMOS_RTC_HOURS);
-    regs->dl = inb_cmos(CMOS_STATUS_B) & RTC_B_DSE;
+    regs->dh = rtc_read(CMOS_RTC_SECONDS);
+    regs->cl = rtc_read(CMOS_RTC_MINUTES);
+    regs->ch = rtc_read(CMOS_RTC_HOURS);
+    regs->dl = rtc_read(CMOS_STATUS_B) & RTC_B_DSE;
     regs->ah = 0;
     regs->al = regs->ch;
     set_success(regs);
@@ -169,13 +124,13 @@ handle_1a03(struct bregs *regs)
         rtc_setup();
         // fall through as if an update were not in progress
     }
-    outb_cmos(regs->dh, CMOS_RTC_SECONDS);
-    outb_cmos(regs->cl, CMOS_RTC_MINUTES);
-    outb_cmos(regs->ch, CMOS_RTC_HOURS);
+    rtc_write(CMOS_RTC_SECONDS, regs->dh);
+    rtc_write(CMOS_RTC_MINUTES, regs->cl);
+    rtc_write(CMOS_RTC_HOURS, regs->ch);
     // Set Daylight Savings time enabled bit to requested value
-    u8 val8 = ((inb_cmos(CMOS_STATUS_B) & (RTC_B_PIE|RTC_B_AIE))
+    u8 val8 = ((rtc_read(CMOS_STATUS_B) & (RTC_B_PIE|RTC_B_AIE))
                | RTC_B_24HR | (regs->dl & RTC_B_DSE));
-    outb_cmos(val8, CMOS_STATUS_B);
+    rtc_write(CMOS_STATUS_B, val8);
     regs->ah = 0;
     regs->al = val8; // val last written to Reg B
     set_success(regs);
@@ -190,9 +145,9 @@ handle_1a04(struct bregs *regs)
         set_invalid(regs);
         return;
     }
-    regs->cl = inb_cmos(CMOS_RTC_YEAR);
-    regs->dh = inb_cmos(CMOS_RTC_MONTH);
-    regs->dl = inb_cmos(CMOS_RTC_DAY_MONTH);
+    regs->cl = rtc_read(CMOS_RTC_YEAR);
+    regs->dh = rtc_read(CMOS_RTC_MONTH);
+    regs->dl = rtc_read(CMOS_RTC_DAY_MONTH);
     regs->ch = GET_LOW(Century);
     regs->al = regs->ch;
     set_success(regs);
@@ -217,13 +172,13 @@ handle_1a05(struct bregs *regs)
         set_invalid(regs);
         return;
     }
-    outb_cmos(regs->cl, CMOS_RTC_YEAR);
-    outb_cmos(regs->dh, CMOS_RTC_MONTH);
-    outb_cmos(regs->dl, CMOS_RTC_DAY_MONTH);
+    rtc_write(CMOS_RTC_YEAR, regs->cl);
+    rtc_write(CMOS_RTC_MONTH, regs->dh);
+    rtc_write(CMOS_RTC_DAY_MONTH, regs->dl);
     SET_LOW(Century, regs->ch);
     // clear halt-clock bit
-    u8 val8 = inb_cmos(CMOS_STATUS_B) & ~RTC_B_SET;
-    outb_cmos(val8, CMOS_STATUS_B);
+    u8 val8 = rtc_read(CMOS_STATUS_B) & ~RTC_B_SET;
+    rtc_write(CMOS_STATUS_B, val8);
     regs->ah = 0;
     regs->al = val8; // AL = val last written to Reg B
     set_success(regs);
@@ -243,7 +198,7 @@ handle_1a06(struct bregs *regs)
     //
     // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
     // My assumption: RegB = ((RegB & 01111111b) | 00100000b)
-    u8 val8 = inb_cmos(CMOS_STATUS_B); // Get Status Reg B
+    u8 val8 = rtc_read(CMOS_STATUS_B); // Get Status Reg B
     regs->ax = 0;
     if (val8 & RTC_B_AIE) {
         // Alarm interrupt enabled already
@@ -254,11 +209,11 @@ handle_1a06(struct bregs *regs)
         rtc_setup();
         // fall through as if an update were not in progress
     }
-    outb_cmos(regs->dh, CMOS_RTC_SECONDS_ALARM);
-    outb_cmos(regs->cl, CMOS_RTC_MINUTES_ALARM);
-    outb_cmos(regs->ch, CMOS_RTC_HOURS_ALARM);
+    rtc_write(CMOS_RTC_SECONDS_ALARM, regs->dh);
+    rtc_write(CMOS_RTC_MINUTES_ALARM, regs->cl);
+    rtc_write(CMOS_RTC_HOURS_ALARM, regs->ch);
     // enable Status Reg B alarm bit, clear halt clock bit
-    outb_cmos((val8 & ~RTC_B_SET) | RTC_B_AIE, CMOS_STATUS_B);
+    rtc_write(CMOS_STATUS_B, (val8 & ~RTC_B_SET) | RTC_B_AIE);
     set_success(regs);
 }
 
@@ -276,9 +231,9 @@ handle_1a07(struct bregs *regs)
     //
     // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
     // My assumption: RegB = (RegB & 01010111b)
-    u8 val8 = inb_cmos(CMOS_STATUS_B); // Get Status Reg B
+    u8 val8 = rtc_read(CMOS_STATUS_B); // Get Status Reg B
     // clear clock-halt bit, disable alarm bit
-    outb_cmos(val8 & ~(RTC_B_SET|RTC_B_AIE), CMOS_STATUS_B);
+    rtc_write(CMOS_STATUS_B, val8 & ~(RTC_B_SET|RTC_B_AIE));
     regs->ah = 0;
     regs->al = val8; // val last written to Reg B
     set_success(regs);
@@ -374,32 +329,6 @@ irqtimer_check(u32 end)
  * Periodic timer
  ****************************************************************/
 
-int RTCusers VARLOW;
-
-void
-useRTC(void)
-{
-    int count = GET_LOW(RTCusers);
-    SET_LOW(RTCusers, count+1);
-    if (count)
-        return;
-    // Turn on the Periodic Interrupt timer
-    u8 bRegister = inb_cmos(CMOS_STATUS_B);
-    outb_cmos(bRegister | RTC_B_PIE, CMOS_STATUS_B);
-}
-
-void
-releaseRTC(void)
-{
-    int count = GET_LOW(RTCusers);
-    SET_LOW(RTCusers, count-1);
-    if (count != 1)
-        return;
-    // Clear the Periodic Interrupt.
-    u8 bRegister = inb_cmos(CMOS_STATUS_B);
-    outb_cmos(bRegister & ~RTC_B_PIE, CMOS_STATUS_B);
-}
-
 static int
 set_usertimer(u32 usecs, u16 seg, u16 offset)
 {
@@ -410,7 +339,7 @@ set_usertimer(u32 usecs, u16 seg, u16 offset)
     SET_BDA(rtc_wait_flag, RWS_WAIT_PENDING);  // Set status byte.
     SET_BDA(user_wait_complete_flag, SEGOFF(seg, offset));
     SET_BDA(user_wait_timeout, usecs);
-    useRTC();
+    rtc_use();
     return 0;
 }
 
@@ -421,7 +350,7 @@ clear_usertimer(void)
         return;
     // Turn off status byte.
     SET_BDA(rtc_wait_flag, 0);
-    releaseRTC();
+    rtc_release();
 }
 
 #define RET_ECLOCKINUSE  0x83
@@ -489,8 +418,8 @@ handle_70(void)
     debug_isr(DEBUG_ISR_70);
 
     // Check which modes are enabled and have occurred.
-    u8 registerB = inb_cmos(CMOS_STATUS_B);
-    u8 registerC = inb_cmos(CMOS_STATUS_C);
+    u8 registerB = rtc_read(CMOS_STATUS_B);
+    u8 registerC = rtc_read(CMOS_STATUS_C);
 
     if (!(registerB & (RTC_B_PIE|RTC_B_AIE)))
         goto done;
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c
index 2524b7b..f8d44d7 100644
--- a/src/fw/paravirt.c
+++ b/src/fw/paravirt.c
@@ -10,8 +10,8 @@
 
 #include "byteorder.h" // be32_to_cpu
 #include "config.h" // CONFIG_QEMU
-#include "hw/cmos.h" // CMOS_*
 #include "hw/pci.h" // create_pirtable
+#include "hw/rtc.h" // CMOS_*
 #include "ioport.h" // outw
 #include "malloc.h" // malloc_tmp
 #include "memmap.h" // add_e820
@@ -69,21 +69,21 @@ qemu_preinit(void)
     kvm_preinit();
 
     // On emulators, get memory size from nvram.
-    u32 rs = ((inb_cmos(CMOS_MEM_EXTMEM2_LOW) << 16)
-              | (inb_cmos(CMOS_MEM_EXTMEM2_HIGH) << 24));
+    u32 rs = ((rtc_read(CMOS_MEM_EXTMEM2_LOW) << 16)
+              | (rtc_read(CMOS_MEM_EXTMEM2_HIGH) << 24));
     if (rs)
         rs += 16 * 1024 * 1024;
     else
-        rs = (((inb_cmos(CMOS_MEM_EXTMEM_LOW) << 10)
-               | (inb_cmos(CMOS_MEM_EXTMEM_HIGH) << 18))
+        rs = (((rtc_read(CMOS_MEM_EXTMEM_LOW) << 10)
+               | (rtc_read(CMOS_MEM_EXTMEM_HIGH) << 18))
               + 1 * 1024 * 1024);
     RamSize = rs;
     add_e820(0, rs, E820_RAM);
 
     // Check for memory over 4Gig
-    u64 high = ((inb_cmos(CMOS_MEM_HIGHMEM_LOW) << 16)
-                | ((u32)inb_cmos(CMOS_MEM_HIGHMEM_MID) << 24)
-                | ((u64)inb_cmos(CMOS_MEM_HIGHMEM_HIGH) << 32));
+    u64 high = ((rtc_read(CMOS_MEM_HIGHMEM_LOW) << 16)
+                | ((u32)rtc_read(CMOS_MEM_HIGHMEM_MID) << 24)
+                | ((u64)rtc_read(CMOS_MEM_HIGHMEM_HIGH) << 32));
     RamSizeOver4G = high;
     add_e820(0x100000000ull, high, E820_RAM);
 
diff --git a/src/fw/smp.c b/src/fw/smp.c
index b96bcfd..38fe383 100644
--- a/src/fw/smp.c
+++ b/src/fw/smp.c
@@ -6,7 +6,7 @@
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 
 #include "config.h" // CONFIG_*
-#include "hw/cmos.h" // CMOS_BIOS_SMP_COUNT
+#include "hw/rtc.h" // CMOS_BIOS_SMP_COUNT
 #include "output.h" // dprintf
 #include "romfile.h" // romfile_loadint
 #include "stacks.h" // yield
@@ -132,7 +132,7 @@ smp_setup(void)
     writel(APIC_ICR_LOW, 0x000C4600 | sipi_vector);
 
     // Wait for other CPUs to process the SIPI.
-    u8 cmos_smp_count = inb_cmos(CMOS_BIOS_SMP_COUNT);
+    u8 cmos_smp_count = rtc_read(CMOS_BIOS_SMP_COUNT);
     while (cmos_smp_count + 1 != readl(&CountCPUs))
         yield();
 
diff --git a/src/hw/ata.c b/src/hw/ata.c
index 34ba119..8165e50 100644
--- a/src/hw/ata.c
+++ b/src/hw/ata.c
@@ -10,7 +10,6 @@
 #include "block.h" // struct drive_s
 #include "blockcmd.h" // CDB_CMD_READ_10
 #include "byteorder.h" // be16_to_cpu
-#include "cmos.h" // inb_cmos
 #include "ioport.h" // inb
 #include "malloc.h" // malloc_fseg
 #include "output.h" // dprintf
diff --git a/src/hw/floppy.c b/src/hw/floppy.c
index 39efaad..cf1ab87 100644
--- a/src/hw/floppy.c
+++ b/src/hw/floppy.c
@@ -8,7 +8,6 @@
 #include "biosvar.h" // SET_BDA
 #include "block.h" // struct drive_s
 #include "bregs.h" // struct bregs
-#include "cmos.h" // inb_cmos
 #include "config.h" // CONFIG_FLOPPY
 #include "malloc.h" // malloc_fseg
 #include "output.h" // dprintf
@@ -16,6 +15,7 @@
 #include "pci_ids.h" // PCI_CLASS_BRIDGE_ISA
 #include "pic.h" // pic_eoi1
 #include "romfile.h" // romfile_loadint
+#include "rtc.h" // rtc_read
 #include "stacks.h" // yield
 #include "std/disk.h" // DISK_RET_SUCCESS
 #include "string.h" // memset
@@ -139,7 +139,7 @@ floppy_setup(void)
     dprintf(3, "init floppy drives\n");
 
     if (CONFIG_QEMU) {
-        u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE);
+        u8 type = rtc_read(CMOS_FLOPPY_DRIVE_TYPE);
         if (type & 0xf0)
             addFloppy(0, type >> 4);
         if (type & 0x0f)
diff --git a/src/hw/rtc.c b/src/hw/rtc.c
new file mode 100644
index 0000000..9886aa5
--- /dev/null
+++ b/src/hw/rtc.c
@@ -0,0 +1,93 @@
+// Support for MC146818 Real Time Clock chip.
+//
+// Copyright (C) 2008-2013  Kevin O'Connor <kevin at koconnor.net>
+// Copyright (C) 2002  MandrakeSoft S.A.
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "biosvar.h" // GET_LOW
+#include "ioport.h" // inb
+#include "rtc.h" // rtc_read
+#include "stacks.h" // yield
+#include "util.h" // timer_calc
+
+u8
+rtc_read(u8 index)
+{
+    index |= NMI_DISABLE_BIT;
+    outb(index, PORT_CMOS_INDEX);
+    return inb(PORT_CMOS_DATA);
+}
+
+void
+rtc_write(u8 index, u8 val)
+{
+    index |= NMI_DISABLE_BIT;
+    outb(index, PORT_CMOS_INDEX);
+    outb(val, PORT_CMOS_DATA);
+}
+
+void
+rtc_mask(u8 index, u8 off, u8 on)
+{
+    outb(index, PORT_CMOS_INDEX);
+    u8 val = inb(PORT_CMOS_DATA);
+    outb((val & ~off) | on, PORT_CMOS_DATA);
+}
+
+int
+rtc_updating(void)
+{
+    // This function checks to see if the update-in-progress bit
+    // is set in CMOS Status Register A.  If not, it returns 0.
+    // If it is set, it tries to wait until there is a transition
+    // to 0, and will return 0 if such a transition occurs.  A -1
+    // is returned only after timing out.  The maximum period
+    // that this bit should be set is constrained to (1984+244)
+    // useconds, but we wait for longer just to be sure.
+
+    if ((rtc_read(CMOS_STATUS_A) & RTC_A_UIP) == 0)
+        return 0;
+    u32 end = timer_calc(15);
+    for (;;) {
+        if ((rtc_read(CMOS_STATUS_A) & RTC_A_UIP) == 0)
+            return 0;
+        if (timer_check(end))
+            // update-in-progress never transitioned to 0
+            return -1;
+        yield();
+    }
+}
+
+void
+rtc_setup(void)
+{
+    rtc_write(CMOS_STATUS_A, 0x26);    // 32,768Khz src, 976.5625us updates
+    rtc_mask(CMOS_STATUS_B, ~RTC_B_DSE, RTC_B_24HR);
+    rtc_read(CMOS_STATUS_C);
+    rtc_read(CMOS_STATUS_D);
+}
+
+int RTCusers VARLOW;
+
+void
+rtc_use(void)
+{
+    int count = GET_LOW(RTCusers);
+    SET_LOW(RTCusers, count+1);
+    if (count)
+        return;
+    // Turn on the Periodic Interrupt timer
+    rtc_mask(CMOS_STATUS_B, 0, RTC_B_PIE);
+}
+
+void
+rtc_release(void)
+{
+    int count = GET_LOW(RTCusers);
+    SET_LOW(RTCusers, count-1);
+    if (count != 1)
+        return;
+    // Clear the Periodic Interrupt.
+    rtc_mask(CMOS_STATUS_B, RTC_B_PIE, 0);
+}
diff --git a/src/hw/cmos.h b/src/hw/rtc.h
similarity index 67%
rename from src/hw/cmos.h
rename to src/hw/rtc.h
index 067c7fa..d975f6b 100644
--- a/src/hw/cmos.h
+++ b/src/hw/rtc.h
@@ -1,10 +1,5 @@
-// Definitions for X86 CMOS non-volatile memory access.
-//
-// Copyright (C) 2008  Kevin O'Connor <kevin at koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-#ifndef __CMOS_H
-#define __CMOS_H
+#ifndef __RTC_H
+#define __RTC_H
 
 // Standard BIOS RTC chip entries
 #define CMOS_RTC_SECONDS         0x00
@@ -45,34 +40,30 @@
 #define CMOS_MEM_HIGHMEM_HIGH    0x5d
 #define CMOS_BIOS_SMP_COUNT      0x5f
 
-// CMOS_FLOPPY_DRIVE_TYPE bitdefs
-#define CFD_NO_DRIVE 0
-#define CFD_360KB    1
-#define CFD_12MB     2
-#define CFD_720KB    3
-#define CFD_144MB    4
-#define CFD_288MB    5
+// RTC register flags
+#define RTC_A_UIP 0x80
 
-#ifndef __ASSEMBLY__
+#define RTC_B_SET  0x80
+#define RTC_B_PIE  0x40
+#define RTC_B_AIE  0x20
+#define RTC_B_UIE  0x10
+#define RTC_B_BIN  0x04
+#define RTC_B_24HR 0x02
+#define RTC_B_DSE  0x01
 
-#include "ioport.h" // inb, outb
+#ifndef __ASSEMBLY__
 
-static inline u8
-inb_cmos(u8 reg)
-{
-    reg |= NMI_DISABLE_BIT;
-    outb(reg, PORT_CMOS_INDEX);
-    return inb(PORT_CMOS_DATA);
-}
+#include "types.h" // u8
 
-static inline void
-outb_cmos(u8 val, u8 reg)
-{
-    reg |= NMI_DISABLE_BIT;
-    outb(reg, PORT_CMOS_INDEX);
-    outb(val, PORT_CMOS_DATA);
-}
+// rtc.c
+u8 rtc_read(u8 index);
+void rtc_write(u8 index, u8 val);
+void rtc_mask(u8 index, u8 off, u8 on);
+int rtc_updating(void);
+void rtc_setup(void);
+void rtc_use(void);
+void rtc_release(void);
 
 #endif // !__ASSEMBLY__
 
-#endif // cmos.h
+#endif // rtc.h
diff --git a/src/post.c b/src/post.c
index 592176d..acd2362 100644
--- a/src/post.c
+++ b/src/post.c
@@ -12,12 +12,12 @@
 #include "fw/xen.h" // xen_preinit
 #include "hw/ahci.h" // ahci_setup
 #include "hw/ata.h" // ata_setup
-#include "hw/cmos.h" // CMOS_*
 #include "hw/esp-scsi.h" // esp_scsi_setup
 #include "hw/lsi-scsi.h" // lsi_scsi_setup
 #include "hw/megasas.h" // megasas_setup
 #include "hw/pic.h" // pic_setup
 #include "hw/ps2port.h" // ps2port_setup
+#include "hw/rtc.h" // rtc_write
 #include "hw/usb.h" // usb_setup
 #include "hw/virtio-blk.h" // virtio_blk_setup
 #include "hw/virtio-scsi.h" // virtio_scsi_setup
@@ -39,7 +39,7 @@ ivt_init(void)
 
     // Setup reset-vector entry point (controls legacy reboots).
     HaveRunPost = 1;
-    outb_cmos(0, CMOS_RESET_CODE);
+    rtc_write(CMOS_RESET_CODE, 0);
 
     // Initialize all vectors to the default handler.
     int i;
diff --git a/src/resume.c b/src/resume.c
index af39a1d..12daf0f 100644
--- a/src/resume.c
+++ b/src/resume.c
@@ -7,10 +7,10 @@
 #include "bregs.h" // struct bregs
 #include "config.h" // CONFIG_*
 #include "farptr.h" // FLATPTR_TO_SEGOFF
-#include "hw/cmos.h" // inb_cmos
 #include "hw/pci.h" // pci_reboot
 #include "hw/pic.h" // pic_eoi2
 #include "hw/ps2port.h" // i8042_reboot
+#include "hw/rtc.h" // rtc_read
 #include "ioport.h" // outb
 #include "output.h" // dprintf
 #include "stacks.h" // farcall16big
@@ -40,8 +40,8 @@ handle_resume(void)
 {
     ASSERT16();
     debug_serial_preinit();
-    int status = inb_cmos(CMOS_RESET_CODE);
-    outb_cmos(0, CMOS_RESET_CODE);
+    int status = rtc_read(CMOS_RESET_CODE);
+    rtc_write(CMOS_RESET_CODE, 0);
     dprintf(1, "In resume (status=%d)\n", status);
 
     dma_setup();
diff --git a/src/romlayout.S b/src/romlayout.S
index 17904ae..3307f76 100644
--- a/src/romlayout.S
+++ b/src/romlayout.S
@@ -8,7 +8,7 @@
 #include "config.h" // CONFIG_*
 #include "ioport.h" // PORT_A20
 #include "x86.h" // CR0_*
-#include "hw/cmos.h" // CMOS_RESET_CODE
+#include "hw/rtc.h" // CMOS_RESET_CODE
 #include "asm-offsets.h" // BREGS_*
 #include "entryfuncs.S" // ENTRY_*
 
diff --git a/src/stacks.c b/src/stacks.c
index cc597c6..d8aaca8 100644
--- a/src/stacks.c
+++ b/src/stacks.c
@@ -6,6 +6,7 @@
 
 #include "biosvar.h" // GET_GLOBAL
 #include "bregs.h" // CR0_PE
+#include "hw/rtc.h" // rtc_use
 #include "list.h" // hlist_node
 #include "malloc.h" // free
 #include "output.h" // dprintf
@@ -446,7 +447,7 @@ start_preempt(void)
         return;
     CanPreempt = 1;
     PreemptCount = 0;
-    useRTC();
+    rtc_use();
 }
 
 // Turn off RTC irqs / stop checking for thread execution.
@@ -458,7 +459,7 @@ finish_preempt(void)
         return;
     }
     CanPreempt = 0;
-    releaseRTC();
+    rtc_release();
     dprintf(9, "Done preempt - %d checks\n", PreemptCount);
     yield();
 }
diff --git a/src/util.h b/src/util.h
index 57c3ae9..9c45925 100644
--- a/src/util.h
+++ b/src/util.h
@@ -59,8 +59,6 @@ u32 irqtimer_calc_ticks(u32 count);
 u32 irqtimer_calc(u32 msecs);
 int irqtimer_check(u32 end);
 void handle_1586(struct bregs *regs);
-void useRTC(void);
-void releaseRTC(void);
 
 // fw/acpi.c
 extern struct rsdp_descriptor *RsdpAddr;
-- 
1.8.3.1




More information about the SeaBIOS mailing list