1 /*- 2 * SPDX-License-Identifier: Beerware 3 * 4 * ---------------------------------------------------------------------------- 5 * "THE BEER-WARE LICENSE" (Revision 42): 6 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 7 * can do whatever you want with this stuff. If we meet some day, and you think 8 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 9 * ---------------------------------------------------------------------------- 10 * 11 * 12 * This driver implements a draft-mogul-pps-api-02.txt PPS source. 13 * 14 * The input pin is pin#10 15 * The echo output pin is pin#14 16 * 17 */ 18 19 #include <sys/cdefs.h> 20 __FBSDID("$FreeBSD$"); 21 22 #include <sys/param.h> 23 #include <sys/lock.h> 24 #include <sys/kernel.h> 25 #include <sys/systm.h> 26 #include <sys/module.h> 27 #include <sys/sx.h> 28 #include <sys/bus.h> 29 #include <sys/conf.h> 30 #include <sys/timepps.h> 31 #include <machine/bus.h> 32 #include <machine/resource.h> 33 #include <sys/rman.h> 34 35 #include <dev/ppbus/ppbconf.h> 36 #include "ppbus_if.h" 37 #include <dev/ppbus/ppbio.h> 38 39 #define PPS_NAME "pps" /* our official name */ 40 41 #define PRVERBOSE(fmt, arg...) if (bootverbose) printf(fmt, ##arg); 42 43 struct pps_data { 44 struct ppb_device pps_dev; 45 struct pps_state pps[9]; 46 struct cdev *devs[9]; 47 device_t ppsdev; 48 device_t ppbus; 49 int busy; 50 struct callout timeout; 51 int lastdata; 52 53 struct sx lock; 54 struct resource *intr_resource; /* interrupt resource */ 55 void *intr_cookie; /* interrupt registration cookie */ 56 }; 57 58 static void ppsintr(void *arg); 59 static void ppshcpoll(void *arg); 60 61 #define DEVTOSOFTC(dev) \ 62 ((struct pps_data *)device_get_softc(dev)) 63 64 static d_open_t ppsopen; 65 static d_close_t ppsclose; 66 static d_ioctl_t ppsioctl; 67 68 static struct cdevsw pps_cdevsw = { 69 .d_version = D_VERSION, 70 .d_open = ppsopen, 71 .d_close = ppsclose, 72 .d_ioctl = ppsioctl, 73 .d_name = PPS_NAME, 74 }; 75 76 static void 77 ppsidentify(driver_t *driver, device_t parent) 78 { 79 80 device_t dev; 81 82 dev = device_find_child(parent, PPS_NAME, -1); 83 if (!dev) 84 BUS_ADD_CHILD(parent, 0, PPS_NAME, -1); 85 } 86 87 static int 88 ppstry(device_t ppbus, int send, int expect) 89 { 90 int i; 91 92 ppb_wdtr(ppbus, send); 93 i = ppb_rdtr(ppbus); 94 PRVERBOSE("S: %02x E: %02x G: %02x\n", send, expect, i); 95 return (i != expect); 96 } 97 98 static int 99 ppsprobe(device_t ppsdev) 100 { 101 device_set_desc(ppsdev, "Pulse per second Timing Interface"); 102 103 return (0); 104 } 105 106 static int 107 ppsattach(device_t dev) 108 { 109 struct pps_data *sc = DEVTOSOFTC(dev); 110 device_t ppbus = device_get_parent(dev); 111 struct cdev *d; 112 int error, i, unit, rid = 0; 113 114 /* declare our interrupt handler */ 115 sc->intr_resource = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 116 RF_SHAREABLE); 117 118 /* interrupts seem mandatory */ 119 if (sc->intr_resource == NULL) { 120 device_printf(dev, "Unable to allocate interrupt resource\n"); 121 return (ENXIO); 122 } 123 124 error = bus_setup_intr(dev, sc->intr_resource, 125 INTR_TYPE_TTY | INTR_MPSAFE, NULL, ppsintr, 126 sc, &sc->intr_cookie); 127 if (error) { 128 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->intr_resource); 129 device_printf(dev, "Unable to register interrupt handler\n"); 130 return (error); 131 } 132 133 sx_init(&sc->lock, "pps"); 134 ppb_init_callout(ppbus, &sc->timeout, 0); 135 sc->ppsdev = dev; 136 sc->ppbus = ppbus; 137 unit = device_get_unit(ppbus); 138 d = make_dev(&pps_cdevsw, unit, 139 UID_ROOT, GID_WHEEL, 0600, PPS_NAME "%d", unit); 140 sc->devs[0] = d; 141 sc->pps[0].ppscap = PPS_CAPTUREASSERT | PPS_ECHOASSERT; 142 sc->pps[0].driver_abi = PPS_ABI_VERSION; 143 sc->pps[0].driver_mtx = ppb_get_lock(ppbus); 144 d->si_drv1 = sc; 145 d->si_drv2 = (void*)0; 146 pps_init_abi(&sc->pps[0]); 147 148 ppb_lock(ppbus); 149 if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) { 150 ppb_unlock(ppbus); 151 return (0); 152 } 153 154 do { 155 i = ppb_set_mode(sc->ppbus, PPB_EPP); 156 PRVERBOSE("EPP: %d %d\n", i, PPB_IN_EPP_MODE(sc->ppbus)); 157 if (i == -1) 158 break; 159 i = 0; 160 ppb_wctr(ppbus, i); 161 if (ppstry(ppbus, 0x00, 0x00)) 162 break; 163 if (ppstry(ppbus, 0x55, 0x55)) 164 break; 165 if (ppstry(ppbus, 0xaa, 0xaa)) 166 break; 167 if (ppstry(ppbus, 0xff, 0xff)) 168 break; 169 170 i = IRQENABLE | PCD | STROBE | nINIT | SELECTIN; 171 ppb_wctr(ppbus, i); 172 PRVERBOSE("CTR = %02x (%02x)\n", ppb_rctr(ppbus), i); 173 if (ppstry(ppbus, 0x00, 0x00)) 174 break; 175 if (ppstry(ppbus, 0x55, 0x00)) 176 break; 177 if (ppstry(ppbus, 0xaa, 0x00)) 178 break; 179 if (ppstry(ppbus, 0xff, 0x00)) 180 break; 181 182 i = IRQENABLE | PCD | nINIT | SELECTIN; 183 ppb_wctr(ppbus, i); 184 PRVERBOSE("CTR = %02x (%02x)\n", ppb_rctr(ppbus), i); 185 ppstry(ppbus, 0x00, 0xff); 186 ppstry(ppbus, 0x55, 0xff); 187 ppstry(ppbus, 0xaa, 0xff); 188 ppstry(ppbus, 0xff, 0xff); 189 ppb_unlock(ppbus); 190 191 for (i = 1; i < 9; i++) { 192 d = make_dev(&pps_cdevsw, unit + 0x10000 * i, 193 UID_ROOT, GID_WHEEL, 0600, PPS_NAME "%db%d", unit, i - 1); 194 sc->devs[i] = d; 195 sc->pps[i].ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; 196 sc->pps[i].driver_abi = PPS_ABI_VERSION; 197 sc->pps[i].driver_mtx = ppb_get_lock(ppbus); 198 d->si_drv1 = sc; 199 d->si_drv2 = (void *)(intptr_t)i; 200 pps_init_abi(&sc->pps[i]); 201 } 202 ppb_lock(ppbus); 203 } while (0); 204 i = ppb_set_mode(sc->ppbus, PPB_COMPATIBLE); 205 ppb_release_bus(ppbus, dev); 206 ppb_unlock(ppbus); 207 208 return (0); 209 } 210 211 static int 212 ppsopen(struct cdev *dev, int flags, int fmt, struct thread *td) 213 { 214 struct pps_data *sc = dev->si_drv1; 215 device_t ppbus = sc->ppbus; 216 int subdev = (intptr_t)dev->si_drv2; 217 int i; 218 219 /* 220 * The sx lock is here solely to serialize open()'s to close 221 * the race of concurrent open()'s when pps(4) doesn't own the 222 * ppbus. 223 */ 224 sx_xlock(&sc->lock); 225 ppb_lock(ppbus); 226 if (!sc->busy) { 227 device_t ppsdev = sc->ppsdev; 228 229 if (ppb_request_bus(ppbus, ppsdev, PPB_WAIT|PPB_INTR)) { 230 ppb_unlock(ppbus); 231 sx_xunlock(&sc->lock); 232 return (EINTR); 233 } 234 235 i = ppb_set_mode(sc->ppbus, PPB_PS2); 236 PRVERBOSE("EPP: %d %d\n", i, PPB_IN_EPP_MODE(sc->ppbus)); 237 238 i = IRQENABLE | PCD | nINIT | SELECTIN; 239 ppb_wctr(ppbus, i); 240 } 241 if (subdev > 0 && !(sc->busy & ~1)) { 242 /* XXX: Timeout of 1? hz/100 instead perhaps? */ 243 callout_reset(&sc->timeout, 1, ppshcpoll, sc); 244 sc->lastdata = ppb_rdtr(sc->ppbus); 245 } 246 sc->busy |= (1 << subdev); 247 ppb_unlock(ppbus); 248 sx_xunlock(&sc->lock); 249 return(0); 250 } 251 252 static int 253 ppsclose(struct cdev *dev, int flags, int fmt, struct thread *td) 254 { 255 struct pps_data *sc = dev->si_drv1; 256 int subdev = (intptr_t)dev->si_drv2; 257 258 sx_xlock(&sc->lock); 259 sc->pps[subdev].ppsparam.mode = 0; /* PHK ??? */ 260 ppb_lock(sc->ppbus); 261 sc->busy &= ~(1 << subdev); 262 if (subdev > 0 && !(sc->busy & ~1)) 263 callout_stop(&sc->timeout); 264 if (!sc->busy) { 265 device_t ppsdev = sc->ppsdev; 266 device_t ppbus = sc->ppbus; 267 268 ppb_wdtr(ppbus, 0); 269 ppb_wctr(ppbus, 0); 270 271 ppb_set_mode(ppbus, PPB_COMPATIBLE); 272 ppb_release_bus(ppbus, ppsdev); 273 } 274 ppb_unlock(sc->ppbus); 275 sx_xunlock(&sc->lock); 276 return(0); 277 } 278 279 static void 280 ppshcpoll(void *arg) 281 { 282 struct pps_data *sc = arg; 283 int i, j, k, l; 284 285 KASSERT(sc->busy & ~1, ("pps polling w/o opened devices")); 286 i = ppb_rdtr(sc->ppbus); 287 if (i == sc->lastdata) 288 return; 289 l = sc->lastdata ^ i; 290 k = 1; 291 for (j = 1; j < 9; j ++) { 292 if (l & k) { 293 pps_capture(&sc->pps[j]); 294 pps_event(&sc->pps[j], 295 i & k ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR); 296 } 297 k += k; 298 } 299 sc->lastdata = i; 300 callout_reset(&sc->timeout, 1, ppshcpoll, sc); 301 } 302 303 static void 304 ppsintr(void *arg) 305 { 306 struct pps_data *sc = (struct pps_data *)arg; 307 308 ppb_assert_locked(sc->ppbus); 309 pps_capture(&sc->pps[0]); 310 if (!(ppb_rstr(sc->ppbus) & nACK)) 311 return; 312 313 if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) 314 ppb_wctr(sc->ppbus, IRQENABLE | AUTOFEED); 315 pps_event(&sc->pps[0], PPS_CAPTUREASSERT); 316 if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) 317 ppb_wctr(sc->ppbus, IRQENABLE); 318 } 319 320 static int 321 ppsioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td) 322 { 323 struct pps_data *sc = dev->si_drv1; 324 int subdev = (intptr_t)dev->si_drv2; 325 int err; 326 327 ppb_lock(sc->ppbus); 328 err = pps_ioctl(cmd, data, &sc->pps[subdev]); 329 ppb_unlock(sc->ppbus); 330 return (err); 331 } 332 333 static device_method_t pps_methods[] = { 334 /* device interface */ 335 DEVMETHOD(device_identify, ppsidentify), 336 DEVMETHOD(device_probe, ppsprobe), 337 DEVMETHOD(device_attach, ppsattach), 338 { 0, 0 } 339 }; 340 341 static driver_t pps_driver = { 342 PPS_NAME, 343 pps_methods, 344 sizeof(struct pps_data), 345 }; 346 347 DRIVER_MODULE(pps, ppbus, pps_driver, 0, 0); 348 MODULE_DEPEND(pps, ppbus, 1, 1, 1); 349