Sat Jul 9 14:46:56 2011 UTC ()
add digital TV framework which implements a subset of Linux DVB APIs


(jmcneill)
diff -r0 -r1.1 src/sys/dev/dtv/Makefile
diff -r0 -r1.1 src/sys/dev/dtv/dtv_buffer.c
diff -r0 -r1.1 src/sys/dev/dtv/dtv_device.c
diff -r0 -r1.1 src/sys/dev/dtv/dtv_ioctl.c
diff -r0 -r1.1 src/sys/dev/dtv/dtv_scatter.c
diff -r0 -r1.1 src/sys/dev/dtv/dtv_scatter.h
diff -r0 -r1.1 src/sys/dev/dtv/dtvif.h
diff -r0 -r1.1 src/sys/dev/dtv/dtvio.h
diff -r0 -r1.1 src/sys/dev/dtv/dtvio_demux.h
diff -r0 -r1.1 src/sys/dev/dtv/dtvio_frontend.h
diff -r0 -r1.1 src/sys/dev/dtv/dtvmodule.h
diff -r0 -r1.1 src/sys/dev/dtv/dtvvar.h
diff -r0 -r1.1 src/sys/dev/dtv/files.dtv

File Added: src/sys/dev/dtv/Makefile
# $NetBSD: Makefile,v 1.1 2011/07/09 14:46:56 jmcneill Exp $

INCSDIR= /usr/include/dev/dtv
INCS=	dtvio.h dtvio_frontend.h dtvio_demux.h

.include <bsd.kinc.mk>

File Added: src/sys/dev/dtv/dtv_buffer.c
/* $NetBSD: dtv_buffer.c,v 1.1 2011/07/09 14:46:56 jmcneill Exp $ */

/*-
 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
 * All rights reserved.
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by Jared D. McNeill.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``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 FOUNDATION 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.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: dtv_buffer.c,v 1.1 2011/07/09 14:46:56 jmcneill Exp $");

#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/vnode.h>
#include <sys/poll.h>
#include <sys/select.h>

#include <dev/dtv/dtvvar.h>

#define	PAGE_ALIGN(a)	(((a) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))

static void
dtv_buffer_write(struct dtv_softc *sc, const uint8_t *buf, size_t buflen)
{
	struct dtv_stream *ds = &sc->sc_stream;
	struct dtv_buffer *db;
	struct dtv_scatter_io sio;
	size_t resid = buflen, avail;
       	off_t offset = 0;

	KASSERT(buflen == TS_PKTLEN);

	while (resid > 0) {
		mutex_enter(&ds->ds_lock);

		if (SIMPLEQ_EMPTY(&ds->ds_ingress)) {
			aprint_debug_dev(sc->sc_dev,
			    "dropping sample (%u)\n", resid);
			mutex_exit(&ds->ds_lock);
			return;
		}

		db = SIMPLEQ_FIRST(&ds->ds_ingress);
		avail = min(db->db_length - db->db_bytesused, resid);
		if (dtv_scatter_io_init(&ds->ds_data,
		    db->db_offset + db->db_bytesused, avail, &sio)) {
			dtv_scatter_io_copyin(&sio, buf + offset);
			db->db_bytesused += (avail - sio.sio_resid);
			offset += (avail - sio.sio_resid);
			resid -= (avail - sio.sio_resid);
		}

		if (db->db_bytesused == db->db_length) {
			SIMPLEQ_REMOVE_HEAD(&ds->ds_ingress, db_entries);
			SIMPLEQ_INSERT_TAIL(&ds->ds_egress, db, db_entries);
			cv_broadcast(&ds->ds_sample_cv);
			selnotify(&ds->ds_sel, 0, 0);
		}

		mutex_exit(&ds->ds_lock);
	}
}

void
dtv_submit_payload(device_t self, const struct dtv_payload *payload)
{
	struct dtv_softc *sc = device_private(self);
	struct dtv_ts *ts = &sc->sc_ts;
	const uint8_t *tspkt;
	unsigned int npkts, i;

	tspkt = payload->data;
	npkts = payload->size / TS_PKTLEN;
	for (i = 0; i < npkts; i++) {
		if (TS_HAS_SYNC(tspkt) && ts->ts_pidfilter[TS_PID(tspkt)]) {
			dtv_buffer_write(sc, tspkt, TS_PKTLEN);
		}
		tspkt += TS_PKTLEN;
	}
}

static struct dtv_buffer *
dtv_buffer_alloc(void)
{
	return kmem_alloc(sizeof(struct dtv_buffer), KM_SLEEP);
}

static void
dtv_buffer_free(struct dtv_buffer *db)
{
	kmem_free(db, sizeof(*db));
}

static int
dtv_buffer_realloc(struct dtv_softc *sc, size_t bufsize)
{
	struct dtv_stream *ds = &sc->sc_stream;
	unsigned int i, nbufs, oldnbufs, minnbufs;
	struct dtv_buffer **oldbuf;
	off_t offset;
	int error;

	nbufs = PAGE_ALIGN(bufsize) / PAGE_SIZE;

	error = dtv_scatter_buf_set_size(&ds->ds_data, bufsize);
	if (error)
		return error;

	oldnbufs = ds->ds_nbufs;
	oldbuf = ds->ds_buf;

	ds->ds_nbufs = nbufs;
	if (nbufs > 0) {
		ds->ds_buf = kmem_alloc(sizeof(struct dtv_buffer *) * nbufs,
		    KM_SLEEP);
		if (ds->ds_buf == NULL) {
			ds->ds_nbufs = oldnbufs;
			ds->ds_buf = oldbuf;
			return ENOMEM;
		}
	} else {
		ds->ds_buf = NULL;
	}

	minnbufs = min(nbufs, oldnbufs);
	for (i = 0; i < minnbufs; i++)
		ds->ds_buf[i] = oldbuf[i];
	for (; i < nbufs; i++)
		ds->ds_buf[i] = dtv_buffer_alloc();
	for (; i < oldnbufs; i++) {
		dtv_buffer_free(oldbuf[i]);
		oldbuf[i] = NULL;
	}
	if (oldbuf != NULL)
		kmem_free(oldbuf, sizeof(struct dtv_buffer *) * oldnbufs);

	offset = 0;
	for (i = 0; i < nbufs; i++) {
		ds->ds_buf[i]->db_offset = offset;
		ds->ds_buf[i]->db_bytesused = 0;
		ds->ds_buf[i]->db_length = PAGE_SIZE;
		offset += PAGE_SIZE;
	}

	return 0;
}

static struct dtv_buffer *
dtv_stream_dequeue(struct dtv_stream *ds)
{
	struct dtv_buffer *db;

	if (!SIMPLEQ_EMPTY(&ds->ds_egress)) {
		db = SIMPLEQ_FIRST(&ds->ds_egress);
		SIMPLEQ_REMOVE_HEAD(&ds->ds_egress, db_entries);
		return db;
	}

	return NULL;
}

static void
dtv_stream_enqueue(struct dtv_stream *ds, struct dtv_buffer *db)
{
	db->db_bytesused = 0;
	SIMPLEQ_INSERT_TAIL(&ds->ds_ingress, db, db_entries);
}

int
dtv_buffer_setup(struct dtv_softc *sc, size_t bufsize)
{
	struct dtv_stream *ds = &sc->sc_stream;
	unsigned int i;
	int error;

	mutex_enter(&ds->ds_lock);

	error = dtv_buffer_realloc(sc, PAGE_ALIGN(bufsize));
	if (error) {
		mutex_exit(&ds->ds_lock);
		return error;
	}

	for (i = 0; i < ds->ds_nbufs; i++)
		dtv_stream_enqueue(ds, ds->ds_buf[i]);

	mutex_exit(&ds->ds_lock);

	return 0;
}

int
dtv_buffer_destroy(struct dtv_softc *sc)
{
	struct dtv_stream *ds = &sc->sc_stream;

	mutex_enter(&ds->ds_lock);

	while (SIMPLEQ_FIRST(&ds->ds_ingress))
		SIMPLEQ_REMOVE_HEAD(&ds->ds_ingress, db_entries);
	while (SIMPLEQ_FIRST(&ds->ds_egress))
		SIMPLEQ_REMOVE_HEAD(&ds->ds_egress, db_entries);
	dtv_buffer_realloc(sc, 0);

	mutex_exit(&ds->ds_lock);

	return 0;
}

int
dtv_buffer_read(struct dtv_softc *sc, struct uio *uio, int flags)
{
	struct dtv_stream *ds = &sc->sc_stream;
	struct dtv_buffer *db;
	struct dtv_scatter_io sio;
	off_t offset;
	size_t len, bread = 0;
	int error;

	while (uio->uio_resid > 0) {
		mutex_enter(&ds->ds_lock);

retry:
		while (SIMPLEQ_EMPTY(&ds->ds_egress)) {
			if (flags & IO_NDELAY) {
				mutex_exit(&ds->ds_lock);
				return bread ? 0 : EWOULDBLOCK;
			}

			error = cv_wait_sig(&ds->ds_sample_cv, &ds->ds_lock);
			if (error) {
				mutex_exit(&ds->ds_lock);
				return EINTR;
			}
		}
		db = SIMPLEQ_FIRST(&ds->ds_egress);

		if (db->db_bytesused == 0) {
			db = dtv_stream_dequeue(ds);
			dtv_stream_enqueue(ds, db);
			ds->ds_bytesread = 0;
			goto retry;
		}

		mutex_exit(&ds->ds_lock);

		len = min(uio->uio_resid, db->db_bytesused - ds->ds_bytesread);
		offset = db->db_offset + ds->ds_bytesread;

		if (dtv_scatter_io_init(&ds->ds_data, offset, len, &sio)) {
			error = dtv_scatter_io_uiomove(&sio, uio);
			if (error == EFAULT)
				return EFAULT;
			ds->ds_bytesread += (len - sio.sio_resid);
			bread += (len - sio.sio_resid);
		}

		if (ds->ds_bytesread >= db->db_bytesused) {
			mutex_enter(&ds->ds_lock);
			db = dtv_stream_dequeue(ds);
			dtv_stream_enqueue(ds, db);
			mutex_exit(&ds->ds_lock);

			ds->ds_bytesread = 0;
		}
	}

	return 0;
}

int
dtv_buffer_poll(struct dtv_softc *sc, int events, lwp_t *l)
{
	struct dtv_stream *ds = &sc->sc_stream;
	int revents = 0;

	mutex_enter(&ds->ds_lock);
	if (!SIMPLEQ_EMPTY(&ds->ds_egress)) {
		revents |= (POLLIN | POLLOUT | POLLPRI);
	} else {
		selrecord(l, &ds->ds_sel);
	}
	mutex_exit(&ds->ds_lock);

	return revents;
}

File Added: src/sys/dev/dtv/dtv_device.c
/* $NetBSD: dtv_device.c,v 1.1 2011/07/09 14:46:56 jmcneill Exp $ */

