From owner-freebsd-hackers Wed Sep 3 22:20:19 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id WAA06073 for hackers-outgoing; Wed, 3 Sep 1997 22:20:19 -0700 (PDT) Received: from bunyip.cc.uq.edu.au (daemon@bunyip.cc.uq.edu.au [130.102.2.1]) by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id WAA06066 for ; Wed, 3 Sep 1997 22:20:13 -0700 (PDT) Received: (from daemon@localhost) by bunyip.cc.uq.edu.au (8.8.7/8.8.7) id PAA29559; Thu, 4 Sep 1997 15:19:35 +1000 Received: from localhost.dtir.qld.gov.au by ogre.dtir.qld.gov.au (8.7.5/DEVETIR-E0.3a) with SMTP id PAA09446; Thu, 4 Sep 1997 15:19:14 +1000 (EST) Message-Id: <199709040519.PAA09446@ogre.dtir.qld.gov.au> To: Mike Smith , Simon Shapiro cc: freebsd-hackers@freebsd.org, syssgm@dtir.qld.gov.au Subject: Re: IOCTL Commands - Where is my mistake? References: <199709040247.MAA00870@word.smith.net.au> In-Reply-To: <199709040247.MAA00870@word.smith.net.au> from Mike Smith at "Thu, 04 Sep 1997 02:47:22 +0000" Date: Thu, 04 Sep 1997 15:19:14 +1000 From: Stephen McKay Sender: owner-freebsd-hackers@freebsd.org X-Loop: FreeBSD.org Precedence: bulk On Thursday, 4th September 1997, Mike Smith wrote: >... the correct approach would seem to be : > >struct foo { > int a, b; >}; > >#define FOO_IOCTL _IOWR('F', 1, struct foo) > >... > struct foo bar; >... > ioctl(fd, FOO_IOCTL, bar); >... > > case FOO_IOCTL: > { > struct foo oof = (struct foo *)cmdarg; >... > >... > } > >This will copy the 'bar' structure into and out of the kernel (tune >with the macro to suit), and allow you to call the ioctl handler from >within the kernel (eg. from one of the ABI emulation layers). > >I hope this a) makes sense, and b) works for you. Well Mike, I'm pretty sure now that you've made a boo-boo. :-) I direct your attention to TIOCGWINSZ and a typical use of this in nvi/cl/cl_term.c: struct winsize win; if (ioctl(STDERR_FILENO, TIOCGWINSZ, &win) != -1) { ... } The definition of TIOCGWINSZ: #define TIOCGWINSZ _IOR('t', 104, struct winsize) and some code from kern/tty.c: int ttioctl(tp, cmd, data, flag) register struct tty *tp; int cmd, flag; void *data; { ... case TIOCGWINSZ: /* get window size */ *(struct winsize *)data = tp->t_winsize; break; ... } There are a few levels of calls between ioctl() in kern/sys_generic.c and ttioctl() in kern/tty.c but 'data' stays the same. >From this, I expect that Simon wants to use his ioctl like: dpt_perf_t metrics; if ( (result = ioctl(fd, DPT_IOCTL_INTERNAL_METRICS, &metrics)) != 0 ) { ... } Define his ioctl like: #define DPT_IOCTL_INTERNAL_METRICS _IOR('D', 1, dpt_perf_t) And put this in his driver: int dpt_ioctl(dev_t dev, int cmd, caddr_t cmdarg, int flags, struct proc *p) ... switch (cmd) { case DPT_IOCTL_INTERNAL_METRICS: *(dpt_perf_t *)cmdarg = dpt->performance; break; The reason that: #define DPT_IOCTL_INTERNAL_METRICS IOC_INOUT | 1 works with his current driver code is sheer luck, as Mike says. The size is encoded as 0, and that falls through some odd code in ioctl() and hands you a cmdarg that points to the pointer that was passed in from user mode. A zero size should be an error in my books. Stephen.