intro.c revision 1.4.4.2 1 1.4.4.2 matt /* $NetBSD: intro.c,v 1.4.4.2 2008/01/09 01:38:58 matt Exp $ */
2 1.4.4.2 matt
3 1.4.4.2 matt /*
4 1.4.4.2 matt * El extra-simplo example of the userspace driver framework.
5 1.4.4.2 matt *
6 1.4.4.2 matt * Eventually there will be a library a la libpuffs (perhaps,
7 1.4.4.2 matt * gasp, even the same lib), but for now it's all manual until
8 1.4.4.2 matt * I get it figured out.
9 1.4.4.2 matt *
10 1.4.4.2 matt * So how to run this?
11 1.4.4.2 matt * 0) sh MAKEDEV putter (if you don't have a freshly created /dev)
12 1.4.4.2 matt * 1) run this program with the argument "/dev/pud"
13 1.4.4.2 matt * 2) mknod a char device with the major 377 (see sources below)
14 1.4.4.2 matt * 3) echo ascii art and jokes into device created in previous step
15 1.4.4.2 matt * or read the device
16 1.4.4.2 matt */
17 1.4.4.2 matt
18 1.4.4.2 matt #include <sys/types.h>
19 1.4.4.2 matt
20 1.4.4.2 matt #include <dev/pud/pud_msgif.h>
21 1.4.4.2 matt
22 1.4.4.2 matt #include <err.h>
23 1.4.4.2 matt #include <errno.h>
24 1.4.4.2 matt #include <fcntl.h>
25 1.4.4.2 matt #include <stdio.h>
26 1.4.4.2 matt #include <stdlib.h>
27 1.4.4.2 matt #include <string.h>
28 1.4.4.2 matt #include <unistd.h>
29 1.4.4.2 matt
30 1.4.4.2 matt #include "common.h"
31 1.4.4.2 matt
32 1.4.4.2 matt #define DEFALLOC 1024*1024
33 1.4.4.2 matt #define ECHOSTR1 "Would you like some sauce diable with that?\n"
34 1.4.4.2 matt #define ECHOSTR2 "Nej tack, you fool, I'm happy with my tournedos Rossini\n"
35 1.4.4.2 matt #define NSTR 2
36 1.4.4.2 matt
37 1.4.4.2 matt const char *curstr = ECHOSTR1;
38 1.4.4.2 matt
39 1.4.4.2 matt #ifndef MIN
40 1.4.4.2 matt #define MIN(a,b) ((a)<(b)?(a):(b))
41 1.4.4.2 matt #endif
42 1.4.4.2 matt
43 1.4.4.2 matt int
44 1.4.4.2 matt main(int argc, char *argv[])
45 1.4.4.2 matt {
46 1.4.4.2 matt struct pud_req *pdr = malloc(DEFALLOC);
47 1.4.4.2 matt struct pud_conf_reg pcr;
48 1.4.4.2 matt int fd;
49 1.4.4.2 matt ssize_t n;
50 1.4.4.2 matt
51 1.4.4.2 matt if (argc != 2)
52 1.4.4.2 matt errx(1, "args");
53 1.4.4.2 matt
54 1.4.4.2 matt /*
55 1.4.4.2 matt * open pud device
56 1.4.4.2 matt */
57 1.4.4.2 matt fd = open(argv[1], O_RDWR);
58 1.4.4.2 matt if (fd == -1)
59 1.4.4.2 matt err(1, "open");
60 1.4.4.2 matt
61 1.4.4.2 matt /*
62 1.4.4.2 matt * register our major number
63 1.4.4.2 matt */
64 1.4.4.2 matt memset(&pcr, 0, sizeof(pcr));
65 1.4.4.2 matt pcr.pm_pdr.pdr_pth.pth_framelen = sizeof(struct pud_conf_reg);
66 1.4.4.2 matt pcr.pm_version = PUD_DEVELVERSION | PUD_VERSION;
67 1.4.4.2 matt pcr.pm_pdr.pdr_reqclass = PUD_REQ_CONF;
68 1.4.4.2 matt pcr.pm_pdr.pdr_reqtype = PUD_CONF_REG;
69 1.4.4.2 matt
70 1.4.4.2 matt pcr.pm_regdev = makedev(377, 0);
71 1.4.4.2 matt pcr.pm_flags = PUD_CONFFLAG_BDEV;
72 1.4.4.2 matt strlcpy(pcr.pm_devname, "testdev", sizeof(pcr.pm_devname));
73 1.4.4.2 matt
74 1.4.4.2 matt n = write(fd, &pcr, pcr.pm_pdr.pdr_pth.pth_framelen);
75 1.4.4.2 matt if (n == -1)
76 1.4.4.2 matt err(1, "configure write");
77 1.4.4.2 matt
78 1.4.4.2 matt /*
79 1.4.4.2 matt * process requests
80 1.4.4.2 matt */
81 1.4.4.2 matt for (;;) {
82 1.4.4.2 matt n = read(fd, pdr, DEFALLOC);
83 1.4.4.2 matt printf("read %d %d\n", n, errno);
84 1.4.4.2 matt
85 1.4.4.2 matt switch (pdr->pdr_reqtype) {
86 1.4.4.2 matt case PUD_CDEV_OPEN:
87 1.4.4.2 matt case PUD_CDEV_CLOSE:
88 1.4.4.2 matt printf("got openclose %d\n", pdr->pdr_reqtype);
89 1.4.4.2 matt pdr->pdr_rv = 0;
90 1.4.4.2 matt break;
91 1.4.4.2 matt
92 1.4.4.2 matt case PUD_CDEV_READ:
93 1.4.4.2 matt /* uh oh case PUD_BDEV_STRATREAD: */
94 1.4.4.2 matt {
95 1.4.4.2 matt struct pud_creq_read *pc_read;
96 1.4.4.2 matt size_t clen;
97 1.4.4.2 matt
98 1.4.4.2 matt pc_read = (void *)pdr;
99 1.4.4.2 matt printf("read from offset %llu, resid %zu\n",
100 1.4.4.2 matt (unsigned long long)pc_read->pm_offset,
101 1.4.4.2 matt pc_read->pm_resid);
102 1.4.4.2 matt
103 1.4.4.2 matt clen = MIN(strlen(curstr), pc_read->pm_resid);
104 1.4.4.2 matt strncpy(pc_read->pm_data, curstr, clen);
105 1.4.4.2 matt if (pdr->pdr_reqclass == PUD_REQ_BDEV) {
106 1.4.4.2 matt clen = pc_read->pm_resid;
107 1.4.4.2 matt pc_read->pm_resid = 0;
108 1.4.4.2 matt } else {
109 1.4.4.2 matt pc_read->pm_resid -= clen;
110 1.4.4.2 matt }
111 1.4.4.2 matt pdr->pdr_pth.pth_framelen =
112 1.4.4.2 matt sizeof(struct pud_creq_read) + clen;
113 1.4.4.2 matt }
114 1.4.4.2 matt break;
115 1.4.4.2 matt
116 1.4.4.2 matt case PUD_CDEV_WRITE:
117 1.4.4.2 matt /* uh uh oh case PUD_BDEV_STRATWRITE: */
118 1.4.4.2 matt {
119 1.4.4.2 matt struct pud_creq_write *pc_write;
120 1.4.4.2 matt
121 1.4.4.2 matt pc_write = (void *)pdr;
122 1.4.4.2 matt printf("write to offset %llu, resid %zu\n",
123 1.4.4.2 matt (unsigned long long)pc_write->pm_offset,
124 1.4.4.2 matt pc_write->pm_resid);
125 1.4.4.2 matt
126 1.4.4.2 matt pc_write->pm_data[pc_write->pm_resid] = '\0';
127 1.4.4.2 matt printf("got via write: %s", pc_write->pm_data);
128 1.4.4.2 matt pdr->pdr_pth.pth_framelen =
129 1.4.4.2 matt sizeof(struct pud_creq_write);
130 1.4.4.2 matt pc_write->pm_resid = 0;
131 1.4.4.2 matt }
132 1.4.4.2 matt break;
133 1.4.4.2 matt
134 1.4.4.2 matt case PUD_CDEV_IOCTL:
135 1.4.4.2 matt {
136 1.4.4.2 matt struct pud_req_ioctl *pc_ioctl;
137 1.4.4.2 matt int *iocval;
138 1.4.4.2 matt
139 1.4.4.2 matt pc_ioctl = (void *)pdr;
140 1.4.4.2 matt switch (pc_ioctl->pm_iocmd) {
141 1.4.4.2 matt case INTROTOGGLE:
142 1.4.4.2 matt case INTROTOGGLE_R:
143 1.4.4.2 matt iocval = (int *)pc_ioctl->pm_data;
144 1.4.4.2 matt if (*iocval < 0 || *iocval > 2) {
145 1.4.4.2 matt pdr->pdr_rv = ERANGE;
146 1.4.4.2 matt break;
147 1.4.4.2 matt }
148 1.4.4.2 matt
149 1.4.4.2 matt if (*iocval == 1)
150 1.4.4.2 matt curstr = ECHOSTR1;
151 1.4.4.2 matt else
152 1.4.4.2 matt curstr = ECHOSTR2;
153 1.4.4.2 matt
154 1.4.4.2 matt *iocval = 0;
155 1.4.4.2 matt break;
156 1.4.4.2 matt default:
157 1.4.4.2 matt abort();
158 1.4.4.2 matt }
159 1.4.4.2 matt }
160 1.4.4.2 matt break;
161 1.4.4.2 matt
162 1.4.4.2 matt default:
163 1.4.4.2 matt abort();
164 1.4.4.2 matt }
165 1.4.4.2 matt
166 1.4.4.2 matt n = write(fd, pdr, pdr->pdr_pth.pth_framelen);
167 1.4.4.2 matt printf("wrote %d %d\n", n, errno);
168 1.4.4.2 matt }
169 1.4.4.2 matt }
170