Date: Fri, 18 Feb 2011 21:55:42 +0100 From: Juergen Lock <nox@jelal.kn-bremen.de> To: Juergen Lock <nox@jelal.kn-bremen.de> Cc: "J.R. Oldroyd" <fbsd@opal.com>, freebsd-hackers@freebsd.org, Andrew Gallatin <gallatin@gmail.com>, freebsd-emulation@freebsd.org, Kostik Belousov <kostikbel@gmail.com>, Alexander Leidinger <Alexander@leidinger.net> Subject: Re: Can vm_mmap()/vm_map_remove() be called with giant held? (linuxolator dvb patches) Message-ID: <20110218205542.GA45210@triton8.kn-bremen.de> In-Reply-To: <20110129235448.GA15788@triton8.kn-bremen.de> References: <20110129201000.GA10774@triton8.kn-bremen.de> <20110129205105.GI2518@deviant.kiev.zoral.com.ua> <20110129235448.GA15788@triton8.kn-bremen.de>
next in thread | previous in thread | raw e-mail | index | archive | help
I have finally got back to this and did the style and vm_map_remove() return value handling fixes, updated the patches in-place: http://people.freebsd.org/~nox/dvb/linux-dvb.patch (for head) http://people.freebsd.org/~nox/dvb/linux-dvb-8.patch (for 8.) On Sun, Jan 30, 2011 at 12:54:48AM +0100, Juergen Lock wrote: > On Sat, Jan 29, 2011 at 10:51:05PM +0200, Kostik Belousov wrote: > > On Sat, Jan 29, 2011 at 09:10:00PM +0100, Juergen Lock wrote: > > > Hi! > > > > > > I was kinda hoping to be able to post a correct patch in public but > > > getting an answer to ${Subject} seems to be more difficult than I > > > thought... :) So, does anyone here know? copyout_map() and > > You do not need Giant locked for vm_map* functions. > > > The question was more do I need to drop it first before calling them... > > > > copyout_unmap() are copied from ksyms_map() from sys/dev/ksyms/ksyms.c > > > - should there maybe be global versions instead of two static copies > > > each, and what would be good names? And giant is taken by linux_ioctl() > > Would you make a patch for this ? > > > Heh if you want me to... Where should they go and are my name choices ok? > I haven't done this yet so people can keep patching linux.ko in-place without having to build a new kernel too... > > > in the same source file before calling the parts I added. So here > > > comes the patch, it is to add support for dvb ioctls to the linuxolator > > > as discussed on -emulation earlier in this thread: > > > > > > http://lists.freebsd.org/pipermail/freebsd-multimedia/2011-January/011575.html > > > > > > (patch also at: > > > > > > http://people.freebsd.org/~nox/dvb/linux-dvb.patch > > > > > > and a version for 8, which is what I tested with w_scan on dvb-s2 > > > and dvb-t, and Andrew Gallatin also tested it with SageTV: > > > > > > http://people.freebsd.org/~nox/dvb/linux-dvb-8.patch > > > > > > ) > > > > > > + /* > > > + * Map somewhere after heap in process memory. > > > + */ > > > + PROC_LOCK(td->td_proc); > > > + *addr = round_page((vm_offset_t)vms->vm_daddr + > > > + lim_max(td->td_proc, RLIMIT_DATA)); > > > + PROC_UNLOCK(td->td_proc); > > Are you sure that this is needed ? Why not leave the address selection > > to the VM ? > > > I don't know, maybe sys/dev/ksyms/ksyms.c has a reason? How would I leave the address selection to the VM? Just trying to initialize *addr to (vm_offset_t)NULL there caused the patch to stop working. Thanx, :) Juergen Here is the new version for head: Index: src/sys/compat/linux/linux_ioctl.c =================================================================== RCS file: /home/scvs/src/sys/compat/linux/linux_ioctl.c,v retrieving revision 1.167 diff -u -p -r1.167 linux_ioctl.c --- src/sys/compat/linux/linux_ioctl.c 30 Dec 2010 02:18:04 -0000 1.167 +++ src/sys/compat/linux/linux_ioctl.c 18 Feb 2011 20:10:32 -0000 @@ -59,6 +59,14 @@ __FBSDID("$FreeBSD: src/sys/compat/linux #include <sys/sx.h> #include <sys/tty.h> #include <sys/uio.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/resourcevar.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_extern.h> +#include <vm/vm_map.h> #include <net/if.h> #include <net/if_dl.h> @@ -83,6 +91,9 @@ __FBSDID("$FreeBSD: src/sys/compat/linux #include <compat/linux/linux_videodev.h> #include <compat/linux/linux_videodev_compat.h> +#include <compat/linux/linux_dvb.h> +#include <compat/linux/linux_dvb_compat.h> + CTASSERT(LINUX_IFNAMSIZ == IFNAMSIZ); static linux_ioctl_function_t linux_ioctl_cdrom; @@ -97,6 +108,7 @@ static linux_ioctl_function_t linux_ioct static linux_ioctl_function_t linux_ioctl_drm; static linux_ioctl_function_t linux_ioctl_sg; static linux_ioctl_function_t linux_ioctl_v4l; +static linux_ioctl_function_t linux_ioctl_dvb; static linux_ioctl_function_t linux_ioctl_special; static linux_ioctl_function_t linux_ioctl_fbsd_usb; @@ -124,6 +136,8 @@ static struct linux_ioctl_handler sg_han { linux_ioctl_sg, LINUX_IOCTL_SG_MIN, LINUX_IOCTL_SG_MAX }; static struct linux_ioctl_handler video_handler = { linux_ioctl_v4l, LINUX_IOCTL_VIDEO_MIN, LINUX_IOCTL_VIDEO_MAX }; +static struct linux_ioctl_handler dvb_handler = +{ linux_ioctl_dvb, LINUX_IOCTL_DVB_MIN, LINUX_IOCTL_DVB_MAX }; static struct linux_ioctl_handler fbsd_usb = { linux_ioctl_fbsd_usb, FBSD_LUSB_MIN, FBSD_LUSB_MAX }; @@ -139,6 +153,7 @@ DATA_SET(linux_ioctl_handler_set, privat DATA_SET(linux_ioctl_handler_set, drm_handler); DATA_SET(linux_ioctl_handler_set, sg_handler); DATA_SET(linux_ioctl_handler_set, video_handler); +DATA_SET(linux_ioctl_handler_set, dvb_handler); DATA_SET(linux_ioctl_handler_set, fbsd_usb); struct handler_element @@ -2989,6 +3004,255 @@ linux_ioctl_special(struct thread *td, s } /* + * Map some anonymous memory in user space of size sz, rounded up to the page + * boundary. + */ +static int +copyout_map(struct thread *td, vm_offset_t *addr, size_t sz) +{ + struct vmspace *vms; + int error; + vm_size_t size; + + vms = td->td_proc->p_vmspace; + + /* + * Map somewhere after heap in process memory. + */ + PROC_LOCK(td->td_proc); + *addr = round_page((vm_offset_t)vms->vm_daddr + + lim_max(td->td_proc, RLIMIT_DATA)); + PROC_UNLOCK(td->td_proc); + + /* Round size up to page boundary. */ + size = (vm_size_t)round_page(sz); + + error = vm_mmap(&vms->vm_map, addr, size, PROT_READ | PROT_WRITE, + VM_PROT_ALL, MAP_PRIVATE | MAP_ANON, OBJT_DEFAULT, NULL, 0); + + return (error); +} + +/* + * Unmap memory in user space. + */ +static int +copyout_unmap(struct thread *td, vm_offset_t addr, size_t sz) +{ + int error; + vm_map_t map; + vm_size_t size; + + map = &td->td_proc->p_vmspace->vm_map; + size = (vm_size_t) round_page(sz); + + error = vm_map_remove(map, addr, addr + size); + + return (error); +} + +static int +linux_to_bsd_dtv_properties(struct l_dtv_properties *lvps, struct dtv_properties *vps) +{ + + vps->num = lvps->num; + vps->props = PTRIN(lvps->props); /* possible pointer size conversion */ + return (0); +} + +static int +linux_to_bsd_dtv_property(struct l_dtv_property *lvp, struct dtv_property *vp) +{ + + /* + * Everything until u.buffer.reserved2 is fixed size so + * just memcpy it. + */ + memcpy(vp, lvp, offsetof(struct l_dtv_property, u.buffer.reserved2)); + /* + * The pointer may be garbage since it's part of a union, + * currently no Linux code uses it so just set it to NULL. + */ + vp->u.buffer.reserved2 = NULL; + vp->result = lvp->result; + return (0); +} + +static int +bsd_to_linux_dtv_property(struct dtv_property *vp, struct l_dtv_property *lvp) +{ + + /* + * Everything until u.buffer.reserved2 is fixed size so + * just memcpy it. + */ + memcpy(lvp, vp, offsetof(struct l_dtv_property, u.buffer.reserved2)); + /* + * The pointer may be garbage since it's part of a union, + * currently no Linux code uses it so just set it to NULL. + */ + lvp->u.buffer.reserved2 = PTROUT(NULL); + lvp->result = vp->result; + return (0); +} + +static int +linux_ioctl_dvb(struct thread *td, struct linux_ioctl_args *args) +{ + struct file *fp; + int error, i; + struct l_dtv_properties l_vps; + struct dtv_properties vps; + struct l_dtv_property *l_vp, *l_p; + struct dtv_property *vp, *p; + size_t l_propsiz, propsiz; + vm_offset_t uvp; + + l_vp = NULL; + vp = NULL; + + switch (args->cmd & 0xffff) { + case LINUX_AUDIO_STOP: + case LINUX_AUDIO_PLAY: + case LINUX_AUDIO_PAUSE: + case LINUX_AUDIO_CONTINUE: + case LINUX_AUDIO_SELECT_SOURCE: + case LINUX_AUDIO_SET_MUTE: + case LINUX_AUDIO_SET_AV_SYNC: + case LINUX_AUDIO_SET_BYPASS_MODE: + case LINUX_AUDIO_CHANNEL_SELECT: + case LINUX_AUDIO_CLEAR_BUFFER: + case LINUX_AUDIO_SET_ID: + case LINUX_AUDIO_SET_STREAMTYPE: + case LINUX_AUDIO_SET_EXT_ID: + case LINUX_AUDIO_BILINGUAL_CHANNEL_SELECT: + case LINUX_DMX_START: + case LINUX_DMX_STOP: + case LINUX_DMX_SET_BUFFER_SIZE: + case LINUX_NET_REMOVE_IF: + case LINUX_FE_DISEQC_RESET_OVERLOAD: + case LINUX_FE_DISEQC_SEND_BURST: + case LINUX_FE_SET_TONE: + case LINUX_FE_SET_VOLTAGE: + case LINUX_FE_ENABLE_HIGH_LNB_VOLTAGE: + case LINUX_FE_DISHNETWORK_SEND_LEGACY_CMD: + case LINUX_FE_SET_FRONTEND_TUNE_MODE: + case LINUX_CA_RESET: + if ((args->cmd & IOC_DIRMASK) != LINUX_IOC_VOID) + return ENOIOCTL; + args->cmd = (args->cmd & 0xffff) | IOC_VOID; + break; + + case LINUX_DMX_REMOVE_PID: + /* overlaps with LINUX_NET_ADD_IF */ + if ((args->cmd & IOC_DIRMASK) == LINUX_IOC_INOUT) + goto net_add_if; + /* FALLTHRU */ + case LINUX_AUDIO_SET_MIXER: + case LINUX_AUDIO_SET_ATTRIBUTES: + case LINUX_AUDIO_SET_KARAOKE: + case LINUX_DMX_SET_FILTER: + case LINUX_DMX_SET_PES_FILTER: + case LINUX_DMX_SET_SOURCE: + case LINUX_DMX_ADD_PID: + case LINUX_FE_DISEQC_SEND_MASTER_CMD: + case LINUX_FE_SET_FRONTEND: + case LINUX_CA_SEND_MSG: + case LINUX_CA_SET_DESCR: + case LINUX_CA_SET_PID: + args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_IN; + break; + + case LINUX_AUDIO_GET_STATUS: + case LINUX_AUDIO_GET_CAPABILITIES: + case LINUX_AUDIO_GET_PTS: + case LINUX_DMX_GET_PES_PIDS: + case LINUX_DMX_GET_CAPS: + case LINUX_FE_GET_INFO: + case LINUX_FE_DISEQC_RECV_SLAVE_REPLY: + case LINUX_FE_READ_STATUS: + case LINUX_FE_READ_BER: + case LINUX_FE_READ_SIGNAL_STRENGTH: + case LINUX_FE_READ_SNR: + case LINUX_FE_READ_UNCORRECTED_BLOCKS: + case LINUX_FE_GET_FRONTEND: + case LINUX_FE_GET_EVENT: + case LINUX_CA_GET_CAP: + case LINUX_CA_GET_SLOT_INFO: + case LINUX_CA_GET_DESCR_INFO: + case LINUX_CA_GET_MSG: + args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_OUT; + break; + + case LINUX_DMX_GET_STC: + case LINUX_NET_GET_IF: + net_add_if: + args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_INOUT; + break; + + case LINUX_FE_SET_PROPERTY: + case LINUX_FE_GET_PROPERTY: + error = copyin((void *)args->arg, &l_vps, sizeof(l_vps)); + if (error) + return (error); + linux_to_bsd_dtv_properties(&l_vps, &vps); + if ((vps.num == 0) || vps.num > DTV_IOCTL_MAX_MSGS) + return EINVAL; + + l_propsiz = vps.num * sizeof(*l_vp); + propsiz = vps.num * sizeof(*vp); + l_vp = malloc(l_propsiz, M_LINUX, M_WAITOK); + vp = malloc(propsiz, M_LINUX, M_WAITOK); + error = copyin((void *)vps.props, l_vp, l_propsiz); + if (error) + goto out2; + for (i = vps.num, l_p = l_vp, p = vp; i--; ++l_p, ++p) + linux_to_bsd_dtv_property(l_p, p); + + error = copyout_map(td, &uvp, propsiz); + if (error) + goto out2; + copyout(vp, (void *)uvp, propsiz); + + if ((error = fget(td, args->fd, &fp)) != 0) { + (void)copyout_unmap(td, uvp, propsiz); + goto out2; + } + vps.props = (void *)uvp; + if ((args->cmd & 0xffff) == LINUX_FE_SET_PROPERTY) + error = fo_ioctl(fp, FE_SET_PROPERTY, &vps, td->td_ucred, td); + else + error = fo_ioctl(fp, FE_GET_PROPERTY, &vps, td->td_ucred, td); + if (error) { + (void)copyout_unmap(td, uvp, propsiz); + goto out; + } + error = copyin((void *)uvp, vp, propsiz); + (void)copyout_unmap(td, uvp, propsiz); + if (error) + goto out; + for (i = vps.num, l_p = l_vp, p = vp; i--; ++l_p, ++p) + bsd_to_linux_dtv_property(p, l_p); + linux_to_bsd_dtv_properties(&l_vps, &vps); + copyout(l_vp, (void *)vps.props, l_propsiz); + + out: + fdrop(fp, td); + out2: + if (l_vp) + free(l_vp, M_LINUX); + if (vp) + free(vp, M_LINUX); + return (error); + + default: return (ENOIOCTL); + } + + error = ioctl(td, (struct ioctl_args *)args); + return (error); +} + +/* * Support for emulators/linux-libusb. This port uses FBSD_LUSB* macros * instead of USB* ones. This lets us to provide correct values for cmd. * 0xffffffe0 -- 0xffffffff range seemed to be the least collision-prone. Index: src/sys/compat/linux/linux_ioctl.h =================================================================== RCS file: /home/scvs/src/sys/compat/linux/linux_ioctl.h,v retrieving revision 1.32 diff -u -p -r1.32 linux_ioctl.h --- src/sys/compat/linux/linux_ioctl.h 30 Dec 2010 02:18:04 -0000 1.32 +++ src/sys/compat/linux/linux_ioctl.h 18 Jan 2011 17:48:27 -0000 @@ -32,6 +32,17 @@ #define _LINUX_IOCTL_H_ /* + * ioctl + * + * XXX comments in Linux' <asm-generic/ioctl.h> indicate these + * could be arch-dependant... + */ +#define LINUX_IOC_VOID 0 +#define LINUX_IOC_IN 0x40000000 +#define LINUX_IOC_OUT 0x80000000 +#define LINUX_IOC_INOUT (LINUX_IOC_IN|LINUX_IOC_OUT) + +/* * disk */ #define LINUX_BLKROSET 0x125d @@ -613,6 +624,83 @@ int linux_ifname(struct ifnet *, char #define LINUX_IOCTL_VIDEO_MAX LINUX_VIDIOCSVBIFMT /* + * DVB (osd.h and video.h not handled) + */ +#define LINUX_AUDIO_STOP 0x6f01 /* 0x00006f01 */ +#define LINUX_AUDIO_PLAY 0x6f02 /* 0x00006f02 */ +#define LINUX_AUDIO_PAUSE 0x6f03 /* 0x00006f03 */ +#define LINUX_AUDIO_CONTINUE 0x6f04 /* 0x00006f04 */ +#define LINUX_AUDIO_SELECT_SOURCE 0x6f05 /* 0x00006f05 */ +#define LINUX_AUDIO_SET_MUTE 0x6f06 /* 0x00006f06 */ +#define LINUX_AUDIO_SET_AV_SYNC 0x6f07 /* 0x00006f07 */ +#define LINUX_AUDIO_SET_BYPASS_MODE 0x6f08 /* 0x00006f08 */ +#define LINUX_AUDIO_CHANNEL_SELECT 0x6f09 /* 0x00006f09 */ +#define LINUX_AUDIO_GET_STATUS 0x6f0a /* 0x80206f0a */ +#define LINUX_AUDIO_GET_CAPABILITIES 0x6f0b /* 0x80046f0b */ +#define LINUX_AUDIO_CLEAR_BUFFER 0x6f0c /* 0x00006f0c */ +#define LINUX_AUDIO_SET_ID 0x6f0d /* 0x00006f0d */ +#define LINUX_AUDIO_SET_MIXER 0x6f0e /* 0x40086f0e */ +#define LINUX_AUDIO_SET_STREAMTYPE 0x6f0f /* 0x00006f0f */ +#define LINUX_AUDIO_SET_EXT_ID 0x6f10 /* 0x00006f10 */ +#define LINUX_AUDIO_SET_ATTRIBUTES 0x6f11 /* 0x40026f11 */ +#define LINUX_AUDIO_SET_KARAOKE 0x6f12 /* 0x400c6f12 */ +#define LINUX_AUDIO_GET_PTS 0x6f13 /* 0x80086f13 */ +#define LINUX_AUDIO_BILINGUAL_CHANNEL_SELECT 0x6f14 /* 0x00006f14 */ +#define LINUX_DMX_START 0x6f29 /* 0x00006f29 */ +#define LINUX_DMX_STOP 0x6f2a /* 0x00006f2a */ +#define LINUX_DMX_SET_FILTER 0x6f2b /* 0x403c6f2b */ +#define LINUX_DMX_SET_PES_FILTER 0x6f2c /* 0x40146f2c */ +#define LINUX_DMX_SET_BUFFER_SIZE 0x6f2d /* 0x00006f2d */ +#define LINUX_DMX_GET_PES_PIDS 0x6f2f /* 0x800a6f2f */ +#define LINUX_DMX_GET_CAPS 0x6f30 /* 0x80086f30 */ +#define LINUX_DMX_SET_SOURCE 0x6f31 /* 0x40046f31 */ +#define LINUX_DMX_GET_STC 0x6f32 /* 0xc0106f32 */ +#define LINUX_DMX_ADD_PID 0x6f33 /* 0x40026f33 */ +#define LINUX_DMX_REMOVE_PID 0x6f34 /* 0x40026f34 */ +#define LINUX_FE_GET_INFO 0x6f3d /* 0x80a86f3d */ +#define LINUX_FE_DISEQC_RESET_OVERLOAD 0x6f3e /* 0x00006f3e */ +#define LINUX_FE_DISEQC_SEND_MASTER_CMD 0x6f3f /* 0x40076f3f */ +#define LINUX_FE_DISEQC_RECV_SLAVE_REPLY 0x6f40 /* 0x800c6f40 */ +#define LINUX_FE_DISEQC_SEND_BURST 0x6f41 /* 0x00006f41 */ +#define LINUX_FE_SET_TONE 0x6f42 /* 0x00006f42 */ +#define LINUX_FE_SET_VOLTAGE 0x6f43 /* 0x00006f43 */ +#define LINUX_FE_ENABLE_HIGH_LNB_VOLTAGE 0x6f44 /* 0x00006f44 */ +#define LINUX_FE_READ_STATUS 0x6f45 /* 0x80046f45 */ +#define LINUX_FE_READ_BER 0x6f46 /* 0x80046f46 */ +#define LINUX_FE_READ_SIGNAL_STRENGTH 0x6f47 /* 0x80026f47 */ +#define LINUX_FE_READ_SNR 0x6f48 /* 0x80026f48 */ +#define LINUX_FE_READ_UNCORRECTED_BLOCKS 0x6f49 /* 0x80046f49 */ +#define LINUX_FE_SET_FRONTEND 0x6f4c /* 0x40246f4c */ +#define LINUX_FE_GET_FRONTEND 0x6f4d /* 0x80246f4d */ +#define LINUX_FE_GET_EVENT 0x6f4e /* 0x80286f4e */ +#define LINUX_FE_DISHNETWORK_SEND_LEGACY_CMD 0x6f50 /* 0x00006f50 */ +#define LINUX_FE_SET_FRONTEND_TUNE_MODE 0x6f51 /* 0x00006f51 */ +#define LINUX_FE_SET_PROPERTY 0x6f52 /* 0x40086f52 */ +#define LINUX_FE_GET_PROPERTY 0x6f53 /* 0x80086f53 */ +#define LINUX_CA_RESET 0x6f80 /* 0x00006f80 */ +#define LINUX_CA_GET_CAP 0x6f81 /* 0x80106f81 */ +#define LINUX_CA_GET_SLOT_INFO 0x6f82 /* 0x800c6f82 */ +#define LINUX_CA_GET_DESCR_INFO 0x6f83 /* 0x80086f83 */ +#define LINUX_CA_GET_MSG 0x6f84 /* 0x810c6f84 */ +#define LINUX_CA_SEND_MSG 0x6f85 /* 0x410c6f85 */ +#define LINUX_CA_SET_DESCR 0x6f86 /* 0x40106f86 */ +#define LINUX_CA_SET_PID 0x6f87 /* 0x40086f87 */ + +/* + * DVB net.h + * (LINUX_NET_ADD_IF and LINUX___NET_ADD_IF_OLD overlap with + * LINUX_DMX_REMOVE_PID) + */ +#define LINUX_NET_ADD_IF 0x6f34 /* 0xc0066f34 */ +#define LINUX_NET_REMOVE_IF 0x6f35 /* 0x00006f35 */ +#define LINUX_NET_GET_IF 0x6f36 /* 0xc0066f36 */ +#define LINUX___NET_ADD_IF_OLD 0x6f34 /* 0xc0046f34 */ +#define LINUX___NET_GET_IF_OLD 0x6f36 /* 0xc0046f36 */ + +#define LINUX_IOCTL_DVB_MIN LINUX_AUDIO_STOP +#define LINUX_IOCTL_DVB_MAX LINUX_CA_SET_PID + +/* * Our libusb(8) calls emulated within linux(4). */ #define FBSD_LUSB_DEVICEENUMERATE 0xffff Index: src/sys/compat/linux/linux_dvb.h @@ -0,0 +1,63 @@ +/* + * Extracted from <linux/dvb/frontend.h>, which is: + * + * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de> + * Ralph Metzler <ralph@convergence.de> + * Holger Waechtler <holger@convergence.de> + * Andre Draszik <ad@convergence.de> + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef __LINUX_DVB_H +#define __LINUX_DVB_H + +#include <sys/types.h> + +struct dtv_property { + uint32_t cmd; + uint32_t reserved[3]; + union { + uint32_t data; + struct { + uint8_t data[32]; + uint32_t len; + uint32_t reserved1[3]; + void *reserved2; + } buffer; + } u; + int result; +} __attribute__ ((packed)); + +/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */ +#define DTV_IOCTL_MAX_MSGS 64 + +struct dtv_properties { + uint32_t num; + struct dtv_property *props; +}; + +#define FE_SET_PROPERTY _IOW('o', 82, struct dtv_properties) +/* + * This is broken on linux as well but they workaround it in the driver. + * Since this is impossible to do on FreeBSD fix the header instead. + * Detailed and discussion : + * http://lists.freebsd.org/pipermail/freebsd-multimedia/2010-April/010958.html + */ +#define FE_GET_PROPERTY _IOW('o', 83, struct dtv_properties) + +#endif /*__LINUX_DVB_H*/ Index: src/sys/compat/linux/linux_dvb_compat.h @@ -0,0 +1,26 @@ +#ifndef __LINUX_DVB_COMPAT_H +#define __LINUX_DVB_COMPAT_H + +#include <sys/types.h> + +struct l_dtv_property { + uint32_t cmd; + uint32_t reserved[3]; + union { + uint32_t data; + struct { + uint8_t data[32]; + uint32_t len; + uint32_t reserved1[3]; + l_uintptr_t reserved2; + } buffer; + } u; + l_int result; +} __attribute__ ((packed)); + +struct l_dtv_properties { + uint32_t num; + l_uintptr_t props; +}; + +#endif /*__LINUX_DVB_H*/
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20110218205542.GA45210>