VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/i8042prt/moucmn.c@ 1

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.8 KB
Line 
1
2/*++
3
4Copyright (c) 1990, 1991, 1992, 1993 Microsoft Corporation
5
6Module Name:
7
8 moucmn.c
9
10Abstract:
11
12 The common portions of the Intel i8042 port driver which
13 apply to the auxiliary (PS/2 mouse) device.
14
15Environment:
16
17 Kernel mode only.
18
19Notes:
20
21 NOTES: (Future/outstanding issues)
22
23 - Powerfail not implemented.
24
25 - Consolidate duplicate code, where possible and appropriate.
26
27Revision History:
28
29--*/
30
31#include "stdarg.h"
32#include "stdio.h"
33#include "string.h"
34#include "ntddk.h"
35#include "i8042prt.h"
36
37
38
39VOID
40I8042MouseIsrDpc(
41 IN PKDPC Dpc,
42 IN PDEVICE_OBJECT DeviceObject,
43 IN PIRP Irp,
44 IN PVOID Context
45 )
46
47/*++
48
49Routine Description:
50
51 This routine runs at DISPATCH_LEVEL IRQL to finish processing
52 mouse interrupts. It is queued in the mouse ISR. The real
53 work is done via a callback to the connected mouse class driver.
54
55Arguments:
56
57 Dpc - Pointer to the DPC object.
58
59 DeviceObject - Pointer to the device object.
60
61 Irp - Pointer to the Irp.
62
63 Context - Not used.
64
65Return Value:
66
67 None.
68
69--*/
70
71{
72
73 PDEVICE_EXTENSION deviceExtension;
74 GET_DATA_POINTER_CONTEXT getPointerContext;
75 SET_DATA_POINTER_CONTEXT setPointerContext;
76 VARIABLE_OPERATION_CONTEXT operationContext;
77 PVOID classService;
78 PVOID classDeviceObject;
79 LONG interlockedResult;
80 BOOLEAN moreDpcProcessing;
81 ULONG dataNotConsumed = 0;
82 ULONG inputDataConsumed = 0;
83 LARGE_INTEGER deltaTime;
84
85 UNREFERENCED_PARAMETER(Dpc);
86 UNREFERENCED_PARAMETER(Irp);
87 UNREFERENCED_PARAMETER(Context);
88
89 I8xPrint((2, "I8042PRT-I8042MouseIsrDpc: enter\n"));
90
91 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
92
93 //
94 // Use DpcInterlockMouse to determine whether the DPC is running
95 // concurrently on another processor. We only want one instantiation
96 // of the DPC to actually do any work. DpcInterlockMouse is -1
97 // when no DPC is executing. We increment it, and if the result is
98 // zero then the current instantiation is the only one executing, and it
99 // is okay to proceed. Otherwise, we just return.
100 //
101 //
102
103 operationContext.VariableAddress =
104 &deviceExtension->DpcInterlockMouse;
105 operationContext.Operation = IncrementOperation;
106 operationContext.NewValue = &interlockedResult;
107
108 KeSynchronizeExecution(
109 deviceExtension->MouseInterruptObject,
110 (PKSYNCHRONIZE_ROUTINE) I8xDpcVariableOperation,
111 (PVOID) &operationContext
112 );
113
114 moreDpcProcessing = (interlockedResult == 0)? TRUE:FALSE;
115
116 while (moreDpcProcessing) {
117
118 dataNotConsumed = 0;
119 inputDataConsumed = 0;
120
121 //
122 // Get the port InputData queue pointers synchronously.
123 //
124
125 getPointerContext.DeviceExtension = deviceExtension;
126 setPointerContext.DeviceExtension = deviceExtension;
127 getPointerContext.DeviceType = (CCHAR) MouseDeviceType;
128 setPointerContext.DeviceType = (CCHAR) MouseDeviceType;
129 setPointerContext.InputCount = 0;
130
131 KeSynchronizeExecution(
132 deviceExtension->MouseInterruptObject,
133 (PKSYNCHRONIZE_ROUTINE) I8xGetDataQueuePointer,
134 (PVOID) &getPointerContext
135 );
136
137 if (getPointerContext.InputCount != 0) {
138
139 //
140 // Call the connected class driver's callback ISR with the
141 // port InputData queue pointers. If we have to wrap the queue,
142 // break the operation into two pieces, and call the class callback
143 // ISR once for each piece.
144 //
145
146 classDeviceObject =
147 deviceExtension->MouseExtension.ConnectData.ClassDeviceObject;
148 classService =
149 deviceExtension->MouseExtension.ConnectData.ClassService;
150 ASSERT(classService != NULL);
151
152 if (getPointerContext.DataOut >= getPointerContext.DataIn) {
153
154 //
155 // We'll have to wrap the InputData circular buffer. Call
156 // the class callback ISR with the chunk of data starting at
157 // DataOut and ending at the end of the queue.
158 //
159
160 I8xPrint((
161 2,
162 "I8042PRT-I8042MouseIsrDpc: calling class callback\n"
163 ));
164 I8xPrint((
165 2,
166 "I8042PRT-I8042MouseIsrDpc: with Start 0x%x and End 0x%x\n",
167 getPointerContext.DataOut,
168 deviceExtension->MouseExtension.DataEnd
169 ));
170
171 (*(PSERVICE_CALLBACK_ROUTINE) classService)(
172 classDeviceObject,
173 getPointerContext.DataOut,
174 deviceExtension->MouseExtension.DataEnd,
175 &inputDataConsumed
176 );
177
178 dataNotConsumed = (((PUCHAR)
179 deviceExtension->MouseExtension.DataEnd -
180 (PUCHAR) getPointerContext.DataOut)
181 / sizeof(MOUSE_INPUT_DATA)) - inputDataConsumed;
182
183 I8xPrint((
184 2,
185 "I8042PRT-I8042MouseIsrDpc: (Wrap) Call callback consumed %d items, left %d\n",
186 inputDataConsumed,
187 dataNotConsumed
188 ));
189
190 setPointerContext.InputCount += inputDataConsumed;
191
192 if (dataNotConsumed) {
193 setPointerContext.DataOut =
194 ((PUCHAR)getPointerContext.DataOut) +
195 (inputDataConsumed * sizeof(MOUSE_INPUT_DATA));
196 } else {
197 setPointerContext.DataOut =
198 deviceExtension->MouseExtension.InputData;
199 getPointerContext.DataOut = setPointerContext.DataOut;
200 }
201 }
202
203 //
204 // Call the class callback ISR with data remaining in the queue.
205 //
206
207 if ((dataNotConsumed == 0) &&
208 (inputDataConsumed < getPointerContext.InputCount)){
209 I8xPrint((
210 2,
211 "I8042PRT-I8042MouseIsrDpc: calling class callback\n"
212 ));
213 I8xPrint((
214 2,
215 "I8042PRT-I8042MouseIsrDpc: with Start 0x%x and End 0x%x\n",
216 getPointerContext.DataOut,
217 getPointerContext.DataIn
218 ));
219
220 (*(PSERVICE_CALLBACK_ROUTINE) classService)(
221 classDeviceObject,
222 getPointerContext.DataOut,
223 getPointerContext.DataIn,
224 &inputDataConsumed
225 );
226
227 dataNotConsumed = (((PUCHAR) getPointerContext.DataIn -
228 (PUCHAR) getPointerContext.DataOut)
229 / sizeof(MOUSE_INPUT_DATA)) - inputDataConsumed;
230
231 I8xPrint((
232 2,
233 "I8042PRT-I8042MouseIsrDpc: Call callback consumed %d items, left %d\n",
234 inputDataConsumed,
235 dataNotConsumed
236 ));
237
238 setPointerContext.DataOut =
239 ((PUCHAR)getPointerContext.DataOut) +
240 (inputDataConsumed * sizeof(MOUSE_INPUT_DATA));
241 setPointerContext.InputCount += inputDataConsumed;
242
243 }
244
245 //
246 // Update the port InputData queue DataOut pointer and InputCount
247 // synchronously.
248 //
249
250 KeSynchronizeExecution(
251 deviceExtension->MouseInterruptObject,
252 (PKSYNCHRONIZE_ROUTINE) I8xSetDataQueuePointer,
253 (PVOID) &setPointerContext
254 );
255
256 }
257
258 if (dataNotConsumed) {
259
260 //
261 // The class driver was unable to consume all the data.
262 // Reset the interlocked variable to -1. We do not want
263 // to attempt to move more data to the class driver at this
264 // point, because it is already overloaded. Need to wait a
265 // while to give the Raw Input Thread a chance to read some
266 // of the data out of the class driver's queue. We accomplish
267 // this "wait" via a timer.
268 //
269
270 I8xPrint((2, "I8042PRT-I8042MouseIsrDpc: set timer in DPC\n"));
271
272 operationContext.Operation = WriteOperation;
273 interlockedResult = -1;
274 operationContext.NewValue = &interlockedResult;
275
276 KeSynchronizeExecution(
277 deviceExtension->MouseInterruptObject,
278 (PKSYNCHRONIZE_ROUTINE) I8xDpcVariableOperation,
279 (PVOID) &operationContext
280 );
281
282 deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000);
283 deltaTime.HighPart = -1;
284
285 (VOID) KeSetTimer(
286 &deviceExtension->MouseExtension.DataConsumptionTimer,
287 deltaTime,
288 &deviceExtension->MouseIsrDpcRetry
289 );
290
291 moreDpcProcessing = FALSE;
292
293 } else {
294
295 //
296 // Decrement DpcInterlockMouse. If the result goes negative,
297 // then we're all finished processing the DPC. Otherwise, either
298 // the ISR incremented DpcInterlockMouse because it has more
299 // work for the ISR DPC to do, or a concurrent DPC executed on
300 // some processor while the current DPC was running (the
301 // concurrent DPC wouldn't have done any work). Make sure that
302 // the current DPC handles any extra work that is ready to be
303 // done.
304 //
305
306 operationContext.Operation = DecrementOperation;
307 operationContext.NewValue = &interlockedResult;
308
309 KeSynchronizeExecution(
310 deviceExtension->MouseInterruptObject,
311 (PKSYNCHRONIZE_ROUTINE) I8xDpcVariableOperation,
312 (PVOID) &operationContext
313 );
314
315 if (interlockedResult != -1) {
316
317 //
318 // The interlocked variable is still greater than or equal to
319 // zero. Reset it to zero, so that we execute the loop one
320 // more time (assuming no more DPCs execute and bump the
321 // variable up again).
322 //
323
324 operationContext.Operation = WriteOperation;
325 interlockedResult = 0;
326 operationContext.NewValue = &interlockedResult;
327
328 KeSynchronizeExecution(
329 deviceExtension->MouseInterruptObject,
330 (PKSYNCHRONIZE_ROUTINE) I8xDpcVariableOperation,
331 (PVOID) &operationContext
332 );
333
334 I8xPrint((2, "I8042PRT-I8042MouseIsrDpc: loop in DPC\n"));
335 } else {
336 moreDpcProcessing = FALSE;
337 }
338 }
339 }
340
341 I8xPrint((2, "I8042PRT-I8042MouseIsrDpc: exit\n"));
342
343}
344
345
346BOOLEAN
347I8xWriteDataToMouseQueue(
348 PPORT_MOUSE_EXTENSION MouseExtension,
349 IN PMOUSE_INPUT_DATA InputData
350 )
351
352/*++
353
354Routine Description:
355
356 This routine adds input data from the mouse to the InputData queue.
357
358Arguments:
359
360 MouseExtension - Pointer to the mouse portion of the device extension.
361
362 InputData - Pointer to the data to add to the InputData queue.
363
364Return Value:
365
366 Returns TRUE if the data was added, otherwise FALSE.
367
368--*/
369
370{
371
372 I8xPrint((2,"I8042PRT-I8xWriteDataToMouseQueue: enter\n"));
373 I8xPrint((
374 3,
375 "I8042PRT-I8xWriteDataToMouseQueue: DataIn 0x%x, DataOut 0x%x\n",
376 MouseExtension->DataIn,
377 MouseExtension->DataOut
378 ));
379 I8xPrint((
380 3,
381 "I8042PRT-I8xWriteDataToMouseQueue: InputCount %d\n",
382 MouseExtension->InputCount
383 ));
384
385 //
386 // Check for full input data queue.
387 //
388
389 if ((MouseExtension->DataIn == MouseExtension->DataOut) &&
390 (MouseExtension->InputCount != 0)) {
391
392 //
393 // The input data queue is full. Intentionally ignore
394 // the new data.
395 //
396
397 I8xPrint((1,"I8042PRT-I8xWriteDataToMouseQueue: OVERFLOW\n"));
398 return(FALSE);
399
400 } else {
401 *(MouseExtension->DataIn) = *InputData;
402 MouseExtension->InputCount += 1;
403 MouseExtension->DataIn++;
404 I8xPrint((
405 2,
406 "I8042PRT-I8xWriteDataToMouseQueue: new InputCount %d\n",
407 MouseExtension->InputCount
408 ));
409 if (MouseExtension->DataIn == MouseExtension->DataEnd) {
410 I8xPrint((2,"I8042PRT-I8xWriteDataToMouseQueue: wrap buffer\n"));
411 MouseExtension->DataIn = MouseExtension->InputData;
412 }
413 }
414
415 I8xPrint((2,"I8042PRT-I8xWriteDataToMouseQueue: exit\n"));
416
417 return(TRUE);
418}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette