FreeBSD/Linux Kernel Cross Reference
sys/i386/pit.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
4 * Copyright (c) 1991 IBM Corporation
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify and distribute this software and its
8 * documentation is hereby granted, provided that both the copyright
9 * notice and this permission notice appear in all copies of the
10 * software, derivative works or modified versions, and any portions
11 * thereof, and that both notices appear in supporting documentation,
12 * and that the name IBM not be used in advertising or publicity
13 * pertaining to distribution of the software without specific, written
14 * prior permission.
15 *
16 * CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17 * CONDITION. CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR
18 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 *
20 * Carnegie Mellon requests users of this software to return to
21 *
22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23 * School of Computer Science
24 * Carnegie Mellon University
25 * Pittsburgh PA 15213-3890
26 *
27 * any improvements or extensions that they make and grant Carnegie Mellon
28 * the rights to redistribute these changes.
29 */
30
31 /*
32 * HISTORY
33 * $Log: pit.c,v $
34 * Revision 2.12 93/11/17 16:39:17 dbg
35 * Disable clkstart for new clocks.
36 * [93/02/18 dbg]
37 *
38 * Revision 2.11 93/02/04 07:56:56 danner
39 * Make spinwait() and tenmicrosec() [findspeed() & microtime()]
40 * available for everyone. They once were but they were incorrect.
41 * Re-add tenmicrosec for PS2.
42 * [92/02/25 dbg@ibm]
43 *
44 * Revision 2.9 91/10/07 17:25:03 af
45 * tenmicrosec() was all wrong has been expunged, since noone uses
46 * it.
47 * [91/09/04 rvb]
48 *
49 * Revision 2.8 91/06/19 11:55:29 rvb
50 * cputypes.h->platforms.h
51 * [91/06/12 13:45:16 rvb]
52 *
53 * Revision 2.7 91/05/14 16:14:40 mrt
54 * Correcting copyright
55 *
56 * Revision 2.6 91/02/05 17:14:03 mrt
57 * Changed to new Mach copyright
58 * [91/02/01 17:37:14 mrt]
59 *
60 * Revision 2.5 91/01/09 19:25:33 rpd
61 * Fixed clkstart to reset clock interrupt priority, etc.
62 * [91/01/09 rpd]
63 *
64 * Flush dead EXL code.
65 * [90/11/27 11:38:08 rvb]
66 *
67 * Revision 2.3 90/08/27 21:57:57 dbg
68 * Fix Intel Copyright as per B. Davies authorization.
69 * [90/08/14 dbg]
70 * Add Intel copyright.
71 * [90/01/08 rvb]
72 * splall/backall -> splon/sploff
73 * [89/10/20 rvb]
74 *
75 * Revision 2.2 90/05/03 15:36:34 dbg
76 * Converted for pure kernel.
77 * [90/02/20 dbg]
78 *
79 * Revision 2.2 89/09/25 12:32:40 rvb
80 * File was provided by Intel 9/18/89.
81 * [89/09/23 rvb]
82 *
83 */
84
85 /*
86 Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
87
88 All Rights Reserved
89
90 Permission to use, copy, modify, and distribute this software and
91 its documentation for any purpose and without fee is hereby
92 granted, provided that the above copyright notice appears in all
93 copies and that both the copyright notice and this permission notice
94 appear in supporting documentation, and that the name of Intel
95 not be used in advertising or publicity pertaining to distribution
96 of the software without specific, written prior permission.
97
98 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
99 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
100 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
101 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
102 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
103 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
104 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
105 */
106
107 #include <platforms.h>
108 #include <kern/time_out.h>
109 #include <i386/ipl.h>
110 #include <i386/pit.h>
111
112 int pitctl_port = PITCTL_PORT; /* For 386/20 Board */
113 int pitctr0_port = PITCTR0_PORT; /* For 386/20 Board */
114 int pitctr1_port = PITCTR1_PORT; /* For 386/20 Board */
115 int pitctr2_port = PITCTR2_PORT; /* For 386/20 Board */
116 /* We want PIT 0 in square wave mode */
117
118 int pit0_mode = PIT_C0|PIT_SQUAREMODE|PIT_READMODE ;
119
120
121 unsigned int delaycount; /* loop count in trying to delay for
122 * 1 millisecond
123 */
124 unsigned long microdata=50; /* loop count for 10 microsecond wait.
125 MUST be initialized for those who
126 insist on calling "tenmicrosec"
127 it before the clock has been
128 initialized.
129 */
130 unsigned int clknumb = CLKNUM; /* interrupt interval for timer 0 */
131
132 #ifdef PS2
133 extern int clock_int_handler();
134
135 #include <sys/types.h>
136 #include <i386ps2/abios.h>
137 static struct generic_request *clock_request_block;
138 static int clock_flags;
139 char cqbuf[200]; /*XXX temporary.. should use kmem_alloc or whatever..*/
140 #endif /* PS2 */
141
142 #if 0
143 clkstart()
144 {
145 unsigned int flags;
146 unsigned char byte;
147 int s;
148
149 intpri[0] = SPLHI;
150 form_pic_mask();
151
152 findspeed();
153 microfind();
154 s = sploff(); /* disable interrupts */
155
156 #ifdef PS2
157 abios_clock_start();
158 #endif /* PS2 */
159
160 /* Since we use only timer 0, we program that.
161 * 8254 Manual specifically says you do not need to program
162 * timers you do not use
163 */
164 outb(pitctl_port, pit0_mode);
165 clknumb = CLKNUM/hz;
166 byte = clknumb;
167 outb(pitctr0_port, byte);
168 byte = clknumb>>8;
169 outb(pitctr0_port, byte);
170 splon(s); /* restore interrupt state */
171 }
172 #endif
173
174 #define COUNT 10000 /* should be a multiple of 1000! */
175
176 findspeed()
177 {
178 unsigned int flags;
179 unsigned char byte;
180 unsigned int leftover;
181 int i;
182 int j;
183 int s;
184
185 s = sploff(); /* disable interrupts */
186 /* Put counter in count down mode */
187 #define PIT_COUNTDOWN PIT_READMODE|PIT_NDIVMODE
188 outb(pitctl_port, PIT_COUNTDOWN);
189 /* output a count of -1 to counter 0 */
190 outb(pitctr0_port, 0xff);
191 outb(pitctr0_port, 0xff);
192 delaycount = COUNT;
193 spinwait(1);
194 /* Read the value left in the counter */
195 byte = inb(pitctr0_port); /* least siginifcant */
196 leftover = inb(pitctr0_port); /* most significant */
197 leftover = (leftover<<8) + byte ;
198 /* Formula for delaycount is :
199 * (loopcount * timer clock speed)/ (counter ticks * 1000)
200 * 1000 is for figuring out milliseconds
201 */
202 /* we arrange calculation so that it doesn't overflow */
203 delaycount = ((COUNT/1000) * CLKNUM) / (0xffff-leftover);
204 printf("findspeed: delaycount=%d (tics=%d)\n",
205 delaycount, (0xffff-leftover));
206 splon(s); /* restore interrupt state */
207 }
208
209 #ifdef PS2
210
211 abios_clock_start()
212 {
213 struct generic_request temp_request_block;
214 int rc;
215
216 nmi_enable(); /* has to happen somewhere! */
217 temp_request_block.r_current_req_blck_len = ABIOS_MIN_REQ_SIZE;
218 temp_request_block.r_logical_id = abios_next_LID(SYSTIME_ID,
219 ABIOS_FIRST_LID);
220 temp_request_block.r_unit = 0;
221 temp_request_block.r_function = ABIOS_LOGICAL_PARAMETER;
222 temp_request_block.r_return_code = ABIOS_UNDEFINED;
223
224 abios_common_start(&temp_request_block,0);
225 if (temp_request_block.r_return_code != ABIOS_DONE) {
226 panic("couldn init abios time code!\n");
227 }
228
229 /*
230 * now build the clock request for the hardware system clock
231 */
232 clock_request_block = (struct generic_request *)cqbuf;
233 clock_request_block->r_current_req_blck_len =
234 temp_request_block.r_request_block_length;
235 clock_request_block->r_logical_id = temp_request_block.r_logical_id;
236 clock_request_block->r_unit = 0;
237 clock_request_block->r_function = ABIOS_DEFAULT_INTERRUPT;
238 clock_request_block->r_return_code = ABIOS_UNDEFINED;
239 clock_flags = temp_request_block.r_logical_id_flags;
240 }
241
242 ackrtclock()
243 {
244 if (clock_request_block) {
245 clock_request_block->r_return_code = ABIOS_UNDEFINED;
246 abios_common_interrupt(clock_request_block,clock_flags);
247 }
248 }
249 #endif /* PS2 */
250
251
252 spinwait(millis)
253 int millis; /* number of milliseconds to delay */
254 {
255 int i, j;
256
257 for (i=0;i<millis;i++)
258 for (j=0;j<delaycount;j++)
259 ;
260 }
261
262 #define MICROCOUNT 1000 /* keep small to prevent overflow */
263 microfind()
264 {
265 unsigned int flags;
266 unsigned char byte;
267 unsigned short leftover;
268 int s;
269
270
271 s = sploff(); /* disable interrupts */
272
273 /* Put counter in count down mode */
274 outb(pitctl_port, PIT_COUNTDOWN);
275 /* output a count of -1 to counter 0 */
276 outb(pitctr0_port, 0xff);
277 outb(pitctr0_port, 0xff);
278 microdata=MICROCOUNT;
279 tenmicrosec();
280 /* Read the value left in the counter */
281 byte = inb(pitctr0_port); /* least siginifcant */
282 leftover = inb(pitctr0_port); /* most significant */
283 leftover = (leftover<<8) + byte ;
284 /* Formula for delaycount is :
285 * (loopcount * timer clock speed)/ (counter ticks * 1000)
286 * Note also that 1000 is for figuring out milliseconds
287 */
288 microdata = (MICROCOUNT * CLKNUM) / ((0xffff-leftover)*100000);
289 if (!microdata)
290 microdata++;
291
292 splon(s); /* restore interrupt state */
293 }
Cache object: 7d7a7650b01ad035ff3cab359f16d11d
|