TianoCore EDK2 master
Loading...
Searching...
No Matches
AhciPeiPassThru.c
Go to the documentation of this file.
1
12#include "AhciPei.h"
13
30 IN UINT16 Port,
31 IN UINT16 PortMultiplierPort
32 )
33{
34 PEI_AHCI_ATA_DEVICE_DATA *DeviceData;
35 LIST_ENTRY *Node;
36
37 Node = GetFirstNode (&Private->DeviceList);
38 while (!IsNull (&Private->DeviceList, Node)) {
39 DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node);
40
41 if ((DeviceData->Port == Port) &&
42 (DeviceData->PortMultiplier == PortMultiplierPort))
43 {
44 return DeviceData;
45 }
46
47 Node = GetNextNode (&Private->DeviceList, Node);
48 }
49
50 return NULL;
51}
52
88 IN UINT16 Port,
89 IN UINT16 PortMultiplierPort,
90 IN UINT8 FisIndex,
92 )
93{
94 EFI_STATUS Status;
95
96 if (PortMultiplierPort == 0xFFFF) {
97 //
98 // If there is no port multiplier, PortMultiplierPort will be 0xFFFF
99 // according to UEFI spec. Here, we convert its value to 0 to follow
100 // AHCI spec.
101 //
102 PortMultiplierPort = 0;
103 }
104
105 switch (Packet->Protocol) {
106 case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:
107 Status = AhciNonDataTransfer (
108 Private,
109 (UINT8)Port,
110 (UINT8)PortMultiplierPort,
111 FisIndex,
112 Packet->Acb,
113 Packet->Asb,
114 Packet->Timeout
115 );
116 break;
117 case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:
118 Status = AhciPioTransfer (
119 Private,
120 (UINT8)Port,
121 (UINT8)PortMultiplierPort,
122 FisIndex,
123 TRUE,
124 Packet->Acb,
125 Packet->Asb,
126 Packet->InDataBuffer,
127 Packet->InTransferLength,
128 Packet->Timeout
129 );
130 break;
131 case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:
132 Status = AhciPioTransfer (
133 Private,
134 (UINT8)Port,
135 (UINT8)PortMultiplierPort,
136 FisIndex,
137 FALSE,
138 Packet->Acb,
139 Packet->Asb,
140 Packet->OutDataBuffer,
141 Packet->OutTransferLength,
142 Packet->Timeout
143 );
144 break;
145 default:
146 return EFI_UNSUPPORTED;
147 }
148
149 return Status;
150}
151
188EFIAPI
191 IN UINT16 Port,
192 IN UINT16 PortMultiplierPort,
194 )
195{
196 UINT32 IoAlign;
198 PEI_AHCI_ATA_DEVICE_DATA *DeviceData;
199 UINT32 MaxSectorCount;
200 UINT32 BlockSize;
201
202 if ((This == NULL) || (Packet == NULL)) {
203 return EFI_INVALID_PARAMETER;
204 }
205
206 IoAlign = This->Mode->IoAlign;
207 if ((IoAlign > 1) && !ADDRESS_IS_ALIGNED (Packet->InDataBuffer, IoAlign)) {
208 return EFI_INVALID_PARAMETER;
209 }
210
211 if ((IoAlign > 1) && !ADDRESS_IS_ALIGNED (Packet->OutDataBuffer, IoAlign)) {
212 return EFI_INVALID_PARAMETER;
213 }
214
215 if ((IoAlign > 1) && !ADDRESS_IS_ALIGNED (Packet->Asb, IoAlign)) {
216 return EFI_INVALID_PARAMETER;
217 }
218
219 Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_PASS_THRU (This);
220 DeviceData = SearchDeviceByPort (Private, Port, PortMultiplierPort);
221 if (DeviceData == NULL) {
222 return EFI_NOT_FOUND;
223 }
224
225 MaxSectorCount = mMaxTransferBlockNumber[DeviceData->Lba48Bit];
226 BlockSize = DeviceData->Media.BlockSize;
227
228 //
229 // Convert the transfer length from sector count to byte.
230 //
231 if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) &&
232 (Packet->InTransferLength != 0))
233 {
234 Packet->InTransferLength = Packet->InTransferLength * BlockSize;
235 }
236
237 //
238 // Convert the transfer length from sector count to byte.
239 //
240 if (((Packet->Length & EFI_ATA_PASS_THRU_LENGTH_BYTES) == 0) &&
241 (Packet->OutTransferLength != 0))
242 {
243 Packet->OutTransferLength = Packet->OutTransferLength * BlockSize;
244 }
245
246 //
247 // If the data buffer described by InDataBuffer/OutDataBuffer and
248 // InTransferLength/OutTransferLength is too big to be transferred in a single
249 // command, then no data is transferred and EFI_BAD_BUFFER_SIZE is returned.
250 //
251 if (((Packet->InTransferLength != 0) && (Packet->InTransferLength > MaxSectorCount * BlockSize)) ||
252 ((Packet->OutTransferLength != 0) && (Packet->OutTransferLength > MaxSectorCount * BlockSize)))
253 {
254 return EFI_BAD_BUFFER_SIZE;
255 }
256
257 return AhciPassThruExecute (
258 Private,
259 DeviceData->Port,
260 DeviceData->PortMultiplier,
261 DeviceData->FisIndex,
262 Packet
263 );
264}
265
299EFIAPI
302 IN OUT UINT16 *Port
303 )
304{
306 PEI_AHCI_ATA_DEVICE_DATA *DeviceData;
307 LIST_ENTRY *Node;
308
309 if ((This == NULL) || (Port == NULL)) {
310 return EFI_INVALID_PARAMETER;
311 }
312
313 Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_PASS_THRU (This);
314
315 if (*Port == 0xFFFF) {
316 //
317 // If the Port is all 0xFF's, start to traverse the device list from the
318 // beginning.
319 //
320 Node = GetFirstNode (&Private->DeviceList);
321 if (!IsNull (&Private->DeviceList, Node)) {
322 DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node);
323
324 *Port = DeviceData->Port;
325 goto Exit;
326 }
327
328 return EFI_NOT_FOUND;
329 } else if (*Port == Private->PreviousPort) {
330 Node = GetFirstNode (&Private->DeviceList);
331
332 while (!IsNull (&Private->DeviceList, Node)) {
333 DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node);
334
335 if (DeviceData->Port > *Port) {
336 *Port = DeviceData->Port;
337 goto Exit;
338 }
339
340 Node = GetNextNode (&Private->DeviceList, Node);
341 }
342
343 return EFI_NOT_FOUND;
344 } else {
345 //
346 // Port is not equal to all 0xFF's and not equal to previous return value.
347 //
348 return EFI_INVALID_PARAMETER;
349 }
350
351Exit:
352 //
353 // Update the PreviousPort.
354 //
355 Private->PreviousPort = *Port;
356
357 return EFI_SUCCESS;
358}
359
408EFIAPI
411 IN UINT16 Port,
412 IN OUT UINT16 *PortMultiplierPort
413 )
414{
416 PEI_AHCI_ATA_DEVICE_DATA *DeviceData;
417 LIST_ENTRY *Node;
418
419 if ((This == NULL) || (PortMultiplierPort == NULL)) {
420 return EFI_INVALID_PARAMETER;
421 }
422
423 Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_PASS_THRU (This);
424
425 if (Private->PreviousPortMultiplier == 0xFFFF) {
426 //
427 // If a device is directly attached on a port, previous call to this
428 // function will return the value 0xFFFF for PortMultiplierPort. In
429 // this case, there should be no more device on the port multiplier.
430 //
431 Private->PreviousPortMultiplier = 0;
432 return EFI_NOT_FOUND;
433 }
434
435 if (*PortMultiplierPort == Private->PreviousPortMultiplier) {
436 Node = GetFirstNode (&Private->DeviceList);
437
438 while (!IsNull (&Private->DeviceList, Node)) {
439 DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node);
440
441 if ((DeviceData->Port == Port) &&
442 (DeviceData->PortMultiplier > *PortMultiplierPort))
443 {
444 *PortMultiplierPort = DeviceData->PortMultiplier;
445 goto Exit;
446 }
447
448 Node = GetNextNode (&Private->DeviceList, Node);
449 }
450
451 return EFI_NOT_FOUND;
452 } else if (*PortMultiplierPort == 0xFFFF) {
453 //
454 // If the PortMultiplierPort is all 0xFF's, start to traverse the device list
455 // from the beginning.
456 //
457 Node = GetFirstNode (&Private->DeviceList);
458
459 while (!IsNull (&Private->DeviceList, Node)) {
460 DeviceData = AHCI_PEI_ATA_DEVICE_INFO_FROM_THIS (Node);
461
462 if (DeviceData->Port == Port) {
463 *PortMultiplierPort = DeviceData->PortMultiplier;
464 goto Exit;
465 }
466
467 Node = GetNextNode (&Private->DeviceList, Node);
468 }
469
470 return EFI_NOT_FOUND;
471 } else {
472 //
473 // PortMultiplierPort is not equal to all 0xFF's and not equal to previous
474 // return value.
475 //
476 return EFI_INVALID_PARAMETER;
477 }
478
479Exit:
480 //
481 // Update the PreviousPortMultiplier.
482 //
483 Private->PreviousPortMultiplier = *PortMultiplierPort;
484
485 return EFI_SUCCESS;
486}
487
506EFIAPI
509 OUT UINTN *DevicePathLength,
510 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
511 )
512{
514
515 if ((This == NULL) || (DevicePathLength == NULL) || (DevicePath == NULL)) {
516 return EFI_INVALID_PARAMETER;
517 }
518
519 Private = GET_AHCI_PEIM_HC_PRIVATE_DATA_FROM_THIS_PASS_THRU (This);
520
521 *DevicePathLength = Private->DevicePathLength;
522 *DevicePath = AllocateCopyPool (Private->DevicePathLength, Private->DevicePath);
523 if (*DevicePath == NULL) {
524 *DevicePathLength = 0;
525 return EFI_OUT_OF_RESOURCES;
526 }
527
528 return EFI_SUCCESS;
529}
UINT64 UINTN
EFI_STATUS AhciNonDataTransfer(IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, IN UINT8 Port, IN UINT8 PortMultiplier, IN UINT8 FisIndex, IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, IN UINT64 Timeout)
Definition: AhciMode.c:981
EFI_STATUS AhciPioTransfer(IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, IN UINT8 Port, IN UINT8 PortMultiplier, IN UINT8 FisIndex, IN BOOLEAN Read, IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, IN OUT VOID *MemoryAddr, IN UINT32 DataCount, IN UINT64 Timeout)
Definition: AhciMode.c:717
EFI_STATUS EFIAPI AhciAtaPassThruGetNextDevice(IN EDKII_PEI_ATA_PASS_THRU_PPI *This, IN UINT16 Port, IN OUT UINT16 *PortMultiplierPort)
EFI_STATUS EFIAPI AhciAtaPassThruGetDevicePath(IN EDKII_PEI_ATA_PASS_THRU_PPI *This, OUT UINTN *DevicePathLength, OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath)
EFI_STATUS EFIAPI AhciAtaPassThruPassThru(IN EDKII_PEI_ATA_PASS_THRU_PPI *This, IN UINT16 Port, IN UINT16 PortMultiplierPort, IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet)
PEI_AHCI_ATA_DEVICE_DATA * SearchDeviceByPort(IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, IN UINT16 Port, IN UINT16 PortMultiplierPort)
EFI_STATUS EFIAPI AhciAtaPassThruGetNextPort(IN EDKII_PEI_ATA_PASS_THRU_PPI *This, IN OUT UINT16 *Port)
EFI_STATUS AhciPassThruExecute(IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, IN UINT16 Port, IN UINT16 PortMultiplierPort, IN UINT8 FisIndex, IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet)
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define NULL
Definition: Base.h:319
#define ADDRESS_IS_ALIGNED(Address, Alignment)
Definition: Base.h:923
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
VOID EFIAPI Exit(IN EFI_STATUS Status)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112