/*-
 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
 * All rights reserved.
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by Jared D. McNeill.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``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 FOUNDATION 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.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: dtv_device.c,v 1.1 2011/07/09 14:46:56 jmcneill Exp $");

#include <sys/types.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/atomic.h>
#include <sys/module.h>
#include <sys/poll.h>
#include <sys/select.h>

#include <dev/dtv/dtvvar.h>
#include <dev/dtv/dtvmodule.h>

MODULE(MODULE_CLASS_DRIVER, dtv, NULL);

static dev_type_open(dtvopen);
static dev_type_close(dtvclose);
static dev_type_read(dtvread);
static dev_type_ioctl(dtvioctl);
static dev_type_poll(dtvpoll);

const struct cdevsw dtv_cdevsw = {
	.d_open = dtvopen,
	.d_close = dtvclose,
	.d_read = dtvread,
	.d_ioctl = dtvioctl,
	.d_poll = dtvpoll,
	.d_flag = D_OTHER|D_MPSAFE,
};

static int	dtv_match(device_t, cfdata_t, void *);
static void	dtv_attach(device_t, device_t, void *);
static int	dtv_detach(device_t, int);

CFATTACH_DECL_NEW(dtv,
    sizeof(struct dtv_softc),
    dtv_match,
    dtv_attach,
    dtv_detach,
    NULL
);

static int
dtv_match(device_t parent, cfdata_t cfdata, void *aa)
{
	return 1;
}

static void
dtv_attach(device_t parent, device_t self, void *aa)
{
	struct dtv_attach_args *daa = aa;
	struct dtv_softc *sc = device_private(self);
	struct dtv_stream *ds = &sc->sc_stream;
	struct dvb_frontend_info info;

	sc->sc_dev = self;
	sc->sc_hw = daa->hw;
	sc->sc_priv = daa->priv;
	atomic_swap_uint(&sc->sc_open, 0);

	ds->ds_nbufs = 0;
	ds->ds_buf = NULL;
	SIMPLEQ_INIT(&ds->ds_ingress);
	SIMPLEQ_INIT(&ds->ds_egress);
	mutex_init(&ds->ds_lock, MUTEX_DEFAULT, IPL_VM);
	cv_init(&ds->ds_sample_cv, "dtv");
	selinit(&ds->ds_sel);
	dtv_scatter_buf_init(&ds->ds_data);

	dtv_device_get_devinfo(sc, &info);

	aprint_naive("\n");
	aprint_normal(": '%s'", info.name);
	switch (info.type) {
	case FE_QPSK:
		aprint_normal(" [QPSK]");
		break;
	case FE_QAM:
		aprint_normal(" [QAM]");
		break;
	case FE_OFDM:
		aprint_normal(" [OFDM]");
		break;
	case FE_ATSC:
		aprint_normal(" [ATSC]");
		break;
	}
	aprint_normal("\n");
}

static int
dtv_detach(device_t self, int flags)
{
	struct dtv_softc *sc = device_private(self);
	struct dtv_stream *ds = &sc->sc_stream;

	cv_destroy(&ds->ds_sample_cv);
	mutex_destroy(&ds->ds_lock);
	seldestroy(&ds->ds_sel);
	dtv_scatter_buf_destroy(&ds->ds_data);

	return 0;
}

static int
dtv_modcmd(modcmd_t cmd, void *arg)
{
	int error, bmaj = -1, cmaj = -1;

	switch (cmd) {
	case MODULE_CMD_INIT:
		error = config_init_component(cfdriver_ioconf_dtv,
		    cfattach_ioconf_dtv, cfdata_ioconf_dtv);
		if (error)
			return error;
		error = devsw_attach("dtv", NULL, &bmaj, &dtv_cdevsw, &cmaj);
		if (error)
			config_fini_component(cfdriver_ioconf_dtv,
			    cfattach_ioconf_dtv, cfdata_ioconf_dtv);
		return error;
	case MODULE_CMD_FINI:
		devsw_detach(NULL, &dtv_cdevsw);
		return config_fini_component(cfdriver_ioconf_dtv,
		    cfattach_ioconf_dtv, cfdata_ioconf_dtv);
	default:
		return ENOTTY;
	}
}

static int
dtvopen(dev_t dev, int flags, int mode, lwp_t *l)
{
	struct dtv_softc *sc;
	struct dtv_ts *ts;
	unsigned int n;
	int error;

	if ((sc = device_lookup_private(&dtv_cd, DTVUNIT(dev))) == NULL)
		return ENXIO;
	if (sc->sc_dying == true)
		return ENODEV;
	ts = &sc->sc_ts;

	n = atomic_cas_uint(&sc->sc_open, 0, 1);
	if (n == 0) {
		error = dtv_device_open(sc, flags);
		if (error) {
			atomic_swap_uint(&sc->sc_open, 0);
			return error;
		}
		sc->sc_bufsize = DTV_DEFAULT_BUFSIZE;
		sc->sc_bufsize_chg = true;
		memset(ts->ts_pidfilter, 0, sizeof(ts->ts_pidfilter));
	}

	return 0;
}

static int
dtvclose(dev_t dev, int flags, int mode, lwp_t *l)
{
	struct dtv_softc *sc;

	if ((sc = device_lookup_private(&dtv_cd, DTVUNIT(dev))) == NULL)
		return ENXIO;

	dtv_device_close(sc);
	dtv_buffer_destroy(sc);
	atomic_swap_uint(&sc->sc_open, 0);

	return 0;
}

static int
dtvread(dev_t dev, struct uio *uio, int flags)
{
	struct dtv_softc *sc;

	if ((sc = device_lookup_private(&dtv_cd, DTVUNIT(dev))) == NULL)
		return ENXIO;

	if (ISDTVDVR(dev))
		return dtv_buffer_read(sc, uio, flags);

	return ENXIO;
}

static int
dtvioctl(dev_t dev, u_long cmd, void *ptr, int flags, lwp_t *l)
{
	struct dtv_softc *sc;

	if ((sc = device_lookup_private(&dtv_cd, DTVUNIT(dev))) == NULL)
		return ENXIO;

	if (ISDTVFRONTEND(dev)) {
		return dtv_frontend_ioctl(sc, cmd, ptr, flags);
	} else if (ISDTVDEMUX(dev)) {
		return dtv_demux_ioctl(sc, cmd, ptr, flags);
	}

	return EINVAL;
}

static int
dtvpoll(dev_t dev, int events, lwp_t *l)
{
	struct dtv_softc *sc;

	if ((sc = device_lookup_private(&dtv_cd, DTVUNIT(dev))) == NULL)
		return POLLERR;

	if (ISDTVFRONTEND(dev)) {
		return POLLPRI|POLLIN; /* XXX event */
	} else if (ISDTVDEMUX(dev)) {
		return POLLIN|POLLOUT; /* XXX */
	} else if (ISDTVDVR(dev)) {
		return dtv_buffer_poll(sc, events, l);
	}

	printf("%s: DTVDEV = 0x%x, events = 0x%x\n",
	    __func__, DTVDEV(dev), events);

	return POLLERR;
}

