ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

android emulator虚拟设备之qemu pipe分析(三),Android高级工程师进阶学习】

2022-01-29 12:59:38  阅读:226  来源: 互联网

标签:__ PIPE 进阶 dev pipe emulator address channel


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 long)pipe, dev->base + PIPE_REG_CHANNEL);

writel(CMD_POLL, dev->base + PIPE_REG_COMMAND);

status = readl(dev->base + PIPE_REG_STATUS);

spin_unlock_irqrestore(&dev->lock, irq_flags);

mutex_unlock(&pipe->lock);

if (status & PIPE_POLL_IN)

mask |= POLLIN | POLLRDNORM;

if (status & PIPE_POLL_OUT)

mask |= POLLOUT | POLLWRNORM;

if (status & PIPE_POLL_HUP)

mask |= POLLHUP;

if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))

mask |= POLLERR;

return mask;

}

qemu_pipe_interrupt,中断处理函数,循环处理每一个qemu_pipe,看看是否可读 or 可写 or 关闭了,然后唤醒对应的线程

static irqreturn_t qemu_pipe_interrupt(int irq, void *dev_id)

{

struct qemu_pipe_dev *dev = dev_id;

unsigned long irq_flags;

int count = 0;

/* We’re going to read from the emulator a list of (channel,flags)

* pairs corresponding to the wake events that occured on each

* blocked pipe (i.e. channel).

*/

spin_lock_irqsave(&dev->lock, irq_flags);

for (;

标签:__,PIPE,进阶,dev,pipe,emulator,address,channel
来源: https://blog.csdn.net/m0_66144992/article/details/122741809

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有