1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24: #include "hw.h"
25: #include "pc.h"
26: #include "isa.h"
27: #include "qemu-timer.h"
28:
29:
30:
31: #define RW_STATE_LSB 1
32: #define RW_STATE_MSB 2
33: #define RW_STATE_WORD0 3
34: #define RW_STATE_WORD1 4
35:
36: typedef struct PITChannelState {
37: int count;
38: uint16_t latched_count;
39: uint8_t count_latched;
40: uint8_t status_latched;
41: uint8_t status;
42: uint8_t read_state;
43: uint8_t write_state;
44: uint8_t write_latch;
45: uint8_t rw_mode;
46: uint8_t mode;
47: uint8_t bcd;
48: uint8_t gate;
49: int64_t count_load_time;
50:
51: int64_t next_transition_time;
52: QEMUTimer *irq_timer;
53: qemu_irq irq;
54: } PITChannelState;
55:
56: struct PITState {
57: PITChannelState channels[3];
58: };
59:
60: static PITState pit_state;
61:
62: static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
63:
64: static int pit_get_count(PITChannelState *s)
65: {
66: uint64_t d;
67: int counter;
68:
69: d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, PIT_FREQ, ticks_per_sec);
70: switch(s->mode) {
71: case 0:
72: case 1:
73: case 4:
74: case 5:
75: counter = (s->count - d) & 0xffff;
76: break;
77: case 3:
78:
79: counter = s->count - ((2 * d) % s->count);
80: break;
81: default:
82: counter = s->count - (d % s->count);
83: break;
84: }
85: return counter;
86: }
87:
88:
89: static int pit_get_out1(PITChannelState *s, int64_t current_time)
90: {
91: uint64_t d;
92: int out;
93:
94: d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
95: switch(s->mode) {
96: default:
97: case 0:
98: out = (d >= s->count);
99: break;
100: case 1:
101: out = (d < s->count);
102: break;
103: case 2:
104: if ((d % s->count) == 0 && d != 0)
105: out = 1;
106: else
107: out = 0;
108: break;
109: case 3:
110: out = (d % s->count) < ((s->count + 1) >> 1);
111: break;
112: case 4:
113: case 5:
114: out = (d == s->count);
115: break;
116: }
117: return out;
118: }
119:
120: int pit_get_out(PITState *pit, int channel, int64_t current_time)
121: {
122: PITChannelState *s = &pit->channels[channel];
123: return pit_get_out1(s, current_time);
124: }
125:
126:
127: static int64_t pit_get_next_transition_time(PITChannelState *s,
128: int64_t current_time)
129: {
130: uint64_t d, next_time, base;
131: int period2;
132:
133: d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
134: switch(s->mode) {
135: default:
136: case 0:
137: case 1:
138: if (d < s->count)
139: next_time = s->count;
140: else
141: return -1;
142: break;
143: case 2:
144: base = (d / s->count) * s->count;
145: if ((d - base) == 0 && d != 0)
146: next_time = base + s->count;
147: else
148: next_time = base + s->count + 1;
149: break;
150: case 3:
151: base = (d / s->count) * s->count;
152: period2 = ((s->count + 1) >> 1);
153: if ((d - base) < period2)
154: next_time = base + period2;
155: else
156: next_time = base + s->count;
157: break;
158: case 4:
159: case 5:
160: if (d < s->count)
161: next_time = s->count;
162: else if (d == s->count)
163: next_time = s->count + 1;
164: else
165: return -1;
166: break;
167: }
168:
169: next_time = s->count_load_time + muldiv64(next_time, ticks_per_sec, PIT_FREQ);
170:
171:
172: if (next_time <= current_time)
173: next_time = current_time + 1;
174: return next_time;
175: }
176:
177:
178: void pit_set_gate(PITState *pit, int channel, int val)
179: {
180: PITChannelState *s = &pit->channels[channel];
181:
182: switch(s->mode) {
183: default:
184: case 0:
185: case 4:
186:
187: break;
188: case 1:
189: case 5:
190: if (s->gate < val) {
191:
192: s->count_load_time = qemu_get_clock(vm_clock);
193: pit_irq_timer_update(s, s->count_load_time);
194: }
195: break;
196: case 2:
197: case 3:
198: if (s->gate < val) {
199:
200: s->count_load_time = qemu_get_clock(vm_clock);
201: pit_irq_timer_update(s, s->count_load_time);
202: }
203:
204: break;
205: }
206: s->gate = val;
207: }
208:
209: int pit_get_gate(PITState *pit, int channel)
210: {
211: PITChannelState *s = &pit->channels[channel];
212: return s->gate;
213: }
214:
215: int pit_get_initial_count(PITState *pit, int channel)
216: {
217: PITChannelState *s = &pit->channels[channel];
218: return s->count;
219: }
220:
221: int pit_get_mode(PITState *pit, int channel)
222: {
223: PITChannelState *s = &pit->channels[channel];
224: return s->mode;
225: }
226:
227: static inline void pit_load_count(PITChannelState *s, int val)
228: {
229: if (val == 0)
230: val = 0x10000;
231: s->count_load_time = qemu_get_clock(vm_clock);
232: s->count = val;
233: pit_irq_timer_update(s, s->count_load_time);
234: }
235:
236:
237: static void pit_latch_count(PITChannelState *s)
238: {
239: if (!s->count_latched) {
240: s->latched_count = pit_get_count(s);
241: s->count_latched = s->rw_mode;
242: }
243: }
244:
245: static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
246: {
247: PITState *pit = opaque;
248: int channel, access;
249: PITChannelState *s;
250:
251: addr &= 3;
252: if (addr == 3) {
253: channel = val >> 6;
254: if (channel == 3) {
255:
256: for(channel = 0; channel < 3; channel++) {
257: s = &pit->channels[channel];
258: if (val & (2 << channel)) {
259: if (!(val & 0x20)) {
260: pit_latch_count(s);
261: }
262: if (!(val & 0x10) && !s->status_latched) {
263:
264:
265: s->status = (pit_get_out1(s, qemu_get_clock(vm_clock)) << 7) |
266: (s->rw_mode << 4) |
267: (s->mode << 1) |
268: s->bcd;
269: s->status_latched = 1;
270: }
271: }
272: }
273: } else {
274: s = &pit->channels[channel];
275: access = (val >> 4) & 3;
276: if (access == 0) {
277: pit_latch_count(s);
278: } else {
279: s->rw_mode = access;
280: s->read_state = access;
281: s->write_state = access;
282:
283: s->mode = (val >> 1) & 7;
284: s->bcd = val & 1;
285:
286: }
287: }
288: } else {
289: s = &pit->channels[addr];
290: switch(s->write_state) {
291: default:
292: case RW_STATE_LSB:
293: pit_load_count(s, val);
294: break;
295: case RW_STATE_MSB:
296: pit_load_count(s, val << 8);
297: break;
298: case RW_STATE_WORD0:
299: s->write_latch = val;
300: s->write_state = RW_STATE_WORD1;
301: break;
302: case RW_STATE_WORD1:
303: pit_load_count(s, s->write_latch | (val << 8));
304: s->write_state = RW_STATE_WORD0;
305: break;
306: }
307: }
308: }
309:
310: static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
311: {
312: PITState *pit = opaque;
313: int ret, count;
314: PITChannelState *s;
315:
316: addr &= 3;
317: s = &pit->channels[addr];
318: if (s->status_latched) {
319: s->status_latched = 0;
320: ret = s->status;
321: } else if (s->count_latched) {
322: switch(s->count_latched) {
323: default:
324: case RW_STATE_LSB:
325: ret = s->latched_count & 0xff;
326: s->count_latched = 0;
327: break;
328: case RW_STATE_MSB:
329: ret = s->latched_count >> 8;
330: s->count_latched = 0;
331: break;
332: case RW_STATE_WORD0:
333: ret = s->latched_count & 0xff;
334: s->count_latched = RW_STATE_MSB;
335: break;
336: }
337: } else {
338: switch(s->read_state) {
339: default:
340: case RW_STATE_LSB:
341: count = pit_get_count(s);
342: ret = count & 0xff;
343: break;
344: case RW_STATE_MSB:
345: count = pit_get_count(s);
346: ret = (count >> 8) & 0xff;
347: break;
348: case RW_STATE_WORD0:
349: count = pit_get_count(s);
350: ret = count & 0xff;
351: s->read_state = RW_STATE_WORD1;
352: break;
353: case RW_STATE_WORD1:
354: count = pit_get_count(s);
355: ret = (count >> 8) & 0xff;
356: s->read_state = RW_STATE_WORD0;
357: break;
358: }
359: }
360: return ret;
361: }
362:
363: static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
364: {
365: int64_t expire_time;
366: int irq_level;
367:
368: if (!s->irq_timer)
369: return;
370: expire_time = pit_get_next_transition_time(s, current_time);
371: irq_level = pit_get_out1(s, current_time);
372: qemu_set_irq(s->irq, irq_level);
373: #ifdef DEBUG_PIT
374: printf("irq_level=%d next_delay=%f\n",
375: irq_level,
376: (double)(expire_time - current_time) / ticks_per_sec);
377: #endif
378: s->next_transition_time = expire_time;
379: if (expire_time != -1)
380: qemu_mod_timer(s->irq_timer, expire_time);
381: else
382: qemu_del_timer(s->irq_timer);
383: }
384:
385: static void pit_irq_timer(void *opaque)
386: {
387: PITChannelState *s = opaque;
388:
389: pit_irq_timer_update(s, s->next_transition_time);
390: }
391:
392: static void pit_save(QEMUFile *f, void *opaque)
393: {
394: PITState *pit = opaque;
395: PITChannelState *s;
396: int i;
397:
398: for(i = 0; i < 3; i++) {
399: s = &pit->channels[i];
400: qemu_put_be32(f, s->count);
401: qemu_put_be16s(f, &s->latched_count);
402: qemu_put_8s(f, &s->count_latched);
403: qemu_put_8s(f, &s->status_latched);
404: qemu_put_8s(f, &s->status);
405: qemu_put_8s(f, &s->read_state);
406: qemu_put_8s(f, &s->write_state);
407: qemu_put_8s(f, &s->write_latch);
408: qemu_put_8s(f, &s->rw_mode);
409: qemu_put_8s(f, &s->mode);
410: qemu_put_8s(f, &s->bcd);
411: qemu_put_8s(f, &s->gate);
412: qemu_put_be64(f, s->count_load_time);
413: if (s->irq_timer) {
414: qemu_put_be64(f, s->next_transition_time);
415: qemu_put_timer(f, s->irq_timer);
416: }
417: }
418: }
419:
420: static int pit_load(QEMUFile *f, void *opaque, int version_id)
421: {
422: PITState *pit = opaque;
423: PITChannelState *s;
424: int i;
425:
426: if (version_id != 1)
427: return -EINVAL;
428:
429: for(i = 0; i < 3; i++) {
430: s = &pit->channels[i];
431: s->count=qemu_get_be32(f);
432: qemu_get_be16s(f, &s->latched_count);
433: qemu_get_8s(f, &s->count_latched);
434: qemu_get_8s(f, &s->status_latched);
435: qemu_get_8s(f, &s->status);
436: qemu_get_8s(f, &s->read_state);
437: qemu_get_8s(f, &s->write_state);
438: qemu_get_8s(f, &s->write_latch);
439: qemu_get_8s(f, &s->rw_mode);
440: qemu_get_8s(f, &s->mode);
441: qemu_get_8s(f, &s->bcd);
442: qemu_get_8s(f, &s->gate);
443: s->count_load_time=qemu_get_be64(f);
444: if (s->irq_timer) {
445: s->next_transition_time=qemu_get_be64(f);
446: qemu_get_timer(f, s->irq_timer);
447: }
448: }
449: return 0;
450: }
451:
452: static void pit_reset(void *opaque)
453: {
454: PITState *pit = opaque;
455: PITChannelState *s;
456: int i;
457:
458: for(i = 0;i < 3; i++) {
459: s = &pit->channels[i];
460: s->mode = 3;
461: s->gate = (i != 2);
462: pit_load_count(s, 0);
463: }
464: }
465:
466: PITState *pit_init(int base, qemu_irq irq)
467: {
468: PITState *pit = &pit_state;
469: PITChannelState *s;
470:
471: s = &pit->channels[0];
472:
473: s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
474: s->irq = irq;
475:
476: register_savevm("i8254", base, 1, pit_save, pit_load, pit);
477:
478: qemu_register_reset(pit_reset, pit);
479: register_ioport_write(base, 4, 1, pit_ioport_write, pit);
480: register_ioport_read(base, 3, 1, pit_ioport_read, pit);
481:
482: pit_reset(pit);
483:
484: return pit;
485: }