int
dtv_print(void *arg, const char *pnp)
{
	if (pnp)
		aprint_normal("dtv at %s", pnp);

	return UNCONF;
}

File Added: src/sys/dev/dtv/dtv_ioctl.c
/* $NetBSD: dtv_ioctl.c,v 1.1 2011/07/09 14:46:56 jmcneill Exp $ */

/*-
 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
 * All rights reserved.
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by Jared D. McNeill.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``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 FOUNDATION 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.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: dtv_ioctl.c,v 1.1 2011/07/09 14:46:56 jmcneill Exp $");

#include <sys/param.h>
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/kmem.h>
#include <sys/device.h>
#include <sys/select.h>

#include <dev/dtv/dtvvar.h>

int
dtv_frontend_ioctl(struct dtv_softc *sc, u_long cmd, void *data, int flags)
{
	switch (cmd) {
	case FE_READ_STATUS:
		*(fe_status_t *)data = dtv_device_get_status(sc);
		return 0;
	case FE_READ_BER:
		*(uint32_t *)data = 0;	/* XXX TODO */
		return 0;
	case FE_READ_SNR:
		*(uint16_t *)data = dtv_device_get_snr(sc);
		return 0;
	case FE_READ_SIGNAL_STRENGTH:
		*(uint16_t *)data = dtv_device_get_signal_strength(sc);
		return 0;
	case FE_SET_FRONTEND:
		return dtv_device_set_tuner(sc, data);
	case FE_GET_INFO:
		dtv_device_get_devinfo(sc, data);
		return 0;
	default:
		return EINVAL;
	}
}

