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>
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 \
#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
// 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;
#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
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;
#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)
{
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
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);
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);
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);
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);
//
// 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
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);
}
//
// 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);
* 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)
{
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;
}
return;
// Turn off status byte.
SET_BDA(rtc_wait_flag, 0);
- releaseRTC();
+ rtc_release();
}
#define RET_ECLOCKINUSE 0x83
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;
#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
}
// 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);
// 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
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();
#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
+++ /dev/null
-// 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
#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
#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
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)
--- /dev/null
+// 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);
+}
--- /dev/null
+#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
#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
// 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;
#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
{
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();
#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_*
#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
return;
CanPreempt = 1;
PreemptCount = 0;
- useRTC();
+ rtc_use();
}
// Turn off RTC irqs / stop checking for thread execution.
return;
}
CanPreempt = 0;
- releaseRTC();
+ rtc_release();
dprintf(9, "Done preempt - %d checks\n", PreemptCount);
yield();
}
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;