/** * seek the read-buffer */ loff_t file_llseek_configured(struct file *filp, loff_t off, int whence) { struct phys_mem_session *session = (struct phys_mem_session *) filp->private_data; size_t max_size = 0; long newpos = 0; long error = 0; if (down_interruptible(&session->sem)) return -ERESTARTSYS; if ((GET_STATE(session) != SESSION_STATE_CONFIGURED) && (GET_STATE(session) != SESSION_STATE_MAPPED)) { error = -EIO; pr_notice("Session %llu: The session cannot be llseek in state %i", session->session_id, GET_STATE(session)); goto err; } max_size = SESSION_FRAME_STATI_SIZE(session->num_frame_stati); switch (whence) { case 0: /* SEEK_SET */ newpos = off; break; case 1: /* SEEK_CUR */ newpos = filp->f_pos + off; break; case 2: /* SEEK_END */ newpos = max_size + off; break; default: /* can't happen */ error = -EINVAL; goto err; } if (newpos < 0) { error = -EINVAL; goto err; } #if 0 pr_debug("Session %llu: llseek OK %08lli, %i with max_size: %li From %lli to %li \n", session->session_id, off, whence, max_size, filp->f_pos, newpos); #endif filp->f_pos = newpos; up(&session->sem); return newpos; err: #if 0 pr_debug("Session %llu: llseek ERR %08lli, %i with max_size: %li From %lli to %li \n", session->session_id, off, whence, max_size, filp->f_pos, newpos); #endif up(&session->sem); return error; }
/** * Read: Read session->frame_stati * * This assumes that the session is in * SESSION_STATE_CONFIGURED or SESSION_STATE_MAPPED */ ssize_t file_read_configured(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { ssize_t retval = 0, max_size = 0; struct phys_mem_session *session = (struct phys_mem_session *) filp->private_data; if (down_interruptible(&session->sem)) return -ERESTARTSYS; if ((GET_STATE(session) != SESSION_STATE_CONFIGURED) && (GET_STATE(session) != SESSION_STATE_MAPPED)) { retval = -EIO; pr_notice("Session %llu: The session cannot be read in state %i", session->session_id, GET_STATE(session)); goto nothing; } max_size = SESSION_FRAME_STATI_SIZE(session->num_frame_stati); if (*f_pos > max_size) goto nothing; if (*f_pos + count > max_size) count = max_size - *f_pos; if (copy_to_user(buf, ((void *)((unsigned long)session->frame_stati) + *f_pos), count)) { retval = -EFAULT; goto nothing; } #if 0 pr_debug("Session %llu: read OK %08lli, %zi with max_size: %zi From %lli to %lli \n", session->session_id, *f_pos, count, max_size, *f_pos, *f_pos + count); #endif up(&session->sem); *f_pos += count; return count; nothing: #if 0 pr_debug("Session %llu: read ERR %08lli, %zi with max_size: %zi (p+s = %lli) -> %zi\n", session->session_id, *f_pos, count, max_size, *f_pos + count, retval); #endif up(&session->sem); return retval; }
int file_mmap_configured(struct file * filp, struct vm_area_struct * vma){ struct phys_mem_session* session = (struct phys_mem_session*) filp->private_data; int ret = 0; unsigned long max_size; if (down_interruptible (&session->sem)) return -ERESTARTSYS; if ((GET_STATE(session) != SESSION_STATE_CONFIGURED) && (GET_STATE(session) != SESSION_STATE_MAPPED) ) { ret = -EIO; printk(KERN_NOTICE "The session cannot be mmaped in state %i", GET_STATE(session)); goto err; } max_size = ROUND_UP_TO_PAGE(SESSION_FRAME_STATI_SIZE(session->num_frame_stati)); max_size <<= PAGE_SHIFT; if ( vma->vm_end - vma->vm_start > max_size){ ret = -EINVAL; printk(KERN_NOTICE "Mmap too large: %lx > %lx", vma->vm_end - vma->vm_start, max_size ); goto err; } ret = assemble_vma(session, vma); if (ret) goto err; vma->vm_ops = &phys_mem_vm_ops; vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP); vma->vm_flags |= VM_IO; vma->vm_private_data = session; up(&session->sem); phys_mem_vma_open(vma); return ret; err: up(&session->sem); return ret; }