int
dtv_demux_ioctl(struct dtv_softc *sc, u_long cmd, void *data, int flags)
{
	struct dmx_pes_filter_params *pesfilt;
	uint16_t pid;
	size_t bufsize;
	int error;

	switch (cmd) {
	case DMX_START:
		if (sc->sc_bufsize_chg) {
			if ((error = dtv_buffer_setup(sc, sc->sc_bufsize)) != 0)
				return error;
			sc->sc_bufsize_chg = false;
		}
		return dtv_device_start_transfer(sc);
	case DMX_STOP:
		return dtv_device_stop_transfer(sc);
	case DMX_SET_BUFFER_SIZE:
		bufsize = *(uintptr_t *)data;
		if (bufsize >= DTV_DEFAULT_BUFSIZE &&
		    sc->sc_bufsize != bufsize) {
			sc->sc_bufsize = bufsize;
			sc->sc_bufsize_chg = true;
		}
		return 0;
	case DMX_SET_PES_FILTER:
		pesfilt = data;

		if (pesfilt->input != DMX_IN_FRONTEND)
			return EINVAL;
		if (pesfilt->output != DMX_OUT_TS_TAP)
			return EINVAL;
		if (pesfilt->pes_type != DMX_PES_OTHER)
			return EINVAL;

		error = dtv_demux_ioctl(sc, DMX_ADD_PID, &pesfilt->pid, flags);
		if (error)
			return error;

		if (pesfilt->flags & DMX_IMMEDIATE_START) {
			error = dtv_demux_ioctl(sc, DMX_START, NULL, flags);
			if (error)
				return error;
		}
		return 0;
	case DMX_ADD_PID:
		pid = *(uint16_t *)data;
		if (pid > 0x2000)
			return EINVAL;

		if (pid == 0x2000) {
			memset(sc->sc_ts.ts_pidfilter, 1,
			    sizeof(sc->sc_ts.ts_pidfilter));
		} else {
			sc->sc_ts.ts_pidfilter[pid] = 1;
		}
		return 0;
	case DMX_REMOVE_PID:
		pid = *(uint16_t *)data;
		if (pid > 0x2000)
			return EINVAL;

		if (pid == 0x2000) {
			memset(sc->sc_ts.ts_pidfilter, 0,
			    sizeof(sc->sc_ts.ts_pidfilter));
		} else {
			sc->sc_ts.ts_pidfilter[pid] = 0;
		}
		return 0;
	default:
		return EINVAL;
	}
}

File Added: src/sys/dev/dtv/dtv_scatter.c
/* $NetBSD: dtv_scatter.c,v 1.1 2011/07/09 14:46:56 jmcneill Exp $ */

/*
 * Copyright (c) 2008 Patrick Mahoney <pat@polycrystal.org>
 * All rights reserved.
 *
 * This code was written by Patrick Mahoney (pat@polycrystal.org) as
 * part of Google Summer of Code 2008.
 *
 * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``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 FOUNDATION 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.
 */

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: dtv_scatter.c,v 1.1 2011/07/09 14:46:56 jmcneill Exp $");

#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <sys/vnode.h>
#include <sys/poll.h>
#include <sys/select.h>
#include <sys/kmem.h>
#include <sys/pool.h>
#include <sys/conf.h>
#include <sys/types.h>
#include <sys/device.h>
#include <sys/condvar.h>
#include <sys/queue.h>

#include <dev/dtv/dtvvar.h>

#define IPL_DTV		IPL_VM
#define spldtv()	splvm()

void
dtv_scatter_buf_init(struct dtv_scatter_buf *sb)
{
	sb->sb_pool = pool_cache_init(PAGE_SIZE, 0, 0, 0,
				      "dtvscatter", NULL, IPL_DTV,
				      NULL, NULL, NULL);
	sb->sb_size = 0;
	sb->sb_npages = 0;
	sb->sb_page_ary = NULL;
}

void
dtv_scatter_buf_destroy(struct dtv_scatter_buf *sb)
{
	/* Do we need to return everything to the pool first? */
	dtv_scatter_buf_set_size(sb, 0);
	pool_cache_destroy(sb->sb_pool);
	sb->sb_pool = 0;
	sb->sb_npages = 0;
	sb->sb_page_ary = NULL;
}

/* Increase or decrease the size of the buffer */
int
dtv_scatter_buf_set_size(struct dtv_scatter_buf *sb, size_t sz)
{
	unsigned int i;
	size_t npages, minpages, oldnpages;
	uint8_t **old_ary;

	npages = (sz >> PAGE_SHIFT) + ((sz & PAGE_MASK) > 0);
	
	if (sb->sb_npages == npages) {
		return 0;
	}

	oldnpages = sb->sb_npages;
	old_ary = sb->sb_page_ary;

	sb->sb_npages = npages;
	if (npages > 0) {
		sb->sb_page_ary =
		    kmem_alloc(sizeof(uint8_t *) * npages, KM_SLEEP);
		if (sb->sb_page_ary == NULL) {
			sb->sb_npages = oldnpages;
			sb->sb_page_ary = old_ary;
			return ENOMEM;
		}
	} else {
		sb->sb_page_ary = NULL;
	}

	minpages = min(npages, oldnpages);
	/* copy any pages that will be reused */
	for (i = 0; i < minpages; ++i)
		sb->sb_page_ary[i] = old_ary[i];
	/* allocate any new pages */
	for (; i < npages; ++i) {
		sb->sb_page_ary[i] = pool_cache_get(sb->sb_pool, 0);
		/* TODO: does pool_cache_get return NULL on
		 * ENOMEM?  If so, we need to release or note
		 * the pages with did allocate
		 * successfully. */
		if (sb->sb_page_ary[i] == NULL) {
			return ENOMEM;
		}
	}
	/* return any pages no longer needed */
	for (; i < oldnpages; ++i)
		pool_cache_put(sb->sb_pool, old_ary[i]);

	if (old_ary != NULL)
		kmem_free(old_ary, sizeof(uint8_t *) * oldnpages);

	sb->sb_size = sb->sb_npages << PAGE_SHIFT;
	
	return 0;
}


paddr_t
dtv_scatter_buf_map(struct dtv_scatter_buf *sb, off_t off)
{
	size_t pg;
	paddr_t pa;
	
	pg = off >> PAGE_SHIFT;

	if (pg >= sb->sb_npages)
		return -1;
	else if (!pmap_extract(pmap_kernel(), (vaddr_t)sb->sb_page_ary[pg], &pa))
		return -1;

	return atop(pa);
}

/* Initialize data for an io operation on a scatter buffer. Returns
 * true if the transfer is valid, or false if out of range. */
bool
dtv_scatter_io_init(struct dtv_scatter_buf *sb,
		    off_t off, size_t len,
		    struct dtv_scatter_io *sio)
{
	if ((off + len) > sb->sb_size) {
		printf("dtv: %s failed: off=%" PRId64
			 " len=%zu sb->sb_size=%zu\n",
			 __func__, off, len, sb->sb_size);
		return false;
	}

