pps.c revision 51658
1171802Sdelphij/* 2170808Sdelphij * ---------------------------------------------------------------------------- 3182739Sdelphij * "THE BEER-WARE LICENSE" (Revision 42): 4171802Sdelphij * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 5170808Sdelphij * can do whatever you want with this stuff. If we meet some day, and you think 6170808Sdelphij * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7170808Sdelphij * ---------------------------------------------------------------------------- 8170808Sdelphij * 9170808Sdelphij * $FreeBSD: head/sys/dev/ppbus/pps.c 51658 1999-09-25 18:24:47Z phk $ 10170808Sdelphij * 11170808Sdelphij * This driver implements a draft-mogul-pps-api-02.txt PPS source. 12170808Sdelphij * 13170808Sdelphij * The input pin is pin#10 14170808Sdelphij * The echo output pin is pin#14 15170808Sdelphij * 16170808Sdelphij */ 17170808Sdelphij 18170808Sdelphij#include <sys/param.h> 19170808Sdelphij#include <sys/kernel.h> 20170808Sdelphij#include <sys/systm.h> 21170808Sdelphij#include <sys/conf.h> 22170808Sdelphij#include <sys/timepps.h> 23170808Sdelphij#include <sys/malloc.h> 24170808Sdelphij 25170808Sdelphij#include <dev/ppbus/ppbconf.h> 26170808Sdelphij#include "pps.h" 27170808Sdelphij 28170808Sdelphij#define PPS_NAME "pps" /* our official name */ 29170808Sdelphij 30170808Sdelphijstruct pps_data { 31170808Sdelphij int pps_open; 32170808Sdelphij struct ppb_device pps_dev; 33170808Sdelphij struct pps_state pps; 34170808Sdelphij}; 35170808Sdelphij 36170808Sdelphijstatic int npps; 37170808Sdelphij 38170808Sdelphij/* 39170808Sdelphij * Make ourselves visible as a ppbus driver 40170808Sdelphij */ 41170808Sdelphij 42170808Sdelphijstatic struct ppb_device *ppsprobe(struct ppb_data *ppb); 43170808Sdelphijstatic int ppsattach(struct ppb_device *dev); 44170808Sdelphijstatic void ppsintr(struct ppb_device *ppd); 45197850Sdelphij 46197850Sdelphijstatic struct ppb_driver ppsdriver = { 47170808Sdelphij ppsprobe, ppsattach, PPS_NAME 48170808Sdelphij}; 49170808Sdelphij 50170808SdelphijDATA_SET(ppbdriver_set, ppsdriver); 51170808Sdelphij 52170808Sdelphijstatic d_open_t ppsopen; 53170808Sdelphijstatic d_close_t ppsclose; 54170808Sdelphijstatic d_ioctl_t ppsioctl; 55170808Sdelphij 56188929Salc#define CDEV_MAJOR 89 57170808Sdelphijstatic struct cdevsw pps_cdevsw = { 58170808Sdelphij /* open */ ppsopen, 59170808Sdelphij /* close */ ppsclose, 60170808Sdelphij /* read */ noread, 61170808Sdelphij /* write */ nowrite, 62170808Sdelphij /* ioctl */ ppsioctl, 63170808Sdelphij /* poll */ nopoll, 64170808Sdelphij /* mmap */ nommap, 65171069Sdelphij /* strategy */ nostrategy, 66170808Sdelphij /* name */ PPS_NAME, 67170808Sdelphij /* maj */ CDEV_MAJOR, 68170808Sdelphij /* dump */ nodump, 69170808Sdelphij /* psize */ nopsize, 70170808Sdelphij /* flags */ 0, 71170808Sdelphij /* bmaj */ -1 72170808Sdelphij}; 73170808Sdelphij 74170808Sdelphij 75170808Sdelphijstatic struct ppb_device * 76170808Sdelphijppsprobe(struct ppb_data *ppb) 77170808Sdelphij{ 78170808Sdelphij struct pps_data *sc; 79170808Sdelphij static int once; 80191990Sattilio dev_t dev; 81170808Sdelphij 82170808Sdelphij if (!once++) 83170808Sdelphij cdevsw_add(&pps_cdevsw); 84170808Sdelphij 85170808Sdelphij sc = (struct pps_data *) malloc(sizeof(struct pps_data), 86170808Sdelphij M_TEMP, M_NOWAIT); 87170808Sdelphij if (!sc) { 88170808Sdelphij printf(PPS_NAME ": cannot malloc!\n"); 89197953Sdelphij return (0); 90197953Sdelphij } 91197953Sdelphij bzero(sc, sizeof(struct pps_data)); 92197953Sdelphij 93197953Sdelphij dev = make_dev(&pps_cdevsw, npps, 94170808Sdelphij UID_ROOT, GID_WHEEL, 0644, PPS_NAME "%d", npps); 95171799Sdelphij 96171799Sdelphij dev->si_drv1 = sc; 97176559Sattilio 98171802Sdelphij sc->pps_dev.id_unit = npps++; 99175294Sattilio sc->pps_dev.ppb = ppb; 100170808Sdelphij sc->pps_dev.name = ppsdriver.name; 101171799Sdelphij sc->pps_dev.bintr = ppsintr; 102191990Sattilio sc->pps_dev.drv1 = sc; 103170808Sdelphij 104175202Sattilio sc->pps.ppscap = PPS_CAPTUREASSERT | PPS_ECHOASSERT; 105171802Sdelphij pps_init(&sc->pps); 106170808Sdelphij return (&sc->pps_dev); 107170808Sdelphij} 108170808Sdelphij 109170808Sdelphijstatic int 110170808Sdelphijppsattach(struct ppb_device *dev) 111188318Skib{ 112211598Sed 113211598Sed /* 114211598Sed * Report ourselves 115170808Sdelphij */ 116170808Sdelphij printf(PPS_NAME "%d: <Pulse per second Timing Interface> on ppbus %d\n", 117170808Sdelphij dev->id_unit, dev->ppb->ppb_link->adapter_unit); 118170808Sdelphij 119170808Sdelphij return (1); 120170808Sdelphij} 121211598Sed 122211598Sedstatic int 123211598Sedppsopen(dev_t dev, int flags, int fmt, struct proc *p) 124211598Sed{ 125170808Sdelphij struct pps_data *sc; 126170808Sdelphij u_int unit = minor(dev); 127170808Sdelphij 128170808Sdelphij if ((unit >= npps)) 129170808Sdelphij return (ENXIO); 130170808Sdelphij 131170808Sdelphij sc = dev->si_drv1; 132170808Sdelphij 133170808Sdelphij if (!sc->pps_open) { 134170808Sdelphij if (ppb_request_bus(&sc->pps_dev, PPB_WAIT|PPB_INTR)) 135170808Sdelphij return (EINTR); 136170808Sdelphij 137170808Sdelphij ppb_wctr(&sc->pps_dev, 0); 138170808Sdelphij ppb_wctr(&sc->pps_dev, IRQENABLE); 139170808Sdelphij sc->pps_open = 1; 140170808Sdelphij } 141170808Sdelphij 142170808Sdelphij return(0); 143170808Sdelphij} 144170808Sdelphij 145170808Sdelphijstatic int 146170808Sdelphijppsclose(dev_t dev, int flags, int fmt, struct proc *p) 147170808Sdelphij{ 148170808Sdelphij struct pps_data *sc = dev->si_drv1; 149170808Sdelphij 150170808Sdelphij sc->pps.ppsparam.mode = 0; /* PHK ??? */ 151170808Sdelphij 152170808Sdelphij ppb_wdtr(&sc->pps_dev, 0); 153170808Sdelphij ppb_wctr(&sc->pps_dev, 0); 154170808Sdelphij 155170808Sdelphij ppb_release_bus(&sc->pps_dev); 156170808Sdelphij sc->pps_open = 0; 157170808Sdelphij return(0); 158170808Sdelphij} 159170808Sdelphij 160170808Sdelphijstatic void 161170808Sdelphijppsintr(struct ppb_device *ppd) 162170808Sdelphij{ 163170808Sdelphij struct pps_data *sc = ppd->drv1; 164170808Sdelphij struct timecounter *tc; 165171070Sdelphij unsigned count; 166170808Sdelphij 167171799Sdelphij tc = timecounter; 168191990Sattilio count = timecounter->tc_get_timecount(tc); 169170808Sdelphij if (!(ppb_rstr(&sc->pps_dev) & nACK)) 170170808Sdelphij return; 171170808Sdelphij if (sc->pps.ppsparam.mode & PPS_ECHOASSERT) 172170808Sdelphij ppb_wctr(&sc->pps_dev, IRQENABLE | AUTOFEED); 173170808Sdelphij pps_event(&sc->pps, tc, count, PPS_CAPTUREASSERT); 174170808Sdelphij if (sc->pps.ppsparam.mode & PPS_ECHOASSERT) 175170808Sdelphij ppb_wctr(&sc->pps_dev, IRQENABLE); 176170808Sdelphij} 177170808Sdelphij 178170808Sdelphijstatic int 179171070Sdelphijppsioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 180170808Sdelphij{ 181171799Sdelphij struct pps_data *sc = dev->si_drv1; 182171799Sdelphij 183191990Sattilio return (pps_ioctl(cmd, data, &sc->pps)); 184170808Sdelphij} 185170808Sdelphij 186170808Sdelphij