示例#1
0
static void virtio_audio_cmd_result(uint32_t value, VirtQueueElement *elem,
                                    size_t *out_bytes)
{
    size_t offset = *out_bytes;
    int len;
    int n;

    DPRINTF("cmd result %d\n", value);
    for (n = 0; n < elem->in_num; n++) {
        len = elem->in_sg[n].iov_len;
        if (len < offset) {
            offset -= len;
            len = 0;
        } else {
            if (len  - offset < 4) {
                BADF("buffer too short\n");
                return;
            }
            stl_p(elem->in_sg[n].iov_base + offset, value);
            (*out_bytes) += 4;
            return;
        }
    }
    BADF("No space left\n");
}
示例#2
0
文件: smbus.c 项目: AmesianX/winkvm
static int smbus_i2c_recv(i2c_slave *s)
{
    SMBusDevice *dev = (SMBusDevice *)s;
    int ret;

    switch (dev->mode) {
    case SMBUS_RECV_BYTE:
        if (dev->receive_byte) {
            ret = dev->receive_byte(dev);
        } else {
            ret = 0;
        }
        DPRINTF("Receive Byte %02x\n", ret);
        dev->mode = SMBUS_DONE;
        break;
    case SMBUS_READ_DATA:
        if (dev->read_data) {
            ret = dev->read_data(dev, dev->command, dev->data_len);
            dev->data_len++;
        } else {
            ret = 0;
        }
        DPRINTF("Read data %02x\n", ret);
        break;
    default:
        BADF("Unexpected read in state %d\n", dev->mode);
        dev->mode = SMBUS_CONFUSED;
        ret = 0;
        break;
    }
    return ret;
}
示例#3
0
void qdev_add_chardev(QEMUDeviceClass *dc)
{
    if (dc->has_chardev) {
        BADF("Device class %s already has a chardev\n", dc->name);
    }
    dc->has_chardev = 1;
}
示例#4
0
static int execute_command(BlockDriverState *bdrv,
                           SCSIGenericReq *r, int direction,
			   BlockDriverCompletionFunc *complete)
{
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);

    r->io_header.interface_id = 'S';
    r->io_header.dxfer_direction = direction;
    r->io_header.dxferp = r->buf;
    r->io_header.dxfer_len = r->buflen;
    r->io_header.cmdp = r->req.cmd.buf;
    r->io_header.cmd_len = r->req.cmd.len;
    r->io_header.mx_sb_len = sizeof(s->sensebuf);
    r->io_header.sbp = s->sensebuf;
    r->io_header.timeout = MAX_UINT;
    r->io_header.usr_ptr = r;
    r->io_header.flags |= SG_FLAG_DIRECT_IO;

    r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
    if (r->req.aiocb == NULL) {
        BADF("execute_command: read failed !\n");
        return -ENOMEM;
    }

    return 0;
}
示例#5
0
static uint32_t syborg_virtio_readb(void *opaque, target_phys_addr_t offset)
{
    SyborgVirtIOProxy *s = opaque;
    VirtIODevice *vdev = s->vdev;

    DPRINTF("readb 0x%x\n", (int)offset);
    if (offset >= SYBORG_VIRTIO_CONFIG) {
        return virtio_config_readb(vdev, offset - SYBORG_VIRTIO_CONFIG);
    }
    BADF("Bad byte read offset 0x%x\n", (int)offset);
    return -1;
}
示例#6
0
static int smbus_i2c_send(I2CSlave *s, uint8_t data)
{
    SMBusDevice *dev = SMBUS_DEVICE(s);

    switch (dev->mode) {
    case SMBUS_WRITE_DATA:
        DPRINTF("Write data %02x\n", data);
        if (dev->data_len >= sizeof(dev->data_buf)) {
            BADF("Too many bytes sent\n");
        } else {
            dev->data_buf[dev->data_len++] = data;
        }
        break;

    default:
        BADF("Unexpected write in state %d\n", dev->mode);
        break;
    }

    return 0;
}
示例#7
0
/* Helper function for command completion.  */
static void scsi_command_complete(void *opaque, int ret)
{
    int status;
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;

    r->req.aiocb = NULL;
    if (r->req.io_canceled) {
        scsi_req_cancel_complete(&r->req);
        goto done;
    }
    if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
        r->req.sense_len = r->io_header.sb_len_wr;
    }

    if (ret != 0) {
        switch (ret) {
        case -EDOM:
            status = TASK_SET_FULL;
            break;
        case -ENOMEM:
            status = CHECK_CONDITION;
            scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
            break;
        default:
            status = CHECK_CONDITION;
            scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
            break;
        }
    } else {
        if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
            r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
            r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
            (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
            status = BUSY;
            BADF("Driver Timeout\n");
        } else if (r->io_header.host_status) {
            status = CHECK_CONDITION;
            scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
        } else if (r->io_header.status) {
            status = r->io_header.status;
        } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
            status = CHECK_CONDITION;
        } else {
            status = GOOD;
        }
    }
    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
            r, r->req.tag, status);

    scsi_req_complete(&r->req, status);