	sio->sio_buf = sb;
	sio->sio_offset = off;
	sio->sio_resid = len;

	return true;
}

/* Store the pointer and size of the next contiguous segment.  Returns
 * true if the segment is valid, or false if all has been transfered.
 * Does not check for overflow. */
bool
dtv_scatter_io_next(struct dtv_scatter_io *sio, void **p, size_t *sz)
{
	size_t pg, pgo;

	if (sio->sio_resid == 0)
		return false;
	
	pg = sio->sio_offset >> PAGE_SHIFT;
	pgo = sio->sio_offset & PAGE_MASK;

	*sz = min(PAGE_SIZE - pgo, sio->sio_resid);
	*p = sio->sio_buf->sb_page_ary[pg] + pgo;

	sio->sio_offset += *sz;
	sio->sio_resid -= *sz;

	return true;
}

/* Semi-undo of a failed segment copy.  Updates the scatter_io
 * struct to the previous values prior to a failed segment copy. */
void
dtv_scatter_io_undo(struct dtv_scatter_io *sio, size_t sz)
{
	sio->sio_offset -= sz;
	sio->sio_resid += sz;
}

/* Copy data from src into the scatter_buf as described by io. */
void
dtv_scatter_io_copyin(struct dtv_scatter_io *sio, const void *p)
{
	void *dst;
	const uint8_t *src = p;
	size_t sz;

	while (dtv_scatter_io_next(sio, &dst, &sz)) {
		memcpy(dst, src, sz);
		src += sz;
	}
}

/* --not used; commented to avoid compiler warnings--
void
dtv_scatter_io_copyout(struct dtv_scatter_io *sio, void *p)
{
	void *src;
	uint8_t *dst = p;
	size_t sz;

	while (dtv_scatter_io_next(sio, &src, &sz)) {
		memcpy(dst, src, sz);
		dst += sz;
	}
}
*/

/* Performat a series of uiomove calls on a scatter buf.  Returns
 * EFAULT if uiomove EFAULTs on the first segment.  Otherwise, returns
 * an incomplete transfer but with no error. */
int
dtv_scatter_io_uiomove(struct dtv_scatter_io *sio, struct uio *uio)
{
	void *p;
	size_t sz;
	bool first = true;
	int err;
	
	while (dtv_scatter_io_next(sio, &p, &sz)) {
		err = uiomove(p, sz, uio);
		if (err == EFAULT) {
			dtv_scatter_io_undo(sio, sz);
			if (first)
				return EFAULT;
			else
				return 0;
		}
		first = false;
	}

	return 0;
}

File Added: src/sys/dev/dtv/dtv_scatter.h
/* $NetBSD: dtv_scatter.h,v 1.1 2011/07/09 14:46:56 jmcneill Exp $ */

/*-
 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
 * All rights reserved.
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by Jared D. McNeill.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``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 FOUNDATION 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.
 */

#ifndef _DEV_DTV_DTV_SCATTER_H
#define _DEV_DTV_DTV_SCATTER_H

#include <sys/pool.h>

struct dtv_scatter_buf {
	pool_cache_t	sb_pool;
	size_t		sb_size;    /* size in bytes */
	size_t		sb_npages;  /* number of pages */
	uint8_t		**sb_page_ary; /* array of page pointers */
};

struct dtv_scatter_io {
	struct dtv_scatter_buf *sio_buf;
	off_t		sio_offset;
	size_t		sio_resid;
};

void	dtv_scatter_buf_init(struct dtv_scatter_buf *);
void	dtv_scatter_buf_destroy(struct dtv_scatter_buf *);
int	dtv_scatter_buf_set_size(struct dtv_scatter_buf *, size_t);
paddr_t	dtv_scatter_buf_map(struct dtv_scatter_buf *, off_t);

bool	dtv_scatter_io_init(struct dtv_scatter_buf *, off_t, size_t,
			    struct dtv_scatter_io *);
bool	dtv_scatter_io_next(struct dtv_scatter_io *, void **, size_t *);
void	dtv_scatter_io_undo(struct dtv_scatter_io *, size_t);
void	dtv_scatter_io_copyin(struct dtv_scatter_io *, const void *);
/* void	dtv_scatter_io_copyout(struct dtv_scatter_io *, void *); */
int	dtv_scatter_io_uiomove(struct dtv_scatter_io *, struct uio *);

#endif /* !_DEV_DTV_DTV_SCATTER_H */

File Added: src/sys/dev/dtv/dtvif.h
/* $NetBSD: dtvif.h,v 1.1 2011/07/09 14:46:56 jmcneill Exp $ */

/*-
 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
 * All rights reserved.
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by Jared D. McNeill.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``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 FOUNDATION 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.
 */

#ifndef _DEV_DTV_DTVIF_H
#define _DEV_DTV_DTVIF_H

#include <dev/dtv/dtvio.h>

#define	DTV_DEVICE_FRONTEND	0
#define	DTV_DEVICE_DEMUX	1
#define	DTV_DEVICE_DVR		2

#define	DTV_NUM_DEVICES		3

#define	DTVUNIT(x)		(minor(x) & 0x0f)
#define	DTVDEV(x)		((minor(x) & 0xf0) >> 4)

#define	ISDTVFRONTEND(x)	(DTVDEV((x)) == DTV_DEVICE_FRONTEND)
#define	ISDTVDEMUX(x)		(DTVDEV((x)) == DTV_DEVICE_DEMUX)
#define	ISDTVDVR(x)		(DTVDEV((x)) == DTV_DEVICE_DVR)

struct dtv_hw_if {
	void		(*get_devinfo)(void *, struct dvb_frontend_info *);

	int		(*open)(void *, int);
	void		(*close)(void *);
	int		(*set_tuner)(void *, const struct dvb_frontend_parameters *);
	fe_status_t	(*get_status)(void *);
	uint16_t	(*get_signal_strength)(void *);
	uint16_t	(*get_snr)(void *);
	int		(*start_transfer)(void *);
	int		(*stop_transfer)(void *);
};

struct dtv_attach_args {
	const struct dtv_hw_if *hw;
	void *priv;
};

struct dtv_payload {
	const uint8_t	*data;
	size_t		size;
};

int	dtv_print(void *, const char *);

void	dtv_submit_payload(device_t, const struct dtv_payload *);

#endif /* !_DEV_DTV_DTVIF_H */

File Added: src/sys/dev/dtv/dtvio.h
/* $NetBSD: dtvio.h,v 1.1 2011/07/09 14:46:56 jmcneill Exp $ */

