Deleted Added
full compact
pps.c (51658) pps.c (55939)
1/*
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 * ----------------------------------------------------------------------------
8 *
1/*
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 * ----------------------------------------------------------------------------
8 *
9 * $FreeBSD: head/sys/dev/ppbus/pps.c 51658 1999-09-25 18:24:47Z phk $
9 * $FreeBSD: head/sys/dev/ppbus/pps.c 55939 2000-01-14 00:18:06Z nsouch $
10 *
11 * This driver implements a draft-mogul-pps-api-02.txt PPS source.
12 *
13 * The input pin is pin#10
14 * The echo output pin is pin#14
15 *
16 */
17
18#include <sys/param.h>
19#include <sys/kernel.h>
20#include <sys/systm.h>
10 *
11 * This driver implements a draft-mogul-pps-api-02.txt PPS source.
12 *
13 * The input pin is pin#10
14 * The echo output pin is pin#14
15 *
16 */
17
18#include <sys/param.h>
19#include <sys/kernel.h>
20#include <sys/systm.h>
21#include <sys/module.h>
22#include <sys/bus.h>
21#include <sys/conf.h>
22#include <sys/timepps.h>
23#include <sys/malloc.h>
23#include <sys/conf.h>
24#include <sys/timepps.h>
25#include <sys/malloc.h>
26#include <machine/bus.h>
27#include <machine/resource.h>
28#include <sys/rman.h>
24
25#include <dev/ppbus/ppbconf.h>
29
30#include <dev/ppbus/ppbconf.h>
31#include "ppbus_if.h"
32#include <dev/ppbus/ppbio.h>
26#include "pps.h"
27
28#define PPS_NAME "pps" /* our official name */
29
30struct pps_data {
31 int pps_open;
32 struct ppb_device pps_dev;
33 struct pps_state pps;
33#include "pps.h"
34
35#define PPS_NAME "pps" /* our official name */
36
37struct pps_data {
38 int pps_open;
39 struct ppb_device pps_dev;
40 struct pps_state pps;
41
42 struct resource *intr_resource; /* interrupt resource */
43 void *intr_cookie; /* interrupt registration cookie */
34};
35
44};
45
36static int npps;
46static int ppsprobe(device_t dev);
47static int ppsattach(device_t dev);
48static void ppsintr(void *arg);
37
49
38/*
39 * Make ourselves visible as a ppbus driver
40 */
50#define DEVTOSOFTC(dev) \
51 ((struct pps_data *)device_get_softc(dev))
52#define UNITOSOFTC(unit) \
53 ((struct pps_data *)devclass_get_softc(pps_devclass, (unit)))
54#define UNITODEVICE(unit) \
55 (devclass_get_device(pps_devclass, (unit)))
41
56
42static struct ppb_device *ppsprobe(struct ppb_data *ppb);
43static int ppsattach(struct ppb_device *dev);
44static void ppsintr(struct ppb_device *ppd);
57static devclass_t pps_devclass;
45
58
46static struct ppb_driver ppsdriver = {
47 ppsprobe, ppsattach, PPS_NAME
59static device_method_t pps_methods[] = {
60 /* device interface */
61 DEVMETHOD(device_probe, ppsprobe),
62 DEVMETHOD(device_attach, ppsattach),
63
64 { 0, 0 }
48};
49
65};
66
50DATA_SET(ppbdriver_set, ppsdriver);
67static driver_t pps_driver = {
68 PPS_NAME,
69 pps_methods,
70 sizeof(struct pps_data),
71};
51
52static d_open_t ppsopen;
53static d_close_t ppsclose;
54static d_ioctl_t ppsioctl;
55
56#define CDEV_MAJOR 89
57static struct cdevsw pps_cdevsw = {
58 /* open */ ppsopen,

--- 7 unchanged lines hidden (view full) ---

66 /* name */ PPS_NAME,
67 /* maj */ CDEV_MAJOR,
68 /* dump */ nodump,
69 /* psize */ nopsize,
70 /* flags */ 0,
71 /* bmaj */ -1
72};
73
72
73static d_open_t ppsopen;
74static d_close_t ppsclose;
75static d_ioctl_t ppsioctl;
76
77#define CDEV_MAJOR 89
78static struct cdevsw pps_cdevsw = {
79 /* open */ ppsopen,

--- 7 unchanged lines hidden (view full) ---

87 /* name */ PPS_NAME,
88 /* maj */ CDEV_MAJOR,
89 /* dump */ nodump,
90 /* psize */ nopsize,
91 /* flags */ 0,
92 /* bmaj */ -1
93};
94
74
75static struct ppb_device *
76ppsprobe(struct ppb_data *ppb)
95static int
96ppsprobe(device_t ppsdev)
77{
78 struct pps_data *sc;
79 static int once;
80 dev_t dev;
97{
98 struct pps_data *sc;
99 static int once;
100 dev_t dev;
101 int unit;
81
82 if (!once++)
83 cdevsw_add(&pps_cdevsw);
84
102
103 if (!once++)
104 cdevsw_add(&pps_cdevsw);
105
85 sc = (struct pps_data *) malloc(sizeof(struct pps_data),
86 M_TEMP, M_NOWAIT);
87 if (!sc) {
88 printf(PPS_NAME ": cannot malloc!\n");
89 return (0);
90 }
106 sc = DEVTOSOFTC(ppsdev);
91 bzero(sc, sizeof(struct pps_data));
92
107 bzero(sc, sizeof(struct pps_data));
108
93 dev = make_dev(&pps_cdevsw, npps,
94 UID_ROOT, GID_WHEEL, 0644, PPS_NAME "%d", npps);
109 unit = device_get_unit(ppsdev);
110 dev = make_dev(&pps_cdevsw, unit,
111 UID_ROOT, GID_WHEEL, 0644, PPS_NAME "%d", unit);
95
112
96 dev->si_drv1 = sc;
113 device_set_desc(ppsdev, "Pulse per second Timing Interface");
97
114
98 sc->pps_dev.id_unit = npps++;
99 sc->pps_dev.ppb = ppb;
100 sc->pps_dev.name = ppsdriver.name;
101 sc->pps_dev.bintr = ppsintr;
102 sc->pps_dev.drv1 = sc;
103
104 sc->pps.ppscap = PPS_CAPTUREASSERT | PPS_ECHOASSERT;
105 pps_init(&sc->pps);
115 sc->pps.ppscap = PPS_CAPTUREASSERT | PPS_ECHOASSERT;
116 pps_init(&sc->pps);
106 return (&sc->pps_dev);
117 return (0);
107}
108
109static int
118}
119
120static int
110ppsattach(struct ppb_device *dev)
121ppsattach(device_t dev)
111{
122{
123 struct pps_data *sc = DEVTOSOFTC(dev);
124 device_t ppbus = device_get_parent(dev);
125 int irq, zero = 0;
112
126
113 /*
114 * Report ourselves
115 */
116 printf(PPS_NAME "%d: <Pulse per second Timing Interface> on ppbus %d\n",
117 dev->id_unit, dev->ppb->ppb_link->adapter_unit);
127 /* retrieve the ppbus irq */
128 BUS_READ_IVAR(ppbus, dev, PPBUS_IVAR_IRQ, &irq);
118
129
119 return (1);
130 if (irq > 0) {
131 /* declare our interrupt handler */
132 sc->intr_resource = bus_alloc_resource(dev, SYS_RES_IRQ,
133 &zero, irq, irq, 1, RF_SHAREABLE);
134 }
135 /* interrupts seem mandatory */
136 if (sc->intr_resource == 0)
137 return (ENXIO);
138
139 return (0);
120}
121
122static int
123ppsopen(dev_t dev, int flags, int fmt, struct proc *p)
124{
140}
141
142static int
143ppsopen(dev_t dev, int flags, int fmt, struct proc *p)
144{
125 struct pps_data *sc;
126 u_int unit = minor(dev);
145 u_int unit = minor(dev);
146 struct pps_data *sc = UNITOSOFTC(unit);
147 device_t ppsdev = UNITODEVICE(unit);
148 device_t ppbus = device_get_parent(ppsdev);
149 int error;
127
150
128 if ((unit >= npps))
129 return (ENXIO);
130
131 sc = dev->si_drv1;
132
133 if (!sc->pps_open) {
151 if (!sc->pps_open) {
134 if (ppb_request_bus(&sc->pps_dev, PPB_WAIT|PPB_INTR))
152 if (ppb_request_bus(ppbus, ppsdev, PPB_WAIT|PPB_INTR))
135 return (EINTR);
136
153 return (EINTR);
154
137 ppb_wctr(&sc->pps_dev, 0);
138 ppb_wctr(&sc->pps_dev, IRQENABLE);
155 /* attach the interrupt handler */
156 if ((error = BUS_SETUP_INTR(ppbus, ppsdev, sc->intr_resource,
157 INTR_TYPE_TTY, ppsintr, ppsdev,
158 &sc->intr_cookie))) {
159 ppb_release_bus(ppbus, ppsdev);
160 return (error);
161 }
162
163 ppb_wctr(ppbus, 0);
164 ppb_wctr(ppbus, IRQENABLE);
139 sc->pps_open = 1;
140 }
141
142 return(0);
143}
144
145static int
146ppsclose(dev_t dev, int flags, int fmt, struct proc *p)
147{
165 sc->pps_open = 1;
166 }
167
168 return(0);
169}
170
171static int
172ppsclose(dev_t dev, int flags, int fmt, struct proc *p)
173{
148 struct pps_data *sc = dev->si_drv1;
174 u_int unit = minor(dev);
175 struct pps_data *sc = UNITOSOFTC(unit);
176 device_t ppsdev = UNITODEVICE(unit);
177 device_t ppbus = device_get_parent(ppsdev);
149
150 sc->pps.ppsparam.mode = 0; /* PHK ??? */
151
178
179 sc->pps.ppsparam.mode = 0; /* PHK ??? */
180
152 ppb_wdtr(&sc->pps_dev, 0);
153 ppb_wctr(&sc->pps_dev, 0);
181 ppb_wdtr(ppbus, 0);
182 ppb_wctr(ppbus, 0);
154
183
155 ppb_release_bus(&sc->pps_dev);
184 /* Note: the interrupt handler is automatically detached */
185 ppb_release_bus(ppbus, ppsdev);
156 sc->pps_open = 0;
157 return(0);
158}
159
160static void
186 sc->pps_open = 0;
187 return(0);
188}
189
190static void
161ppsintr(struct ppb_device *ppd)
191ppsintr(void *arg)
162{
192{
163 struct pps_data *sc = ppd->drv1;
193 device_t ppsdev = (device_t)arg;
194 device_t ppbus = device_get_parent(ppsdev);
195 struct pps_data *sc = DEVTOSOFTC(ppsdev);
164 struct timecounter *tc;
165 unsigned count;
166
167 tc = timecounter;
168 count = timecounter->tc_get_timecount(tc);
196 struct timecounter *tc;
197 unsigned count;
198
199 tc = timecounter;
200 count = timecounter->tc_get_timecount(tc);
169 if (!(ppb_rstr(&sc->pps_dev) & nACK))
201 if (!(ppb_rstr(ppbus) & nACK))
170 return;
171 if (sc->pps.ppsparam.mode & PPS_ECHOASSERT)
202 return;
203 if (sc->pps.ppsparam.mode & PPS_ECHOASSERT)
172 ppb_wctr(&sc->pps_dev, IRQENABLE | AUTOFEED);
204 ppb_wctr(ppbus, IRQENABLE | AUTOFEED);
173 pps_event(&sc->pps, tc, count, PPS_CAPTUREASSERT);
174 if (sc->pps.ppsparam.mode & PPS_ECHOASSERT)
205 pps_event(&sc->pps, tc, count, PPS_CAPTUREASSERT);
206 if (sc->pps.ppsparam.mode & PPS_ECHOASSERT)
175 ppb_wctr(&sc->pps_dev, IRQENABLE);
207 ppb_wctr(ppbus, IRQENABLE);
176}
177
178static int
179ppsioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
180{
208}
209
210static int
211ppsioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
212{
181 struct pps_data *sc = dev->si_drv1;
213 u_int unit = minor(dev);
214 struct pps_data *sc = UNITOSOFTC(unit);
182
183 return (pps_ioctl(cmd, data, &sc->pps));
184}
185
215
216 return (pps_ioctl(cmd, data, &sc->pps));
217}
218
219DRIVER_MODULE(pps, ppbus, pps_driver, pps_devclass, 0, 0);