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