/*-
 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
 * All rights reserved.
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by Jared D. McNeill.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``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 FOUNDATION 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.
 */

#ifndef _DEV_DTV_DTVIO_H
#define _DEV_DTV_DTVIO_H

#define	DVB_API_VERSION		5
#define	DVB_API_VERSION_MINOR	2

#include <sys/types.h>
#include <dev/dtv/dtvio_frontend.h>
#include <dev/dtv/dtvio_demux.h>

#endif /* !_DEV_DTV_DTVIO_H */

File Added: src/sys/dev/dtv/dtvio_demux.h
/* $NetBSD: dtvio_demux.h,v 1.1 2011/07/09 14:46:56 jmcneill Exp $ */

/*-
 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
 * All rights reserved.
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by Jared D. McNeill.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``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 FOUNDATION 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.
 */

#ifndef _DEV_DTV_DTVIO_DEMUX_H
#define _DEV_DTV_DTVIO_DEMUX_H

#include <sys/ioccom.h>

/*
 * DVB Demux API
 */

typedef enum {
	DMX_OUT_DECODER,
	DMX_OUT_TAP,
	DMX_OUT_TS_TAP,
	DMX_OUT_TSDEMUX_TAP,
} dmx_output_t;

typedef enum {
	DMX_IN_FRONTEND,
	DMX_IN_DVR,
} dmx_input_t;

typedef enum {
	DMX_PES_AUDIO0,
	DMX_PES_VIDEO0,
	DMX_PES_TELETEXT0,
	DMX_PES_SUBTITLE0,
	DMX_PES_PCR0,

	DMX_PES_AUDIO1,
	DMX_PES_VIDEO1,
	DMX_PES_TELETEXT1,
	DMX_PES_SUBTITLE1,
	DMX_PES_PCR1,

	DMX_PES_AUDIO2,
	DMX_PES_VIDEO2,
	DMX_PES_TELETEXT2,
	DMX_PES_SUBTITLE2,
	DMX_PES_PCR2,

	DMX_PES_AUDIO3,
	DMX_PES_VIDEO3,
	DMX_PES_TELETEXT3,
	DMX_PES_SUBTITLE3,
	DMX_PES_PCR3,

	DMX_PES_OTHER,
} dmx_pes_type_t;

#define	DMX_FILTER_SIZE	16

typedef struct dmx_filter {
	uint8_t		filter[DMX_FILTER_SIZE];
	uint8_t		mask[DMX_FILTER_SIZE];
	uint8_t		mode[DMX_FILTER_SIZE];
} dmx_filter_t;

struct dmx_sct_filter_params {
	uint16_t	pid;
	dmx_filter_t	filter;
	uint32_t	timeout;
	uint32_t	flags;
#define	DMX_CHECK_CRC		0x0001
#define	DMX_ONESHOT		0x0002
#define	DMX_IMMEDIATE_START	0x0004
#define	DMX_KERNEL_CLIENT	0x8000
};

struct dmx_pes_filter_params {
	uint16_t	pid;
	dmx_input_t	input;
	dmx_output_t	output;
	dmx_pes_type_t	pes_type;
	uint32_t	flags;
};

struct dmx_stc {
	unsigned int	num;
	unsigned int	base;
	uint64_t	stc;
};

typedef struct dmx_caps {
	uint32_t	caps;
	int		num_decoders;
} dmx_caps_t;

typedef enum {
	DMX_SOURCE_FRONT0 = 0,
	DMX_SOURCE_FRONT1,
	DMX_SOURCE_FRONT2,
	DMX_SOURCE_FRONT3,
	DMX_SOURCE_DVR0 = 16,
	DMX_SOURCE_DVR1,
	DMX_SOURCE_DVR2,
	DMX_SOURCE_DVR3,
} dmx_source_t;

#define	DMX_START		   _IO('D', 100)
#define	DMX_STOP		   _IO('D', 101)
#define	DMX_SET_FILTER		   _IOW('D', 102, struct dmx_sct_filter_params)
#define	DMX_SET_PES_FILTER	   _IOW('D', 103, struct dmx_pes_filter_params)
#define	DMX_SET_BUFFER_SIZE	   _IO('D', 104)
#define	DMX_GET_STC		   _IOWR('D', 105, struct dmx_stc)
#define	DMX_ADD_PID		   _IOW('D', 106, uint16_t)
#define	DMX_REMOVE_PID		   _IOW('D', 107, uint16_t)
#define	DMX_GET_CAPS		   _IOR('D', 108, dmx_caps_t)
#define	DMX_SET_SOURCE		   _IOW('D', 109, dmx_source_t)

#endif /* !_DEV_DTV_DTVIO_DEMUX_H */

File Added: src/sys/dev/dtv/dtvio_frontend.h
/* $NetBSD: dtvio_frontend.h,v 1.1 2011/07/09 14:46:56 jmcneill Exp $ */

/*-
 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
 * All rights reserved.
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by Jared D. McNeill.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``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 FOUNDATION 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.
 */

#ifndef _DEV_DTV_DTVIO_FRONTEND_H
#define _DEV_DTV_DTVIO_FRONTEND_H

#include <sys/ioccom.h>

/*
 * DVB Frontend API
 */

/* Frontend types */
typedef enum fe_type {
	FE_QPSK,	/* DVB-S */
	FE_QAM,		/* DVB-C annex A/C */
	FE_OFDM,	/* DVB-T */
	FE_ATSC,	/* ATSC or DVB-C annex B */
} fe_type_t;

/* Frontend capabilities */
typedef enum fe_caps {
	FE_IS_STUPID			= 0,
	FE_CAN_INVERSION_AUTO		= 0x1,
	FE_CAN_FEC_1_2			= 0x2,
	FE_CAN_FEC_2_3			= 0x4,
	FE_CAN_FEC_3_4			= 0x8,
	FE_CAN_FEC_4_5			= 0x10,
	FE_CAN_FEC_5_6			= 0x20,
	FE_CAN_FEC_6_7			= 0x40,
	FE_CAN_FEC_7_8			= 0x80,
	FE_CAN_FEC_8_9			= 0x100,
	FE_CAN_FEC_AUTO			= 0x200,
	FE_CAN_QPSK			= 0x400,
	FE_CAN_QAM_16			= 0x800,
	FE_CAN_QAM_32			= 0x1000,
	FE_CAN_QAM_64			= 0x2000,
	FE_CAN_QAM_128			= 0x4000,
	FE_CAN_QAM_256			= 0x8000,
	FE_CAN_QAM_AUTO			= 0x10000,
	FE_CAN_TRANSMISSION_MODE_AUTO	= 0x20000,
	FE_CAN_BANDWIDTH_AUTO		= 0x40000,
	FE_CAN_GUARD_INTERVAL_AUTO	= 0x80000,
	FE_CAN_HIERARCHY_AUTO		= 0x100000,
	FE_CAN_8VSB			= 0x200000,
	FE_CAN_16VSB			= 0x400000,
	FE_HAS_EXTENDED_CAPS		= 0x800000,
	FE_CAN_TURBO_FEC		= 0x8000000,
	FE_CAN_2G_MODULATION		= 0x10000000,
	FE_NEEDS_BENDING		= 0x20000000,
	FE_CAN_RECOVER			= 0x40000000,
	FE_CAN_MUTE_TS			= 0x80000000,
} fe_caps_t;

