]> Git Repo - qemu.git/blob - hw/mc146818rtc.c
virtio-9p: Add P9_TREAD support
[qemu.git] / hw / mc146818rtc.c
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 "apic.h"
29 #include "isa.h"
30 #include "hpet_emul.h"
31
32 //#define DEBUG_CMOS
33
34 #define RTC_REINJECT_ON_ACK_COUNT 20
35
36 #define RTC_SECONDS             0
37 #define RTC_SECONDS_ALARM       1
38 #define RTC_MINUTES             2
39 #define RTC_MINUTES_ALARM       3
40 #define RTC_HOURS               4
41 #define RTC_HOURS_ALARM         5
42 #define RTC_ALARM_DONT_CARE    0xC0
43
44 #define RTC_DAY_OF_WEEK         6
45 #define RTC_DAY_OF_MONTH        7
46 #define RTC_MONTH               8
47 #define RTC_YEAR                9
48
49 #define RTC_REG_A               10
50 #define RTC_REG_B               11
51 #define RTC_REG_C               12
52 #define RTC_REG_D               13
53
54 #define REG_A_UIP 0x80
55
56 #define REG_B_SET  0x80
57 #define REG_B_PIE  0x40
58 #define REG_B_AIE  0x20
59 #define REG_B_UIE  0x10
60 #define REG_B_SQWE 0x08
61 #define REG_B_DM   0x04
62
63 #define REG_C_UF   0x10
64 #define REG_C_IRQF 0x80
65 #define REG_C_PF   0x40
66 #define REG_C_AF   0x20
67
68 struct RTCState {
69     ISADevice dev;
70     uint8_t cmos_data[128];
71     uint8_t cmos_index;
72     struct tm current_tm;
73     int32_t base_year;
74     qemu_irq irq;
75     qemu_irq sqw_irq;
76     int it_shift;
77     /* periodic timer */
78     QEMUTimer *periodic_timer;
79     int64_t next_periodic_time;
80     /* second update */
81     int64_t next_second_time;
82     uint16_t irq_reinject_on_ack_count;
83     uint32_t irq_coalesced;
84     uint32_t period;
85     QEMUTimer *coalesced_timer;
86     QEMUTimer *second_timer;
87     QEMUTimer *second_timer2;
88 };
89
90 static void rtc_irq_raise(qemu_irq irq)
91 {
92     /* When HPET is operating in legacy mode, RTC interrupts are disabled
93      * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
94      * mode is established while interrupt is raised. We want it to
95      * be lowered in any case
96      */
97 #if defined TARGET_I386
98     if (!hpet_in_legacy_mode())
99 #endif
100         qemu_irq_raise(irq);
101 }
102
103 static void rtc_set_time(RTCState *s);
104 static void rtc_copy_date(RTCState *s);
105
106 #ifdef TARGET_I386
107 static void rtc_coalesced_timer_update(RTCState *s)
108 {
109     if (s->irq_coalesced == 0) {
110         qemu_del_timer(s->coalesced_timer);
111     } else {
112         /* divide each RTC interval to 2 - 8 smaller intervals */
113         int c = MIN(s->irq_coalesced, 7) + 1; 
114         int64_t next_clock = qemu_get_clock(rtc_clock) +
115             muldiv64(s->period / c, get_ticks_per_sec(), 32768);
116         qemu_mod_timer(s->coalesced_timer, next_clock);
117     }
118 }
119
120 static void rtc_coalesced_timer(void *opaque)
121 {
122     RTCState *s = opaque;
123
124     if (s->irq_coalesced != 0) {
125         apic_reset_irq_delivered();
126         s->cmos_data[RTC_REG_C] |= 0xc0;
127         rtc_irq_raise(s->irq);
128         if (apic_get_irq_delivered()) {
129             s->irq_coalesced--;
130         }
131     }
132
133     rtc_coalesced_timer_update(s);
134 }
135 #endif
136
137 static void rtc_timer_update(RTCState *s, int64_t current_time)
138 {
139     int period_code, period;
140     int64_t cur_clock, next_irq_clock;
141     int enable_pie;
142
143     period_code = s->cmos_data[RTC_REG_A] & 0x0f;
144 #if defined TARGET_I386
145     /* disable periodic timer if hpet is in legacy mode, since interrupts are
146      * disabled anyway.
147      */
148     enable_pie = !hpet_in_legacy_mode();
149 #else
150     enable_pie = 1;
151 #endif
152     if (period_code != 0
153         && (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie)
154             || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
155         if (period_code <= 2)
156             period_code += 7;
157         /* period in 32 Khz cycles */
158         period = 1 << (period_code - 1);
159 #ifdef TARGET_I386
160         if(period != s->period)
161             s->irq_coalesced = (s->irq_coalesced * s->period) / period;
162         s->period = period;
163 #endif
164         /* compute 32 khz clock */
165         cur_clock = muldiv64(current_time, 32768, get_ticks_per_sec());
166         next_irq_clock = (cur_clock & ~(period - 1)) + period;
167         s->next_periodic_time =
168             muldiv64(next_irq_clock, get_ticks_per_sec(), 32768) + 1;
169         qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
170     } else {
171 #ifdef TARGET_I386
172         s->irq_coalesced = 0;
173 #endif
174         qemu_del_timer(s->periodic_timer);
175     }
176 }
177
178 static void rtc_periodic_timer(void *opaque)
179 {
180     RTCState *s = opaque;
181
182     rtc_timer_update(s, s->next_periodic_time);
183     if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
184         s->cmos_data[RTC_REG_C] |= 0xc0;
185 #ifdef TARGET_I386
186         if(rtc_td_hack) {
187             if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
188                 s->irq_reinject_on_ack_count = 0;               
189             apic_reset_irq_delivered();
190             rtc_irq_raise(s->irq);
191             if (!apic_get_irq_delivered()) {
192                 s->irq_coalesced++;
193                 rtc_coalesced_timer_update(s);
194             }
195         } else
196 #endif
197         rtc_irq_raise(s->irq);
198     }
199     if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
200         /* Not square wave at all but we don't want 2048Hz interrupts!
201            Must be seen as a pulse.  */
202         qemu_irq_raise(s->sqw_irq);
203     }
204 }
205
206 static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
207 {
208     RTCState *s = opaque;
209
210     if ((addr & 1) == 0) {
211         s->cmos_index = data & 0x7f;
212     } else {
213 #ifdef DEBUG_CMOS
214         printf("cmos: write index=0x%02x val=0x%02x\n",
215                s->cmos_index, data);
216 #endif
217         switch(s->cmos_index) {
218         case RTC_SECONDS_ALARM:
219         case RTC_MINUTES_ALARM:
220         case RTC_HOURS_ALARM:
221             /* XXX: not supported */
222             s->cmos_data[s->cmos_index] = data;
223             break;
224         case RTC_SECONDS:
225         case RTC_MINUTES:
226         case RTC_HOURS:
227         case RTC_DAY_OF_WEEK:
228         case RTC_DAY_OF_MONTH:
229         case RTC_MONTH:
230         case RTC_YEAR:
231             s->cmos_data[s->cmos_index] = data;
232             /* if in set mode, do not update the time */
233             if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
234                 rtc_set_time(s);
235             }
236             break;
237         case RTC_REG_A:
238             /* UIP bit is read only */
239             s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
240                 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
241             rtc_timer_update(s, qemu_get_clock(rtc_clock));
242             break;
243         case RTC_REG_B:
244             if (data & REG_B_SET) {
245                 /* set mode: reset UIP mode */
246                 s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
247                 data &= ~REG_B_UIE;
248             } else {
249                 /* if disabling set mode, update the time */
250                 if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
251                     rtc_set_time(s);
252                 }
253             }
254             s->cmos_data[RTC_REG_B] = data;
255             rtc_timer_update(s, qemu_get_clock(rtc_clock));
256             break;
257         case RTC_REG_C:
258         case RTC_REG_D:
259             /* cannot write to them */
260             break;
261         default:
262             s->cmos_data[s->cmos_index] = data;
263             break;
264         }
265     }
266 }
267
268 static inline int rtc_to_bcd(RTCState *s, int a)
269 {
270     if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
271         return a;
272     } else {
273         return ((a / 10) << 4) | (a % 10);
274     }
275 }
276
277 static inline int rtc_from_bcd(RTCState *s, int a)
278 {
279     if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
280         return a;
281     } else {
282         return ((a >> 4) * 10) + (a & 0x0f);
283     }
284 }
285
286 static void rtc_set_time(RTCState *s)
287 {
288     struct tm *tm = &s->current_tm;
289
290     tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
291     tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
292     tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
293     if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
294         (s->cmos_data[RTC_HOURS] & 0x80)) {
295         tm->tm_hour += 12;
296     }
297     tm->tm_wday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1;
298     tm->tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
299     tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
300     tm->tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900;
301
302     rtc_change_mon_event(tm);
303 }
304
305 static void rtc_copy_date(RTCState *s)
306 {
307     const struct tm *tm = &s->current_tm;
308     int year;
309
310     s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec);
311     s->cmos_data[RTC_MINUTES] = rtc_to_bcd(s, tm->tm_min);
312     if (s->cmos_data[RTC_REG_B] & 0x02) {
313         /* 24 hour format */
314         s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour);
315     } else {
316         /* 12 hour format */
317         s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour % 12);
318         if (tm->tm_hour >= 12)
319             s->cmos_data[RTC_HOURS] |= 0x80;
320     }
321     s->cmos_data[RTC_DAY_OF_WEEK] = rtc_to_bcd(s, tm->tm_wday + 1);
322     s->cmos_data[RTC_DAY_OF_MONTH] = rtc_to_bcd(s, tm->tm_mday);
323     s->cmos_data[RTC_MONTH] = rtc_to_bcd(s, tm->tm_mon + 1);
324     year = (tm->tm_year - s->base_year) % 100;
325     if (year < 0)
326         year += 100;
327     s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year);
328 }
329
330 /* month is between 0 and 11. */
331 static int get_days_in_month(int month, int year)
332 {
333     static const int days_tab[12] = {
334         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
335     };
336     int d;
337     if ((unsigned )month >= 12)
338         return 31;
339     d = days_tab[month];
340     if (month == 1) {
341         if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
342             d++;
343     }
344     return d;
345 }
346
347 /* update 'tm' to the next second */
348 static void rtc_next_second(struct tm *tm)
349 {
350     int days_in_month;
351
352     tm->tm_sec++;
353     if ((unsigned)tm->tm_sec >= 60) {
354         tm->tm_sec = 0;
355         tm->tm_min++;
356         if ((unsigned)tm->tm_min >= 60) {
357             tm->tm_min = 0;
358             tm->tm_hour++;
359             if ((unsigned)tm->tm_hour >= 24) {
360                 tm->tm_hour = 0;
361                 /* next day */
362                 tm->tm_wday++;
363                 if ((unsigned)tm->tm_wday >= 7)
364                     tm->tm_wday = 0;
365                 days_in_month = get_days_in_month(tm->tm_mon,
366                                                   tm->tm_year + 1900);
367                 tm->tm_mday++;
368                 if (tm->tm_mday < 1) {
369                     tm->tm_mday = 1;
370                 } else if (tm->tm_mday > days_in_month) {
371                     tm->tm_mday = 1;
372                     tm->tm_mon++;
373                     if (tm->tm_mon >= 12) {
374                         tm->tm_mon = 0;
375                         tm->tm_year++;
376                     }
377                 }
378             }
379         }
380     }
381 }
382
383
384 static void rtc_update_second(void *opaque)
385 {
386     RTCState *s = opaque;
387     int64_t delay;
388
389     /* if the oscillator is not in normal operation, we do not update */
390     if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
391         s->next_second_time += get_ticks_per_sec();
392         qemu_mod_timer(s->second_timer, s->next_second_time);
393     } else {
394         rtc_next_second(&s->current_tm);
395
396         if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
397             /* update in progress bit */
398             s->cmos_data[RTC_REG_A] |= REG_A_UIP;
399         }
400         /* should be 244 us = 8 / 32768 seconds, but currently the
401            timers do not have the necessary resolution. */
402         delay = (get_ticks_per_sec() * 1) / 100;
403         if (delay < 1)
404             delay = 1;
405         qemu_mod_timer(s->second_timer2,
406                        s->next_second_time + delay);
407     }
408 }
409
410 static void rtc_update_second2(void *opaque)
411 {
412     RTCState *s = opaque;
413
414     if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
415         rtc_copy_date(s);
416     }
417
418     /* check alarm */
419     if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
420         if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
421              s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
422             ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
423              s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
424             ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
425              s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
426
427             s->cmos_data[RTC_REG_C] |= 0xa0;
428             rtc_irq_raise(s->irq);
429         }
430     }
431
432     /* update ended interrupt */
433     s->cmos_data[RTC_REG_C] |= REG_C_UF;
434     if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
435       s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
436       rtc_irq_raise(s->irq);
437     }
438
439     /* clear update in progress bit */
440     s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
441
442     s->next_second_time += get_ticks_per_sec();
443     qemu_mod_timer(s->second_timer, s->next_second_time);
444 }
445
446 static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
447 {
448     RTCState *s = opaque;
449     int ret;
450     if ((addr & 1) == 0) {
451         return 0xff;
452     } else {
453         switch(s->cmos_index) {
454         case RTC_SECONDS:
455         case RTC_MINUTES:
456         case RTC_HOURS:
457         case RTC_DAY_OF_WEEK:
458         case RTC_DAY_OF_MONTH:
459         case RTC_MONTH:
460         case RTC_YEAR:
461             ret = s->cmos_data[s->cmos_index];
462             break;
463         case RTC_REG_A:
464             ret = s->cmos_data[s->cmos_index];
465             break;
466         case RTC_REG_C:
467             ret = s->cmos_data[s->cmos_index];
468             qemu_irq_lower(s->irq);
469 #ifdef TARGET_I386
470             if(s->irq_coalesced &&
471                     s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
472                 s->irq_reinject_on_ack_count++;
473                 apic_reset_irq_delivered();
474                 qemu_irq_raise(s->irq);
475                 if (apic_get_irq_delivered())
476                     s->irq_coalesced--;
477                 break;
478             }
479 #endif
480
481             s->cmos_data[RTC_REG_C] = 0x00;
482             break;
483         default:
484             ret = s->cmos_data[s->cmos_index];
485             break;
486         }
487 #ifdef DEBUG_CMOS
488         printf("cmos: read index=0x%02x val=0x%02x\n",
489                s->cmos_index, ret);
490 #endif
491         return ret;
492     }
493 }
494
495 void rtc_set_memory(RTCState *s, int addr, int val)
496 {
497     if (addr >= 0 && addr <= 127)
498         s->cmos_data[addr] = val;
499 }
500
501 void rtc_set_date(RTCState *s, const struct tm *tm)
502 {
503     s->current_tm = *tm;
504     rtc_copy_date(s);
505 }
506
507 /* PC cmos mappings */
508 #define REG_IBM_CENTURY_BYTE        0x32
509 #define REG_IBM_PS2_CENTURY_BYTE    0x37
510
511 static void rtc_set_date_from_host(RTCState *s)
512 {
513     struct tm tm;
514     int val;
515
516     /* set the CMOS date */
517     qemu_get_timedate(&tm, 0);
518     rtc_set_date(s, &tm);
519
520     val = rtc_to_bcd(s, (tm.tm_year / 100) + 19);
521     rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
522     rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
523 }
524
525 static int rtc_post_load(void *opaque, int version_id)
526 {
527 #ifdef TARGET_I386
528     RTCState *s = opaque;
529
530     if (version_id >= 2) {
531         if (rtc_td_hack) {
532             rtc_coalesced_timer_update(s);
533         }
534     }
535 #endif
536     return 0;
537 }
538
539 static const VMStateDescription vmstate_rtc = {
540     .name = "mc146818rtc",
541     .version_id = 2,
542     .minimum_version_id = 1,
543     .minimum_version_id_old = 1,
544     .post_load = rtc_post_load,
545     .fields      = (VMStateField []) {
546         VMSTATE_BUFFER(cmos_data, RTCState),
547         VMSTATE_UINT8(cmos_index, RTCState),
548         VMSTATE_INT32(current_tm.tm_sec, RTCState),
549         VMSTATE_INT32(current_tm.tm_min, RTCState),
550         VMSTATE_INT32(current_tm.tm_hour, RTCState),
551         VMSTATE_INT32(current_tm.tm_wday, RTCState),
552         VMSTATE_INT32(current_tm.tm_mday, RTCState),
553         VMSTATE_INT32(current_tm.tm_mon, RTCState),
554         VMSTATE_INT32(current_tm.tm_year, RTCState),
555         VMSTATE_TIMER(periodic_timer, RTCState),
556         VMSTATE_INT64(next_periodic_time, RTCState),
557         VMSTATE_INT64(next_second_time, RTCState),
558         VMSTATE_TIMER(second_timer, RTCState),
559         VMSTATE_TIMER(second_timer2, RTCState),
560         VMSTATE_UINT32_V(irq_coalesced, RTCState, 2),
561         VMSTATE_UINT32_V(period, RTCState, 2),
562         VMSTATE_END_OF_LIST()
563     }
564 };
565
566 static void rtc_reset(void *opaque)
567 {
568     RTCState *s = opaque;
569
570     s->cmos_data[RTC_REG_B] &= ~(REG_B_PIE | REG_B_AIE | REG_B_SQWE);
571     s->cmos_data[RTC_REG_C] &= ~(REG_C_UF | REG_C_IRQF | REG_C_PF | REG_C_AF);
572
573     qemu_irq_lower(s->irq);
574
575 #ifdef TARGET_I386
576     if (rtc_td_hack)
577             s->irq_coalesced = 0;
578 #endif
579 }
580
581 static int rtc_initfn(ISADevice *dev)
582 {
583     RTCState *s = DO_UPCAST(RTCState, dev, dev);
584     int base = 0x70;
585     int isairq = 8;
586
587     isa_init_irq(dev, &s->irq, isairq);
588
589     s->cmos_data[RTC_REG_A] = 0x26;
590     s->cmos_data[RTC_REG_B] = 0x02;
591     s->cmos_data[RTC_REG_C] = 0x00;
592     s->cmos_data[RTC_REG_D] = 0x80;
593
594     rtc_set_date_from_host(s);
595
596     s->periodic_timer = qemu_new_timer(rtc_clock, rtc_periodic_timer, s);
597 #ifdef TARGET_I386
598     if (rtc_td_hack)
599         s->coalesced_timer =
600             qemu_new_timer(rtc_clock, rtc_coalesced_timer, s);
601 #endif
602     s->second_timer = qemu_new_timer(rtc_clock, rtc_update_second, s);
603     s->second_timer2 = qemu_new_timer(rtc_clock, rtc_update_second2, s);
604
605     s->next_second_time =
606         qemu_get_clock(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
607     qemu_mod_timer(s->second_timer2, s->next_second_time);
608
609     register_ioport_write(base, 2, 1, cmos_ioport_write, s);
610     register_ioport_read(base, 2, 1, cmos_ioport_read, s);
611
612     vmstate_register(base, &vmstate_rtc, s);
613     qemu_register_reset(rtc_reset, s);
614     return 0;
615 }
616
617 RTCState *rtc_init(int base_year)
618 {
619     ISADevice *dev;
620
621     dev = isa_create("mc146818rtc");
622     qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
623     qdev_init_nofail(&dev->qdev);
624     return DO_UPCAST(RTCState, dev, dev);
625 }
626
627 static ISADeviceInfo mc146818rtc_info = {
628     .qdev.name     = "mc146818rtc",
629     .qdev.size     = sizeof(RTCState),
630     .qdev.no_user  = 1,
631     .init          = rtc_initfn,
632     .qdev.props    = (Property[]) {
633         DEFINE_PROP_INT32("base_year", RTCState, base_year, 1980),
634         DEFINE_PROP_END_OF_LIST(),
635     }
636 };
637
638 static void mc146818rtc_register(void)
639 {
640     isa_qdev_register(&mc146818rtc_info);
641 }
642 device_init(mc146818rtc_register)
This page took 0.060425 seconds and 4 git commands to generate.