static void goldfish_timer_write(void *opaque, target_phys_addr_t offset, uint32_t value_ns)
{
    struct timer_state *s = (struct timer_state *)opaque;
    int64_t alarm_tks, now_tks;
    switch(offset) {
        case TIMER_ALARM_LOW:
            s->alarm_low_ns = value_ns;
            alarm_tks = ns2tks(s->alarm_low_ns | (int64_t)s->alarm_high_ns << 32);
            now_tks   = qemu_get_clock(vm_clock);
            if (alarm_tks <= now_tks) {
                goldfish_device_set_irq(&s->dev, 0, 1);
            } else {
                qemu_mod_timer(s->timer, alarm_tks);
                s->armed = 1;
            }
            break;
        case TIMER_ALARM_HIGH:
            s->alarm_high_ns = value_ns;
            break;
        case TIMER_CLEAR_ALARM:
            qemu_del_timer(s->timer);
            s->armed = 0;
            /* fall through */
        case TIMER_CLEAR_INTERRUPT:
            goldfish_device_set_irq(&s->dev, 0, 0);
            break;
        default:
            cpu_abort (cpu_single_env, "goldfish_timer_write: Bad offset %x\n", offset);
    }
}
static void goldfish_timer_write(void *opaque, target_phys_addr_t offset, uint32_t value)
{
    struct timer_state *s = (struct timer_state *)opaque;
    int64_t alarm, now;
    switch(offset) {
        case TIMER_ALARM_LOW:
            s->alarm_low = value;
            alarm = muldiv64(s->alarm_low | (int64_t)s->alarm_high << 32, ticks_per_sec, 1000000000);
            now   = qemu_get_clock(vm_clock);
            if (alarm <= now) {
                goldfish_device_set_irq(&s->dev, 0, 1);
            } else {
                qemu_mod_timer(s->timer, alarm);
                s->armed = 1;
            }
            break;
        case TIMER_ALARM_HIGH:
            s->alarm_high = value;
            //printf("alarm_high %d\n", s->alarm_high);
            break;
        case TIMER_CLEAR_ALARM:
            qemu_del_timer(s->timer);
            s->armed = 0;
            /* fall through */
        case TIMER_CLEAR_INTERRUPT:
            goldfish_device_set_irq(&s->dev, 0, 0);
            break;
        default:
            cpu_abort (cpu_single_env, "goldfish_timer_write: Bad offset %x\n", offset);
    }
}
Beispiel #3
0
static void
goldfish_nfc_process_ctrl(struct nfc_state* s)
{
    int res;

    if (s->ctrl == CTRL_INTR_ACK) {
        s->status ^= STATUS_INTR;
        goldfish_device_set_irq(&s->dev, 0, 0);

    } else if (s->ctrl == CTRL_RESP_RCV) {
        s->status &= ~(STATUS_NCI_RESP|STATUS_HCI_RESP);

    } else if (s->ctrl == CTRL_NTFN_RCV) {
        s->status ^= STATUS_NCI_NTFN;

    } else if (s->ctrl == CTRL_DATA_RCV) {
        s->status ^= STATUS_NCI_DATA;

    } else if (s->ctrl == CTRL_NCI_CMND_SNT) {
      if (s->status&(STATUS_NCI_RESP|STATUS_HCI_RESP))
          return; /* previous response still loaded, do nothing */

      s->status |= STATUS_NCI_CMND;

      memset(s->resp, 0, sizeof(s->resp));
      res = nfc_process_nci_msg((const union nci_packet*)s->cmnd, &s->nfc,
                                (union nci_packet*)s->resp);

      s->status &= ~STATUS_NCI_CMND;
      s->status |= STATUS_NCI_RESP * !!res;

      s->status |= STATUS_INTR;
      goldfish_device_set_irq(&s->dev, 0, 1);

    } else if (s->ctrl == CTRL_HCI_CMND_SNT) {
      if (s->status&(STATUS_NCI_RESP|STATUS_HCI_RESP))
          return; /* previous response still loaded, do nothing */

      s->status |= STATUS_HCI_CMND;

      memset(s->resp, 0, sizeof(s->resp));
      res = nfc_process_hci_cmd((const union hci_packet*)s->cmnd, &s->nfc,
                                (union hci_answer*)s->resp);

      s->status &= ~STATUS_HCI_CMND;
      s->status |= STATUS_HCI_RESP * !!res;

      s->status |= STATUS_INTR;
      goldfish_device_set_irq(&s->dev, 0, 1);
    }
}
static void goldfish_switch_write(void *opaque, target_phys_addr_t offset, uint32_t value)
{
    struct switch_state *s = (struct switch_state *)opaque;

    

    switch(offset) {
        case SW_NAME_PTR:
            safe_memory_rw_debug(cpu_single_env, value, (void*)s->name, strlen(s->name), 1);
            break;

        case SW_STATE:
            if(s->writefn) {
                uint32_t new_state;
                new_state = s->writefn(s->writeopaque, value);
                if(new_state != s->state) {
                    goldfish_switch_set_state(s, new_state);
                }
            }
            else
                cpu_abort (cpu_single_env, "goldfish_switch_write: write to SW_STATE on input\n");
            break;

        case SW_INT_ENABLE:
            value &= 1;
            if(s->state_changed && s->int_enable != value)
                goldfish_device_set_irq(&s->dev, 0, value);
            s->int_enable = value;
            break;

        default:
            cpu_abort (cpu_single_env, "goldfish_switch_write: Bad offset %x\n", offset);
    }
}
static void goldfish_timer_tick(void *opaque)
{
    struct timer_state *s = (struct timer_state *)opaque;

    s->armed = 0;
    goldfish_device_set_irq(&s->dev, 0, 1);
}
void goldfish_battery_set_prop(int ac, int property, int value)
{
    int new_status = (ac ? AC_STATUS_CHANGED : BATTERY_STATUS_CHANGED);

    if (!battery_state || !battery_state->hw_has_battery)
        return;

    if (ac) {
        switch (property) {
            case POWER_SUPPLY_PROP_ONLINE:
                battery_state->ac_online = value;
                break;
        }
    } else {
         switch (property) {
            case POWER_SUPPLY_PROP_STATUS:
                battery_state->status = value;
                break;
            case POWER_SUPPLY_PROP_HEALTH:
                battery_state->health = value;
                break;
            case POWER_SUPPLY_PROP_PRESENT:
                battery_state->present = value;
                break;
            case POWER_SUPPLY_PROP_CAPACITY:
                battery_state->capacity = value;
                break;
        }
    }

    if (new_status != battery_state->int_status) {
        battery_state->int_status |= new_status;
        goldfish_device_set_irq(&battery_state->dev, 0, (battery_state->int_status & battery_state->int_enable));
    }
}
Beispiel #7
0
void goldfish_battery_set_prop(void *opaque, int ac, int property, int value)
{
    int new_status = (ac ? AC_STATUS_CHANGED : BATTERY_STATUS_CHANGED);
    GoldfishBatteryDevice *s = (GoldfishBatteryDevice *)opaque;

    if (ac) {
        switch (property) {
            case POWER_SUPPLY_PROP_ONLINE:
                s->ac_online = value;
                break;
        }
    } else {
         switch (property) {
            case POWER_SUPPLY_PROP_STATUS:
                s->status = value;
                break;
            case POWER_SUPPLY_PROP_HEALTH:
                s->health = value;
                break;
            case POWER_SUPPLY_PROP_PRESENT:
                s->present = value;
                break;
            case POWER_SUPPLY_PROP_CAPACITY:
                s->capacity = value;
                break;
        }
    }

    if (new_status != s->int_status) {
        s->int_status |= new_status;
        goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
    }
}
Beispiel #8
0
static uint32_t goldfish_battery_read(void *opaque, target_phys_addr_t offset)
{
    uint32_t ret;
    GoldfishBatteryDevice *s = (GoldfishBatteryDevice *)opaque;

    switch(offset) {
        case BATTERY_INT_STATUS:
            // return current buffer status flags
            ret = s->int_status & s->int_enable;
            if (ret) {
                goldfish_device_set_irq(&s->dev, 0, 0);
                s->int_status = 0;
            }
            return ret;

		case BATTERY_INT_ENABLE:
		    return s->int_enable;
		case BATTERY_AC_ONLINE:
		    return s->ac_online;
		case BATTERY_STATUS:
		    return s->status;
		case BATTERY_HEALTH:
		    return s->health;
		case BATTERY_PRESENT:
		    return s->present;
		case BATTERY_CAPACITY:
		    return s->capacity;

        default:
            cpu_abort (cpu_single_env, "goldfish_battery_read: Bad offset %x\n", offset);
            return 0;
    }
}
static uint32_t goldfish_switch_read(void *opaque, target_phys_addr_t offset)
{
    struct switch_state *s = (struct switch_state *)opaque;

    

    switch (offset) {
        case SW_NAME_LEN:
            return strlen(s->name);
        case SW_FLAGS:
            return s->writefn ? SW_FLAGS_OUTPUT : 0;
        case SW_STATE:
            return s->state;
        case SW_INT_STATUS:
            if(s->state_changed && s->int_enable) {
                s->state_changed = 0;
                goldfish_device_set_irq(&s->dev, 0, 0);
                return 1;
            }
            return 0;
    default:
        cpu_abort (cpu_single_env, "goldfish_switch_read: Bad offset %x\n", offset);
        return 0;
    }
}
void goldfish_switch_set_state(void *opaque, uint32_t state)
{
    struct switch_state *s = opaque;
    s->state_changed = 1;
    s->state = state;
    if(s->int_enable)
        goldfish_device_set_irq(&s->dev, 0, 1);
}
static void
goldfish_rfkill_update_irq(struct rfkill_state *s)
{
    /* Pull down IRQ line if no active interrupt source. */
    int level = (s->int_mask & s->inta) ? 1 : 0;
    D("irq level: %d\n", level);
    goldfish_device_set_irq(&s->dev, 0, level);
}
Beispiel #12
0
static void tty_receive(void *opaque, const uint8_t *buf, int size)
{
    struct tty_state *s = opaque;

    memcpy(s->data + s->data_count, buf, size);
    s->data_count += size;
    if(s->data_count > 0 && s->ready)
        goldfish_device_set_irq(&s->dev, 0, 1);
}
Beispiel #13
0
static void goldfish_bus_op_init(struct bus_state *s)
{
    struct goldfish_device *dev = first_device;
    while(dev) {
        dev->reported_state = 0;
        dev = dev->next;
    }
    s->current = NULL;
    goldfish_device_set_irq(&s->dev, 0, first_device != NULL);
}
Beispiel #14
0
static void goldfish_tty_update_irq(struct tty_state *s)
{
    static int current_level = 0;
    int level;

    level = (s_tty.int_mask & s_tty.int_active) ? 1 : 0;
    if (level != current_level) {
        current_level = level;
        goldfish_device_set_irq(&s->dev, 0, level);
    }
}
Beispiel #15
0
/* I/O read */
static uint32_t pipe_dev_read(void *opaque, hwaddr offset)
{
    PipeDevice *dev = (PipeDevice *)opaque;

    switch (offset) {
    case PIPE_REG_STATUS:
        DR("%s: REG_STATUS status=%d (0x%x)", __FUNCTION__, dev->status, dev->status);
        return dev->status;

    case PIPE_REG_CHANNEL:
        if (dev->signaled_pipes != NULL) {
            Pipe* pipe = dev->signaled_pipes;
            DR("%s: channel=0x%llx wanted=%d", __FUNCTION__,
               (unsigned long long)pipe->channel, pipe->wanted);
            dev->wakes = pipe->wanted;
            pipe->wanted = 0;
            dev->signaled_pipes = pipe->next_waked;
            pipe->next_waked = NULL;
            if (dev->signaled_pipes == NULL) {
                goldfish_device_set_irq(&dev->dev, 0, 0);
                DD("%s: lowering IRQ", __FUNCTION__);
            }
            return (uint32_t)(pipe->channel & 0xFFFFFFFFUL);
        }
        DR("%s: no signaled channels", __FUNCTION__);
        return 0;

    case PIPE_REG_CHANNEL_HIGH:
        if (dev->signaled_pipes != NULL) {
            Pipe* pipe = dev->signaled_pipes;
            DR("%s: channel_high=0x%llx wanted=%d", __FUNCTION__,
               (unsigned long long)pipe->channel, pipe->wanted);
            return (uint32_t)(pipe->channel >> 32);
        }
        DR("%s: no signaled channels", __FUNCTION__);
        return 0;

    case PIPE_REG_WAKES:
        DR("%s: wakes %d", __FUNCTION__, dev->wakes);
        return dev->wakes;

    case PIPE_REG_PARAMS_ADDR_HIGH:
        return (uint32_t)(dev->params_addr >> 32);

    case PIPE_REG_PARAMS_ADDR_LOW:
        return (uint32_t)(dev->params_addr & 0xFFFFFFFFUL);

    default:
        D("%s: offset=%d (0x%x)\n", __FUNCTION__, offset, offset);
    }
Beispiel #16
0
static uint32_t goldfish_bus_read(void *opaque, hwaddr offset)
{
    struct bus_state *s = (struct bus_state *)opaque;

    switch (offset) {
    case PDEV_BUS_OP:
        if(s->current) {
            s->current->reported_state = 1;
            s->current = s->current->next;
        }
        else {
            s->current = first_device;
        }
        while(s->current && s->current->reported_state == 1)
            s->current = s->current->next;
        if(s->current)
            return PDEV_BUS_OP_ADD_DEV;
        else {
            goldfish_device_set_irq(&s->dev, 0, 0);
            return PDEV_BUS_OP_DONE;
        }

    case PDEV_BUS_NAME_LEN:
        return s->current ? strlen(s->current->name) : 0;
    case PDEV_BUS_ID:
        return s->current ? s->current->id : 0;
    case PDEV_BUS_IO_BASE:
        return s->current ? s->current->base : 0;
    case PDEV_BUS_IO_SIZE:
        return s->current ? s->current->size : 0;
    case PDEV_BUS_IRQ:
        return s->current ? s->current->irq : 0;
    case PDEV_BUS_IRQ_COUNT:
        return s->current ? s->current->irq_count : 0;
    default:
        cpu_abort(cpu_single_env,
                  "goldfish_bus_read: Bad offset %" HWADDR_PRIx "\n",
                  offset);
        return 0;
    }
}
void
goldfish_pipe_wake( void* hwpipe, unsigned flags )
{
    Pipe*  pipe = hwpipe;
    Pipe** lookup;
    PipeDevice*  dev = pipe->device;

    DD("%s: channel=0x%x flags=%d", __FUNCTION__, pipe->channel, flags);

    
    lookup = pipe_list_findp_waked(&dev->signaled_pipes, pipe);
    if (!*lookup) {
        pipe->next_waked = dev->signaled_pipes;
        dev->signaled_pipes = pipe;
    }
    pipe->wanted |= (unsigned)flags;

    
    goldfish_device_set_irq(&dev->dev, 0, 1);
    DD("%s: raising IRQ", __FUNCTION__);
}
static void goldfish_rtc_write(void *opaque, target_phys_addr_t offset, uint32_t value)
{
    struct rtc_state *s = (struct rtc_state *)opaque;
    int64_t alarm;
    switch(offset) {
        case 0x8:
            s->alarm_low = value;
            alarm = s->alarm_low | (int64_t)s->alarm_high << 32;
            //printf("next alarm at %lld, tps %lld\n", alarm, ticks_per_sec);
            //qemu_mod_timer(s->timer, alarm);
            break;
        case 0xc:
            s->alarm_high = value;
            //printf("alarm_high %d\n", s->alarm_high);
            break;
        case 0x10:
            goldfish_device_set_irq(&s->dev, 0, 0);
            break;
        default:
            cpu_abort (cpu_single_env, "goldfish_rtc_write: Bad offset %x\n", offset);
    }
}
Beispiel #19
0
static uint32_t goldfish_sensor_read(void *opaque, target_phys_addr_t offset)
{
    uint32_t ret;
    struct goldfish_sensor_state *s = opaque;
    offset -= s->dev.base;
    switch(offset) {
        case INT_ENABLE:
            // return current buffer status flags
            ret = s->int_status & s->int_enable;
            if (ret) {
                goldfish_device_set_irq(&s->dev, 0, 0);
                s->int_status = 0;
            }
            return ret;

        case ACCEL_X:
            return s->accel_x;
        case ACCEL_Y:
            return s->accel_y;
        case ACCEL_Z:
            return s->accel_z;
        case COMPASS_X:
            return s->compass_x;
        case COMPASS_Y:
            return s->compass_y;
        case COMPASS_Z:
            return s->compass_z;
        case ORIENT_X:
            return s->orient_x;
        case ORIENT_Y:
            return s->orient_y;
        case ORIENT_Z:
            return s->orient_z;
        default:
            cpu_abort (cpu_single_env, "goldfish_sensor_read: Bad offset %x\n", offset);
            return 0;
    }
}
Beispiel #20
0
static int  goldfish_timer_load(QEMUFile*  f, void*  opaque, int  version_id)
{
    struct timer_state*  s   = opaque;

    if (version_id != GOLDFISH_TIMER_SAVE_VERSION)
        return -1;

    s->now   = qemu_get_be64(f);
    s->armed = qemu_get_byte(f);
    if (s->armed) {
        int64_t  now   = qemu_get_clock(vm_clock);
        int64_t  diff  = qemu_get_be64(f);
        int64_t  alarm = now + diff;

        if (alarm <= now) {
            goldfish_device_set_irq(&s->dev, 0, 1);
            s->armed = 0;
        } else {
            qemu_mod_timer(s->timer, alarm);
        }
    }
    return 0;
}
Beispiel #21
0
int
goldfish_nfc_send_ntf(ssize_t (*create)(void*, struct nfc_device*, size_t,
                                        union nci_packet*), void* data)
{
    struct nfc_state* s;
    size_t maxlen;
    ssize_t res;

    assert(create);

    s = &_nfc_states[0];

    maxlen = MIN(sizeof(s->ntfn), MAX_NCI_PAYLOAD_LENGTH);
    memset(s->ntfn, 0, maxlen);
    res = create(data, &s->nfc, maxlen, (union nci_packet*)s->ntfn);
    if (res < 0)
      return -1;

    s->status |= STATUS_NCI_NTFN * !!res;
    s->status |= STATUS_INTR;
    goldfish_device_set_irq(&s->dev, 0, 1);

    return 0;
}
Beispiel #22
0
void goldfish_sensor_set_prop(int sensor, int x,int y,int z)
{

    switch (sensor) {
        case 0:
            sensor_state->accel_x=x;
            sensor_state->accel_y=y;
            sensor_state->accel_z=z;
            break;
        case 1:
            sensor_state->compass_x=x;
            sensor_state->compass_y=y;
            sensor_state->compass_z=z;
            break;

        case 2:
            sensor_state->orient_x=x;
            sensor_state->orient_y=y;
            sensor_state->orient_z=z;
            break;	
    }
    sensor_state->int_status |= (1<<sensor);
    goldfish_device_set_irq(&sensor_state->dev, 0, (sensor_state->int_status & sensor_state->int_enable));
}
static int  goldfish_timer_load(QEMUFile*  f, void*  opaque, int  version_id)
{
    struct timer_state*  s   = opaque;

    if (version_id != GOLDFISH_TIMER_SAVE_VERSION)
        return -1;

    s->now_ns = qemu_get_sbe64(f);  /* using qemu_get_be64 (without 's') causes faulty code generation
                                       in the compiler, dropping the 32 most significant bits */
    s->armed  = qemu_get_byte(f);
    if (s->armed) {
        int64_t  now_tks   = qemu_get_clock(vm_clock);
        int64_t  diff_tks  = qemu_get_be64(f);
        int64_t  alarm_tks = now_tks + diff_tks;

        if (alarm_tks <= now_tks) {
            goldfish_device_set_irq(&s->dev, 0, 1);
            s->armed = 0;
        } else {
            qemu_mod_timer(s->timer, alarm_tks);
        }
    }
    return 0;
}
Beispiel #24
0
static void goldfish_tty_write(void *opaque, hwaddr offset, uint32_t value)
{
    struct tty_state *s = (struct tty_state *)opaque;

    //printf("goldfish_tty_read %x %x %x\n", offset, value, size);

    switch(offset) {
        case TTY_PUT_CHAR: {
            uint8_t ch = value;
            if(s->cs)
                qemu_chr_write(s->cs, &ch, 1);
        } break;

        case TTY_CMD:
            switch(value) {
                case TTY_CMD_INT_DISABLE:
                    if(s->ready) {
                        if(s->data_count > 0)
                            goldfish_device_set_irq(&s->dev, 0, 0);
                        s->ready = 0;
                    }
                    break;

                case TTY_CMD_INT_ENABLE:
                    if(!s->ready) {
                        if(s->data_count > 0)
                            goldfish_device_set_irq(&s->dev, 0, 1);
                        s->ready = 1;
                    }
                    break;

                case TTY_CMD_WRITE_BUFFER:
                    if(s->cs) {
                        int len;
                        hwaddr  buf;

                        buf = s->ptr;
                        len = s->ptr_len;

                        while (len) {
                            char   temp[64];
                            int    to_write = sizeof(temp);
                            if (to_write > len)
                                to_write = len;

                            safe_memory_rw_debug(cpu_single_env, buf, (uint8_t*)temp, to_write, 0);
                            qemu_chr_write(s->cs, (const uint8_t*)temp, to_write);
                            buf += to_write;
                            len -= to_write;
                        }
                        //printf("goldfish_tty_write: got %d bytes from %x\n", s->ptr_len, s->ptr);
                    }
                    break;

                case TTY_CMD_READ_BUFFER:
                    if(s->ptr_len > s->data_count)
                        cpu_abort (cpu_single_env, "goldfish_tty_write: reading more data than available %d %d\n", s->ptr_len, s->data_count);
                    safe_memory_rw_debug(cpu_single_env,s->ptr, s->data, s->ptr_len,1);
                    //printf("goldfish_tty_write: read %d bytes to %x\n", s->ptr_len, s->ptr);
                    if(s->data_count > s->ptr_len)
                        memmove(s->data, s->data + s->ptr_len, s->data_count - s->ptr_len);
                    s->data_count -= s->ptr_len;
                    if(s->data_count == 0 && s->ready)
                        goldfish_device_set_irq(&s->dev, 0, 0);
                    break;

                default:
                    cpu_abort (cpu_single_env, "goldfish_tty_write: Bad command %x\n", value);
            };
            break;

        case TTY_DATA_PTR:
            s->ptr = value;
            break;

        case TTY_DATA_LEN:
            s->ptr_len = value;
            break;

        default:
            cpu_abort (cpu_single_env, "goldfish_tty_write: Bad offset %x\n", offset);
    }
}