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  * $FreeBSD$
   10  *
   11  * A very simple device driver for PCI cards based on Xilinx 6200 series
   12  * FPGA/RPU devices.  Current Functionality is to allow you to open and
   13  * mmap the entire thing into your program.
   14  *
   15  * Hardware currently supported:
   16  *      www.vcc.com HotWorks 1 6216 based card.
   17  *
   18  */
   19 
   20 #include "opt_devfs.h"
   21 
   22 #include "xrpu.h"
   23 #include <sys/param.h>
   24 #include <sys/systm.h>
   25 #include <sys/conf.h>
   26 #include <sys/kernel.h>
   27 #include <sys/malloc.h>
   28 #include <sys/timepps.h>
   29 #ifdef DEVFS
   30 #include <sys/devfsext.h>
   31 #endif
   32 #include <sys/xrpuio.h>
   33 #include <pci/pcireg.h>
   34 #include <pci/pcivar.h>
   35 
   36 static  const char*     xrpu_probe  (pcici_t tag, pcidi_t type);
   37 static  void    xrpu_attach (pcici_t tag, int unit);
   38 static  u_long  xrpu_count;
   39 
   40 static void xrpu_poll_pps(struct timecounter *tc);
   41 
   42 /*
   43  * Device driver initialization stuff
   44  */
   45 
   46 static d_open_t xrpu_open;
   47 static d_close_t xrpu_close;
   48 static d_ioctl_t xrpu_ioctl;
   49 static d_mmap_t xrpu_mmap;
   50 
   51 #define CDEV_MAJOR 100
   52 static struct cdevsw xrpudevsw = {
   53         xrpu_open,      xrpu_close,     noread,         nowrite,
   54         xrpu_ioctl,     nullstop,       noreset,        nodevtotty,
   55         seltrue,        xrpu_mmap,      nostrategy,     "xrpu",
   56         NULL,           -1
   57 };
   58 
   59 static MALLOC_DEFINE(M_XRPU, "xrpu", "XRPU related");
   60 
   61 #define dev2unit(devt) (minor(devt) & 0xff)
   62 #define dev2pps(devt) ((minor(devt) >> 16)-1)
   63 
   64 static struct softc {
   65         pcici_t tag;
   66         enum { NORMAL, TIMECOUNTER } mode;
   67         vm_offset_t virbase, physbase;
   68         u_int   *virbase62;
   69         struct timecounter tc;
   70         u_int *trigger, *latch, dummy;
   71         struct pps_state pps[XRPU_MAX_PPS];
   72         u_int *assert[XRPU_MAX_PPS], *clear[XRPU_MAX_PPS];
   73 } *softc[NXRPU];
   74 
   75 static unsigned         
   76 xrpu_get_timecount(struct timecounter *tc)
   77 {               
   78         struct softc *sc = tc->tc_priv;
   79 
   80         sc->dummy += *sc->trigger;
   81         return (*sc->latch & tc->tc_counter_mask);
   82 }        
   83 
   84 void            
   85 xrpu_poll_pps(struct timecounter *tc)
   86 {               
   87         struct softc *sc = tc->tc_priv;
   88         int i;
   89         unsigned count1, ppscount; 
   90                 
   91         for (i = 0; i < XRPU_MAX_PPS; i++) {
   92                 if (sc->assert[i]) {
   93                         ppscount = *(sc->assert[i]) & tc->tc_counter_mask;
   94                         do {
   95                                 count1 = ppscount;
   96                                 ppscount =  *(sc->assert[i]) & tc->tc_counter_mask;
   97                         } while (ppscount != count1);
   98                         pps_event(&sc->pps[i], &sc->tc, ppscount, PPS_CAPTUREASSERT);
   99                 }
  100                 if (sc->clear[i]) {
  101                         ppscount = *(sc->clear[i]) & tc->tc_counter_mask;
  102                         do {
  103                                 count1 = ppscount;
  104                                 ppscount =  *(sc->clear[i]) & tc->tc_counter_mask;
  105                         } while (ppscount != count1);
  106                         pps_event(&sc->pps[i], &sc->tc, ppscount, PPS_CAPTURECLEAR);
  107                 }
  108         }
  109 }
  110 
  111 static int
  112 xrpu_open(dev_t dev, int flag, int mode, struct proc *p)
  113 {
  114         return (0);
  115 }
  116 
  117 static int
  118 xrpu_close(dev_t dev, int flag, int mode, struct proc *p)
  119 { 
  120         return (0);
  121 }
  122 
  123 static int
  124 xrpu_mmap(dev_t dev, vm_offset_t offset, int nprot)
  125 {
  126         struct softc *sc = softc[dev2unit(dev)];
  127         if (offset >= 0x1000000) 
  128                 return (-1);
  129         return (i386_btop(sc->physbase + offset));
  130 }
  131 
  132 static int
  133 xrpu_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *pr)
  134 {
  135         struct softc *sc = softc[dev2unit(dev)];
  136         int i, error;
  137 
  138         if (sc->mode == TIMECOUNTER) {
  139                 i = dev2pps(dev);
  140                 if (i < 0 || i >= XRPU_MAX_PPS)
  141                         return ENODEV;
  142                 error =  pps_ioctl(cmd, arg, &sc->pps[i]);
  143                 return (error);
  144         }
  145                 
  146         if (cmd == XRPU_IOC_TIMECOUNTING) {
  147                 struct xrpu_timecounting *xt = (struct xrpu_timecounting *)arg;
  148 
  149                 /* Name SHALL be zero terminated */
  150                 xt->xt_name[sizeof xt->xt_name - 1] = '\0';
  151                 i = strlen(xt->xt_name);
  152                 sc->tc.tc_name = (char *)malloc(i + 1, M_XRPU, M_WAITOK);
  153                 strcpy(sc->tc.tc_name, xt->xt_name);
  154                 sc->tc.tc_frequency = xt->xt_frequency;
  155                 sc->tc.tc_get_timecount = xrpu_get_timecount;
  156                 sc->tc.tc_poll_pps = xrpu_poll_pps;
  157                 sc->tc.tc_priv = sc;
  158                 sc->tc.tc_counter_mask = xt->xt_mask;
  159                 sc->trigger = sc->virbase62 + xt->xt_addr_trigger;
  160                 sc->latch = sc->virbase62 + xt->xt_addr_latch;
  161 
  162                 for (i = 0; i < XRPU_MAX_PPS; i++) {
  163                         if (xt->xt_pps[i].xt_addr_assert == 0
  164                             && xt->xt_pps[i].xt_addr_clear == 0)
  165                                 continue;
  166 #ifdef DEVFS
  167                         devfs_add_devswf(&xrpudevsw, (i+1)<<16, DV_CHR, UID_ROOT, GID_WHEEL, 
  168                             0600, "xpps%d", i);
  169 #endif
  170                         sc->pps[i].ppscap = 0;
  171                         if (xt->xt_pps[i].xt_addr_assert) {
  172                                 sc->assert[i] = sc->virbase62 + xt->xt_pps[i].xt_addr_assert;
  173                                 sc->pps[i].ppscap |= PPS_CAPTUREASSERT;
  174                         }
  175                         if (xt->xt_pps[i].xt_addr_clear) {
  176                                 sc->clear[i] = sc->virbase62 + xt->xt_pps[i].xt_addr_clear;
  177                                 sc->pps[i].ppscap |= PPS_CAPTURECLEAR;
  178                         }
  179                         pps_init(&sc->pps[i]);
  180                 }
  181                 sc->mode = TIMECOUNTER;
  182                 init_timecounter(&sc->tc);
  183                 return (0);
  184         }
  185         error = ENOTTY;
  186         return (error);
  187 }
  188 
  189 /*
  190  * PCI initialization stuff
  191  */
  192 
  193 static struct pci_device xrpu_device = {
  194         "xrpu",
  195         xrpu_probe,
  196         xrpu_attach,
  197         &xrpu_count,
  198         NULL
  199 };
  200 
  201 DATA_SET (pcidevice_set, xrpu_device);
  202 
  203 static const char* 
  204 xrpu_probe (pcici_t tag, pcidi_t typea)
  205 {
  206         u_int id;
  207         const char *vendor, *chip, *type;
  208 
  209         (void)pci_conf_read(tag, PCI_CLASS_REG);
  210         id = pci_conf_read(tag, PCI_ID_REG);
  211 
  212         vendor = chip = type = 0;
  213 
  214         if (id == 0x6216133e) {
  215                 return "VCC Hotworks-I xc6216";
  216         }
  217         return 0;
  218 }
  219 
  220 static void
  221 xrpu_attach (pcici_t tag, int unit)
  222 {
  223         struct softc *sc;
  224         dev_t cdev = makedev(CDEV_MAJOR, unit);
  225 
  226         sc = (struct softc *)malloc(sizeof *sc, M_XRPU, M_WAITOK);
  227         softc[unit] = sc;
  228         bzero(sc, sizeof *sc);
  229 
  230         sc->tag = tag;
  231         sc->mode = NORMAL;
  232 
  233         pci_map_mem(tag, PCI_MAP_REG_START, &sc->virbase, &sc->physbase);
  234 
  235         sc->virbase62 = (u_int *)(sc->virbase + 0x800000);
  236 
  237         if (bootverbose)
  238                 printf("Mapped physbase %#lx to virbase %#lx\n",
  239                     (u_long)sc->physbase, (u_long)sc->virbase);
  240 
  241         if (!unit)
  242                 cdevsw_add(&cdev, &xrpudevsw, NULL);
  243 
  244 #ifdef DEVFS
  245         devfs_add_devswf(&xrpudevsw, 0, DV_CHR, UID_ROOT, GID_WHEEL, 0600,
  246                 "xrpu%d", unit);
  247 #endif
  248 }

Cache object: c74e7574da9de050f23f21a035badfaf


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