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"); }
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; }
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; }
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; }
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; }
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; }
/* 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); }
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); }
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; } }
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++; }
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; }
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 {
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; }
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; } }
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); } }
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); } }
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; }
/* 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); }
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; }
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; } }
/* 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); } }
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; } }
/* 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; }
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; } }
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; }
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; } } }