示例#1
0
static int 
devi_devctl(resmgr_context_t *ctp, io_devctl_t *msg, RESMGR_OCB_T *ocb)
{
        devi_attr_t	*attr;
	iov_t		iov;
        char		*buffer, *allocd;
	long		dcmd;
	int		error, nbytes;

	attr = ocb->ocb.attr;
        error = EOK;

	if ((error = iofunc_devctl(ctp, msg, &ocb->ocb, &attr->attr)) != _RESMGR_DEFAULT)
                return (error);
  
        /* ripped off from deva....:-) */
        if (!(get_device_direction(dcmd = msg->i.dcmd) & DEVDIR_TOFROM))
                nbytes = 0, buffer = allocd = NULL;
        else if ((nbytes = msg->i.nbytes) <= ctp->msg_max_size - sizeof(*msg))
                buffer = _DEVCTL_DATA(*msg), allocd = NULL;
        else if ((buffer = allocd = malloc((nbytes + 3) & ~3)) == NULL)
                return (_RESMGR_ERRNO(ENOMEM));
        else if ((get_device_direction(dcmd) & DEVDIR_TO)) {
                SETIOV(&iov, buffer, nbytes);
                if (resmgr_msgreadv(ctp, &iov, 1, sizeof(msg->i)) == -1)
                        goto error_out;
        }

        /* TODO: now call a helper function to actually do the devctl
           returns < 0 on error, else nbytes to xfer back on EOK */

        msg->o.ret_val = error;
        if (error == EOK && get_device_direction(dcmd) & DEVDIR_FROM) {
                SETIOV(&iov, buffer, nbytes);
                if (resmgr_msgwritev(ctp, &iov, 1, sizeof(msg->o)) == -1)
                        goto error_out;
        }

        if (allocd != NULL)
                free(allocd);

        return((error == EOK) ? _RESMGR_PTR(ctp, &msg->o, sizeof(msg->o)) : 
               _RESMGR_ERRNO(error));

 error_out:
        error = errno;
        if (allocd != NULL)
                free(allocd);
        return(_RESMGR_ERRNO(error));
}
示例#2
0
文件: devmem.c 项目: vocho/openqnx
static int 
mem_read_write(resmgr_context_t *ctp, resmgr_iomsgs_t *msg, struct mem_ocb *ocb) {
	void					*addr;
	unsigned				nbytes;
	unsigned				size;
	PROCESS					*proc;
	union object			*obp;
	unsigned				*pos;
	unsigned				offset;
	size_t					skip;

	// IO_READ and IO_WRITE messages exactly overlay, as does XTYPE_OFFSET!

	if(!ocb) {
		nbytes = 0;
		goto ok;
	}
	if(!(ocb->ioflag & ((msg->type == _IO_READ) ? _IO_FLAG_RD : _IO_FLAG_WR))) {
		return EBADF;
	}
	nbytes = msg->read.i.nbytes;

	obp = ocb->object;
	if((msg->type == _IO_WRITE) && (ocb->ioflag & O_APPEND) && obp) {
		ocb->pos = OBJECT_SIZE(obp);
	}

	switch (msg->read.i.xtype & _IO_XTYPE_MASK)
	{
    	case _IO_XTYPE_NONE:
		    pos = &ocb->pos;
			skip = sizeof(msg->read.i);
			break;
	    case _IO_XTYPE_OFFSET:
			offset = ((io_pread_t*)msg)->offset.offset;
			pos = &offset;
			skip = sizeof(io_pread_t);
			break;
		default: /* this really shouldn't happen, but just in case */
		    return ENOSYS;
	}

	proc = sysmgr_prp;
	size = obp ? OBJECT_SIZE(obp) : UINT_MAX;
	if( *pos > size - nbytes || *pos + nbytes > size) {
		if(obp && msg->type == _IO_WRITE) {
			int					status;

			status = memmgr.resize(obp, *pos + nbytes);
			if(status != EOK) {
				return status;
			}
			size = OBJECT_SIZE(obp);
		}
		if(*pos >= size) {
			nbytes = 0;
		} else {
			nbytes = size - *pos;
		}
	}

	if(nbytes) {
		int						status, err;
		int						flags;
		part_id_t			mpid;

		if(proc_thread_pool_reserve() != 0) {
			return EAGAIN;
		}
		ProcessBind(SYSMGR_PID);

		proc_wlock_adp(proc);
		flags = MAP_SHARED;
		if(obp != NULL) {
			proc_mux_lock(&obp->mem.mm.mux);
			mpid = obp->hdr.mpid;
		} else {
			flags |= MAP_PHYS;
			mpid = part_id_t_INVALID;
		}
		status = memmgr.mmap(proc, 0, nbytes, PROT_READ|PROT_WRITE, flags,
						obp, *pos, 0, nbytes, NOFD, &addr, &size, mpid);
		if(obp != NULL) proc_mux_unlock(&obp->mem.mm.mux);
		proc_unlock_adp(proc);
		if(status != EOK) {
			ProcessBind(0);
			proc_thread_pool_reserve_done();
			return status;
		}

		SETIOV(ctp->iov + 0, addr, nbytes);

		if(msg->type == _IO_READ) {
			status = resmgr_msgwritev(ctp, ctp->iov + 0, 1, 0);
		} else {
			status = resmgr_msgreadv(ctp, ctp->iov + 0, 1, skip);
		}
		err = errno;

		proc_wlock_adp(proc);
		(void) memmgr.munmap(proc, (uintptr_t)addr, size, 0, mempart_getid(proc, sys_memclass_id));
		proc_unlock_adp(proc);

		if(status == -1) {
			ProcessBind(0);
			proc_thread_pool_reserve_done();
			return err;
		}

		*pos += nbytes;
		if(obp && msg->type == _IO_WRITE) {
			obp->mem.pm.mtime = time(0);
		}
		ProcessBind(0);
		proc_thread_pool_reserve_done();
	}

ok:
	_IO_SET_READ_NBYTES(ctp, nbytes);
	return EOK;
}