⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i8254.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
        default:        case RW_STATE_LSB:            pit_load_count(pit, addr, val);            break;        case RW_STATE_MSB:            pit_load_count(pit, addr, val << 8);            break;        case RW_STATE_WORD0:            s->write_latch = val;            s->write_state = RW_STATE_WORD1;            break;        case RW_STATE_WORD1:            pit_load_count(pit, addr, s->write_latch | (val << 8));            s->write_state = RW_STATE_WORD0;            break;        }    }    spin_unlock(&pit->lock);}static uint32_t pit_ioport_read(struct PITState *pit, uint32_t addr){    int ret, count;    struct hvm_hw_pit_channel *s;        addr &= 3;    s = &pit->hw.channels[addr];    spin_lock(&pit->lock);    if ( s->status_latched )    {        s->status_latched = 0;        ret = s->status;    }    else if ( s->count_latched )    {        switch ( s->count_latched )        {        default:        case RW_STATE_LSB:            ret = s->latched_count & 0xff;            s->count_latched = 0;            break;        case RW_STATE_MSB:            ret = s->latched_count >> 8;            s->count_latched = 0;            break;        case RW_STATE_WORD0:            ret = s->latched_count & 0xff;            s->count_latched = RW_STATE_MSB;            break;        }    }    else    {        switch ( s->read_state )        {        default:        case RW_STATE_LSB:            count = pit_get_count(pit, addr);            ret = count & 0xff;            break;        case RW_STATE_MSB:            count = pit_get_count(pit, addr);            ret = (count >> 8) & 0xff;            break;        case RW_STATE_WORD0:            count = pit_get_count(pit, addr);            ret = count & 0xff;            s->read_state = RW_STATE_WORD1;            break;        case RW_STATE_WORD1:            count = pit_get_count(pit, addr);            ret = (count >> 8) & 0xff;            s->read_state = RW_STATE_WORD0;            break;        }    }    spin_unlock(&pit->lock);    return ret;}void pit_stop_channel0_irq(PITState *pit){    spin_lock(&pit->lock);    destroy_periodic_time(&pit->pt0);    spin_unlock(&pit->lock);}#ifdef HVM_DEBUG_SUSPENDstatic void pit_info(PITState *pit){    struct hvm_hw_pit_channel *s;    struct periodic_time *pt;    int i;    for ( i = 0; i < 3; i++ )    {        printk("*****pit channel %d's state:*****\n", i);        s = &pit->hw.channels[i];        printk("pit 0x%x.\n", s->count);        printk("pit 0x%x.\n", s->latched_count);        printk("pit 0x%x.\n", s->count_latched);        printk("pit 0x%x.\n", s->status_latched);        printk("pit 0x%x.\n", s->status);        printk("pit 0x%x.\n", s->read_state);        printk("pit 0x%x.\n", s->write_state);        printk("pit 0x%x.\n", s->write_latch);        printk("pit 0x%x.\n", s->rw_mode);        printk("pit 0x%x.\n", s->mode);        printk("pit 0x%x.\n", s->bcd);        printk("pit 0x%x.\n", s->gate);        printk("pit %"PRId64"\n", pit->count_load_time[i]);    }    pt = &pit->pt0;    printk("pit channel 0 periodic timer:\n", i);    printk("pt %d.\n", pt->enabled);    printk("pt %d.\n", pt->one_shot);    printk("pt %d.\n", pt->irq);    printk("pt %d.\n", pt->first_injected);    printk("pt %d.\n", pt->pending_intr_nr);    printk("pt %d.\n", pt->period);    printk("pt %"PRId64"\n", pt->period_cycles);    printk("pt %"PRId64"\n", pt->last_plt_gtime);}#elsestatic void pit_info(PITState *pit){}#endifstatic int pit_save(struct domain *d, hvm_domain_context_t *h){    PITState *pit = domain_vpit(d);    int rc;    spin_lock(&pit->lock);        pit_info(pit);    /* Save the PIT hardware state */    rc = hvm_save_entry(PIT, 0, h, &pit->hw);    spin_unlock(&pit->lock);    return rc;}static int pit_load(struct domain *d, hvm_domain_context_t *h){    PITState *pit = domain_vpit(d);    int i;    spin_lock(&pit->lock);    /* Restore the PIT hardware state */    if ( hvm_load_entry(PIT, h, &pit->hw) )    {        spin_unlock(&pit->lock);        return 1;    }        /* Recreate platform timers from hardware state.  There will be some      * time jitter here, but the wall-clock will have jumped massively, so      * we hope the guest can handle it. */    pit->pt0.last_plt_gtime = hvm_get_guest_time(d->vcpu[0]);    for ( i = 0; i < 3; i++ )        pit_load_count(pit, i, pit->hw.channels[i].count);    pit_info(pit);    spin_unlock(&pit->lock);    return 0;}HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load, 1, HVMSR_PER_DOM);void pit_init(struct vcpu *v, unsigned long cpu_khz){    PITState *pit = vcpu_vpit(v);    struct hvm_hw_pit_channel *s;    int i;    spin_lock_init(&pit->lock);    /* Some sub-functions assert that they are called with the lock held. */    spin_lock(&pit->lock);    pit->pt0.source = PTSRC_isa;    register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io);    register_portio_handler(v->domain, 0x61, 1, handle_speaker_io);    ticks_per_sec(v) = cpu_khz * (int64_t)1000;    for ( i = 0; i < 3; i++ )    {        s = &pit->hw.channels[i];        s->mode = 0xff; /* the init mode */        s->gate = (i != 2);        pit_load_count(pit, i, 0);    }    spin_unlock(&pit->lock);}void pit_deinit(struct domain *d){    PITState *pit = domain_vpit(d);    destroy_periodic_time(&pit->pt0);}/* the intercept action for PIT DM retval:0--not handled; 1--handled */  static int handle_pit_io(    int dir, uint32_t port, uint32_t bytes, uint32_t *val){    struct PITState *vpit = vcpu_vpit(current);    if ( bytes != 1 )    {        gdprintk(XENLOG_WARNING, "PIT bad access\n");        return 1;    }    if ( dir == IOREQ_WRITE )    {        pit_ioport_write(vpit, port, *val);    }    else    {        if ( (port & 3) != 3 )            *val = pit_ioport_read(vpit, port);        else            gdprintk(XENLOG_WARNING, "PIT: read A1:A0=3!\n");    }    return 1;}static void speaker_ioport_write(    struct PITState *pit, uint32_t addr, uint32_t val){    pit->hw.speaker_data_on = (val >> 1) & 1;    pit_set_gate(pit, 2, val & 1);}static uint32_t speaker_ioport_read(    struct PITState *pit, uint32_t addr){    /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */    unsigned int refresh_clock = ((unsigned int)NOW() >> 14) & 1;    return ((pit->hw.speaker_data_on << 1) | pit_get_gate(pit, 2) |            (pit_get_out(pit, 2) << 5) | (refresh_clock << 4));}static int handle_speaker_io(    int dir, uint32_t port, uint32_t bytes, uint32_t *val){    struct PITState *vpit = vcpu_vpit(current);    if ( bytes != 1 )    {        gdprintk(XENLOG_WARNING, "PIT_SPEAKER bad access\n");        return 1;    }    spin_lock(&vpit->lock);    if ( dir == IOREQ_WRITE )        speaker_ioport_write(vpit, port, *val);    else        *val = speaker_ioport_read(vpit, port);    spin_unlock(&vpit->lock);    return 1;}int pv_pit_handler(int port, int data, int write){    ioreq_t ioreq = {        .size = 1,        .type = IOREQ_TYPE_PIO,        .addr = port,        .dir  = write ? IOREQ_WRITE : IOREQ_READ,        .data = data    };    if ( (current->domain->domain_id == 0) && dom0_pit_access(&ioreq) )    {        /* nothing to do */;    }    else    {        uint32_t val = data;        if ( port == 0x61 )            handle_speaker_io(ioreq.dir, port, 1, &val);        else            handle_pit_io(ioreq.dir, port, 1, &val);        ioreq.data = val;    }    return !write ? ioreq.data : 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -