summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2008-06-05 20:50:29 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2008-06-05 20:50:29 +0000
commit8069d0dbe3969ba410e2a7148cb59e4670241e30 (patch)
tree13ee5f1bba004b6540339fbc13b146841c0e1d3f /sys/dev
parent49e010146a7fe56465e8001af0a6701af58d4095 (diff)
Add some first mmap bits.
Help by miod@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/uvideo.c102
-rw-r--r--sys/dev/usb/uvideo.h15
-rw-r--r--sys/dev/video.c47
-rw-r--r--sys/dev/video_if.h7
4 files changed, 143 insertions, 28 deletions
diff --git a/sys/dev/usb/uvideo.c b/sys/dev/usb/uvideo.c
index 0fa8ef73151..d82bf4eb2f5 100644
--- a/sys/dev/usb/uvideo.c
+++ b/sys/dev/usb/uvideo.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvideo.c,v 1.22 2008/05/30 06:37:38 mglocker Exp $ */
+/* $OpenBSD: uvideo.c,v 1.23 2008/06/05 20:50:28 mglocker Exp $ */
/*
* Copyright (c) 2008 Robert Nagy <robert@openbsd.org>
@@ -34,6 +34,7 @@
#include <sys/stat.h>
#include <sys/device.h>
#include <sys/poll.h>
+#include <uvm/uvm.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -134,10 +135,12 @@ int uvideo_querycap(void *, struct v4l2_capability *);
int uvideo_enum_fmt(void *, struct v4l2_fmtdesc *);
int uvideo_s_fmt(void *, struct v4l2_format *);
int uvideo_g_fmt(void *, struct v4l2_format *);
-int uvideo_reqbufs(void *, struct v4l2_requestbuffers *);
int uvideo_enum_input(void *, struct v4l2_input *);
int uvideo_s_input(void *, int);
+int uvideo_reqbufs(void *, struct v4l2_requestbuffers *);
+int uvideo_querybuf(void *, struct v4l2_buffer *);
int uvideo_try_fmt(void *, struct v4l2_format *);
+caddr_t uvideo_mappage(void *, off_t, int);
#define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
@@ -166,12 +169,13 @@ struct video_hw_if uvideo_hw_if = {
uvideo_enum_fmt, /* VIDIOC_ENUM_FMT */
uvideo_s_fmt, /* VIDIOC_S_FMT */
uvideo_g_fmt, /* VIDIOC_G_FMT */
- uvideo_reqbufs, /* VIDIOC_REQBUFS */
uvideo_enum_input, /* VIDIOC_ENUMINPUT */
uvideo_s_input, /* VIDIOC_S_INPUT */
- NULL, /* VIDIOC_QBUF */
+ uvideo_reqbufs, /* VIDIOC_REQBUFS */
+ uvideo_querybuf, /* VIDIOC_QUERYBUF */
NULL, /* VIDIOC_DQBUF */
- uvideo_try_fmt /* VIDIOC_TRY_FMT */
+ uvideo_try_fmt, /* VIDIOC_TRY_FMT */
+ uvideo_mappage /* mmap */
};
int
@@ -1711,12 +1715,6 @@ uvideo_g_fmt(void *v, struct v4l2_format *fmt)
}
int
-uvideo_reqbufs(void *v, struct v4l2_requestbuffers *rb)
-{
- return (0);
-}
-
-int
uvideo_enum_input(void *v, struct v4l2_input *input)
{
if (input->index != 0)
@@ -1740,6 +1738,77 @@ uvideo_s_input(void *v, int input)
}
int
+uvideo_reqbufs(void *v, struct v4l2_requestbuffers *rb)
+{
+ struct uvideo_softc *sc = v;
+ int i, buf_count, buf_size, buf_size_total;
+
+ DPRINTF(1, "%s: count=%d\n", __func__, rb->count);
+
+ /* limit the buffers */
+ if (rb->count > UVIDEO_MAX_BUFFERS)
+ buf_count = UVIDEO_MAX_BUFFERS;
+ else
+ buf_count = rb->count;
+
+ /* allocate the total mmap buffer */
+ buf_size = UGETDW(sc->sc_desc_probe.dwMaxVideoFrameSize);
+ buf_size_total = buf_count * buf_size;
+ buf_size_total = round_page(buf_size_total); /* page align buffer */
+ sc->sc_mmap_buffer.buf = malloc(buf_size_total, M_DEVBUF, M_NOWAIT);
+ if (sc->sc_mmap_buffer.buf == NULL) {
+ printf("%s: can't allocate mmap buffer!\n", DEVNAME(sc));
+ return (EINVAL);
+ }
+ DPRINTF(1, "%s: allocated %d bytes mmap buffer\n",
+ DEVNAME(sc), buf_size_total);
+
+ /* fill the v4l2_buffer structure */
+ for (i = 0; i < buf_count; i++) {
+ sc->sc_mmap_buffer.v4l2_buf[i].index = i;
+ sc->sc_mmap_buffer.v4l2_buf[i].m.offset = i * buf_size;
+ sc->sc_mmap_buffer.v4l2_buf[i].length = buf_size;
+ sc->sc_mmap_buffer.v4l2_buf[i].type =
+ V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ sc->sc_mmap_buffer.v4l2_buf[i].sequence = 0;
+ sc->sc_mmap_buffer.v4l2_buf[i].field = V4L2_FIELD_NONE;
+ sc->sc_mmap_buffer.v4l2_buf[i].memory = V4L2_MEMORY_MMAP;
+ sc->sc_mmap_buffer.v4l2_buf[i].flags = V4L2_MEMORY_MMAP;
+ DPRINTF(1, "%s: %s: index=%d, offset=%d, length=%d\n",
+ DEVNAME(sc), __func__,
+ sc->sc_mmap_buffer.v4l2_buf[i].index,
+ sc->sc_mmap_buffer.v4l2_buf[i].m.offset,
+ sc->sc_mmap_buffer.v4l2_buf[i].length);
+ }
+
+ /* tell how many buffers we have really allocated */
+ rb->count = buf_count;
+
+ return (0);
+}
+
+int
+uvideo_querybuf(void *v, struct v4l2_buffer *qb)
+{
+ struct uvideo_softc *sc = v;
+
+ if (qb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ qb->memory != V4L2_MEMORY_MMAP)
+ return (EINVAL);
+
+ bcopy(&sc->sc_mmap_buffer.v4l2_buf[qb->index], qb,
+ sizeof(struct v4l2_buffer));
+
+ DPRINTF(1, "%s: %s: index=%d, offset=%d, length=%d\n",
+ DEVNAME(sc), __func__,
+ qb->index,
+ qb->m.offset,
+ qb->length);
+
+ return (0);
+}
+
+int
uvideo_try_fmt(void *v, struct v4l2_format *fmt)
{
if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -1747,3 +1816,14 @@ uvideo_try_fmt(void *v, struct v4l2_format *fmt)
return (0);
}
+
+caddr_t
+uvideo_mappage(void *v, off_t off, int prot)
+{
+ struct uvideo_softc *sc = v;
+ caddr_t p;
+
+ p = sc->sc_mmap_buffer.buf + off;
+
+ return (p);
+}
diff --git a/sys/dev/usb/uvideo.h b/sys/dev/usb/uvideo.h
index efb996ea0f2..593ea01138c 100644
--- a/sys/dev/usb/uvideo.h
+++ b/sys/dev/usb/uvideo.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvideo.h,v 1.9 2008/05/27 17:47:28 mglocker Exp $ */
+/* $OpenBSD: uvideo.h,v 1.10 2008/06/05 20:50:28 mglocker Exp $ */
/*
* Copyright (c) 2007 Robert Nagy <robert@openbsd.org>
@@ -351,6 +351,18 @@ struct uvideo_sample_buffer {
uint8_t *buf;
};
+#define UVIDEO_MAX_BUFFERS 256
+struct uvideo_mmap_buffer {
+ /*
+ * TODO
+ * Complete buffer so we can queue/dequeue video frames.
+ * Maybe we should use some queue macros for this?
+ */
+ uint8_t *buf;
+
+ struct v4l2_buffer v4l2_buf[UVIDEO_MAX_BUFFERS];
+};
+
struct uvideo_softc {
struct device sc_dev;
usbd_device_handle sc_udev;
@@ -380,6 +392,7 @@ struct uvideo_softc {
u_int32_t quirks;
struct uvideo_sample_buffer sc_sample_buffer;
+ struct uvideo_mmap_buffer sc_mmap_buffer;
struct vnode *sc_vp;
struct usb_task sc_task_write;
diff --git a/sys/dev/video.c b/sys/dev/video.c
index 4131a767f7d..e72ca70778d 100644
--- a/sys/dev/video.c
+++ b/sys/dev/video.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: video.c,v 1.5 2008/05/30 06:37:38 mglocker Exp $ */
+/* $OpenBSD: video.c,v 1.6 2008/06/05 20:50:28 mglocker Exp $ */
/*
* Copyright (c) 2008 Robert Nagy <robert@openbsd.org>
*
@@ -27,6 +27,8 @@
#include <sys/malloc.h>
#include <sys/conf.h>
#include <sys/videoio.h>
+#include <uvm/uvm.h>
+#include <uvm/uvm_pmap.h>
#include <dev/video_if.h>
#include <dev/videovar.h>
@@ -179,11 +181,6 @@ videoioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
error = (sc->hw_if->g_fmt)(sc->hw_hdl,
(struct v4l2_format *)data);
break;
- case VIDIOC_REQBUFS:
- if (sc->hw_if->reqbufs)
- error = (sc->hw_if->reqbufs)(sc->hw_hdl,
- (struct v4l2_requestbuffers *)data);
- break;
case VIDIOC_ENUMINPUT:
if (sc->hw_if->enum_input)
error = (sc->hw_if->enum_input)(sc->hw_hdl,
@@ -194,9 +191,17 @@ videoioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
error = (sc->hw_if->s_input)(sc->hw_hdl,
(int)*data);
break;
+ case VIDIOC_REQBUFS:
+ if (sc->hw_if->reqbufs)
+ error = (sc->hw_if->reqbufs)(sc->hw_hdl,
+ (struct v4l2_requestbuffers *)data);
+ break;
case VIDIOC_QUERYBUF:
+ if (sc->hw_if->querybuf)
+ error = (sc->hw_if->querybuf)(sc->hw_hdl,
+ (struct v4l2_buffer *)data);
break;
- case VIDIOC_QBUF:
+ case VIDIOC_DQBUF:
break;
case VIDIOC_TRY_FMT:
if (sc->hw_if->try_fmt)
@@ -215,18 +220,34 @@ videommap(dev_t dev, off_t off, int prot)
{
struct video_softc *sc;
int unit;
+ caddr_t p;
+ paddr_t pa;
+
+ DPRINTF(("%s: off=%d, prot=%d\n", __func__, off, prot));
unit = VIDEOUNIT(dev);
if (unit >= video_cd.cd_ndevs ||
(sc = video_cd.cd_devs[unit]) == NULL)
- return (ENXIO);
+ return (-1);
if (sc->sc_dying)
- return (EIO);
-
- /* TODO */
-
- return (0);
+ return (-1);
+
+ if (sc->hw_if->mappage == NULL)
+ return (-1);
+
+ p = sc->hw_if->mappage(sc->hw_hdl, off, prot);
+ if (p == NULL)
+ return (-1);
+ if (pmap_extract(pmap_kernel(), (vaddr_t)p, &pa) == FALSE)
+ panic("videommap: invalid page");
+ pmap_update(pmap_kernel());
+
+#if defined(__powerpc__) || defined(__sparc64__)
+ return (pa);
+#else
+ return (atop(pa));
+#endif
}
/*
diff --git a/sys/dev/video_if.h b/sys/dev/video_if.h
index eb672e75302..492ae2d96e9 100644
--- a/sys/dev/video_if.h
+++ b/sys/dev/video_if.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: video_if.h,v 1.5 2008/05/30 06:37:38 mglocker Exp $ */
+/* $OpenBSD: video_if.h,v 1.6 2008/06/05 20:50:28 mglocker Exp $ */
/*
* Copyright (c) 2008 Robert Nagy <robert@openbsd.org>
*
@@ -38,12 +38,13 @@ struct video_hw_if {
int (*enum_fmt)(void *, struct v4l2_fmtdesc *);
int (*s_fmt)(void *, struct v4l2_format *);
int (*g_fmt)(void *, struct v4l2_format *);
- int (*reqbufs)(void *, struct v4l2_requestbuffers *);
int (*enum_input)(void *, struct v4l2_input *);
int (*s_input)(void *, int);
- int (*qbuf)(void *, struct v4l2_buffer *);
+ int (*reqbufs)(void *, struct v4l2_requestbuffers *);
+ int (*querybuf)(void *, struct v4l2_buffer *);
int (*dqbuf)(void *, struct v4l2_buffer *);
int (*try_fmt)(void *, struct v4l2_format *);
+ caddr_t (*mappage)(void *, off_t, int);
};
struct video_attach_args {