1 ///////////////////////////////////////////////////////////////////////// 2 // $Id: hpet.h 14112 2021-01-31 10:50:53Z vruppert $ 3 ///////////////////////////////////////////////////////////////////////// 4 // 5 // High Precision Event Timer emulation ported from Qemu 6 // 7 // Copyright (c) 2007 Alexander Graf 8 // Copyright (c) 2008 IBM Corporation 9 // 10 // Authors: Beth Kon <bkon@us.ibm.com> 11 // 12 // Copyright (C) 2017-2021 The Bochs Project 13 // 14 // This library is free software; you can redistribute it and/or 15 // modify it under the terms of the GNU Lesser General Public 16 // License as published by the Free Software Foundation; either 17 // version 2 of the License, or (at your option) any later version. 18 // 19 // This library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 // Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public 25 // License along with this library; if not, write to the Free Software 26 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 27 // 28 ///////////////////////////////////////////////////////////////////////// 29 30 #ifndef BX_IODEV_HPET_H 31 #define BX_IODEV_HPET_H 32 33 #if BX_SUPPORT_PCI 34 35 /* HPET will set up timers to fire after a certain period of time. 36 * These values can be used to clamp this period to reasonable/supported values. 37 * The values are in ticks. 38 */ 39 #define HPET_MAX_ALLOWED_PERIOD 0x0400000000000000ull // Must not overflow when multiplied by HPET_CLK_PERIOD 40 #define HPET_MIN_ALLOWED_PERIOD 1 41 42 #define RTC_ISA_IRQ 8 43 44 #define HPET_BASE 0xfed00000 45 #define HPET_LEN 0x400 46 #define HPET_CLK_PERIOD 10 // 10 ns 47 #define HPET_ROUTING_CAP 0xffffffull // allowed irq routing 48 49 #define FS_PER_NS 1000000 /* 1000000 femtosectons == 1 ns */ 50 #define HPET_MIN_TIMERS 3 51 #define HPET_MAX_TIMERS 32 52 53 #define HPET_CFG_ENABLE 0x001 54 #define HPET_CFG_LEGACY 0x002 55 56 #define HPET_ID 0x000 57 #define HPET_PERIOD 0x004 58 #define HPET_CFG 0x010 59 #define HPET_STATUS 0x020 60 #define HPET_COUNTER 0x0f0 61 #define HPET_TN_CFG 0x000 62 #define HPET_TN_CMP 0x008 63 #define HPET_TN_ROUTE 0x010 64 #define HPET_CFG_WRITE_MASK 0x3 65 66 #define HPET_TN_TYPE_LEVEL 0x002 67 #define HPET_TN_ENABLE 0x004 68 #define HPET_TN_PERIODIC 0x008 69 #define HPET_TN_PERIODIC_CAP 0x010 70 #define HPET_TN_SIZE_CAP 0x020 71 #define HPET_TN_SETVAL 0x040 72 #define HPET_TN_32BIT 0x100 73 #define HPET_TN_INT_ROUTE_MASK 0x3e00 74 #define HPET_TN_FSB_ENABLE 0x4000 75 #define HPET_TN_CFG_WRITE_MASK 0x7f4e 76 #define HPET_TN_INT_ROUTE_SHIFT 9 77 78 typedef struct { 79 Bit8u tn; 80 int timer_id; 81 Bit64u config; 82 Bit64u cmp; 83 Bit64u fsb; 84 Bit64u period; 85 Bit64u last_checked; 86 } HPETTimer; 87 88 class bx_hpet_c : public bx_devmodel_c { 89 public: 90 bx_hpet_c(); 91 virtual ~bx_hpet_c(); 92 virtual void init(); 93 virtual void reset(unsigned type); 94 virtual void register_state(void); 95 #if BX_DEBUGGER 96 virtual void debug_dump(int argc, char **argv); 97 #endif 98 99 Bit32u read_aligned(bx_phy_address address); 100 void write_aligned(bx_phy_address address, Bit32u data); 101 102 private: hpet_in_legacy_mode(void)103 Bit32u hpet_in_legacy_mode(void) {return s.config & HPET_CFG_LEGACY;} timer_int_route(HPETTimer * timer)104 Bit32u timer_int_route(HPETTimer *timer) 105 { 106 return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT; 107 } timer_fsb_route(HPETTimer * t)108 Bit32u timer_fsb_route(HPETTimer *t) {return t->config & HPET_TN_FSB_ENABLE;} hpet_enabled(void)109 Bit32u hpet_enabled(void) {return s.config & HPET_CFG_ENABLE;} timer_is_periodic(HPETTimer * t)110 Bit32u timer_is_periodic(HPETTimer *t) {return t->config & HPET_TN_PERIODIC;} timer_enabled(HPETTimer * t)111 Bit32u timer_enabled(HPETTimer *t) {return t->config & HPET_TN_ENABLE;} 112 Bit64u hpet_get_ticks(void); 113 Bit64u hpet_calculate_diff(HPETTimer *t, Bit64u current); 114 void update_irq(HPETTimer *timer, bool set); 115 void hpet_set_timer(HPETTimer *t); 116 void hpet_del_timer(HPETTimer *t); 117 118 static void timer_handler(void *); 119 void hpet_timer(void); 120 121 struct { 122 Bit8u num_timers; 123 Bit64u hpet_reference_value; 124 Bit64u hpet_reference_time; 125 Bit64u capability; 126 Bit64u config; 127 Bit64u isr; 128 Bit64u hpet_counter; 129 HPETTimer timer[HPET_MAX_TIMERS]; 130 } s; 131 }; 132 133 #endif 134 135 #endif 136