2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
9 * $Id: pps.c,v 1.19 1999/05/31 11:25:00 phk Exp $
11 * This driver implements a draft-mogul-pps-api-02.txt PPS source.
13 * The input pin is pin#10
14 * The echo output pin is pin#14
18 #include <sys/param.h>
19 #include <sys/kernel.h>
20 #include <sys/systm.h>
22 #include <sys/timepps.h>
23 #include <sys/malloc.h>
25 #include <dev/ppbus/ppbconf.h>
28 #define PPS_NAME "pps" /* our official name */
32 struct ppb_device pps_dev;
39 * Make ourselves visible as a ppbus driver
42 static struct ppb_device *ppsprobe(struct ppb_data *ppb);
43 static int ppsattach(struct ppb_device *dev);
44 static void ppsintr(struct ppb_device *ppd);
46 static struct ppb_driver ppsdriver = {
47 ppsprobe, ppsattach, PPS_NAME
50 DATA_SET(ppbdriver_set, ppsdriver);
52 static d_open_t ppsopen;
53 static d_close_t ppsclose;
54 static d_ioctl_t ppsioctl;
57 static struct cdevsw pps_cdevsw = {
65 /* devtotty */ nodevtotty,
68 /* strategy */ nostrategy,
80 static struct ppb_device *
81 ppsprobe(struct ppb_data *ppb)
88 cdevsw_add(&pps_cdevsw);
90 sc = (struct pps_data *) malloc(sizeof(struct pps_data),
93 printf(PPS_NAME ": cannot malloc!\n");
96 bzero(sc, sizeof(struct pps_data));
98 dev = make_dev(&pps_cdevsw, npps,
99 UID_ROOT, GID_WHEEL, 0644, PPS_NAME "%d", npps);
103 sc->pps_dev.id_unit = npps++;
104 sc->pps_dev.ppb = ppb;
105 sc->pps_dev.name = ppsdriver.name;
106 sc->pps_dev.bintr = ppsintr;
107 sc->pps_dev.drv1 = sc;
109 sc->pps.ppscap = PPS_CAPTUREASSERT | PPS_ECHOASSERT;
111 return (&sc->pps_dev);
115 ppsattach(struct ppb_device *dev)
121 printf(PPS_NAME "%d: <Pulse per second Timing Interface> on ppbus %d\n",
122 dev->id_unit, dev->ppb->ppb_link->adapter_unit);
128 ppsopen(dev_t dev, int flags, int fmt, struct proc *p)
131 u_int unit = minor(dev);
139 if (ppb_request_bus(&sc->pps_dev, PPB_WAIT|PPB_INTR))
142 ppb_wctr(&sc->pps_dev, 0);
143 ppb_wctr(&sc->pps_dev, IRQENABLE);
151 ppsclose(dev_t dev, int flags, int fmt, struct proc *p)
153 struct pps_data *sc = dev->si_drv1;
155 sc->pps.ppsparam.mode = 0; /* PHK ??? */
157 ppb_wdtr(&sc->pps_dev, 0);
158 ppb_wctr(&sc->pps_dev, 0);
160 ppb_release_bus(&sc->pps_dev);
166 ppsintr(struct ppb_device *ppd)
168 struct pps_data *sc = ppd->drv1;
169 struct timecounter *tc;
173 count = timecounter->tc_get_timecount(tc);
174 if (!(ppb_rstr(&sc->pps_dev) & nACK))
176 if (sc->pps.ppsparam.mode & PPS_ECHOASSERT)
177 ppb_wctr(&sc->pps_dev, IRQENABLE | AUTOFEED);
178 pps_event(&sc->pps, tc, count, PPS_CAPTUREASSERT);
179 if (sc->pps.ppsparam.mode & PPS_ECHOASSERT)
180 ppb_wctr(&sc->pps_dev, IRQENABLE);
184 ppsioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
186 struct pps_data *sc = dev->si_drv1;
188 return (pps_ioctl(cmd, data, &sc->pps));