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/pci/xrpu.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  * A very simple device driver for PCI cards based on Xilinx 6200 series
   10  * FPGA/RPU devices.  Current Functionality is to allow you to open and
   11  * mmap the entire thing into your program.
   12  *
   13  * Hardware currently supported:
   14  *      www.vcc.com HotWorks 1 6216 based card.
   15  */
   16 
   17 #include <sys/cdefs.h>
   18 __FBSDID("$FreeBSD: releng/5.3/sys/pci/xrpu.c 130585 2004-06-16 09:47:26Z phk $");
   19 
   20 #include <sys/param.h>
   21 #include <sys/systm.h>
   22 #include <sys/conf.h>
   23 #include <sys/kernel.h>
   24 #include <sys/malloc.h>
   25 #include <sys/module.h>
   26 #include <sys/timetc.h>
   27 #include <sys/timepps.h>
   28 #include <sys/xrpuio.h>
   29 #include <sys/bus.h>
   30 #include <machine/bus.h>
   31 #include <sys/rman.h>
   32 #include <machine/resource.h>
   33 #include <dev/pci/pcireg.h>
   34 #include <dev/pci/pcivar.h>
   35 #include "pci_if.h"
   36 
   37 /*
   38  * Device driver initialization stuff
   39  */
   40 
   41 static d_open_t xrpu_open;
   42 static d_close_t xrpu_close;
   43 static d_ioctl_t xrpu_ioctl;
   44 static d_mmap_t xrpu_mmap;
   45 
   46 static struct cdevsw xrpu_cdevsw = {
   47         .d_version =    D_VERSION,
   48         .d_flags =      D_NEEDGIANT,
   49         .d_open =       xrpu_open,
   50         .d_close =      xrpu_close,
   51         .d_ioctl =      xrpu_ioctl,
   52         .d_mmap =       xrpu_mmap,
   53         .d_name =       "xrpu",
   54 };
   55 
   56 static MALLOC_DEFINE(M_XRPU, "xrpu", "XRPU related");
   57 
   58 static devclass_t xrpu_devclass;
   59 
   60 #define dev2unit(devt) (minor(devt) & 0xff)
   61 #define dev2pps(devt) ((minor(devt) >> 16)-1)
   62 
   63 struct softc {
   64         enum { NORMAL, TIMECOUNTER } mode;
   65         vm_offset_t virbase, physbase;
   66         u_int   *virbase62;
   67         struct timecounter tc;
   68         u_int *trigger, *latch, dummy;
   69         struct pps_state pps[XRPU_MAX_PPS];
   70         u_int *assert[XRPU_MAX_PPS], *clear[XRPU_MAX_PPS];
   71 };
   72 
   73 static unsigned         
   74 xrpu_get_timecount(struct timecounter *tc)
   75 {               
   76         struct softc *sc = tc->tc_priv;
   77 
   78         sc->dummy += *sc->trigger;
   79         return (*sc->latch & tc->tc_counter_mask);
   80 }        
   81 
   82 static void            
   83 xrpu_poll_pps(struct timecounter *tc)
   84 {               
   85         struct softc *sc = tc->tc_priv;
   86         int i, j;
   87         unsigned count1, ppscount; 
   88                 
   89         for (i = 0; i < XRPU_MAX_PPS; i++) {
   90                 if (sc->assert[i]) {
   91                         pps_capture(&sc->pps[i]);
   92                         ppscount = *(sc->assert[i]) & tc->tc_counter_mask;
   93                         j = 0;
   94                         do {
   95                                 count1 = ppscount;
   96                                 ppscount =  *(sc->assert[i]) & tc->tc_counter_mask;
   97                         } while (ppscount != count1 && ++j < 5);
   98                         sc->pps[i].capcount = ppscount;
   99                         pps_event(&sc->pps[i], PPS_CAPTUREASSERT);
  100                 }
  101                 if (sc->clear[i]) {
  102                         pps_capture(&sc->pps[i]);
  103                         j = 0;
  104                         ppscount = *(sc->clear[i]) & tc->tc_counter_mask;
  105                         do {
  106                                 count1 = ppscount;
  107                                 ppscount =  *(sc->clear[i]) & tc->tc_counter_mask;
  108                         } while (ppscount != count1 && ++j < 5);
  109                         sc->pps[i].capcount = ppscount;
  110                         pps_event(&sc->pps[i], PPS_CAPTURECLEAR);
  111                 }
  112         }
  113 }
  114 
  115 static int
  116 xrpu_open(struct cdev *dev, int flag, int mode, struct  thread *td)
  117 {
  118         struct softc *sc = devclass_get_softc(xrpu_devclass, dev2unit(dev));
  119 
  120         if (!sc)
  121                 return (ENXIO);
  122         dev->si_drv1 = sc;
  123         return (0);
  124 }
  125 
  126 static int
  127 xrpu_close(struct cdev *dev, int flag, int mode, struct  thread *td)
  128 { 
  129         return (0);
  130 }
  131 
  132 static int
  133 xrpu_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
  134 {
  135         struct softc *sc = dev->si_drv1;
  136         if (offset >= 0x1000000) 
  137                 return (-1);
  138         *paddr = sc->physbase + offset;
  139         return (0);
  140 }
  141 
  142 static int
  143 xrpu_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct  thread *tdr)
  144 {
  145         struct softc *sc = dev->si_drv1;
  146         int i, error;
  147 
  148         if (sc->mode == TIMECOUNTER) {
  149                 i = dev2pps(dev);
  150                 if (i < 0 || i >= XRPU_MAX_PPS)
  151                         return ENODEV;
  152                 error =  pps_ioctl(cmd, arg, &sc->pps[i]);
  153                 return (error);
  154         }
  155                 
  156         if (cmd == XRPU_IOC_TIMECOUNTING) {
  157                 struct xrpu_timecounting *xt = (struct xrpu_timecounting *)arg;
  158 
  159                 /* Name SHALL be zero terminated */
  160                 xt->xt_name[sizeof xt->xt_name - 1] = '\0';
  161                 i = strlen(xt->xt_name);
  162                 sc->tc.tc_name = (char *)malloc(i + 1, M_XRPU, M_WAITOK);
  163                 strcpy(sc->tc.tc_name, xt->xt_name);
  164                 sc->tc.tc_frequency = xt->xt_frequency;
  165                 sc->tc.tc_get_timecount = xrpu_get_timecount;
  166                 sc->tc.tc_poll_pps = xrpu_poll_pps;
  167                 sc->tc.tc_priv = sc;
  168                 sc->tc.tc_counter_mask = xt->xt_mask;
  169                 sc->trigger = sc->virbase62 + xt->xt_addr_trigger;
  170                 sc->latch = sc->virbase62 + xt->xt_addr_latch;
  171 
  172                 for (i = 0; i < XRPU_MAX_PPS; i++) {
  173                         if (xt->xt_pps[i].xt_addr_assert == 0
  174                             && xt->xt_pps[i].xt_addr_clear == 0)
  175                                 continue;
  176                         make_dev(&xrpu_cdevsw, (i+1)<<16, 
  177                             UID_ROOT, GID_WHEEL, 0600, "xpps%d", i);
  178                         sc->pps[i].ppscap = 0;
  179                         if (xt->xt_pps[i].xt_addr_assert) {
  180                                 sc->assert[i] = sc->virbase62 + xt->xt_pps[i].xt_addr_assert;
  181                                 sc->pps[i].ppscap |= PPS_CAPTUREASSERT;
  182                         }
  183                         if (xt->xt_pps[i].xt_addr_clear) {
  184                                 sc->clear[i] = sc->virbase62 + xt->xt_pps[i].xt_addr_clear;
  185                                 sc->pps[i].ppscap |= PPS_CAPTURECLEAR;
  186                         }
  187                         pps_init(&sc->pps[i]);
  188                 }
  189                 sc->mode = TIMECOUNTER;
  190                 tc_init(&sc->tc);
  191                 return (0);
  192         }
  193         error = ENOTTY;
  194         return (error);
  195 }
  196 
  197 /*
  198  * PCI initialization stuff
  199  */
  200 
  201 static int
  202 xrpu_probe(device_t self)
  203 {
  204         char *desc;
  205 
  206         desc = NULL;
  207         switch (pci_get_devid(self)) {
  208         case 0x6216133e:
  209                 desc = "VCC Hotworks-I xc6216";
  210                 break;
  211         }
  212         if (desc == NULL)
  213                 return ENXIO;
  214 
  215         device_set_desc(self, desc);
  216         return 0;
  217 }
  218 
  219 static int
  220 xrpu_attach(device_t self)
  221 {
  222         struct softc *sc;
  223         struct resource *res;
  224         int rid, unit;
  225 
  226         unit = device_get_unit(self);
  227         sc = device_get_softc(self);
  228         sc->mode = NORMAL;
  229         rid = PCIR_BAR(0);
  230         res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
  231         if (res == NULL) {
  232                 device_printf(self, "Could not map memory\n");
  233                 return ENXIO;
  234         }
  235         sc->virbase = (vm_offset_t)rman_get_virtual(res);
  236         sc->physbase = rman_get_start(res);
  237         sc->virbase62 = (u_int *)(sc->virbase + 0x800000);
  238 
  239         if (bootverbose)
  240                 printf("Mapped physbase %#lx to virbase %#lx\n",
  241                     (u_long)sc->physbase, (u_long)sc->virbase);
  242 
  243         make_dev(&xrpu_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "xrpu%d", unit);
  244         return 0;
  245 }
  246 
  247 static device_method_t xrpu_methods[] = {
  248         /* Device interface */
  249         DEVMETHOD(device_probe,         xrpu_probe),
  250         DEVMETHOD(device_attach,        xrpu_attach),
  251         DEVMETHOD(device_suspend,       bus_generic_suspend),
  252         DEVMETHOD(device_resume,        bus_generic_resume),
  253         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  254 
  255         {0, 0}
  256 };
  257  
  258 static driver_t xrpu_driver = {
  259         "xrpu",
  260         xrpu_methods,
  261         sizeof(struct softc)
  262 };
  263  
  264  
  265 DRIVER_MODULE(xrpu, pci, xrpu_driver, xrpu_devclass, 0, 0);
  266 MODULE_DEPEND(xrpu, pci, 1, 1, 1);

Cache object: 4101b181333e28aa6b1ac7f5fc1d8c2a


[ 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.