/* Frontend information */
struct dvb_frontend_info {
	char		name[128];
	fe_type_t	type;
	uint32_t	frequency_min;
	uint32_t	frequency_max;
	uint32_t	frequency_stepsize;
	uint32_t	frequency_tolerance;
	uint32_t	symbol_rate_min;
	uint32_t	symbol_rate_max;
	uint32_t	symbol_rate_tolerance;	/* ppm */
	uint32_t	notifier_delay;		/* ms */
	fe_caps_t	caps;
};

/* Frontend status */
typedef enum fe_status {
	FE_HAS_SIGNAL	= 0x01,	/* found something above the noise level */
	FE_HAS_CARRIER	= 0x02,	/* found a DVB signal */
	FE_HAS_VITERBI	= 0x04,	/* FEC is stable */
	FE_HAS_SYNC	= 0x08,	/* found sync bytes */
	FE_HAS_LOCK	= 0x10,	/* everything's working... */
	FE_TIMEDOUT	= 0x20,	/* no lock within the last ~2 seconds */
	FE_REINIT	= 0x40,	/* frontend was reinitialized */
} fe_status_t;

/* Frontend spectral inversion */
typedef enum fe_spectral_inversion {
	INVERSION_OFF,
	INVERSION_ON,
	INVERSION_AUTO,
} fe_spectral_inversion_t;

/* Frontend code rate */
typedef enum fe_code_rate {
	FEC_NONE = 0,
	FEC_1_2,
	FEC_2_3,
	FEC_3_4,
	FEC_4_5,
	FEC_5_6,
	FEC_6_7,
	FEC_7_8,
	FEC_8_9,
	FEC_AUTO,
	FEC_3_5,
	FEC_9_10,
} fe_code_rate_t;

/* Frontend modulation type for QAM, OFDM, and VSB */
typedef enum fe_modulation {
	QPSK,
	QAM_16,
	QAM_32,
	QAM_64,
	QAM_128,
	QAM_256,
	QAM_AUTO,
	VSB_8,
	VSB_16,
	PSK_8,
	APSK_16,
	APSK_32,
	DQPSK,
} fe_modulation_t;

/* Number of carriers per channel */
typedef enum fe_transmit_mode {
	TRANSMISSION_MODE_2K,
	TRANSMISSION_MODE_8K,
	TRANSMISSION_MODE_AUTO,
	TRANSMISSION_MODE_4K,
	TRANSMISSION_MODE_1K,
	TRANSMISSION_MODE_16K,
	TRANSMISSION_MODE_32K,
} fe_transmit_mode_t;

/* Frontend bandwidth */
typedef enum fe_bandwidth {
	BANDWIDTH_8_MHZ,
	BANDWIDTH_7_MHZ,
	BANDWIDTH_6_MHZ,
	BANDWIDTH_AUTO,
	BANDWIDTH_5_MHZ,
	BANDWIDTH_10_MHZ,
	BANDWIDTH_1_172_MHZ,
} fe_bandwidth_t;

/* Frontend guard interval */
typedef enum fe_guard_interval {
	GUARD_INTERVAL_1_32,
	GUARD_INTERVAL_1_16,
	GUARD_INTERVAL_1_8,
	GUARD_INTERVAL_1_4,
	GUARD_INTERVAL_AUTO,
	GUARD_INTERVAL_1_128,
	GUARD_INTERVAL_19_128,
	GUARD_INTERVAL_19_256,
} fe_guard_interval_t;

/* Frontend hierarchy */
typedef enum fe_hierarchy {
	HIERARCHY_NONE,
	HIERARCHY_1,
	HIERARCHY_2,
	HIERARCHY_4,
	HIERARCHY_AUTO
} fe_hierarchy_t;

/* QPSK parameters */
struct dvb_qpsk_parameters {
	uint32_t	symbol_rate;
	fe_code_rate_t	fec_inner;
};

/* QAM parameters */
struct dvb_qam_parameters {
	uint32_t	symbol_rate;
	fe_code_rate_t	fec_inner;
	fe_modulation_t	modulation;
};

/* VSB parameters */
struct dvb_vsb_parameters {
	fe_modulation_t	modulation;
};

/* OFDM parameters */
struct dvb_ofdm_parameters {
	fe_bandwidth_t		bandwidth;
	fe_code_rate_t		code_rate_HP;
	fe_code_rate_t		code_rate_LP;
	fe_modulation_t		constellation;
	fe_transmit_mode_t	transmission_mode;
	fe_guard_interval_t	guard_interval;
	fe_hierarchy_t		hierarchy_information;
};

/* Frontend parameters */
struct dvb_frontend_parameters {
	uint32_t		frequency;
	fe_spectral_inversion_t	inversion;
	union {
		struct dvb_qpsk_parameters	qpsk;
		struct dvb_qam_parameters	qam;
		struct dvb_ofdm_parameters	ofdm;
		struct dvb_vsb_parameters	vsb;
	} u;
};

/* Frontend events */
struct dvb_frontend_event {
	fe_status_t			status;
	struct dvb_frontend_parameters	parameters;
};

/* DiSEqC master command */
struct dvb_diseqc_master_cmd {
	uint8_t		msg[6];
	uint8_t		msg_len;
};

/* DiSEqC slave reply */
struct dvb_diseqc_slave_reply {
	uint8_t		msg[4];
	uint8_t		msg_len;
	int		timeout;
};

/* SEC voltage */
typedef enum fe_sec_voltage {
	SEC_VOLTAGE_13,
	SEC_VOLTAGE_18,
} fe_sec_voltage_t;

/* SEC continuous tone */
typedef enum fe_sec_tone_mode {
	SEC_TONE_ON,
	SEC_TONE_OFF,
} fe_sec_tone_mode_t;

/* SEC tone burst */
typedef enum fe_sec_mini_cmd {
	SEC_MINI_A,
	SEC_MINI_B,
} fe_sec_mini_cmd_t;

