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