2011-10-11 1:11:14
#define Q_TAILQ_ENTRY(type, qual) \
struct { \
qual type *tqe_next; /* next element */ \
qual type *qual *tqe_prev; /* address of previous next element */\
}
#define QTAILQ_ENTRY(type) Q_TAILQ_ENTRY(struct type,)
字符驱动状态
struct CharDriverState {
void (*init)(struct CharDriverState *s);
int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
void (*chr_update_read_handler)(struct CharDriverState *s);
int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
IOEventHandler *chr_event;
IOCanRWHandler *chr_can_read;
IOReadHandler *chr_read;
void *handler_opaque;
void (*chr_send_event)(struct CharDriverState *chr, int event);
void (*chr_close)(struct CharDriverState *chr);
void (*chr_accept_input)(struct CharDriverState *chr);
void *opaque;
int focus;
QEMUBH *bh;
char *label;
char *filename;
QTAILQ_ENTRY(CharDriverState) next;
};
void qemu_chr_add_handlers(CharDriverState *s,
IOCanRWHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
void *opaque)
{
s->chr_can_read = fd_can_read;
s->chr_read = fd_read;
s->chr_event = fd_event;
s->handler_opaque = opaque;
if (s->chr_update_read_handler)
s->chr_update_read_handler(s);
}
获取读处理
if(cs) {
qemu_chr_add_handlers(cs, tty_can_receive, tty_receive, NULL, s);
}
为什么要重置CS的方法
static void goldfish_tty_write(void *opaque, target_phys_addr_t 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;
直接调用CS的写方法
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;
target_phys_addr_t 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;
cpu_memory_rw_debug(cpu_single_env, buf, temp, to_write, 0);
qemu_chr_write(s->cs, 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);
cpu_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);
}
}
goldfish_tty_add(serial_hds[0], 0, 0xff002000, 4);
for(i = 1; i < MAX_SERIAL_PORTS; i++) {
//printf("android_arm_init serial %d %x\n", i, serial_hds[i]);
if(serial_hds[i]) {
goldfish_tty_add(serial_hds[i], i, 0, 0);
}
}
模拟了4个串口