|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 Microsoft Corporation
4: Copyright (c) 1993 Logitech Inc.
5:
6: Module Name:
7:
8: uart.c
9:
10: Abstract:
11:
12: Environment:
13:
14: Kernel mode only.
15:
16: Notes:
17:
18: Revision History:
19:
20: --*/
21:
22: #include "ntddk.h"
23: #include "uart.h"
24: #include "sermouse.h"
25: #include "debug.h"
26:
27: #ifdef ALLOC_PRAGMA
28: #pragma alloc_text(init,UARTSetFifo)
29: #pragma alloc_text(init,UARTGetInterruptCtrl)
30: #pragma alloc_text(init,UARTSetInterruptCtrl)
31: #pragma alloc_text(init,UARTGetLineCtrl)
32: #pragma alloc_text(init,UARTSetLineCtrl)
33: #pragma alloc_text(init,UARTGetModemCtrl)
34: #pragma alloc_text(init,UARTSetModemCtrl)
35: #pragma alloc_text(init,UARTSetDlab)
36: #pragma alloc_text(init,UARTGetBaudRate)
37: #pragma alloc_text(init,UARTSetBaudRate)
38: #pragma alloc_text(init,UARTGetState)
39: #pragma alloc_text(init,UARTSetState)
40: #pragma alloc_text(init,UARTReadChar)
41: #pragma alloc_text(init,UARTIsTransmitEmpty)
42: #pragma alloc_text(init,UARTWriteChar)
43: #pragma alloc_text(init,UARTWriteString)
44: #endif // ALLOC_PRAGMA
45:
46: //
47: // Constants
48: //
49:
50:
51: VOID
52: UARTSetFifo(
53: PUCHAR Port,
54: UCHAR Value
55: )
56: /*++
57:
58: Routine Description:
59:
60: Set the FIFO register.
61:
62: Arguments:
63:
64: Port - Pointer to the serial port.
65:
66: Value - The FIFO control mask.
67:
68: Return Value:
69:
70: None.
71:
72: --*/
73: {
74: WRITE_PORT_UCHAR(Port + ACE_IIDR, Value);
75: }
76: UCHAR
77: UARTGetInterruptCtrl(
78: PUCHAR Port
79: )
80: /*++
81:
82: Routine Description:
83:
84: Get the serial port interrupt control register.
85:
86: Arguments:
87:
88: Port - Pointer to the serial port.
89:
90: Return Value:
91:
92: Serial port interrupt control register value.
93:
94: --*/
95: {
96: return READ_PORT_UCHAR(Port + ACE_IER);
97: }
98:
99: UCHAR
100: UARTSetInterruptCtrl(
101: PUCHAR Port,
102: UCHAR Value
103: )
104: /*++
105:
106: Routine Description:
107:
108: Set the interrupt control register.
109:
110: Arguments:
111:
112: Port - Pointer to the serial port.
113:
114: Value - The interrupt control mask.
115:
116: Return Value:
117:
118: Previous interrupt control value.
119:
120: --*/
121: {
122: UCHAR oldValue = UARTGetInterruptCtrl(Port);
123: WRITE_PORT_UCHAR(Port + ACE_IER, Value);
124:
125: return oldValue;
126: }
127:
128:
129: UCHAR
130: UARTGetLineCtrl(
131: PUCHAR Port
132: )
133: /*++
134:
135: Routine Description:
136:
137: Get the serial port line control register.
138:
139: Arguments:
140:
141: Port - Pointer to the serial port.
142:
143: Return Value:
144:
145: Serial port line control value.
146:
147: --*/
148: {
149: return READ_PORT_UCHAR(Port + ACE_LCR);
150: }
151:
152: UCHAR
153: UARTSetLineCtrl(
154: PUCHAR Port,
155: UCHAR Value
156: )
157: /*++
158:
159: Routine Description:
160:
161: Set the serial port line control register.
162:
163: Arguments:
164:
165: Port - Pointer to the serial port.
166:
167: Value - New line control value.
168:
169: Return Value:
170:
171: Previous serial line control register value.
172:
173: --*/
174: {
175: UCHAR oldValue = UARTGetLineCtrl(Port);
176: WRITE_PORT_UCHAR(Port + ACE_LCR, Value);
177:
178: return oldValue;
179: }
180:
181:
182: UCHAR
183: UARTGetModemCtrl(
184: PUCHAR Port
185: )
186: /*++
187:
188: Routine Description:
189:
190: Get the serial port modem control register.
191:
192: Arguments:
193:
194: Port - Pointer to the serial port.
195:
196: Return Value:
197:
198: Serial port modem control register value.
199:
200: --*/
201: {
202: return READ_PORT_UCHAR(Port + ACE_MCR);
203: }
204:
205: UCHAR
206: UARTSetModemCtrl(
207: PUCHAR Port,
208: UCHAR Value
209: )
210: /*++
211:
212: Routine Description:
213:
214: Set the serial port modem control register.
215:
216: Arguments:
217:
218: Port - Pointer to the serial port.
219:
220: Return Value:
221:
222: Previous modem control register value.
223:
224: --*/
225: {
226:
227: UCHAR oldValue = UARTGetModemCtrl(Port);
228: WRITE_PORT_UCHAR(Port + ACE_MCR, Value);
229:
230: return oldValue;
231: }
232:
233:
234: BOOLEAN
235: UARTSetDlab(
236: PUCHAR Port,
237: BOOLEAN Set
238: )
239: /*++
240:
241: Routine Description:
242:
243: Set/reset the baud rate access bit.
244:
245: Arguments:
246:
247: Port - Pointer to the serial port.
248:
249: Set - Set or Reset (TRUE/FALSE) the baud rate access bit.
250:
251: Return Value:
252:
253: The previous baud rate access bit setting.
254:
255: --*/
256: {
257: UCHAR lineControl = UARTGetLineCtrl(Port);
258: UCHAR newLineControl = Set ? lineControl | ACE_DLAB :
259: lineControl & ~ACE_DLAB;
260:
261: WRITE_PORT_UCHAR(Port + ACE_LCR, newLineControl);
262:
263: return lineControl & ACE_DLAB;
264: }
265:
266: ULONG
267: UARTGetBaudRate(
268: PUCHAR Port,
269: ULONG BaudClock
270: )
271: /*++
272:
273: Routine Description:
274:
275: Get the serial port baud rate setting.
276:
277: Arguments:
278:
279: Port - Pointer to the serial port.
280:
281: BaudClock - The external frequency driving the serial chip.
282:
283: Return Value:
284:
285: Serial port baud rate.
286:
287: --*/
288: {
289: USHORT baudRateDivisor;
290: ULONG baudRateFactor = BaudClock/BAUD_GENERATOR_DIVISOR;
291:
292: //
293: // Set the baud rate access bit.
294: //
295:
296: UARTSetDlab(Port, TRUE);
297:
298: //
299: // Read the baud rate factor.
300: //
301:
302: baudRateDivisor = READ_PORT_UCHAR(Port + ACE_DLL);
303: baudRateDivisor |= READ_PORT_UCHAR(Port + ACE_DLM) << 8;
304:
305: //
306: // Reset the baud rate bit for normal data access.
307: //
308:
309: UARTSetDlab(Port, FALSE);
310:
311: //
312: // Make sure the divisor is not zero.
313: //
314:
315: if (baudRateDivisor == 0) {
316: baudRateDivisor = 1;
317: }
318:
319: return baudRateFactor / baudRateDivisor;
320: }
321:
322: VOID
323: UARTSetBaudRate(
324: PUCHAR Port,
325: ULONG BaudRate,
326: ULONG BaudClock
327: )
328: /*++
329:
330: Routine Description:
331:
332: Set the serial port baud rate.
333:
334: Arguments:
335:
336: Port - Pointer to the serial port.
337:
338: BaudRate - New serial port baud rate.
339:
340: BaudClock - The external frequency driving the serial chip.
341:
342: Return Value:
343:
344: None.
345:
346: --*/
347: {
348:
349: ULONG baudRateFactor = BaudClock/BAUD_GENERATOR_DIVISOR;
350: USHORT baudRateDivisor;
351:
352: SerMouPrint((2, "SERMOUSE-SetBaudRate: Enter\n"));
353:
354: baudRateDivisor = baudRateFactor / BaudRate;
355: UARTSetDlab(Port, TRUE);
356: WRITE_PORT_UCHAR(Port + ACE_DLL, (UCHAR)baudRateDivisor);
357: WRITE_PORT_UCHAR(Port + ACE_DLM, (UCHAR)(baudRateDivisor >> 8));
358: UARTSetDlab(Port, FALSE);
359: SerMouPrint((2, "SERMOUSE-New BaudRate: %u\n", BaudRate));
360:
361: SerMouPrint((2, "SERMOUSE-SetBaudRate: Exit\n"));
362:
363: return;
364: }
365:
366:
367: VOID
368: UARTGetState(
369: PUCHAR Port,
370: PUART Uart,
371: ULONG BaudClock
372: )
373: /*++
374:
375: Routine Description:
376:
377: Get the complete state of the serial port. May be used for save/restore.
378:
379: Arguments:
380:
381: Port - Pointer to the serial port.
382:
383: Uart - Pointer to a serial port structure.
384:
385: BaudClock - The external frequency driving the serial chip.
386:
387: Return Value:
388:
389: None.
390:
391: --*/
392: {
393: Uart->LineCtrl = UARTGetLineCtrl(Port);
394: Uart->ModemCtrl = UARTGetModemCtrl(Port);
395: Uart->InterruptCtrl = UARTGetInterruptCtrl(Port);
396: Uart->BaudRate = UARTGetBaudRate(Port, BaudClock);
397:
398: return;
399: }
400:
401: VOID
402: UARTSetState(
403: PUCHAR Port,
404: PUART Uart,
405: ULONG BaudClock
406: )
407: /*++
408:
409: Routine Description:
410:
411: Set the complete state of a serial port.
412:
413: Arguments:
414:
415: Port - Pointer to the serial port.
416:
417: Uart - Pointer to a serial port structure.
418:
419: BaudClock - The external frequency driving the serial chip.
420:
421: Return Value:
422:
423: None.
424:
425: --*/
426: {
427: UARTSetLineCtrl(Port, Uart->LineCtrl);
428: UARTSetModemCtrl(Port, Uart->ModemCtrl);
429: UARTSetInterruptCtrl(Port, Uart->InterruptCtrl);
430: UARTSetBaudRate(Port, Uart->BaudRate, BaudClock);
431:
432: return;
433: }
434:
435:
436: BOOLEAN
437: UARTIsReceiveBufferFull(
438: PUCHAR Port
439: )
440: /*++
441:
442: Routine Description:
443:
444: Check whether the serial port input buffer is full.
445:
446: Arguments:
447:
448: Port - Pointer to the serial port.
449:
450: Return Value:
451:
452: TRUE if a character is present in the input buffer, otherwise FALSE.
453:
454: --*/
455: {
456: return READ_PORT_UCHAR(Port + ACE_LSR) & ACE_DR;
457: }
458:
459:
460: BOOLEAN
461: UARTReadCharNoWait(
462: PUCHAR Port,
463: PUCHAR Value
464: )
465: /*++
466:
467: Routine Description:
468:
469: Read a character from the serial port and return immediately.
470:
471: Arguments:
472:
473: Port - Pointer to the serial port.
474:
475: Value - The character read from the serial port input buffer.
476:
477: Return Value:
478:
479: TRUE if character has been read, FALSE otherwise.
480:
481: --*/
482: {
483: BOOLEAN charReady = FALSE;
484:
485: if ( UARTIsReceiveBufferFull(Port) ) {
486: *Value = READ_PORT_UCHAR(Port + ACE_RBR);
487: charReady = TRUE;
488: }
489:
490: return charReady;
491: }
492:
493: BOOLEAN
494: UARTReadChar(
495: PUCHAR Port,
496: PUCHAR Value,
497: ULONG Timeout
498: )
499: /*++
500:
501: Routine Description:
502:
503: Read a character from the serial port. Waits until a character has
504: been read or the timeout value is reached.
505:
506: Arguments:
507:
508: Port - Pointer to the serial port.
509:
510: Value - The character read from the serial port input buffer.
511:
512: Timeout - The timeout value in milliseconds for the read.
513:
514: Return Value:
515:
516: TRUE if a character has been read, FALSE if a timeout occured.
517:
518: --*/
519: {
520:
521: ULONG i, j;
522: BOOLEAN returnValue = FALSE;
523:
524:
525: //
526: // Exit when a character is found or the timeout value is reached.
527: //
528:
529: for (i = 0; i < Timeout; i++) {
530: for (j = 0; j < MS_TO_MICROSECONDS; j++) {
531: if ((returnValue = UARTReadCharNoWait(Port, Value)) == TRUE) {
532:
533: //
534: // Got a character.
535: //
536:
537: break;
538: } else {
539:
540: //
541: // Stall 1 microsecond and then try to read again.
542: //
543:
544: KeStallExecutionProcessor(1);
545: }
546: }
547: if (returnValue) {
548: break;
549: }
550: }
551:
552: return(returnValue);
553: }
554:
555: BOOLEAN
556: UARTFlushReadBuffer(
557: PUCHAR Port
558: )
559: /*++
560:
561: Routine Description:
562:
563: Flush the serial port input buffer.
564:
565: Arguments:
566:
567: Port - Pointer to the serial port.
568:
569: Return Value:
570:
571: TRUE.
572:
573: --*/
574: {
575: UCHAR value;
576:
577: SerMouPrint((4, "SERMOUSE-UARTFlushReadBuffer: Enter\n"));
578: while (UARTReadCharNoWait(Port, &value)) {
579: /* Nothing */
580: }
581: SerMouPrint((4, "SERMOUSE-UARTFlushReadBuffer: Exit\n"));
582:
583: return TRUE;
584: }
585:
586:
587: BOOLEAN
588: UARTIsTransmitEmpty(
589: PUCHAR Port
590: )
591: /*++
592:
593: Routine Description:
594:
595: Check whether the serial port transmit buffer is empty.
596:
597: Note: We also check whether the shift register is empty. This is
598: not critical in our case, but allows some more delay between characters
599: sent to a device. (Safe, safe...)
600:
601: Arguments:
602:
603: Port - Pointer to the serial port.
604:
605: Return Value:
606:
607: TRUE if the serial port transmit buffer is empty.
608:
609: --*/
610: {
611: return ((READ_PORT_UCHAR((PUCHAR) (Port + ACE_LSR)) &
612: (ACE_TSRE | ACE_THRE)) == (ACE_THRE | ACE_TSRE));
613: }
614:
615:
616: BOOLEAN
617: UARTWriteChar(
618: PUCHAR Port,
619: UCHAR Value
620: )
621: /*++
622:
623: Routine Description:
624:
625: Write a character to a serial port. Make sure the transmit buffer
626: is empty before we write there.
627:
628: Arguments:
629:
630: Port - Pointer to the serial port.
631:
632: Value - Value to write to the serial port.
633:
634: Return Value:
635:
636: TRUE.
637:
638: --*/
639: {
640: while (!UARTIsTransmitEmpty(Port)) {
641: /* Nothing */
642: }
643: WRITE_PORT_UCHAR(Port + ACE_THR, Value);
644:
645: return TRUE;
646: }
647:
648: BOOLEAN
649: UARTWriteString(
650: PUCHAR Port,
651: PSZ Buffer
652: )
653: /*++
654:
655: Routine Description:
656:
657: Write a zero-terminated string to the serial port.
658:
659: Arguments:
660:
661: Port - Pointer to the serial port.
662:
663: Buffer - Pointer to a zero terminated string to write to
664: the serial port.
665:
666: Return Value:
667:
668: TRUE.
669:
670: --*/
671: {
672: PSZ current = Buffer;
673:
674: while (*current) {
675: UARTWriteChar(Port, *current++);
676: }
677:
678: return TRUE;
679: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.