|
|
1.1 root 1:
2: /*++
3:
4: Copyright (c) 1990, 1991, 1992, 1993 Microsoft Corporation
5:
6: Module Name:
7:
8: moudep.c
9:
10: Abstract:
11:
12: The initialization and hardware-dependent portions of
13: the Intel i8042 port driver which are specific to
14: the auxiliary (PS/2 mouse) device.
15:
16: Environment:
17:
18: Kernel mode only.
19:
20: Notes:
21:
22: NOTES: (Future/outstanding issues)
23:
24: - Powerfail not implemented.
25:
26: - Consolidate duplicate code, where possible and appropriate.
27:
28: Revision History:
29:
30: --*/
31:
32: #include "stdarg.h"
33: #include "stdio.h"
34: #include "string.h"
35: #include "ntddk.h"
36: #include "i8042prt.h"
37: #include "i8042log.h"
38:
39: //
40: // Use the alloc_text pragma to specify the driver initialization routines
41: // (they can be paged out).
42: //
43:
44: #ifdef ALLOC_PRAGMA
45: #pragma alloc_text(init,I8xMouseConfiguration)
46: #pragma alloc_text(init,I8xMousePeripheralCallout)
47: #pragma alloc_text(init,I8xInitializeMouse)
48: #endif
49:
50:
51: BOOLEAN
52: I8042MouseInterruptService(
53: IN PKINTERRUPT Interrupt,
54: IN PVOID Context
55: )
56:
57: /*++
58:
59: Routine Description:
60:
61: This is the interrupt service routine for the mouse device.
62:
63: Arguments:
64:
65: Interrupt - A pointer to the interrupt object for this interrupt.
66:
67: Context - A pointer to the device object.
68:
69: Return Value:
70:
71: Returns TRUE if the interrupt was expected (and therefore processed);
72: otherwise, FALSE is returned.
73:
74: --*/
75:
76: {
77: PDEVICE_EXTENSION deviceExtension;
78: PDEVICE_OBJECT deviceObject;
79: LARGE_INTEGER tickDelta, newTick;
80: UCHAR previousButtons;
81: UCHAR previousSignAndOverflow;
82: UCHAR byte;
83:
84: UNREFERENCED_PARAMETER(Interrupt);
85:
86: I8xPrint((2, "I8042PRT-I8042MouseInterruptService: enter\n"));
87:
88: deviceObject = (PDEVICE_OBJECT) Context;
89: deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
90:
91: //
92: // Verify that this device really interrupted. Check the status
93: // register. The Output Buffer Full bit should be set, and the
94: // Auxiliary Device Output Buffer Full bit should be set.
95: //
96:
97: if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort])
98: & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
99: != (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)) {
100:
101: //
102: // Stall and then try again. The Olivetti MIPS machine
103: // sometimes gets a mouse interrupt before the status
104: // register is set.
105: //
106:
107: KeStallExecutionProcessor(10);
108: if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort])
109: & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
110: != (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)) {
111:
112: //
113: // Not our interrupt.
114: //
115:
116: I8xPrint((
117: 1,
118: "I8042PRT-I8042MouseInterruptService: not our interrupt!\n"
119: ));
120: return(FALSE);
121: }
122: }
123:
124: //
125: // Read the byte from the i8042 data port.
126: //
127:
128: I8xGetByteAsynchronous(
129: (CCHAR) MouseDeviceType,
130: deviceExtension,
131: &byte
132: );
133:
134: I8xPrint((
135: 3,
136: "I8042PRT-I8042MouseInterruptService: byte 0x%x\n",
137: byte
138: ));
139:
140: //
141: // Take the appropriate action, depending on the current state.
142: // When the state is Idle, we expect to receive mouse button
143: // data. When the state is XMovement, we expect to receive mouse
144: // motion in the X direction data. When the state is YMovement,
145: // we expect to receive mouse motion in the Y direction data. Once
146: // the Y motion data has been received, the data is queued to the
147: // mouse InputData queue, the mouse ISR DPC is requested, and the
148: // state returns to Idle.
149: //
150:
151: KeQueryTickCount(&newTick);
152: tickDelta = RtlLargeIntegerSubtract(
153: newTick,
154: deviceExtension->MouseExtension.PreviousTick
155: );
156:
157: if ((deviceExtension->MouseExtension.InputState != MouseIdle)
158: && (deviceExtension->MouseExtension.InputState != MouseExpectingACK)
159: && ((tickDelta.LowPart >= deviceExtension->MouseExtension.SynchTickCount)
160: || (tickDelta.HighPart != 0))) {
161:
162: //
163: // It has been a long time since we got a byte of
164: // the data packet. Assume that we are now receiving
165: // the first byte of a new packet, and discard any
166: // partially received packet.
167: //
168: // N.B. We assume that SynchTickCount is ULONG, and avoid
169: // a LARGE_INTEGER compare with tickDelta...
170: //
171:
172: I8xPrint((
173: 1,
174: "I8042PRT-I8042MouseInterruptService: State was %d, synching\n",
175: deviceExtension->MouseExtension.InputState
176: ));
177:
178: deviceExtension->MouseExtension.InputState = MouseIdle;
179: }
180:
181: deviceExtension->MouseExtension.PreviousTick = newTick;
182:
183: switch(deviceExtension->MouseExtension.InputState) {
184:
185: //
186: // The mouse interrupted with a status byte. The status byte
187: // contains information on the mouse button state along with
188: // the sign and overflow bits for the (yet-to-be-received)
189: // X and Y motion bytes.
190: //
191:
192: case MouseIdle:
193:
194: I8xPrint((
195: 3,
196: "I8042PRT-I8042MouseInterruptService: mouse status byte\n"
197: ));
198:
199: //
200: // Update CurrentInput with button transition data.
201: // I.e., set a button up/down bit in the Buttons field if
202: // the state of a given button has changed since we
203: // received the last packet.
204: //
205:
206: previousButtons =
207: deviceExtension->MouseExtension.PreviousButtons;
208:
209: deviceExtension->MouseExtension.CurrentInput.Buttons = 0;
210:
211: if ((!(previousButtons & LEFT_BUTTON_DOWN))
212: && (byte & LEFT_BUTTON_DOWN)) {
213: deviceExtension->MouseExtension.CurrentInput.Buttons |=
214: MOUSE_LEFT_BUTTON_DOWN;
215: } else
216: if ((previousButtons & LEFT_BUTTON_DOWN)
217: && !(byte & LEFT_BUTTON_DOWN)) {
218: deviceExtension->MouseExtension.CurrentInput.Buttons |=
219: MOUSE_LEFT_BUTTON_UP;
220: }
221: if ((!(previousButtons & RIGHT_BUTTON_DOWN))
222: && (byte & RIGHT_BUTTON_DOWN)) {
223: deviceExtension->MouseExtension.CurrentInput.Buttons |=
224: MOUSE_RIGHT_BUTTON_DOWN;
225: } else
226: if ((previousButtons & RIGHT_BUTTON_DOWN)
227: && !(byte & RIGHT_BUTTON_DOWN)) {
228: deviceExtension->MouseExtension.CurrentInput.Buttons |=
229: MOUSE_RIGHT_BUTTON_UP;
230: }
231: if ((!(previousButtons & MIDDLE_BUTTON_DOWN))
232: && (byte & MIDDLE_BUTTON_DOWN)) {
233: deviceExtension->MouseExtension.CurrentInput.Buttons |=
234: MOUSE_MIDDLE_BUTTON_DOWN;
235: } else
236: if ((previousButtons & MIDDLE_BUTTON_DOWN)
237: && !(byte & MIDDLE_BUTTON_DOWN)) {
238: deviceExtension->MouseExtension.CurrentInput.Buttons |=
239: MOUSE_MIDDLE_BUTTON_UP;
240: }
241:
242: //
243: // Save the button state for comparison the next time around.
244: //
245:
246: deviceExtension->MouseExtension.PreviousButtons =
247: byte & (RIGHT_BUTTON_DOWN|MIDDLE_BUTTON_DOWN|LEFT_BUTTON_DOWN);
248:
249: //
250: // Save the sign and overflow information from the current byte.
251: //
252:
253: deviceExtension->MouseExtension.CurrentSignAndOverflow =
254: (UCHAR) (byte & MOUSE_SIGN_OVERFLOW_MASK);
255:
256: //
257: // Update to the next state.
258: //
259:
260: deviceExtension->MouseExtension.InputState = XMovement;
261:
262: break;
263:
264: //
265: // The mouse interrupted with the X motion byte. Apply
266: // the sign and overflow bits from the mouse status byte received
267: // previously. Attempt to correct for bogus changes in sign
268: // that occur with large, rapid mouse movements.
269: //
270:
271: case XMovement:
272:
273: I8xPrint((
274: 3,
275: "I8042PRT-I8042MouseInterruptService: mouse LastX byte\n"
276: ));
277:
278: //
279: // Update CurrentInput with the X motion data.
280: //
281:
282: if (deviceExtension->MouseExtension.CurrentSignAndOverflow
283: & X_OVERFLOW) {
284:
285: //
286: // Handle overflow in the X direction. If the previous
287: // mouse movement overflowed too, ensure that the current
288: // overflow is in the same direction (i.e., that the sign
289: // is the same as it was for the previous event). We do this
290: // to correct for hardware problems -- it should not be possible
291: // to overflow in one direction and then immediately overflow
292: // in the opposite direction.
293: //
294:
295: previousSignAndOverflow =
296: deviceExtension->MouseExtension.PreviousSignAndOverflow;
297: if (previousSignAndOverflow & X_OVERFLOW) {
298: if ((previousSignAndOverflow & X_DATA_SIGN) !=
299: (deviceExtension->MouseExtension.CurrentSignAndOverflow
300: & X_DATA_SIGN)) {
301: deviceExtension->MouseExtension.CurrentSignAndOverflow
302: ^= X_DATA_SIGN;
303: }
304: }
305:
306: if (deviceExtension->MouseExtension.CurrentSignAndOverflow &
307: X_DATA_SIGN)
308: deviceExtension->MouseExtension.CurrentInput.LastX =
309: (LONG) MOUSE_MAXIMUM_NEGATIVE_DELTA;
310: else
311: deviceExtension->MouseExtension.CurrentInput.LastX =
312: (LONG) MOUSE_MAXIMUM_POSITIVE_DELTA;
313:
314: } else {
315:
316: //
317: // No overflow. Just store the data, correcting for the
318: // sign if necessary.
319: //
320:
321: deviceExtension->MouseExtension.CurrentInput.LastX =
322: (ULONG) byte;
323: if (deviceExtension->MouseExtension.CurrentSignAndOverflow &
324: X_DATA_SIGN)
325: deviceExtension->MouseExtension.CurrentInput.LastX |=
326: MOUSE_MAXIMUM_NEGATIVE_DELTA;
327: }
328:
329: //
330: // Update to the next state.
331: //
332:
333: deviceExtension->MouseExtension.InputState = YMovement;
334:
335: break;
336:
337: //
338: // The mouse interrupted with the Y motion byte. Apply
339: // the sign and overflow bits from the mouse status byte received
340: // previously. [Attempt to correct for bogus changes in sign
341: // that occur with large, rapid mouse movements.] Write the
342: // data to the mouse InputData queue, and queue the mouse ISR DPC
343: // to complete the interrupt processing.
344: //
345:
346: case YMovement:
347:
348: I8xPrint((
349: 3,
350: "I8042PRT-I8042MouseInterruptService: mouse LastY byte\n"
351: ));
352:
353: //
354: // Update CurrentInput with the Y motion data.
355: //
356:
357: if (deviceExtension->MouseExtension.CurrentSignAndOverflow
358: & Y_OVERFLOW) {
359:
360: //
361: // Handle overflow in the Y direction. If the previous
362: // mouse movement overflowed too, ensure that the current
363: // overflow is in the same direction (i.e., that the sign
364: // is the same as it was for the previous event). We do this
365: // to correct for hardware problems -- it should not be possible
366: // to overflow in one direction and then immediately overflow
367: // in the opposite direction.
368: //
369:
370: previousSignAndOverflow =
371: deviceExtension->MouseExtension.PreviousSignAndOverflow;
372: if (previousSignAndOverflow & Y_OVERFLOW) {
373: if ((previousSignAndOverflow & Y_DATA_SIGN) !=
374: (deviceExtension->MouseExtension.CurrentSignAndOverflow
375: & Y_DATA_SIGN)) {
376: deviceExtension->MouseExtension.CurrentSignAndOverflow
377: ^= Y_DATA_SIGN;
378: }
379: }
380:
381: if (deviceExtension->MouseExtension.CurrentSignAndOverflow &
382: Y_DATA_SIGN)
383: deviceExtension->MouseExtension.CurrentInput.LastY =
384: (LONG) MOUSE_MAXIMUM_POSITIVE_DELTA;
385: else
386: deviceExtension->MouseExtension.CurrentInput.LastY =
387: (LONG) MOUSE_MAXIMUM_NEGATIVE_DELTA;
388:
389: } else {
390:
391: //
392: // No overflow. Just store the data, correcting for the
393: // sign if necessary.
394: //
395:
396: deviceExtension->MouseExtension.CurrentInput.LastY =
397: (ULONG) byte;
398: if (deviceExtension->MouseExtension.CurrentSignAndOverflow &
399: Y_DATA_SIGN)
400: deviceExtension->MouseExtension.CurrentInput.LastY |=
401: MOUSE_MAXIMUM_NEGATIVE_DELTA;
402:
403: //
404: // Negate the LastY value (the hardware reports positive
405: // motion in the direction that we consider negative).
406: //
407:
408: deviceExtension->MouseExtension.CurrentInput.LastY =
409: -deviceExtension->MouseExtension.CurrentInput.LastY;
410:
411: }
412:
413: //
414: // Update our notion of the previous sign and overflow bits for
415: // the start of the next mouse input sequence.
416: //
417:
418: deviceExtension->MouseExtension.PreviousSignAndOverflow =
419: deviceExtension->MouseExtension.CurrentSignAndOverflow;
420:
421: //
422: // If the mouse is enabled, add the data to the InputData queue
423: // and queue the ISR DPC. One might wonder why we bother to
424: // do all this processing of the mouse packet, only to toss it
425: // away (i.e., not queue it) at this point. The answer is that
426: // this mouse provides no data to allow the driver to determine
427: // when the first byte of a packet is received -- if the driver
428: // doesn't process all interrupts from the start, there is no
429: // way to keep MouseExtension.InputState in synch with hardware
430: // reality.
431: //
432:
433: if (deviceExtension->MouseEnableCount) {
434: deviceExtension->MouseExtension.CurrentInput.UnitId =
435: deviceExtension->MouseExtension.UnitId;
436: if (!I8xWriteDataToMouseQueue(
437: &deviceExtension->MouseExtension,
438: &deviceExtension->MouseExtension.CurrentInput
439: )) {
440:
441: //
442: // InputData queue overflowed.
443: //
444: // Queue a DPC to log an overrun error.
445: //
446:
447: I8xPrint((
448: 1,
449: "I8042PRT-I8042MouseInterruptService: queue overflow\n"
450: ));
451:
452: if (deviceExtension->MouseExtension.OkayToLogOverflow) {
453: KeInsertQueueDpc(
454: &deviceExtension->ErrorLogDpc,
455: (PIRP) NULL,
456: (PVOID) (ULONG) I8042_MOU_BUFFER_OVERFLOW
457: );
458: deviceExtension->MouseExtension.OkayToLogOverflow =
459: FALSE;
460: }
461:
462: } else if (deviceExtension->DpcInterlockMouse >= 0) {
463:
464: //
465: // The ISR DPC is already executing. Tell the ISR DPC it has
466: // more work to do by incrementing DpcInterlockMouse.
467: //
468:
469: deviceExtension->DpcInterlockMouse += 1;
470:
471: } else {
472:
473: //
474: // Queue the ISR DPC.
475: //
476:
477: KeInsertQueueDpc(
478: &deviceExtension->MouseIsrDpc,
479: deviceObject->CurrentIrp,
480: NULL
481: );
482: }
483:
484: }
485:
486: //
487: // Reset the state.
488: //
489:
490: deviceExtension->MouseExtension.InputState = MouseIdle;
491:
492: break;
493:
494: case MouseExpectingACK:
495:
496: //
497: // This is a special case. We hit this on one of the very
498: // first mouse interrupts following the IoConnectInterrupt.
499: // The interrupt is caused when we enable mouse transmissions
500: // via I8xMouseEnableTransmission() -- the hardware returns
501: // an ACK. Just toss this byte away, and set the input state
502: // to coincide with the start of a new mouse data packet.
503: //
504:
505: I8xPrint((
506: 1,
507: "I8042PRT-I8042MouseInterruptService: expecting ACK (0x%x), got 0x%x\n",
508: (ULONG) ACKNOWLEDGE,
509: (ULONG) byte
510: ));
511:
512: if (byte == (UCHAR) ACKNOWLEDGE) {
513: deviceExtension->MouseExtension.InputState = MouseIdle;
514: } else if (byte == (UCHAR) RESEND) {
515:
516: //
517: // Resend the "Enable Mouse Transmission" sequence.
518: //
519: // NOTE: This is a hack for the Olivetti MIPS machine,
520: // which sends a resend response if a key is held down
521: // while we're attempting the I8xMouseEnableTransmission.
522: //
523:
524: I8xPutByteAsynchronous(
525: (CCHAR) CommandPort,
526: deviceExtension,
527: (UCHAR) I8042_WRITE_TO_AUXILIARY_DEVICE
528: );
529:
530: I8xPutByteAsynchronous(
531: (CCHAR) DataPort,
532: deviceExtension,
533: (UCHAR) ENABLE_MOUSE_TRANSMISSION
534: );
535: }
536:
537: break;
538:
539: default:
540:
541: I8xPrint((
542: 3,
543: "I8042PRT-I8042MouseInterruptService: INVALID STATE\n"
544: ));
545:
546: //
547: // Queue a DPC to log an internal driver error.
548: //
549:
550: KeInsertQueueDpc(
551: &deviceExtension->ErrorLogDpc,
552: (PIRP) NULL,
553: (PVOID) (ULONG) I8042_INVALID_ISR_STATE
554: );
555:
556: ASSERT(FALSE);
557: break;
558:
559: }
560:
561: I8xPrint((2, "I8042PRT-I8042MouseInterruptService: exit\n"));
562:
563: return(TRUE);
564: }
565:
566: NTSTATUS
567: I8xInitializeMouse(
568: IN PDEVICE_OBJECT DeviceObject
569: )
570:
571: /*++
572:
573: Routine Description:
574:
575: This routine initializes the i8042 mouse hardware. It is called
576: only at initialization, and does not synchronize access to the hardware.
577:
578: Arguments:
579:
580: DeviceObject - Pointer to the device object.
581:
582: Return Value:
583:
584: Returns status.
585:
586: --*/
587:
588: {
589: NTSTATUS status;
590: PDEVICE_EXTENSION deviceExtension;
591: UCHAR byte;
592: ULONG i;
593: PIO_ERROR_LOG_PACKET errorLogEntry;
594: ULONG uniqueErrorValue;
595: NTSTATUS errorCode = STATUS_SUCCESS;
596: ULONG dumpCount = 0;
597:
598: #define DUMP_COUNT 4
599: ULONG dumpData[DUMP_COUNT];
600:
601: I8xPrint((2, "I8042PRT-I8xInitializeMouse: enter\n"));
602:
603: for (i = 0; i < DUMP_COUNT; i++)
604: dumpData[i] = 0;
605:
606: //
607: // Get the device extension.
608: //
609:
610: deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
611:
612: //
613: // Reset the mouse. Send a Write To Auxiliary Device command to the
614: // 8042 controller. Then send the Reset Mouse command to the mouse
615: // through the 8042 data register. Expect to get back an ACK, followed
616: // by a completion code and the ID code (0x00).
617: //
618:
619: status = I8xPutBytePolled(
620: (CCHAR) DataPort,
621: WAIT_FOR_ACKNOWLEDGE,
622: (CCHAR) MouseDeviceType,
623: deviceExtension,
624: (UCHAR) MOUSE_RESET
625: );
626: if (!NT_SUCCESS(status)) {
627: I8xPrint((
628: 1,
629: "I8042PRT-I8xInitializeMouse: failed mouse reset, status 0x%x\n",
630: status
631: ));
632:
633: //
634: // Set up error log info.
635: //
636:
637: errorCode = I8042_MOU_RESET_COMMAND_FAILED;
638: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 415;
639: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
640: dumpData[1] = DataPort;
641: dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
642: dumpData[3] = MOUSE_RESET;
643: dumpCount = 4;
644:
645: goto I8xInitializeMouseExit;
646: }
647:
648: //
649: // Get the mouse reset responses. The first response should be a
650: // MOUSE_COMPLETE. The second response should be the mouse ID.
651: // Note that it is usually necessary to stall a long time to get the
652: // mouse reset/self-test to work. The stall value was determined by
653: // experimentation.
654: //
655: //
656:
657: for (i = 0; i < 11200; i++) {
658:
659: status = I8xGetBytePolled(
660: (CCHAR) ControllerDeviceType,
661: deviceExtension,
662: &byte
663: );
664:
665: if (NT_SUCCESS(status) && (byte == (UCHAR) MOUSE_COMPLETE)) {
666:
667: //
668: // The reset completed successfully.
669: //
670:
671: break;
672:
673:
674: } else {
675:
676: //
677: // Stall, and then try again to get a response from
678: // the reset.
679: //
680:
681: if (status == STATUS_IO_TIMEOUT) {
682:
683: //
684: // Stall, and then try again to get a response from
685: // the reset.
686: //
687:
688: KeStallExecutionProcessor(50);
689:
690: } else {
691:
692: break;
693:
694: }
695: }
696: }
697:
698: if (!NT_SUCCESS(status)) {
699: I8xPrint((
700: 1,
701: "I8042PRT-I8xInitializeMouse: failed reset response 1, status 0x%x, byte 0x%x\n",
702: status,
703: byte
704: ));
705:
706: //
707: // Set up error log info.
708: //
709:
710: errorCode = I8042_MOU_RESET_RESPONSE_FAILED;
711: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 420;
712: dumpData[0] = KBDMOU_INCORRECT_RESPONSE;
713: dumpData[1] = ControllerDeviceType;
714: dumpData[2] = MOUSE_COMPLETE;
715: dumpData[3] = byte;
716: dumpCount = 4;
717:
718: goto I8xInitializeMouseExit;
719: }
720:
721: status = I8xGetBytePolled(
722: (CCHAR) ControllerDeviceType,
723: deviceExtension,
724: &byte
725: );
726:
727: if ((!NT_SUCCESS(status)) || (byte != MOUSE_ID_BYTE)) {
728: I8xPrint((
729: 1,
730: "I8042PRT-I8xInitializeMouse: failed reset response 2, status 0x%x, byte 0x%x\n",
731: status,
732: byte
733: ));
734:
735: //
736: // Set up error log info.
737: //
738:
739: errorCode = I8042_MOU_RESET_RESPONSE_FAILED;
740: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 425;
741: dumpData[0] = KBDMOU_INCORRECT_RESPONSE;
742: dumpData[1] = ControllerDeviceType;
743: dumpData[2] = MOUSE_ID_BYTE;
744: dumpData[3] = byte;
745: dumpCount = 4;
746:
747: goto I8xInitializeMouseExit;
748: }
749:
750: //
751: // Set mouse sampling rate. Send a Write To Auxiliary Device command
752: // to the 8042 controller. Then send the Set Mouse Sampling Rate
753: // command to the mouse through the 8042 data register,
754: // followed by its parameter.
755: //
756:
757: status = I8xPutBytePolled(
758: (CCHAR) DataPort,
759: WAIT_FOR_ACKNOWLEDGE,
760: (CCHAR) MouseDeviceType,
761: deviceExtension,
762: (UCHAR) SET_MOUSE_SAMPLING_RATE
763: );
764: if (!NT_SUCCESS(status)) {
765: I8xPrint((
766: 1,
767: "I8042PRT-I8xInitializeMouse: failed write set sample rate, status 0x%x\n",
768: status
769: ));
770:
771: //
772: // Set up error log info.
773: //
774:
775: errorCode = I8042_SET_SAMPLE_RATE_FAILED;
776: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 435;
777: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
778: dumpData[1] = DataPort;
779: dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
780: dumpData[3] = SET_MOUSE_SAMPLING_RATE;
781: dumpCount = 4;
782:
783: goto I8xInitializeMouseExit;
784: }
785:
786: status = I8xPutBytePolled(
787: (CCHAR) DataPort,
788: WAIT_FOR_ACKNOWLEDGE,
789: (CCHAR) MouseDeviceType,
790: deviceExtension,
791: (UCHAR) MOUSE_SAMPLE_RATE
792: );
793: if (!NT_SUCCESS(status)) {
794: I8xPrint((
795: 1,
796: "I8042PRT-I8xInitializeMouse: failed write sample rate, status 0x%x\n",
797: status
798: ));
799:
800: //
801: // Set up error log info.
802: //
803:
804: errorCode = I8042_SET_SAMPLE_RATE_FAILED;
805: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 445;
806: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
807: dumpData[1] = DataPort;
808: dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
809: dumpData[3] = MOUSE_SAMPLE_RATE;
810: dumpCount = 4;
811:
812: goto I8xInitializeMouseExit;
813: }
814:
815: //
816: // Set the mouse resolution. Send a Write To Auxiliary Device command
817: // to the 8042 controller. Then send the Set Mouse Resolution
818: // command to the mouse through the 8042 data register,
819: // followed by its parameter.
820: //
821:
822: status = I8xPutBytePolled(
823: (CCHAR) DataPort,
824: WAIT_FOR_ACKNOWLEDGE,
825: (CCHAR) MouseDeviceType,
826: deviceExtension,
827: (UCHAR) SET_MOUSE_RESOLUTION
828: );
829: if (!NT_SUCCESS(status)) {
830: I8xPrint((
831: 1,
832: "I8042PRT-I8xInitializeMouse: failed write set resolution, status 0x%x\n",
833: status
834: ));
835:
836: //
837: // Set up error log info.
838: //
839:
840: errorCode = I8042_SET_RESOLUTION_FAILED;
841: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 455;
842: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
843: dumpData[1] = DataPort;
844: dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
845: dumpData[3] = SET_MOUSE_RESOLUTION;
846: dumpCount = 4;
847:
848: goto I8xInitializeMouseExit;
849: }
850:
851: status = I8xPutBytePolled(
852: (CCHAR) DataPort,
853: WAIT_FOR_ACKNOWLEDGE,
854: (CCHAR) MouseDeviceType,
855: deviceExtension,
856: (UCHAR) deviceExtension->Configuration.MouseResolution
857: );
858: if (!NT_SUCCESS(status)) {
859: I8xPrint((
860: 1,
861: "I8042PRT-I8xInitializeMouse: failed set mouse resolution, status 0x%x\n",
862: status
863: ));
864:
865: //
866: // Set up error log info.
867: //
868:
869: errorCode = I8042_SET_RESOLUTION_FAILED;
870: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 465;
871: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
872: dumpData[1] = DataPort;
873: dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
874: dumpData[3] = deviceExtension->Configuration.MouseResolution;
875: dumpCount = 4;
876:
877: goto I8xInitializeMouseExit;
878: }
879:
880: I8xInitializeMouseExit:
881:
882: if (!NT_SUCCESS(status)) {
883:
884: //
885: // The mouse initialization failed. Log an error.
886: //
887:
888: if (errorCode != STATUS_SUCCESS) {
889: errorLogEntry = (PIO_ERROR_LOG_PACKET)
890: IoAllocateErrorLogEntry(
891: DeviceObject,
892: (UCHAR) (sizeof(IO_ERROR_LOG_PACKET)
893: + (dumpCount * sizeof(ULONG)))
894: );
895:
896: if (errorLogEntry != NULL) {
897:
898: errorLogEntry->ErrorCode = errorCode;
899: errorLogEntry->DumpDataSize = dumpCount * sizeof(ULONG);
900: errorLogEntry->SequenceNumber = 0;
901: errorLogEntry->MajorFunctionCode = 0;
902: errorLogEntry->IoControlCode = 0;
903: errorLogEntry->RetryCount = 0;
904: errorLogEntry->UniqueErrorValue = uniqueErrorValue;
905: errorLogEntry->FinalStatus = status;
906: for (i = 0; i < dumpCount; i++)
907: errorLogEntry->DumpData[i] = dumpData[i];
908:
909: IoWriteErrorLogEntry(errorLogEntry);
910: }
911: }
912: }
913:
914: //
915: // Initialize current mouse input packet state.
916: //
917:
918: deviceExtension->MouseExtension.PreviousSignAndOverflow = 0;
919: deviceExtension->MouseExtension.InputState = MouseExpectingACK;
920:
921: I8xPrint((2, "I8042PRT-I8xInitializeMouse: exit\n"));
922:
923: return(status);
924: }
925:
926: VOID
927: I8xMouseConfiguration(
928: IN PDEVICE_EXTENSION DeviceExtension,
929: IN PUNICODE_STRING RegistryPath,
930: IN PUNICODE_STRING KeyboardDeviceName,
931: IN PUNICODE_STRING PointerDeviceName
932: )
933:
934: /*++
935:
936: Routine Description:
937:
938: This routine retrieves the configuration information for the mouse.
939:
940: Arguments:
941:
942: DeviceExtension - Pointer to the device extension.
943:
944: RegistryPath - Pointer to the null-terminated Unicode name of the
945: registry path for this driver.
946:
947: KeyboardDeviceName - Pointer to the Unicode string that will receive
948: the keyboard port device name.
949:
950: PointerDeviceName - Pointer to the Unicode string that will receive
951: the pointer port device name.
952:
953:
954: Return Value:
955:
956: None. As a side-effect, may set DeviceExtension->HardwarePresent.
957:
958: --*/
959: {
960: NTSTATUS status = STATUS_SUCCESS;
961: INTERFACE_TYPE interfaceType;
962: CONFIGURATION_TYPE controllerType = PointerController;
963: CONFIGURATION_TYPE peripheralType = PointerPeripheral;
964: ULONG i;
965:
966: for (i = 0; i < MaximumInterfaceType; i++) {
967:
968: //
969: // Get the registry information for this device.
970: //
971:
972: interfaceType = i;
973: status = IoQueryDeviceDescription(&interfaceType,
974: NULL,
975: &controllerType,
976: NULL,
977: &peripheralType,
978: NULL,
979: I8xMousePeripheralCallout,
980: (PVOID) DeviceExtension);
981:
982: if (DeviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) {
983:
984: //
985: // If we didn't already get these when determining the keyboard
986: // configuration, get the service parameters now (e.g.,
987: // user-configurable number of resends, polling iterations, etc.).
988: //
989:
990: if (!(DeviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT))
991: I8xServiceParameters(
992: DeviceExtension,
993: RegistryPath,
994: KeyboardDeviceName,
995: PointerDeviceName
996: );
997:
998: //
999: // Initialize mouse-specific configuration parameters.
1000: //
1001:
1002: DeviceExtension->Configuration.MouseAttributes.MouseIdentifier =
1003: MOUSE_I8042_HARDWARE;
1004:
1005: break;
1006:
1007: } else {
1008: I8xPrint((
1009: 1,
1010: "I8042PRT-I8xMouseConfiguration: IoQueryDeviceDescription for bus type %d failed\n",
1011: interfaceType
1012: ));
1013: }
1014: }
1015: }
1016:
1017: NTSTATUS
1018: I8xMouseEnableTransmission(
1019: IN PDEVICE_OBJECT DeviceObject
1020: )
1021:
1022: /*++
1023:
1024: Routine Description:
1025:
1026: This routine sends an Enable command to the mouse hardware, causing
1027: the mouse to begin transmissions. It is called at initialization
1028: time, but only after the interrupt has been connected. This is
1029: necessary so the driver can keep its notion of the mouse input data
1030: state in sync with the hardware (i.e., for this type of mouse there is no
1031: way to differentiate the first byte of a packet; if the user is randomly
1032: moving the mouse during boot/initialization, the first mouse interrupt we
1033: receive following IoConnectInterrupt could be for a byte that is not the
1034: start of a packet, and we have no way to know that).
1035:
1036: Arguments:
1037:
1038: DeviceObject - Pointer to the device object.
1039:
1040: Return Value:
1041:
1042: Returns status.
1043:
1044: --*/
1045:
1046: {
1047: NTSTATUS status;
1048: PDEVICE_EXTENSION deviceExtension;
1049: PIO_ERROR_LOG_PACKET errorLogEntry;
1050: ULONG uniqueErrorValue;
1051: NTSTATUS errorCode = STATUS_SUCCESS;
1052: ULONG i;
1053: ULONG dumpCount = 0;
1054:
1055: #define DUMP_COUNT 4
1056: ULONG dumpData[DUMP_COUNT];
1057:
1058: I8xPrint((2, "I8042PRT-I8xMouseEnableTransmission: enter\n"));
1059:
1060: for (i = 0; i < DUMP_COUNT; i++)
1061: dumpData[i] = 0;
1062:
1063: //
1064: // Get the device extension.
1065: //
1066:
1067: deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
1068:
1069: //
1070: // Re-enable the mouse at the mouse hardware, so that it can transmit
1071: // data packets in continuous mode. Note that this is not the same
1072: // as enabling the mouse device at the 8042 controller. The mouse
1073: // hardware is sent an Enable command here, because it was
1074: // Disabled as a result of the mouse reset command performed
1075: // in I8xInitializeMouse().
1076: //
1077: // Note that we don't wait for an ACKNOWLEDGE back. The
1078: // ACKNOWLEDGE back will actually cause a mouse interrupt, which
1079: // then gets handled in the mouse ISR.
1080: //
1081:
1082: status = I8xPutBytePolled(
1083: (CCHAR) DataPort,
1084: NO_WAIT_FOR_ACKNOWLEDGE,
1085: (CCHAR) MouseDeviceType,
1086: deviceExtension,
1087: (UCHAR) ENABLE_MOUSE_TRANSMISSION
1088: );
1089: if (!NT_SUCCESS(status)) {
1090: I8xPrint((
1091: 1,
1092: "I8042PRT-I8xMouseEnableTransmission: failed write enable transmission, status 0x%x\n",
1093: status
1094: ));
1095:
1096: //
1097: // Set up error log info.
1098: //
1099:
1100: errorCode = I8042_MOU_ENABLE_XMIT;
1101: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 475;
1102: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
1103: dumpData[1] = DataPort;
1104: dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
1105: dumpData[3] = ENABLE_MOUSE_TRANSMISSION;
1106: dumpCount = 4;
1107:
1108: }
1109:
1110: I8xPrint((2, "I8042PRT-I8xMouseEnableTransmission: exit\n"));
1111:
1112: return(status);
1113: }
1114:
1115: NTSTATUS
1116: I8xMousePeripheralCallout(
1117: IN PVOID Context,
1118: IN PUNICODE_STRING PathName,
1119: IN INTERFACE_TYPE BusType,
1120: IN ULONG BusNumber,
1121: IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
1122: IN CONFIGURATION_TYPE ControllerType,
1123: IN ULONG ControllerNumber,
1124: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
1125: IN CONFIGURATION_TYPE PeripheralType,
1126: IN ULONG PeripheralNumber,
1127: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
1128: )
1129:
1130: /*++
1131:
1132: Routine Description:
1133:
1134: This is the callout routine sent as a parameter to
1135: IoQueryDeviceDescription. It grabs the pointer controller and
1136: peripheral configuration information.
1137:
1138: Arguments:
1139:
1140: Context - Context parameter that was passed in by the routine
1141: that called IoQueryDeviceDescription.
1142:
1143: PathName - The full pathname for the registry key.
1144:
1145: BusType - Bus interface type (Isa, Eisa, Mca, etc.).
1146:
1147: BusNumber - The bus sub-key (0, 1, etc.).
1148:
1149: BusInformation - Pointer to the array of pointers to the full value
1150: information for the bus.
1151:
1152: ControllerType - The controller type (should be PointerController).
1153:
1154: ControllerNumber - The controller sub-key (0, 1, etc.).
1155:
1156: ControllerInformation - Pointer to the array of pointers to the full
1157: value information for the controller key.
1158:
1159: PeripheralType - The peripheral type (should be PointerPeripheral).
1160:
1161: PeripheralNumber - The peripheral sub-key.
1162:
1163: PeripheralInformation - Pointer to the array of pointers to the full
1164: value information for the peripheral key.
1165:
1166:
1167: Return Value:
1168:
1169: None. If successful, will have the following side-effects:
1170:
1171: - Sets DeviceObject->DeviceExtension->HardwarePresent.
1172: - Sets configuration fields in
1173: DeviceObject->DeviceExtension->Configuration.
1174:
1175: --*/
1176: {
1177: PDEVICE_EXTENSION deviceExtension;
1178: PI8042_CONFIGURATION_INFORMATION configuration;
1179: UNICODE_STRING unicodeIdentifier;
1180: ANSI_STRING ansiString;
1181: PUCHAR controllerData;
1182: NTSTATUS status = STATUS_SUCCESS;
1183: ULONG i;
1184: ULONG listCount;
1185: PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceDescriptor;
1186: CM_PARTIAL_RESOURCE_DESCRIPTOR tmpResourceDescriptor;
1187: BOOLEAN portInfoNeeded;
1188: BOOLEAN defaultInterruptShare;
1189: KINTERRUPT_MODE defaultInterruptMode;
1190:
1191: I8xPrint((
1192: 1,
1193: "I8042PRT-I8xMousePeripheralCallout: Path @ 0x%x, Bus Type 0x%x, Bus Number 0x%x\n",
1194: PathName, BusType, BusNumber
1195: ));
1196: I8xPrint((
1197: 1,
1198: " Controller Type 0x%x, Controller Number 0x%x, Controller info @ 0x%x\n",
1199: ControllerType, ControllerNumber, ControllerInformation
1200: ));
1201: I8xPrint((
1202: 1,
1203: " Peripheral Type 0x%x, Peripheral Number 0x%x, Peripheral info @ 0x%x\n",
1204: PeripheralType, PeripheralNumber, PeripheralInformation
1205: ));
1206:
1207: //
1208: // Get the length of the peripheral identifier information.
1209: //
1210:
1211: unicodeIdentifier.Length =
1212: (*(PeripheralInformation + IoQueryDeviceIdentifier))->DataLength;
1213:
1214: //
1215: // If we already have the configuration information for the
1216: // pointer peripheral, or if the peripheral identifier is missing,
1217: // just return.
1218: //
1219:
1220: deviceExtension = (PDEVICE_EXTENSION) Context;
1221: if ((deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT)
1222: || (unicodeIdentifier.Length == 0)) {
1223: return (status);
1224: }
1225:
1226: configuration = &deviceExtension->Configuration;
1227:
1228: //
1229: // Get the identifier information for the peripheral.
1230: //
1231:
1232: unicodeIdentifier.MaximumLength = unicodeIdentifier.Length;
1233: unicodeIdentifier.Buffer = (PWSTR) (((PUCHAR)(*(PeripheralInformation +
1234: IoQueryDeviceIdentifier))) +
1235: (*(PeripheralInformation +
1236: IoQueryDeviceIdentifier))->DataOffset);
1237: I8xPrint((
1238: 1,
1239: "I8042PRT-I8xMousePeripheralCallout: Mouse type %ws\n",
1240: unicodeIdentifier.Buffer));
1241:
1242: //
1243: // Verify that this is an i8042 mouse.
1244: //
1245:
1246: status = RtlUnicodeStringToAnsiString(
1247: &ansiString,
1248: &unicodeIdentifier,
1249: TRUE
1250: );
1251:
1252: if (!NT_SUCCESS(status)) {
1253: I8xPrint((
1254: 1,
1255: "I8042PRT-I8xMousePeripheralCallout: Could not convert identifier to Ansi\n"
1256: ));
1257: return(status);
1258: }
1259:
1260: if (strstr(ansiString.Buffer, "PS2")) {
1261:
1262: //
1263: // There is a mouse on the i8042 controller.
1264: //
1265:
1266: deviceExtension->HardwarePresent |= MOUSE_HARDWARE_PRESENT;
1267: }
1268:
1269: RtlFreeAnsiString(&ansiString);
1270:
1271: if (!(deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT)) {
1272: return(status);
1273: }
1274:
1275: if (!(deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)) {
1276:
1277: //
1278: // If we don't already have the bus information as the result
1279: // of the keyboard configuration, grab it now.
1280: //
1281:
1282: configuration->InterfaceType = BusType;
1283: configuration->BusNumber = BusNumber;
1284: configuration->FloatingSave = I8042_FLOATING_SAVE;
1285: }
1286:
1287: if (configuration->InterfaceType == MicroChannel) {
1288: defaultInterruptShare = TRUE;
1289: defaultInterruptMode = LevelSensitive;
1290: } else {
1291: defaultInterruptShare = I8042_INTERRUPT_SHARE;
1292: defaultInterruptMode = I8042_INTERRUPT_MODE;
1293: }
1294:
1295: //
1296: // Look through the controller's resource list for interrupt
1297: // and (possibly) port configuration information.
1298: //
1299:
1300: if ((*(ControllerInformation + IoQueryDeviceConfigurationData))->DataLength != 0){
1301: controllerData = ((PUCHAR) (*(ControllerInformation +
1302: IoQueryDeviceConfigurationData))) +
1303: (*(ControllerInformation +
1304: IoQueryDeviceConfigurationData))->DataOffset;
1305:
1306: controllerData += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR,
1307: PartialResourceList);
1308:
1309: listCount = ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->Count;
1310:
1311: resourceDescriptor =
1312: ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->PartialDescriptors;
1313:
1314: portInfoNeeded = configuration->PortListCount? FALSE:TRUE;
1315:
1316: for (i = 0; i < listCount; i++, resourceDescriptor++) {
1317: switch(resourceDescriptor->Type) {
1318: case CmResourceTypePort:
1319:
1320: if (portInfoNeeded) {
1321:
1322: //
1323: // If we don't already have the port information as
1324: // a result of the keyboard configuration, copy it
1325: // to the port list.
1326: //
1327:
1328: configuration->PortList[configuration->PortListCount] =
1329: *resourceDescriptor;
1330: configuration->PortList[configuration->PortListCount].ShareDisposition =
1331: I8042_REGISTER_SHARE? CmResourceShareShared:
1332: CmResourceShareDriverExclusive;
1333: configuration->PortListCount += 1;
1334:
1335: }
1336:
1337: break;
1338:
1339: case CmResourceTypeInterrupt:
1340:
1341: //
1342: // Copy the interrupt information.
1343: //
1344:
1345: configuration->MouseInterrupt = *resourceDescriptor;
1346: configuration->MouseInterrupt.ShareDisposition =
1347: defaultInterruptShare? CmResourceShareShared :
1348: CmResourceShareDeviceExclusive;
1349:
1350: break;
1351:
1352: default:
1353: break;
1354: }
1355: }
1356: }
1357:
1358: //
1359: // If no interrupt configuration information was found, use the
1360: // mouse driver defaults.
1361: //
1362:
1363: if (!(configuration->MouseInterrupt.Type & CmResourceTypeInterrupt)) {
1364:
1365: I8xPrint((
1366: 1,
1367: "I8042PRT-I8xMousePeripheralCallout: Using default mouse interrupt config\n"
1368: ));
1369:
1370: configuration->MouseInterrupt.Type = CmResourceTypeInterrupt;
1371: configuration->MouseInterrupt.ShareDisposition =
1372: defaultInterruptShare? CmResourceShareShared :
1373: CmResourceShareDeviceExclusive;
1374: configuration->MouseInterrupt.Flags =
1375: (defaultInterruptMode == Latched)? CM_RESOURCE_INTERRUPT_LATCHED :
1376: CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1377: configuration->MouseInterrupt.u.Interrupt.Level = MOUSE_IRQL;
1378: configuration->MouseInterrupt.u.Interrupt.Vector = MOUSE_VECTOR;
1379: }
1380:
1381: I8xPrint((
1382: 1,
1383: "I8042PRT-I8xMousePeripheralCallout: Mouse interrupt config --\n"
1384: ));
1385: I8xPrint((
1386: 1,
1387: "%s, %s, Irq = %d\n",
1388: configuration->MouseInterrupt.ShareDisposition == CmResourceShareShared?
1389: "Sharable" : "NonSharable",
1390: configuration->MouseInterrupt.Flags == CM_RESOURCE_INTERRUPT_LATCHED?
1391: "Latched" : "Level Sensitive",
1392: configuration->MouseInterrupt.u.Interrupt.Vector
1393: ));
1394:
1395: //
1396: // If no port configuration information was found, use the
1397: // mouse driver defaults.
1398: //
1399:
1400: if (configuration->PortListCount == 0) {
1401:
1402: //
1403: // No port configuration information was found, so use
1404: // the driver defaults.
1405: //
1406:
1407: I8xPrint((
1408: 1,
1409: "I8042PRT-I8xMousePeripheralCallout: Using default port config\n"
1410: ));
1411:
1412: configuration->PortList[DataPort].Type = CmResourceTypePort;
1413: configuration->PortList[DataPort].Flags = I8042_PORT_TYPE;
1414: configuration->PortList[DataPort].ShareDisposition =
1415: I8042_REGISTER_SHARE? CmResourceShareShared:
1416: CmResourceShareDriverExclusive;
1417: configuration->PortList[DataPort].u.Port.Start.LowPart =
1418: I8042_PHYSICAL_BASE + I8042_DATA_REGISTER_OFFSET;
1419: configuration->PortList[DataPort].u.Port.Start.HighPart = 0;
1420: configuration->PortList[DataPort].u.Port.Length = I8042_REGISTER_LENGTH;
1421:
1422: configuration->PortList[CommandPort].Type = CmResourceTypePort;
1423: configuration->PortList[CommandPort].Flags = I8042_PORT_TYPE;
1424: configuration->PortList[CommandPort].ShareDisposition =
1425: I8042_REGISTER_SHARE? CmResourceShareShared:
1426: CmResourceShareDriverExclusive;
1427: configuration->PortList[CommandPort].u.Port.Start.LowPart =
1428: I8042_PHYSICAL_BASE + I8042_COMMAND_REGISTER_OFFSET;
1429: configuration->PortList[CommandPort].u.Port.Start.HighPart = 0;
1430: configuration->PortList[CommandPort].u.Port.Length = I8042_REGISTER_LENGTH;
1431:
1432: configuration->PortListCount = 2;
1433: } else if (configuration->PortListCount == 1) {
1434:
1435: //
1436: // Kludge for Jazz machines. Their ARC firmware neglects to
1437: // separate out the port addresses, so fix that up here.
1438: //
1439:
1440: configuration->PortList[CommandPort] = configuration->PortList[DataPort];
1441: configuration->PortList[CommandPort].u.Port.Start.LowPart +=
1442: I8042_COMMAND_REGISTER_OFFSET;
1443: configuration->PortListCount += 1;
1444: } else {
1445:
1446: //
1447: // Put the lowest port address range in the DataPort element of
1448: // the port list.
1449: //
1450:
1451: if (configuration->PortList[CommandPort].u.Port.Start.LowPart
1452: < configuration->PortList[DataPort].u.Port.Start.LowPart) {
1453: tmpResourceDescriptor = configuration->PortList[DataPort];
1454: configuration->PortList[DataPort] =
1455: configuration->PortList[CommandPort];
1456: configuration->PortList[CommandPort] = tmpResourceDescriptor;
1457: }
1458: }
1459:
1460: for (i = 0; i < configuration->PortListCount; i++) {
1461:
1462: I8xPrint((
1463: 1,
1464: " %s, Ports 0x%x - 0x%x\n",
1465: configuration->PortList[i].ShareDisposition
1466: == CmResourceShareShared? "Sharable" : "NonSharable",
1467: configuration->PortList[i].u.Port.Start.LowPart,
1468: configuration->PortList[i].u.Port.Start.LowPart +
1469: configuration->PortList[i].u.Port.Length - 1
1470: ));
1471: }
1472:
1473: return(status);
1474: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.