1 /** @file
2 PEIM to produce gEfiPeiVirtualBlockIoPpiGuid & gEfiPeiVirtualBlockIo2PpiGuid PPI for
3 ATA controllers in the platform.
4
5 This PPI can be consumed by PEIM which produce gEfiPeiDeviceRecoveryModulePpiGuid
6 for Atapi CD ROM device.
7
8 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
9
10 This program and the accompanying materials
11 are licensed and made available under the terms and conditions
12 of the BSD License which accompanies this distribution. The
13 full text of the license may be found at
14 http://opensource.org/licenses/bsd-license.php
15
16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18
19 **/
20
21 #include "AtapiPeim.h"
22
23 /**
24 Initializes the Atapi Block Io PPI.
25
26 @param[in] FileHandle Handle of the file being invoked.
27 @param[in] PeiServices Describes the list of possible PEI Services.
28
29 @retval EFI_SUCCESS Operation performed successfully.
30 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate.
31
32 **/
33 EFI_STATUS
34 EFIAPI
AtapiPeimEntry(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)35 AtapiPeimEntry (
36 IN EFI_PEI_FILE_HANDLE FileHandle,
37 IN CONST EFI_PEI_SERVICES **PeiServices
38 )
39 {
40 PEI_ATA_CONTROLLER_PPI *AtaControllerPpi;
41 EFI_STATUS Status;
42 ATAPI_BLK_IO_DEV *AtapiBlkIoDev;
43
44 Status = PeiServicesRegisterForShadow (FileHandle);
45 if (!EFI_ERROR (Status)) {
46 return Status;
47 }
48
49 Status = PeiServicesLocatePpi (
50 &gPeiAtaControllerPpiGuid,
51 0,
52 NULL,
53 (VOID **) &AtaControllerPpi
54 );
55 ASSERT_EFI_ERROR (Status);
56
57 AtapiBlkIoDev = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (*AtapiBlkIoDev)));
58 if (AtapiBlkIoDev == NULL) {
59 return EFI_OUT_OF_RESOURCES;
60 }
61
62 AtapiBlkIoDev->Signature = ATAPI_BLK_IO_DEV_SIGNATURE;
63 AtapiBlkIoDev->AtaControllerPpi = AtaControllerPpi;
64
65 //
66 // atapi device enumeration and build private data
67 //
68 AtapiEnumerateDevices (AtapiBlkIoDev);
69
70 AtapiBlkIoDev->AtapiBlkIo.GetNumberOfBlockDevices = AtapiGetNumberOfBlockDevices;
71 AtapiBlkIoDev->AtapiBlkIo.GetBlockDeviceMediaInfo = AtapiGetBlockDeviceMediaInfo;
72 AtapiBlkIoDev->AtapiBlkIo.ReadBlocks = AtapiReadBlocks;
73 AtapiBlkIoDev->AtapiBlkIo2.Revision = EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
74 AtapiBlkIoDev->AtapiBlkIo2.GetNumberOfBlockDevices = AtapiGetNumberOfBlockDevices2;
75 AtapiBlkIoDev->AtapiBlkIo2.GetBlockDeviceMediaInfo = AtapiGetBlockDeviceMediaInfo2;
76 AtapiBlkIoDev->AtapiBlkIo2.ReadBlocks = AtapiReadBlocks2;
77
78 AtapiBlkIoDev->PpiDescriptor.Flags = EFI_PEI_PPI_DESCRIPTOR_PPI;
79 AtapiBlkIoDev->PpiDescriptor.Guid = &gEfiPeiVirtualBlockIoPpiGuid;
80 AtapiBlkIoDev->PpiDescriptor.Ppi = &AtapiBlkIoDev->AtapiBlkIo;
81
82 AtapiBlkIoDev->PpiDescriptor2.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
83 AtapiBlkIoDev->PpiDescriptor2.Guid = &gEfiPeiVirtualBlockIo2PpiGuid;
84 AtapiBlkIoDev->PpiDescriptor2.Ppi = &AtapiBlkIoDev->AtapiBlkIo2;
85
86 DEBUG ((EFI_D_INFO, "Atatpi Device Count is %d\n", AtapiBlkIoDev->DeviceCount));
87 if (AtapiBlkIoDev->DeviceCount != 0) {
88 Status = PeiServicesInstallPpi (&AtapiBlkIoDev->PpiDescriptor);
89 if (EFI_ERROR (Status)) {
90 return EFI_OUT_OF_RESOURCES;
91 }
92 }
93
94 return EFI_SUCCESS;
95 }
96
97 /**
98 Gets the count of block I/O devices that one specific block driver detects.
99
100 This function is used for getting the count of block I/O devices that one
101 specific block driver detects. To the PEI ATAPI driver, it returns the number
102 of all the detected ATAPI devices it detects during the enumeration process.
103 To the PEI legacy floppy driver, it returns the number of all the legacy
104 devices it finds during its enumeration process. If no device is detected,
105 then the function will return zero.
106
107 @param[in] PeiServices General-purpose services that are available
108 to every PEIM.
109 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
110 instance.
111 @param[out] NumberBlockDevices The number of block I/O devices discovered.
112
113 @retval EFI_SUCCESS Operation performed successfully.
114
115 **/
116 EFI_STATUS
117 EFIAPI
AtapiGetNumberOfBlockDevices(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_RECOVERY_BLOCK_IO_PPI * This,OUT UINTN * NumberBlockDevices)118 AtapiGetNumberOfBlockDevices (
119 IN EFI_PEI_SERVICES **PeiServices,
120 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
121 OUT UINTN *NumberBlockDevices
122 )
123 {
124 ATAPI_BLK_IO_DEV *AtapiBlkIoDev;
125
126 AtapiBlkIoDev = NULL;
127
128 AtapiBlkIoDev = PEI_RECOVERY_ATAPI_FROM_BLKIO_THIS (This);
129
130 *NumberBlockDevices = AtapiBlkIoDev->DeviceCount;
131
132 return EFI_SUCCESS;
133 }
134
135 /**
136 Gets a block device's media information.
137
138 This function will provide the caller with the specified block device's media
139 information. If the media changes, calling this function will update the media
140 information accordingly.
141
142 @param[in] PeiServices General-purpose services that are available to every
143 PEIM
144 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
145 @param[in] DeviceIndex Specifies the block device to which the function wants
146 to talk. Because the driver that implements Block I/O
147 PPIs will manage multiple block devices, the PPIs that
148 want to talk to a single device must specify the
149 device index that was assigned during the enumeration
150 process. This index is a number from one to
151 NumberBlockDevices.
152 @param[out] MediaInfo The media information of the specified block media.
153 The caller is responsible for the ownership of this
154 data structure.
155
156 @retval EFI_SUCCESS Media information about the specified block device
157 was obtained successfully.
158 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware
159 error.
160 @retval Others Other failure occurs.
161
162 **/
163 EFI_STATUS
164 EFIAPI
AtapiGetBlockDeviceMediaInfo(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_RECOVERY_BLOCK_IO_PPI * This,IN UINTN DeviceIndex,OUT EFI_PEI_BLOCK_IO_MEDIA * MediaInfo)165 AtapiGetBlockDeviceMediaInfo (
166 IN EFI_PEI_SERVICES **PeiServices,
167 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
168 IN UINTN DeviceIndex,
169 OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
170 )
171 {
172 UINTN DeviceCount;
173 ATAPI_BLK_IO_DEV *AtapiBlkIoDev;
174 EFI_STATUS Status;
175 UINTN Index;
176
177 AtapiBlkIoDev = NULL;
178
179 if (This == NULL || MediaInfo == NULL) {
180 return EFI_INVALID_PARAMETER;
181 }
182
183 AtapiBlkIoDev = PEI_RECOVERY_ATAPI_FROM_BLKIO_THIS (This);
184
185 DeviceCount = AtapiBlkIoDev->DeviceCount;
186
187 //
188 // DeviceIndex is a value from 1 to NumberBlockDevices.
189 //
190 if ((DeviceIndex < 1) || (DeviceIndex > DeviceCount) || (DeviceIndex > MAX_IDE_DEVICES)) {
191 return EFI_INVALID_PARAMETER;
192 }
193
194 Index = DeviceIndex - 1;
195
196 //
197 // probe media and retrieve latest media information
198 //
199 DEBUG ((EFI_D_INFO, "Atatpi GetInfo DevicePosition is %d\n", AtapiBlkIoDev->DeviceInfo[Index].DevicePosition));
200 DEBUG ((EFI_D_INFO, "Atatpi GetInfo DeviceType is %d\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.DeviceType));
201 DEBUG ((EFI_D_INFO, "Atatpi GetInfo MediaPresent is %d\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.MediaPresent));
202 DEBUG ((EFI_D_INFO, "Atatpi GetInfo BlockSize is 0x%x\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.BlockSize));
203 DEBUG ((EFI_D_INFO, "Atatpi GetInfo LastBlock is 0x%x\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.LastBlock));
204
205 Status = DetectMedia (
206 AtapiBlkIoDev,
207 AtapiBlkIoDev->DeviceInfo[Index].DevicePosition,
208 &AtapiBlkIoDev->DeviceInfo[Index].MediaInfo,
209 &AtapiBlkIoDev->DeviceInfo[Index].MediaInfo2
210 );
211 if (Status != EFI_SUCCESS) {
212 return EFI_DEVICE_ERROR;
213 }
214
215 DEBUG ((EFI_D_INFO, "Atatpi GetInfo DevicePosition is %d\n", AtapiBlkIoDev->DeviceInfo[Index].DevicePosition));
216 DEBUG ((EFI_D_INFO, "Atatpi GetInfo DeviceType is %d\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.DeviceType));
217 DEBUG ((EFI_D_INFO, "Atatpi GetInfo MediaPresent is %d\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.MediaPresent));
218 DEBUG ((EFI_D_INFO, "Atatpi GetInfo BlockSize is 0x%x\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.BlockSize));
219 DEBUG ((EFI_D_INFO, "Atatpi GetInfo LastBlock is 0x%x\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.LastBlock));
220
221 //
222 // Get media info from AtapiBlkIoDev
223 //
224 CopyMem (MediaInfo, &AtapiBlkIoDev->DeviceInfo[Index].MediaInfo, sizeof(EFI_PEI_BLOCK_IO_MEDIA));
225
226 return EFI_SUCCESS;
227 }
228
229 /**
230 Reads the requested number of blocks from the specified block device.
231
232 The function reads the requested number of blocks from the device. All the
233 blocks are read, or an error is returned. If there is no media in the device,
234 the function returns EFI_NO_MEDIA.
235
236 @param[in] PeiServices General-purpose services that are available to
237 every PEIM.
238 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
239 @param[in] DeviceIndex Specifies the block device to which the function wants
240 to talk. Because the driver that implements Block I/O
241 PPIs will manage multiple block devices, the PPIs that
242 want to talk to a single device must specify the device
243 index that was assigned during the enumeration process.
244 This index is a number from one to NumberBlockDevices.
245 @param[in] StartLBA The starting logical block address (LBA) to read from
246 on the device
247 @param[in] BufferSize The size of the Buffer in bytes. This number must be
248 a multiple of the intrinsic block size of the device.
249 @param[out] Buffer A pointer to the destination buffer for the data.
250 The caller is responsible for the ownership of the
251 buffer.
252
253 @retval EFI_SUCCESS The data was read correctly from the device.
254 @retval EFI_DEVICE_ERROR The device reported an error while attempting
255 to perform the read operation.
256 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
257 valid, or the buffer is not properly aligned.
258 @retval EFI_NO_MEDIA There is no media in the device.
259 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
260 the intrinsic block size of the device.
261
262 **/
263 EFI_STATUS
264 EFIAPI
AtapiReadBlocks(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_RECOVERY_BLOCK_IO_PPI * This,IN UINTN DeviceIndex,IN EFI_PEI_LBA StartLBA,IN UINTN BufferSize,OUT VOID * Buffer)265 AtapiReadBlocks (
266 IN EFI_PEI_SERVICES **PeiServices,
267 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
268 IN UINTN DeviceIndex,
269 IN EFI_PEI_LBA StartLBA,
270 IN UINTN BufferSize,
271 OUT VOID *Buffer
272 )
273 {
274
275 EFI_PEI_BLOCK_IO_MEDIA MediaInfo;
276 EFI_STATUS Status;
277 UINTN NumberOfBlocks;
278 UINTN BlockSize;
279 ATAPI_BLK_IO_DEV *AtapiBlkIoDev;
280
281 AtapiBlkIoDev = NULL;
282
283 if (This == NULL) {
284 return EFI_INVALID_PARAMETER;
285 }
286
287 AtapiBlkIoDev = PEI_RECOVERY_ATAPI_FROM_BLKIO_THIS (This);
288
289 if (Buffer == NULL) {
290 return EFI_INVALID_PARAMETER;
291 }
292
293 if (BufferSize == 0) {
294 return EFI_SUCCESS;
295 }
296
297 Status = AtapiGetBlockDeviceMediaInfo (
298 PeiServices,
299 This,
300 DeviceIndex,
301 &MediaInfo
302 );
303 if (Status != EFI_SUCCESS) {
304 return EFI_DEVICE_ERROR;
305 }
306
307 if (!MediaInfo.MediaPresent) {
308 return EFI_NO_MEDIA;
309 }
310
311 BlockSize = MediaInfo.BlockSize;
312
313 if (BufferSize % BlockSize != 0) {
314 return EFI_BAD_BUFFER_SIZE;
315 }
316
317 NumberOfBlocks = BufferSize / BlockSize;
318
319 if ((StartLBA + NumberOfBlocks - 1) > AtapiBlkIoDev->DeviceInfo[DeviceIndex - 1].MediaInfo2.LastBlock) {
320 return EFI_INVALID_PARAMETER;
321 }
322
323 Status = ReadSectors (
324 AtapiBlkIoDev,
325 AtapiBlkIoDev->DeviceInfo[DeviceIndex - 1].DevicePosition,
326 Buffer,
327 StartLBA,
328 NumberOfBlocks,
329 BlockSize
330 );
331 if (EFI_ERROR (Status)) {
332 return EFI_DEVICE_ERROR;
333 }
334
335 return EFI_SUCCESS;
336 }
337
338 /**
339 Gets the count of block I/O devices that one specific block driver detects.
340
341 This function is used for getting the count of block I/O devices that one
342 specific block driver detects. To the PEI ATAPI driver, it returns the number
343 of all the detected ATAPI devices it detects during the enumeration process.
344 To the PEI legacy floppy driver, it returns the number of all the legacy
345 devices it finds during its enumeration process. If no device is detected,
346 then the function will return zero.
347
348 @param[in] PeiServices General-purpose services that are available
349 to every PEIM.
350 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
351 instance.
352 @param[out] NumberBlockDevices The number of block I/O devices discovered.
353
354 @retval EFI_SUCCESS Operation performed successfully.
355
356 **/
357 EFI_STATUS
358 EFIAPI
AtapiGetNumberOfBlockDevices2(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI * This,OUT UINTN * NumberBlockDevices)359 AtapiGetNumberOfBlockDevices2 (
360 IN EFI_PEI_SERVICES **PeiServices,
361 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
362 OUT UINTN *NumberBlockDevices
363 )
364 {
365 EFI_STATUS Status;
366 ATAPI_BLK_IO_DEV *AtapiBlkIoDev;
367
368 AtapiBlkIoDev = PEI_RECOVERY_ATAPI_FROM_BLKIO2_THIS (This);
369
370 Status = AtapiGetNumberOfBlockDevices (
371 PeiServices,
372 &AtapiBlkIoDev->AtapiBlkIo,
373 NumberBlockDevices
374 );
375
376 return Status;
377 }
378
379 /**
380 Gets a block device's media information.
381
382 This function will provide the caller with the specified block device's media
383 information. If the media changes, calling this function will update the media
384 information accordingly.
385
386 @param[in] PeiServices General-purpose services that are available to every
387 PEIM
388 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
389 @param[in] DeviceIndex Specifies the block device to which the function wants
390 to talk. Because the driver that implements Block I/O
391 PPIs will manage multiple block devices, the PPIs that
392 want to talk to a single device must specify the
393 device index that was assigned during the enumeration
394 process. This index is a number from one to
395 NumberBlockDevices.
396 @param[out] MediaInfo The media information of the specified block media.
397 The caller is responsible for the ownership of this
398 data structure.
399
400 @retval EFI_SUCCESS Media information about the specified block device
401 was obtained successfully.
402 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware
403 error.
404 @retval Others Other failure occurs.
405
406 **/
407 EFI_STATUS
408 EFIAPI
AtapiGetBlockDeviceMediaInfo2(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI * This,IN UINTN DeviceIndex,OUT EFI_PEI_BLOCK_IO2_MEDIA * MediaInfo)409 AtapiGetBlockDeviceMediaInfo2 (
410 IN EFI_PEI_SERVICES **PeiServices,
411 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
412 IN UINTN DeviceIndex,
413 OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo
414 )
415 {
416 ATAPI_BLK_IO_DEV *AtapiBlkIoDev;
417 EFI_STATUS Status;
418 EFI_PEI_BLOCK_IO_MEDIA Media;
419
420 AtapiBlkIoDev = NULL;
421
422 if (This == NULL || MediaInfo == NULL) {
423 return EFI_INVALID_PARAMETER;
424 }
425
426 AtapiBlkIoDev = PEI_RECOVERY_ATAPI_FROM_BLKIO2_THIS (This);
427
428 Status = AtapiGetBlockDeviceMediaInfo (
429 PeiServices,
430 &AtapiBlkIoDev->AtapiBlkIo,
431 DeviceIndex,
432 &Media
433 );
434 if (EFI_ERROR (Status)) {
435 return Status;
436 }
437 //
438 // Get media info from AtapiBlkIoDev
439 //
440 CopyMem (MediaInfo, &AtapiBlkIoDev->DeviceInfo[DeviceIndex - 1].MediaInfo2, sizeof(EFI_PEI_BLOCK_IO2_MEDIA));
441
442 return EFI_SUCCESS;
443 }
444
445 /**
446 Reads the requested number of blocks from the specified block device.
447
448 The function reads the requested number of blocks from the device. All the
449 blocks are read, or an error is returned. If there is no media in the device,
450 the function returns EFI_NO_MEDIA.
451
452 @param[in] PeiServices General-purpose services that are available to
453 every PEIM.
454 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
455 @param[in] DeviceIndex Specifies the block device to which the function wants
456 to talk. Because the driver that implements Block I/O
457 PPIs will manage multiple block devices, the PPIs that
458 want to talk to a single device must specify the device
459 index that was assigned during the enumeration process.
460 This index is a number from one to NumberBlockDevices.
461 @param[in] StartLBA The starting logical block address (LBA) to read from
462 on the device
463 @param[in] BufferSize The size of the Buffer in bytes. This number must be
464 a multiple of the intrinsic block size of the device.
465 @param[out] Buffer A pointer to the destination buffer for the data.
466 The caller is responsible for the ownership of the
467 buffer.
468
469 @retval EFI_SUCCESS The data was read correctly from the device.
470 @retval EFI_DEVICE_ERROR The device reported an error while attempting
471 to perform the read operation.
472 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
473 valid, or the buffer is not properly aligned.
474 @retval EFI_NO_MEDIA There is no media in the device.
475 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
476 the intrinsic block size of the device.
477
478 **/
479 EFI_STATUS
480 EFIAPI
AtapiReadBlocks2(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI * This,IN UINTN DeviceIndex,IN EFI_PEI_LBA StartLBA,IN UINTN BufferSize,OUT VOID * Buffer)481 AtapiReadBlocks2 (
482 IN EFI_PEI_SERVICES **PeiServices,
483 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
484 IN UINTN DeviceIndex,
485 IN EFI_PEI_LBA StartLBA,
486 IN UINTN BufferSize,
487 OUT VOID *Buffer
488 )
489 {
490 EFI_STATUS Status;
491 ATAPI_BLK_IO_DEV *AtapiBlkIoDev;
492
493 AtapiBlkIoDev = NULL;
494
495 if (This == NULL) {
496 return EFI_INVALID_PARAMETER;
497 }
498
499 AtapiBlkIoDev = PEI_RECOVERY_ATAPI_FROM_BLKIO2_THIS (This);
500
501 Status = AtapiReadBlocks (
502 PeiServices,
503 &AtapiBlkIoDev->AtapiBlkIo,
504 DeviceIndex,
505 StartLBA,
506 BufferSize,
507 Buffer
508 );
509
510 return Status;
511 }
512
513
514 /**
515 Enumerate Atapi devices.
516
517 This function is used to enumerate Atatpi device in Ide channel.
518
519 @param[in] AtapiBlkIoDev A pointer to atapi block IO device
520
521 **/
522 VOID
AtapiEnumerateDevices(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev)523 AtapiEnumerateDevices (
524 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev
525 )
526 {
527 UINT8 Index1;
528 UINT8 Index2;
529 UINTN DevicePosition;
530 EFI_PEI_BLOCK_IO_MEDIA MediaInfo;
531 EFI_PEI_BLOCK_IO2_MEDIA MediaInfo2;
532 EFI_STATUS Status;
533 UINTN DeviceCount;
534 UINT16 CommandBlockBaseAddr;
535 UINT16 ControlBlockBaseAddr;
536 UINT32 IdeEnabledNumber;
537 IDE_REGS_BASE_ADDR IdeRegsBaseAddr[MAX_IDE_CHANNELS];
538
539 DeviceCount = 0;
540 DevicePosition = 0;
541
542 //
543 // Scan IDE bus for ATAPI devices
544 //
545
546 //
547 // Enable Sata and IDE controller.
548 //
549 AtapiBlkIoDev->AtaControllerPpi->EnableAtaChannel (
550 (EFI_PEI_SERVICES **) GetPeiServicesTablePointer(),
551 AtapiBlkIoDev->AtaControllerPpi,
552 PEI_ICH_IDE_PRIMARY | PEI_ICH_IDE_SECONDARY
553 );
554
555 //
556 // Allow SATA Devices to spin-up. This is needed if
557 // SEC and PEI phase is too short, for example Release Build.
558 //
559 DEBUG ((EFI_D_INFO, "Delay for %d seconds for SATA devices to spin-up\n", PcdGet16 (PcdSataSpinUpDelayInSecForRecoveryPath)));
560 MicroSecondDelay (PcdGet16 (PcdSataSpinUpDelayInSecForRecoveryPath) * 1000 * 1000); //
561
562 //
563 // Get four channels (primary or secondary Pata, Sata Channel) Command and Control Regs Base address.
564 //
565 IdeEnabledNumber = AtapiBlkIoDev->AtaControllerPpi->GetIdeRegsBaseAddr (
566 (EFI_PEI_SERVICES **) GetPeiServicesTablePointer(),
567 AtapiBlkIoDev->AtaControllerPpi,
568 IdeRegsBaseAddr
569 );
570
571 //
572 // Using Command and Control Regs Base Address to fill other registers.
573 //
574 for (Index1 = 0; Index1 < IdeEnabledNumber; Index1 ++) {
575 CommandBlockBaseAddr = IdeRegsBaseAddr[Index1].CommandBlockBaseAddr;
576 AtapiBlkIoDev->IdeIoPortReg[Index1].Data = CommandBlockBaseAddr;
577 AtapiBlkIoDev->IdeIoPortReg[Index1].Reg1.Feature = (UINT16) (CommandBlockBaseAddr + 0x1);
578 AtapiBlkIoDev->IdeIoPortReg[Index1].SectorCount = (UINT16) (CommandBlockBaseAddr + 0x2);
579 AtapiBlkIoDev->IdeIoPortReg[Index1].SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x3);
580 AtapiBlkIoDev->IdeIoPortReg[Index1].CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x4);
581 AtapiBlkIoDev->IdeIoPortReg[Index1].CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x5);
582 AtapiBlkIoDev->IdeIoPortReg[Index1].Head = (UINT16) (CommandBlockBaseAddr + 0x6);
583 AtapiBlkIoDev->IdeIoPortReg[Index1].Reg.Command = (UINT16) (CommandBlockBaseAddr + 0x7);
584
585 ControlBlockBaseAddr = IdeRegsBaseAddr[Index1].ControlBlockBaseAddr;
586 AtapiBlkIoDev->IdeIoPortReg[Index1].Alt.DeviceControl = ControlBlockBaseAddr;
587 AtapiBlkIoDev->IdeIoPortReg[Index1].DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x1);
588
589 //
590 // Scan IDE bus for ATAPI devices IDE or Sata device
591 //
592 for (Index2 = IdeMaster; Index2 < IdeMaxDevice; Index2++) {
593 //
594 // Pata & Sata, Primary & Secondary channel, Master & Slave device
595 //
596 DevicePosition = (UINTN) (Index1 * 2 + Index2);
597
598 if (DiscoverAtapiDevice (AtapiBlkIoDev, DevicePosition, &MediaInfo, &MediaInfo2)) {
599 //
600 // ATAPI Device at DevicePosition is found.
601 //
602 AtapiBlkIoDev->DeviceInfo[DeviceCount].DevicePosition = DevicePosition;
603 //
604 // Retrieve Media Info
605 //
606 Status = DetectMedia (AtapiBlkIoDev, DevicePosition, &MediaInfo, &MediaInfo2);
607 CopyMem (&(AtapiBlkIoDev->DeviceInfo[DeviceCount].MediaInfo), &MediaInfo, sizeof (MediaInfo));
608 CopyMem (&(AtapiBlkIoDev->DeviceInfo[DeviceCount].MediaInfo2), &MediaInfo2, sizeof (MediaInfo2));
609
610 DEBUG ((EFI_D_INFO, "Atatpi Device Position is %d\n", DevicePosition));
611 DEBUG ((EFI_D_INFO, "Atatpi DeviceType is %d\n", MediaInfo.DeviceType));
612 DEBUG ((EFI_D_INFO, "Atatpi MediaPresent is %d\n", MediaInfo.MediaPresent));
613 DEBUG ((EFI_D_INFO, "Atatpi BlockSize is 0x%x\n", MediaInfo.BlockSize));
614
615 if (EFI_ERROR (Status)) {
616 AtapiBlkIoDev->DeviceInfo[DeviceCount].MediaInfo.MediaPresent = FALSE;
617 AtapiBlkIoDev->DeviceInfo[DeviceCount].MediaInfo.LastBlock = 0;
618 AtapiBlkIoDev->DeviceInfo[DeviceCount].MediaInfo2.MediaPresent = FALSE;
619 AtapiBlkIoDev->DeviceInfo[DeviceCount].MediaInfo2.LastBlock = 0;
620 }
621 DeviceCount += 1;
622 }
623 }
624 }
625
626 AtapiBlkIoDev->DeviceCount = DeviceCount;
627 }
628
629 /**
630 Detect Atapi devices.
631
632 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
633 @param[in] DevicePosition An integer to signify device position.
634 @param[out] MediaInfo The media information of the specified block media.
635 @param[out] MediaInfo2 The media information 2 of the specified block media.
636
637 @retval TRUE Atapi device exists in specified position.
638 @retval FALSE Atapi device does not exist in specified position.
639
640 **/
641 BOOLEAN
DiscoverAtapiDevice(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,OUT EFI_PEI_BLOCK_IO_MEDIA * MediaInfo,OUT EFI_PEI_BLOCK_IO2_MEDIA * MediaInfo2)642 DiscoverAtapiDevice (
643 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
644 IN UINTN DevicePosition,
645 OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo,
646 OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo2
647 )
648 {
649 EFI_STATUS Status;
650
651 if (!DetectIDEController (AtapiBlkIoDev, DevicePosition)) {
652 return FALSE;
653 }
654 //
655 // test if it is an ATAPI device (only supported device)
656 //
657 if (ATAPIIdentify (AtapiBlkIoDev, DevicePosition) == EFI_SUCCESS) {
658
659 Status = Inquiry (AtapiBlkIoDev, DevicePosition, MediaInfo, MediaInfo2);
660 if (!EFI_ERROR (Status)) {
661 return TRUE;
662 }
663 }
664
665 return FALSE;
666 }
667
668 /**
669 Check power mode of Atapi devices.
670
671 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
672 @param[in] DevicePosition An integer to signify device position.
673 @param[in] AtaCommand The Ata Command passed in.
674
675 @retval EFI_SUCCESS The Atapi device support power mode.
676 @retval EFI_NOT_FOUND The Atapi device not found.
677 @retval EFI_TIMEOUT Atapi command transaction is time out.
678 @retval EFI_ABORTED Atapi command abort.
679
680 **/
681 EFI_STATUS
CheckPowerMode(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,IN UINT8 AtaCommand)682 CheckPowerMode (
683 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
684 IN UINTN DevicePosition,
685 IN UINT8 AtaCommand
686 )
687 {
688 UINT8 Channel;
689 UINT8 Device;
690 UINT16 StatusRegister;
691 UINT16 HeadRegister;
692 UINT16 CommandRegister;
693 UINT16 ErrorRegister;
694 UINT16 SectorCountRegister;
695 EFI_STATUS Status;
696 UINT8 StatusValue;
697 UINT8 ErrorValue;
698 UINT8 SectorCountValue;
699
700 Channel = (UINT8) (DevicePosition / 2);
701 Device = (UINT8) (DevicePosition % 2);
702
703 ASSERT (Channel < MAX_IDE_CHANNELS);
704
705 StatusRegister = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Status;
706 HeadRegister = AtapiBlkIoDev->IdeIoPortReg[Channel].Head;
707 CommandRegister = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Command;
708 ErrorRegister = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg1.Error;
709 SectorCountRegister = AtapiBlkIoDev->IdeIoPortReg[Channel].SectorCount;
710
711 //
712 // select device
713 //
714 IoWrite8 (HeadRegister, (UINT8) ((Device << 4) | 0xe0));
715
716 //
717 // refresh the SectorCount register
718 //
719 SectorCountValue = 0x55;
720 IoWrite8 (SectorCountRegister, SectorCountValue);
721
722 //
723 // select device
724 //
725 IoWrite8 (HeadRegister, (UINT8) ((Device << 4) | 0xe0));
726
727 Status = DRDYReady (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), 100);
728
729 //
730 // select device
731 //
732 IoWrite8 (HeadRegister, (UINT8) ((Device << 4) | 0xe0));
733 //
734 // send 'check power' commandd via Command Register
735 //
736 IoWrite8 (CommandRegister, AtaCommand);
737
738 Status = WaitForBSYClear (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), 3000);
739 if (EFI_ERROR (Status)) {
740 return EFI_TIMEOUT;
741 }
742
743 StatusValue = IoRead8 (StatusRegister);
744
745 //
746 // command returned status is DRDY, indicating device supports the command,
747 // so device is present.
748 //
749 if ((StatusValue & ATA_STSREG_DRDY) == ATA_STSREG_DRDY) {
750 return EFI_SUCCESS;
751 }
752
753 SectorCountValue = IoRead8 (SectorCountRegister);
754
755 //
756 // command returned status is ERR & ABRT_ERR, indicating device does not support
757 // the command, so device is present.
758 //
759 if ((StatusValue & ATA_STSREG_ERR) == ATA_STSREG_ERR) {
760 ErrorValue = IoRead8 (ErrorRegister);
761 if ((ErrorValue & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
762 return EFI_ABORTED;
763 } else {
764 //
765 // According to spec, no other error code is valid
766 //
767 return EFI_NOT_FOUND;
768 }
769 }
770
771 if ((SectorCountValue == 0x00) || (SectorCountValue == 0x80) || (SectorCountValue == 0xff)) {
772 //
773 // Write SectorCount 0x55 but return valid state value. Maybe no device
774 // exists or some slow kind of ATAPI device exists.
775 //
776 IoWrite8 (HeadRegister, (UINT8) ((Device << 4) | 0xe0));
777
778 //
779 // write 0x55 and 0xaa to SectorCounter register,
780 // if the data could be written into the register,
781 // indicating the device is present, otherwise the device is not present.
782 //
783 SectorCountValue = 0x55;
784 IoWrite8 (SectorCountRegister, SectorCountValue);
785 MicroSecondDelay (10000);
786
787 SectorCountValue = IoRead8 (SectorCountRegister);
788 if (SectorCountValue != 0x55) {
789 return EFI_NOT_FOUND;
790 }
791 //
792 // Send a "ATAPI TEST UNIT READY" command ... slow but accurate
793 //
794 Status = TestUnitReady (AtapiBlkIoDev, DevicePosition);
795 return Status;
796 }
797
798 return EFI_NOT_FOUND;
799 }
800
801 /**
802 Detect if an IDE controller exists in specified position.
803
804 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
805 @param[in] DevicePosition An integer to signify device position.
806
807 @retval TRUE The Atapi device exists.
808 @retval FALSE The Atapi device does not present.
809
810 **/
811 BOOLEAN
DetectIDEController(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition)812 DetectIDEController (
813 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
814 IN UINTN DevicePosition
815 )
816 {
817 UINT8 Channel;
818 EFI_STATUS Status;
819 UINT8 AtaCommand;
820
821 Channel = (UINT8) (DevicePosition / 2);
822
823 ASSERT (Channel < MAX_IDE_CHANNELS);
824 //
825 // Wait 31 seconds for BSY clear
826 //
827 Status = WaitForBSYClear (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), 31000);
828 if (EFI_ERROR (Status)) {
829 return FALSE;
830 }
831 //
832 // Send 'check power' command for IDE device
833 //
834 AtaCommand = 0xE5;
835 Status = CheckPowerMode (AtapiBlkIoDev, DevicePosition, AtaCommand);
836 if ((Status == EFI_ABORTED) || (Status == EFI_SUCCESS)) {
837 return TRUE;
838 }
839
840 return FALSE;
841 }
842
843 /**
844 Wait specified time interval to poll for BSY bit clear in the Status Register.
845
846 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
847 @param[in] IdeIoRegisters A pointer to IDE IO registers.
848 @param[in] TimeoutInMilliSeconds Time specified in milliseconds.
849
850 @retval EFI_SUCCESS BSY bit is cleared in the specified time interval.
851 @retval EFI_TIMEOUT BSY bit is not cleared in the specified time interval.
852
853 **/
854 EFI_STATUS
WaitForBSYClear(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN IDE_BASE_REGISTERS * IdeIoRegisters,IN UINTN TimeoutInMilliSeconds)855 WaitForBSYClear (
856 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
857 IN IDE_BASE_REGISTERS *IdeIoRegisters,
858 IN UINTN TimeoutInMilliSeconds
859 )
860 {
861 UINTN Delay;
862 UINT16 StatusRegister;
863 UINT8 StatusValue;
864
865 StatusValue = 0;
866
867 StatusRegister = IdeIoRegisters->Reg.Status;
868
869 Delay = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
870 do {
871 StatusValue = IoRead8 (StatusRegister);
872 if ((StatusValue & ATA_STSREG_BSY) == 0x00) {
873 break;
874 }
875 MicroSecondDelay (250);
876
877 Delay--;
878
879 } while (Delay != 0);
880
881 if (Delay == 0) {
882 return EFI_TIMEOUT;
883 }
884
885 return EFI_SUCCESS;
886 }
887
888 /**
889 Wait specified time interval to poll for DRDY bit set in the Status register.
890
891 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
892 @param[in] IdeIoRegisters A pointer to IDE IO registers.
893 @param[in] TimeoutInMilliSeconds Time specified in milliseconds.
894
895 @retval EFI_SUCCESS DRDY bit is set in the specified time interval.
896 @retval EFI_TIMEOUT DRDY bit is not set in the specified time interval.
897
898 **/
899 EFI_STATUS
DRDYReady(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN IDE_BASE_REGISTERS * IdeIoRegisters,IN UINTN TimeoutInMilliSeconds)900 DRDYReady (
901 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
902 IN IDE_BASE_REGISTERS *IdeIoRegisters,
903 IN UINTN TimeoutInMilliSeconds
904 )
905 {
906 UINTN Delay;
907 UINT16 StatusRegister;
908 UINT8 StatusValue;
909 UINT8 ErrValue;
910
911 StatusValue = 0;
912
913 StatusRegister = IdeIoRegisters->Reg.Status;
914
915 Delay = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
916 do {
917 StatusValue = IoRead8 (StatusRegister);
918 //
919 // BSY == 0 , DRDY == 1
920 //
921 if ((StatusValue & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) {
922 break;
923 }
924
925 if ((StatusValue & (ATA_STSREG_ERR | ATA_STSREG_BSY)) == ATA_STSREG_ERR) {
926 ErrValue = IoRead8 (IdeIoRegisters->Reg1.Error);
927 if ((ErrValue & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
928 return EFI_ABORTED;
929 }
930 }
931
932 MicroSecondDelay (250);
933
934 Delay--;
935
936 } while (Delay != 0);
937
938 if (Delay == 0) {
939 return EFI_TIMEOUT;
940 }
941
942 return EFI_SUCCESS;
943 }
944
945 /**
946 Wait specified time interval to poll for DRQ bit clear in the Status Register.
947
948 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
949 @param[in] IdeIoRegisters A pointer to IDE IO registers.
950 @param[in] TimeoutInMilliSeconds Time specified in milliseconds.
951
952 @retval EFI_SUCCESS DRQ bit is cleared in the specified time interval.
953 @retval EFI_TIMEOUT DRQ bit is not cleared in the specified time interval.
954
955 **/
956 EFI_STATUS
DRQClear(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN IDE_BASE_REGISTERS * IdeIoRegisters,IN UINTN TimeoutInMilliSeconds)957 DRQClear (
958 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
959 IN IDE_BASE_REGISTERS *IdeIoRegisters,
960 IN UINTN TimeoutInMilliSeconds
961 )
962 {
963 UINTN Delay;
964 UINT16 StatusRegister;
965 UINT8 StatusValue;
966 UINT8 ErrValue;
967
968 StatusValue = 0;
969
970 StatusRegister = IdeIoRegisters->Reg.Status;
971
972 Delay = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
973 do {
974
975 StatusValue = IoRead8 (StatusRegister);
976
977 //
978 // wait for BSY == 0 and DRQ == 0
979 //
980 if ((StatusValue & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {
981 break;
982 }
983
984 if ((StatusValue & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
985 ErrValue = IoRead8 (IdeIoRegisters->Reg1.Error);
986 if ((ErrValue & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
987 return EFI_ABORTED;
988 }
989 }
990
991 MicroSecondDelay (250);
992
993 Delay--;
994 } while (Delay != 0);
995
996 if (Delay == 0) {
997 return EFI_TIMEOUT;
998 }
999
1000 return EFI_SUCCESS;
1001 }
1002
1003 /**
1004 Wait specified time interval to poll for DRQ bit clear in the Alternate Status Register.
1005
1006 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1007 @param[in] IdeIoRegisters A pointer to IDE IO registers.
1008 @param[in] TimeoutInMilliSeconds Time specified in milliseconds.
1009
1010 @retval EFI_SUCCESS DRQ bit is cleared in the specified time interval.
1011 @retval EFI_TIMEOUT DRQ bit is not cleared in the specified time interval.
1012
1013 **/
1014 EFI_STATUS
DRQClear2(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN IDE_BASE_REGISTERS * IdeIoRegisters,IN UINTN TimeoutInMilliSeconds)1015 DRQClear2 (
1016 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
1017 IN IDE_BASE_REGISTERS *IdeIoRegisters,
1018 IN UINTN TimeoutInMilliSeconds
1019 )
1020 {
1021 UINTN Delay;
1022 UINT16 AltStatusRegister;
1023 UINT8 AltStatusValue;
1024 UINT8 ErrValue;
1025
1026 AltStatusValue = 0;
1027
1028 AltStatusRegister = IdeIoRegisters->Alt.AltStatus;
1029
1030 Delay = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
1031 do {
1032
1033 AltStatusValue = IoRead8 (AltStatusRegister);
1034
1035 //
1036 // wait for BSY == 0 and DRQ == 0
1037 //
1038 if ((AltStatusValue & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {
1039 break;
1040 }
1041
1042 if ((AltStatusValue & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
1043 ErrValue = IoRead8 (IdeIoRegisters->Reg1.Error);
1044 if ((ErrValue & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
1045 return EFI_ABORTED;
1046 }
1047 }
1048
1049 MicroSecondDelay (250);
1050
1051 Delay--;
1052 } while (Delay != 0);
1053
1054 if (Delay == 0) {
1055 return EFI_TIMEOUT;
1056 }
1057
1058 return EFI_SUCCESS;
1059 }
1060
1061 /**
1062 Wait specified time interval to poll for DRQ bit set in the Status Register.
1063
1064 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1065 @param[in] IdeIoRegisters A pointer to IDE IO registers.
1066 @param[in] TimeoutInMilliSeconds Time specified in milliseconds.
1067
1068 @retval EFI_SUCCESS DRQ bit is set in the specified time interval.
1069 @retval EFI_TIMEOUT DRQ bit is not set in the specified time interval.
1070 @retval EFI_ABORTED Operation Aborted.
1071
1072 **/
1073 EFI_STATUS
DRQReady(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN IDE_BASE_REGISTERS * IdeIoRegisters,IN UINTN TimeoutInMilliSeconds)1074 DRQReady (
1075 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
1076 IN IDE_BASE_REGISTERS *IdeIoRegisters,
1077 IN UINTN TimeoutInMilliSeconds
1078 )
1079 {
1080 UINTN Delay;
1081 UINT16 StatusRegister;
1082 UINT8 StatusValue;
1083 UINT8 ErrValue;
1084
1085 StatusValue = 0;
1086 ErrValue = 0;
1087
1088 StatusRegister = IdeIoRegisters->Reg.Status;
1089
1090 Delay = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
1091 do {
1092 //
1093 // read Status Register will clear interrupt
1094 //
1095 StatusValue = IoRead8 (StatusRegister);
1096
1097 //
1098 // BSY==0,DRQ==1
1099 //
1100 if ((StatusValue & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {
1101 break;
1102 }
1103
1104 if ((StatusValue & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
1105
1106 ErrValue = IoRead8 (IdeIoRegisters->Reg1.Error);
1107 if ((ErrValue & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
1108 return EFI_ABORTED;
1109 }
1110 }
1111 MicroSecondDelay (250);
1112
1113 Delay--;
1114 } while (Delay != 0);
1115
1116 if (Delay == 0) {
1117 return EFI_TIMEOUT;
1118 }
1119
1120 return EFI_SUCCESS;
1121 }
1122
1123 /**
1124 Wait specified time interval to poll for DRQ bit set in the Alternate Status Register.
1125
1126 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1127 @param[in] IdeIoRegisters A pointer to IDE IO registers.
1128 @param[in] TimeoutInMilliSeconds Time specified in milliseconds.
1129
1130 @retval EFI_SUCCESS DRQ bit is set in the specified time interval.
1131 @retval EFI_TIMEOUT DRQ bit is not set in the specified time interval.
1132 @retval EFI_ABORTED Operation Aborted.
1133
1134 **/
1135 EFI_STATUS
DRQReady2(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN IDE_BASE_REGISTERS * IdeIoRegisters,IN UINTN TimeoutInMilliSeconds)1136 DRQReady2 (
1137 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
1138 IN IDE_BASE_REGISTERS *IdeIoRegisters,
1139 IN UINTN TimeoutInMilliSeconds
1140 )
1141 {
1142 UINTN Delay;
1143 UINT16 AltStatusRegister;
1144 UINT8 AltStatusValue;
1145 UINT8 ErrValue;
1146
1147 AltStatusValue = 0;
1148
1149 AltStatusRegister = IdeIoRegisters->Alt.AltStatus;
1150
1151 Delay = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
1152 do {
1153
1154 AltStatusValue = IoRead8 (AltStatusRegister);
1155
1156 //
1157 // BSY==0,DRQ==1
1158 //
1159 if ((AltStatusValue & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {
1160 break;
1161 }
1162
1163 if ((AltStatusValue & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
1164
1165 ErrValue = IoRead8 (IdeIoRegisters->Reg1.Error);
1166 if ((ErrValue & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
1167 return EFI_ABORTED;
1168 }
1169 }
1170 MicroSecondDelay (250);
1171
1172 Delay--;
1173 } while (Delay != 0);
1174
1175 if (Delay == 0) {
1176 return EFI_TIMEOUT;
1177 }
1178
1179 return EFI_SUCCESS;
1180 }
1181
1182 /**
1183 Check if there is an error in Status Register.
1184
1185 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1186 @param[in] StatusReg The address to IDE IO registers.
1187
1188 @retval EFI_SUCCESS Operation success.
1189 @retval EFI_DEVICE_ERROR Device error.
1190
1191 **/
1192 EFI_STATUS
CheckErrorStatus(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINT16 StatusReg)1193 CheckErrorStatus (
1194 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
1195 IN UINT16 StatusReg
1196 )
1197 {
1198 UINT8 StatusValue;
1199
1200 StatusValue = IoRead8 (StatusReg);
1201
1202 if ((StatusValue & (ATA_STSREG_ERR | ATA_STSREG_DWF | ATA_STSREG_CORR)) == 0) {
1203
1204 return EFI_SUCCESS;
1205 }
1206
1207 return EFI_DEVICE_ERROR;
1208
1209 }
1210
1211 /**
1212 Idendify Atapi devices.
1213
1214 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1215 @param[in] DevicePosition An integer to signify device position.
1216
1217 @retval EFI_SUCCESS Identify successfully.
1218 @retval EFI_DEVICE_ERROR Device cannot be identified successfully.
1219
1220 **/
1221 EFI_STATUS
ATAPIIdentify(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition)1222 ATAPIIdentify (
1223 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
1224 IN UINTN DevicePosition
1225 )
1226 {
1227 ATAPI_IDENTIFY_DATA AtapiIdentifyData;
1228 UINT8 Channel;
1229 UINT8 Device;
1230 UINT16 StatusReg;
1231 UINT16 HeadReg;
1232 UINT16 CommandReg;
1233 UINT16 DataReg;
1234 UINT16 SectorCountReg;
1235 UINT16 SectorNumberReg;
1236 UINT16 CylinderLsbReg;
1237 UINT16 CylinderMsbReg;
1238
1239 UINT32 WordCount;
1240 UINT32 Increment;
1241 UINT32 Index;
1242 UINT32 ByteCount;
1243 UINT16 *Buffer16;
1244
1245 EFI_STATUS Status;
1246
1247 ByteCount = sizeof (AtapiIdentifyData);
1248 Buffer16 = (UINT16 *) &AtapiIdentifyData;
1249
1250 Channel = (UINT8) (DevicePosition / 2);
1251 Device = (UINT8) (DevicePosition % 2);
1252
1253 ASSERT (Channel < MAX_IDE_CHANNELS);
1254
1255 StatusReg = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Status;
1256 HeadReg = AtapiBlkIoDev->IdeIoPortReg[Channel].Head;
1257 CommandReg = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Command;
1258 DataReg = AtapiBlkIoDev->IdeIoPortReg[Channel].Data;
1259 SectorCountReg = AtapiBlkIoDev->IdeIoPortReg[Channel].SectorCount;
1260 SectorNumberReg = AtapiBlkIoDev->IdeIoPortReg[Channel].SectorNumber;
1261 CylinderLsbReg = AtapiBlkIoDev->IdeIoPortReg[Channel].CylinderLsb;
1262 CylinderMsbReg = AtapiBlkIoDev->IdeIoPortReg[Channel].CylinderMsb;
1263
1264 //
1265 // Send ATAPI Identify Command to get IDENTIFY data.
1266 //
1267 if (WaitForBSYClear (
1268 AtapiBlkIoDev,
1269 &(AtapiBlkIoDev->IdeIoPortReg[Channel]),
1270 ATATIMEOUT
1271 ) != EFI_SUCCESS) {
1272 return EFI_DEVICE_ERROR;
1273 }
1274 //
1275 // select device via Head/Device register.
1276 // Before write Head/Device register, BSY and DRQ must be 0.
1277 //
1278 if (DRQClear2 (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), ATATIMEOUT) != EFI_SUCCESS) {
1279 return EFI_DEVICE_ERROR;
1280 }
1281 //
1282 // e0:1110,0000-- bit7 and bit5 are reserved bits.
1283 // bit6 set means LBA mode
1284 //
1285 IoWrite8 (HeadReg, (UINT8) ((Device << 4) | 0xe0));
1286
1287 //
1288 // set all the command parameters
1289 // Before write to all the following registers, BSY and DRQ must be 0.
1290 //
1291 if (DRQClear2 (
1292 AtapiBlkIoDev,
1293 &(AtapiBlkIoDev->IdeIoPortReg[Channel]),
1294 ATATIMEOUT
1295 ) != EFI_SUCCESS) {
1296
1297 return EFI_DEVICE_ERROR;
1298 }
1299
1300 IoWrite8 (SectorCountReg, 0);
1301 IoWrite8 (SectorNumberReg, 0);
1302 IoWrite8 (CylinderLsbReg, 0);
1303 IoWrite8 (CylinderMsbReg, 0);
1304
1305 //
1306 // send command via Command Register
1307 //
1308 IoWrite8 (CommandReg, ATA_CMD_IDENTIFY_DEVICE);
1309
1310 //
1311 // According to PIO data in protocol, host can perform a series of reads to the
1312 // data register after each time device set DRQ ready;
1313 // The data size of "a series of read" is command specific.
1314 // For most ATA command, data size received from device will not exceed 1 sector,
1315 // hense the data size for "a series of read" can be the whole data size of one command request.
1316 // For ATA command such as Read Sector command, whole data size of one ATA command request is often larger
1317 // than 1 sector, according to the Read Sector command, the data size of "a series of read" is exactly
1318 // 1 sector.
1319 // Here for simplification reason, we specify the data size for "a series of read" to
1320 // 1 sector (256 words) if whole data size of one ATA commmand request is larger than 256 words.
1321 //
1322 Increment = 256;
1323 //
1324 // 256 words
1325 //
1326 WordCount = 0;
1327 //
1328 // WordCount is used to record bytes of currently transfered data
1329 //
1330 while (WordCount < ByteCount / 2) {
1331 //
1332 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.
1333 //
1334 Status = DRQReady2 (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), ATATIMEOUT);
1335 if (Status != EFI_SUCCESS) {
1336 return Status;
1337 }
1338
1339 if (CheckErrorStatus (AtapiBlkIoDev, StatusReg) != EFI_SUCCESS) {
1340
1341 return EFI_DEVICE_ERROR;
1342 }
1343 //
1344 // Get the byte count for one series of read
1345 //
1346 if ((WordCount + Increment) > ByteCount / 2) {
1347 Increment = ByteCount / 2 - WordCount;
1348 }
1349 //
1350 // perform a series of read without check DRQ ready
1351 //
1352 for (Index = 0; Index < Increment; Index++) {
1353 *Buffer16++ = IoRead16 (DataReg);
1354 }
1355
1356 WordCount += Increment;
1357
1358 }
1359 //
1360 // while
1361 //
1362 if (DRQClear (
1363 AtapiBlkIoDev,
1364 &(AtapiBlkIoDev->IdeIoPortReg[Channel]),
1365 ATATIMEOUT
1366 ) != EFI_SUCCESS) {
1367 return CheckErrorStatus (AtapiBlkIoDev, StatusReg);
1368 }
1369
1370 return EFI_SUCCESS;
1371
1372 }
1373
1374 /**
1375 Sends out ATAPI Test Unit Ready Packet Command to the specified device
1376 to find out whether device is accessible.
1377
1378 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1379 @param[in] DevicePosition An integer to signify device position.
1380
1381 @retval EFI_SUCCESS TestUnit command executed successfully.
1382 @retval EFI_DEVICE_ERROR Device cannot be executed TestUnit command successfully.
1383
1384 **/
1385 EFI_STATUS
TestUnitReady(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition)1386 TestUnitReady (
1387 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
1388 IN UINTN DevicePosition
1389 )
1390 {
1391 ATAPI_PACKET_COMMAND Packet;
1392 EFI_STATUS Status;
1393
1394 //
1395 // fill command packet
1396 //
1397 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1398 Packet.TestUnitReady.opcode = ATA_CMD_TEST_UNIT_READY;
1399
1400 //
1401 // send command packet
1402 //
1403 Status = AtapiPacketCommandIn (AtapiBlkIoDev, DevicePosition, &Packet, NULL, 0, ATAPITIMEOUT);
1404 return Status;
1405 }
1406
1407 /**
1408 Send out ATAPI commands conforms to the Packet Command with PIO Data In Protocol.
1409
1410 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1411 @param[in] DevicePosition An integer to signify device position.
1412 @param[in] Packet A pointer to ATAPI command packet.
1413 @param[in] Buffer Buffer to contain requested transfer data from device.
1414 @param[in] ByteCount Requested transfer data length.
1415 @param[in] TimeoutInMilliSeconds Time out value, in unit of milliseconds.
1416
1417 @retval EFI_SUCCESS Command executed successfully.
1418 @retval EFI_DEVICE_ERROR Device cannot be executed command successfully.
1419
1420 **/
1421 EFI_STATUS
AtapiPacketCommandIn(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,IN ATAPI_PACKET_COMMAND * Packet,IN UINT16 * Buffer,IN UINT32 ByteCount,IN UINTN TimeoutInMilliSeconds)1422 AtapiPacketCommandIn (
1423 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
1424 IN UINTN DevicePosition,
1425 IN ATAPI_PACKET_COMMAND *Packet,
1426 IN UINT16 *Buffer,
1427 IN UINT32 ByteCount,
1428 IN UINTN TimeoutInMilliSeconds
1429 )
1430 {
1431 UINT8 Channel;
1432 UINT8 Device;
1433 UINT16 StatusReg;
1434 UINT16 HeadReg;
1435 UINT16 CommandReg;
1436 UINT16 FeatureReg;
1437 UINT16 CylinderLsbReg;
1438 UINT16 CylinderMsbReg;
1439 UINT16 DeviceControlReg;
1440 UINT16 DataReg;
1441 EFI_STATUS Status;
1442 UINT32 Count;
1443 UINT16 *CommandIndex;
1444 UINT16 *PtrBuffer;
1445 UINT32 Index;
1446 UINT8 StatusValue;
1447 UINT32 WordCount;
1448
1449 //
1450 // required transfer data in word unit.
1451 //
1452 UINT32 RequiredWordCount;
1453
1454 //
1455 // actual transfer data in word unit.
1456 //
1457 UINT32 ActualWordCount;
1458
1459 Channel = (UINT8) (DevicePosition / 2);
1460 Device = (UINT8) (DevicePosition % 2);
1461
1462 ASSERT (Channel < MAX_IDE_CHANNELS);
1463
1464 StatusReg = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Status;
1465 HeadReg = AtapiBlkIoDev->IdeIoPortReg[Channel].Head;
1466 CommandReg = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Command;
1467 FeatureReg = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg1.Feature;
1468 CylinderLsbReg = AtapiBlkIoDev->IdeIoPortReg[Channel].CylinderLsb;
1469 CylinderMsbReg = AtapiBlkIoDev->IdeIoPortReg[Channel].CylinderMsb;
1470 DeviceControlReg = AtapiBlkIoDev->IdeIoPortReg[Channel].Alt.DeviceControl;
1471 DataReg = AtapiBlkIoDev->IdeIoPortReg[Channel].Data;
1472
1473 //
1474 // Set all the command parameters by fill related registers.
1475 // Before write to all the following registers, BSY and DRQ must be 0.
1476 //
1477 if (DRQClear2 (
1478 AtapiBlkIoDev,
1479 &(AtapiBlkIoDev->IdeIoPortReg[Channel]),
1480 ATATIMEOUT
1481 ) != EFI_SUCCESS) {
1482 return EFI_DEVICE_ERROR;
1483 }
1484 //
1485 // Select device via Device/Head Register.
1486 // DEFAULT_CMD: 0xa0 (1010,0000)
1487 //
1488 IoWrite8 (HeadReg, (UINT8) ((Device << 4) | ATA_DEFAULT_CMD));
1489
1490 //
1491 // No OVL; No DMA
1492 //
1493 IoWrite8 (FeatureReg, 0x00);
1494
1495 //
1496 // set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device
1497 // determine how many data should be transfered.
1498 //
1499 IoWrite8 (CylinderLsbReg, (UINT8) (ATAPI_MAX_BYTE_COUNT & 0x00ff));
1500 IoWrite8 (CylinderMsbReg, (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8));
1501
1502 //
1503 // DEFAULT_CTL:0x0a (0000,1010)
1504 // Disable interrupt
1505 //
1506 IoWrite8 (DeviceControlReg, ATA_DEFAULT_CTL);
1507
1508 //
1509 // Send Packet command to inform device
1510 // that the following data bytes are command packet.
1511 //
1512 IoWrite8 (CommandReg, ATA_CMD_PACKET);
1513
1514 Status = DRQReady (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), TimeoutInMilliSeconds);
1515 if (Status != EFI_SUCCESS) {
1516 return Status;
1517 }
1518 //
1519 // Send out command packet
1520 //
1521 CommandIndex = Packet->Data16;
1522 for (Count = 0; Count < 6; Count++, CommandIndex++) {
1523 IoWrite16 (DataReg, *CommandIndex);
1524 MicroSecondDelay (10);
1525 }
1526
1527 StatusValue = IoRead8 (StatusReg);
1528 if ((StatusValue & ATA_STSREG_ERR) == ATA_STSREG_ERR) {
1529 //
1530 // Trouble! Something's wrong here... Wait some time and return. 3 second is
1531 // supposed to be long enough for a device reset latency or error recovery
1532 //
1533 MicroSecondDelay (3000000);
1534 return EFI_DEVICE_ERROR;
1535 }
1536
1537 if (Buffer == NULL || ByteCount == 0) {
1538 return EFI_SUCCESS;
1539 }
1540 //
1541 // call PioReadWriteData() function to get
1542 // requested transfer data form device.
1543 //
1544 PtrBuffer = Buffer;
1545 RequiredWordCount = ByteCount / 2;
1546 //
1547 // ActuralWordCount means the word count of data really transfered.
1548 //
1549 ActualWordCount = 0;
1550
1551 Status = EFI_SUCCESS;
1552 while ((Status == EFI_SUCCESS) && (ActualWordCount < RequiredWordCount)) {
1553 //
1554 // before each data transfer stream, the host should poll DRQ bit ready,
1555 // which informs device is ready to transfer data.
1556 //
1557 if (DRQReady2 (
1558 AtapiBlkIoDev,
1559 &(AtapiBlkIoDev->IdeIoPortReg[Channel]),
1560 TimeoutInMilliSeconds
1561 ) != EFI_SUCCESS) {
1562 return CheckErrorStatus (AtapiBlkIoDev, StatusReg);
1563 }
1564 //
1565 // read Status Register will clear interrupt
1566 //
1567 StatusValue = IoRead8 (StatusReg);
1568
1569 //
1570 // get current data transfer size from Cylinder Registers.
1571 //
1572 WordCount = IoRead8 (CylinderMsbReg) << 8;
1573 WordCount = WordCount | IoRead8 (CylinderLsbReg);
1574 WordCount = WordCount & 0xffff;
1575 WordCount /= 2;
1576
1577 //
1578 // perform a series data In/Out.
1579 //
1580 for (Index = 0; (Index < WordCount) && (ActualWordCount < RequiredWordCount); Index++, ActualWordCount++) {
1581
1582 *PtrBuffer = IoRead16 (DataReg);
1583
1584 PtrBuffer++;
1585
1586 }
1587
1588 if (((ATAPI_REQUEST_SENSE_CMD *) Packet)->opcode == ATA_CMD_REQUEST_SENSE && ActualWordCount >= 4) {
1589 RequiredWordCount = MIN (
1590 RequiredWordCount,
1591 (UINT32) (4 + (((ATAPI_REQUEST_SENSE_DATA *) Buffer)->addnl_sense_length / 2))
1592 );
1593 }
1594
1595 }
1596 //
1597 // After data transfer is completed, normally, DRQ bit should clear.
1598 //
1599 Status = DRQClear2 (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), TimeoutInMilliSeconds);
1600 if (Status != EFI_SUCCESS) {
1601 return EFI_DEVICE_ERROR;
1602 }
1603 //
1604 // read status register to check whether error happens.
1605 //
1606 Status = CheckErrorStatus (AtapiBlkIoDev, StatusReg);
1607 return Status;
1608 }
1609
1610 /**
1611 Sends out ATAPI Inquiry Packet Command to the specified device.
1612 This command will return INQUIRY data of the device.
1613
1614 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1615 @param[in] DevicePosition An integer to signify device position.
1616 @param[out] MediaInfo The media information of the specified block media.
1617 @param[out] MediaInfo2 The media information 2 of the specified block media.
1618
1619 @retval EFI_SUCCESS Command executed successfully.
1620 @retval EFI_DEVICE_ERROR Device cannot be executed command successfully.
1621 @retval EFI_UNSUPPORTED Unsupported device type.
1622
1623 **/
1624 EFI_STATUS
Inquiry(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,OUT EFI_PEI_BLOCK_IO_MEDIA * MediaInfo,OUT EFI_PEI_BLOCK_IO2_MEDIA * MediaInfo2)1625 Inquiry (
1626 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
1627 IN UINTN DevicePosition,
1628 OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo,
1629 OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo2
1630 )
1631 {
1632 ATAPI_PACKET_COMMAND Packet;
1633 EFI_STATUS Status;
1634 ATAPI_INQUIRY_DATA Idata;
1635
1636 //
1637 // prepare command packet for the ATAPI Inquiry Packet Command.
1638 //
1639 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1640 ZeroMem (&Idata, sizeof (ATAPI_INQUIRY_DATA));
1641
1642 Packet.Inquiry.opcode = ATA_CMD_INQUIRY;
1643 Packet.Inquiry.page_code = 0;
1644 Packet.Inquiry.allocation_length = (UINT8) sizeof (ATAPI_INQUIRY_DATA);
1645
1646 //
1647 // Send command packet and get requested Inquiry data.
1648 //
1649 Status = AtapiPacketCommandIn (
1650 AtapiBlkIoDev,
1651 DevicePosition,
1652 &Packet,
1653 (UINT16 *) (&Idata),
1654 sizeof (ATAPI_INQUIRY_DATA),
1655 ATAPITIMEOUT
1656 //50
1657 );
1658
1659 if (Status != EFI_SUCCESS) {
1660 return EFI_DEVICE_ERROR;
1661 }
1662 //
1663 // Identify device type via INQUIRY data.
1664 //
1665 switch (Idata.peripheral_type & 0x1f) {
1666 case 0x00:
1667 //
1668 // Magnetic Disk
1669 //
1670 MediaInfo->DeviceType = IdeLS120;
1671 MediaInfo->MediaPresent = FALSE;
1672 MediaInfo->LastBlock = 0;
1673 MediaInfo->BlockSize = 0x200;
1674 MediaInfo2->InterfaceType = MSG_ATAPI_DP;
1675 MediaInfo2->RemovableMedia = TRUE;
1676 MediaInfo2->MediaPresent = FALSE;
1677 MediaInfo2->ReadOnly = FALSE;
1678 MediaInfo2->BlockSize = 0x200;
1679 MediaInfo2->LastBlock = 0;
1680 break;
1681
1682 case 0x05:
1683 //
1684 // CD-ROM
1685 //
1686 MediaInfo->DeviceType = IdeCDROM;
1687 MediaInfo->MediaPresent = FALSE;
1688 MediaInfo->LastBlock = 0;
1689 MediaInfo->BlockSize = 0x800;
1690 MediaInfo2->InterfaceType = MSG_ATAPI_DP;
1691 MediaInfo2->RemovableMedia = TRUE;
1692 MediaInfo2->MediaPresent = FALSE;
1693 MediaInfo2->ReadOnly = TRUE;
1694 MediaInfo2->BlockSize = 0x200;
1695 MediaInfo2->LastBlock = 0;
1696 break;
1697
1698 default:
1699 return EFI_UNSUPPORTED;
1700 }
1701
1702 return EFI_SUCCESS;
1703 }
1704
1705 /**
1706 Used before read/write blocks from/to ATAPI device media.
1707 Since ATAPI device media is removable, it is necessary to detect
1708 whether media is present and get current present media's information.
1709
1710 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1711 @param[in] DevicePosition An integer to signify device position.
1712 @param[in, out] MediaInfo The media information of the specified block media.
1713 @param[in, out] MediaInfo2 The media information 2 of the specified block media.
1714
1715 @retval EFI_SUCCESS Command executed successfully.
1716 @retval EFI_DEVICE_ERROR Some device errors happen.
1717 @retval EFI_OUT_OF_RESOURCES Can not allocate required resources.
1718
1719 **/
1720 EFI_STATUS
DetectMedia(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,IN OUT EFI_PEI_BLOCK_IO_MEDIA * MediaInfo,IN OUT EFI_PEI_BLOCK_IO2_MEDIA * MediaInfo2)1721 DetectMedia (
1722 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
1723 IN UINTN DevicePosition,
1724 IN OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo,
1725 IN OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo2
1726 )
1727 {
1728
1729 UINTN Index;
1730 UINTN RetryNum;
1731 UINTN MaxRetryNum;
1732 ATAPI_REQUEST_SENSE_DATA *SenseBuffers;
1733 BOOLEAN NeedReadCapacity;
1734 BOOLEAN NeedRetry;
1735 EFI_STATUS Status;
1736 UINT8 SenseCounts;
1737
1738 SenseBuffers = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (*SenseBuffers)));
1739 if (SenseBuffers == NULL) {
1740 return EFI_OUT_OF_RESOURCES;
1741 }
1742
1743 //
1744 // Test Unit Ready command is used to detect whether device is accessible,
1745 // the device will produce corresponding Sense data.
1746 //
1747 for (Index = 0; Index < 2; Index++) {
1748
1749 Status = TestUnitReady (AtapiBlkIoDev, DevicePosition);
1750 if (Status != EFI_SUCCESS) {
1751 Status = ResetDevice (AtapiBlkIoDev, DevicePosition, FALSE);
1752
1753 if (Status != EFI_SUCCESS) {
1754 ResetDevice (AtapiBlkIoDev, DevicePosition, TRUE);
1755 }
1756
1757 } else {
1758 break;
1759 }
1760 }
1761
1762 SenseCounts = MAX_SENSE_KEY_COUNT;
1763 Status = EFI_SUCCESS;
1764 NeedReadCapacity = TRUE;
1765
1766 for (Index = 0; Index < 5; Index++) {
1767 SenseCounts = MAX_SENSE_KEY_COUNT;
1768 Status = RequestSense (
1769 AtapiBlkIoDev,
1770 DevicePosition,
1771 SenseBuffers,
1772 &SenseCounts
1773 );
1774 DEBUG ((EFI_D_INFO, "Atapi Request Sense Count is %d\n", SenseCounts));
1775 if (IsDeviceStateUnclear (SenseBuffers, SenseCounts) || IsNoMedia (SenseBuffers, SenseCounts)) {
1776 //
1777 // We are not sure whether the media is present or not, try again
1778 //
1779 TestUnitReady (AtapiBlkIoDev, DevicePosition);
1780 } else {
1781 break;
1782 }
1783 }
1784
1785 if (Status == EFI_SUCCESS) {
1786
1787 if (IsNoMedia (SenseBuffers, SenseCounts)) {
1788
1789 NeedReadCapacity = FALSE;
1790 MediaInfo->MediaPresent = FALSE;
1791 MediaInfo->LastBlock = 0;
1792 MediaInfo2->MediaPresent = FALSE;
1793 MediaInfo2->LastBlock = 0;
1794 }
1795
1796 if (IsMediaError (SenseBuffers, SenseCounts)) {
1797 return EFI_DEVICE_ERROR;
1798 }
1799 }
1800
1801 if (NeedReadCapacity) {
1802 //
1803 // at most retry 5 times
1804 //
1805 MaxRetryNum = 5;
1806 RetryNum = 1;
1807 //
1808 // initial retry once
1809 //
1810 for (Index = 0; (Index < RetryNum) && (Index < MaxRetryNum); Index++) {
1811
1812 Status = ReadCapacity (AtapiBlkIoDev, DevicePosition, MediaInfo, MediaInfo2);
1813 MicroSecondDelay (200000);
1814 SenseCounts = MAX_SENSE_KEY_COUNT;
1815
1816 if (Status != EFI_SUCCESS) {
1817
1818 Status = RequestSense (AtapiBlkIoDev, DevicePosition, SenseBuffers, &SenseCounts);
1819 //
1820 // If Request Sense data failed, reset the device and retry.
1821 //
1822 if (Status != EFI_SUCCESS) {
1823
1824 Status = ResetDevice (AtapiBlkIoDev, DevicePosition, FALSE);
1825 //
1826 // if ATAPI soft reset fail,
1827 // use stronger reset mechanism -- ATA soft reset.
1828 //
1829 if (Status != EFI_SUCCESS) {
1830 ResetDevice (AtapiBlkIoDev, DevicePosition, TRUE);
1831 }
1832
1833 RetryNum++;
1834 //
1835 // retry once more
1836 //
1837 continue;
1838 }
1839 //
1840 // No Media
1841 //
1842 if (IsNoMedia (SenseBuffers, SenseCounts)) {
1843
1844 MediaInfo->MediaPresent = FALSE;
1845 MediaInfo->LastBlock = 0;
1846 MediaInfo2->MediaPresent = FALSE;
1847 MediaInfo2->LastBlock = 0;
1848 break;
1849 }
1850
1851 if (IsMediaError (SenseBuffers, SenseCounts)) {
1852 return EFI_DEVICE_ERROR;
1853 }
1854
1855 if (!IsDriveReady (SenseBuffers, SenseCounts, &NeedRetry)) {
1856 //
1857 // Drive not ready: if NeedRetry, then retry once more;
1858 // else return error
1859 //
1860 if (NeedRetry) {
1861 RetryNum++;
1862 continue;
1863 } else {
1864 return EFI_DEVICE_ERROR;
1865 }
1866 }
1867 //
1868 // if read capacity fail not for above reasons, retry once more
1869 //
1870 RetryNum++;
1871
1872 }
1873
1874 }
1875
1876 }
1877
1878 return EFI_SUCCESS;
1879 }
1880
1881 /**
1882 Reset specified Atapi device.
1883
1884 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1885 @param[in] DevicePosition An integer to signify device position.
1886 @param[in] Extensive If TRUE, use ATA soft reset, otherwise use Atapi soft reset.
1887
1888 @retval EFI_SUCCESS Command executed successfully.
1889 @retval EFI_DEVICE_ERROR Some device errors happen.
1890
1891 **/
1892 EFI_STATUS
ResetDevice(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,IN BOOLEAN Extensive)1893 ResetDevice (
1894 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
1895 IN UINTN DevicePosition,
1896 IN BOOLEAN Extensive
1897 )
1898 {
1899 UINT8 DevControl;
1900 UINT8 Command;
1901 UINT8 DeviceSelect;
1902 UINT16 DeviceControlReg;
1903 UINT16 CommandReg;
1904 UINT16 HeadReg;
1905 UINT8 Channel;
1906 UINT8 Device;
1907
1908 Channel = (UINT8) (DevicePosition / 2);
1909 Device = (UINT8) (DevicePosition % 2);
1910
1911 ASSERT (Channel < MAX_IDE_CHANNELS);
1912
1913 DeviceControlReg = AtapiBlkIoDev->IdeIoPortReg[Channel].Alt.DeviceControl;
1914 CommandReg = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Command;
1915 HeadReg = AtapiBlkIoDev->IdeIoPortReg[Channel].Head;
1916
1917 if (Extensive) {
1918
1919 DevControl = 0;
1920 DevControl |= ATA_CTLREG_SRST;
1921 //
1922 // set SRST bit to initiate soft reset
1923 //
1924 DevControl |= BIT1;
1925 //
1926 // disable Interrupt
1927 //
1928 IoWrite8 (DeviceControlReg, DevControl);
1929
1930 //
1931 // Wait 10us
1932 //
1933 MicroSecondDelay (10);
1934
1935 //
1936 // Clear SRST bit
1937 //
1938 DevControl &= 0xfb;
1939 //
1940 // 0xfb:1111,1011
1941 //
1942 IoWrite8 (DeviceControlReg, DevControl);
1943
1944 //
1945 // slave device needs at most 31s to clear BSY
1946 //
1947 if (WaitForBSYClear (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), 31000) == EFI_TIMEOUT) {
1948 return EFI_DEVICE_ERROR;
1949 }
1950
1951 } else {
1952 //
1953 // for ATAPI device, no need to wait DRDY ready after device selecting.
1954 // bit7 and bit5 are both set to 1 for backward compatibility
1955 //
1956 DeviceSelect = (UINT8) (((BIT7 | BIT5) | (Device << 4)));
1957 IoWrite8 (HeadReg, DeviceSelect);
1958
1959 Command = ATA_CMD_SOFT_RESET;
1960 IoWrite8 (CommandReg, Command);
1961
1962 //
1963 // BSY cleared is the only status return to the host by the device when reset is completed
1964 // slave device needs at most 31s to clear BSY
1965 //
1966 if (WaitForBSYClear (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), 31000) != EFI_SUCCESS) {
1967 return EFI_DEVICE_ERROR;
1968 }
1969 //
1970 // stall 5 seconds to make the device status stable
1971 //
1972 MicroSecondDelay (STALL_1_SECONDS * 5);
1973 }
1974
1975 return EFI_SUCCESS;
1976
1977 }
1978
1979 /**
1980 Sends out ATAPI Request Sense Packet Command to the specified device.
1981
1982 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1983 @param[in] DevicePosition An integer to signify device position.
1984 @param[in] SenseBuffers Pointer to sense buffer.
1985 @param[in, out] SenseCounts Length of sense buffer.
1986
1987 @retval EFI_SUCCESS Command executed successfully.
1988 @retval EFI_DEVICE_ERROR Some device errors happen.
1989
1990 **/
1991 EFI_STATUS
RequestSense(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,IN ATAPI_REQUEST_SENSE_DATA * SenseBuffers,IN OUT UINT8 * SenseCounts)1992 RequestSense (
1993 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
1994 IN UINTN DevicePosition,
1995 IN ATAPI_REQUEST_SENSE_DATA *SenseBuffers,
1996 IN OUT UINT8 *SenseCounts
1997 )
1998 {
1999 EFI_STATUS Status;
2000 ATAPI_REQUEST_SENSE_DATA *Sense;
2001 UINT16 *Ptr;
2002 BOOLEAN SenseReq;
2003 ATAPI_PACKET_COMMAND Packet;
2004
2005 ZeroMem (SenseBuffers, sizeof (ATAPI_REQUEST_SENSE_DATA) * (*SenseCounts));
2006 //
2007 // fill command packet for Request Sense Packet Command
2008 //
2009 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
2010 Packet.RequestSence.opcode = ATA_CMD_REQUEST_SENSE;
2011 Packet.RequestSence.allocation_length = (UINT8) sizeof (ATAPI_REQUEST_SENSE_DATA);
2012
2013 Ptr = (UINT16 *) SenseBuffers;
2014 //
2015 // initialize pointer
2016 //
2017 *SenseCounts = 0;
2018 //
2019 // request sense data from device continiously until no sense data exists in the device.
2020 //
2021 for (SenseReq = TRUE; SenseReq;) {
2022
2023 Sense = (ATAPI_REQUEST_SENSE_DATA *) Ptr;
2024
2025 //
2026 // send out Request Sense Packet Command and get one Sense data form device
2027 //
2028 Status = AtapiPacketCommandIn (
2029 AtapiBlkIoDev,
2030 DevicePosition,
2031 &Packet,
2032 Ptr,
2033 sizeof (ATAPI_REQUEST_SENSE_DATA),
2034 ATAPITIMEOUT
2035 );
2036 //
2037 // failed to get Sense data
2038 //
2039 if (Status != EFI_SUCCESS) {
2040 if (*SenseCounts == 0) {
2041 return EFI_DEVICE_ERROR;
2042 } else {
2043 return EFI_SUCCESS;
2044 }
2045 }
2046
2047 (*SenseCounts)++;
2048
2049 if (*SenseCounts > MAX_SENSE_KEY_COUNT) {
2050 return EFI_SUCCESS;
2051 }
2052 //
2053 // We limit MAX sense data count to 20 in order to avoid dead loop. Some
2054 // incompatible ATAPI devices don't retrive NO_SENSE when there is no media.
2055 // In this case, dead loop occurs if we don't have a gatekeeper. 20 is
2056 // supposed to be large enough for any ATAPI device.
2057 //
2058 if ((Sense->sense_key != ATA_SK_NO_SENSE) && ((*SenseCounts) < 20)) {
2059
2060 Ptr += sizeof (ATAPI_REQUEST_SENSE_DATA) / 2;
2061 //
2062 // Ptr is word based pointer
2063 //
2064 } else {
2065 //
2066 // when no sense key, skip out the loop
2067 //
2068 SenseReq = FALSE;
2069 }
2070 }
2071
2072 return EFI_SUCCESS;
2073 }
2074
2075 /**
2076 Sends out ATAPI Read Capacity Packet Command to the specified device.
2077 This command will return the information regarding the capacity of the
2078 media in the device.
2079
2080 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
2081 @param[in] DevicePosition An integer to signify device position.
2082 @param[in, out] MediaInfo The media information of the specified block media.
2083 @param[in, out] MediaInfo2 The media information 2 of the specified block media.
2084
2085 @retval EFI_SUCCESS Command executed successfully.
2086 @retval EFI_DEVICE_ERROR Some device errors happen.
2087
2088 **/
2089 EFI_STATUS
ReadCapacity(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,IN OUT EFI_PEI_BLOCK_IO_MEDIA * MediaInfo,IN OUT EFI_PEI_BLOCK_IO2_MEDIA * MediaInfo2)2090 ReadCapacity (
2091 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
2092 IN UINTN DevicePosition,
2093 IN OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo,
2094 IN OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo2
2095 )
2096 {
2097 EFI_STATUS Status;
2098 ATAPI_PACKET_COMMAND Packet;
2099
2100 //
2101 // used for capacity data returned from ATAPI device
2102 //
2103 ATAPI_READ_CAPACITY_DATA Data;
2104 ATAPI_READ_FORMAT_CAPACITY_DATA FormatData;
2105
2106 ZeroMem (&Data, sizeof (Data));
2107 ZeroMem (&FormatData, sizeof (FormatData));
2108
2109 if (MediaInfo->DeviceType == IdeCDROM) {
2110
2111 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
2112 Packet.Inquiry.opcode = ATA_CMD_READ_CAPACITY;
2113 Status = AtapiPacketCommandIn (
2114 AtapiBlkIoDev,
2115 DevicePosition,
2116 &Packet,
2117 (UINT16 *) (&Data),
2118 sizeof (ATAPI_READ_CAPACITY_DATA),
2119 ATAPITIMEOUT
2120 );
2121
2122 } else {
2123 //
2124 // DeviceType == IdeLS120
2125 //
2126 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
2127 Packet.ReadFormatCapacity.opcode = ATA_CMD_READ_FORMAT_CAPACITY;
2128 Packet.ReadFormatCapacity.allocation_length_lo = 12;
2129 Status = AtapiPacketCommandIn (
2130 AtapiBlkIoDev,
2131 DevicePosition,
2132 &Packet,
2133 (UINT16 *) (&FormatData),
2134 sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA),
2135 ATAPITIMEOUT*10
2136 );
2137 }
2138
2139 if (Status == EFI_SUCCESS) {
2140
2141 if (MediaInfo->DeviceType == IdeCDROM) {
2142
2143 MediaInfo->LastBlock = (Data.LastLba3 << 24) | (Data.LastLba2 << 16) | (Data.LastLba1 << 8) | Data.LastLba0;
2144 MediaInfo->MediaPresent = TRUE;
2145 //
2146 // Because the user data portion in the sector of the Data CD supported
2147 // is always 800h
2148 //
2149 MediaInfo->BlockSize = 0x800;
2150
2151 MediaInfo2->LastBlock = MediaInfo->LastBlock;
2152 MediaInfo2->MediaPresent = MediaInfo->MediaPresent;
2153 MediaInfo2->BlockSize = (UINT32)MediaInfo->BlockSize;
2154 }
2155
2156 if (MediaInfo->DeviceType == IdeLS120) {
2157
2158 if (FormatData.DesCode == 3) {
2159 MediaInfo->MediaPresent = FALSE;
2160 MediaInfo->LastBlock = 0;
2161 MediaInfo2->MediaPresent = FALSE;
2162 MediaInfo2->LastBlock = 0;
2163 } else {
2164 MediaInfo->LastBlock = (FormatData.LastLba3 << 24) |
2165 (FormatData.LastLba2 << 16) |
2166 (FormatData.LastLba1 << 8) |
2167 FormatData.LastLba0;
2168 MediaInfo->LastBlock--;
2169
2170 MediaInfo->MediaPresent = TRUE;
2171
2172 MediaInfo->BlockSize = 0x200;
2173
2174 MediaInfo2->LastBlock = MediaInfo->LastBlock;
2175 MediaInfo2->MediaPresent = MediaInfo->MediaPresent;
2176 MediaInfo2->BlockSize = (UINT32)MediaInfo->BlockSize;
2177
2178 }
2179 }
2180
2181 return EFI_SUCCESS;
2182
2183 } else {
2184 return EFI_DEVICE_ERROR;
2185 }
2186 }
2187
2188 /**
2189 Perform read from disk in block unit.
2190
2191 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
2192 @param[in] DevicePosition An integer to signify device position.
2193 @param[in] Buffer Buffer to contain read data.
2194 @param[in] StartLba Starting LBA address.
2195 @param[in] NumberOfBlocks Number of blocks to read.
2196 @param[in] BlockSize Size of each block.
2197
2198 @retval EFI_SUCCESS Command executed successfully.
2199 @retval EFI_DEVICE_ERROR Some device errors happen.
2200
2201 **/
2202 EFI_STATUS
ReadSectors(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,IN VOID * Buffer,IN EFI_PEI_LBA StartLba,IN UINTN NumberOfBlocks,IN UINTN BlockSize)2203 ReadSectors (
2204 IN ATAPI_BLK_IO_DEV *AtapiBlkIoDev,
2205 IN UINTN DevicePosition,
2206 IN VOID *Buffer,
2207 IN EFI_PEI_LBA StartLba,
2208 IN UINTN NumberOfBlocks,
2209 IN UINTN BlockSize
2210 )
2211 {
2212
2213 ATAPI_PACKET_COMMAND Packet;
2214 ATAPI_READ10_CMD *Read10Packet;
2215 EFI_STATUS Status;
2216 UINTN BlocksRemaining;
2217 UINT32 Lba32;
2218 UINT32 ByteCount;
2219 UINT16 SectorCount;
2220 VOID *PtrBuffer;
2221 UINT16 MaxBlock;
2222
2223 //
2224 // fill command packet for Read(10) command
2225 //
2226 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
2227 Read10Packet = &Packet.Read10;
2228 Lba32 = (UINT32) StartLba;
2229 PtrBuffer = Buffer;
2230
2231 //
2232 // limit the data bytes that can be transfered by one Read(10) Command
2233 //
2234 MaxBlock = (UINT16) (0x10000 / BlockSize);
2235 //
2236 // (64k bytes)
2237 //
2238 BlocksRemaining = NumberOfBlocks;
2239
2240 Status = EFI_SUCCESS;
2241 while (BlocksRemaining > 0) {
2242
2243 if (BlocksRemaining <= MaxBlock) {
2244 SectorCount = (UINT16) BlocksRemaining;
2245 } else {
2246 SectorCount = MaxBlock;
2247 }
2248 //
2249 // fill the Packet data sturcture
2250 //
2251 Read10Packet->opcode = ATA_CMD_READ_10;
2252
2253 //
2254 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
2255 // Lba0 is MSB, Lba3 is LSB
2256 //
2257 Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
2258 Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
2259 Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
2260 Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
2261
2262 //
2263 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
2264 // TranLen0 is MSB, TranLen is LSB
2265 //
2266 Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
2267 Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
2268
2269 ByteCount = (UINT32) (SectorCount * BlockSize);
2270
2271 Status = AtapiPacketCommandIn (
2272 AtapiBlkIoDev,
2273 DevicePosition,
2274 &Packet,
2275 (UINT16 *) PtrBuffer,
2276 ByteCount,
2277 ATAPILONGTIMEOUT
2278 );
2279 if (Status != EFI_SUCCESS) {
2280 return Status;
2281 }
2282
2283 Lba32 += SectorCount;
2284 PtrBuffer = (UINT8 *) PtrBuffer + SectorCount * BlockSize;
2285 BlocksRemaining -= SectorCount;
2286 }
2287
2288 return Status;
2289 }
2290
2291 /**
2292 Check if there is media according to sense data.
2293
2294 @param[in] SenseData Pointer to sense data.
2295 @param[in] SenseCounts Count of sense data.
2296
2297 @retval TRUE No media
2298 @retval FALSE Media exists
2299
2300 **/
2301 BOOLEAN
IsNoMedia(IN ATAPI_REQUEST_SENSE_DATA * SenseData,IN UINTN SenseCounts)2302 IsNoMedia (
2303 IN ATAPI_REQUEST_SENSE_DATA *SenseData,
2304 IN UINTN SenseCounts
2305 )
2306 {
2307 ATAPI_REQUEST_SENSE_DATA *SensePtr;
2308 UINTN Index;
2309 BOOLEAN IsNoMedia;
2310
2311 IsNoMedia = FALSE;
2312
2313 SensePtr = SenseData;
2314
2315 for (Index = 0; Index < SenseCounts; Index++) {
2316
2317 if ((SensePtr->sense_key == ATA_SK_NOT_READY) && (SensePtr->addnl_sense_code == ATA_ASC_NO_MEDIA)) {
2318 IsNoMedia = TRUE;
2319 }
2320
2321 SensePtr++;
2322 }
2323
2324 return IsNoMedia;
2325 }
2326
2327 /**
2328 Check if device state is unclear according to sense data.
2329
2330 @param[in] SenseData Pointer to sense data.
2331 @param[in] SenseCounts Count of sense data.
2332
2333 @retval TRUE Device state is unclear
2334 @retval FALSE Device state is clear
2335
2336 **/
2337 BOOLEAN
IsDeviceStateUnclear(IN ATAPI_REQUEST_SENSE_DATA * SenseData,IN UINTN SenseCounts)2338 IsDeviceStateUnclear (
2339 IN ATAPI_REQUEST_SENSE_DATA *SenseData,
2340 IN UINTN SenseCounts
2341 )
2342 {
2343 ATAPI_REQUEST_SENSE_DATA *SensePtr;
2344 UINTN Index;
2345 BOOLEAN Unclear;
2346
2347 Unclear = FALSE;
2348
2349 SensePtr = SenseData;
2350
2351 for (Index = 0; Index < SenseCounts; Index++) {
2352
2353 if (SensePtr->sense_key == 0x06) {
2354 //
2355 // Sense key is 0x06 means the device is just be reset or media just
2356 // changed. The current state of the device is unclear.
2357 //
2358 Unclear = TRUE;
2359 break;
2360 }
2361
2362 SensePtr++;
2363 }
2364
2365 return Unclear;
2366 }
2367
2368 /**
2369 Check if there is media error according to sense data.
2370
2371 @param[in] SenseData Pointer to sense data.
2372 @param[in] SenseCounts Count of sense data.
2373
2374 @retval TRUE Media error
2375 @retval FALSE No media error
2376
2377 **/
2378 BOOLEAN
IsMediaError(IN ATAPI_REQUEST_SENSE_DATA * SenseData,IN UINTN SenseCounts)2379 IsMediaError (
2380 IN ATAPI_REQUEST_SENSE_DATA *SenseData,
2381 IN UINTN SenseCounts
2382 )
2383 {
2384 ATAPI_REQUEST_SENSE_DATA *SensePtr;
2385 UINTN Index;
2386 BOOLEAN IsError;
2387
2388 IsError = FALSE;
2389
2390 SensePtr = SenseData;
2391
2392 for (Index = 0; Index < SenseCounts; Index++) {
2393
2394 switch (SensePtr->sense_key) {
2395
2396 case ATA_SK_MEDIUM_ERROR:
2397 switch (SensePtr->addnl_sense_code) {
2398 case ATA_ASC_MEDIA_ERR1:
2399 //
2400 // fall through
2401 //
2402 case ATA_ASC_MEDIA_ERR2:
2403 //
2404 // fall through
2405 //
2406 case ATA_ASC_MEDIA_ERR3:
2407 //
2408 // fall through
2409 //
2410 case ATA_ASC_MEDIA_ERR4:
2411 IsError = TRUE;
2412 break;
2413
2414 default:
2415 break;
2416 }
2417
2418 break;
2419
2420 case ATA_SK_NOT_READY:
2421 switch (SensePtr->addnl_sense_code) {
2422 case ATA_ASC_MEDIA_UPSIDE_DOWN:
2423 IsError = TRUE;
2424 break;
2425
2426 default:
2427 break;
2428 }
2429 break;
2430
2431 default:
2432 break;
2433 }
2434
2435 SensePtr++;
2436 }
2437
2438 return IsError;
2439 }
2440
2441 /**
2442 Check if drive is ready according to sense data.
2443
2444 @param[in] SenseData Pointer to sense data.
2445 @param[in] SenseCounts Count of sense data.
2446 @param[out] NeedRetry Indicate if retry is needed.
2447
2448 @retval TRUE Drive ready
2449 @retval FALSE Drive not ready
2450
2451 **/
2452 BOOLEAN
IsDriveReady(IN ATAPI_REQUEST_SENSE_DATA * SenseData,IN UINTN SenseCounts,OUT BOOLEAN * NeedRetry)2453 IsDriveReady (
2454 IN ATAPI_REQUEST_SENSE_DATA *SenseData,
2455 IN UINTN SenseCounts,
2456 OUT BOOLEAN *NeedRetry
2457 )
2458 {
2459 ATAPI_REQUEST_SENSE_DATA *SensePtr;
2460 UINTN Index;
2461 BOOLEAN IsReady;
2462
2463 IsReady = TRUE;
2464 *NeedRetry = FALSE;
2465
2466 SensePtr = SenseData;
2467
2468 for (Index = 0; Index < SenseCounts; Index++) {
2469
2470 switch (SensePtr->sense_key) {
2471
2472 case ATA_SK_NOT_READY:
2473 switch (SensePtr->addnl_sense_code) {
2474 case ATA_ASC_NOT_READY:
2475 switch (SensePtr->addnl_sense_code_qualifier) {
2476 case ATA_ASCQ_IN_PROGRESS:
2477 IsReady = FALSE;
2478 *NeedRetry = TRUE;
2479 break;
2480
2481 default:
2482 IsReady = FALSE;
2483 *NeedRetry = FALSE;
2484 break;
2485 }
2486 break;
2487
2488 default:
2489 break;
2490 }
2491 break;
2492
2493 default:
2494 break;
2495 }
2496
2497 SensePtr++;
2498 }
2499
2500 return IsReady;
2501 }
2502