Annotation of qemu/hw/i8254_common.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * QEMU 8253/8254 - common bits of emulated and KVM kernel model
        !             3:  *
        !             4:  * Copyright (c) 2003-2004 Fabrice Bellard
        !             5:  * Copyright (c) 2012      Jan Kiszka, Siemens AG
        !             6:  *
        !             7:  * Permission is hereby granted, free of charge, to any person obtaining a copy
        !             8:  * of this software and associated documentation files (the "Software"), to deal
        !             9:  * in the Software without restriction, including without limitation the rights
        !            10:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !            11:  * copies of the Software, and to permit persons to whom the Software is
        !            12:  * furnished to do so, subject to the following conditions:
        !            13:  *
        !            14:  * The above copyright notice and this permission notice shall be included in
        !            15:  * all copies or substantial portions of the Software.
        !            16:  *
        !            17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            18:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
        !            20:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        !            21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        !            22:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        !            23:  * THE SOFTWARE.
        !            24:  */
        !            25: #include "hw.h"
        !            26: #include "pc.h"
        !            27: #include "isa.h"
        !            28: #include "qemu-timer.h"
        !            29: #include "i8254.h"
        !            30: #include "i8254_internal.h"
        !            31: 
        !            32: /* val must be 0 or 1 */
        !            33: void pit_set_gate(ISADevice *dev, int channel, int val)
        !            34: {
        !            35:     PITCommonState *pit = PIT_COMMON(dev);
        !            36:     PITChannelState *s = &pit->channels[channel];
        !            37:     PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
        !            38: 
        !            39:     c->set_channel_gate(pit, s, val);
        !            40: }
        !            41: 
        !            42: /* get pit output bit */
        !            43: int pit_get_out(PITChannelState *s, int64_t current_time)
        !            44: {
        !            45:     uint64_t d;
        !            46:     int out;
        !            47: 
        !            48:     d = muldiv64(current_time - s->count_load_time, PIT_FREQ,
        !            49:                  get_ticks_per_sec());
        !            50:     switch (s->mode) {
        !            51:     default:
        !            52:     case 0:
        !            53:         out = (d >= s->count);
        !            54:         break;
        !            55:     case 1:
        !            56:         out = (d < s->count);
        !            57:         break;
        !            58:     case 2:
        !            59:         if ((d % s->count) == 0 && d != 0) {
        !            60:             out = 1;
        !            61:         } else {
        !            62:             out = 0;
        !            63:         }
        !            64:         break;
        !            65:     case 3:
        !            66:         out = (d % s->count) < ((s->count + 1) >> 1);
        !            67:         break;
        !            68:     case 4:
        !            69:     case 5:
        !            70:         out = (d == s->count);
        !            71:         break;
        !            72:     }
        !            73:     return out;
        !            74: }
        !            75: 
        !            76: /* return -1 if no transition will occur.  */
        !            77: int64_t pit_get_next_transition_time(PITChannelState *s, int64_t current_time)
        !            78: {
        !            79:     uint64_t d, next_time, base;
        !            80:     int period2;
        !            81: 
        !            82:     d = muldiv64(current_time - s->count_load_time, PIT_FREQ,
        !            83:                  get_ticks_per_sec());
        !            84:     switch (s->mode) {
        !            85:     default:
        !            86:     case 0:
        !            87:     case 1:
        !            88:         if (d < s->count) {
        !            89:             next_time = s->count;
        !            90:         } else {
        !            91:             return -1;
        !            92:         }
        !            93:         break;
        !            94:     case 2:
        !            95:         base = (d / s->count) * s->count;
        !            96:         if ((d - base) == 0 && d != 0) {
        !            97:             next_time = base + s->count;
        !            98:         } else {
        !            99:             next_time = base + s->count + 1;
        !           100:         }
        !           101:         break;
        !           102:     case 3:
        !           103:         base = (d / s->count) * s->count;
        !           104:         period2 = ((s->count + 1) >> 1);
        !           105:         if ((d - base) < period2) {
        !           106:             next_time = base + period2;
        !           107:         } else {
        !           108:             next_time = base + s->count;
        !           109:         }
        !           110:         break;
        !           111:     case 4:
        !           112:     case 5:
        !           113:         if (d < s->count) {
        !           114:             next_time = s->count;
        !           115:         } else if (d == s->count) {
        !           116:             next_time = s->count + 1;
        !           117:         } else {
        !           118:             return -1;
        !           119:         }
        !           120:         break;
        !           121:     }
        !           122:     /* convert to timer units */
        !           123:     next_time = s->count_load_time + muldiv64(next_time, get_ticks_per_sec(),
        !           124:                                               PIT_FREQ);
        !           125:     /* fix potential rounding problems */
        !           126:     /* XXX: better solution: use a clock at PIT_FREQ Hz */
        !           127:     if (next_time <= current_time) {
        !           128:         next_time = current_time + 1;
        !           129:     }
        !           130:     return next_time;
        !           131: }
        !           132: 
        !           133: void pit_get_channel_info_common(PITCommonState *s, PITChannelState *sc,
        !           134:                                  PITChannelInfo *info)
        !           135: {
        !           136:     info->gate = sc->gate;
        !           137:     info->mode = sc->mode;
        !           138:     info->initial_count = sc->count;
        !           139:     info->out = pit_get_out(sc, qemu_get_clock_ns(vm_clock));
        !           140: }
        !           141: 
        !           142: void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info)
        !           143: {
        !           144:     PITCommonState *pit = PIT_COMMON(dev);
        !           145:     PITChannelState *s = &pit->channels[channel];
        !           146:     PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
        !           147: 
        !           148:     c->get_channel_info(pit, s, info);
        !           149: }
        !           150: 
        !           151: void pit_reset_common(PITCommonState *pit)
        !           152: {
        !           153:     PITChannelState *s;
        !           154:     int i;
        !           155: 
        !           156:     for (i = 0; i < 3; i++) {
        !           157:         s = &pit->channels[i];
        !           158:         s->mode = 3;
        !           159:         s->gate = (i != 2);
        !           160:         s->count_load_time = qemu_get_clock_ns(vm_clock);
        !           161:         s->count = 0x10000;
        !           162:         if (i == 0 && !s->irq_disabled) {
        !           163:             s->next_transition_time =
        !           164:                 pit_get_next_transition_time(s, s->count_load_time);
        !           165:         }
        !           166:     }
        !           167: }
        !           168: 
        !           169: static int pit_init_common(ISADevice *dev)
        !           170: {
        !           171:     PITCommonState *pit = PIT_COMMON(dev);
        !           172:     PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
        !           173:     int ret;
        !           174: 
        !           175:     ret = c->init(pit);
        !           176:     if (ret < 0) {
        !           177:         return ret;
        !           178:     }
        !           179: 
        !           180:     isa_register_ioport(dev, &pit->ioports, pit->iobase);
        !           181: 
        !           182:     qdev_set_legacy_instance_id(&dev->qdev, pit->iobase, 2);
        !           183: 
        !           184:     return 0;
        !           185: }
        !           186: 
        !           187: static const VMStateDescription vmstate_pit_channel = {
        !           188:     .name = "pit channel",
        !           189:     .version_id = 2,
        !           190:     .minimum_version_id = 2,
        !           191:     .minimum_version_id_old = 2,
        !           192:     .fields = (VMStateField[]) {
        !           193:         VMSTATE_INT32(count, PITChannelState),
        !           194:         VMSTATE_UINT16(latched_count, PITChannelState),
        !           195:         VMSTATE_UINT8(count_latched, PITChannelState),
        !           196:         VMSTATE_UINT8(status_latched, PITChannelState),
        !           197:         VMSTATE_UINT8(status, PITChannelState),
        !           198:         VMSTATE_UINT8(read_state, PITChannelState),
        !           199:         VMSTATE_UINT8(write_state, PITChannelState),
        !           200:         VMSTATE_UINT8(write_latch, PITChannelState),
        !           201:         VMSTATE_UINT8(rw_mode, PITChannelState),
        !           202:         VMSTATE_UINT8(mode, PITChannelState),
        !           203:         VMSTATE_UINT8(bcd, PITChannelState),
        !           204:         VMSTATE_UINT8(gate, PITChannelState),
        !           205:         VMSTATE_INT64(count_load_time, PITChannelState),
        !           206:         VMSTATE_INT64(next_transition_time, PITChannelState),
        !           207:         VMSTATE_END_OF_LIST()
        !           208:     }
        !           209: };
        !           210: 
        !           211: static int pit_load_old(QEMUFile *f, void *opaque, int version_id)
        !           212: {
        !           213:     PITCommonState *pit = opaque;
        !           214:     PITCommonClass *c = PIT_COMMON_GET_CLASS(pit);
        !           215:     PITChannelState *s;
        !           216:     int i;
        !           217: 
        !           218:     if (version_id != 1) {
        !           219:         return -EINVAL;
        !           220:     }
        !           221: 
        !           222:     for (i = 0; i < 3; i++) {
        !           223:         s = &pit->channels[i];
        !           224:         s->count = qemu_get_be32(f);
        !           225:         qemu_get_be16s(f, &s->latched_count);
        !           226:         qemu_get_8s(f, &s->count_latched);
        !           227:         qemu_get_8s(f, &s->status_latched);
        !           228:         qemu_get_8s(f, &s->status);
        !           229:         qemu_get_8s(f, &s->read_state);
        !           230:         qemu_get_8s(f, &s->write_state);
        !           231:         qemu_get_8s(f, &s->write_latch);
        !           232:         qemu_get_8s(f, &s->rw_mode);
        !           233:         qemu_get_8s(f, &s->mode);
        !           234:         qemu_get_8s(f, &s->bcd);
        !           235:         qemu_get_8s(f, &s->gate);
        !           236:         s->count_load_time = qemu_get_be64(f);
        !           237:         s->irq_disabled = 0;
        !           238:         if (i == 0) {
        !           239:             s->next_transition_time = qemu_get_be64(f);
        !           240:         }
        !           241:     }
        !           242:     if (c->post_load) {
        !           243:         c->post_load(pit);
        !           244:     }
        !           245:     return 0;
        !           246: }
        !           247: 
        !           248: static void pit_dispatch_pre_save(void *opaque)
        !           249: {
        !           250:     PITCommonState *s = opaque;
        !           251:     PITCommonClass *c = PIT_COMMON_GET_CLASS(s);
        !           252: 
        !           253:     if (c->pre_save) {
        !           254:         c->pre_save(s);
        !           255:     }
        !           256: }
        !           257: 
        !           258: static int pit_dispatch_post_load(void *opaque, int version_id)
        !           259: {
        !           260:     PITCommonState *s = opaque;
        !           261:     PITCommonClass *c = PIT_COMMON_GET_CLASS(s);
        !           262: 
        !           263:     if (c->post_load) {
        !           264:         c->post_load(s);
        !           265:     }
        !           266:     return 0;
        !           267: }
        !           268: 
        !           269: static const VMStateDescription vmstate_pit_common = {
        !           270:     .name = "i8254",
        !           271:     .version_id = 3,
        !           272:     .minimum_version_id = 2,
        !           273:     .minimum_version_id_old = 1,
        !           274:     .load_state_old = pit_load_old,
        !           275:     .pre_save = pit_dispatch_pre_save,
        !           276:     .post_load = pit_dispatch_post_load,
        !           277:     .fields = (VMStateField[]) {
        !           278:         VMSTATE_UINT32_V(channels[0].irq_disabled, PITCommonState, 3),
        !           279:         VMSTATE_STRUCT_ARRAY(channels, PITCommonState, 3, 2,
        !           280:                              vmstate_pit_channel, PITChannelState),
        !           281:         VMSTATE_INT64(channels[0].next_transition_time,
        !           282:                       PITCommonState), /* formerly irq_timer */
        !           283:         VMSTATE_END_OF_LIST()
        !           284:     }
        !           285: };
        !           286: 
        !           287: static void pit_common_class_init(ObjectClass *klass, void *data)
        !           288: {
        !           289:     ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
        !           290:     DeviceClass *dc = DEVICE_CLASS(klass);
        !           291: 
        !           292:     ic->init = pit_init_common;
        !           293:     dc->vmsd = &vmstate_pit_common;
        !           294:     dc->no_user = 1;
        !           295: }
        !           296: 
        !           297: static TypeInfo pit_common_type = {
        !           298:     .name          = TYPE_PIT_COMMON,
        !           299:     .parent        = TYPE_ISA_DEVICE,
        !           300:     .instance_size = sizeof(PITCommonState),
        !           301:     .class_size    = sizeof(PITCommonClass),
        !           302:     .class_init    = pit_common_class_init,
        !           303:     .abstract      = true,
        !           304: };
        !           305: 
        !           306: static void register_devices(void)
        !           307: {
        !           308:     type_register_static(&pit_common_type);
        !           309: }
        !           310: 
        !           311: type_init(register_devices);

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.