]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/Serial.c
Updated to use new PCD settings
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaSerialDxe / Serial.c
1 /**@file
2 Serial driver for standard UARTS on an ISA bus.
3
4 Copyright (c) 2006 - 2007, Intel Corporation<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Serial.h"
16
17 //
18 // ISA Serial Driver Global Variables
19 //
20 EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver = {
21 SerialControllerDriverSupported,
22 SerialControllerDriverStart,
23 SerialControllerDriverStop,
24 0xa,
25 NULL,
26 NULL
27 };
28
29
30 SERIAL_DEV gSerialDevTempate = {
31 SERIAL_DEV_SIGNATURE,
32 NULL,
33 { // SerialIo
34 SERIAL_IO_INTERFACE_REVISION,
35 IsaSerialReset,
36 IsaSerialSetAttributes,
37 IsaSerialSetControl,
38 IsaSerialGetControl,
39 IsaSerialWrite,
40 IsaSerialRead,
41 NULL
42 },
43 { // SerialMode
44 SERIAL_PORT_DEFAULT_CONTROL_MASK,
45 SERIAL_PORT_DEFAULT_TIMEOUT,
46 FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
47 SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH,
48 FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits
49 FixedPcdGet8 (PcdUartDefaultParity), // Parity
50 FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits
51 },
52 NULL,
53 NULL,
54 { // UartDevicePath
55 {
56 MESSAGING_DEVICE_PATH,
57 MSG_UART_DP,
58 (UINT8) (sizeof (UART_DEVICE_PATH)),
59 (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8),
60 },
61 0,
62 FixedPcdGet64 (PcdUartDefaultBaudRate),
63 FixedPcdGet8 (PcdUartDefaultDataBits),
64 FixedPcdGet8 (PcdUartDefaultParity),
65 FixedPcdGet8 (PcdUartDefaultStopBits)
66 },
67 NULL,
68 0, //BaseAddress
69 {
70 0,
71 0,
72 SERIAL_MAX_BUFFER_SIZE,
73 { 0 }
74 },
75 {
76 0,
77 0,
78 SERIAL_MAX_BUFFER_SIZE,
79 { 0 }
80 },
81 FALSE,
82 FALSE,
83 UART16550A,
84 NULL
85 };
86
87 /**
88 The user Entry Point for module IsaSerial. The user code starts with this function.
89
90 @param[in] ImageHandle The firmware allocated handle for the EFI image.
91 @param[in] SystemTable A pointer to the EFI System Table.
92
93 @retval EFI_SUCCESS The entry point is executed successfully.
94 @retval other Some error occurs when executing this entry point.
95
96 **/
97 EFI_STATUS
98 EFIAPI
99 InitializeIsaSerial (
100 IN EFI_HANDLE ImageHandle,
101 IN EFI_SYSTEM_TABLE *SystemTable
102 )
103 {
104 EFI_STATUS Status;
105
106 //
107 // Install driver model protocol(s).
108 //
109 Status = EfiLibInstallAllDriverProtocols (
110 ImageHandle,
111 SystemTable,
112 &gSerialControllerDriver,
113 ImageHandle,
114 &gIsaSerialComponentName,
115 NULL,
116 NULL
117 );
118 ASSERT_EFI_ERROR (Status);
119
120
121 return Status;
122 }
123
124
125 EFI_STATUS
126 EFIAPI
127 SerialControllerDriverSupported (
128 IN EFI_DRIVER_BINDING_PROTOCOL *This,
129 IN EFI_HANDLE Controller,
130 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
131 )
132 /*++
133
134 Routine Description:
135
136 Check to see if this driver supports the given controller
137
138 Arguments:
139
140 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
141 Controller - The handle of the controller to test.
142 RemainingDevicePath - A pointer to the remaining portion of a device path.
143
144 Returns:
145
146 EFI_SUCCESS - This driver can support the given controller
147
148 --*/
149 {
150 EFI_STATUS Status;
151 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
152 EFI_ISA_IO_PROTOCOL *IsaIo;
153 UART_DEVICE_PATH UartNode;
154
155 //
156 // Ignore the RemainingDevicePath
157 //
158 //
159 // Open the IO Abstraction(s) needed to perform the supported test
160 //
161 Status = gBS->OpenProtocol (
162 Controller,
163 &gEfiDevicePathProtocolGuid,
164 (VOID **) &ParentDevicePath,
165 This->DriverBindingHandle,
166 Controller,
167 EFI_OPEN_PROTOCOL_BY_DRIVER
168 );
169 if (Status == EFI_ALREADY_STARTED) {
170 return EFI_SUCCESS;
171 }
172
173 if (EFI_ERROR (Status)) {
174 return Status;
175 }
176
177 gBS->CloseProtocol (
178 Controller,
179 &gEfiDevicePathProtocolGuid,
180 This->DriverBindingHandle,
181 Controller
182 );
183
184 Status = gBS->OpenProtocol (
185 Controller,
186 &gEfiIsaIoProtocolGuid,
187 (VOID **) &IsaIo,
188 This->DriverBindingHandle,
189 Controller,
190 EFI_OPEN_PROTOCOL_BY_DRIVER
191 );
192
193 if (Status == EFI_ALREADY_STARTED) {
194 return EFI_SUCCESS;
195 }
196
197 if (EFI_ERROR (Status)) {
198 return Status;
199 }
200 //
201 // Use the ISA I/O Protocol to see if Controller is standard ISA UART that
202 // can be managed by this driver.
203 //
204 Status = EFI_SUCCESS;
205 if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x501)) {
206 Status = EFI_UNSUPPORTED;
207 goto Error;
208 }
209 //
210 // Make sure RemainingDevicePath is valid
211 //
212 if (RemainingDevicePath != NULL) {
213 Status = EFI_UNSUPPORTED;
214 CopyMem (
215 &UartNode,
216 (UART_DEVICE_PATH *) RemainingDevicePath,
217 sizeof (UART_DEVICE_PATH)
218 );
219 if (UartNode.Header.Type != MESSAGING_DEVICE_PATH ||
220 UartNode.Header.SubType != MSG_UART_DP ||
221 sizeof (UART_DEVICE_PATH) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &UartNode)
222 ) {
223 goto Error;
224 }
225
226 if (UartNode.BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {
227 goto Error;
228 }
229
230 if (UartNode.Parity < NoParity || UartNode.Parity > SpaceParity) {
231 goto Error;
232 }
233
234 if (UartNode.DataBits < 5 || UartNode.DataBits > 8) {
235 goto Error;
236 }
237
238 if (UartNode.StopBits < OneStopBit || UartNode.StopBits > TwoStopBits) {
239 goto Error;
240 }
241
242 if ((UartNode.DataBits == 5) && (UartNode.StopBits == TwoStopBits)) {
243 goto Error;
244 }
245
246 if ((UartNode.DataBits >= 6) && (UartNode.DataBits <= 8) && (UartNode.StopBits == OneFiveStopBits)) {
247 goto Error;
248 }
249
250 Status = EFI_SUCCESS;
251 }
252
253 Error:
254 //
255 // Close the I/O Abstraction(s) used to perform the supported test
256 //
257 gBS->CloseProtocol (
258 Controller,
259 &gEfiIsaIoProtocolGuid,
260 This->DriverBindingHandle,
261 Controller
262 );
263
264 return Status;
265 }
266
267 EFI_STATUS
268 EFIAPI
269 SerialControllerDriverStart (
270 IN EFI_DRIVER_BINDING_PROTOCOL *This,
271 IN EFI_HANDLE Controller,
272 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
273 )
274 /*++
275
276 Routine Description:
277
278 Start to management the controller passed in
279
280 Arguments:
281
282 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
283 Controller - The handle of the controller to test.
284 RemainingDevicePath - A pointer to the remaining portion of a device path.
285
286 Returns:
287
288 EFI_SUCCESS - Driver is started successfully
289
290 --*/
291 {
292 EFI_STATUS Status;
293 EFI_ISA_IO_PROTOCOL *IsaIo;
294 SERIAL_DEV *SerialDevice;
295 UINTN Index;
296 UART_DEVICE_PATH Node;
297 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
298 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
299 UINTN EntryCount;
300 EFI_SERIAL_IO_PROTOCOL *SerialIo;
301
302 SerialDevice = NULL;
303 //
304 // Get the Parent Device Path
305 //
306 Status = gBS->OpenProtocol (
307 Controller,
308 &gEfiDevicePathProtocolGuid,
309 (VOID **) &ParentDevicePath,
310 This->DriverBindingHandle,
311 Controller,
312 EFI_OPEN_PROTOCOL_BY_DRIVER
313 );
314 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
315 return Status;
316 }
317 //
318 // Report status code enable the serial
319 //
320 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
321 EFI_PROGRESS_CODE,
322 EFI_P_PC_ENABLE | EFI_PERIPHERAL_SERIAL_PORT,
323 ParentDevicePath
324 );
325
326 //
327 // Grab the IO abstraction we need to get any work done
328 //
329 Status = gBS->OpenProtocol (
330 Controller,
331 &gEfiIsaIoProtocolGuid,
332 (VOID **) &IsaIo,
333 This->DriverBindingHandle,
334 Controller,
335 EFI_OPEN_PROTOCOL_BY_DRIVER
336 );
337 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
338 goto Error;
339 }
340
341 if (Status == EFI_ALREADY_STARTED) {
342
343 if (RemainingDevicePath == NULL) {
344 return EFI_SUCCESS;
345 }
346 //
347 // Make sure a child handle does not already exist. This driver can only
348 // produce one child per serial port.
349 //
350 Status = gBS->OpenProtocolInformation (
351 Controller,
352 &gEfiIsaIoProtocolGuid,
353 &OpenInfoBuffer,
354 &EntryCount
355 );
356 if (EFI_ERROR (Status)) {
357 return Status;
358 }
359
360 Status = EFI_ALREADY_STARTED;
361 for (Index = 0; Index < EntryCount; Index++) {
362 if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
363 Status = gBS->OpenProtocol (
364 OpenInfoBuffer[Index].ControllerHandle,
365 &gEfiSerialIoProtocolGuid,
366 (VOID **) &SerialIo,
367 This->DriverBindingHandle,
368 Controller,
369 EFI_OPEN_PROTOCOL_GET_PROTOCOL
370 );
371 if (!EFI_ERROR (Status)) {
372 CopyMem (&Node, RemainingDevicePath, sizeof (UART_DEVICE_PATH));
373 Status = SerialIo->SetAttributes (
374 SerialIo,
375 Node.BaudRate,
376 SerialIo->Mode->ReceiveFifoDepth,
377 SerialIo->Mode->Timeout,
378 (EFI_PARITY_TYPE) Node.Parity,
379 Node.DataBits,
380 (EFI_STOP_BITS_TYPE) Node.StopBits
381 );
382 }
383 break;
384 }
385 }
386
387 gBS->FreePool (OpenInfoBuffer);
388 return Status;
389 }
390 //
391 // Initialize the serial device instance
392 //
393 SerialDevice = AllocateCopyPool (sizeof (SERIAL_DEV), &gSerialDevTempate);
394 if (SerialDevice == NULL) {
395 Status = EFI_OUT_OF_RESOURCES;
396 goto Error;
397 }
398
399 SerialDevice->SerialIo.Mode = &(SerialDevice->SerialMode);
400 SerialDevice->IsaIo = IsaIo;
401 SerialDevice->ParentDevicePath = ParentDevicePath;
402
403 ADD_SERIAL_NAME (SerialDevice, IsaIo);
404
405 for (Index = 0; SerialDevice->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) {
406 if (SerialDevice->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) {
407 SerialDevice->BaseAddress = (UINT16) SerialDevice->IsaIo->ResourceList->ResourceItem[Index].StartRange;
408 }
409 }
410 //
411 // Report status code the serial present
412 //
413 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
414 EFI_PROGRESS_CODE,
415 EFI_P_PC_PRESENCE_DETECT | EFI_PERIPHERAL_SERIAL_PORT,
416 ParentDevicePath
417 );
418
419 if (!IsaSerialPortPresent (SerialDevice)) {
420 Status = EFI_DEVICE_ERROR;
421 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
422 EFI_ERROR_CODE,
423 EFI_P_EC_NOT_DETECTED | EFI_PERIPHERAL_SERIAL_PORT,
424 ParentDevicePath
425 );
426 goto Error;
427 }
428
429 if (RemainingDevicePath != NULL) {
430 //
431 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
432 // already checked to make sure the RemainingDevicePath contains settings
433 // that we can support.
434 //
435 CopyMem (&SerialDevice->UartDevicePath, RemainingDevicePath, sizeof (UART_DEVICE_PATH));
436 } else {
437 //
438 // Use the values from the gSerialDevTempate as no remaining device path was
439 // passed in.
440 //
441 }
442 //
443 // Build the device path by appending the UART node to the ParentDevicePath
444 // from the WinNtIo handle. The Uart setings are zero here, since
445 // SetAttribute() will update them to match the current setings.
446 //
447 SerialDevice->DevicePath = AppendDevicePathNode (
448 ParentDevicePath,
449 (EFI_DEVICE_PATH_PROTOCOL *)&SerialDevice->UartDevicePath
450 );
451 if (SerialDevice->DevicePath == NULL) {
452 Status = EFI_DEVICE_ERROR;
453 goto Error;
454 }
455
456 //
457 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
458 //
459 SerialDevice->SerialMode.BaudRate = SerialDevice->UartDevicePath.BaudRate;
460 SerialDevice->SerialMode.DataBits = SerialDevice->UartDevicePath.DataBits;
461 SerialDevice->SerialMode.Parity = SerialDevice->UartDevicePath.Parity;
462 SerialDevice->SerialMode.StopBits = SerialDevice->UartDevicePath.StopBits;
463
464 //
465 // Issue a reset to initialize the COM port
466 //
467 Status = SerialDevice->SerialIo.Reset (&SerialDevice->SerialIo);
468 if (EFI_ERROR (Status)) {
469 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
470 EFI_ERROR_CODE,
471 EFI_P_EC_CONTROLLER_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
472 ParentDevicePath
473 );
474 goto Error;
475 }
476 //
477 // Install protocol interfaces for the serial device.
478 //
479 Status = gBS->InstallMultipleProtocolInterfaces (
480 &SerialDevice->Handle,
481 &gEfiDevicePathProtocolGuid,
482 SerialDevice->DevicePath,
483 &gEfiSerialIoProtocolGuid,
484 &SerialDevice->SerialIo,
485 NULL
486 );
487 if (EFI_ERROR (Status)) {
488 goto Error;
489 }
490 //
491 // Open For Child Device
492 //
493 Status = gBS->OpenProtocol (
494 Controller,
495 &gEfiIsaIoProtocolGuid,
496 (VOID **) &IsaIo,
497 This->DriverBindingHandle,
498 SerialDevice->Handle,
499 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
500 );
501
502 Error:
503 if (EFI_ERROR (Status)) {
504 gBS->CloseProtocol (
505 Controller,
506 &gEfiDevicePathProtocolGuid,
507 This->DriverBindingHandle,
508 Controller
509 );
510 gBS->CloseProtocol (
511 Controller,
512 &gEfiIsaIoProtocolGuid,
513 This->DriverBindingHandle,
514 Controller
515 );
516 if (SerialDevice) {
517 if (SerialDevice->DevicePath) {
518 gBS->FreePool (SerialDevice->DevicePath);
519 }
520
521 FreeUnicodeStringTable (SerialDevice->ControllerNameTable);
522 gBS->FreePool (SerialDevice);
523 }
524 }
525
526 return Status;
527 }
528
529 EFI_STATUS
530 EFIAPI
531 SerialControllerDriverStop (
532 IN EFI_DRIVER_BINDING_PROTOCOL *This,
533 IN EFI_HANDLE Controller,
534 IN UINTN NumberOfChildren,
535 IN EFI_HANDLE *ChildHandleBuffer
536 )
537 /*++
538
539 Routine Description:
540
541 Disconnect this driver with the controller, uninstall related protocol instance
542
543 Arguments:
544
545 This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
546 Controller - The handle of the controller to test.
547 NumberOfChildren - Number of child device.
548 RemainingDevicePath - A pointer to the remaining portion of a device path.
549
550 Returns:
551
552 EFI_SUCCESS - Operation successfully
553 EFI_DEVICE_ERROR - Cannot stop the driver successfully
554
555 --*/
556 {
557 EFI_STATUS Status;
558 UINTN Index;
559 BOOLEAN AllChildrenStopped;
560 EFI_SERIAL_IO_PROTOCOL *SerialIo;
561 SERIAL_DEV *SerialDevice;
562 EFI_ISA_IO_PROTOCOL *IsaIo;
563 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
564
565 Status = gBS->HandleProtocol (
566 Controller,
567 &gEfiDevicePathProtocolGuid,
568 (VOID **) &DevicePath
569 );
570
571 //
572 // Report the status code disable the serial
573 //
574 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
575 EFI_PROGRESS_CODE,
576 EFI_P_PC_DISABLE | EFI_PERIPHERAL_SERIAL_PORT,
577 DevicePath
578 );
579
580 //
581 // Complete all outstanding transactions to Controller.
582 // Don't allow any new transaction to Controller to be started.
583 //
584 if (NumberOfChildren == 0) {
585 //
586 // Close the bus driver
587 //
588 Status = gBS->CloseProtocol (
589 Controller,
590 &gEfiIsaIoProtocolGuid,
591 This->DriverBindingHandle,
592 Controller
593 );
594
595 Status = gBS->CloseProtocol (
596 Controller,
597 &gEfiDevicePathProtocolGuid,
598 This->DriverBindingHandle,
599 Controller
600 );
601 return Status;
602 }
603
604 AllChildrenStopped = TRUE;
605
606 for (Index = 0; Index < NumberOfChildren; Index++) {
607
608 Status = gBS->OpenProtocol (
609 ChildHandleBuffer[Index],
610 &gEfiSerialIoProtocolGuid,
611 (VOID **) &SerialIo,
612 This->DriverBindingHandle,
613 Controller,
614 EFI_OPEN_PROTOCOL_GET_PROTOCOL
615 );
616 if (!EFI_ERROR (Status)) {
617
618 SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo);
619
620 Status = gBS->CloseProtocol (
621 Controller,
622 &gEfiIsaIoProtocolGuid,
623 This->DriverBindingHandle,
624 ChildHandleBuffer[Index]
625 );
626
627 Status = gBS->UninstallMultipleProtocolInterfaces (
628 ChildHandleBuffer[Index],
629 &gEfiDevicePathProtocolGuid,
630 SerialDevice->DevicePath,
631 &gEfiSerialIoProtocolGuid,
632 &SerialDevice->SerialIo,
633 NULL
634 );
635 if (EFI_ERROR (Status)) {
636 gBS->OpenProtocol (
637 Controller,
638 &gEfiIsaIoProtocolGuid,
639 (VOID **) &IsaIo,
640 This->DriverBindingHandle,
641 ChildHandleBuffer[Index],
642 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
643 );
644 } else {
645 if (SerialDevice->DevicePath) {
646 gBS->FreePool (SerialDevice->DevicePath);
647 }
648
649 FreeUnicodeStringTable (SerialDevice->ControllerNameTable);
650 gBS->FreePool (SerialDevice);
651 }
652 }
653
654 if (EFI_ERROR (Status)) {
655 AllChildrenStopped = FALSE;
656 }
657 }
658
659 if (!AllChildrenStopped) {
660 return EFI_DEVICE_ERROR;
661 }
662
663 return EFI_SUCCESS;
664 }
665
666 BOOLEAN
667 IsaSerialFifoFull (
668 IN SERIAL_DEV_FIFO *Fifo
669 )
670 /*++
671
672 Routine Description:
673
674 Detect whether specific FIFO is full or not
675
676 Arguments:
677
678 Fifo - A pointer to the Data Structure SERIAL_DEV_FIFO
679
680 Returns:
681
682 TRUE - the FIFO is full
683 FALSE - the FIFO is not full
684
685 --*/
686 {
687 if (Fifo->Surplus == 0) {
688 return TRUE;
689 }
690
691 return FALSE;
692 }
693
694 BOOLEAN
695 IsaSerialFifoEmpty (
696 IN SERIAL_DEV_FIFO *Fifo
697 )
698 /*++
699
700 Routine Description:
701
702 Detect whether specific FIFO is empty or not
703
704 Arguments:
705
706 Fifo - A pointer to the Data Structure SERIAL_DEV_FIFO
707
708 Returns:
709
710 TRUE - the FIFO is empty
711 FALSE - the FIFO is not empty
712
713 --*/
714 {
715 if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {
716 return TRUE;
717 }
718
719 return FALSE;
720 }
721
722 EFI_STATUS
723 IsaSerialFifoAdd (
724 IN SERIAL_DEV_FIFO *Fifo,
725 IN UINT8 Data
726 )
727 /*++
728
729 Routine Description:
730
731 Add data to specific FIFO
732
733 Arguments:
734
735 Fifo - A pointer to the Data Structure SERIAL_DEV_FIFO
736 Data - the data added to FIFO
737
738 Returns:
739
740 EFI_SUCCESS - Add data to specific FIFO successfully
741 EFI_OUT_OF_RESOURCE - Failed to add data because FIFO is already full
742
743 --*/
744 {
745 //
746 // if FIFO full can not add data
747 //
748 if (IsaSerialFifoFull (Fifo)) {
749 return EFI_OUT_OF_RESOURCES;
750 }
751 //
752 // FIFO is not full can add data
753 //
754 Fifo->Data[Fifo->Last] = Data;
755 Fifo->Surplus--;
756 Fifo->Last++;
757 if (Fifo->Last == SERIAL_MAX_BUFFER_SIZE) {
758 Fifo->Last = 0;
759 }
760
761 return EFI_SUCCESS;
762 }
763
764 EFI_STATUS
765 IsaSerialFifoRemove (
766 IN SERIAL_DEV_FIFO *Fifo,
767 OUT UINT8 *Data
768 )
769 /*++
770
771 Routine Description:
772
773 Remove data from specific FIFO
774
775 Arguments:
776
777 Fifo - A pointer to the Data Structure SERIAL_DEV_FIFO
778 Data - the data removed from FIFO
779
780 Returns:
781 EFI_SUCCESS - Remove data from specific FIFO successfully
782 EFI_OUT_OF_RESOURCE - Failed to remove data because FIFO is empty
783
784 --*/
785 {
786 //
787 // if FIFO is empty, no data can remove
788 //
789 if (IsaSerialFifoEmpty (Fifo)) {
790 return EFI_OUT_OF_RESOURCES;
791 }
792 //
793 // FIFO is not empty, can remove data
794 //
795 *Data = Fifo->Data[Fifo->First];
796 Fifo->Surplus++;
797 Fifo->First++;
798 if (Fifo->First == SERIAL_MAX_BUFFER_SIZE) {
799 Fifo->First = 0;
800 }
801
802 return EFI_SUCCESS;
803 }
804
805 EFI_STATUS
806 IsaSerialReceiveTransmit (
807 IN SERIAL_DEV *SerialDevice
808 )
809 /*++
810
811 Routine Description:
812
813 Reads and writes all avaliable data.
814
815 Arguments:
816
817 SerialDevice - The device to flush
818
819 Returns:
820
821 EFI_SUCCESS - Data was read/written successfully.
822 EFI_OUT_OF_RESOURCE - Failed because software receive FIFO is full. Note, when
823 this happens, pending writes are not done.
824
825 --*/
826 {
827 SERIAL_PORT_LSR Lsr;
828 UINT8 Data;
829 BOOLEAN ReceiveFifoFull;
830 SERIAL_PORT_MSR Msr;
831 SERIAL_PORT_MCR Mcr;
832 UINTN TimeOut;
833
834 Data = 0;
835
836 //
837 // Begin the read or write
838 //
839 if (SerialDevice->SoftwareLoopbackEnable) {
840 do {
841 ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);
842 if (!IsaSerialFifoEmpty (&SerialDevice->Transmit)) {
843 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);
844 if (ReceiveFifoFull) {
845 return EFI_OUT_OF_RESOURCES;
846 }
847
848 IsaSerialFifoAdd (&SerialDevice->Receive, Data);
849 }
850 } while (!IsaSerialFifoEmpty (&SerialDevice->Transmit));
851 } else {
852 ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);
853 do {
854 Lsr.Data = READ_LSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
855
856 if (FeaturePcdGet (PcdNtEmulatorEnable)) {
857 //
858 // This is required for NT to avoid a forever-spin...
859 // This would be better if READ_LSR was a polling operation
860 // that would timeout.
861 //
862 Lsr.Bits.THRE = 1;
863 }
864 //
865 // Flush incomming data to prevent a an overrun during a long write
866 //
867 if (Lsr.Bits.DR && !ReceiveFifoFull) {
868 ReceiveFifoFull = IsaSerialFifoFull (&SerialDevice->Receive);
869 if (!ReceiveFifoFull) {
870 if (Lsr.Bits.FIFOE || Lsr.Bits.OE || Lsr.Bits.PE || Lsr.Bits.FE || Lsr.Bits.BI) {
871 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
872 EFI_ERROR_CODE,
873 EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
874 SerialDevice->DevicePath
875 );
876 if (Lsr.Bits.FIFOE || Lsr.Bits.PE || Lsr.Bits.FE || Lsr.Bits.BI) {
877 Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
878 continue;
879 }
880 }
881 //
882 // Make sure the receive data will not be missed, Assert DTR
883 //
884 if (SerialDevice->HardwareFlowControl) {
885 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
886 Mcr.Bits.DTRC &= 0;
887 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
888 }
889
890 Data = READ_RBR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
891
892 //
893 // Deassert DTR
894 //
895 if (SerialDevice->HardwareFlowControl) {
896 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
897 Mcr.Bits.DTRC |= 1;
898 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
899 }
900
901 IsaSerialFifoAdd (&SerialDevice->Receive, Data);
902
903 continue;
904 } else {
905 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
906 EFI_PROGRESS_CODE,
907 EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER | EFI_PERIPHERAL_SERIAL_PORT,
908 SerialDevice->DevicePath
909 );
910 }
911 }
912 //
913 // Do the write
914 //
915 if (Lsr.Bits.THRE && !IsaSerialFifoEmpty (&SerialDevice->Transmit)) {
916 //
917 // Make sure the transmit data will not be missed
918 //
919 if (SerialDevice->HardwareFlowControl) {
920 //
921 // Send RTS
922 //
923 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
924 Mcr.Bits.RTS |= 1;
925 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
926 //
927 // Wait for CTS
928 //
929 TimeOut = 0;
930 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
931 while (!Msr.Bits.CTS) {
932 gBS->Stall (TIMEOUT_STALL_INTERVAL);
933 TimeOut++;
934 if (TimeOut > 5) {
935 break;
936 }
937
938 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
939 }
940
941 if (Msr.Bits.CTS) {
942 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);
943 WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);
944 }
945 }
946 //
947 // write the data out
948 //
949 if (!SerialDevice->HardwareFlowControl) {
950 IsaSerialFifoRemove (&SerialDevice->Transmit, &Data);
951 WRITE_THR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Data);
952 }
953 //
954 // Make sure the transmit data will not be missed
955 //
956 if (SerialDevice->HardwareFlowControl) {
957 //
958 // Assert RTS
959 //
960 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
961 Mcr.Bits.RTS &= 0;
962 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
963 }
964 }
965 } while (Lsr.Bits.THRE && !IsaSerialFifoEmpty (&SerialDevice->Transmit));
966 }
967
968 return EFI_SUCCESS;
969 }
970 //
971 // Interface Functions
972 //
973 EFI_STATUS
974 EFIAPI
975 IsaSerialReset (
976 IN EFI_SERIAL_IO_PROTOCOL *This
977 )
978 /*++
979
980 Routine Description:
981
982 Reset serial device
983
984 Arguments:
985
986 This - Pointer to EFI_SERIAL_IO_PROTOCOL
987
988 Returns:
989
990 EFI_SUCCESS - Reset successfully
991 EFI_DEVICE_ERROR - Failed to reset
992
993 --*/
994 {
995 EFI_STATUS Status;
996 SERIAL_DEV *SerialDevice;
997 SERIAL_PORT_LCR Lcr;
998 SERIAL_PORT_IER Ier;
999 SERIAL_PORT_MCR Mcr;
1000 SERIAL_PORT_FCR Fcr;
1001 EFI_TPL Tpl;
1002
1003 SerialDevice = SERIAL_DEV_FROM_THIS (This);
1004
1005 //
1006 // Report the status code reset the serial
1007 //
1008 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1009 EFI_PROGRESS_CODE,
1010 EFI_P_PC_RESET | EFI_PERIPHERAL_SERIAL_PORT,
1011 SerialDevice->DevicePath
1012 );
1013
1014 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
1015
1016 //
1017 // Make sure DLAB is 0.
1018 //
1019 Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
1020 Lcr.Bits.DLAB = 0;
1021 WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);
1022
1023 //
1024 // Turn off all interrupts
1025 //
1026 Ier.Data = READ_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress);
1027 Ier.Bits.RAVIE = 0;
1028 Ier.Bits.THEIE = 0;
1029 Ier.Bits.RIE = 0;
1030 Ier.Bits.MIE = 0;
1031 WRITE_IER (SerialDevice->IsaIo, SerialDevice->BaseAddress, Ier.Data);
1032
1033 //
1034 // Disable the FIFO.
1035 //
1036 Fcr.Bits.TRFIFOE = 0;
1037 WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);
1038
1039 //
1040 // Turn off loopback and disable device interrupt.
1041 //
1042 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
1043 Mcr.Bits.OUT1 = 0;
1044 Mcr.Bits.OUT2 = 0;
1045 Mcr.Bits.LME = 0;
1046 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
1047
1048 //
1049 // Clear the scratch pad register
1050 //
1051 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0);
1052
1053 //
1054 // Go set the current attributes
1055 //
1056 Status = This->SetAttributes (
1057 This,
1058 This->Mode->BaudRate,
1059 This->Mode->ReceiveFifoDepth,
1060 This->Mode->Timeout,
1061 (EFI_PARITY_TYPE) This->Mode->Parity,
1062 (UINT8) This->Mode->DataBits,
1063 (EFI_STOP_BITS_TYPE) This->Mode->StopBits
1064 );
1065
1066 if (EFI_ERROR (Status)) {
1067 gBS->RestoreTPL (Tpl);
1068 return EFI_DEVICE_ERROR;
1069 }
1070 //
1071 // Go set the current control bits
1072 //
1073 Status = This->SetControl (
1074 This,
1075 This->Mode->ControlMask
1076 );
1077
1078 if (EFI_ERROR (Status)) {
1079 gBS->RestoreTPL (Tpl);
1080 return EFI_DEVICE_ERROR;
1081 }
1082 //
1083 // for 16550A enable FIFO, 16550 disable FIFO
1084 //
1085 Fcr.Bits.TRFIFOE = 1;
1086 Fcr.Bits.RESETRF = 1;
1087 Fcr.Bits.RESETTF = 1;
1088 WRITE_FCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Fcr.Data);
1089
1090 //
1091 // Reset the software FIFO
1092 //
1093 SerialDevice->Receive.First = 0;
1094 SerialDevice->Receive.Last = 0;
1095 SerialDevice->Receive.Surplus = SERIAL_MAX_BUFFER_SIZE;
1096 SerialDevice->Transmit.First = 0;
1097 SerialDevice->Transmit.Last = 0;
1098 SerialDevice->Transmit.Surplus = SERIAL_MAX_BUFFER_SIZE;
1099
1100 gBS->RestoreTPL (Tpl);
1101
1102 //
1103 // Device reset is complete
1104 //
1105 return EFI_SUCCESS;
1106 }
1107
1108 EFI_STATUS
1109 EFIAPI
1110 IsaSerialSetAttributes (
1111 IN EFI_SERIAL_IO_PROTOCOL *This,
1112 IN UINT64 BaudRate,
1113 IN UINT32 ReceiveFifoDepth,
1114 IN UINT32 Timeout,
1115 IN EFI_PARITY_TYPE Parity,
1116 IN UINT8 DataBits,
1117 IN EFI_STOP_BITS_TYPE StopBits
1118 )
1119 /*++
1120
1121 Routine Description:
1122
1123 Set new attributes to a serial device
1124
1125 Arguments:
1126
1127 This - Pointer to EFI_SERIAL_IO_PROTOCOL
1128 BaudRate - The baudrate of the serial device
1129 ReceiveFifoDepth - The depth of receive FIFO buffer
1130 Timeout - The request timeout for a single char
1131 Parity - The type of parity used in serial device
1132 DataBits - Number of databits used in serial device
1133 StopBits - Number of stopbits used in serial device
1134
1135 Returns:
1136
1137 EFI_SUCCESS - The new attributes were set
1138 EFI_INVALID_PARAMETERS - One or more attributes have an unsupported value
1139 EFI_UNSUPPORTED - Data Bits can not set to 5 or 6
1140 EFI_DEVICE_ERROR - The serial device is not functioning correctly (no return)
1141
1142 --*/
1143 {
1144 EFI_STATUS Status;
1145 SERIAL_DEV *SerialDevice;
1146 UINT32 Divisor;
1147 UINT32 Remained;
1148 SERIAL_PORT_LCR Lcr;
1149 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
1150 EFI_TPL Tpl;
1151
1152 SerialDevice = SERIAL_DEV_FROM_THIS (This);
1153
1154 //
1155 // Check for default settings and fill in actual values.
1156 //
1157 if (BaudRate == 0) {
1158 BaudRate = FixedPcdGet64 (PcdUartDefaultBaudRate);
1159 }
1160
1161 if (ReceiveFifoDepth == 0) {
1162 ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;
1163 }
1164
1165 if (Timeout == 0) {
1166 Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;
1167 }
1168
1169 if (Parity == DefaultParity) {
1170 Parity = FixedPcdGet8 (PcdUartDefaultParity);
1171 }
1172
1173 if (DataBits == 0) {
1174 DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
1175 }
1176
1177 if (StopBits == DefaultStopBits) {
1178 StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits);
1179 }
1180 //
1181 // 5 and 6 data bits can not be verified on a 16550A UART
1182 // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.
1183 //
1184 if ((DataBits == 5) || (DataBits == 6)) {
1185 return EFI_INVALID_PARAMETER;
1186 }
1187 //
1188 // Make sure all parameters are valid
1189 //
1190 if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {
1191 return EFI_INVALID_PARAMETER;
1192 }
1193 //
1194 // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,
1195 // 38400,57600,115200
1196 //
1197 if (BaudRate < 75) {
1198 BaudRate = 50;
1199 } else if (BaudRate < 110) {
1200 BaudRate = 75;
1201 } else if (BaudRate < 134) {
1202 BaudRate = 110;
1203 } else if (BaudRate < 150) {
1204 BaudRate = 134;
1205 } else if (BaudRate < 300) {
1206 BaudRate = 150;
1207 } else if (BaudRate < 600) {
1208 BaudRate = 300;
1209 } else if (BaudRate < 1200) {
1210 BaudRate = 600;
1211 } else if (BaudRate < 1800) {
1212 BaudRate = 1200;
1213 } else if (BaudRate < 2000) {
1214 BaudRate = 1800;
1215 } else if (BaudRate < 2400) {
1216 BaudRate = 2000;
1217 } else if (BaudRate < 3600) {
1218 BaudRate = 2400;
1219 } else if (BaudRate < 4800) {
1220 BaudRate = 3600;
1221 } else if (BaudRate < 7200) {
1222 BaudRate = 4800;
1223 } else if (BaudRate < 9600) {
1224 BaudRate = 7200;
1225 } else if (BaudRate < 19200) {
1226 BaudRate = 9600;
1227 } else if (BaudRate < 38400) {
1228 BaudRate = 19200;
1229 } else if (BaudRate < 57600) {
1230 BaudRate = 38400;
1231 } else if (BaudRate < 115200) {
1232 BaudRate = 57600;
1233 } else if (BaudRate <= SERIAL_PORT_MAX_BAUD_RATE) {
1234 BaudRate = 115200;
1235 }
1236
1237 if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {
1238 return EFI_INVALID_PARAMETER;
1239 }
1240
1241 if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {
1242 return EFI_INVALID_PARAMETER;
1243 }
1244
1245 if ((Parity < NoParity) || (Parity > SpaceParity)) {
1246 return EFI_INVALID_PARAMETER;
1247 }
1248
1249 if ((DataBits < 5) || (DataBits > 8)) {
1250 return EFI_INVALID_PARAMETER;
1251 }
1252
1253 if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {
1254 return EFI_INVALID_PARAMETER;
1255 }
1256 //
1257 // for DataBits = 5, StopBits can not set TwoStopBits
1258 //
1259 // if ((DataBits == 5) && (StopBits == TwoStopBits)) {
1260 // return EFI_INVALID_PARAMETER;
1261 // }
1262 //
1263 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits
1264 //
1265 if ((DataBits >= 6) && (DataBits <= 8) && (StopBits == OneFiveStopBits)) {
1266 return EFI_INVALID_PARAMETER;
1267 }
1268
1269 //
1270 // Compute divisor use to program the baud rate using a round determination
1271 //
1272 Divisor = (UINT32) DivU64x32Remainder (
1273 SERIAL_PORT_INPUT_CLOCK,
1274 ((UINT32) BaudRate * 16),
1275 &Remained
1276 );
1277 if (Remained) {
1278 Divisor += 1;
1279 }
1280
1281 if ((Divisor == 0) || (Divisor & 0xffff0000)) {
1282 return EFI_INVALID_PARAMETER;
1283 }
1284
1285 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
1286
1287 //
1288 // Compute the actual baud rate that the serial port will be programmed for.
1289 //
1290 BaudRate = SERIAL_PORT_INPUT_CLOCK / Divisor / 16;
1291
1292 //
1293 // Put serial port on Divisor Latch Mode
1294 //
1295 Lcr.Data = READ_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
1296 Lcr.Bits.DLAB = 1;
1297 WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);
1298
1299 //
1300 // Write the divisor to the serial port
1301 //
1302 WRITE_DLL (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) (Divisor & 0xff));
1303 WRITE_DLM (SerialDevice->IsaIo, SerialDevice->BaseAddress, (UINT8) ((Divisor >> 8) & 0xff));
1304
1305 //
1306 // Put serial port back in normal mode and set remaining attributes.
1307 //
1308 Lcr.Bits.DLAB = 0;
1309
1310 switch (Parity) {
1311 case NoParity:
1312 Lcr.Bits.PAREN = 0;
1313 Lcr.Bits.EVENPAR = 0;
1314 Lcr.Bits.STICPAR = 0;
1315 break;
1316
1317 case EvenParity:
1318 Lcr.Bits.PAREN = 1;
1319 Lcr.Bits.EVENPAR = 1;
1320 Lcr.Bits.STICPAR = 0;
1321 break;
1322
1323 case OddParity:
1324 Lcr.Bits.PAREN = 1;
1325 Lcr.Bits.EVENPAR = 0;
1326 Lcr.Bits.STICPAR = 0;
1327 break;
1328
1329 case SpaceParity:
1330 Lcr.Bits.PAREN = 1;
1331 Lcr.Bits.EVENPAR = 1;
1332 Lcr.Bits.STICPAR = 1;
1333 break;
1334
1335 case MarkParity:
1336 Lcr.Bits.PAREN = 1;
1337 Lcr.Bits.EVENPAR = 0;
1338 Lcr.Bits.STICPAR = 1;
1339 break;
1340
1341 default:
1342 break;
1343 }
1344
1345 switch (StopBits) {
1346 case OneStopBit:
1347 Lcr.Bits.STOPB = 0;
1348 break;
1349
1350 case OneFiveStopBits:
1351 case TwoStopBits:
1352 Lcr.Bits.STOPB = 1;
1353 break;
1354
1355 default:
1356 break;
1357 }
1358 //
1359 // DataBits
1360 //
1361 Lcr.Bits.SERIALDB = (UINT8) ((DataBits - 5) & 0x03);
1362 WRITE_LCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Lcr.Data);
1363
1364 //
1365 // Set the Serial I/O mode
1366 //
1367 This->Mode->BaudRate = BaudRate;
1368 This->Mode->ReceiveFifoDepth = ReceiveFifoDepth;
1369 This->Mode->Timeout = Timeout;
1370 This->Mode->Parity = Parity;
1371 This->Mode->DataBits = DataBits;
1372 This->Mode->StopBits = StopBits;
1373
1374 //
1375 // See if Device Path Node has actually changed
1376 //
1377 if (SerialDevice->UartDevicePath.BaudRate == BaudRate &&
1378 SerialDevice->UartDevicePath.DataBits == DataBits &&
1379 SerialDevice->UartDevicePath.Parity == Parity &&
1380 SerialDevice->UartDevicePath.StopBits == StopBits
1381 ) {
1382 gBS->RestoreTPL (Tpl);
1383 return EFI_SUCCESS;
1384 }
1385 //
1386 // Update the device path
1387 //
1388 SerialDevice->UartDevicePath.BaudRate = BaudRate;
1389 SerialDevice->UartDevicePath.DataBits = DataBits;
1390 SerialDevice->UartDevicePath.Parity = (UINT8) Parity;
1391 SerialDevice->UartDevicePath.StopBits = (UINT8) StopBits;
1392
1393 NewDevicePath = AppendDevicePathNode (
1394 SerialDevice->ParentDevicePath,
1395 (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath
1396 );
1397 if (NewDevicePath == NULL) {
1398 gBS->RestoreTPL (Tpl);
1399 return EFI_DEVICE_ERROR;
1400 }
1401
1402 if (SerialDevice->Handle != NULL) {
1403 Status = gBS->ReinstallProtocolInterface (
1404 SerialDevice->Handle,
1405 &gEfiDevicePathProtocolGuid,
1406 SerialDevice->DevicePath,
1407 NewDevicePath
1408 );
1409 if (EFI_ERROR (Status)) {
1410 gBS->RestoreTPL (Tpl);
1411 return Status;
1412 }
1413 }
1414
1415 if (SerialDevice->DevicePath) {
1416 gBS->FreePool (SerialDevice->DevicePath);
1417 }
1418
1419 SerialDevice->DevicePath = NewDevicePath;
1420
1421 gBS->RestoreTPL (Tpl);
1422
1423 return EFI_SUCCESS;
1424 }
1425
1426 EFI_STATUS
1427 EFIAPI
1428 IsaSerialSetControl (
1429 IN EFI_SERIAL_IO_PROTOCOL *This,
1430 IN UINT32 Control
1431 )
1432 /*++
1433
1434 Routine Description:
1435
1436 Set Control Bits
1437
1438 Arguments:
1439
1440 This - Pointer to EFI_SERIAL_IO_PROTOCOL
1441 Control - Control bits that can be settable
1442
1443 Returns:
1444
1445 EFI_SUCCESS - New Control bits were set successfully
1446 EFI_UNSUPPORTED - The Control bits wanted to set are not supported
1447
1448 --*/
1449 {
1450 SERIAL_DEV *SerialDevice;
1451 SERIAL_PORT_MCR Mcr;
1452 EFI_TPL Tpl;
1453
1454 //
1455 // The control bits that can be set are :
1456 // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO
1457 // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO
1458 // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW
1459 // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW
1460 //
1461 SerialDevice = SERIAL_DEV_FROM_THIS (This);
1462
1463 //
1464 // first determine the parameter is invalid
1465 //
1466 if (Control & 0xffff8ffc) {
1467 return EFI_UNSUPPORTED;
1468 }
1469
1470 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
1471
1472 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
1473 Mcr.Bits.DTRC = 0;
1474 Mcr.Bits.RTS = 0;
1475 Mcr.Bits.LME = 0;
1476 SerialDevice->SoftwareLoopbackEnable = FALSE;
1477 SerialDevice->HardwareFlowControl = FALSE;
1478
1479 if (Control & EFI_SERIAL_DATA_TERMINAL_READY) {
1480 Mcr.Bits.DTRC = 1;
1481 }
1482
1483 if (Control & EFI_SERIAL_REQUEST_TO_SEND) {
1484 Mcr.Bits.RTS = 1;
1485 }
1486
1487 if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
1488 Mcr.Bits.LME = 1;
1489 }
1490
1491 if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
1492 SerialDevice->HardwareFlowControl = TRUE;
1493 }
1494
1495 WRITE_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Mcr.Data);
1496
1497 if (Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {
1498 SerialDevice->SoftwareLoopbackEnable = TRUE;
1499 }
1500
1501 gBS->RestoreTPL (Tpl);
1502
1503 return EFI_SUCCESS;
1504 }
1505
1506 EFI_STATUS
1507 EFIAPI
1508 IsaSerialGetControl (
1509 IN EFI_SERIAL_IO_PROTOCOL *This,
1510 OUT UINT32 *Control
1511 )
1512 /*++
1513
1514 Routine Description:
1515
1516 Get ControlBits
1517
1518 Arguments:
1519
1520 This - Pointer to EFI_SERIAL_IO_PROTOCOL
1521 Control - Control signals of the serial device
1522
1523 Returns:
1524
1525 EFI_SUCCESS - Get Control signals successfully
1526
1527 --*/
1528 {
1529 SERIAL_DEV *SerialDevice;
1530 SERIAL_PORT_MSR Msr;
1531 SERIAL_PORT_MCR Mcr;
1532 EFI_TPL Tpl;
1533
1534 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
1535
1536 SerialDevice = SERIAL_DEV_FROM_THIS (This);
1537
1538 *Control = 0;
1539
1540 //
1541 // Read the Modem Status Register
1542 //
1543 Msr.Data = READ_MSR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
1544
1545 if (Msr.Bits.CTS) {
1546 *Control |= EFI_SERIAL_CLEAR_TO_SEND;
1547 }
1548
1549 if (Msr.Bits.DSR) {
1550 *Control |= EFI_SERIAL_DATA_SET_READY;
1551 }
1552
1553 if (Msr.Bits.RI) {
1554 *Control |= EFI_SERIAL_RING_INDICATE;
1555 }
1556
1557 if (Msr.Bits.DCD) {
1558 *Control |= EFI_SERIAL_CARRIER_DETECT;
1559 }
1560 //
1561 // Read the Modem Control Register
1562 //
1563 Mcr.Data = READ_MCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
1564
1565 if (Mcr.Bits.DTRC) {
1566 *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
1567 }
1568
1569 if (Mcr.Bits.RTS) {
1570 *Control |= EFI_SERIAL_REQUEST_TO_SEND;
1571 }
1572
1573 if (Mcr.Bits.LME) {
1574 *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
1575 }
1576
1577 if (SerialDevice->HardwareFlowControl) {
1578 *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
1579 }
1580 //
1581 // See if the Transmit FIFO is empty
1582 //
1583 IsaSerialReceiveTransmit (SerialDevice);
1584
1585 if (IsaSerialFifoEmpty (&SerialDevice->Transmit)) {
1586 *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
1587 }
1588 //
1589 // See if the Receive FIFO is empty.
1590 //
1591 IsaSerialReceiveTransmit (SerialDevice);
1592
1593 if (IsaSerialFifoEmpty (&SerialDevice->Receive)) {
1594 *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
1595 }
1596
1597 if (SerialDevice->SoftwareLoopbackEnable) {
1598 *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
1599 }
1600
1601 gBS->RestoreTPL (Tpl);
1602
1603 return EFI_SUCCESS;
1604 }
1605
1606 EFI_STATUS
1607 EFIAPI
1608 IsaSerialWrite (
1609 IN EFI_SERIAL_IO_PROTOCOL *This,
1610 IN OUT UINTN *BufferSize,
1611 IN VOID *Buffer
1612 )
1613 /*++
1614
1615 Routine Description:
1616
1617 Write the specified number of bytes to serial device
1618
1619 Arguments:
1620
1621 This - Pointer to EFI_SERIAL_IO_PROTOCOL
1622 BufferSize - On input the size of Buffer, on output the amount of
1623 data actually written
1624 Buffer - The buffer of data to write
1625
1626 Returns:
1627
1628 EFI_SUCCESS - The data were written successfully
1629 EFI_DEVICE_ERROR - The device reported an error
1630 EFI_TIMEOUT - The write operation was stopped due to timeout
1631
1632 --*/
1633 {
1634 SERIAL_DEV *SerialDevice;
1635 UINT8 *CharBuffer;
1636 UINT32 Index;
1637 UINTN Elapsed;
1638 UINTN ActualWrite;
1639 EFI_TPL Tpl;
1640
1641 SerialDevice = SERIAL_DEV_FROM_THIS (This);
1642 Elapsed = 0;
1643 ActualWrite = 0;
1644
1645 if (*BufferSize == 0) {
1646 return EFI_SUCCESS;
1647 }
1648
1649 if (!Buffer) {
1650 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1651 EFI_ERROR_CODE,
1652 EFI_P_EC_OUTPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
1653 SerialDevice->DevicePath
1654 );
1655
1656 return EFI_DEVICE_ERROR;
1657 }
1658
1659 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
1660
1661 CharBuffer = (UINT8 *) Buffer;
1662
1663 for (Index = 0; Index < *BufferSize; Index++) {
1664 IsaSerialFifoAdd (&SerialDevice->Transmit, CharBuffer[Index]);
1665
1666 while (IsaSerialReceiveTransmit (SerialDevice) != EFI_SUCCESS || !IsaSerialFifoEmpty (&SerialDevice->Transmit)) {
1667 //
1668 // Unsuccessful write so check if timeout has expired, if not,
1669 // stall for a bit, increment time elapsed, and try again
1670 //
1671 if (Elapsed >= This->Mode->Timeout) {
1672 *BufferSize = ActualWrite;
1673 gBS->RestoreTPL (Tpl);
1674 return EFI_TIMEOUT;
1675 }
1676
1677 gBS->Stall (TIMEOUT_STALL_INTERVAL);
1678
1679 Elapsed += TIMEOUT_STALL_INTERVAL;
1680 }
1681
1682 ActualWrite++;
1683 //
1684 // Successful write so reset timeout
1685 //
1686 Elapsed = 0;
1687 }
1688
1689 gBS->RestoreTPL (Tpl);
1690
1691 return EFI_SUCCESS;
1692 }
1693
1694 EFI_STATUS
1695 EFIAPI
1696 IsaSerialRead (
1697 IN EFI_SERIAL_IO_PROTOCOL *This,
1698 IN OUT UINTN *BufferSize,
1699 OUT VOID *Buffer
1700 )
1701 /*++
1702
1703 Routine Description:
1704
1705 Read the specified number of bytes from serial device
1706
1707 Arguments:
1708
1709 This - Pointer to EFI_SERIAL_IO_PROTOCOL
1710 BufferSize - On input the size of Buffer, on output the amount of
1711 data returned in buffer
1712 Buffer - The buffer to return the data into
1713
1714 Returns:
1715
1716 EFI_SUCCESS - The data were read successfully
1717 EFI_DEVICE_ERROR - The device reported an error
1718 EFI_TIMEOUT - The read operation was stopped due to timeout
1719
1720 --*/
1721 {
1722 SERIAL_DEV *SerialDevice;
1723 UINT32 Index;
1724 UINT8 *CharBuffer;
1725 UINTN Elapsed;
1726 EFI_STATUS Status;
1727 EFI_TPL Tpl;
1728
1729 SerialDevice = SERIAL_DEV_FROM_THIS (This);
1730 Elapsed = 0;
1731
1732 if (*BufferSize == 0) {
1733 return EFI_SUCCESS;
1734 }
1735
1736 if (!Buffer) {
1737 return EFI_DEVICE_ERROR;
1738 }
1739
1740 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
1741
1742 Status = IsaSerialReceiveTransmit (SerialDevice);
1743
1744 if (EFI_ERROR (Status)) {
1745 *BufferSize = 0;
1746
1747 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1748 EFI_ERROR_CODE,
1749 EFI_P_EC_INPUT_ERROR | EFI_PERIPHERAL_SERIAL_PORT,
1750 SerialDevice->DevicePath
1751 );
1752
1753 gBS->RestoreTPL (Tpl);
1754
1755 return EFI_DEVICE_ERROR;
1756 }
1757
1758 CharBuffer = (UINT8 *) Buffer;
1759 for (Index = 0; Index < *BufferSize; Index++) {
1760 while (IsaSerialFifoRemove (&SerialDevice->Receive, &(CharBuffer[Index])) != EFI_SUCCESS) {
1761 //
1762 // Unsuccessful read so check if timeout has expired, if not,
1763 // stall for a bit, increment time elapsed, and try again
1764 // Need this time out to get conspliter to work.
1765 //
1766 if (Elapsed >= This->Mode->Timeout) {
1767 *BufferSize = Index;
1768 gBS->RestoreTPL (Tpl);
1769 return EFI_TIMEOUT;
1770 }
1771
1772 gBS->Stall (TIMEOUT_STALL_INTERVAL);
1773 Elapsed += TIMEOUT_STALL_INTERVAL;
1774
1775 Status = IsaSerialReceiveTransmit (SerialDevice);
1776 if (Status == EFI_DEVICE_ERROR) {
1777 *BufferSize = Index;
1778 gBS->RestoreTPL (Tpl);
1779 return EFI_DEVICE_ERROR;
1780 }
1781 }
1782 //
1783 // Successful read so reset timeout
1784 //
1785 Elapsed = 0;
1786 }
1787
1788 IsaSerialReceiveTransmit (SerialDevice);
1789
1790 gBS->RestoreTPL (Tpl);
1791
1792 return EFI_SUCCESS;
1793 }
1794
1795 BOOLEAN
1796 IsaSerialPortPresent (
1797 IN SERIAL_DEV *SerialDevice
1798 )
1799 /*++
1800
1801 Routine Description:
1802
1803 Use scratchpad register to test if this serial port is present
1804
1805 Arguments:
1806
1807 SerialDevice - Pointer to serial device structure
1808
1809 Returns:
1810
1811 TRUE - The serial port is present
1812 FALSE - The serial port is NOT present
1813
1814 --*/
1815 {
1816 UINT8 Temp;
1817 BOOLEAN Status;
1818
1819 Status = TRUE;
1820
1821 //
1822 // Save SCR reg
1823 //
1824 Temp = READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress);
1825 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0xAA);
1826
1827 if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0xAA) {
1828 if (!FeaturePcdGet (PcdNtEmulatorEnable)) {
1829 Status = FALSE;
1830 }
1831 }
1832
1833 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, 0x55);
1834
1835 if (READ_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress) != 0x55) {
1836 if (!FeaturePcdGet (PcdNtEmulatorEnable)) {
1837 Status = FALSE;
1838 }
1839 }
1840 //
1841 // Restore SCR
1842 //
1843 WRITE_SCR (SerialDevice->IsaIo, SerialDevice->BaseAddress, Temp);
1844 return Status;
1845 }
1846
1847 UINT8
1848 IsaSerialReadPort (
1849 IN EFI_ISA_IO_PROTOCOL *IsaIo,
1850 IN UINT16 BaseAddress,
1851 IN UINT32 Offset
1852 )
1853 /*++
1854
1855 Routine Description:
1856
1857 Use IsaIo protocol to read serial port
1858
1859 Arguments:
1860
1861 IsaIo - Pointer to EFI_ISA_IO_PROTOCOL instance
1862 BaseAddress - Serial port register group base address
1863 Offset - Offset in register group
1864
1865 Returns:
1866
1867 Data read from serial port
1868
1869 --*/
1870 {
1871 UINT8 Data;
1872
1873 //
1874 // Use IsaIo to access IO
1875 //
1876 IsaIo->Io.Read (
1877 IsaIo,
1878 EfiIsaIoWidthUint8,
1879 BaseAddress + Offset,
1880 1,
1881 &Data
1882 );
1883 return Data;
1884 }
1885
1886 VOID
1887 IsaSerialWritePort (
1888 IN EFI_ISA_IO_PROTOCOL *IsaIo,
1889 IN UINT16 BaseAddress,
1890 IN UINT32 Offset,
1891 IN UINT8 Data
1892 )
1893 /*++
1894
1895 Routine Description:
1896
1897 Use IsaIo protocol to write serial port
1898
1899 Arguments:
1900
1901 IsaIo - Pointer to EFI_ISA_IO_PROTOCOL instance
1902 BaseAddress - Serial port register group base address
1903 Offset - Offset in register group
1904 Data - data which is to be written to some serial port register
1905
1906 Returns:
1907
1908 None
1909
1910 --*/
1911 {
1912 //
1913 // Use IsaIo to access IO
1914 //
1915 IsaIo->Io.Write (
1916 IsaIo,
1917 EfiIsaIoWidthUint8,
1918 BaseAddress + Offset,
1919 1,
1920 &Data
1921 );
1922 }
1923