]> xenbits.xensource.com Git - seabios.git/commitdiff
Rename hw/cmos.h to hw/rtc.h and copy RTC code from clock.c to hw/rtc.c.
authorKevin O'Connor <kevin@koconnor.net>
Sun, 15 Sep 2013 06:29:06 +0000 (02:29 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Sun, 29 Sep 2013 02:05:55 +0000 (22:05 -0400)
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@koconnor.net>
16 files changed:
Makefile
src/block.c
src/boot.c
src/clock.c
src/fw/paravirt.c
src/fw/smp.c
src/hw/ata.c
src/hw/cmos.h [deleted file]
src/hw/floppy.c
src/hw/rtc.c [new file with mode: 0644]
src/hw/rtc.h [new file with mode: 0644]
src/post.c
src/resume.c
src/romlayout.S
src/stacks.c
src/util.h

index 229fe54299c938914750f288e34aaf79e1bac636..215e6f58242f1bb18c2bb38f159815b918dde5b9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,7 @@ IASL:=iasl
 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-xhci.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 \
index 4560b24fcb835d159a4877ae00fac5001a15aa2e..cbcf9e145982d08cc492e9fc8593998fec69dd68 100644 (file)
@@ -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;
index a2851b25687190526cb6231955b80de4750940cb..b14ced9bad69646f9abb77bdf5953e5f302ef38e 100644 (file)
@@ -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;
index e54944bec42c87868238b1d603397ba3fa1d345a..9ab0ac0267cacfc5933f0f168ddd29d6e2c40343 100644 (file)
@@ -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;
index 357de5673eedc01ef42bcd0418ee861ca87be94b..5e369f2bedea48a7ccc65029c1fc2e42ccf19aba 100644 (file)
@@ -10,9 +10,9 @@
 
 #include "byteorder.h" // be32_to_cpu
 #include "config.h" // CONFIG_QEMU
-#include "hw/cmos.h" // CMOS_*
 #include "hw/pci.h" // create_pirtable
 #include "hw/pci_regs.h" // PCI_DEVICE_ID
+#include "hw/rtc.h" // CMOS_*
 #include "ioport.h" // outw
 #include "malloc.h" // malloc_tmp
 #include "memmap.h" // add_e820
@@ -105,21 +105,21 @@ qemu_preinit(void)
     }
 
     // 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);
 
index b96bcfd73fcce41a6bf2c702f935e0d6265d8abd..38fe383afca7b818f80e64251ded73f0f960d84f 100644 (file)
@@ -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();
 
