From owner-freebsd-hackers Wed Sep 3 01:31:54 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id BAA29338 for hackers-outgoing; Wed, 3 Sep 1997 01:31:54 -0700 (PDT) Received: from genesis.atrad.adelaide.edu.au (genesis.atrad.adelaide.edu.au [129.127.96.120]) by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id BAA29307 for ; Wed, 3 Sep 1997 01:31:47 -0700 (PDT) Received: from word.smith.net.au (lot.atrad.adelaide.edu.au [203.20.121.21]) by genesis.atrad.adelaide.edu.au (8.8.5/8.7.3) with ESMTP id SAA04214 for ; Wed, 3 Sep 1997 18:01:44 +0930 (CST) Received: from word.smith.net.au (localhost.atrad.adelaide.edu.au [127.0.0.1]) by word.smith.net.au (8.8.7/8.8.5) with ESMTP id RAA00286; Wed, 3 Sep 1997 17:51:58 +0930 (CST) Message-Id: <199709030821.RAA00286@word.smith.net.au> X-Mailer: exmh version 2.0zeta 7/24/97 To: Simon Shapiro cc: freebsd-hackers@freebsd.org Subject: Re: IOCTL Commands - Where is my mistake? In-reply-to: Your message of "Wed, 03 Sep 1997 00:40:53 MST." Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Wed, 03 Sep 1997 17:51:57 +0930 From: Mike Smith Sender: owner-freebsd-hackers@freebsd.org X-Loop: FreeBSD.org Precedence: bulk > I want to pass IOCTL commands to a driver. This is what I do: > > #define DPT_IOCTL_INTERNAL_METRICS _IOW('D', 1, dpt_perf_t) You want to pass a pointer to the struct, not the struct itself. > switch (cmd) { > case DPT_IOCTL_INTERNAL_METRICS: > result = copyout((char *)&dpt->performance, > (dpt_softc_t *)(*(caddr_t *)cmdarg), > sizeof(dpt_perf_t)); This is *hideously* bogus. Try : caddr_t dest; /* get address in userspace */ dest = fuword(*(caddr_t *)cmdarg); /* copy out to userspace */ return(copyout(&dpt->performance, dest, sizeof(dpt->performance)) ie. cmdarg is a pointer in kernel space to a *copy* of the value passed as an argument to the ioctl. You could also define the ioctl : #define DPT_IOCTL_INTERNAL_METRICS _IOR('D', 1, dpt_perf_t) and then in the kernel say : memcpy(cmdarg, &dpt->performance, sizeof(dpt->performance)); however this will perform two copies; once as you copy it to the arg area, and another when the ioctl returns the copy to userspace. This approach is somewhat discouraged from an efficiency point of view. You would call this as : ioctl(fd, DPT_IOCTL_INTERNAL_METRICS, metrics) ie. pass the structure, not a pointer to it. Think of an ioctl define as being like a function prototype. mike