56 ASSERT (PortId < MAX_PORTS);
59 return (UINT16)(VIRTIO_SERIAL_Q_RX_BASE + (PortId - 1) * 2);
62 return VIRTIO_SERIAL_Q_RX_PORT0;
71 ASSERT (PortId < MAX_PORTS);
74 return (UINT16)(VIRTIO_SERIAL_Q_TX_BASE + (PortId - 1) * 2);
77 return VIRTIO_SERIAL_Q_TX_PORT0;
87 DEBUG ((DEBUG_VERBOSE,
"%a:%d:\n", __func__, __LINE__));
94VirtioSerialIoSetAttributes (
97 IN UINT32 ReceiveFifoDepth,
106 "%a:%d: Rate %ld, Fifo %d, Bits %d\n",
119VirtioSerialIoSetControl (
124 DEBUG ((DEBUG_INFO,
"%a:%d: Control 0x%x\n", __func__, __LINE__, Control));
131VirtioSerialIoGetControl (
136 DEBUG ((DEBUG_VERBOSE,
"%a:%d: Control 0x%x\n", __func__, __LINE__, *Control));
154 if (!Port->DeviceOpen) {
159 VirtioSerialRingClearTx (SerialIo->Dev, PortTx (SerialIo->PortId));
161 OldTpl =
gBS->RaiseTPL (TPL_NOTIFY);
162 if (SerialIo->WriteOffset &&
163 (SerialIo->WriteOffset + *BufferSize > PORT_TX_BUFSIZE))
165 DEBUG ((DEBUG_VERBOSE,
"%a:%d: WriteFlush %d\n", __func__, __LINE__, SerialIo->WriteOffset));
166 VirtioSerialRingSendBuffer (
168 PortTx (SerialIo->PortId),
169 SerialIo->WriteBuffer,
170 SerialIo->WriteOffset,
173 SerialIo->WriteOffset = 0;
176 Length =
MIN ((UINT32)(*BufferSize), PORT_TX_BUFSIZE - SerialIo->WriteOffset);
177 CopyMem (SerialIo->WriteBuffer + SerialIo->WriteOffset, Buffer, Length);
178 SerialIo->WriteOffset += Length;
179 *BufferSize = Length;
180 gBS->RestoreTPL (OldTpl);
200 if (!Port->DeviceOpen) {
204 OldTpl =
gBS->RaiseTPL (TPL_NOTIFY);
205 if (SerialIo->WriteOffset) {
206 DEBUG ((DEBUG_VERBOSE,
"%a:%d: WriteFlush %d\n", __func__, __LINE__, SerialIo->WriteOffset));
207 VirtioSerialRingSendBuffer (
209 PortTx (SerialIo->PortId),
210 SerialIo->WriteBuffer,
211 SerialIo->WriteOffset,
214 SerialIo->WriteOffset = 0;
217 gBS->RestoreTPL (OldTpl);
219 if (SerialIo->ReadOffset == SerialIo->ReadSize) {
220 HasData = VirtioSerialRingGetBuffer (
222 PortRx (SerialIo->PortId),
223 &SerialIo->ReadBuffer,
230 SerialIo->ReadOffset = 0;
233 if (SerialIo->ReadOffset < SerialIo->ReadSize) {
234 Length = SerialIo->ReadSize - SerialIo->ReadOffset;
235 if (Length > *BufferSize) {
236 Length = (UINT32)(*BufferSize);
239 CopyMem (Buffer, SerialIo->ReadBuffer + SerialIo->ReadOffset, Length);
240 SerialIo->ReadOffset += Length;
241 *BufferSize = Length;
263 Port->SerialIo = SerialIo;
265 SerialIo->SerialIo.
Revision = EFI_SERIAL_IO_PROTOCOL_REVISION;
266 SerialIo->SerialIo.Reset = VirtioSerialIoReset;
267 SerialIo->SerialIo.SetAttributes = VirtioSerialIoSetAttributes;
268 SerialIo->SerialIo.SetControl = VirtioSerialIoSetControl;
269 SerialIo->SerialIo.GetControl = VirtioSerialIoGetControl;
270 SerialIo->SerialIo.Write = VirtioSerialIoWrite;
271 SerialIo->SerialIo.Read = VirtioSerialIoRead;
272 SerialIo->SerialIo.
Mode = &SerialIo->SerialIoMode;
274 SerialIo->PortId = PortId;
277 mAcpiSerialDevNode.
UID = PortId;
279 SerialIo->DevicePath,
283 SerialIo->DevicePath,
287 LogDevicePath (DEBUG_INFO, __func__, L
"UART", SerialIo->DevicePath);
289 Status =
gBS->InstallMultipleProtocolInterfaces (
290 &SerialIo->DeviceHandle,
291 &gEfiDevicePathProtocolGuid,
292 SerialIo->DevicePath,
293 &gEfiSerialIoProtocolGuid,
297 if (EFI_ERROR (Status)) {
298 DEBUG ((DEBUG_INFO,
"%a:%d: ERROR: %r\n", __func__, __LINE__, Status));
302 Status =
gBS->OpenProtocol (
304 &gVirtioDeviceProtocolGuid,
305 (VOID **)&Dev->VirtIo,
306 Dev->DriverBindingHandle,
307 SerialIo->DeviceHandle,
308 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
310 if (EFI_ERROR (Status)) {
311 DEBUG ((DEBUG_INFO,
"%a:%d: ERROR: %r\n", __func__, __LINE__, Status));
312 goto UninstallProtocol;
318 gBS->UninstallMultipleProtocolInterfaces (
319 SerialIo->DeviceHandle,
320 &gEfiDevicePathProtocolGuid,
321 SerialIo->DevicePath,
322 &gEfiSerialIoProtocolGuid,
329 Port->SerialIo =
NULL;
336VirtioSerialIoUninit (
343 DEBUG ((DEBUG_INFO,
"%a:%d: %s\n", __func__, __LINE__, Port->Name));
347 &gVirtioDeviceProtocolGuid,
348 Dev->DriverBindingHandle,
349 SerialIo->DeviceHandle
352 gBS->UninstallMultipleProtocolInterfaces (
353 SerialIo->DeviceHandle,
354 &gEfiDevicePathProtocolGuid,
355 SerialIo->DevicePath,
356 &gEfiSerialIoProtocolGuid,
362 Port->SerialIo =
NULL;
379 Status = VirtioSerialInitRing (Dev, PortRx (PortId), PORT_RX_BUFSIZE);
380 if (EFI_ERROR (Status)) {
384 Status = VirtioSerialInitRing (Dev, PortTx (PortId), PORT_TX_BUFSIZE);
385 if (EFI_ERROR (Status)) {
389 UnicodeSPrint (Port->Name, sizeof (Port->Name), L
"Port #%d", PortId);
390 VirtioSerialRingFillRx (Dev, PortRx (PortId));
396 VirtioSerialUninitRing (Dev, PortRx (PortId));
402VirtioSerialPortSetConsole (
409 Port->Console =
TRUE;
410 UnicodeSPrint (Port->Name, sizeof (Port->Name), L
"Console #%d", PortId);
411 VirtioSerialIoInit (Dev, PortId);
416VirtioSerialPortSetName (
424 DEBUG ((DEBUG_INFO,
"%a:%d: \"%a\"\n", __func__, __LINE__, Name));
425 UnicodeSPrint (Port->Name, sizeof (Port->Name), L
"NamedPort #%d (%a)", PortId, Name);
430VirtioSerialPortSetDeviceOpen (
438 Port->DeviceOpen = (BOOLEAN)Value;
439 if (Port->DeviceOpen) {
440 VirtioSerialTxControl (Dev, PortId, VIRTIO_SERIAL_PORT_OPEN, 1);
446VirtioSerialPortRemove (
457 if (Port->SerialIo) {
458 VirtioSerialIoUninit (Port->SerialIo);
459 Port->SerialIo =
NULL;
462 VirtioSerialUninitRing (Dev, PortRx (PortId));
463 VirtioSerialUninitRing (Dev, PortTx (PortId));
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define MESSAGING_DEVICE_PATH
EFI_DEVICE_PATH_PROTOCOL *EFIAPI AppendDevicePathNode(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DuplicateDevicePath(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
UINTN EFIAPI UnicodeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
#define DEBUG(Expression)
EFI_SERIAL_IO_MODE * Mode