done:
    scsi_req_unref(&r->req);
}
示例#8
0
static void syborg_virtio_writeb(void *opaque, target_phys_addr_t offset,
                                 uint32_t value)
{
    SyborgVirtIOProxy *s = opaque;
    VirtIODevice *vdev = s->vdev;

    DPRINTF("writeb 0x%x = 0x%x\n", (int)offset, value);
    if (offset >= SYBORG_VIRTIO_CONFIG) {
        return virtio_config_writeb(vdev, offset - SYBORG_VIRTIO_CONFIG,
                                    value);
    }
    BADF("Bad byte write offset 0x%x\n", (int)offset);
}
示例#9
0
static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
                                 uint32_t value)
{
    SyborgVirtIOProxy *s = opaque;
    VirtIODevice *vdev = s->vdev;

    DPRINTF("writel 0x%x = 0x%x\n", (int)offset, value);
    if (offset >= SYBORG_VIRTIO_CONFIG) {
        return virtio_config_writel(vdev, offset - SYBORG_VIRTIO_CONFIG,
                                    value);
    }
    switch (offset >> 2) {
    case SYBORG_VIRTIO_GUEST_FEATURES:
        if (vdev->set_features)
            vdev->set_features(vdev, value);
        vdev->guest_features = value;
        break;
    case SYBORG_VIRTIO_QUEUE_BASE:
        if (value == 0)
            virtio_reset(vdev);
        else
            virtio_queue_set_addr(vdev, vdev->queue_sel, value);
        break;
    case SYBORG_VIRTIO_QUEUE_SEL:
        if (value < VIRTIO_PCI_QUEUE_MAX)
            vdev->queue_sel = value;
        break;
    case SYBORG_VIRTIO_QUEUE_NOTIFY:
        if (value < VIRTIO_PCI_QUEUE_MAX) {
            virtio_queue_notify(vdev, value);
        }
        break;
    case SYBORG_VIRTIO_STATUS:
        virtio_set_status(vdev, value & 0xFF);
        if (vdev->status == 0)
            virtio_reset(vdev);
        break;
    case SYBORG_VIRTIO_INT_ENABLE:
        s->int_enable = value;
        virtio_update_irq(vdev);
        break;
    case SYBORG_VIRTIO_INT_STATUS:
        vdev->isr &= ~value;
        virtio_update_irq(vdev);
        break;
    default:
        BADF("Bad write offset 0x%x\n", (int)offset);
        break;
    }
}
示例#10
0
void qdev_add_registers(QEMUDeviceClass *dc, CPUReadMemoryFunc **mem_read,
                        CPUWriteMemoryFunc **mem_write,
                        target_phys_addr_t mem_size)
{
    if (dc->num_regs == MAX_DEV_REGS) {
        BADF("too many regs");
        return;
    }

    dc->mem_read[dc->num_regs] = mem_read;
    dc->mem_write[dc->num_regs] = mem_write;
    dc->mem_size[dc->num_regs] = mem_size;
    dc->num_regs++;
}
示例#11
0
文件: smbus.c 项目: AmesianX/winkvm
static int smbus_i2c_send(i2c_slave *s, uint8_t data)
{
    SMBusDevice *dev = (SMBusDevice *)s;
    switch (dev->mode) {
    case SMBUS_WRITE_DATA:
        DPRINTF("Write data %02x\n", data);
        dev->data_buf[dev->data_len++] = data;
        break;
    default:
        BADF("Unexpected write in state %d\n", dev->mode);
        break;
    }
    return 0;
}
示例#12
0
static void g364fb_draw_graphic8(G364State *s)
{
    int i, w;
    uint8_t *vram;
    uint8_t *data_display, *dd;
    ram_addr_t page, page_min, page_max;
    int x, y;
    int xmin, xmax;
    int ymin, ymax;
    int xcursor, ycursor;
    unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned int b);

    switch (ds_get_bits_per_pixel(s->ds)) {
        case 8:
            rgb_to_pixel = rgb_to_pixel8;
            w = 1;
            break;
        case 15:
            rgb_to_pixel = rgb_to_pixel15;
            w = 2;
            break;
        case 16:
            rgb_to_pixel = rgb_to_pixel16;
            w = 2;
            break;
        case 32:
            rgb_to_pixel = rgb_to_pixel32;
            w = 4;
            break;
        default:
            BADF("unknown host depth %d\n", ds_get_bits_per_pixel(s->ds));
            return;
    }

    page = s->vram_offset;
    page_min = (ram_addr_t)-1;
    page_max = 0;

    x = y = 0;
    xmin = s->width;
    xmax = 0;
    ymin = s->height;
    ymax = 0;

    if (!(s->ctla & CTLA_NO_CURSOR)) {
        xcursor = s->cursor_position >> 12;
        ycursor = s->cursor_position & 0xfff;
    } else {
示例#13
0
static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
{
    SyborgVirtIOProxy *s = opaque;
    VirtIODevice *vdev = s->vdev;
    uint32_t ret;

    DPRINTF("readl 0x%x\n", (int)offset);
    if (offset >= SYBORG_VIRTIO_CONFIG) {
        return virtio_config_readl(vdev, offset - SYBORG_VIRTIO_CONFIG);
    }
    switch(offset >> 2) {
    case SYBORG_VIRTIO_ID:
        ret = SYBORG_ID_VIRTIO;
        break;
    case SYBORG_VIRTIO_DEVTYPE:
        ret = s->id;
        break;
    case SYBORG_VIRTIO_HOST_FEATURES:
        ret = vdev->get_features(vdev);
        ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
        break;
    case SYBORG_VIRTIO_GUEST_FEATURES:
        ret = vdev->features;
        break;
    case SYBORG_VIRTIO_QUEUE_BASE:
        ret = virtio_queue_get_addr(vdev, vdev->queue_sel);
        break;
    case SYBORG_VIRTIO_QUEUE_NUM:
        ret = virtio_queue_get_num(vdev, vdev->queue_sel);
        break;
    case SYBORG_VIRTIO_QUEUE_SEL:
        ret = vdev->queue_sel;
        break;
    case SYBORG_VIRTIO_STATUS:
        ret = vdev->status;
        break;
    case SYBORG_VIRTIO_INT_ENABLE:
        ret = s->int_enable;
        break;
    case SYBORG_VIRTIO_INT_STATUS:
        ret = vdev->isr;
        break;
    default:
        BADF("Bad read offset 0x%x\n", (int)offset);
        return 0;
    }
    return ret;
}
示例#14
0
static void led_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
    LedState *s = opaque;

    DPRINTF("write addr=" TARGET_FMT_plx " val=0x%02x\n", addr, val);

    switch (addr) {
    case 0:
        s->segments = val;
        s->state |= REDRAW_SEGMENTS;
        break;
    default:
        BADF("invalid write of 0x%08x at [" TARGET_FMT_plx "]\n", val, addr);
        break;
    }
}
示例#15
0
文件: pl022.c 项目: npe9/qemu-acid
static void pl022_write(void *opaque, hwaddr offset,
                        uint64_t value, unsigned size)
{
    pl022_state *s = (pl022_state *)opaque;

    switch (offset) {
    case 0x00: /* CR0 */
        s->cr0 = value;
        /* Clock rate and format are ignored.  */
        s->bitmask = (1 << ((value & 15) + 1)) - 1;
        break;
    case 0x04: /* CR1 */
        s->cr1 = value;
        if ((s->cr1 & (PL022_CR1_MS | PL022_CR1_SSE))
                   == (PL022_CR1_MS | PL022_CR1_SSE)) {
            BADF("SPI slave mode not implemented\n");
        }
        pl022_xfer(s);
        break;
    case 0x08: /* DR */
        if (s->tx_fifo_len < 8) {
            DPRINTF("TX %02x\n", (unsigned)value);
            s->tx_fifo[s->tx_fifo_head] = value & s->bitmask;
            s->tx_fifo_head = (s->tx_fifo_head + 1) & 7;
            s->tx_fifo_len++;
            pl022_xfer(s);
        }
        break;
    case 0x10: /* CPSR */
        /* Prescaler.  Ignored.  */
        s->cpsr = value & 0xff;
        break;
    case 0x14: /* IMSC */
        s->im = value;
        pl022_update(s);
        break;
    case 0x20: /* DMACR */
        if (value) {
            qemu_log_mask(LOG_UNIMP, "pl022: DMA not implemented\n");
        }
        break;
    default:
        qemu_log_mask(LOG_GUEST_ERROR,
                      "pl022_write: Bad offset %x\n", (int)offset);
    }
}
示例#16
0
文件: pl022.c 项目: AmesianX/winkvm
static void pl022_write(void *opaque, target_phys_addr_t offset,
                        uint32_t value)
{
    pl022_state *s = (pl022_state *)opaque;

    offset -= s->base;
    switch (offset) {
    case 0x00: /* CR0 */
        s->cr0 = value;
        /* Clock rate and format are ignored.  */
        s->bitmask = (1 << ((value & 15) + 1)) - 1;
        break;
    case 0x04: /* CR1 */
        s->cr1 = value;
        if ((s->cr1 & (PL022_CR1_MS | PL022_CR1_SSE))
                   == (PL022_CR1_MS | PL022_CR1_SSE)) {
            BADF("SPI slave mode not implemented\n");
        }
        pl022_xfer(s);
        break;
    case 0x08: /* DR */
        if (s->tx_fifo_len < 8) {
            DPRINTF("TX %02x\n", value);
            s->tx_fifo[s->tx_fifo_head] = value & s->bitmask;
            s->tx_fifo_head = (s->tx_fifo_head + 1) & 7;
            s->tx_fifo_len++;
            pl022_xfer(s);
        }
        break;
    case 0x10: /* CPSR */
        /* Prescaler.  Ignored.  */
        s->cpsr = value & 0xff;
        break;
    case 0x14: /* IMSC */
        s->im = value;
        pl022_update(s);
        break;
    case 0x20: /* DMACR */
        if (value)
            cpu_abort (cpu_single_env, "pl022: DMA not implemented\n");
        break;
    default:
        cpu_abort (cpu_single_env, "pl022_write: Bad offset %x\n",
                   (int)offset);
    }
}
示例#17
0
static uint32_t led_readb(void *opaque, target_phys_addr_t addr)
{
    LedState *s = opaque;
    uint32_t val;

    switch (addr) {
    case 0:
        val = s->segments;
        break;
    default:
        BADF("invalid read at [" TARGET_FMT_plx "]\n", addr);
        val = 0;
    }

    DPRINTF("read addr=" TARGET_FMT_plx " val=0x%02x\n", addr, val);

    return val;
}
示例#18
0
/* Helper function for command completion.  */
static void scsi_command_complete(void *opaque, int ret)
{
    SCSIGenericReq *r = (SCSIGenericReq *)opaque;
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, r->req.dev);

    r->req.aiocb = NULL;
    s->driver_status = r->io_header.driver_status;
    if (s->driver_status & SG_ERR_DRIVER_SENSE)
        s->senselen = r->io_header.sb_len_wr;

    if (ret != 0) {
        switch (ret) {
        case -EDOM:
            r->req.status = TASK_SET_FULL;
            break;
        case -EINVAL:
            r->req.status = CHECK_CONDITION;
            scsi_set_sense(s, SENSE_CODE(INVALID_FIELD));
            break;
        case -ENOMEM:
            r->req.status = CHECK_CONDITION;
            scsi_set_sense(s, SENSE_CODE(TARGET_FAILURE));
            break;
        default:
            r->req.status = CHECK_CONDITION;
            scsi_set_sense(s, SENSE_CODE(IO_ERROR));
            break;
        }
    } else {
        if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
            r->req.status = BUSY;
            BADF("Driver Timeout\n");
        } else if (r->io_header.status)
            r->req.status = r->io_header.status;
        else if (s->driver_status & SG_ERR_DRIVER_SENSE)
            r->req.status = CHECK_CONDITION;
        else
            r->req.status = GOOD;
    }
    DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
            r, r->req.tag, r->req.status);

    scsi_req_complete(&r->req);
}
示例#19
0
static uint8_t smbus_i2c_recv(I2CSlave *s)
{
    SMBusDevice *dev = SMBUS_DEVICE(s);
    SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
    uint8_t ret = 0xff;

    switch (dev->mode) {
    case SMBUS_READ_DATA:
        if (sc->receive_byte) {
            ret = sc->receive_byte(dev);
        }
        DPRINTF("Read data %02x\n", ret);
        break;

    default:
        BADF("Unexpected read in state %d\n", dev->mode);
        dev->mode = SMBUS_CONFUSED;
        break;
    }

    return ret;
}
示例#20
0
static uint64_t stellaris_enet_read(void *opaque, hwaddr offset,
                                    unsigned size)
{
    stellaris_enet_state *s = (stellaris_enet_state *)opaque;
    uint32_t val;

    switch (offset) {
    case 0x00: /* RIS */
        DPRINTF("IRQ status %02x\n", s->ris);
        return s->ris;
    case 0x04: /* IM */
        return s->im;
    case 0x08: /* RCTL */
        return s->rctl;
    case 0x0c: /* TCTL */
        return s->tctl;
    case 0x10: /* DATA */
    {
        uint8_t *rx_fifo;

        if (s->np == 0) {
            BADF("RX underflow\n");
            return 0;
        }

        rx_fifo = s->rx[s->next_packet].data + s->rx_fifo_offset;

        val = rx_fifo[0] | (rx_fifo[1] << 8) | (rx_fifo[2] << 16)
              | (rx_fifo[3] << 24);
        s->rx_fifo_offset += 4;
        if (s->rx_fifo_offset >= s->rx[s->next_packet].len) {
            s->rx_fifo_offset = 0;
            s->next_packet++;
            if (s->next_packet >= 31)
                s->next_packet = 0;
            s->np--;
            DPRINTF("RX done np=%d\n", s->np);
            if (!s->np && stellaris_enet_can_receive(s)) {
                qemu_flush_queued_packets(qemu_get_queue(s->nic));
            }
        }
        return val;
    }
    case 0x14: /* IA0 */
        return s->conf.macaddr.a[0] | (s->conf.macaddr.a[1] << 8)
            | (s->conf.macaddr.a[2] << 16)
            | ((uint32_t)s->conf.macaddr.a[3] << 24);
    case 0x18: /* IA1 */
        return s->conf.macaddr.a[4] | (s->conf.macaddr.a[5] << 8);
    case 0x1c: /* THR */
        return s->thr;
    case 0x20: /* MCTL */
        return s->mctl;
    case 0x24: /* MDV */
        return s->mdv;
    case 0x28: /* MADD */
        return 0;
    case 0x2c: /* MTXD */
        return s->mtxd;
    case 0x30: /* MRXD */
        return s->mrxd;
    case 0x34: /* NP */
        return s->np;
    case 0x38: /* TR */
        return 0;
    case 0x3c: /* Undocuented: Timestamp? */
        return 0;
    default:
        hw_error("stellaris_enet_read: Bad offset %x\n", (int)offset);
        return 0;
    }
}
示例#21
0
/* Command queue.  */
static void virtio_audio_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
{
    VirtIOAudio *s = to_virtio_audio(vdev);
    VirtIOAudioStream *stream;
    VirtQueueElement elem;
    int out_n;
    uint32_t *p;
    int len;
    size_t out_bytes;
    uint32_t value;

    while (virtqueue_pop(s->cmd_vq, &elem)) {
        size_t bytes_transferred = 0;
        for (out_n = 0; out_n < elem.out_num; out_n++) {
            p = (uint32_t *)elem.out_sg[out_n].iov_base;
            len = elem.out_sg[out_n].iov_len;
            while (len > 0) {
                if (len < 12) {
                    BADF("Bad command length\n");
                    break;
                }
                DPRINTF("Command %d %d %d\n",
                        ldl_p(p), ldl_p(p + 1), ldl_p (p + 2));
                value = ldl_p(p + 1);
                if (value >= NUM_STREAMS)
                    break;
                stream = &s->stream[value];
                value = ldl_p(p + 2);
                switch (ldl_p(p)) {
                case VIRTIO_AUDIO_CMD_SET_ENDIAN:
                    stream->fmt.endianness = value;
                    break;
                case VIRTIO_AUDIO_CMD_SET_CHANNELS:
                    stream->fmt.nchannels = value;
                    break;
                case VIRTIO_AUDIO_CMD_SET_FMT:
                    stream->fmt.fmt = value;
                    break;
                case VIRTIO_AUDIO_CMD_SET_FREQ:
                    stream->fmt.freq = value;
                    break;
                case VIRTIO_AUDIO_CMD_INIT:
                    out_bytes = 0;
                    if (value == 1) {
                        if (stream->out_voice) {
                            AUD_close_out(&s->card, stream->out_voice);
                            stream->out_voice = NULL;
                        }
                        stream->in_voice =
                          AUD_open_in(&s->card, stream->in_voice,
                                      "virtio-audio.in",
                                      stream,
                                      virtio_audio_callback,
                                      &stream->fmt);
                        virtio_audio_cmd_result(0, &elem, &out_bytes);
                    } else if (value == 0) {
                        if (stream->in_voice) {
                            AUD_close_in(&s->card, stream->in_voice);
                            stream->in_voice = NULL;
                        }
                        stream->out_voice =
                          AUD_open_out(&s->card, stream->out_voice,
                                       "virtio-audio.out",
                                       stream,
                                       virtio_audio_callback,
                                       &stream->fmt);
                        value = AUD_get_buffer_size_out(stream->out_voice);
                        virtio_audio_cmd_result(value, &elem, &out_bytes);
                    } else { // let us close all down
                        if (stream->out_voice) {
                            AUD_close_out(&s->card, stream->out_voice);
                            stream->out_voice = NULL;
                        }
                        if (stream->in_voice) {
                            AUD_close_in(&s->card, stream->in_voice);
                            stream->in_voice = NULL;
                        }                        
                    }
                    bytes_transferred += out_bytes;
                    break;
                case VIRTIO_AUDIO_CMD_RUN:
                    if (stream->in_voice) {
                        AUD_set_active_in(stream->in_voice, value);
                    } else if (stream->out_voice) {
                        AUD_set_active_out(stream->out_voice, value);
                    } else
                    {
                        DPRINTF("Cannot execute CMD_RUN as no voice is active\n");
                    }
                    break;
                }
                p += 3;
                len -= 12;
                bytes_transferred += 12;
            }
        }
        virtqueue_push(s->cmd_vq, &elem, bytes_transferred);
        virtio_notify(vdev, s->cmd_vq);		
    }
}
示例#22
0
static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
{
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, req->dev);
    SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req);
    int ret;

    if (cmd[0] != REQUEST_SENSE && req->lun != s->lun) {
        DPRINTF("Unimplemented LUN %d\n", req->lun);
        scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED));
        r->req.status = CHECK_CONDITION;
        scsi_req_complete(&r->req);
        return 0;
    }

    if (-1 == scsi_req_parse(&r->req, cmd)) {
        BADF("Unsupported command length, command %x\n", cmd[0]);
        scsi_command_complete(r, -EINVAL);
        return 0;
    }
    scsi_req_fixup(&r->req);

    DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag,
            r->req.cmd.xfer, cmd[0]);

