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/i386/isa/loran.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: releng/5.0/sys/i386/isa/loran.c 105224 2002-10-16 10:16:17Z phk $
   10  *
   11  * This device-driver helps the userland controlprogram for a LORAN-C
   12  * receiver avoid monopolizing the CPU.
   13  *
   14  * This is clearly a candidate for the "most weird hardware support in
   15  * FreeBSD" prize.  At this time only two copies of the receiver are
   16  * known to exist in the entire world.
   17  *
   18  * Details can be found at:
   19  *     ftp://ftp.eecis.udel.edu/pub/ntp/loran.tar.Z
   20  *
   21  */
   22 
   23 #ifdef _KERNEL
   24 #include <sys/param.h>
   25 #include <sys/systm.h>
   26 #include <sys/sysctl.h>
   27 #include <sys/conf.h>
   28 #include <sys/kernel.h>
   29 #include <sys/uio.h>
   30 #include <sys/bus.h>
   31 #include <sys/malloc.h>
   32 #include <sys/timetc.h>
   33 
   34 #include <i386/isa/isa_device.h>
   35 #endif /* _KERNEL */
   36 
   37 typedef TAILQ_HEAD(, datapoint) dphead_t;
   38 
   39 struct datapoint {
   40         /* Fields used by kernel */
   41         u_int64_t               scheduled;
   42         u_int                   code;
   43         u_int                   fri;
   44         u_int                   agc;
   45         u_int                   phase;
   46         u_int                   width;
   47         u_int                   par;
   48         u_int                   isig;
   49         u_int                   qsig;
   50         u_int                   ssig;
   51         u_int64_t               epoch;
   52         TAILQ_ENTRY(datapoint)  list;
   53         int                     vco;
   54         int                     bounce;
   55         pid_t                   pid;
   56         struct timespec         when;
   57 
   58         int                     priority;
   59         dphead_t                *home;
   60 
   61         /* Fields used only in userland */
   62         void                    (*proc)(struct datapoint *);
   63         void                    *ident;
   64         int                     index;
   65         char                    *name;
   66 
   67 
   68         /* Fields used only in userland */
   69         double                  ival;
   70         double                  qval;
   71         double                  sval;
   72         double                  mval;
   73 
   74 };
   75 
   76 /*
   77  * Mode register (PAR) hardware definitions
   78  */
   79     #define INTEG 0x03          /* integrator mask */
   80         #define INTEG_1000us    0
   81         #define INTEG_264us     1
   82         #define INTEG_36us      2
   83         #define INTEG_SHORT     3
   84     #define GATE 0x0C           /* gate source mask */
   85         #define GATE_OPEN       0x0
   86         #define GATE_GRI        0x4
   87         #define GATE_PCI        0x8
   88         #define GATE_STB        0xc
   89     #define MSB 0x10            /* load dac high-order bits */
   90     #define IEN 0x20            /* enable interrupt bit */
   91     #define EN5 0x40            /* enable counter 5 bit */
   92     #define ENG 0x80            /* enable gri bit */
   93 
   94 #define VCO_SHIFT 8             /* bits of fraction on VCO value */
   95 #define VCO (2048 << VCO_SHIFT) /* initial vco dac (0 V)*/
   96 
   97 
   98 #define PGUARD 990             /* program guard time (cycle) (990!) */
   99 
  100 #ifdef _KERNEL
  101 
  102 #define NLORAN  10              /* Allow ten minor devices */
  103 
  104 #define NDUMMY 4                /* How many idlers we want */
  105 
  106 #define PORT 0x0300             /* controller port address */
  107 
  108 
  109 #define GRI 800                 /* pulse-group gate (cycle) */
  110 
  111 /*
  112  * Analog/digital converter (ADC) hardware definitions
  113  */
  114 #define ADC PORT+2              /* adc buffer (r)/address (w) */
  115 #define ADCGO PORT+3            /* adc status (r)/adc start (w) */
  116     #define ADC_START 0x01      /* converter start bit (w) */
  117     #define ADC_BUSY 0x01       /* converter busy bit (r) */
  118     #define ADC_DONE 0x80       /* converter done bit (r) */
  119     #define ADC_I 0             /* i channel (phase) */
  120     #define ADC_Q 1             /* q channel (amplitude) */
  121     #define ADC_S 2             /* s channel (agc) */
  122 
  123 /*
  124  * Digital/analog converter (DAC) hardware definitions
  125  * Note: output voltage increases with value programmed; the buffer
  126  * is loaded in two 8-bit bytes, the lsb 8 bits with the MSB bit off in
  127  * the PAR register, the msb 4 bits with the MSB on.
  128  */
  129 #define DACA PORT+4             /* vco (dac a) buffer (w) */
  130 #define DACB PORT+5             /* agc (dac b) buffer (w) */
  131 
  132 #define LOAD_DAC(dac, val) if (0) { } else {                            \
  133         par &= ~MSB; outb(PAR, par); outb((dac), (val) & 0xff);         \
  134         par |=  MSB; outb(PAR, par); outb((dac), ((val) >> 8) & 0xff);  \
  135         }
  136 
  137 /*
  138  * Pulse-code generator (CODE) hardware definitions
  139  * Note: bits are shifted out from the lsb first
  140  */
  141 #define CODE PORT+6             /* pulse-code buffer (w) */
  142     #define MPCA 0xCA           /* LORAN-C master pulse code group a */
  143     #define MPCB 0x9F           /* LORAN-C master pulse code group b */
  144     #define SPCA 0xF9           /* LORAN-C slave pulse code group a */
  145     #define SPCB 0xAC           /* LORAN-C slave pulse code group b */
  146 
  147 /*
  148  * Mode register (PAR) hardware definitions
  149  */
  150 #define PAR PORT+7              /* parameter buffer (w) */
  151 
  152 #define TGC PORT+0              /* stc control port (r/w) */
  153 #define TGD PORT+1              /* stc data port (r/w) */
  154 
  155 /*
  156  * Timing generator (STC) hardware commands
  157  */
  158 /* argument sssss = counter numbers 5-1 */
  159 #define TG_LOADDP 0x00             /* load data pointer */
  160     /* argument ee = element (all groups except ggg = 000 or 111) */
  161     #define MODEREG 0x00        /* mode register */
  162     #define LOADREG 0x08        /* load register */
  163     #define HOLDREG 0x10        /* hold register */
  164     #define HOLDINC 0x18        /* hold register (hold cycle increm) */
  165     /* argument ee = element (group ggg = 111) */
  166     #define ALARM1 0x07         /* alarm register 1 */
  167     #define ALARM2 0x0F         /* alarm register 2 */
  168     #define MASTER 0x17         /* master mode register */
  169     #define STATUS 0x1F         /* status register */
  170 #define ARM 0x20                /* arm counters */
  171 #define LOAD 0x40               /* load counters */
  172 #define TG_LOADARM 0x60            /* load and arm counters */
  173 #define DISSAVE 0x80            /* disarm and save counters */
  174 #define TG_SAVE 0xA0               /* save counters */
  175 #define DISARM 0xC0             /* disarm counters */
  176 /* argument nnn = counter number */
  177 #define SETTOG 0xE8             /* set toggle output HIGH for counter */
  178 #define CLRTOG 0xE0             /* set toggle output LOW for counter */
  179 #define STEP 0xF0               /* step counter */
  180 /* argument eeggg, where ee = element, ggg - counter group */
  181 /* no arguments */
  182 #define ENABDPS 0xE0            /* enable data pointer sequencing */
  183 #define ENABFOUT 0xE6           /* enable fout */
  184 #define ENAB8 0xE7              /* enable 8-bit data bus */
  185 #define DSABDPS 0xE8            /* disable data pointer sequencing */
  186 #define ENAB16 0xEF             /* enable 16-bit data bus */
  187 #define DSABFOUT 0xEE           /* disable fout */
  188 #define ENABPFW 0xF8            /* enable prefetch for write */
  189 #define DSABPFW 0xF9            /* disable prefetch for write */
  190 #define TG_RESET 0xFF              /* master reset */
  191 
  192 #define LOAD_9513(index, val) if (0) {} else {          \
  193         outb(TGC, TG_LOADDP + (index));                 \
  194         outb(TGD, (val) & 0xff);                                        \
  195         outb(TGD, ((val) >> 8) & 0xff);                         \
  196         }
  197 
  198 #define NENV 40                 /* size of envelope filter */
  199 #define CLOCK 50                /* clock period (clock) */
  200 #define CYCLE 10                /* carrier period (us) */
  201 #define PCX (NENV * CLOCK)      /* envelope gate (clock) */
  202 #define STROBE 50               /* strobe gate (clock) */
  203 
  204 /**********************************************************************/
  205 
  206 extern struct cdevsw loran_cdevsw;
  207 
  208 static dphead_t minors[NLORAN + 1], working;
  209 
  210 static struct datapoint dummy[NDUMMY], *first, *second;
  211 
  212 static u_int64_t ticker;
  213 
  214 static u_char par;
  215 
  216 static MALLOC_DEFINE(M_LORAN, "Loran", "Loran datapoints");
  217 
  218 static int loranerror;
  219 static char lorantext[160];
  220 
  221 static u_int vco_is;
  222 static u_int vco_should;
  223 static u_int vco_want;
  224 static u_int64_t vco_when;
  225 static int64_t vco_error;
  226 
  227 /**********************************************************************/
  228 
  229 static  int             loranprobe (struct isa_device *dvp);
  230 static  void            init_tgc (void);
  231 static  int             loranattach (struct isa_device *isdp);
  232 static  void            loranenqueue (struct datapoint *);
  233 static  d_open_t        loranopen;
  234 static  d_close_t       loranclose;
  235 static  d_read_t        loranread;
  236 static  d_write_t       loranwrite;
  237 static  ointhand2_t     loranintr;
  238 extern  struct timecounter loran_timecounter;
  239 
  240 /**********************************************************************/
  241 
  242 static int
  243 loranprobe(struct isa_device *dvp)
  244 {
  245         static int once;
  246 
  247         if (!once++)
  248                 cdevsw_add(&loran_cdevsw);
  249         dvp->id_iobase = PORT;
  250         return (8);
  251 }
  252 
  253 static u_short tg_init[] = {            /* stc initialization vector    */
  254         0x0562,      12,         13,    /* counter 1 (p0)  Mode J       */
  255         0x0262,  PGUARD,        GRI,    /* counter 2 (gri) Mode J       */
  256         0x8562,     PCX, 5000 - PCX,    /* counter 3 (pcx)              */
  257         0xc562,       0,     STROBE,    /* counter 4 (stb) Mode L       */
  258         0x052a,       0,          0     /* counter 5 (out)              */
  259 };
  260 
  261 static void
  262 init_tgc(void)
  263 {
  264         int i;
  265 
  266         /* Initialize the 9513A */
  267         outb(TGC, TG_RESET);         outb(TGC, LOAD+0x1f); /* reset STC chip */
  268         LOAD_9513(MASTER, 0x8af0);
  269         outb(TGC, TG_LOADDP+1);
  270         tg_init[4] = 7499 - GRI;
  271         for (i = 0; i < 5*3; i++) {
  272                 outb(TGD, tg_init[i]);
  273                 outb(TGD, tg_init[i] >> 8);
  274         }
  275         outb(TGC, TG_LOADARM+0x1f);    /* let the good times roll */
  276 }
  277 
  278 static int
  279 loranattach(struct isa_device *isdp)
  280 {
  281         int i;
  282 
  283         isdp->id_ointr = loranintr;
  284 
  285         /* We need to be a "fast-intr" */
  286         /* isdp->id_ri_flags |= RI_FAST; XXX unimplemented - use newbus! */
  287 
  288         printf("loran0: LORAN-C Receiver\n");
  289 
  290         vco_want = vco_should = VCO;
  291         vco_is = vco_should >> VCO_SHIFT;
  292         LOAD_DAC(DACA, vco_is);
  293          
  294         init_tgc();
  295 
  296         tc_init(&loran_timecounter);
  297 
  298         TAILQ_INIT(&working);
  299         for (i = 0; i < NLORAN + 1; i++) {
  300                 TAILQ_INIT(&minors[i]);
  301                 
  302         }
  303 
  304         for (i = 0; i < NDUMMY; i++) {
  305                 dummy[i].agc = 4095;
  306                 dummy[i].code = 0xac;
  307                 dummy[i].fri = PGUARD;
  308                 dummy[i].scheduled = PGUARD * 2 * i;
  309                 dummy[i].phase = 50;
  310                 dummy[i].width = 50;
  311                 dummy[i].priority = NLORAN * 256;
  312                 dummy[i].home = &minors[NLORAN];
  313                 if (i == 0) 
  314                         first = &dummy[i];
  315                 else if (i == 1) 
  316                         second = &dummy[i];
  317                 else
  318                         TAILQ_INSERT_TAIL(&working, &dummy[i], list);
  319         }
  320 
  321         inb(ADC);               /* Flush any old result */
  322         outb(ADC, ADC_S);
  323 
  324         par = ENG|IEN;
  325         outb(PAR, par);
  326 
  327         return (1);
  328 }
  329 
  330 static  int
  331 loranopen (dev_t dev, int flags, int fmt, struct thread *td)
  332 {
  333         int idx;
  334 
  335         idx = minor(dev);
  336         if (idx >= NLORAN) 
  337                 return (ENODEV);
  338 
  339         return(0);
  340 }
  341 
  342 static  int
  343 loranclose(dev_t dev, int flags, int fmt, struct thread *td)
  344 {
  345         return(0);
  346 }
  347 
  348 static  int
  349 loranread(dev_t dev, struct uio * uio, int ioflag)
  350 {
  351         u_long ef;
  352         struct datapoint *this;
  353         int err, c;
  354         int idx;
  355 
  356         idx = minor(dev);
  357         
  358         if (loranerror) {
  359                 printf("Loran0: %s", lorantext);
  360                 loranerror = 0;
  361                 return(EIO);
  362         }
  363         if (TAILQ_EMPTY(&minors[idx])) 
  364                 tsleep ((caddr_t)&minors[idx], (PZERO + 8) |PCATCH, "loranrd", hz*2);
  365         if (TAILQ_EMPTY(&minors[idx])) 
  366                 return(0);
  367         this = TAILQ_FIRST(&minors[idx]);
  368         ef = read_eflags();
  369         disable_intr();
  370         TAILQ_REMOVE(&minors[idx], this, list);
  371         write_eflags(ef);
  372 
  373         c = imin(uio->uio_resid, (int)sizeof *this);
  374         err = uiomove((caddr_t)this, c, uio);        
  375         FREE(this, M_LORAN);
  376         return(err);
  377 }
  378 
  379 static void
  380 loranenqueue(struct datapoint *dp)
  381 {
  382         struct datapoint *dpp;
  383 
  384         TAILQ_FOREACH(dpp, &working, list) {
  385                 if (dpp->priority <= dp->priority)
  386                         continue;
  387                 TAILQ_INSERT_BEFORE(dpp, dp, list);
  388                 return;
  389         }
  390         TAILQ_INSERT_TAIL(&working, dp, list);
  391 }
  392 
  393 static  int
  394 loranwrite(dev_t dev, struct uio * uio, int ioflag)
  395 {
  396         u_long ef;
  397         int err = 0, c;
  398         struct datapoint *this;
  399         int idx;
  400         u_int64_t dt;
  401         u_int64_t when;
  402 
  403         idx = minor(dev);
  404 
  405         MALLOC(this, struct datapoint *, sizeof *this, M_LORAN, M_WAITOK);
  406         c = imin(uio->uio_resid, (int)sizeof *this);
  407         err = uiomove((caddr_t)this, c, uio);        
  408         if (err) {
  409                 FREE(this, M_LORAN);
  410                 return (err);
  411         }
  412         if (this->fri == 0) {
  413                 FREE(this, M_LORAN);
  414                 return (EINVAL);
  415         }
  416         this->par &= INTEG|GATE;
  417         /* XXX more checks needed! */
  418         this->home = &minors[idx];
  419         this->priority &= 0xff;
  420         this->priority += idx * 256;
  421         this->bounce = 0;
  422         when = second->scheduled + PGUARD;
  423         if (when > this->scheduled) {
  424                 dt = when - this->scheduled;
  425                 dt -= dt % this->fri;
  426                 this->scheduled += dt;
  427         }
  428         ef = read_eflags();
  429         disable_intr();
  430         loranenqueue(this);
  431         write_eflags(ef);
  432         if (this->vco >= 0)
  433                 vco_want = this->vco;
  434         return(err);
  435 }
  436 
  437 static void
  438 loranintr(int unit)
  439 {
  440         u_long ef;
  441         int status = 0, i;
  442 #if 0
  443         int count = 0;
  444 #endif
  445         int delay;
  446         u_int64_t when;
  447         struct timespec there, then;
  448         struct datapoint *dp, *done;
  449 
  450         ef = read_eflags();
  451         disable_intr();
  452 
  453         /*
  454          * Pick up the measurement which just completed, and setup
  455          * the next measurement.  We have 1100 microseconds for this
  456          * of which some eaten by the A/D of the S channel and the 
  457          * interrupt to get us here.
  458          */
  459 
  460         done = first;
  461 
  462         nanotime(&there);
  463         done->ssig = inb(ADC);
  464 
  465         par &= ~(ENG | IEN);
  466         outb(PAR, par);
  467 
  468         outb(ADC, ADC_I);
  469         outb(ADCGO, ADC_START);
  470 
  471         /* Interlude: while we wait: setup the next measurement */
  472                 LOAD_DAC(DACB, second->agc);
  473                 outb(CODE, second->code);
  474                 par &= ~(INTEG|GATE);
  475                 par |= second->par;
  476                 par |= ENG | IEN;
  477 
  478         while (!(inb(ADCGO) & ADC_DONE))
  479                 continue;
  480         done->isig = inb(ADC);
  481 
  482         outb(ADC, ADC_Q);
  483         outb(ADCGO, ADC_START);
  484         /* Interlude: while we wait: setup the next measurement */
  485                 /*
  486                  * We need to load this from the opposite register due to some 
  487                  * weirdness which you can read about in in the 9513 manual on 
  488                  * page 1-26 under "LOAD"
  489                  */
  490                 LOAD_9513(0x0c, second->phase);
  491                 LOAD_9513(0x14, second->phase);
  492                 outb(TGC, TG_LOADARM + 0x08);
  493                 LOAD_9513(0x14, second->width);
  494         while (!(inb(ADCGO) & ADC_DONE))
  495                 continue;
  496         done->qsig = inb(ADC);
  497 
  498         outb(ADC, ADC_S);
  499 
  500         outb(PAR, par);
  501 
  502         /*
  503          * End of VERY time critical stuff, we have 8 msec to find
  504          * the next measurement and program the delay.
  505          */
  506         status = inb(TGC);
  507         nanotime(&then);
  508 
  509         first = second;
  510         second = 0;
  511         when = first->scheduled + PGUARD;
  512         TAILQ_FOREACH(dp, &working, list) {
  513                 while (dp->scheduled < when)
  514                         dp->scheduled += dp->fri;
  515                 if (second && dp->scheduled + PGUARD >= second->scheduled)
  516                         continue;
  517                 second = dp;
  518         }
  519 
  520         delay = (second->scheduled - first->scheduled) - GRI;
  521 
  522         LOAD_9513(0x0a, delay);
  523 
  524         /* Done, the rest is leisure work */
  525 
  526         vco_error += ((vco_is << VCO_SHIFT) - vco_should) * 
  527             (ticker - vco_when);
  528         vco_should = vco_want;
  529         i = vco_should >> VCO_SHIFT;
  530         if (vco_error < 0)
  531                 i++;
  532         
  533         if (vco_is != i) {
  534                 LOAD_DAC(DACA, i);
  535                 vco_is = i;
  536         }
  537         vco_when = ticker;
  538 
  539         /* Check if we overran */
  540         status &= 0x0c;
  541 #if 0
  542 
  543         if (status) {
  544                 outb(TGC, TG_SAVE + 2);         /* save counter #2 */
  545                 outb(TGC, TG_LOADDP + 0x12);    /* hold counter #2 */
  546                 count = inb(TGD);
  547                 count |= inb(TGD) << 8;
  548                 LOAD_9513(0x12, GRI)
  549         }
  550 #endif
  551 
  552         if (status) {
  553                 printf( "Missed: %02x %d first:%p second:%p %.09ld\n",
  554                     status, delay, first, second,
  555                     then.tv_nsec - there.tv_nsec);
  556                 first->bounce++;
  557         }
  558 
  559         TAILQ_REMOVE(&working, second, list);
  560 
  561         if (done->bounce) {
  562                 done->bounce = 0;
  563                 loranenqueue(done);
  564         } else {
  565                 done->epoch = ticker;
  566                 done->vco = vco_is;
  567                 done->when = there;
  568                 TAILQ_INSERT_TAIL(done->home, done, list);
  569                 wakeup((caddr_t)done->home);
  570         }
  571 
  572         ticker = first->scheduled;
  573 
  574         while ((dp = TAILQ_FIRST(&minors[NLORAN])) != NULL) {
  575                 TAILQ_REMOVE(&minors[NLORAN], dp, list);
  576                 TAILQ_INSERT_TAIL(&working, dp, list);
  577         }
  578 
  579         when = second->scheduled + PGUARD;
  580 
  581         TAILQ_FOREACH(dp, &working, list) {
  582                 while (dp->scheduled < when)
  583                         dp->scheduled += dp->fri;
  584         }
  585         write_eflags(ef);
  586 }
  587 
  588 /**********************************************************************/
  589 
  590 static unsigned
  591 loran_get_timecount(struct timecounter *tc)
  592 {
  593         unsigned count;
  594         u_long ef;
  595 
  596         ef = read_eflags();
  597         disable_intr();
  598 
  599         outb(TGC, TG_SAVE + 0x10);      /* save counter #5 */
  600         outb(TGC, TG_LOADDP +0x15);     /* hold counter #5 */
  601         count = inb(TGD);
  602         count |= inb(TGD) << 8;
  603 
  604         write_eflags(ef);
  605         return (count);
  606 }
  607 
  608 static struct timecounter loran_timecounter = {
  609         loran_get_timecount,    /* get_timecount */
  610         0,                      /* no pps_poll */
  611         0xffff,                 /* counter_mask */
  612         5000000,                /* frequency */
  613         "loran"                 /* name */
  614 };
  615 
  616 
  617 /**********************************************************************/
  618 
  619 struct  isa_driver lorandriver = {
  620         INTR_TYPE_TTY | INTR_FAST,
  621         loranprobe,
  622         loranattach,
  623         "loran"
  624 };
  625 COMPAT_ISA_DRIVER(loran, lorandriver);
  626 
  627 #define CDEV_MAJOR 94
  628 static struct cdevsw loran_cdevsw = {
  629         /* open */      loranopen,
  630         /* close */     loranclose,
  631         /* read */      loranread,
  632         /* write */     loranwrite,
  633         /* ioctl */     noioctl,
  634         /* poll */      nopoll,
  635         /* mmap */      nommap,
  636         /* strategy */  nostrategy,
  637         /* name */      "loran",
  638         /* maj */       CDEV_MAJOR,
  639         /* dump */      nodump,
  640         /* psize */     nopsize,
  641         /* flags */     0,
  642 };
  643 
  644 #endif /* _KERNEL */

Cache object: dfe0187719af9cdcaf885f289ebb996e


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