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/i386at/clockpit.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  * Mach Operating System
    3  * Copyright (c) 1993,1992 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        clockpit.c,v $
   29  * Revision 2.3  93/12/23  10:05:01  dbg
   30  *      Added missing include files.
   31  *      [93/12/14            dbg]
   32  * 
   33  * Revision 2.2  93/11/17  16:41:54  dbg
   34  *      Used common routines from device/clock_dev.c
   35  *      [93/06/02            dbg]
   36  * 
   37  *      Changed mmap routines to return physical address instead of
   38  *      physical page number.
   39  *      [93/05/24            dbg]
   40  * 
   41  *      Added to microkernel mainline.
   42  * 
   43  *      Created
   44  *      [92/06/22       savage]
   45  * 
   46  */
   47 #include <clockpit.h>
   48 
   49 #include <mach/boolean.h>
   50 #include <mach/time_spec.h>
   51 #include <kern/clock.h>
   52 #include <kern/kern_io.h>
   53 #include <vm/vm_kern.h>
   54 
   55 #include <sys/types.h>
   56 #include <chips/busses.h>
   57 #include <device/device_types.h>
   58 #include <device/clock_status.h>
   59 #include <device/clock_dev.h>
   60 
   61 #include <i386/machspl.h>
   62 #include <i386/pio.h>
   63 #include <i386/pit.h>
   64 
   65 /*
   66  *      Adjust for PIT clock round off... Ugly, but true...
   67  */
   68 #define HZ      100                     /* default frequency */
   69 
   70 #define CLOCKPIT_SKEW(res)              (((CLKNUM%(NANOSEC_PER_SEC/res)) \
   71                                                * res) / CLKNUM)
   72 #define CLOCKPIT_DEFAULT_RESOLUTION     (NANOSEC_PER_SEC/HZ - \
   73                                          CLOCKPIT_SKEW((NANOSEC_PER_SEC/HZ)))
   74 
   75 #define CLOCKPIT_MAX_RESOLUTION         (10000000)
   76 
   77 /*
   78  *      Minimum set to 1/2 a millisecond... if you want to play with lower
   79  *      then change this number.
   80  */
   81 #define CLOCKPIT_MIN_RESOLUTION         (500000)
   82 
   83 
   84 mach_clock_data_t               clockpit0;
   85 
   86 mach_clock_t                    clockpit[] = {&clockpit0};
   87 
   88 void    clockpit_setresolution(mach_clock_t);   /* forward */
   89 void    clockpit_write(mach_clock_t, time_spec_t);
   90 void    clockpit_enable_interrupts(mach_clock_t);
   91 
   92 struct clock_ops clockpit_ops = {
   93         clockpit_setresolution,
   94         clockpit_write,
   95         clockpit_enable_interrupts
   96 };
   97 
   98 void    clockpitsysintr(int);
   99 
  100 boolean_t clockpitprobe(
  101         vm_offset_t             port,
  102         struct bus_device       *dev);
  103 void clockpitattach(
  104         struct bus_device       *dev);
  105 
  106 static vm_offset_t              clockpit_std[NCLOCKPIT] = { 0 };
  107 static struct bus_device        *clockpit_info[NCLOCKPIT];
  108 struct bus_driver               clockpitdriver = {
  109         clockpitprobe, 0, clockpitattach, 0, clockpit_std, "clockpit",
  110         clockpit_info,0, 0, 0};
  111 
  112 boolean_t clockpitprobe(
  113         vm_offset_t             port,
  114         struct bus_device       *dev)
  115 {
  116         int             unit = dev->unit;
  117 
  118         if (unit < 0 || unit >= NCLOCKPIT)
  119             return FALSE;
  120 
  121         /*
  122          *      Always have one.
  123          */
  124         return TRUE;
  125 }
  126 
  127 void clockpitattach(
  128         struct bus_device       *dev)
  129 {
  130         int             unit = dev->unit;
  131         mach_clock_t    clock = clockpit[unit];
  132 
  133         clock_init(clock, &clockpit_ops);
  134         clock->resolution = CLOCKPIT_DEFAULT_RESOLUTION;
  135 
  136         if (sys_clock == 0) {
  137             /*
  138              *  If no system clock already, use this as system clock.
  139              */
  140             sys_clock = &clockpit0;
  141             dev->intr = clockpitsysintr;    /* use system clock interrupt */
  142             dev_change_indirect("clock_priv", "clockpit", unit);
  143                                             /* set generic clock device */
  144             set_clock_unpriv();             /* and unprivileged clock */
  145         }
  146 
  147         printf(", time = %u secs : %u nsecs, resolution = %u nsecs",
  148                clock->time.seconds,
  149                clock->time.nanoseconds,
  150                clock->resolution);
  151 }
  152 
  153 /*
  154  *      Enable interrupts from PIT clock
  155  */
  156 void clockpit_enable_interrupts(
  157         mach_clock_t clock)
  158 {
  159         take_dev_irq(clockpit_info[0]);
  160 }
  161 
  162 io_return_t clockpitopen(
  163         int     dev)
  164 {
  165         if (dev < 0 || dev >= NCLOCKPIT) {
  166             return D_NO_SUCH_DEVICE;
  167         }
  168         return clock_open(clockpit[dev]);
  169 }
  170 
  171 io_return_t clockpitclose(
  172         int     dev)
  173 {
  174         return D_SUCCESS;
  175 }
  176 
  177 io_return_t clockpitgetstat(
  178         int             dev,
  179         int             flavor,
  180         dev_status_t    stat,
  181         natural_t       *count)
  182 {
  183         return clock_getstat(clockpit[dev], flavor, stat, count);
  184 }
  185 
  186 io_return_t clockpitsetstat(
  187         int             dev,
  188         int             flavor,
  189         dev_status_t    stat,
  190         natural_t       count)
  191 {
  192         mach_clock_t    clock = clockpit[dev];
  193         unsigned int    frequency;
  194         unsigned int    skew;
  195         spl_t           s;
  196 
  197         switch (flavor) {
  198             case CLOCK_RESOLUTION:
  199             {
  200                 clock_resolution_t      request;
  201 
  202                 if (count < CLOCK_RESOLUTION_COUNT)
  203                     return D_INVALID_SIZE;
  204 
  205                 request = (clock_resolution_t)stat;
  206                 if (request->resolution < CLOCKPIT_MIN_RESOLUTION ||
  207                     request->resolution > CLOCKPIT_MAX_RESOLUTION)
  208                 {
  209                     return D_INVALID_SIZE;
  210                 }
  211                         
  212                 frequency = NANOSEC_PER_SEC/request->resolution;
  213                 skew = CLOCKPIT_SKEW(request->resolution);
  214                         
  215                 if (skew > request->skew) {
  216                     return D_INVALID_SIZE;
  217                 }
  218 
  219                 s = splsched();
  220                 clock_queue_lock(clock);
  221 
  222                 clock->new_resolution = request->resolution - skew;
  223                 clock->new_skew = request->skew + skew; /* ? */
  224 
  225                 clock_queue_unlock(clock);
  226                 splx(s);
  227                 return D_SUCCESS;
  228             }
  229 
  230             default:
  231                 return clock_setstat(clock, flavor, stat, count);
  232         }
  233 }
  234 
  235 vm_offset_t clockpitmmap(
  236         int             dev,
  237         vm_offset_t     off,
  238         vm_prot_t       prot)
  239 {
  240         return clock_map_page(clockpit[dev], off, prot);
  241 }
  242 
  243 io_return_t clockpitinfo(
  244         int             dev,
  245         int             flavor,
  246         mach_clock_t    *info)
  247 {
  248         if (flavor == D_INFO_CLOCK) {
  249             *info = clockpit[dev];
  250             return D_SUCCESS;
  251         }
  252         else {
  253             return D_INVALID_OPERATION;
  254         }
  255 }
  256 
  257 void clockpit_setresolution(
  258         mach_clock_t    clock)
  259 {
  260         unsigned int    pitval;
  261         unsigned int    frequency;
  262 
  263         frequency = NANOSEC_PER_SEC/(clock->resolution);
  264 
  265         pitval = CLKNUM/frequency;
  266         outb(PITCTL_PORT,  PIT_C0|PIT_SQUAREMODE|PIT_READMODE);
  267         outb(PITCTR0_PORT, pitval);
  268         outb(PITCTR0_PORT, pitval>>8);
  269 }
  270 
  271 void clockpit_write(
  272         mach_clock_t    clock,
  273         time_spec_t     new_time)
  274 {
  275         /* XXX no permanent clock storage XXX */
  276 }
  277 

Cache object: 3055a5919d0099dc395b191ccaff7c5e


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