/*
* Copyright (c) 2008 Antti Kantee. All Rights Reserved.
*
* Development of this software was supported by the
* Research Foundation of Helsinki University of Technology
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
void putterattach(void); /* XXX: from autoconf */
dev_type_open(puttercdopen);
struct ptargs {
int comfd;
int fpfd;
struct filedesc *fdp;
};
#define BUFSIZE (64*1024)
extern int hz;
/*
* Read requests from /dev/puffs and forward them to comfd
*
* XXX: the init detection is really sucky, but let's not
* waste too much energy for a better one here
*/
static void
readthread(void *arg)
{
struct ptargs *pap = arg;
struct file *fp;
register_t rv;
char *buf;
off_t off;
int error, inited;
buf = kmem_alloc(BUFSIZE, KM_SLEEP);
inited = 0;
retry:
kpause(NULL, 0, hz/4, NULL);
for (;;) {
size_t n;
off = 0;
fp = fd_getfile(pap->fpfd);
if (fp == NULL)
error = EINVAL;
else
error = dofileread(pap->fpfd, fp, buf, BUFSIZE,
&off, 0, &rv);
if (error) {
if (error == ENOENT && inited == 0)
goto retry;
if (error == ENXIO)
break;
panic("fileread failed: %d", error);
}
inited = 1;
/*
* Need to write everything to the "kernel" in one chunk,
* so make sure we have it here.
*/
off = 0;
toread = sizeof(struct putter_hdr);
do {
struct rumpuser_iovec iov;
iov.iov_base = buf+off;
iov.iov_len = toread;
error = rumpuser_iovread(pap->comfd, &iov, 1,
RUMPUSER_IOV_NOSEEK, &n);
if (error)
panic("rumpuser_read %zd %d", n, error);
if (n == 0)
goto out;
off += n;
if (off >= sizeof(struct putter_hdr))
toread = phdr->pth_framelen - off;
else
toread = off - sizeof(struct putter_hdr);
} while (toread);