The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/misc/pps/pps.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: src/sys/dev/ppbus/pps.c,v 1.24.2.1 2000/05/24 00:20:57 n_hibma Exp $
   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/conf.h>
   22 #include <sys/device.h>
   23 #include <sys/module.h>
   24 #include <sys/bus.h>
   25 #include <sys/timepps.h>
   26 #include <sys/rman.h>
   27 
   28 #include <bus/ppbus/ppbconf.h>
   29 #include <bus/ppbus/ppbio.h>
   30 
   31 #include "ppbus_if.h"
   32 
   33 #define PPS_NAME        "pps"           /* our official name */
   34 
   35 struct pps_data {
   36         int     pps_open;
   37         struct  ppb_device pps_dev;     
   38         struct  pps_state pps;
   39 
   40         struct resource *intr_resource; /* interrupt resource */
   41         void *intr_cookie;              /* interrupt registration cookie */
   42 };
   43 
   44 static void     ppsintr(void *arg);
   45 
   46 #define DEVTOSOFTC(dev) \
   47         ((struct pps_data *)device_get_softc(dev))
   48 #define UNITOSOFTC(unit) \
   49         ((struct pps_data *)devclass_get_softc(pps_devclass, (unit)))
   50 #define UNITODEVICE(unit) \
   51         (devclass_get_device(pps_devclass, (unit)))
   52 
   53 static devclass_t pps_devclass;
   54 
   55 static  d_open_t        ppsopen;
   56 static  d_close_t       ppsclose;
   57 static  d_ioctl_t       ppsioctl;
   58 
   59 static struct dev_ops pps_ops = {
   60         { PPS_NAME, 0, 0 },
   61         .d_open =       ppsopen,
   62         .d_close =      ppsclose,
   63         .d_ioctl =      ppsioctl,
   64 };
   65 
   66 static int
   67 ppsprobe(device_t ppsdev)
   68 {
   69         struct pps_data *sc;
   70 
   71         sc = DEVTOSOFTC(ppsdev);
   72         bzero(sc, sizeof(struct pps_data));
   73 
   74         device_set_desc(ppsdev, "Pulse per second Timing Interface");
   75 
   76         sc->pps.ppscap = PPS_CAPTUREASSERT | PPS_ECHOASSERT;
   77         pps_init(&sc->pps);
   78         return (0);
   79 }
   80 
   81 static int
   82 ppsattach(device_t ppsdev)
   83 {
   84         struct pps_data *sc = DEVTOSOFTC(ppsdev);
   85         device_t ppbus = device_get_parent(ppsdev);
   86         uintptr_t irq;
   87         int unit;
   88         int zero = 0;
   89 
   90         /* retrieve the ppbus irq */
   91         BUS_READ_IVAR(ppbus, ppsdev, PPBUS_IVAR_IRQ, &irq);
   92 
   93         if (irq > 0) {
   94                 /* declare our interrupt handler */
   95                 sc->intr_resource = bus_alloc_legacy_irq_resource(ppsdev,
   96                     &zero, irq, RF_SHAREABLE);
   97         }
   98         /* interrupts seem mandatory */
   99         if (sc->intr_resource == NULL)
  100                 return (ENXIO);
  101 
  102         unit = device_get_unit(ppsdev);
  103         make_dev(&pps_ops, unit, UID_ROOT, GID_WHEEL,
  104                  0644, PPS_NAME "%d", unit);
  105         return (0);
  106 }
  107 
  108 static  int
  109 ppsopen(struct dev_open_args *ap)
  110 {
  111         cdev_t dev = ap->a_head.a_dev;
  112         u_int unit = minor(dev);
  113         struct pps_data *sc = UNITOSOFTC(unit);
  114         device_t ppsdev = UNITODEVICE(unit);
  115         device_t ppbus = device_get_parent(ppsdev);
  116         int error;
  117 
  118         if (!sc->pps_open) {
  119                 if (ppb_request_bus(ppbus, ppsdev, PPB_WAIT|PPB_INTR))
  120                         return (EINTR);
  121 
  122                 /* attach the interrupt handler */
  123                 if ((error = BUS_SETUP_INTR(ppbus, ppsdev, sc->intr_resource,
  124                                0, ppsintr, ppsdev,
  125                                &sc->intr_cookie, NULL, NULL))) {
  126                         ppb_release_bus(ppbus, ppsdev);
  127                         return (error);
  128                 }
  129 
  130                 ppb_wctr(ppbus, 0);
  131                 ppb_wctr(ppbus, IRQENABLE);
  132                 sc->pps_open = 1;
  133         }
  134 
  135         return(0);
  136 }
  137 
  138 static  int
  139 ppsclose(struct dev_close_args *ap)
  140 {
  141         cdev_t dev = ap->a_head.a_dev;
  142         u_int unit = minor(dev);
  143         struct pps_data *sc = UNITOSOFTC(unit);
  144         device_t ppsdev = UNITODEVICE(unit);
  145         device_t ppbus = device_get_parent(ppsdev);
  146 
  147         sc->pps.ppsparam.mode = 0;      /* PHK ??? */
  148 
  149         ppb_wdtr(ppbus, 0);
  150         ppb_wctr(ppbus, 0);
  151 
  152         /* Note: the interrupt handler is automatically detached */
  153         ppb_release_bus(ppbus, ppsdev);
  154         sc->pps_open = 0;
  155         return(0);
  156 }
  157 
  158 static void
  159 ppsintr(void *arg)
  160 {
  161         device_t ppsdev = (device_t)arg;
  162         device_t ppbus = device_get_parent(ppsdev);
  163         struct pps_data *sc = DEVTOSOFTC(ppsdev);
  164         sysclock_t count;
  165 
  166         count = sys_cputimer->count();
  167         if (!(ppb_rstr(ppbus) & nACK))
  168                 return;
  169         if (sc->pps.ppsparam.mode & PPS_ECHOASSERT) 
  170                 ppb_wctr(ppbus, IRQENABLE | AUTOFEED);
  171         pps_event(&sc->pps, count, PPS_CAPTUREASSERT);
  172         if (sc->pps.ppsparam.mode & PPS_ECHOASSERT) 
  173                 ppb_wctr(ppbus, IRQENABLE);
  174 }
  175 
  176 static int
  177 ppsioctl(struct dev_ioctl_args *ap)
  178 {
  179         cdev_t dev = ap->a_head.a_dev;
  180         u_int unit = minor(dev);
  181         struct pps_data *sc = UNITOSOFTC(unit);
  182 
  183         return (pps_ioctl(ap->a_cmd, ap->a_data, &sc->pps));
  184 }
  185 
  186 /*
  187  * Becuase pps is a static device under any attached ppbus, and not scanned
  188  * by the ppbus, we need an identify function to create the device.
  189  */
  190 static device_method_t pps_methods[] = {
  191         /* device interface */
  192         DEVMETHOD(device_identify,      bus_generic_identify),
  193         DEVMETHOD(device_probe,         ppsprobe),
  194         DEVMETHOD(device_attach,        ppsattach),
  195 
  196         DEVMETHOD_END
  197 };
  198 
  199 static driver_t pps_driver = {
  200         PPS_NAME,
  201         pps_methods,
  202         sizeof(struct pps_data),
  203 };
  204 DRIVER_MODULE(pps, ppbus, pps_driver, pps_devclass, NULL, NULL);

Cache object: 2dacd1b2c6d04a2db7346aabdc68ad5f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.