]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c
Add BlockIO2 Protocol.
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AtaBusDxe / AtaPassThruExecute.c
1 /** @file
2 This file implements ATA pass through transaction for ATA bus driver.
3
4 This file implements the low level execution of ATA pass through transaction.
5 It transforms the high level identity, read/write, reset command to ATA pass
6 through command and protocol.
7
8 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
9 This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
13
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16
17
18 **/
19
20 #include "AtaBus.h"
21
22 //
23 // Look up table (UdmaValid, IsWrite) for EFI_ATA_PASS_THRU_CMD_PROTOCOL
24 //
25 EFI_ATA_PASS_THRU_CMD_PROTOCOL mAtaPassThruCmdProtocols[][2] = {
26 {
27 EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN,
28 EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT
29 },
30 {
31 EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN,
32 EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT,
33 }
34 };
35
36 //
37 // Look up table (UdmaValid, Lba48Bit, IsIsWrite) for ATA_CMD
38 //
39 UINT8 mAtaCommands[][2][2] = {
40 {
41 {
42 ATA_CMD_READ_SECTORS, // 28-bit LBA; PIO read
43 ATA_CMD_WRITE_SECTORS // 28-bit LBA; PIO write
44 },
45 {
46 ATA_CMD_READ_SECTORS_EXT, // 48-bit LBA; PIO read
47 ATA_CMD_WRITE_SECTORS_EXT // 48-bit LBA; PIO write
48 }
49 },
50 {
51 {
52 ATA_CMD_READ_DMA, // 28-bit LBA; DMA read
53 ATA_CMD_WRITE_DMA // 28-bit LBA; DMA write
54 },
55 {
56 ATA_CMD_READ_DMA_EXT, // 48-bit LBA; DMA read
57 ATA_CMD_WRITE_DMA_EXT // 48-bit LBA; DMA write
58 }
59 }
60 };
61
62 //
63 // Look up table (Lba48Bit) for maximum transfer block number
64 //
65 UINTN mMaxTransferBlockNumber[] = {
66 MAX_28BIT_TRANSFER_BLOCK_NUM,
67 MAX_48BIT_TRANSFER_BLOCK_NUM
68 };
69
70
71 /**
72 Wrapper for EFI_ATA_PASS_THRU_PROTOCOL.PassThru().
73
74 This function wraps the PassThru() invocation for ATA pass through function
75 for an ATA device. It assembles the ATA pass through command packet for ATA
76 transaction.
77
78 @param[in, out] AtaDevice The ATA child device involved for the operation.
79 @param[in, out] TaskPacket Pointer to a Pass Thru Command Packet. Optional,
80 if it is NULL, blocking mode, and use the packet
81 in AtaDevice. If it is not NULL, non blocking mode,
82 and pass down this Packet.
83 @param[in] Event If Event is NULL, then blocking I/O is performed.
84 If Event is not NULL and non-blocking I/O is
85 supported,then non-blocking I/O is performed,
86 and Event will be signaled when the write
87 request is completed.
88
89 @return The return status from EFI_ATA_PASS_THRU_PROTOCOL.PassThru().
90
91 **/
92 EFI_STATUS
93 AtaDevicePassThru (
94 IN OUT ATA_DEVICE *AtaDevice,
95 IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *TaskPacket, OPTIONAL
96 IN OUT EFI_EVENT Event OPTIONAL
97 )
98 {
99 EFI_STATUS Status;
100 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;
101 EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;
102
103 //
104 // Assemble packet. If it is non blocking mode, the Ata driver should keep each
105 // subtask and clean them when the event is signaled.
106 //
107 if (TaskPacket != NULL) {
108 Packet = TaskPacket;
109 Packet->Asb = AllocateAlignedBuffer (AtaDevice, sizeof (*AtaDevice->Asb));
110 CopyMem (Packet->Asb, AtaDevice->Asb, sizeof (*AtaDevice->Asb));
111 Packet->Acb = AllocateCopyPool(sizeof (EFI_ATA_COMMAND_BLOCK), &AtaDevice->Acb);
112 } else {
113 Packet = &AtaDevice->Packet;
114 Packet->Asb = AtaDevice->Asb;
115 Packet->Acb = &AtaDevice->Acb;
116 }
117
118 AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;
119
120 Status = AtaPassThru->PassThru (
121 AtaPassThru,
122 AtaDevice->Port,
123 AtaDevice->PortMultiplierPort,
124 Packet,
125 Event
126 );
127 //
128 // Ensure ATA pass through caller and callee have the same
129 // interpretation of ATA pass through protocol.
130 //
131 ASSERT (Status != EFI_INVALID_PARAMETER);
132 ASSERT (Status != EFI_BAD_BUFFER_SIZE);
133
134 return Status;
135 }
136
137
138 /**
139 Wrapper for EFI_ATA_PASS_THRU_PROTOCOL.ResetDevice().
140
141 This function wraps the ResetDevice() invocation for ATA pass through function
142 for an ATA device.
143
144 @param AtaDevice The ATA child device involved for the operation.
145
146 @return The return status from EFI_ATA_PASS_THRU_PROTOCOL.PassThru().
147
148 **/
149 EFI_STATUS
150 ResetAtaDevice (
151 IN ATA_DEVICE *AtaDevice
152 )
153 {
154 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;
155
156 AtaPassThru = AtaDevice->AtaBusDriverData->AtaPassThru;
157
158 return AtaPassThru->ResetDevice (
159 AtaPassThru,
160 AtaDevice->Port,
161 AtaDevice->PortMultiplierPort
162 );
163 }
164
165
166 /**
167 Prints ATA model name to ATA device structure.
168
169 This function converts ATA device model name from ATA identify data
170 to a string in ATA device structure. It needs to change the character
171 order in the original model name string.
172
173 @param AtaDevice The ATA child device involved for the operation.
174
175 **/
176 VOID
177 PrintAtaModelName (
178 IN OUT ATA_DEVICE *AtaDevice
179 )
180 {
181 UINTN Index;
182 CHAR8 *Source;
183 CHAR16 *Destination;
184
185 Source = AtaDevice->IdentifyData->ModelName;
186 Destination = AtaDevice->ModelName;
187
188 //
189 // Swap the byte order in the original module name.
190 //
191 for (Index = 0; Index < MAX_MODEL_NAME_LEN; Index += 2) {
192 Destination[Index] = Source[Index + 1];
193 Destination[Index + 1] = Source[Index];
194 }
195 AtaDevice->ModelName[MAX_MODEL_NAME_LEN] = L'\0';
196 }
197
198
199 /**
200 Gets ATA device Capacity according to ATA 6.
201
202 This function returns the capacity of the ATA device if it follows
203 ATA 6 to support 48 bit addressing.
204
205 @param AtaDevice The ATA child device involved for the operation.
206
207 @return The capacity of the ATA device or 0 if the device does not support
208 48-bit addressing defined in ATA 6.
209
210 **/
211 EFI_LBA
212 GetAtapi6Capacity (
213 IN ATA_DEVICE *AtaDevice
214 )
215 {
216 EFI_LBA Capacity;
217 EFI_LBA TmpLba;
218 UINTN Index;
219 ATA_IDENTIFY_DATA *IdentifyData;
220
221 IdentifyData = AtaDevice->IdentifyData;
222 if ((IdentifyData->command_set_supported_83 & BIT10) == 0) {
223 //
224 // The device doesn't support 48 bit addressing
225 //
226 return 0;
227 }
228
229 //
230 // 48 bit address feature set is supported, get maximum capacity
231 //
232 Capacity = 0;
233 for (Index = 0; Index < 4; Index++) {
234 //
235 // Lower byte goes first: word[100] is the lowest word, word[103] is highest
236 //
237 TmpLba = IdentifyData->maximum_lba_for_48bit_addressing[Index];
238 Capacity |= LShiftU64 (TmpLba, 16 * Index);
239 }
240
241 return Capacity;
242 }
243
244
245 /**
246 Identifies ATA device via the Identify data.
247
248 This function identifies the ATA device and initializes the Media information in
249 Block IO protocol interface.
250
251 @param AtaDevice The ATA child device involved for the operation.
252
253 @retval EFI_UNSUPPORTED The device is not a valid ATA device (hard disk).
254 @retval EFI_SUCCESS The device is successfully identified and Media information
255 is correctly initialized.
256
257 **/
258 EFI_STATUS
259 IdentifyAtaDevice (
260 IN OUT ATA_DEVICE *AtaDevice
261 )
262 {
263 ATA_IDENTIFY_DATA *IdentifyData;
264 EFI_BLOCK_IO_MEDIA *BlockMedia;
265 EFI_LBA Capacity;
266 UINT16 PhyLogicSectorSupport;
267 UINT16 UdmaMode;
268
269 IdentifyData = AtaDevice->IdentifyData;
270
271 if ((IdentifyData->config & BIT15) != 0) {
272 //
273 // This is not an hard disk
274 //
275 return EFI_UNSUPPORTED;
276 }
277
278 DEBUG ((EFI_D_INFO, "AtaBus - Identify Device (%x %x)\n", (UINTN)AtaDevice->Port, (UINTN)AtaDevice->PortMultiplierPort));
279
280 //
281 // Check whether the WORD 88 (supported UltraDMA by drive) is valid
282 //
283 if ((IdentifyData->field_validity & BIT2) != 0) {
284 UdmaMode = IdentifyData->ultra_dma_mode;
285 if ((UdmaMode & (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6)) != 0) {
286 //
287 // If BIT0~BIT6 is selected, then UDMA is supported
288 //
289 AtaDevice->UdmaValid = TRUE;
290 }
291 }
292
293 Capacity = GetAtapi6Capacity (AtaDevice);
294 if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) {
295 //
296 // Capacity exceeds 120GB. 48-bit addressing is really needed
297 //
298 AtaDevice->Lba48Bit = TRUE;
299 } else {
300 //
301 // This is a hard disk <= 120GB capacity, treat it as normal hard disk
302 //
303 Capacity = ((UINT32)IdentifyData->user_addressable_sectors_hi << 16) | IdentifyData->user_addressable_sectors_lo;
304 AtaDevice->Lba48Bit = FALSE;
305 }
306
307 //
308 // Block Media Information:
309 //
310 BlockMedia = &AtaDevice->BlockMedia;
311 BlockMedia->LastBlock = Capacity - 1;
312 BlockMedia->IoAlign = AtaDevice->AtaBusDriverData->AtaPassThru->Mode->IoAlign;
313 //
314 // Check whether Long Physical Sector Feature is supported
315 //
316 PhyLogicSectorSupport = IdentifyData->phy_logic_sector_support;
317 if ((PhyLogicSectorSupport & (BIT14 | BIT15)) == BIT14) {
318 //
319 // Check whether one physical block contains multiple physical blocks
320 //
321 if ((PhyLogicSectorSupport & BIT13) != 0) {
322 BlockMedia->LogicalBlocksPerPhysicalBlock = (UINT32) (1 << (PhyLogicSectorSupport & 0x000f));
323 //
324 // Check lowest alignment of logical blocks within physical block
325 //
326 if ((IdentifyData->alignment_logic_in_phy_blocks & (BIT14 | BIT15)) == BIT14) {
327 BlockMedia->LowestAlignedLba = (EFI_LBA) ((BlockMedia->LogicalBlocksPerPhysicalBlock - ((UINT32)IdentifyData->alignment_logic_in_phy_blocks & 0x3fff)) %
328 BlockMedia->LogicalBlocksPerPhysicalBlock);
329 }
330 }
331 //
332 // Check logical block size
333 //
334 if ((PhyLogicSectorSupport & BIT12) != 0) {
335 BlockMedia->BlockSize = (UINT32) (((IdentifyData->logic_sector_size_hi << 16) | IdentifyData->logic_sector_size_lo) * sizeof (UINT16));
336 }
337 AtaDevice->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2;
338 }
339 //
340 // Get ATA model name from identify data structure.
341 //
342 PrintAtaModelName (AtaDevice);
343
344 return EFI_SUCCESS;
345 }
346
347
348 /**
349 Discovers whether it is a valid ATA device.
350
351 This function issues ATA_CMD_IDENTIFY_DRIVE command to the ATA device to identify it.
352 If the command is executed successfully, it then identifies it and initializes
353 the Media information in Block IO protocol interface.
354
355 @param AtaDevice The ATA child device involved for the operation.
356
357 @retval EFI_SUCCESS The device is successfully identified and Media information
358 is correctly initialized.
359 @return others Some error occurs when discovering the ATA device.
360
361 **/
362 EFI_STATUS
363 DiscoverAtaDevice (
364 IN OUT ATA_DEVICE *AtaDevice
365 )
366 {
367 EFI_STATUS Status;
368 EFI_ATA_COMMAND_BLOCK *Acb;
369 EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;
370 UINTN Retry;
371
372 //
373 // Prepare for ATA command block.
374 //
375 Acb = ZeroMem (&AtaDevice->Acb, sizeof (*Acb));
376 Acb->AtaCommand = ATA_CMD_IDENTIFY_DRIVE;
377 Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));
378
379 //
380 // Prepare for ATA pass through packet.
381 //
382 Packet = ZeroMem (&AtaDevice->Packet, sizeof (*Packet));
383 Packet->InDataBuffer = AtaDevice->IdentifyData;
384 Packet->InTransferLength = sizeof (*AtaDevice->IdentifyData);
385 Packet->Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN;
386 Packet->Length = EFI_ATA_PASS_THRU_LENGTH_BYTES | EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;
387 Packet->Timeout = ATA_TIMEOUT;
388
389 Retry = MAX_RETRY_TIMES;
390 do {
391 Status = AtaDevicePassThru (AtaDevice, NULL, NULL);
392 if (!EFI_ERROR (Status)) {
393 //
394 // The command is issued successfully
395 //
396 Status = IdentifyAtaDevice (AtaDevice);
397 if (!EFI_ERROR (Status)) {
398 return Status;
399 }
400 }
401 } while (Retry-- > 0);
402
403 return Status;
404 }
405
406 /**
407 Transfer data from ATA device.
408
409 This function performs one ATA pass through transaction to transfer data from/to
410 ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru
411 interface of ATA pass through.
412
413 @param[in, out] AtaDevice The ATA child device involved for the operation.
414 @param[in, out] TaskPacket Pointer to a Pass Thru Command Packet. Optional,
415 if it is NULL, blocking mode, and use the packet
416 in AtaDevice. If it is not NULL, non blocking mode,
417 and pass down this Packet.
418 @param[in, out] Buffer The pointer to the current transaction buffer.
419 @param[in] StartLba The starting logical block address to be accessed.
420 @param[in] TransferLength The block number or sector count of the transfer.
421 @param[in] IsWrite Indicates whether it is a write operation.
422 @param[in] Event If Event is NULL, then blocking I/O is performed.
423 If Event is not NULL and non-blocking I/O is
424 supported,then non-blocking I/O is performed,
425 and Event will be signaled when the write
426 request is completed.
427
428 @retval EFI_SUCCESS The data transfer is complete successfully.
429 @return others Some error occurs when transferring data.
430
431 **/
432 EFI_STATUS
433 TransferAtaDevice (
434 IN OUT ATA_DEVICE *AtaDevice,
435 IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *TaskPacket, OPTIONAL
436 IN OUT VOID *Buffer,
437 IN EFI_LBA StartLba,
438 IN UINT32 TransferLength,
439 IN BOOLEAN IsWrite,
440 IN EFI_EVENT Event OPTIONAL
441 )
442 {
443 EFI_ATA_COMMAND_BLOCK *Acb;
444 EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet;
445
446 //
447 // Ensure AtaDevice->UdmaValid, AtaDevice->Lba48Bit and IsWrite are valid boolean values
448 //
449 ASSERT ((UINTN) AtaDevice->UdmaValid < 2);
450 ASSERT ((UINTN) AtaDevice->Lba48Bit < 2);
451 ASSERT ((UINTN) IsWrite < 2);
452 //
453 // Prepare for ATA command block.
454 //
455 Acb = ZeroMem (&AtaDevice->Acb, sizeof (*Acb));
456 Acb->AtaCommand = mAtaCommands[AtaDevice->UdmaValid][AtaDevice->Lba48Bit][IsWrite];
457 Acb->AtaSectorNumber = (UINT8) StartLba;
458 Acb->AtaCylinderLow = (UINT8) RShiftU64 (StartLba, 8);
459 Acb->AtaCylinderHigh = (UINT8) RShiftU64 (StartLba, 16);
460 Acb->AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (AtaDevice->PortMultiplierPort << 4));
461 Acb->AtaSectorCount = (UINT8) TransferLength;
462 if (AtaDevice->Lba48Bit) {
463 Acb->AtaSectorNumberExp = (UINT8) RShiftU64 (StartLba, 24);
464 Acb->AtaCylinderLowExp = (UINT8) RShiftU64 (StartLba, 32);
465 Acb->AtaCylinderHighExp = (UINT8) RShiftU64 (StartLba, 40);
466 Acb->AtaSectorCountExp = (UINT8) (TransferLength >> 8);
467 } else {
468 Acb->AtaDeviceHead = (UINT8) (Acb->AtaDeviceHead | RShiftU64 (StartLba, 24));
469 }
470
471 //
472 // Prepare for ATA pass through packet.
473 //
474 if (TaskPacket != NULL) {
475 Packet = ZeroMem (TaskPacket, sizeof (*Packet));
476 } else {
477 Packet = ZeroMem (&AtaDevice->Packet, sizeof (*Packet));
478 }
479
480 if (IsWrite) {
481 Packet->OutDataBuffer = Buffer;
482 Packet->OutTransferLength = TransferLength;
483 } else {
484 Packet->InDataBuffer = Buffer;
485 Packet->InTransferLength = TransferLength;
486 }
487
488 Packet->Protocol = mAtaPassThruCmdProtocols[AtaDevice->UdmaValid][IsWrite];
489 Packet->Length = EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;
490 Packet->Timeout = ATA_TIMEOUT;
491
492 return AtaDevicePassThru (AtaDevice, TaskPacket, Event);
493 }
494
495 /**
496 Free SubTask.
497
498 @param[in, out] Task Pointer to task to be freed.
499
500 **/
501 VOID
502 EFIAPI
503 FreeAtaSubTask (
504 IN ATA_BUS_ASYN_TASK *Task
505 )
506 {
507 if (Task->Packet.Asb != NULL) {
508 FreeAlignedBuffer (Task->Packet.Asb, sizeof (Task->Packet.Asb));
509 }
510 if (Task->Packet.Acb != NULL) {
511 FreePool (Task->Packet.Acb);
512 }
513
514 FreePool (Task);
515 }
516
517 /**
518 Call back funtion when the event is signaled.
519
520 @param[in] Event The Event this notify function registered to.
521 @param[in] Context Pointer to the context data registerd to the
522 Event.
523
524 **/
525 VOID
526 EFIAPI
527 AtaNonBlockingCallBack (
528 IN EFI_EVENT Event,
529 IN VOID *Context
530 )
531 {
532 ATA_BUS_ASYN_TASK *Task;
533
534 Task = (ATA_BUS_ASYN_TASK *) Context;
535 gBS->CloseEvent (Event);
536
537 //
538 // Check the command status.
539 // If there is error during the sub task source allocation, the error status
540 // should be returned to the caller directly, so here the Task->Token may already
541 // be deleted by the caller and no need to update the status.
542 //
543 if ((!(*Task->IsError)) && (Task->Packet.Asb->AtaStatus & 0x01) == 0x01) {
544 Task->Token->TransactionStatus = EFI_DEVICE_ERROR;
545 }
546 DEBUG ((
547 DEBUG_INFO,
548 "NON-BLOCKING EVENT FINISHED!- STATUS = %r\n",
549 Task->Token->TransactionStatus
550 ));
551
552 //
553 // Reduce the SubEventCount, till it comes to zero.
554 //
555 (*Task->UnsignalledEventCount) --;
556 DEBUG ((DEBUG_INFO, "UnsignalledEventCount = %x\n", *Task->UnsignalledEventCount));
557
558 //
559 // Remove the SubTask from the Task list.
560 //
561 RemoveEntryList (&Task->TaskEntry);
562 if ((*Task->UnsignalledEventCount) == 0) {
563 //
564 // All Sub tasks are done, then signal the upper layyer event.
565 // Except there is error during the sub task source allocation.
566 //
567 if (!(*Task->IsError)) {
568 gBS->SignalEvent (Task->Token->Event);
569 DEBUG ((DEBUG_INFO, "Signal Up Level Event UnsignalledEventCount = %x!\n", *Task->UnsignalledEventCount));
570 }
571
572 FreePool (Task->UnsignalledEventCount);
573 FreePool (Task->IsError);
574 }
575
576 DEBUG ((
577 DEBUG_INFO,
578 "PACKET INFO: Write=%s, Lenght=%x, LowCylinder=%x, HighCylinder=%x,SectionNumber=%x",
579 Task->Packet.OutDataBuffer != NULL ? L"YES" : L"NO",
580 Task->Packet.OutDataBuffer != NULL ? Task->Packet.OutTransferLength : Task->Packet.InTransferLength,
581 Task->Packet.Acb->AtaCylinderLow,
582 Task->Packet.Acb->AtaCylinderHigh,
583 Task->Packet.Acb->AtaSectorCount
584 ));
585
586 //
587 // Free the buffer of SubTask.
588 //
589 FreeAtaSubTask (Task);
590 }
591
592 /**
593 Read or write a number of blocks from ATA device.
594
595 This function performs ATA pass through transactions to read/write data from/to
596 ATA device. It may separate the read/write request into several ATA pass through
597 transactions.
598
599 @param[in, out] AtaDevice The ATA child device involved for the operation.
600 @param[in, out] Buffer The pointer to the current transaction buffer.
601 @param[in] StartLba The starting logical block address to be accessed.
602 @param[in] NumberOfBlocks The block number or sector count of the transfer.
603 @param[in] IsWrite Indicates whether it is a write operation.
604 @param[in, out] Token A pointer to the token associated with the transaction.
605
606 @retval EFI_SUCCESS The data transfer is complete successfully.
607 @return others Some error occurs when transferring data.
608
609 **/
610 EFI_STATUS
611 AccessAtaDevice(
612 IN OUT ATA_DEVICE *AtaDevice,
613 IN OUT UINT8 *Buffer,
614 IN EFI_LBA StartLba,
615 IN UINTN NumberOfBlocks,
616 IN BOOLEAN IsWrite,
617 IN OUT EFI_BLOCK_IO2_TOKEN *Token
618 )
619 {
620 EFI_STATUS Status;
621 UINTN MaxTransferBlockNumber;
622 UINTN TransferBlockNumber;
623 UINTN BlockSize;
624 UINTN *EventCount;
625 UINTN TempCount;
626 ATA_BUS_ASYN_TASK *Task;
627 EFI_EVENT SubEvent;
628 UINTN Index;
629 BOOLEAN *IsError;
630 EFI_TPL OldTpl;
631
632 SubEvent = NULL;
633 TempCount = 0;
634 Status = EFI_SUCCESS;
635
636 EventCount = AllocateZeroPool (sizeof (UINTN));
637 if (EventCount == NULL) {
638 return EFI_OUT_OF_RESOURCES;
639 }
640
641 IsError = AllocateZeroPool (sizeof (BOOLEAN));
642 if (IsError == NULL) {
643 goto EXIT;
644 }
645 *IsError = FALSE;
646
647 //
648 // Initial the return status for Non Blocking.
649 //
650 if (Token != NULL && Token->Event != NULL) {
651 Token->TransactionStatus = EFI_SUCCESS;
652 }
653 //
654 // Ensure AtaDevice->Lba48Bit is a valid boolean value
655 //
656 ASSERT ((UINTN) AtaDevice->Lba48Bit < 2);
657 MaxTransferBlockNumber = mMaxTransferBlockNumber[AtaDevice->Lba48Bit];
658 BlockSize = AtaDevice->BlockMedia.BlockSize;
659
660 TempCount = (NumberOfBlocks + MaxTransferBlockNumber - 1) / MaxTransferBlockNumber;
661 *EventCount = TempCount;
662 Index = 0;
663
664 do {
665 if (NumberOfBlocks > MaxTransferBlockNumber) {
666 TransferBlockNumber = MaxTransferBlockNumber;
667 NumberOfBlocks -= MaxTransferBlockNumber;
668 } else {
669 TransferBlockNumber = NumberOfBlocks;
670 NumberOfBlocks = 0;
671 }
672
673 //
674 // Create sub event for the sub Ata task. Non-Blocking Mode.
675 //
676 if (Token != NULL && Token->Event != NULL) {
677 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
678 Task = AllocateZeroPool (sizeof (ATA_BUS_ASYN_TASK));
679 if (Task == NULL) {
680 //
681 // If resource allocation fail, reduce the total sub event counts.
682 //
683 *EventCount = (*EventCount) - (TempCount - Index);
684 *IsError = TRUE;
685 Token->TransactionStatus = EFI_OUT_OF_RESOURCES;
686 Status = EFI_OUT_OF_RESOURCES;
687
688 gBS->RestoreTPL (OldTpl);
689 goto EXIT;
690 }
691
692 Task->UnsignalledEventCount = EventCount;
693 Task->Token = Token;
694 Task->IsError = IsError;
695
696 InsertTailList (&AtaDevice->AtaTaskList, &Task->TaskEntry);
697
698 Status = gBS->CreateEvent (
699 EVT_NOTIFY_SIGNAL,
700 TPL_NOTIFY,
701 AtaNonBlockingCallBack,
702 Task,
703 &SubEvent
704 );
705 //
706 // If resource allocation fail, the un-signalled event count should equal to
707 // the original one minus the unassigned subtasks number.
708 //
709 if (EFI_ERROR (Status)) {
710 *EventCount = (*EventCount) - (TempCount - Index);
711 *IsError = TRUE;
712 gBS->RestoreTPL (OldTpl);
713 goto EXIT;
714 }
715 Index++;
716 gBS->RestoreTPL (OldTpl);
717
718 DEBUG ((EFI_D_INFO, "NON-BLOCKING SET EVENT START: WRITE = %d\n", IsWrite));
719 Status = TransferAtaDevice (AtaDevice, &Task->Packet, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, SubEvent);
720 DEBUG ((
721 EFI_D_INFO,
722 "NON-BLOCKING SET EVENT END:StartLba=%x, TransferBlockNumbers=%x, Status=%r\n",
723 StartLba,
724 TransferBlockNumber,
725 Status
726 ));
727 }else {
728 //
729 // Blocking Mode.
730 //
731 DEBUG ((EFI_D_INFO, "BLOCKING BLOCK I/O START: WRITE = %d\n", IsWrite));
732 Status = TransferAtaDevice (AtaDevice, NULL, Buffer, StartLba, (UINT32) TransferBlockNumber, IsWrite, NULL);
733 DEBUG ((
734 EFI_D_INFO,
735 "BLOCKING BLOCK I/O FINISHE - StartLba = %x; TransferBlockNumbers = %x, status = %r\n",
736 StartLba,
737 TransferBlockNumber,
738 Status
739 ));
740 }
741
742 if (EFI_ERROR (Status)) {
743 goto EXIT;
744 }
745
746 StartLba += TransferBlockNumber;
747 Buffer += TransferBlockNumber * BlockSize;
748 } while (NumberOfBlocks > 0);
749
750 EXIT:
751
752 if (*EventCount == 0) {
753 FreePool (EventCount);
754 FreePool (IsError);
755 }
756
757 return Status;
758 }