index 34ba119d7d1ce67bad8b4db3b53a97bf6b23b896..8165e50e52d25c5ccd6a3dbb0364bdec8443fddf 100644 (file)
@@ -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/cmos.h b/src/hw/cmos.h
deleted file mode 100644 (file)
index 067c7fa..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-// Definitions for X86 CMOS non-volatile memory access.
-//
-// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-#ifndef __CMOS_H
-#define __CMOS_H
-
-// Standard BIOS RTC chip entries
-#define CMOS_RTC_SECONDS         0x00
-#define CMOS_RTC_SECONDS_ALARM   0x01
-#define CMOS_RTC_MINUTES         0x02
-#define CMOS_RTC_MINUTES_ALARM   0x03
-#define CMOS_RTC_HOURS           0x04
-#define CMOS_RTC_HOURS_ALARM     0x05
-#define CMOS_RTC_DAY_WEEK        0x06
-#define CMOS_RTC_DAY_MONTH       0x07
-#define CMOS_RTC_MONTH           0x08
-#define CMOS_RTC_YEAR            0x09
-#define CMOS_STATUS_A            0x0a
-#define CMOS_STATUS_B            0x0b
-#define CMOS_STATUS_C            0x0c
-#define CMOS_STATUS_D            0x0d
-#define CMOS_RESET_CODE          0x0f
-
-// QEMU cmos config fields.  DO NOT ADD MORE.  (All new content should
-// be passed via the fw_cfg "file" interface.)
-#define CMOS_FLOPPY_DRIVE_TYPE   0x10
-#define CMOS_DISK_DATA           0x12
-#define CMOS_EQUIPMENT_INFO      0x14
-#define CMOS_DISK_DRIVE1_TYPE    0x19
-#define CMOS_DISK_DRIVE2_TYPE    0x1a
-#define CMOS_DISK_DRIVE1_CYL     0x1b
-#define CMOS_DISK_DRIVE2_CYL     0x24
-#define CMOS_MEM_EXTMEM_LOW      0x30
-#define CMOS_MEM_EXTMEM_HIGH     0x31
-#define CMOS_CENTURY             0x32
-#define CMOS_MEM_EXTMEM2_LOW     0x34
-#define CMOS_MEM_EXTMEM2_HIGH    0x35
-#define CMOS_BIOS_BOOTFLAG1      0x38
-#define CMOS_BIOS_DISKTRANSFLAG  0x39
-#define CMOS_BIOS_BOOTFLAG2      0x3d
-#define CMOS_MEM_HIGHMEM_LOW     0x5b
-#define CMOS_MEM_HIGHMEM_MID     0x5c
-#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
-
-#ifndef __ASSEMBLY__
-
-#include "ioport.h" // inb, outb
-
-static inline u8
-inb_cmos(u8 reg)
-{
-    reg |= NMI_DISABLE_BIT;
-    outb(reg, PORT_CMOS_INDEX);
-    return inb(PORT_CMOS_DATA);
-}
-
-static inline void
-outb_cmos(u8 val, u8 reg)
-{
-    reg |= NMI_DISABLE_BIT;
-    outb(reg, PORT_CMOS_INDEX);
-    outb(val, PORT_CMOS_DATA);
-}
-
-#endif // !__ASSEMBLY__
-
-#endif // cmos.h
index 39efaadc8472436a014703f2c59e54e8ebd0cc1d..cf1ab87a283373b2dbc80051fa5bbb0bd7f3d5c2 100644 (file)
@@ -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 (file)
index 0000000..9886aa5
--- /dev/null
@@ -0,0 +1,93 @@
+// Support for MC146818 Real Time Clock chip.
+//
+// Copyright (C) 2008-2013  Kevin O'Connor <kevin@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/rtc.h b/src/hw/rtc.h
new file mode 100644 (file)
index 0000000..d975f6b
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef __RTC_H
+#define __RTC_H
+
+// Standard BIOS RTC chip entries
+#define CMOS_RTC_SECONDS         0x00
+#define CMOS_RTC_SECONDS_ALARM   0x01
+#define CMOS_RTC_MINUTES         0x02
+#define CMOS_RTC_MINUTES_ALARM   0x03
+#define CMOS_RTC_HOURS           0x04
+#define CMOS_RTC_HOURS_ALARM     0x05
+#define CMOS_RTC_DAY_WEEK        0x06
+#define CMOS_RTC_DAY_MONTH       0x07
+#define CMOS_RTC_MONTH           0x08
+#define CMOS_RTC_YEAR            0x09
+#define CMOS_STATUS_A            0x0a
+#define CMOS_STATUS_B            0x0b
+#define CMOS_STATUS_C            0x0c
+#define CMOS_STATUS_D            0x0d
+#define CMOS_RESET_CODE          0x0f
+
+// QEMU cmos config fields.  DO NOT ADD MORE.  (All new content should
+// be passed via the fw_cfg "file" interface.)
+#define CMOS_FLOPPY_DRIVE_TYPE   0x10
+#define CMOS_DISK_DATA           0x12
+#define CMOS_EQUIPMENT_INFO      0x14
+#define CMOS_DISK_DRIVE1_TYPE    0x19
+#define CMOS_DISK_DRIVE2_TYPE    0x1a
+#define CMOS_DISK_DRIVE1_CYL     0x1b
+#define CMOS_DISK_DRIVE2_CYL     0x24
+#define CMOS_MEM_EXTMEM_LOW      0x30
+#define CMOS_MEM_EXTMEM_HIGH     0x31
+#define CMOS_CENTURY             0x32
+#define CMOS_MEM_EXTMEM2_LOW     0x34
+#define CMOS_MEM_EXTMEM2_HIGH    0x35
+#define CMOS_BIOS_BOOTFLAG1      0x38
+#define CMOS_BIOS_DISKTRANSFLAG  0x39
+#define CMOS_BIOS_BOOTFLAG2      0x3d
+#define CMOS_MEM_HIGHMEM_LOW     0x5b
+#define CMOS_MEM_HIGHMEM_MID     0x5c
+#define CMOS_MEM_HIGHMEM_HIGH    0x5d
+#define CMOS_BIOS_SMP_COUNT      0x5f
+
+// 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
+
+#ifndef __ASSEMBLY__
+
+#include "types.h" // u8
+
+// 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 // rtc.h
index 592176d01600bd0ea15ba3201a71fd364a13b0ea..acd2362423d765760d7879d80688efc673e3fdce 100644 (file)
 #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;
index af39a1d0103c246692647795ba9166a9fc69bffd..12daf0f422f02b961a6a0b250fd7c674f2657910 100644 (file)
@@ -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();
index 17904ae1d8be151de31ef0772114ea3564bd9c46..3307f7638d0a5d21594c66626bd619430a1fbe2f 100644 (file)
@@ -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_*
 
index cc597c6611460876f2caa068314380b1c2b97a59..d8aaca8b43ba39037fb91d03c7d4158ec498c9fa 100644 (file)
@@ -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();
 }
index 57c3ae979ff296acd2c7b08717644b5487077477..9c459253876b9adfaef8686dea230cfb8febb17e 100644 (file)
@@ -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;