xref: /netbsd-src/share/examples/pud/intro/intro.c (revision a4b032e2c8dedbb826547920ffe49398315801c3)
1*a4b032e2Spooka /*	$NetBSD: intro.c,v 1.3 2007/11/22 11:28:49 pooka Exp $	*/
2378e2f0dSpooka 
3378e2f0dSpooka /*
4378e2f0dSpooka  * El extra-simplo example of the userspace driver framework.
5378e2f0dSpooka  *
6378e2f0dSpooka  * Eventually there will be a library a la libpuffs (perhaps,
7378e2f0dSpooka  * gasp, even the same lib), but for now it's all manual until
8378e2f0dSpooka  * I get it figured out.
9378e2f0dSpooka  *
10378e2f0dSpooka  * So how to run this?
11378e2f0dSpooka  * 0) sh MAKEDEV putter (if you don't have a freshly created /dev)
12378e2f0dSpooka  * 1) run this program with the argument "/dev/pud"
13378e2f0dSpooka  * 2) mknod a char device with the major 377 (see sources below)
14378e2f0dSpooka  * 3) echo ascii art and jokes into device created in previous step
15378e2f0dSpooka  *    or read the device
16378e2f0dSpooka  */
17378e2f0dSpooka 
18378e2f0dSpooka #include <sys/types.h>
19378e2f0dSpooka 
20378e2f0dSpooka #include <dev/pud/pud_msgif.h>
21378e2f0dSpooka 
22378e2f0dSpooka #include <err.h>
23378e2f0dSpooka #include <errno.h>
24378e2f0dSpooka #include <fcntl.h>
25378e2f0dSpooka #include <stdio.h>
26378e2f0dSpooka #include <stdlib.h>
27378e2f0dSpooka #include <string.h>
28378e2f0dSpooka #include <unistd.h>
29378e2f0dSpooka 
30*a4b032e2Spooka #include "common.h"
31*a4b032e2Spooka 
32378e2f0dSpooka #define DEFALLOC 1024*1024
33*a4b032e2Spooka #define ECHOSTR1 "Would you like some sauce diable with that?\n"
34*a4b032e2Spooka #define ECHOSTR2 "Nej tack, you fool, I'm happy with my tournedos Rossini\n"
35*a4b032e2Spooka #define NSTR 2
36*a4b032e2Spooka 
37*a4b032e2Spooka const char *curstr = ECHOSTR1;
38378e2f0dSpooka 
39378e2f0dSpooka #ifndef MIN
40378e2f0dSpooka #define MIN(a,b) ((a)<(b)?(a):(b))
41378e2f0dSpooka #endif
42378e2f0dSpooka 
43378e2f0dSpooka int
44378e2f0dSpooka main(int argc, char *argv[])
45378e2f0dSpooka {
46378e2f0dSpooka 	struct pud_req *pdr = malloc(DEFALLOC);
47378e2f0dSpooka 	struct pud_conf_reg pcr;
48378e2f0dSpooka 	int fd;
49378e2f0dSpooka 	ssize_t n;
50378e2f0dSpooka 
51378e2f0dSpooka 	if (argc != 2)
52378e2f0dSpooka 		errx(1, "args");
53378e2f0dSpooka 
54378e2f0dSpooka 	/*
55378e2f0dSpooka 	 * open pud device
56378e2f0dSpooka 	 */
57378e2f0dSpooka 	fd = open(argv[1], O_RDWR);
58378e2f0dSpooka 	if (fd == -1)
59378e2f0dSpooka 		err(1, "open");
60378e2f0dSpooka 
61378e2f0dSpooka 	/*
62378e2f0dSpooka 	 * register our major number
63378e2f0dSpooka 	 */
64378e2f0dSpooka 	memset(&pcr, 0, sizeof(pcr));
65378e2f0dSpooka 	pcr.pm_pdr.pdr_pth.pth_framelen = sizeof(struct pud_conf_reg);
66378e2f0dSpooka 	pcr.pm_pdr.pdr_reqclass = PUD_REQ_CONF;
67378e2f0dSpooka 	pcr.pm_pdr.pdr_reqtype = PUD_CONF_REG;
68378e2f0dSpooka 
69378e2f0dSpooka 	pcr.pm_regdev = makedev(377, 0);
70cf9f5c85Spooka 	pcr.pm_flags = PUD_CONFFLAG_BDEV;
71378e2f0dSpooka 	strlcpy(pcr.pm_devname, "testdev", sizeof(pcr.pm_devname));
72378e2f0dSpooka 
73378e2f0dSpooka 	n = write(fd, &pcr, pcr.pm_pdr.pdr_pth.pth_framelen);
74378e2f0dSpooka 	if (n == -1)
75378e2f0dSpooka 		err(1, "configure write");
76378e2f0dSpooka 
77378e2f0dSpooka 	/*
78378e2f0dSpooka 	 * process requests
79378e2f0dSpooka 	 */
80378e2f0dSpooka 	for (;;) {
81378e2f0dSpooka 		n = read(fd, pdr, DEFALLOC);
82cf9f5c85Spooka 		printf("read %d %d\n", n, errno);
83378e2f0dSpooka 
84378e2f0dSpooka 		switch (pdr->pdr_reqtype) {
85378e2f0dSpooka 		case PUD_CDEV_OPEN:
86378e2f0dSpooka 		case PUD_CDEV_CLOSE:
87378e2f0dSpooka 			printf("got openclose %d\n", pdr->pdr_reqtype);
88378e2f0dSpooka 			pdr->pdr_rv = 0;
89378e2f0dSpooka 			break;
90378e2f0dSpooka 
91378e2f0dSpooka 		case PUD_CDEV_READ:
92cf9f5c85Spooka 		/* uh oh case PUD_BDEV_STRATREAD: */
93378e2f0dSpooka 		{
94378e2f0dSpooka 			struct pud_creq_read *pc_read;
95378e2f0dSpooka 			size_t clen;
96378e2f0dSpooka 
97378e2f0dSpooka 			pc_read = (void *)pdr;
98cf9f5c85Spooka 			printf("read from offset %llu, resid %zu\n",
99cf9f5c85Spooka 			    (unsigned long long)pc_read->pm_offset,
100cf9f5c85Spooka 			    pc_read->pm_resid);
101cf9f5c85Spooka 
102*a4b032e2Spooka 			clen = MIN(strlen(curstr), pc_read->pm_resid);
103*a4b032e2Spooka 			strncpy(pc_read->pm_data, curstr, clen);
104cf9f5c85Spooka 			if (pdr->pdr_reqclass == PUD_REQ_BDEV) {
105cf9f5c85Spooka 				clen = pc_read->pm_resid;
106cf9f5c85Spooka 				pc_read->pm_resid = 0;
107cf9f5c85Spooka 			} else {
108378e2f0dSpooka 				pc_read->pm_resid -= clen;
109cf9f5c85Spooka 			}
110378e2f0dSpooka 			pdr->pdr_pth.pth_framelen =
111378e2f0dSpooka 			    sizeof(struct pud_creq_read) + clen;
112378e2f0dSpooka 		}
113378e2f0dSpooka 			break;
114378e2f0dSpooka 
115378e2f0dSpooka 		case PUD_CDEV_WRITE:
116cf9f5c85Spooka 		/* uh uh oh case PUD_BDEV_STRATWRITE: */
117378e2f0dSpooka 		{
118378e2f0dSpooka 			struct pud_creq_write *pc_write;
119378e2f0dSpooka 
120378e2f0dSpooka 			pc_write = (void *)pdr;
121cf9f5c85Spooka 			printf("write to offset %llu, resid %zu\n",
122cf9f5c85Spooka 			    (unsigned long long)pc_write->pm_offset,
123cf9f5c85Spooka 			    pc_write->pm_resid);
124cf9f5c85Spooka 
125378e2f0dSpooka 			pc_write->pm_data[pc_write->pm_resid] = '\0';
126378e2f0dSpooka 			printf("got via write: %s", pc_write->pm_data);
127378e2f0dSpooka 			pdr->pdr_pth.pth_framelen =
128378e2f0dSpooka 			    sizeof(struct pud_creq_write);
129378e2f0dSpooka 			pc_write->pm_resid = 0;
130378e2f0dSpooka 		}
131378e2f0dSpooka 			break;
132378e2f0dSpooka 
133*a4b032e2Spooka 		case PUD_CDEV_IOCTL:
134*a4b032e2Spooka 		{
135*a4b032e2Spooka 			struct pud_req_ioctl *pc_ioctl;
136*a4b032e2Spooka 			int *iocval;
137*a4b032e2Spooka 
138*a4b032e2Spooka 			pc_ioctl = (void *)pdr;
139*a4b032e2Spooka 			switch (pc_ioctl->pm_iocmd) {
140*a4b032e2Spooka 			case INTROTOGGLE:
141*a4b032e2Spooka 			case INTROTOGGLE_R:
142*a4b032e2Spooka 				iocval = (int *)pc_ioctl->pm_data;
143*a4b032e2Spooka 				if (*iocval < 0 || *iocval > 2) {
144*a4b032e2Spooka 					pdr->pdr_rv = ERANGE;
145*a4b032e2Spooka 					break;
146*a4b032e2Spooka 				}
147*a4b032e2Spooka 
148*a4b032e2Spooka 				if (*iocval == 1)
149*a4b032e2Spooka 					curstr = ECHOSTR1;
150*a4b032e2Spooka 				else
151*a4b032e2Spooka 					curstr = ECHOSTR2;
152*a4b032e2Spooka 
153*a4b032e2Spooka 				*iocval = 0;
154*a4b032e2Spooka 				break;
155*a4b032e2Spooka 			default:
156*a4b032e2Spooka 				abort();
157*a4b032e2Spooka 			}
158*a4b032e2Spooka 		}
159*a4b032e2Spooka 			break;
160*a4b032e2Spooka 
161378e2f0dSpooka 		default:
162378e2f0dSpooka 			abort();
163378e2f0dSpooka 		}
164378e2f0dSpooka 
165378e2f0dSpooka 		n = write(fd, pdr, pdr->pdr_pth.pth_framelen);
166378e2f0dSpooka 		printf("wrote %d %d\n", n, errno);
167378e2f0dSpooka 	}
168378e2f0dSpooka }
169