mc146818rtc.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. /*
  2. * QEMU MC146818 RTC emulation
  3. *
  4. * Copyright (c) 2003-2004 Fabrice Bellard
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "hw.h"
  25. #include "qemu-timer.h"
  26. #include "sysemu.h"
  27. #include "pc.h"
  28. #include "isa.h"
  29. #include "hpet_emul.h"
  30. //#define DEBUG_CMOS
  31. #define RTC_SECONDS 0
  32. #define RTC_SECONDS_ALARM 1
  33. #define RTC_MINUTES 2
  34. #define RTC_MINUTES_ALARM 3
  35. #define RTC_HOURS 4
  36. #define RTC_HOURS_ALARM 5
  37. #define RTC_ALARM_DONT_CARE 0xC0
  38. #define RTC_DAY_OF_WEEK 6
  39. #define RTC_DAY_OF_MONTH 7
  40. #define RTC_MONTH 8
  41. #define RTC_YEAR 9
  42. #define RTC_REG_A 10
  43. #define RTC_REG_B 11
  44. #define RTC_REG_C 12
  45. #define RTC_REG_D 13
  46. #define REG_A_UIP 0x80
  47. #define REG_B_SET 0x80
  48. #define REG_B_PIE 0x40
  49. #define REG_B_AIE 0x20
  50. #define REG_B_UIE 0x10
  51. #define REG_B_DM 0x04
  52. struct RTCState {
  53. uint8_t cmos_data[128];
  54. uint8_t cmos_index;
  55. struct tm current_tm;
  56. int base_year;
  57. qemu_irq irq;
  58. int it_shift;
  59. /* periodic timer */
  60. QEMUTimer *periodic_timer;
  61. int64_t next_periodic_time;
  62. /* second update */
  63. int64_t next_second_time;
  64. #ifdef TARGET_I386
  65. uint32_t irq_coalesced;
  66. uint32_t period;
  67. #endif
  68. QEMUTimer *second_timer;
  69. QEMUTimer *second_timer2;
  70. };
  71. static void rtc_irq_raise(qemu_irq irq) {
  72. /* When HPET is operating in legacy mode, RTC interrupts are disabled
  73. * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
  74. * mode is established while interrupt is raised. We want it to
  75. * be lowered in any case
  76. */
  77. #if defined TARGET_I386 || defined TARGET_X86_64
  78. if (!hpet_in_legacy_mode())
  79. #endif
  80. qemu_irq_raise(irq);
  81. }
  82. static void rtc_set_time(RTCState *s);
  83. static void rtc_copy_date(RTCState *s);
  84. static void rtc_timer_update(RTCState *s, int64_t current_time)
  85. {
  86. int period_code, period;
  87. int64_t cur_clock, next_irq_clock;
  88. period_code = s->cmos_data[RTC_REG_A] & 0x0f;
  89. #if defined TARGET_I386 || defined TARGET_X86_64
  90. /* disable periodic timer if hpet is in legacy mode, since interrupts are
  91. * disabled anyway.
  92. */
  93. if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE) && !hpet_in_legacy_mode()) {
  94. #else
  95. if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
  96. #endif
  97. if (period_code <= 2)
  98. period_code += 7;
  99. /* period in 32 Khz cycles */
  100. period = 1 << (period_code - 1);
  101. #ifdef TARGET_I386
  102. if(period != s->period)
  103. s->irq_coalesced = (s->irq_coalesced * s->period) / period;
  104. s->period = period;
  105. #endif
  106. /* compute 32 khz clock */
  107. cur_clock = muldiv64(current_time, 32768, ticks_per_sec);
  108. next_irq_clock = (cur_clock & ~(period - 1)) + period;
  109. s->next_periodic_time = muldiv64(next_irq_clock, ticks_per_sec, 32768) + 1;
  110. qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
  111. } else {
  112. #ifdef TARGET_I386
  113. s->irq_coalesced = 0;
  114. #endif
  115. qemu_del_timer(s->periodic_timer);
  116. }
  117. }
  118. static void rtc_periodic_timer(void *opaque)
  119. {
  120. RTCState *s = opaque;
  121. rtc_timer_update(s, s->next_periodic_time);
  122. #ifdef TARGET_I386
  123. if ((s->cmos_data[RTC_REG_C] & 0xc0) && rtc_td_hack) {
  124. s->irq_coalesced++;
  125. return;
  126. }
  127. #endif
  128. s->cmos_data[RTC_REG_C] |= 0xc0;
  129. rtc_irq_raise(s->irq);
  130. }
  131. static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
  132. {
  133. RTCState *s = opaque;
  134. if ((addr & 1) == 0) {
  135. s->cmos_index = data & 0x7f;
  136. } else {
  137. #ifdef DEBUG_CMOS
  138. printf("cmos: write index=0x%02x val=0x%02x\n",
  139. s->cmos_index, data);
  140. #endif
  141. switch(s->cmos_index) {
  142. case RTC_SECONDS_ALARM:
  143. case RTC_MINUTES_ALARM:
  144. case RTC_HOURS_ALARM:
  145. /* XXX: not supported */
  146. s->cmos_data[s->cmos_index] = data;
  147. break;
  148. case RTC_SECONDS:
  149. case RTC_MINUTES:
  150. case RTC_HOURS:
  151. case RTC_DAY_OF_WEEK:
  152. case RTC_DAY_OF_MONTH:
  153. case RTC_MONTH:
  154. case RTC_YEAR:
  155. s->cmos_data[s->cmos_index] = data;
  156. /* if in set mode, do not update the time */
  157. if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
  158. rtc_set_time(s);
  159. }
  160. break;
  161. case RTC_REG_A:
  162. /* UIP bit is read only */
  163. s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
  164. (s->cmos_data[RTC_REG_A] & REG_A_UIP);
  165. rtc_timer_update(s, qemu_get_clock(vm_clock));
  166. break;
  167. case RTC_REG_B:
  168. if (data & REG_B_SET) {
  169. /* set mode: reset UIP mode */
  170. s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
  171. data &= ~REG_B_UIE;
  172. } else {
  173. /* if disabling set mode, update the time */
  174. if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
  175. rtc_set_time(s);
  176. }
  177. }
  178. s->cmos_data[RTC_REG_B] = data;
  179. rtc_timer_update(s, qemu_get_clock(vm_clock));
  180. break;
  181. case RTC_REG_C:
  182. case RTC_REG_D:
  183. /* cannot write to them */
  184. break;
  185. default:
  186. s->cmos_data[s->cmos_index] = data;
  187. break;
  188. }
  189. }
  190. }
  191. static inline int to_bcd(RTCState *s, int a)
  192. {
  193. if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
  194. return a;
  195. } else {
  196. return ((a / 10) << 4) | (a % 10);
  197. }
  198. }
  199. static inline int from_bcd(RTCState *s, int a)
  200. {
  201. if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
  202. return a;
  203. } else {
  204. return ((a >> 4) * 10) + (a & 0x0f);
  205. }
  206. }
  207. static void rtc_set_time(RTCState *s)
  208. {
  209. struct tm *tm = &s->current_tm;
  210. tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
  211. tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
  212. tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
  213. if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
  214. (s->cmos_data[RTC_HOURS] & 0x80)) {
  215. tm->tm_hour += 12;
  216. }
  217. tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1;
  218. tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
  219. tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
  220. tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900;
  221. }
  222. static void rtc_copy_date(RTCState *s)
  223. {
  224. const struct tm *tm = &s->current_tm;
  225. int year;
  226. s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
  227. s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
  228. if (s->cmos_data[RTC_REG_B] & 0x02) {
  229. /* 24 hour format */
  230. s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
  231. } else {
  232. /* 12 hour format */
  233. s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
  234. if (tm->tm_hour >= 12)
  235. s->cmos_data[RTC_HOURS] |= 0x80;
  236. }
  237. s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday + 1);
  238. s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
  239. s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
  240. year = (tm->tm_year - s->base_year) % 100;
  241. if (year < 0)
  242. year += 100;
  243. s->cmos_data[RTC_YEAR] = to_bcd(s, year);
  244. }
  245. /* month is between 0 and 11. */
  246. static int get_days_in_month(int month, int year)
  247. {
  248. static const int days_tab[12] = {
  249. 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  250. };
  251. int d;
  252. if ((unsigned )month >= 12)
  253. return 31;
  254. d = days_tab[month];
  255. if (month == 1) {
  256. if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
  257. d++;
  258. }
  259. return d;
  260. }
  261. /* update 'tm' to the next second */
  262. static void rtc_next_second(struct tm *tm)
  263. {
  264. int days_in_month;
  265. tm->tm_sec++;
  266. if ((unsigned)tm->tm_sec >= 60) {
  267. tm->tm_sec = 0;
  268. tm->tm_min++;
  269. if ((unsigned)tm->tm_min >= 60) {
  270. tm->tm_min = 0;
  271. tm->tm_hour++;
  272. if ((unsigned)tm->tm_hour >= 24) {
  273. tm->tm_hour = 0;
  274. /* next day */
  275. tm->tm_wday++;
  276. if ((unsigned)tm->tm_wday >= 7)
  277. tm->tm_wday = 0;
  278. days_in_month = get_days_in_month(tm->tm_mon,
  279. tm->tm_year + 1900);
  280. tm->tm_mday++;
  281. if (tm->tm_mday < 1) {
  282. tm->tm_mday = 1;
  283. } else if (tm->tm_mday > days_in_month) {
  284. tm->tm_mday = 1;
  285. tm->tm_mon++;
  286. if (tm->tm_mon >= 12) {
  287. tm->tm_mon = 0;
  288. tm->tm_year++;
  289. }
  290. }
  291. }
  292. }
  293. }
  294. }
  295. static void rtc_update_second(void *opaque)
  296. {
  297. RTCState *s = opaque;
  298. int64_t delay;
  299. /* if the oscillator is not in normal operation, we do not update */
  300. if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
  301. s->next_second_time += ticks_per_sec;
  302. qemu_mod_timer(s->second_timer, s->next_second_time);
  303. } else {
  304. rtc_next_second(&s->current_tm);
  305. if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
  306. /* update in progress bit */
  307. s->cmos_data[RTC_REG_A] |= REG_A_UIP;
  308. }
  309. /* should be 244 us = 8 / 32768 seconds, but currently the
  310. timers do not have the necessary resolution. */
  311. delay = (ticks_per_sec * 1) / 100;
  312. if (delay < 1)
  313. delay = 1;
  314. qemu_mod_timer(s->second_timer2,
  315. s->next_second_time + delay);
  316. }
  317. }
  318. static void rtc_update_second2(void *opaque)
  319. {
  320. RTCState *s = opaque;
  321. if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
  322. rtc_copy_date(s);
  323. }
  324. /* check alarm */
  325. if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
  326. if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
  327. s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
  328. ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
  329. s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
  330. ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
  331. s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
  332. s->cmos_data[RTC_REG_C] |= 0xa0;
  333. rtc_irq_raise(s->irq);
  334. }
  335. }
  336. /* update ended interrupt */
  337. if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
  338. s->cmos_data[RTC_REG_C] |= 0x90;
  339. rtc_irq_raise(s->irq);
  340. }
  341. /* clear update in progress bit */
  342. s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
  343. s->next_second_time += ticks_per_sec;
  344. qemu_mod_timer(s->second_timer, s->next_second_time);
  345. }
  346. static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
  347. {
  348. RTCState *s = opaque;
  349. int ret;
  350. if ((addr & 1) == 0) {
  351. return 0xff;
  352. } else {
  353. switch(s->cmos_index) {
  354. case RTC_SECONDS:
  355. case RTC_MINUTES:
  356. case RTC_HOURS:
  357. case RTC_DAY_OF_WEEK:
  358. case RTC_DAY_OF_MONTH:
  359. case RTC_MONTH:
  360. case RTC_YEAR:
  361. ret = s->cmos_data[s->cmos_index];
  362. break;
  363. case RTC_REG_A:
  364. ret = s->cmos_data[s->cmos_index];
  365. break;
  366. case RTC_REG_C:
  367. ret = s->cmos_data[s->cmos_index];
  368. qemu_irq_lower(s->irq);
  369. #ifdef TARGET_I386
  370. if(s->irq_coalesced) {
  371. apic_reset_irq_delivered();
  372. qemu_irq_raise(s->irq);
  373. if (apic_get_irq_delivered())
  374. s->irq_coalesced--;
  375. break;
  376. }
  377. #endif
  378. s->cmos_data[RTC_REG_C] = 0x00;
  379. break;
  380. default:
  381. ret = s->cmos_data[s->cmos_index];
  382. break;
  383. }
  384. #ifdef DEBUG_CMOS
  385. printf("cmos: read index=0x%02x val=0x%02x\n",
  386. s->cmos_index, ret);
  387. #endif
  388. return ret;
  389. }
  390. }
  391. void rtc_set_memory(RTCState *s, int addr, int val)
  392. {
  393. if (addr >= 0 && addr <= 127)
  394. s->cmos_data[addr] = val;
  395. }
  396. void rtc_set_date(RTCState *s, const struct tm *tm)
  397. {
  398. s->current_tm = *tm;
  399. rtc_copy_date(s);
  400. }
  401. /* PC cmos mappings */
  402. #define REG_IBM_CENTURY_BYTE 0x32
  403. #define REG_IBM_PS2_CENTURY_BYTE 0x37
  404. static void rtc_set_date_from_host(RTCState *s)
  405. {
  406. struct tm tm;
  407. int val;
  408. /* set the CMOS date */
  409. qemu_get_timedate(&tm, 0);
  410. rtc_set_date(s, &tm);
  411. val = to_bcd(s, (tm.tm_year / 100) + 19);
  412. rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
  413. rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
  414. }
  415. static void rtc_save(QEMUFile *f, void *opaque)
  416. {
  417. RTCState *s = opaque;
  418. qemu_put_buffer(f, s->cmos_data, 128);
  419. qemu_put_8s(f, &s->cmos_index);
  420. qemu_put_be32(f, s->current_tm.tm_sec);
  421. qemu_put_be32(f, s->current_tm.tm_min);
  422. qemu_put_be32(f, s->current_tm.tm_hour);
  423. qemu_put_be32(f, s->current_tm.tm_wday);
  424. qemu_put_be32(f, s->current_tm.tm_mday);
  425. qemu_put_be32(f, s->current_tm.tm_mon);
  426. qemu_put_be32(f, s->current_tm.tm_year);
  427. qemu_put_timer(f, s->periodic_timer);
  428. qemu_put_be64(f, s->next_periodic_time);
  429. qemu_put_be64(f, s->next_second_time);
  430. qemu_put_timer(f, s->second_timer);
  431. qemu_put_timer(f, s->second_timer2);
  432. }
  433. static int rtc_load(QEMUFile *f, void *opaque, int version_id)
  434. {
  435. RTCState *s = opaque;
  436. if (version_id != 1)
  437. return -EINVAL;
  438. qemu_get_buffer(f, s->cmos_data, 128);
  439. qemu_get_8s(f, &s->cmos_index);
  440. s->current_tm.tm_sec=qemu_get_be32(f);
  441. s->current_tm.tm_min=qemu_get_be32(f);
  442. s->current_tm.tm_hour=qemu_get_be32(f);
  443. s->current_tm.tm_wday=qemu_get_be32(f);
  444. s->current_tm.tm_mday=qemu_get_be32(f);
  445. s->current_tm.tm_mon=qemu_get_be32(f);
  446. s->current_tm.tm_year=qemu_get_be32(f);
  447. qemu_get_timer(f, s->periodic_timer);
  448. s->next_periodic_time=qemu_get_be64(f);
  449. s->next_second_time=qemu_get_be64(f);
  450. qemu_get_timer(f, s->second_timer);
  451. qemu_get_timer(f, s->second_timer2);
  452. return 0;
  453. }
  454. #ifdef TARGET_I386
  455. static void rtc_save_td(QEMUFile *f, void *opaque)
  456. {
  457. RTCState *s = opaque;
  458. qemu_put_be32(f, s->irq_coalesced);
  459. qemu_put_be32(f, s->period);
  460. }
  461. static int rtc_load_td(QEMUFile *f, void *opaque, int version_id)
  462. {
  463. RTCState *s = opaque;
  464. if (version_id != 1)
  465. return -EINVAL;
  466. s->irq_coalesced = qemu_get_be32(f);
  467. s->period = qemu_get_be32(f);
  468. return 0;
  469. }
  470. #endif
  471. RTCState *rtc_init(int base, qemu_irq irq, int base_year)
  472. {
  473. RTCState *s;
  474. s = qemu_mallocz(sizeof(RTCState));
  475. s->irq = irq;
  476. s->cmos_data[RTC_REG_A] = 0x26;
  477. s->cmos_data[RTC_REG_B] = 0x02;
  478. s->cmos_data[RTC_REG_C] = 0x00;
  479. s->cmos_data[RTC_REG_D] = 0x80;
  480. s->base_year = base_year;
  481. rtc_set_date_from_host(s);
  482. s->periodic_timer = qemu_new_timer(vm_clock,
  483. rtc_periodic_timer, s);
  484. s->second_timer = qemu_new_timer(vm_clock,
  485. rtc_update_second, s);
  486. s->second_timer2 = qemu_new_timer(vm_clock,
  487. rtc_update_second2, s);
  488. s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
  489. qemu_mod_timer(s->second_timer2, s->next_second_time);
  490. register_ioport_write(base, 2, 1, cmos_ioport_write, s);
  491. register_ioport_read(base, 2, 1, cmos_ioport_read, s);
  492. register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
  493. #ifdef TARGET_I386
  494. if (rtc_td_hack)
  495. register_savevm("mc146818rtc-td", base, 1, rtc_save_td, rtc_load_td, s);
  496. #endif
  497. return s;
  498. }
  499. /* Memory mapped interface */
  500. static uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr)
  501. {
  502. RTCState *s = opaque;
  503. return cmos_ioport_read(s, addr >> s->it_shift) & 0xFF;
  504. }
  505. static void cmos_mm_writeb (void *opaque,
  506. target_phys_addr_t addr, uint32_t value)
  507. {
  508. RTCState *s = opaque;
  509. cmos_ioport_write(s, addr >> s->it_shift, value & 0xFF);
  510. }
  511. static uint32_t cmos_mm_readw (void *opaque, target_phys_addr_t addr)
  512. {
  513. RTCState *s = opaque;
  514. uint32_t val;
  515. val = cmos_ioport_read(s, addr >> s->it_shift) & 0xFFFF;
  516. #ifdef TARGET_WORDS_BIGENDIAN
  517. val = bswap16(val);
  518. #endif
  519. return val;
  520. }
  521. static void cmos_mm_writew (void *opaque,
  522. target_phys_addr_t addr, uint32_t value)
  523. {
  524. RTCState *s = opaque;
  525. #ifdef TARGET_WORDS_BIGENDIAN
  526. value = bswap16(value);
  527. #endif
  528. cmos_ioport_write(s, addr >> s->it_shift, value & 0xFFFF);
  529. }
  530. static uint32_t cmos_mm_readl (void *opaque, target_phys_addr_t addr)
  531. {
  532. RTCState *s = opaque;
  533. uint32_t val;
  534. val = cmos_ioport_read(s, addr >> s->it_shift);
  535. #ifdef TARGET_WORDS_BIGENDIAN
  536. val = bswap32(val);
  537. #endif
  538. return val;
  539. }
  540. static void cmos_mm_writel (void *opaque,
  541. target_phys_addr_t addr, uint32_t value)
  542. {
  543. RTCState *s = opaque;
  544. #ifdef TARGET_WORDS_BIGENDIAN
  545. value = bswap32(value);
  546. #endif
  547. cmos_ioport_write(s, addr >> s->it_shift, value);
  548. }
  549. static CPUReadMemoryFunc *rtc_mm_read[] = {
  550. &cmos_mm_readb,
  551. &cmos_mm_readw,
  552. &cmos_mm_readl,
  553. };
  554. static CPUWriteMemoryFunc *rtc_mm_write[] = {
  555. &cmos_mm_writeb,
  556. &cmos_mm_writew,
  557. &cmos_mm_writel,
  558. };
  559. RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
  560. int base_year)
  561. {
  562. RTCState *s;
  563. int io_memory;
  564. s = qemu_mallocz(sizeof(RTCState));
  565. s->irq = irq;
  566. s->cmos_data[RTC_REG_A] = 0x26;
  567. s->cmos_data[RTC_REG_B] = 0x02;
  568. s->cmos_data[RTC_REG_C] = 0x00;
  569. s->cmos_data[RTC_REG_D] = 0x80;
  570. s->base_year = base_year;
  571. rtc_set_date_from_host(s);
  572. s->periodic_timer = qemu_new_timer(vm_clock,
  573. rtc_periodic_timer, s);
  574. s->second_timer = qemu_new_timer(vm_clock,
  575. rtc_update_second, s);
  576. s->second_timer2 = qemu_new_timer(vm_clock,
  577. rtc_update_second2, s);
  578. s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
  579. qemu_mod_timer(s->second_timer2, s->next_second_time);
  580. io_memory = cpu_register_io_memory(0, rtc_mm_read, rtc_mm_write, s);
  581. cpu_register_physical_memory(base, 2 << it_shift, io_memory);
  582. register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
  583. #ifdef TARGET_I386
  584. if (rtc_td_hack)
  585. register_savevm("mc146818rtc-td", base, 1, rtc_save_td, rtc_load_td, s);
  586. #endif
  587. return s;
  588. }