#ifdef DEBUG_SCSI
    {
        int i;
        for (i = 1; i < r->req.cmd.len; i++) {
            printf(" 0x%02x", cmd[i]);
        }
        printf("\n");
    }
#endif

    if (r->req.cmd.xfer == 0) {
        if (r->buf != NULL)
            qemu_free(r->buf);
        r->buflen = 0;
        r->buf = NULL;
        ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete);
        if (ret < 0) {
            scsi_command_complete(r, ret);
            return 0;
        }
        return 0;
    }

    if (r->buflen != r->req.cmd.xfer) {
        if (r->buf != NULL)
            qemu_free(r->buf);
        r->buf = qemu_malloc(r->req.cmd.xfer);
        r->buflen = r->req.cmd.xfer;
    }

    memset(r->buf, 0, r->buflen);
    r->len = r->req.cmd.xfer;
    if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
        r->len = 0;
        return -r->req.cmd.xfer;
    } else {
        return r->req.cmd.xfer;
    }
}
示例#23
0
/* FIXME: Should we just have qdev_irq_{raise,lower}?  */
void qdev_get_irq(QEMUDevice *dev, int n, qemu_irq *p)
{
    if (n >= dev->dc->num_irqs)
        BADF("Bad IRQ %d (%d)\n", n, dev->dc->num_irqs);
    dev->irqp[n] = p;
}
示例#24
0
static uint32_t stellaris_enet_read(void *opaque, target_phys_addr_t offset)
{
    stellaris_enet_state *s = (stellaris_enet_state *)opaque;
    uint32_t val;

    switch (offset) {
    case 0x00: /* RIS */
        DPRINTF("IRQ status %02x\n", s->ris);
        return s->ris;
    case 0x04: /* IM */
        return s->im;
    case 0x08: /* RCTL */
        return s->rctl;
    case 0x0c: /* TCTL */
        return s->tctl;
    case 0x10: /* DATA */
        if (s->rx_fifo_len == 0) {
            if (s->np == 0) {
                BADF("RX underflow\n");
                return 0;
            }
            s->rx_fifo_len = s->rx[s->next_packet].len;
            s->rx_fifo = s->rx[s->next_packet].data;
            DPRINTF("RX FIFO start packet len=%d\n", s->rx_fifo_len);
        }
        val = s->rx_fifo[0] | (s->rx_fifo[1] << 8) | (s->rx_fifo[2] << 16)
              | (s->rx_fifo[3] << 24);
        s->rx_fifo += 4;
        s->rx_fifo_len -= 4;
        if (s->rx_fifo_len <= 0) {
            s->rx_fifo_len = 0;
            s->next_packet++;
            if (s->next_packet >= 31)
                s->next_packet = 0;
            s->np--;
            DPRINTF("RX done np=%d\n", s->np);
        }
        return val;
    case 0x14: /* IA0 */
        return s->macaddr[0] | (s->macaddr[1] << 8)
               | (s->macaddr[2] << 16) | (s->macaddr[3] << 24);
    case 0x18: /* IA1 */
        return s->macaddr[4] | (s->macaddr[5] << 8);
    case 0x1c: /* THR */
        return s->thr;
    case 0x20: /* MCTL */
        return s->mctl;
    case 0x24: /* MDV */
        return s->mdv;
    case 0x28: /* MADD */
        return 0;
    case 0x2c: /* MTXD */
        return s->mtxd;
    case 0x30: /* MRXD */
        return s->mrxd;
    case 0x34: /* NP */
        return s->np;
    case 0x38: /* TR */
        return 0;
    case 0x3c: /* Undocuented: Timestamp? */
        return 0;
    default:
        hw_error("stellaris_enet_read: Bad offset %x\n", (int)offset);
        return 0;
    }
}
示例#25
0
static int smbus_i2c_event(I2CSlave *s, enum i2c_event event)
{
    SMBusDevice *dev = SMBUS_DEVICE(s);

    switch (event) {
    case I2C_START_SEND:
        switch (dev->mode) {
        case SMBUS_IDLE:
            DPRINTF("Incoming data\n");
            dev->mode = SMBUS_WRITE_DATA;
            break;

        default:
            BADF("Unexpected send start condition in state %d\n", dev->mode);
            dev->mode = SMBUS_CONFUSED;
            break;
        }
        break;

    case I2C_START_RECV:
        switch (dev->mode) {
        case SMBUS_IDLE:
            DPRINTF("Read mode\n");
            dev->mode = SMBUS_READ_DATA;
            break;

        case SMBUS_WRITE_DATA:
            if (dev->data_len == 0) {
                BADF("Read after write with no data\n");
                dev->mode = SMBUS_CONFUSED;
            } else {
                smbus_do_write(dev);
                DPRINTF("Read mode\n");
                dev->mode = SMBUS_READ_DATA;
            }
            break;

        default:
            BADF("Unexpected recv start condition in state %d\n", dev->mode);
            dev->mode = SMBUS_CONFUSED;
            break;
        }
        break;

    case I2C_FINISH:
        if (dev->data_len == 0) {
            if (dev->mode == SMBUS_WRITE_DATA || dev->mode == SMBUS_READ_DATA) {
                smbus_do_quick_cmd(dev, dev->mode == SMBUS_READ_DATA);
            }
        } else {
            switch (dev->mode) {
            case SMBUS_WRITE_DATA:
                smbus_do_write(dev);
                break;

            case SMBUS_READ_DATA:
                BADF("Unexpected stop during receive\n");
                break;

            default:
                /* Nothing to do.  */
                break;
            }
        }
        dev->mode = SMBUS_IDLE;
        dev->data_len = 0;
        break;

    case I2C_NACK:
        switch (dev->mode) {
        case SMBUS_DONE:
            /* Nothing to do.  */
            break;

        case SMBUS_READ_DATA:
            dev->mode = SMBUS_DONE;
            break;

        default:
            BADF("Unexpected NACK in state %d\n", dev->mode);
            dev->mode = SMBUS_CONFUSED;
            break;
        }
    }

    return 0;
}
示例#26
0
文件: smbus.c 项目: AmesianX/winkvm
static void smbus_i2c_event(i2c_slave *s, enum i2c_event event)
{
    SMBusDevice *dev = (SMBusDevice *)s;
    switch (event) {
    case I2C_START_SEND:
        switch (dev->mode) {
        case SMBUS_IDLE:
            DPRINTF("Incoming data\n");
            dev->mode = SMBUS_WRITE_DATA;
            break;
        default:
            BADF("Unexpected send start condition in state %d\n", dev->mode);
            dev->mode = SMBUS_CONFUSED;
            break;
        }
        break;

    case I2C_START_RECV:
        switch (dev->mode) {
        case SMBUS_IDLE:
            DPRINTF("Read mode\n");
            dev->mode = SMBUS_RECV_BYTE;
            break;
        case SMBUS_WRITE_DATA:
            if (dev->data_len == 0) {
                BADF("Read after write with no data\n");
                dev->mode = SMBUS_CONFUSED;
            } else {
                if (dev->data_len > 1) {
                    smbus_do_write(dev);
                } else {
                    dev->command = dev->data_buf[0];
                    DPRINTF("%02x: Command %d\n", dev->i2c.address,
                            dev->command);
                }
                DPRINTF("Read mode\n");
                dev->data_len = 0;
                dev->mode = SMBUS_READ_DATA;
            }
            break;
        default:
            BADF("Unexpected recv start condition in state %d\n", dev->mode);
            dev->mode = SMBUS_CONFUSED;
            break;
        }
        break;

    case I2C_FINISH:
        switch (dev->mode) {
        case SMBUS_WRITE_DATA:
            smbus_do_write(dev);
            break;
        case SMBUS_RECV_BYTE:
            smbus_do_quick_cmd(dev, 1);
            break;
        case SMBUS_READ_DATA:
            BADF("Unexpected stop during receive\n");
            break;
        default:
            /* Nothing to do.  */
            break;
        }
        dev->mode = SMBUS_IDLE;
        dev->data_len = 0;
        break;

    case I2C_NACK:
        switch (dev->mode) {
        case SMBUS_DONE:
            /* Nothing to do.  */
            break;
        case SMBUS_READ_DATA:
            dev->mode = SMBUS_DONE;
            break;
        default:
            BADF("Unexpected NACK in state %d\n", dev->mode);
            dev->mode = SMBUS_CONFUSED;
            break;
        }
    }
}