1*efe797dcSpooka /* $NetBSD: intro.c,v 1.4 2007/11/28 16:59:02 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
30a4b032e2Spooka #include "common.h"
31a4b032e2Spooka
32378e2f0dSpooka #define DEFALLOC 1024*1024
33a4b032e2Spooka #define ECHOSTR1 "Would you like some sauce diable with that?\n"
34a4b032e2Spooka #define ECHOSTR2 "Nej tack, you fool, I'm happy with my tournedos Rossini\n"
35a4b032e2Spooka #define NSTR 2
36a4b032e2Spooka
37a4b032e2Spooka const char *curstr = ECHOSTR1;
38378e2f0dSpooka
39378e2f0dSpooka #ifndef MIN
40378e2f0dSpooka #define MIN(a,b) ((a)<(b)?(a):(b))
41378e2f0dSpooka #endif
42378e2f0dSpooka
43378e2f0dSpooka int
main(int argc,char * argv[])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);
66*efe797dcSpooka pcr.pm_version = PUD_DEVELVERSION | PUD_VERSION;
67378e2f0dSpooka pcr.pm_pdr.pdr_reqclass = PUD_REQ_CONF;
68378e2f0dSpooka pcr.pm_pdr.pdr_reqtype = PUD_CONF_REG;
69378e2f0dSpooka
70378e2f0dSpooka pcr.pm_regdev = makedev(377, 0);
71cf9f5c85Spooka pcr.pm_flags = PUD_CONFFLAG_BDEV;
72378e2f0dSpooka strlcpy(pcr.pm_devname, "testdev", sizeof(pcr.pm_devname));
73378e2f0dSpooka
74378e2f0dSpooka n = write(fd, &pcr, pcr.pm_pdr.pdr_pth.pth_framelen);
75378e2f0dSpooka if (n == -1)
76378e2f0dSpooka err(1, "configure write");
77378e2f0dSpooka
78378e2f0dSpooka /*
79378e2f0dSpooka * process requests
80378e2f0dSpooka */
81378e2f0dSpooka for (;;) {
82378e2f0dSpooka n = read(fd, pdr, DEFALLOC);
83cf9f5c85Spooka printf("read %d %d\n", n, errno);
84378e2f0dSpooka
85378e2f0dSpooka switch (pdr->pdr_reqtype) {
86378e2f0dSpooka case PUD_CDEV_OPEN:
87378e2f0dSpooka case PUD_CDEV_CLOSE:
88378e2f0dSpooka printf("got openclose %d\n", pdr->pdr_reqtype);
89378e2f0dSpooka pdr->pdr_rv = 0;
90378e2f0dSpooka break;
91378e2f0dSpooka
92378e2f0dSpooka case PUD_CDEV_READ:
93cf9f5c85Spooka /* uh oh case PUD_BDEV_STRATREAD: */
94378e2f0dSpooka {
95378e2f0dSpooka struct pud_creq_read *pc_read;
96378e2f0dSpooka size_t clen;
97378e2f0dSpooka
98378e2f0dSpooka pc_read = (void *)pdr;
99cf9f5c85Spooka printf("read from offset %llu, resid %zu\n",
100cf9f5c85Spooka (unsigned long long)pc_read->pm_offset,
101cf9f5c85Spooka pc_read->pm_resid);
102cf9f5c85Spooka
103a4b032e2Spooka clen = MIN(strlen(curstr), pc_read->pm_resid);
104a4b032e2Spooka strncpy(pc_read->pm_data, curstr, clen);
105cf9f5c85Spooka if (pdr->pdr_reqclass == PUD_REQ_BDEV) {
106cf9f5c85Spooka clen = pc_read->pm_resid;
107cf9f5c85Spooka pc_read->pm_resid = 0;
108cf9f5c85Spooka } else {
109378e2f0dSpooka pc_read->pm_resid -= clen;
110cf9f5c85Spooka }
111378e2f0dSpooka pdr->pdr_pth.pth_framelen =
112378e2f0dSpooka sizeof(struct pud_creq_read) + clen;
113378e2f0dSpooka }
114378e2f0dSpooka break;
115378e2f0dSpooka
116378e2f0dSpooka case PUD_CDEV_WRITE:
117cf9f5c85Spooka /* uh uh oh case PUD_BDEV_STRATWRITE: */
118378e2f0dSpooka {
119378e2f0dSpooka struct pud_creq_write *pc_write;
120378e2f0dSpooka
121378e2f0dSpooka pc_write = (void *)pdr;
122cf9f5c85Spooka printf("write to offset %llu, resid %zu\n",
123cf9f5c85Spooka (unsigned long long)pc_write->pm_offset,
124cf9f5c85Spooka pc_write->pm_resid);
125cf9f5c85Spooka
126378e2f0dSpooka pc_write->pm_data[pc_write->pm_resid] = '\0';
127378e2f0dSpooka printf("got via write: %s", pc_write->pm_data);
128378e2f0dSpooka pdr->pdr_pth.pth_framelen =
129378e2f0dSpooka sizeof(struct pud_creq_write);
130378e2f0dSpooka pc_write->pm_resid = 0;
131378e2f0dSpooka }
132378e2f0dSpooka break;
133378e2f0dSpooka
134a4b032e2Spooka case PUD_CDEV_IOCTL:
135a4b032e2Spooka {
136a4b032e2Spooka struct pud_req_ioctl *pc_ioctl;
137a4b032e2Spooka int *iocval;
138a4b032e2Spooka
139a4b032e2Spooka pc_ioctl = (void *)pdr;
140a4b032e2Spooka switch (pc_ioctl->pm_iocmd) {
141a4b032e2Spooka case INTROTOGGLE:
142a4b032e2Spooka case INTROTOGGLE_R:
143a4b032e2Spooka iocval = (int *)pc_ioctl->pm_data;
144a4b032e2Spooka if (*iocval < 0 || *iocval > 2) {
145a4b032e2Spooka pdr->pdr_rv = ERANGE;
146a4b032e2Spooka break;
147a4b032e2Spooka }
148a4b032e2Spooka
149a4b032e2Spooka if (*iocval == 1)
150a4b032e2Spooka curstr = ECHOSTR1;
151a4b032e2Spooka else
152a4b032e2Spooka curstr = ECHOSTR2;
153a4b032e2Spooka
154a4b032e2Spooka *iocval = 0;
155a4b032e2Spooka break;
156a4b032e2Spooka default:
157a4b032e2Spooka abort();
158a4b032e2Spooka }
159a4b032e2Spooka }
160a4b032e2Spooka break;
161a4b032e2Spooka
162378e2f0dSpooka default:
163378e2f0dSpooka abort();
164378e2f0dSpooka }
165378e2f0dSpooka
166378e2f0dSpooka n = write(fd, pdr, pdr->pdr_pth.pth_framelen);
167378e2f0dSpooka printf("wrote %d %d\n", n, errno);
168378e2f0dSpooka }
169378e2f0dSpooka }
170