while (address < address_end) {
unsigned long page_end = (address & PAGE_MASK) + PAGE_SIZE;
-
unsigned long next = page_end < address_end ? page_end
- address_end;
unsigned long avail = next - address;
int status, wakeBit;
/* Ensure that the corresponding page is properly mapped */
if (is_write) {
char c;
/* Ensure that the page is mapped and readable */
if (__get_user(c, (char __user *)address)) {
PIPE_E(“read fault at address 0x%08x\n”,
(unsigned int)address);
if (!ret)
ret = -EFAULT;
break;
}
} else {
/* Ensure that the page is mapped and writable */
if (__put_user(0, (char __user *)address)) {
PIPE_E(“write fault at address 0x%08x\n”,
(unsigned int)address);
if (!ret)
ret = -EFAULT;
break;
}
}
/* Now, try to transfer the bytes in the current page */
spin_lock_irqsave(&dev->lock, irq_flags);
if (dev->aps == NULL || access_with_param(
dev, CMD_WRITE_BUFFER + cmd_offset, address, avail,
pipe, &status) < 0)
{
writel((unsigned long)pipe,
dev->base + PIPE_REG_CHANNEL);
writel(avail, dev->base + PIPE_REG_SIZE);
writel(address, dev->base + PIPE_REG_ADDRESS);
writel(CMD_WRITE_BUFFER + cmd_offset,
dev->base + PIPE_REG_COMMAND);
status = readl(dev->base + PIPE_REG_STATUS);
}
spin_unlock_irqrestore(&dev->lock, irq_flags);
if (status > 0) { /* Correct transfer */
ret += status;
address += status;
continue;
}
if (status == 0) /* EOF */
break;
/* An error occured. If we already transfered stuff, just
* return with its count. We expect the next call to return
* an error code */
if (ret > 0)
break;
/* If the error is not PIPE_ERROR_AGAIN, or if we are not in
* non-blocking mode, just return the error code.
*/
if (status != PIPE_ERROR_AGAIN ||
(filp->f_flags & O_NONBLOCK) != 0) {
ret = qemu_pipe_error_convert(status);
break;
}
/* We will have to wait until more data/space is available.
* First, mark the pipe as waiting for a specific wake signal.
*/
wakeBit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ;
set_bit(wakeBit, &pipe->flags);
/* Tell the emulator we’re going to wait for a wake event */
spin_lock_irqsave(&dev->lock, irq_flags);
writel((unsigned long)pipe, dev->base + PIPE_REG_CHANNEL);
writel(CMD_WAKE_ON_WRITE + cmd_offset,
dev->base + PIPE_REG_COMMAND);
spin_unlock_irqrestore(&dev->lock, irq_flags);
/* Unlock the pipe, then wait for the wake signal */
mutex_unlock(&pipe->lock);
while (test_bit(wakeBit, &pipe->flags)) {
if (wait_event_interruptible(
pipe->wake_queue,
!test_bit(wakeBit, &pipe->flags))) {
ret = -ERESTARTSYS;
PIPE_W(“rw, wait_event error\n”);
goto out;
}
if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) {
ret = -EIO;
PIPE_W(“rw, pipe already closed\n”);
goto out;
}
}
/* Try to re-acquire the lock */
if (mutex_lock_interruptible(&pipe->lock)) {
ret = -ERESTARTSYS;
goto out;
}
/* Try the transfer again */
continue;
}
mutex_unlock(&pipe->lock);
out:
return ret;
}
static ssize_t qemu_pipe_read(struct file *filp, char __user *buffer,
size_t bufflen, loff_t *ppos)
{
return qemu_pipe_read_write(filp, buffer, bufflen, 0);
}
static ssize_t qemu_pipe_write(struct file *filp,
const char __user *buffer, size_t bufflen,
loff_t *ppos)
{
return qemu_pipe_read_write(filp, (char __user *)buffer, bufflen, 1);
}
qemu_pipe_poll,实现poll,select,epoll接口用的,没什么特殊的,标准实现方式
static unsigned int qemu_pipe_poll(struct file *filp, poll_table *wait)
{
struct qemu_pipe *pipe = filp->private_data;
struct qemu_pipe_dev *dev = pipe->dev;
unsigned long irq_flags;
unsigned int mask = 0;
int status;
mutex_lock(&pipe->lock);
poll_wait(filp, &pipe->wake_queue, wait);
spin_lock_irqsave(&dev->lock, irq_flags);
writel((unsigned