pps.c revision 44666
133323Sphk/* 233323Sphk * ---------------------------------------------------------------------------- 333323Sphk * "THE BEER-WARE LICENSE" (Revision 42): 433323Sphk * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 533323Sphk * can do whatever you want with this stuff. If we meet some day, and you think 633323Sphk * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 733323Sphk * ---------------------------------------------------------------------------- 833323Sphk * 944666Sphk * $Id: pps.c,v 1.13 1999/01/30 15:35:39 nsouch Exp $ 1033323Sphk * 1136938Sphk * This driver implements a draft-mogul-pps-api-02.txt PPS source. 1236938Sphk * 1336938Sphk * The input pin is pin#10 1436938Sphk * The echo output pin is pin#14 1536938Sphk * 1633323Sphk */ 1733323Sphk 1833396Sphk#include "opt_devfs.h" 1933396Sphk 2033323Sphk#include <sys/param.h> 2133323Sphk#include <sys/kernel.h> 2233323Sphk#include <sys/systm.h> 2333323Sphk#include <sys/conf.h> 2436739Sphk#include <sys/timepps.h> 2533323Sphk#ifdef DEVFS 2633323Sphk#include <sys/devfsext.h> 2733396Sphk#endif 2833323Sphk#include <sys/malloc.h> 2933323Sphk 3033323Sphk#include <dev/ppbus/ppbconf.h> 3133326Sphk#include "pps.h" 3233323Sphk 3336739Sphk#define PPS_NAME "lppps" /* our official name */ 3433323Sphk 3533396Sphkstatic struct pps_data { 3633396Sphk int pps_unit; 3733396Sphk struct ppb_device pps_dev; 3844666Sphk struct pps_state pps; 3933326Sphk} *softc[NPPS]; 4033323Sphk 4133396Sphkstatic int npps; 4244666Sphkstatic pps_devsw_installed = 0; 4333323Sphk 4433323Sphk/* 4533323Sphk * Make ourselves visible as a ppbus driver 4633323Sphk */ 4733323Sphk 4833396Sphkstatic struct ppb_device *ppsprobe(struct ppb_data *ppb); 4933396Sphkstatic int ppsattach(struct ppb_device *dev); 5033396Sphkstatic void ppsintr(int unit); 5133396Sphkstatic void pps_drvinit(void *unused); 5233323Sphk 5333396Sphkstatic struct ppb_driver ppsdriver = { 5433396Sphk ppsprobe, ppsattach, PPS_NAME 5533323Sphk}; 5633323Sphk 5733396SphkDATA_SET(ppbdriver_set, ppsdriver); 5833323Sphk 5933396Sphkstatic d_open_t ppsopen; 6033396Sphkstatic d_close_t ppsclose; 6136739Sphkstatic d_ioctl_t ppsioctl; 6233323Sphk 6333323Sphk#define CDEV_MAJOR 89 6433396Sphkstatic struct cdevsw pps_cdevsw = 6536739Sphk { ppsopen, ppsclose, noread, nowrite, 6636739Sphk ppsioctl, nullstop, nullreset, nodevtotty, 6733326Sphk seltrue, nommap, nostrat, PPS_NAME, 6833323Sphk NULL, -1 }; 6933323Sphk 7044666Sphk 7133323Sphkstatic struct ppb_device * 7233396Sphkppsprobe(struct ppb_data *ppb) 7333323Sphk{ 7433396Sphk struct pps_data *sc; 7533323Sphk 7633396Sphk sc = (struct pps_data *) malloc(sizeof(struct pps_data), 7733323Sphk M_TEMP, M_NOWAIT); 7833323Sphk if (!sc) { 7933326Sphk printf(PPS_NAME ": cannot malloc!\n"); 8033323Sphk return (0); 8133323Sphk } 8233396Sphk bzero(sc, sizeof(struct pps_data)); 8333323Sphk 8433396Sphk softc[npps] = sc; 8533323Sphk 8633396Sphk sc->pps_unit = npps++; 8733323Sphk 8833396Sphk sc->pps_dev.id_unit = sc->pps_unit; 8933396Sphk sc->pps_dev.ppb = ppb; 9038061Smsmith sc->pps_dev.name = ppsdriver.name; 9133396Sphk sc->pps_dev.intr = ppsintr; 9233323Sphk 9344666Sphk sc->pps.ppscap = PPS_CAPTUREASSERT | PPS_ECHOASSERT; 9444666Sphk pps_init(&sc->pps); 9533396Sphk return (&sc->pps_dev); 9633323Sphk} 9733323Sphk 9833323Sphkstatic int 9933396Sphkppsattach(struct ppb_device *dev) 10033323Sphk{ 10144666Sphk dev_t devt; 10244666Sphk 10333323Sphk /* 10433323Sphk * Report ourselves 10533323Sphk */ 10633326Sphk printf(PPS_NAME "%d: <Pulse per second Timing Interface> on ppbus %d\n", 10733323Sphk dev->id_unit, dev->ppb->ppb_link->adapter_unit); 10833323Sphk 10933323Sphk#ifdef DEVFS 11033396Sphk devfs_add_devswf(&pps_cdevsw, 11133323Sphk dev->id_unit, DV_CHR, 11233326Sphk UID_ROOT, GID_WHEEL, 0600, PPS_NAME "%d", dev->id_unit); 11333323Sphk#endif 11444666Sphk if( ! pps_devsw_installed ) { 11544666Sphk devt = makedev(CDEV_MAJOR, 0); 11644666Sphk cdevsw_add(&devt, &pps_cdevsw, NULL); 11744666Sphk pps_devsw_installed = 1; 11844666Sphk } 11933323Sphk return (1); 12033323Sphk} 12133323Sphk 12233323Sphkstatic int 12333396Sphkppsopen(dev_t dev, int flags, int fmt, struct proc *p) 12433323Sphk{ 12533396Sphk struct pps_data *sc; 12633323Sphk u_int unit = minor(dev); 12733323Sphk 12833396Sphk if ((unit >= npps)) 12933323Sphk return (ENXIO); 13033323Sphk 13133323Sphk sc = softc[unit]; 13233323Sphk 13333396Sphk if (ppb_request_bus(&sc->pps_dev, PPB_WAIT|PPB_INTR)) 13433323Sphk return (EINTR); 13533323Sphk 13643433Snsouch ppb_wctr(&sc->pps_dev, 0); 13736739Sphk ppb_wctr(&sc->pps_dev, IRQENABLE); 13833323Sphk 13933323Sphk return(0); 14033323Sphk} 14133323Sphk 14233323Sphkstatic int 14333396Sphkppsclose(dev_t dev, int flags, int fmt, struct proc *p) 14433323Sphk{ 14533396Sphk struct pps_data *sc = softc[minor(dev)]; 14633323Sphk 14744666Sphk sc->pps.ppsparam.mode = 0; /* PHK ??? */ 14843433Snsouch 14943433Snsouch ppb_wdtr(&sc->pps_dev, 0); 15043433Snsouch ppb_wctr(&sc->pps_dev, 0); 15143433Snsouch 15233396Sphk ppb_release_bus(&sc->pps_dev); 15333323Sphk return(0); 15433323Sphk} 15533323Sphk 15633323Sphkstatic void 15733396Sphkppsintr(int unit) 15833323Sphk{ 15933396Sphk struct pps_data *sc = softc[unit]; 16044666Sphk struct timecounter *tc; 16144666Sphk unsigned count; 16233323Sphk 16344666Sphk tc = timecounter; 16444666Sphk count = timecounter->tc_get_timecount(tc); 16533396Sphk if (!(ppb_rstr(&sc->pps_dev) & nACK)) 16633323Sphk return; 16744666Sphk if (sc->pps.ppsparam.mode & PPS_ECHOASSERT) 16836739Sphk ppb_wctr(&sc->pps_dev, IRQENABLE | AUTOFEED); 16944666Sphk pps_event(&sc->pps, tc, count, PPS_CAPTUREASSERT); 17044666Sphk if (sc->pps.ppsparam.mode & PPS_ECHOASSERT) 17136739Sphk ppb_wctr(&sc->pps_dev, IRQENABLE); 17233323Sphk} 17333323Sphk 17436739Sphkstatic int 17536748Sbdeppsioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 17633323Sphk{ 17733396Sphk struct pps_data *sc = softc[minor(dev)]; 17833323Sphk 17944666Sphk return (pps_ioctl(cmd, data, &sc->pps)); 18033323Sphk} 18133323Sphk 182