1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-18 15:30:21 +00:00

Fix cdev kld example after it has been broken for year or so. Also extend list

of supported operations by example read() and write() operations.

Inspired by:    http://www.daemonnews.org/200010/blueprints.html
PR:             16173
Submitted by:   sobomax
This commit is contained in:
Maxim Sobolev 2000-10-02 14:14:07 +00:00
parent c7f95f5372
commit 7320fd3a30
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=66549
7 changed files with 114 additions and 15 deletions

View File

@ -58,6 +58,8 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#
1.0 Overview
@ -83,6 +85,19 @@
try out changes to kernel code without rebuilding and
booting from the new kernel.
The idea behind this example is to show some interaction
with the device driver. Therefore the flow of the code that
this driver is aimed at is as follows:
open(2) -> ioctl(2) -> write(2) -> read(2) -> close(2).
We will first open the device in the /dev/ directory; then
we will send an ioctl message to it using ioctl(2) call;
then write a small string via the write(2) call. This string
we write to the device will be stored in a static buffer,
and later will be accessible via the read(2) call. Finally,
we will close(2) our open()'d device so that we may no
longer make read or write calls on it.
2.0 Directions

View File

@ -78,8 +78,8 @@ KLDUNLOAD = /sbin/kldunload
CLEANFILES+= ${KMOD}
load: /dev/cdev
${KLDLOAD} -v ./${KMOD}
load: /dev/cdev ${KMOD}.ko
${KLDLOAD} -v ./${KMOD}.ko
unload:
rm -f /dev/cdev

View File

@ -64,7 +64,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ioccom.h>
@ -90,11 +94,17 @@
#define CDEV_IOCTL1 _IOR('C', 1, u_int)
/* Stores string recv'd by _write() */
static char buf[512+1];
static int len;
int
mydev_open(dev_t dev, int flag, int otyp, struct proc *procp)
{
printf("mydev_open: dev_t=%d, flag=%x, otyp=%x, procp=%p\n",
dev2udev(dev), flag, otyp, procp);
memset(&buf, '\0', 513);
len = 0;
return (0);
}
@ -125,3 +135,43 @@ mydev_ioctl(dev_t dev, u_long cmd, caddr_t arg, int mode, struct proc *procp)
}
return error;
}
/*
* mydev_write takes in a character string and saves it
* to buf for later accessing.
*/
int
mydev_write(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
printf("mydev_write: dev_t=%d, uio=%p, ioflag=%d\n",
dev2udev(dev), uio, ioflag);
err = copyinstr(uio->uio_iov->iov_base, &buf, 512, &len);
if (err != 0) {
printf("Write to \"cdev\" failed.\n");
}
return(err);
}
/*
* The mydev_read function just takes the buf that was saved
* via mydev_write() and returns it to userland for
* accessing.
*/
int
mydev_read(dev_t dev, struct uio *uio, int ioflag)
{
int err = 0;
printf("mydev_read: dev_t=%d, uio=%p, ioflag=%d\n",
dev2udev(dev), uio, ioflag);
if (len <= 0) {
err = -1;
} else { /* copy buf to userland */
copystr(&buf, uio->uio_iov->iov_base, 513, &len);
}
return(err);
}

View File

@ -65,13 +65,17 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* $FreeBSD$
*/
#ifndef __CDEV_H_
#define __CDEV_H_
d_open_t mydev_open;
d_close_t mydev_close;
d_ioctl_t mydev_ioctl;
d_open_t mydev_open;
d_close_t mydev_close;
d_ioctl_t mydev_ioctl;
d_read_t mydev_read;
d_write_t mydev_write;
#endif

View File

@ -64,6 +64,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
@ -78,25 +80,27 @@
static struct cdevsw my_devsw = {
/* open */ mydev_open,
/* close */ mydev_close,
/* read */ noread,
/* write */ nowrite,
/* read */ mydev_read,
/* write */ mydev_write,
/* ioctl */ mydev_ioctl,
/* stop */ nostop,
/* reset */ noreset,
/* devtotty */ nodevtotty,
/* poll */ nopoll,
/* mmap */ nommap,
/* strategy */ nostrategy,
/* name */ "cdev",
/* parms */ noparms,
/* maj */ CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
/* flags */ D_TTY,
/* maxio */ 0,
/* bmaj */ -1
};
/*
* Used as the variable that is the reference to our device
* in devfs... we must keep this variable sane until we
* call kldunload.
*/
static dev_t sdev;
/*
* This function is called each time the module is loaded or unloaded.
* Since we are a miscellaneous module, we have to provide whatever
@ -123,10 +127,12 @@ cdev_load(module_t mod, int cmd, void *arg)
printf("Copyright (c) 1998\n");
printf("Rajesh Vaidheeswarran\n");
printf("All rights reserved\n");
sdev = make_dev(&my_devsw, 0, UID_ROOT, GID_WHEEL, 0600, "cdev");
break; /* Success*/
case MOD_UNLOAD:
printf("Unloaded kld character device driver\n");
destroy_dev(sdev);
break; /* Success*/
default: /* we only understand load/unload*/
@ -139,4 +145,4 @@ cdev_load(module_t mod, int cmd, void *arg)
/* Now declare the module to the system */
DEV_MODULE(cdev, CDEV_MAJOR, -1, my_devsw, cdev_load, 0);
DEV_MODULE(cdev, cdev_load, NULL);

View File

@ -87,6 +87,6 @@ unload:
@echo "has been successfully unloaded by building 'unload' in"
@echo "the 'module' subdirectory."
@echo
${MODSTAT} -n misc_mod
${MODSTAT} -n cdev
.include <bsd.prog.mk>

View File

@ -67,21 +67,28 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* $FreeBSD$
*/
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioccom.h>
#define CDEV_IOCTL1 _IOR('C', 1, u_int)
#define CDEV_DEVICE "cdev"
static char writestr[] = "Hello kernel!";
static char buf[512+1];
int
main(int argc, char *argv[])
{
int kernel_fd;
int one;
int len;
if ((kernel_fd = open("/dev/" CDEV_DEVICE, O_RDONLY)) == -1) {
if ((kernel_fd = open("/dev/" CDEV_DEVICE, O_RDWR)) == -1) {
perror("/dev/" CDEV_DEVICE);
exit(1);
}
@ -92,5 +99,22 @@ main(int argc, char *argv[])
} else {
printf( "Sent ioctl CDEV_IOCTL1 to device /dev/" CDEV_DEVICE "\n");
}
len = strlen(writestr) + 1;
/* Write operation */
if (write(kernel_fd, writestr, len) == -1) {
perror("write()");
} else {
printf("Written \"%s\" string to device /dev/" CDEV_DEVICE "\n", writestr);
}
/* Read operation */
if (read(kernel_fd, buf, len) == -1) {
perror("read()");
} else {
printf("Read \"%s\" string from device /dev/" CDEV_DEVICE "\n", buf);
}
exit(0);
}