#define	FE_READ_STATUS		   _IOR('D', 0, fe_status_t)
#define	FE_READ_BER		   _IOR('D', 1, uint32_t)
#define	FE_READ_SNR		   _IOR('D', 2, uint16_t)
#define	FE_READ_SIGNAL_STRENGTH	   _IOR('D', 3, uint16_t)
#define	FE_READ_UNCORRECTED_BLOCKS _IOR('D', 4, uint32_t)
#define	FE_SET_FRONTEND		   _IOWR('D', 5, struct dvb_frontend_parameters)
#define	FE_GET_FRONTEND		   _IOR('D', 6, struct dvb_frontend_parameters)
#define	FE_GET_EVENT		   _IOR('D', 7, struct dvb_frontend_event)
#define	FE_GET_INFO		   _IOR('D', 8, struct dvb_frontend_info)
#define	FE_DISEQC_RESET_OVERLOAD   _IO('D', 9)
#define	FE_DISEQC_SEND_MASTER_CMD  _IOW('D', 10, struct dvb_diseqc_master_cmd)
#define	FE_DISEQC_RECV_SLAVE_REPLY _IOR('D', 11, struct dvb_diseqc_slave_reply)
#define	FE_DISEQC_SEND_BURST	   _IOW('D', 12, fe_sec_mini_cmd_t)
#define	FE_SET_TONE		   _IOW('D', 13, fe_sec_tone_mode_t)
#define	FE_SET_VOLTAGE		   _IOW('D', 14, fe_sec_voltage_t)
#define	FE_ENABLE_HIGH_LNB_VOLTAGE _IOW('D', 15, int)
#define	FE_SET_FRONTEND_TUNE_MODE  _IOW('D', 16, unsigned int)
#define	FE_DISHNETWORK_SEND_LEGACY_CMD _IOW('D', 17, unsigned long)

#endif /* !_DEV_DTV_DTVIO_FRONTEND_H */

File Added: src/sys/dev/dtv/Attic/dtvmodule.h
/* $NetBSD: dtvmodule.h,v 1.1 2011/07/09 14:46:56 jmcneill Exp $ */

/*-
 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
 * All rights reserved.
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by Jared D. McNeill.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``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 FOUNDATION 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.
 */

#ifndef _DEV_DTV_DTVMODULE_H
#define _DEV_DTV_DTVMODULE_H

#ifdef _MODULE
#include "ioconf.c"
#else
#define config_init_component(xxx)	0
#define	config_fini_component(xxx)	0
#endif

#endif /* !_DEV_DTV_DTVMODULE_H */

File Added: src/sys/dev/dtv/dtvvar.h
/* $NetBSD: dtvvar.h,v 1.1 2011/07/09 14:46:56 jmcneill Exp $ */

/*-
 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
 * All rights reserved.
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *        This product includes software developed by Jared D. McNeill.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``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 FOUNDATION 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.
 */

#ifndef _DEV_DTV_DTVVAR_H
#define _DEV_DTV_DTVVAR_H

#include <dev/dtv/dtvif.h>
#include <dev/dtv/dtv_scatter.h>

#define	DTV_DEFAULT_BUFSIZE	(64 * 4096)

#define	TS_PKTLEN		188
#define	TS_HAS_SYNC(_tspkt)	((_tspkt)[0] == 0x47)
#define	TS_PID(_tspkt)		((((_tspkt)[1] & 0x1f) << 8) | (_tspkt)[2])

struct dtv_buffer {
	uint32_t	db_offset;
	uint32_t	db_bytesused;
	size_t		db_length;
	SIMPLEQ_ENTRY(dtv_buffer) db_entries;
};

SIMPLEQ_HEAD(dtv_sample_queue, dtv_buffer);

struct dtv_stream {
	unsigned int		ds_nbufs;
	struct dtv_buffer	**ds_buf;
	struct dtv_scatter_buf	ds_data;
	struct dtv_sample_queue	ds_ingress, ds_egress;
	kmutex_t		ds_lock;
	kcondvar_t		ds_sample_cv;
	struct selinfo		ds_sel;
	uint32_t		ds_bytesread;
};

struct dtv_ts {
	uint8_t			ts_pidfilter[0x2000];
	kmutex_t		ts_lock;
};

struct dtv_softc {
	device_t	sc_dev;
	const struct dtv_hw_if *sc_hw;
	void		*sc_priv;

	bool		sc_dying;

	unsigned int	sc_open;

	size_t		sc_bufsize;
	bool		sc_bufsize_chg;

	struct dtv_stream sc_stream;
	struct dtv_ts	sc_ts;
};

#define	dtv_device_get_devinfo(sc, info)	\
	((sc)->sc_hw->get_devinfo((sc)->sc_priv, (info)))
#define	dtv_device_open(sc, flags)		\
	((sc)->sc_hw->open((sc)->sc_priv, (flags)))
#define	dtv_device_close(sc)			\
	((sc)->sc_hw->close((sc)->sc_priv))
#define	dtv_device_set_tuner(sc, params)	\
	((sc)->sc_hw->set_tuner((sc)->sc_priv, (params)))
#define	dtv_device_get_status(sc)		\
	((sc)->sc_hw->get_status((sc)->sc_priv))
#define	dtv_device_get_signal_strength(sc)	\
	((sc)->sc_hw->get_signal_strength((sc)->sc_priv))
#define	dtv_device_get_snr(sc)			\
	((sc)->sc_hw->get_snr((sc)->sc_priv))
#define	dtv_device_start_transfer(sc)		\
	((sc)->sc_hw->start_transfer((sc)->sc_priv))
#define	dtv_device_stop_transfer(sc)		\
	((sc)->sc_hw->stop_transfer((sc)->sc_priv))

int	dtv_frontend_ioctl(struct dtv_softc *, u_long, void *, int);
int	dtv_demux_ioctl(struct dtv_softc *, u_long, void *, int);

int	dtv_buffer_setup(struct dtv_softc *, size_t);
int	dtv_buffer_destroy(struct dtv_softc *);
int	dtv_buffer_read(struct dtv_softc *, struct uio *, int);
int	dtv_buffer_poll(struct dtv_softc *, int, lwp_t *);

#endif /* !_DEV_DTV_DTVVAR_H */

File Added: src/sys/dev/dtv/files.dtv
# $NetBSD: files.dtv,v 1.1 2011/07/09 14:46:56 jmcneill Exp $

define	dtvbus { }

device	dtv
attach	dtv at dtvbus
file	dev/dtv/dtv_buffer.c	dtv
file	dev/dtv/dtv_device.c	dtv
file	dev/dtv/dtv_ioctl.c	dtv
file	dev/dtv/dtv_scatter.c	dtv