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