VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxIdeBusDxe/Atapi.c@ 48947

Last change on this file since 48947 was 48947, checked in by vboxsync, 11 years ago

Devices: Whitespace and svn:keyword cleanups by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 54.0 KB
Line 
1/* $Id: Atapi.c 48947 2013-10-07 21:41:00Z vboxsync $ */
2/** @file
3 * Atapi.c
4 */
5
6/*
7 * Copyright (C) 2009-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/** @file
28 This file contains all helper functions on the ATAPI command
29
30 Copyright (c) 2006 - 2008, Intel Corporation
31 All rights reserved. This program and the accompanying materials
32 are licensed and made available under the terms and conditions of the BSD License
33 which accompanies this distribution. The full text of the license may be found at
34 http://opensource.org/licenses/bsd-license.php
35
36 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
37 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
38
39**/
40
41#include "IdeBus.h"
42
43/**
44 This function is used to get the current status of the media residing
45 in the LS-120 drive or ZIP drive. The media status is returned in the
46 Error Status.
47
48 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
49 to record all the information of the IDE device.
50
51 @retval EFI_SUCCESS The media status is achieved successfully and the media
52 can be read/written.
53 @retval EFI_DEVICE_ERROR Get Media Status Command is failed.
54 @retval EFI_NO_MEDIA There is no media in the drive.
55 @retval EFI_WRITE_PROTECTED The media is writing protected.
56
57 @note This function must be called after the LS120EnableMediaStatus()
58 with second parameter set to TRUE
59 (means enable media status notification) is called.
60**/
61EFI_STATUS
62LS120GetMediaStatus (
63 IN IDE_BLK_IO_DEV *IdeDev
64 )
65{
66 UINT8 DeviceSelect;
67 UINT8 StatusValue;
68 EFI_STATUS EfiStatus;
69 //
70 // Poll Alternate Register for BSY clear within timeout.
71 //
72 EfiStatus = WaitForBSYClear2 (IdeDev, ATATIMEOUT);
73 if (EFI_ERROR (EfiStatus)) {
74 return EFI_DEVICE_ERROR;
75 }
76
77 //
78 // Select device via Device/Head Register.
79 //
80 DeviceSelect = (UINT8) ((IdeDev->Device) << 4 | 0xe0);
81 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect);
82
83 //
84 // Poll Alternate Register for DRDY set within timeout.
85 // After device is selected, DRDY set indicates the device is ready to
86 // accept command.
87 //
88 EfiStatus = DRDYReady2 (IdeDev, ATATIMEOUT);
89 if (EFI_ERROR (EfiStatus)) {
90 return EFI_DEVICE_ERROR;
91 }
92
93 //
94 // Get Media Status Command is sent
95 //
96 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0xDA);
97
98 //
99 // BSY bit will clear after command is complete.
100 //
101 EfiStatus = WaitForBSYClear2 (IdeDev, ATATIMEOUT);
102 if (EFI_ERROR (EfiStatus)) {
103 return EFI_DEVICE_ERROR;
104 }
105
106 //
107 // the media status is returned by the command in the ERROR register
108 //
109 StatusValue = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
110
111 if ((StatusValue & BIT1) != 0) {
112 return EFI_NO_MEDIA;
113 }
114
115 if ((StatusValue & BIT6) != 0) {
116 return EFI_WRITE_PROTECTED;
117 } else {
118 return EFI_SUCCESS;
119 }
120}
121/**
122 This function is used to send Enable Media Status Notification Command
123 or Disable Media Status Notification Command.
124
125 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
126 to record all the information of the IDE device.
127
128 @param Enable a flag that indicates whether enable or disable media
129 status notification.
130 @retval EFI_SUCCESS If command completes successfully.
131 @retval EFI_DEVICE_ERROR If command failed.
132**/
133EFI_STATUS
134LS120EnableMediaStatus (
135 IN IDE_BLK_IO_DEV *IdeDev,
136 IN BOOLEAN Enable
137 )
138{
139 UINT8 DeviceSelect;
140 EFI_STATUS Status;
141
142 //
143 // Poll Alternate Register for BSY clear within timeout.
144 //
145 Status = WaitForBSYClear2 (IdeDev, ATATIMEOUT);
146 if (EFI_ERROR (Status)) {
147 return EFI_DEVICE_ERROR;
148 }
149
150 //
151 // Select device via Device/Head Register.
152 //
153 DeviceSelect = (UINT8) ((IdeDev->Device) << 4 | 0xe0);
154 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect);
155
156 //
157 // Poll Alternate Register for DRDY set within timeout.
158 // After device is selected, DRDY set indicates the device is ready to
159 // accept command.
160 //
161 Status = DRDYReady2 (IdeDev, ATATIMEOUT);
162 if (EFI_ERROR (Status)) {
163 return EFI_DEVICE_ERROR;
164 }
165
166 if (Enable) {
167 //
168 // 0x95: Enable media status notification
169 //
170 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x95);
171 } else {
172 //
173 // 0x31: Disable media status notification
174 //
175 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x31);
176 }
177 //
178 // Set Feature Command is sent
179 //
180 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0xEF);
181
182 //
183 // BSY bit will clear after command is complete.
184 //
185 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
186 if (EFI_ERROR (Status)) {
187 return EFI_DEVICE_ERROR;
188 }
189
190 return EFI_SUCCESS;
191}
192/**
193 This function reads the pending data in the device.
194
195 @param IdeDev Indicates the calling context.
196
197 @retval EFI_SUCCESS Successfully read.
198 @retval EFI_NOT_READY The BSY is set avoiding reading.
199
200**/
201EFI_STATUS
202AtapiReadPendingData (
203 IN IDE_BLK_IO_DEV *IdeDev
204 )
205{
206 UINT8 AltRegister;
207 UINT16 TempWordBuffer;
208
209 AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
210 if ((AltRegister & ATA_STSREG_BSY) == ATA_STSREG_BSY) {
211 return EFI_NOT_READY;
212 }
213 if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {
214 TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus);
215 while ((TempWordBuffer & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {
216 IDEReadPortWMultiple (
217 IdeDev->PciIo,
218 IdeDev->IoPort->Data,
219 1,
220 &TempWordBuffer
221 );
222 TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus);
223 }
224 }
225 return EFI_SUCCESS;
226}
227
228/**
229 This function is called by either AtapiPacketCommandIn() or AtapiPacketCommandOut().
230 It is used to transfer data between host and device. The data direction is specified
231 by the fourth parameter.
232
233 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record
234 all the information of the IDE device.
235 @param Buffer buffer contained data transferred between host and device.
236 @param ByteCount data size in byte unit of the buffer.
237 @param Read flag used to determine the data transfer direction.
238 Read equals 1, means data transferred from device to host;
239 Read equals 0, means data transferred from host to device.
240 @param TimeOut timeout value for wait DRQ ready before each data stream's transfer.
241
242 @retval EFI_SUCCESS data is transferred successfully.
243 @retval EFI_DEVICE_ERROR the device failed to transfer data.
244**/
245EFI_STATUS
246PioReadWriteData (
247 IN IDE_BLK_IO_DEV *IdeDev,
248 IN UINT16 *Buffer,
249 IN UINT32 ByteCount,
250 IN BOOLEAN Read,
251 IN UINTN TimeOut
252 )
253{
254 //
255 // required transfer data in word unit.
256 //
257 UINT32 RequiredWordCount;
258
259 //
260 // actual transfer data in word unit.
261 //
262 UINT32 ActualWordCount;
263 UINT32 WordCount;
264 EFI_STATUS Status;
265 UINT16 *PtrBuffer;
266
267 //
268 // No data transfer is permitted.
269 //
270 if (ByteCount == 0) {
271 return EFI_SUCCESS;
272 }
273 //
274 // for performance, we assert the ByteCount is an even number
275 // which is actually a reasonable assumption
276 ASSERT((ByteCount%2) == 0);
277
278 PtrBuffer = Buffer;
279 RequiredWordCount = ByteCount / 2;
280 //
281 // ActuralWordCount means the word count of data really transferred.
282 //
283 ActualWordCount = 0;
284
285 while (ActualWordCount < RequiredWordCount) {
286
287 //
288 // before each data transfer stream, the host should poll DRQ bit ready,
289 // to see whether indicates device is ready to transfer data.
290 //
291 Status = DRQReady2 (IdeDev, TimeOut);
292 if (EFI_ERROR (Status)) {
293 return CheckErrorStatus (IdeDev);
294 }
295
296 //
297 // read Status Register will clear interrupt
298 //
299 IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
300
301 //
302 // get current data transfer size from Cylinder Registers.
303 //
304 WordCount = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) << 8;
305 WordCount = WordCount | IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb);
306 WordCount = WordCount & 0xffff;
307 WordCount /= 2;
308
309 WordCount = MIN (WordCount, (RequiredWordCount - ActualWordCount));
310
311 if (Read) {
312 IDEReadPortWMultiple (
313 IdeDev->PciIo,
314 IdeDev->IoPort->Data,
315 WordCount,
316 PtrBuffer
317 );
318 } else {
319 IDEWritePortWMultiple (
320 IdeDev->PciIo,
321 IdeDev->IoPort->Data,
322 WordCount,
323 PtrBuffer
324 );
325 }
326
327 PtrBuffer += WordCount;
328 ActualWordCount += WordCount;
329 }
330
331 if (Read) {
332 //
333 // In the case where the drive wants to send more data than we need to read,
334 // the DRQ bit will be set and cause delays from DRQClear2().
335 // We need to read data from the drive until it clears DRQ so we can move on.
336 //
337 AtapiReadPendingData (IdeDev);
338 }
339
340 //
341 // After data transfer is completed, normally, DRQ bit should clear.
342 //
343 Status = DRQClear2 (IdeDev, ATAPITIMEOUT);
344 if (EFI_ERROR (Status)) {
345 return EFI_DEVICE_ERROR;
346 }
347
348 //
349 // read status register to check whether error happens.
350 //
351 return CheckErrorStatus (IdeDev);
352}
353
354/**
355 This function is used to send out ATAPI commands conforms to the Packet Command
356 with PIO Data In Protocol.
357
358 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
359 to record all the information of the IDE device.
360 @param Packet pointer pointing to ATAPI_PACKET_COMMAND data structure
361 which contains the contents of the command.
362 @param Buffer buffer contained data transferred from device to host.
363 @param ByteCount data size in byte unit of the buffer.
364 @param TimeOut this parameter is used to specify the timeout value for the
365 PioReadWriteData() function.
366
367 @retval EFI_SUCCESS send out the ATAPI packet command successfully
368 and device sends data successfully.
369 @retval EFI_DEVICE_ERROR the device failed to send data.
370
371**/
372EFI_STATUS
373AtapiPacketCommandIn (
374 IN IDE_BLK_IO_DEV *IdeDev,
375 IN ATAPI_PACKET_COMMAND *Packet,
376 IN UINT16 *Buffer,
377 IN UINT32 ByteCount,
378 IN UINTN TimeOut
379 )
380{
381 UINT16 *CommandIndex;
382 EFI_STATUS Status;
383 UINT32 Count;
384
385 //
386 // Set all the command parameters by fill related registers.
387 // Before write to all the following registers, BSY and DRQ must be 0.
388 //
389 Status = DRQClear2 (IdeDev, ATAPITIMEOUT);
390 if (EFI_ERROR (Status)) {
391 return Status;
392 }
393
394 //
395 // Select device via Device/Head Register.
396 //
397 IDEWritePortB (
398 IdeDev->PciIo,
399 IdeDev->IoPort->Head,
400 (UINT8) ((IdeDev->Device << 4) | ATA_DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000)
401 );
402
403 //
404 // No OVL; No DMA
405 //
406 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00);
407
408 //
409 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
410 // determine how many data should be transferred.
411 //
412 IDEWritePortB (
413 IdeDev->PciIo,
414 IdeDev->IoPort->CylinderLsb,
415 (UINT8) (ATAPI_MAX_BYTE_COUNT & 0x00ff)
416 );
417 IDEWritePortB (
418 IdeDev->PciIo,
419 IdeDev->IoPort->CylinderMsb,
420 (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8)
421 );
422
423 //
424 // ATA_DEFAULT_CTL:0x0a (0000,1010)
425 // Disable interrupt
426 //
427 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, ATA_DEFAULT_CTL);
428
429 //
430 // Send Packet command to inform device
431 // that the following data bytes are command packet.
432 //
433 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, ATA_CMD_PACKET);
434
435 Status = DRQReady (IdeDev, ATAPITIMEOUT);
436 if (EFI_ERROR (Status)) {
437 return Status;
438 }
439
440 //
441 // Send out command packet
442 //
443 CommandIndex = Packet->Data16;
444 for (Count = 0; Count < 6; Count++, CommandIndex++) {
445
446 IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex);
447 gBS->Stall (10);
448 }
449
450 //
451 // call PioReadWriteData() function to get
452 // requested transfer data form device.
453 //
454 return PioReadWriteData (IdeDev, Buffer, ByteCount, 1, TimeOut);
455}
456/**
457 This function is used to send out ATAPI commands conforms to the Packet Command
458 with PIO Data Out Protocol.
459
460 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
461 to record all the information of the IDE device.
462 @param Packet pointer pointing to ATAPI_PACKET_COMMAND data structure
463 which contains the contents of the command.
464 @param Buffer buffer contained data transferred from host to device.
465 @param ByteCount data size in byte unit of the buffer.
466 @param TimeOut this parameter is used to specify the timeout value
467 for the PioReadWriteData() function.
468 @retval EFI_SUCCESS send out the ATAPI packet command successfully
469 and device received data successfully.
470 @retval EFI_DEVICE_ERROR the device failed to send data.
471
472**/
473EFI_STATUS
474AtapiPacketCommandOut (
475 IN IDE_BLK_IO_DEV *IdeDev,
476 IN ATAPI_PACKET_COMMAND *Packet,
477 IN UINT16 *Buffer,
478 IN UINT32 ByteCount,
479 IN UINTN TimeOut
480 )
481{
482 UINT16 *CommandIndex;
483 EFI_STATUS Status;
484 UINT32 Count;
485
486 //
487 // set all the command parameters
488 // Before write to all the following registers, BSY and DRQ must be 0.
489 //
490 Status = DRQClear2 (IdeDev, ATAPITIMEOUT);
491 if (EFI_ERROR (Status)) {
492 return Status;
493 }
494
495 //
496 // Select device via Device/Head Register.
497 //
498 IDEWritePortB (
499 IdeDev->PciIo,
500 IdeDev->IoPort->Head,
501 (UINT8) ((IdeDev->Device << 4) | ATA_DEFAULT_CMD) // ATA_DEFAULT_CMD: 0xa0 (1010,0000)
502 );
503
504 //
505 // No OVL; No DMA
506 //
507 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00);
508
509 //
510 // set the transfersize to ATAPI_MAX_BYTE_COUNT to
511 // let the device determine how many data should be transferred.
512 //
513 IDEWritePortB (
514 IdeDev->PciIo,
515 IdeDev->IoPort->CylinderLsb,
516 (UINT8) (ATAPI_MAX_BYTE_COUNT & 0x00ff)
517 );
518 IDEWritePortB (
519 IdeDev->PciIo,
520 IdeDev->IoPort->CylinderMsb,
521 (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8)
522 );
523
524 //
525 // DEFAULT_CTL:0x0a (0000,1010)
526 // Disable interrupt
527 //
528 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, ATA_DEFAULT_CTL);
529
530 //
531 // Send Packet command to inform device
532 // that the following data bytes are command packet.
533 //
534 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, ATA_CMD_PACKET);
535
536 Status = DRQReady2 (IdeDev, ATAPITIMEOUT);
537 if (EFI_ERROR (Status)) {
538 return Status;
539 }
540
541 //
542 // Send out command packet
543 //
544 CommandIndex = Packet->Data16;
545 for (Count = 0; Count < 6; Count++, CommandIndex++) {
546 IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex);
547 gBS->Stall (10);
548 }
549
550 //
551 // call PioReadWriteData() function to send requested transfer data to device.
552 //
553 return PioReadWriteData (IdeDev, Buffer, ByteCount, 0, TimeOut);
554}
555/**
556 Sends out ATAPI Inquiry Packet Command to the specified device. This command will
557 return INQUIRY data of the device.
558
559 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
560 to record all the information of the IDE device.
561
562 @retval EFI_SUCCESS Inquiry command completes successfully.
563 @retval EFI_DEVICE_ERROR Inquiry command failed.
564
565 @note Parameter "IdeDev" will be updated in this function.
566
567**/
568EFI_STATUS
569AtapiInquiry (
570 IN IDE_BLK_IO_DEV *IdeDev
571 )
572{
573 ATAPI_PACKET_COMMAND Packet;
574 EFI_STATUS Status;
575 ATAPI_INQUIRY_DATA *InquiryData;
576
577 //
578 // prepare command packet for the ATAPI Inquiry Packet Command.
579 //
580 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
581 Packet.Inquiry.opcode = ATA_CMD_INQUIRY;
582 Packet.Inquiry.page_code = 0;
583 Packet.Inquiry.allocation_length = sizeof (ATAPI_INQUIRY_DATA);
584
585 InquiryData = AllocatePool (sizeof (ATAPI_INQUIRY_DATA));
586 if (InquiryData == NULL) {
587 return EFI_DEVICE_ERROR;
588 }
589
590 //
591 // Send command packet and get requested Inquiry data.
592 //
593 Status = AtapiPacketCommandIn (
594 IdeDev,
595 &Packet,
596 (UINT16 *) InquiryData,
597 sizeof (ATAPI_INQUIRY_DATA),
598 ATAPITIMEOUT
599 );
600 if (EFI_ERROR (Status)) {
601 gBS->FreePool (InquiryData);
602 return EFI_DEVICE_ERROR;
603 }
604
605 IdeDev->InquiryData = InquiryData;
606
607 return EFI_SUCCESS;
608}
609/**
610 This function is called by DiscoverIdeDevice() during its device
611 identification.
612 Its main purpose is to get enough information for the device media
613 to fill in the Media data structure of the Block I/O Protocol interface.
614
615 There are 5 steps to reach such objective:
616 1. Sends out the ATAPI Identify Command to the specified device.
617 Only ATAPI device responses to this command. If the command succeeds,
618 it returns the Identify data structure which filled with information
619 about the device. Since the ATAPI device contains removable media,
620 the only meaningful information is the device module name.
621 2. Sends out ATAPI Inquiry Packet Command to the specified device.
622 This command will return inquiry data of the device, which contains
623 the device type information.
624 3. Allocate sense data space for future use. We don't detect the media
625 presence here to improvement boot performance, especially when CD
626 media is present. The media detection will be performed just before
627 each BLK_IO read/write
628
629 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
630 to record all the information of the IDE device.
631
632 @retval EFI_SUCCESS Identify ATAPI device successfully.
633 @retval EFI_DEVICE_ERROR ATAPI Identify Device Command failed or device type
634 is not supported by this IDE driver.
635 @retval EFI_OUT_OF_RESOURCES Allocate memory for sense data failed
636
637 @note Parameter "IdeDev" will be updated in this function.
638**/
639EFI_STATUS
640ATAPIIdentify (
641 IN IDE_BLK_IO_DEV *IdeDev
642 )
643{
644 EFI_IDENTIFY_DATA *AtapiIdentifyPointer;
645 UINT8 DeviceSelect;
646 EFI_STATUS Status;
647
648 //
649 // device select bit
650 //
651 DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
652
653 AtapiIdentifyPointer = AllocatePool (sizeof (EFI_IDENTIFY_DATA));
654 if (AtapiIdentifyPointer == NULL) {
655 return EFI_OUT_OF_RESOURCES;
656 }
657 //
658 // Send ATAPI Identify Command to get IDENTIFY data.
659 //
660 Status = AtaPioDataIn (
661 IdeDev,
662 (VOID *) AtapiIdentifyPointer,
663 sizeof (EFI_IDENTIFY_DATA),
664 ATA_CMD_IDENTIFY_DEVICE,
665 DeviceSelect,
666 0,
667 0,
668 0,
669 0
670 );
671
672 if (EFI_ERROR (Status)) {
673 gBS->FreePool (AtapiIdentifyPointer);
674 return EFI_DEVICE_ERROR;
675 }
676
677 IdeDev->IdData = AtapiIdentifyPointer;
678 PrintAtaModuleName (IdeDev);
679
680 //
681 // Send ATAPI Inquiry Packet Command to get INQUIRY data.
682 //
683 Status = AtapiInquiry (IdeDev);
684 if (EFI_ERROR (Status)) {
685 gBS->FreePool (IdeDev->IdData);
686 //
687 // Make sure the pIdData will not be freed again.
688 //
689 IdeDev->IdData = NULL;
690 return EFI_DEVICE_ERROR;
691 }
692 //
693 // Get media removable info from INQUIRY data.
694 //
695 IdeDev->BlkIo.Media->RemovableMedia = (UINT8) ((IdeDev->InquiryData->RMB & 0x80) == 0x80);
696
697 //
698 // Identify device type via INQUIRY data.
699 //
700 switch (IdeDev->InquiryData->peripheral_type & 0x1f) {
701
702 //
703 // Magnetic Disk
704 //
705 case 0x00:
706
707 //
708 // device is LS120 or ZIP drive.
709 //
710 IdeDev->Type = IdeMagnetic;
711
712 IdeDev->BlkIo.Media->MediaId = 0;
713 //
714 // Give initial value
715 //
716 IdeDev->BlkIo.Media->MediaPresent = FALSE;
717
718 IdeDev->BlkIo.Media->LastBlock = 0;
719 IdeDev->BlkIo.Media->BlockSize = 0x200;
720 break;
721
722 //
723 // CD-ROM
724 //
725 case 0x05:
726
727 IdeDev->Type = IdeCdRom;
728 IdeDev->BlkIo.Media->MediaId = 0;
729 //
730 // Give initial value
731 //
732 IdeDev->BlkIo.Media->MediaPresent = FALSE;
733
734 IdeDev->BlkIo.Media->LastBlock = 0;
735 IdeDev->BlkIo.Media->BlockSize = 0x800;
736 IdeDev->BlkIo.Media->ReadOnly = TRUE;
737 break;
738
739 //
740 // Tape
741 //
742 case 0x01:
743
744 //
745 // WORM
746 //
747 case 0x04:
748
749 //
750 // Optical
751 //
752 case 0x07:
753
754 default:
755 IdeDev->Type = IdeUnknown;
756 gBS->FreePool (IdeDev->IdData);
757 gBS->FreePool (IdeDev->InquiryData);
758 //
759 // Make sure the pIdData and pInquiryData will not be freed again.
760 //
761 IdeDev->IdData = NULL;
762 IdeDev->InquiryData = NULL;
763 return EFI_DEVICE_ERROR;
764 }
765
766 //
767 // original sense data numbers
768 //
769 IdeDev->SenseDataNumber = 20;
770
771 IdeDev->SenseData = AllocatePool (IdeDev->SenseDataNumber * sizeof (ATAPI_REQUEST_SENSE_DATA));
772 if (IdeDev->SenseData == NULL) {
773 gBS->FreePool (IdeDev->IdData);
774 gBS->FreePool (IdeDev->InquiryData);
775 //
776 // Make sure the pIdData and pInquiryData will not be freed again.
777 //
778 IdeDev->IdData = NULL;
779 IdeDev->InquiryData = NULL;
780 return EFI_OUT_OF_RESOURCES;
781 }
782
783 return EFI_SUCCESS;
784}
785/**
786 Sends out ATAPI Request Sense Packet Command to the specified device. This command
787 will return all the current Sense data in the device. This function will pack
788 all the Sense data in one single buffer.
789
790 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
791 to record all the information of the IDE device.
792 @param SenseCounts allocated in this function, and freed by the calling function.
793 This buffer is used to accommodate all the sense data returned
794 by the device.
795
796 @retval EFI_SUCCESS Request Sense command completes successfully.
797 @retval EFI_DEVICE_ERROR Request Sense command failed.
798**/
799EFI_STATUS
800AtapiRequestSense (
801 IN IDE_BLK_IO_DEV *IdeDev,
802 OUT UINTN *SenseCounts
803 )
804{
805 EFI_STATUS Status;
806 ATAPI_REQUEST_SENSE_DATA *Sense;
807 UINT16 *Ptr;
808 BOOLEAN FetchSenseData;
809 ATAPI_PACKET_COMMAND Packet;
810
811 *SenseCounts = 0;
812
813 ZeroMem (IdeDev->SenseData, sizeof (ATAPI_REQUEST_SENSE_DATA) * (IdeDev->SenseDataNumber));
814 //
815 // fill command packet for Request Sense Packet Command
816 //
817 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
818 Packet.RequestSence.opcode = ATA_CMD_REQUEST_SENSE;
819 Packet.RequestSence.allocation_length = sizeof (ATAPI_REQUEST_SENSE_DATA);
820
821 //
822 // initialize pointer
823 //
824 Ptr = (UINT16 *) IdeDev->SenseData;
825 //
826 // request sense data from device continuously until no sense data
827 // exists in the device.
828 //
829 for (FetchSenseData = TRUE; FetchSenseData;) {
830
831 Sense = (ATAPI_REQUEST_SENSE_DATA *) Ptr;
832
833 //
834 // send out Request Sense Packet Command and get one Sense data form device
835 //
836 Status = AtapiPacketCommandIn (
837 IdeDev,
838 &Packet,
839 Ptr,
840 sizeof (ATAPI_REQUEST_SENSE_DATA),
841 ATAPITIMEOUT
842 );
843 //
844 // failed to get Sense data
845 //
846 if (EFI_ERROR (Status)) {
847 if (*SenseCounts == 0) {
848 return EFI_DEVICE_ERROR;
849 } else {
850 return EFI_SUCCESS;
851 }
852 }
853
854 (*SenseCounts)++;
855 //
856 // We limit MAX sense data count to 20 in order to avoid dead loop. Some
857 // incompatible ATAPI devices don't retrieve NO_SENSE when there is no media.
858 // In this case, dead loop occurs if we don't have a gatekeeper. 20 is
859 // supposed to be large enough for any ATAPI device.
860 //
861 if ((Sense->sense_key != ATA_SK_NO_SENSE) && ((*SenseCounts) < 20)) {
862 //
863 // Ptr is word-based pointer
864 //
865 Ptr += (sizeof (ATAPI_REQUEST_SENSE_DATA) + 1) >> 1;
866
867 } else {
868 //
869 // when no sense key, skip out the loop
870 //
871 FetchSenseData = FALSE;
872 }
873 }
874
875 return EFI_SUCCESS;
876}
877/**
878 This function is used to parse sense data. Only the first sense data is honoured
879
880 @param IdeDev Indicates the calling context.
881 @param SenseCount Count of sense data.
882 @param Result The parsed result.
883
884 @retval EFI_SUCCESS Successfully parsed.
885 @retval EFI_INVALID_PARAMETER Count of sense data is zero.
886
887**/
888EFI_STATUS
889ParseSenseData (
890 IN IDE_BLK_IO_DEV *IdeDev,
891 IN UINTN SenseCount,
892 OUT SENSE_RESULT *Result
893 )
894{
895 ATAPI_REQUEST_SENSE_DATA *SenseData;
896
897 if (SenseCount == 0) {
898 return EFI_INVALID_PARAMETER;
899 }
900
901 //
902 // Only use the first sense data
903 //
904 SenseData = IdeDev->SenseData;
905 *Result = SenseOtherSense;
906
907 switch (SenseData->sense_key) {
908 case ATA_SK_NO_SENSE:
909 *Result = SenseNoSenseKey;
910 break;
911 case ATA_SK_NOT_READY:
912 switch (SenseData->addnl_sense_code) {
913 case ATA_ASC_NO_MEDIA:
914 *Result = SenseNoMedia;
915 break;
916 case ATA_ASC_MEDIA_UPSIDE_DOWN:
917 *Result = SenseMediaError;
918 break;
919 case ATA_ASC_NOT_READY:
920 if (SenseData->addnl_sense_code_qualifier == ATA_ASCQ_IN_PROGRESS) {
921 *Result = SenseDeviceNotReadyNeedRetry;
922 } else {
923 *Result = SenseDeviceNotReadyNoRetry;
924 }
925 break;
926 }
927 break;
928 case ATA_SK_UNIT_ATTENTION:
929 if (SenseData->addnl_sense_code == ATA_ASC_MEDIA_CHANGE) {
930 *Result = SenseMediaChange;
931 }
932 break;
933 case ATA_SK_MEDIUM_ERROR:
934 switch (SenseData->addnl_sense_code) {
935 case ATA_ASC_MEDIA_ERR1:
936 case ATA_ASC_MEDIA_ERR2:
937 case ATA_ASC_MEDIA_ERR3:
938 case ATA_ASC_MEDIA_ERR4:
939 *Result = SenseMediaError;
940 break;
941 }
942 break;
943 default:
944 break;
945 }
946
947 return EFI_SUCCESS;
948}
949
950/**
951 Sends out ATAPI Test Unit Ready Packet Command to the specified device
952 to find out whether device is accessible.
953
954 @param IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used
955 to record all the information of the IDE device.
956 @param SResult Sense result for this packet command.
957
958 @retval EFI_SUCCESS Device is accessible.
959 @retval EFI_DEVICE_ERROR Device is not accessible.
960
961**/
962EFI_STATUS
963AtapiTestUnitReady (
964 IN IDE_BLK_IO_DEV *IdeDev,
965 OUT SENSE_RESULT *SResult
966 )
967{
968 ATAPI_PACKET_COMMAND Packet;
969 EFI_STATUS Status;
970 UINTN SenseCount;
971
972 //
973 // fill command packet
974 //
975 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
976 Packet.TestUnitReady.opcode = ATA_CMD_TEST_UNIT_READY;
977
978 //
979 // send command packet
980 //
981 Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT);
982 if (EFI_ERROR (Status)) {
983 return Status;
984 }
985
986 Status = AtapiRequestSense (IdeDev, &SenseCount);
987 if (EFI_ERROR (Status)) {
988 return Status;
989 }
990
991 ParseSenseData (IdeDev, SenseCount, SResult);
992 return EFI_SUCCESS;
993}
994
995
996/**
997 Sends out ATAPI Read Capacity Packet Command to the specified device.
998 This command will return the information regarding the capacity of the
999 media in the device.
1000
1001 Current device status will impact device's response to the Read Capacity
1002 Command. For example, if the device once reset, the Read Capacity
1003 Command will fail. The Sense data record the current device status, so
1004 if the Read Capacity Command failed, the Sense data must be requested
1005 and be analyzed to determine if the Read Capacity Command should retry.
1006
1007 @param IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used
1008 to record all the information of the IDE device.
1009 @param SResult Sense result for this packet command
1010
1011 @retval EFI_SUCCESS Read Capacity Command finally completes successfully.
1012 @retval EFI_DEVICE_ERROR Read Capacity Command failed because of device error.
1013 @retval EFI_NOT_READY Operation succeeds but returned capacity is 0
1014
1015 @note Parameter "IdeDev" will be updated in this function.
1016
1017
1018**/
1019EFI_STATUS
1020AtapiReadCapacity (
1021 IN IDE_BLK_IO_DEV *IdeDev,
1022 OUT SENSE_RESULT *SResult
1023 )
1024{
1025 //
1026 // status returned by Read Capacity Packet Command
1027 //
1028 EFI_STATUS Status;
1029 EFI_STATUS SenseStatus;
1030 ATAPI_PACKET_COMMAND Packet;
1031 UINTN SenseCount;
1032
1033 //
1034 // used for capacity data returned from ATAPI device
1035 //
1036 ATAPI_READ_CAPACITY_DATA Data;
1037 ATAPI_READ_FORMAT_CAPACITY_DATA FormatData;
1038
1039 ZeroMem (&Data, sizeof (Data));
1040 ZeroMem (&FormatData, sizeof (FormatData));
1041
1042 if (IdeDev->Type == IdeCdRom) {
1043
1044 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1045 Packet.Inquiry.opcode = ATA_CMD_READ_CAPACITY;
1046 Status = AtapiPacketCommandIn (
1047 IdeDev,
1048 &Packet,
1049 (UINT16 *) &Data,
1050 sizeof (ATAPI_READ_CAPACITY_DATA),
1051 ATAPITIMEOUT
1052 );
1053
1054 } else {
1055 //
1056 // Type == IdeMagnetic
1057 //
1058 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1059 Packet.ReadFormatCapacity.opcode = ATA_CMD_READ_FORMAT_CAPACITY;
1060 Packet.ReadFormatCapacity.allocation_length_lo = 12;
1061 Status = AtapiPacketCommandIn (
1062 IdeDev,
1063 &Packet,
1064 (UINT16 *) &FormatData,
1065 sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA),
1066 ATAPITIMEOUT
1067 );
1068 }
1069
1070 if (Status == EFI_TIMEOUT) {
1071 return Status;
1072 }
1073
1074 SenseStatus = AtapiRequestSense (IdeDev, &SenseCount);
1075
1076 if (!EFI_ERROR (SenseStatus)) {
1077 ParseSenseData (IdeDev, SenseCount, SResult);
1078
1079 if (!EFI_ERROR (Status) && *SResult == SenseNoSenseKey) {
1080 if (IdeDev->Type == IdeCdRom) {
1081
1082 IdeDev->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) |
1083 (Data.LastLba2 << 16) |
1084 (Data.LastLba1 << 8) |
1085 Data.LastLba0;
1086
1087 IdeDev->BlkIo.Media->MediaPresent = TRUE;
1088
1089 IdeDev->BlkIo.Media->ReadOnly = TRUE;
1090
1091 //
1092 // Because the user data portion in the sector of the Data CD supported
1093 // is always 0x800
1094 //
1095 IdeDev->BlkIo.Media->BlockSize = 0x800;
1096 }
1097
1098 if (IdeDev->Type == IdeMagnetic) {
1099
1100 if (FormatData.DesCode == 3) {
1101 IdeDev->BlkIo.Media->MediaPresent = FALSE;
1102 IdeDev->BlkIo.Media->LastBlock = 0;
1103 } else {
1104
1105 IdeDev->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) |
1106 (FormatData.LastLba2 << 16) |
1107 (FormatData.LastLba1 << 8) |
1108 FormatData.LastLba0;
1109 if (IdeDev->BlkIo.Media->LastBlock != 0) {
1110 IdeDev->BlkIo.Media->LastBlock--;
1111
1112 IdeDev->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) |
1113 (FormatData.BlockSize1 << 8) |
1114 FormatData.BlockSize0;
1115
1116 IdeDev->BlkIo.Media->MediaPresent = TRUE;
1117 } else {
1118 IdeDev->BlkIo.Media->MediaPresent = FALSE;
1119 //
1120 // Return EFI_NOT_READY operation succeeds but returned capacity is 0
1121 //
1122 return EFI_NOT_READY;
1123 }
1124
1125 IdeDev->BlkIo.Media->BlockSize = 0x200;
1126
1127 }
1128 }
1129 }
1130
1131 return EFI_SUCCESS;
1132
1133 } else {
1134 return EFI_DEVICE_ERROR;
1135 }
1136}
1137/**
1138 This function is used to test the current media write-protected or not residing
1139 in the LS-120 drive or ZIP drive.
1140 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
1141 to record all the information of the IDE device.
1142 @param WriteProtected if True, current media is write protected.
1143 if FALSE, current media is writable
1144
1145 @retval EFI_SUCCESS The media write-protected status is achieved successfully
1146 @retval EFI_DEVICE_ERROR Get Media Status Command is failed.
1147**/
1148EFI_STATUS
1149IsLS120orZipWriteProtected (
1150 IN IDE_BLK_IO_DEV *IdeDev,
1151 OUT BOOLEAN *WriteProtected
1152 )
1153{
1154 EFI_STATUS Status;
1155
1156 *WriteProtected = FALSE;
1157
1158 Status = LS120EnableMediaStatus (IdeDev, TRUE);
1159 if (EFI_ERROR (Status)) {
1160 return EFI_DEVICE_ERROR;
1161 }
1162
1163 //
1164 // the Get Media Status Command is only valid
1165 // if a Set Features/Enable Media Status Command has been previously issued.
1166 //
1167 if (LS120GetMediaStatus (IdeDev) == EFI_WRITE_PROTECTED) {
1168
1169 *WriteProtected = TRUE;
1170 } else {
1171
1172 *WriteProtected = FALSE;
1173 }
1174
1175 //
1176 // After Get Media Status Command completes,
1177 // Set Features/Disable Media Command should be sent.
1178 //
1179 Status = LS120EnableMediaStatus (IdeDev, FALSE);
1180 if (EFI_ERROR (Status)) {
1181 return EFI_DEVICE_ERROR;
1182 }
1183
1184 return EFI_SUCCESS;
1185}
1186
1187/**
1188 Used before read/write blocks from/to ATAPI device media. Since ATAPI device
1189 media is removable, it is necessary to detect whether media is present and
1190 get current present media's information, and if media has been changed, Block
1191 I/O Protocol need to be reinstalled.
1192
1193 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
1194 to record all the information of the IDE device.
1195 @param MediaChange return value that indicates if the media of the device has been
1196 changed.
1197
1198 @retval EFI_SUCCESS media found successfully.
1199 @retval EFI_DEVICE_ERROR any error encounters during media detection.
1200 @retval EFI_NO_MEDIA media not found.
1201
1202 @note
1203 parameter IdeDev may be updated in this function.
1204
1205**/
1206EFI_STATUS
1207AtapiDetectMedia (
1208 IN IDE_BLK_IO_DEV *IdeDev,
1209 OUT BOOLEAN *MediaChange
1210 )
1211{
1212 EFI_STATUS Status;
1213 EFI_STATUS CleanStateStatus;
1214 EFI_BLOCK_IO_MEDIA OldMediaInfo;
1215 UINTN RetryTimes;
1216 UINTN RetryNotReady;
1217 SENSE_RESULT SResult;
1218 BOOLEAN WriteProtected;
1219
1220 CopyMem (&OldMediaInfo, IdeDev->BlkIo.Media, sizeof (EFI_BLOCK_IO_MEDIA));
1221 *MediaChange = FALSE;
1222 //
1223 // Retry for SenseDeviceNotReadyNeedRetry.
1224 // Each retry takes 1s and we limit the upper boundary to
1225 // 120 times about 2 min.
1226 //
1227 RetryNotReady = 120;
1228
1229 //
1230 // Do Test Unit Ready
1231 //
1232 DoTUR:
1233 //
1234 // Retry 5 times
1235 //
1236 RetryTimes = 5;
1237 while (RetryTimes != 0) {
1238
1239 Status = AtapiTestUnitReady (IdeDev, &SResult);
1240
1241 if (EFI_ERROR (Status)) {
1242 //
1243 // Test Unit Ready error without sense data.
1244 // For some devices, this means there's extra data
1245 // that has not been read, so we read these extra
1246 // data out before going on.
1247 //
1248 CleanStateStatus = AtapiReadPendingData (IdeDev);
1249 if (EFI_ERROR (CleanStateStatus)) {
1250 //
1251 // Busy wait failed, try again
1252 //
1253 RetryTimes--;
1254 }
1255 //
1256 // Try again without counting down RetryTimes
1257 //
1258 continue;
1259 } else {
1260 switch (SResult) {
1261 case SenseNoSenseKey:
1262 if (IdeDev->BlkIo.Media->MediaPresent) {
1263 goto Done;
1264 } else {
1265 //
1266 // Media present but the internal structure need refreshed.
1267 // Try Read Capacity
1268 //
1269 goto DoRC;
1270 }
1271 break;
1272
1273 case SenseDeviceNotReadyNeedRetry:
1274 if (--RetryNotReady == 0) {
1275 return EFI_DEVICE_ERROR;
1276 }
1277 gBS->Stall (1000 * STALL_1_MILLI_SECOND);
1278 continue;
1279 break;
1280
1281 case SenseNoMedia:
1282 IdeDev->BlkIo.Media->MediaPresent = FALSE;
1283 IdeDev->BlkIo.Media->LastBlock = 0;
1284 goto Done;
1285 break;
1286
1287 case SenseDeviceNotReadyNoRetry:
1288 case SenseMediaError:
1289 return EFI_DEVICE_ERROR;
1290
1291 case SenseMediaChange:
1292 IdeDev->BlkIo.Media->MediaId++;
1293 goto DoRC;
1294 break;
1295
1296 default:
1297 RetryTimes--;
1298 break;
1299 }
1300 }
1301 }
1302
1303 return EFI_DEVICE_ERROR;
1304
1305 //
1306 // Do Read Capacity
1307 //
1308 DoRC:
1309 RetryTimes = 5;
1310
1311 while (RetryTimes != 0) {
1312
1313 Status = AtapiReadCapacity (IdeDev, &SResult);
1314
1315 if (EFI_ERROR (Status)) {
1316 RetryTimes--;
1317 continue;
1318 } else {
1319 switch (SResult) {
1320 case SenseNoSenseKey:
1321 goto Done;
1322 break;
1323
1324 case SenseDeviceNotReadyNeedRetry:
1325 //
1326 // We use Test Unit Ready to retry which
1327 // is faster.
1328 //
1329 goto DoTUR;
1330 break;
1331
1332 case SenseNoMedia:
1333 IdeDev->BlkIo.Media->MediaPresent = FALSE;
1334 IdeDev->BlkIo.Media->LastBlock = 0;
1335 goto Done;
1336 break;
1337
1338 case SenseDeviceNotReadyNoRetry:
1339 case SenseMediaError:
1340 return EFI_DEVICE_ERROR;
1341
1342 case SenseMediaChange:
1343 IdeDev->BlkIo.Media->MediaId++;
1344 continue;
1345 break;
1346
1347 default:
1348 RetryTimes--;
1349 break;
1350 }
1351 }
1352 }
1353
1354 return EFI_DEVICE_ERROR;
1355
1356 Done:
1357 //
1358 // the following code is to check the write-protected for LS120 media
1359 //
1360 if ((IdeDev->BlkIo.Media->MediaPresent) && (IdeDev->Type == IdeMagnetic)) {
1361
1362 Status = IsLS120orZipWriteProtected (IdeDev, &WriteProtected);
1363 if (!EFI_ERROR (Status)) {
1364
1365 if (WriteProtected) {
1366
1367 IdeDev->BlkIo.Media->ReadOnly = TRUE;
1368 } else {
1369
1370 IdeDev->BlkIo.Media->ReadOnly = FALSE;
1371 }
1372
1373 }
1374 }
1375
1376 if (IdeDev->BlkIo.Media->MediaId != OldMediaInfo.MediaId) {
1377 //
1378 // Media change information got from the device
1379 //
1380 *MediaChange = TRUE;
1381 }
1382
1383 if (IdeDev->BlkIo.Media->ReadOnly != OldMediaInfo.ReadOnly) {
1384 *MediaChange = TRUE;
1385 IdeDev->BlkIo.Media->MediaId += 1;
1386 }
1387
1388 if (IdeDev->BlkIo.Media->BlockSize != OldMediaInfo.BlockSize) {
1389 *MediaChange = TRUE;
1390 IdeDev->BlkIo.Media->MediaId += 1;
1391 }
1392
1393 if (IdeDev->BlkIo.Media->LastBlock != OldMediaInfo.LastBlock) {
1394 *MediaChange = TRUE;
1395 IdeDev->BlkIo.Media->MediaId += 1;
1396 }
1397
1398 if (IdeDev->BlkIo.Media->MediaPresent != OldMediaInfo.MediaPresent) {
1399 if (IdeDev->BlkIo.Media->MediaPresent) {
1400 //
1401 // when change from no media to media present, reset the MediaId to 1.
1402 //
1403 IdeDev->BlkIo.Media->MediaId = 1;
1404 } else {
1405 //
1406 // when no media, reset the MediaId to zero.
1407 //
1408 IdeDev->BlkIo.Media->MediaId = 0;
1409 }
1410
1411 *MediaChange = TRUE;
1412 }
1413
1414 //
1415 // if any change on current existing media,
1416 // the Block I/O protocol need to be reinstalled.
1417 //
1418 if (*MediaChange) {
1419 gBS->ReinstallProtocolInterface (
1420 IdeDev->Handle,
1421 &gEfiBlockIoProtocolGuid,
1422 &IdeDev->BlkIo,
1423 &IdeDev->BlkIo
1424 );
1425 }
1426
1427 if (IdeDev->BlkIo.Media->MediaPresent) {
1428 return EFI_SUCCESS;
1429 } else {
1430 return EFI_NO_MEDIA;
1431 }
1432}
1433
1434/**
1435 This function is called by the AtapiBlkIoReadBlocks() to perform
1436 read from media in block unit.
1437
1438 The main command used to access media here is READ(10) Command.
1439 READ(10) Command requests that the ATAPI device media transfer
1440 specified data to the host. Data is transferred in block(sector)
1441 unit. The maximum number of blocks that can be transferred once is
1442 65536. This is the main difference between READ(10) and READ(12)
1443 Command. The maximum number of blocks in READ(12) is 2 power 32.
1444
1445 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
1446 to record all the information of the IDE device.
1447 @param Buffer A pointer to the destination buffer for the data.
1448 @param Lba The starting logical block address to read from on the
1449 device media.
1450 @param NumberOfBlocks The number of transfer data blocks.
1451
1452 @return status is fully dependent on the return status of AtapiPacketCommandIn() function.
1453
1454**/
1455EFI_STATUS
1456AtapiReadSectors (
1457 IN IDE_BLK_IO_DEV *IdeDev,
1458 IN VOID *Buffer,
1459 IN EFI_LBA Lba,
1460 IN UINTN NumberOfBlocks
1461 )
1462{
1463
1464 ATAPI_PACKET_COMMAND Packet;
1465 ATAPI_READ10_CMD *Read10Packet;
1466 EFI_STATUS Status;
1467 UINTN BlocksRemaining;
1468 UINT32 Lba32;
1469 UINT32 BlockSize;
1470 UINT32 ByteCount;
1471 UINT16 SectorCount;
1472 VOID *PtrBuffer;
1473 UINT16 MaxBlock;
1474 UINTN TimeOut;
1475
1476 //
1477 // fill command packet for Read(10) command
1478 //
1479 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1480 Read10Packet = &Packet.Read10;
1481 Lba32 = (UINT32) Lba;
1482 PtrBuffer = Buffer;
1483
1484 BlockSize = IdeDev->BlkIo.Media->BlockSize;
1485
1486 //
1487 // limit the data bytes that can be transferred by one Read(10) Command
1488 //
1489 MaxBlock = 65535;
1490
1491 BlocksRemaining = NumberOfBlocks;
1492
1493 Status = EFI_SUCCESS;
1494 while (BlocksRemaining > 0) {
1495
1496 if (BlocksRemaining <= MaxBlock) {
1497
1498 SectorCount = (UINT16) BlocksRemaining;
1499 } else {
1500
1501 SectorCount = MaxBlock;
1502 }
1503
1504 //
1505 // fill the Packet data structure
1506 //
1507
1508 Read10Packet->opcode = ATA_CMD_READ_10;
1509
1510 //
1511 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
1512 // Lba0 is MSB, Lba3 is LSB
1513 //
1514 Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
1515 Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
1516 Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
1517 Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
1518
1519 //
1520 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
1521 // TranLen0 is MSB, TranLen is LSB
1522 //
1523 Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
1524 Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
1525
1526 ByteCount = SectorCount * BlockSize;
1527
1528 if (IdeDev->Type == IdeCdRom) {
1529 TimeOut = CDROMLONGTIMEOUT;
1530 } else {
1531 TimeOut = ATAPILONGTIMEOUT;
1532 }
1533
1534 Status = AtapiPacketCommandIn (
1535 IdeDev,
1536 &Packet,
1537 (UINT16 *) PtrBuffer,
1538 ByteCount,
1539 TimeOut
1540 );
1541 if (EFI_ERROR (Status)) {
1542 return Status;
1543 }
1544
1545 Lba32 += SectorCount;
1546 PtrBuffer = (UINT8 *) PtrBuffer + SectorCount * BlockSize;
1547 BlocksRemaining -= SectorCount;
1548 }
1549
1550 return Status;
1551}
1552
1553/**
1554 This function is called by the AtapiBlkIoWriteBlocks() to perform
1555 write onto media in block unit.
1556 The main command used to access media here is Write(10) Command.
1557 Write(10) Command requests that the ATAPI device media transfer
1558 specified data to the host. Data is transferred in block (sector)
1559 unit. The maximum number of blocks that can be transferred once is
1560 65536.
1561
1562 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
1563 to record all the information of the IDE device.
1564 @param Buffer A pointer to the source buffer for the data.
1565 @param Lba The starting logical block address to write onto
1566 the device media.
1567 @param NumberOfBlocks The number of transfer data blocks.
1568
1569 @return status is fully dependent on the return status of AtapiPacketCommandOut() function.
1570
1571**/
1572EFI_STATUS
1573AtapiWriteSectors (
1574 IN IDE_BLK_IO_DEV *IdeDev,
1575 IN VOID *Buffer,
1576 IN EFI_LBA Lba,
1577 IN UINTN NumberOfBlocks
1578 )
1579{
1580
1581 ATAPI_PACKET_COMMAND Packet;
1582 ATAPI_READ10_CMD *Read10Packet;
1583
1584 EFI_STATUS Status;
1585 UINTN BlocksRemaining;
1586 UINT32 Lba32;
1587 UINT32 BlockSize;
1588 UINT32 ByteCount;
1589 UINT16 SectorCount;
1590 VOID *PtrBuffer;
1591 UINT16 MaxBlock;
1592
1593 //
1594 // fill command packet for Write(10) command
1595 // Write(10) command packet has the same data structure as
1596 // Read(10) command packet,
1597 // so here use the Read10Packet data structure
1598 // for the Write(10) command packet.
1599 //
1600 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
1601 Read10Packet = &Packet.Read10;
1602
1603 Lba32 = (UINT32) Lba;
1604 PtrBuffer = Buffer;
1605
1606 BlockSize = IdeDev->BlkIo.Media->BlockSize;
1607
1608 //
1609 // limit the data bytes that can be transferred by one Read(10) Command
1610 //
1611 MaxBlock = (UINT16) (65536 / BlockSize);
1612
1613 BlocksRemaining = NumberOfBlocks;
1614
1615 Status = EFI_SUCCESS;
1616 while (BlocksRemaining > 0) {
1617
1618 if (BlocksRemaining >= MaxBlock) {
1619 SectorCount = MaxBlock;
1620 } else {
1621 SectorCount = (UINT16) BlocksRemaining;
1622 }
1623
1624 //
1625 // Command code is WRITE_10.
1626 //
1627 Read10Packet->opcode = ATA_CMD_WRITE_10;
1628
1629 //
1630 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
1631 // Lba0 is MSB, Lba3 is LSB
1632 //
1633 Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
1634 Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
1635 Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
1636 Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
1637
1638 //
1639 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
1640 // TranLen0 is MSB, TranLen is LSB
1641 //
1642 Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
1643 Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
1644
1645 ByteCount = SectorCount * BlockSize;
1646
1647 Status = AtapiPacketCommandOut (
1648 IdeDev,
1649 &Packet,
1650 (UINT16 *) PtrBuffer,
1651 ByteCount,
1652 ATAPILONGTIMEOUT
1653 );
1654 if (EFI_ERROR (Status)) {
1655 return Status;
1656 }
1657
1658 Lba32 += SectorCount;
1659 PtrBuffer = ((UINT8 *) PtrBuffer + SectorCount * BlockSize);
1660 BlocksRemaining -= SectorCount;
1661 }
1662
1663 return Status;
1664}
1665/**
1666 This function is used to implement the Soft Reset on the specified
1667 ATAPI device. Different from the AtaSoftReset(), here reset is a ATA
1668 Soft Reset Command special for ATAPI device, and it only take effects
1669 on the specified ATAPI device, not on the whole IDE bus.
1670 Since the ATAPI soft reset is needed when device is in exceptional
1671 condition (such as BSY bit is always set ), I think the Soft Reset
1672 command should be sent without waiting for the BSY clear and DRDY
1673 set.
1674 This function is called by IdeBlkIoReset(),
1675 a interface function of Block I/O protocol.
1676
1677 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used
1678 to record all the information of the IDE device.
1679
1680 @retval EFI_SUCCESS Soft reset completes successfully.
1681 @retval EFI_DEVICE_ERROR Any step during the reset process is failed.
1682
1683**/
1684EFI_STATUS
1685AtapiSoftReset (
1686 IN IDE_BLK_IO_DEV *IdeDev
1687 )
1688{
1689 UINT8 Command;
1690 UINT8 DeviceSelect;
1691 EFI_STATUS Status;
1692
1693 //
1694 // for ATAPI device, no need to wait DRDY ready after device selecting.
1695 // (bit7 and bit5 are both set to 1 for backward compatibility)
1696 //
1697 DeviceSelect = (UINT8) (((BIT7 | BIT5) | (IdeDev->Device << 4)));
1698 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect);
1699
1700 Command = ATA_CMD_SOFT_RESET;
1701 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, Command);
1702
1703 //
1704 // BSY cleared is the only status return to the host by the device
1705 // when reset is completed.
1706 // slave device needs at most 31s to clear BSY
1707 //
1708 Status = WaitForBSYClear (IdeDev, 31000);
1709 if (EFI_ERROR (Status)) {
1710 return EFI_DEVICE_ERROR;
1711 }
1712
1713 //
1714 // stall 5 seconds to make the device status stable
1715 //
1716 gBS->Stall (5000000);
1717
1718 return EFI_SUCCESS;
1719}
1720
1721/**
1722 This function is the ATAPI implementation for ReadBlocks in the
1723 Block I/O Protocol interface.
1724
1725 @param IdeBlkIoDevice Indicates the calling context.
1726 @param MediaId The media id that the read request is for.
1727 @param Lba The starting logical block address to read from on the device.
1728 @param BufferSize The size of the Buffer in bytes. This must be a multiple
1729 of the intrinsic block size of the device.
1730 @param Buffer A pointer to the destination buffer for the data. The caller
1731 is responsible for either having implicit or explicit
1732 ownership of the memory that data is read into.
1733
1734 @retval EFI_SUCCESS Read Blocks successfully.
1735 @retval EFI_DEVICE_ERROR Read Blocks failed.
1736 @retval EFI_NO_MEDIA There is no media in the device.
1737 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1738 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
1739 intrinsic block size of the device.
1740 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
1741 or the data buffer is not valid.
1742**/
1743EFI_STATUS
1744AtapiBlkIoReadBlocks (
1745 IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
1746 IN UINT32 MediaId,
1747 IN EFI_LBA Lba,
1748 IN UINTN BufferSize,
1749 OUT VOID *Buffer
1750 )
1751{
1752 EFI_BLOCK_IO_MEDIA *Media;
1753 UINTN BlockSize;
1754 UINTN NumberOfBlocks;
1755 EFI_STATUS Status;
1756
1757 BOOLEAN MediaChange;
1758
1759 if (Buffer == NULL) {
1760 return EFI_INVALID_PARAMETER;
1761 }
1762
1763 if (BufferSize == 0) {
1764 return EFI_SUCCESS;
1765 }
1766
1767 //
1768 // ATAPI device media is removable, so it is a must
1769 // to detect media first before read operation
1770 //
1771 MediaChange = FALSE;
1772 Status = AtapiDetectMedia (IdeBlkIoDevice, &MediaChange);
1773 if (EFI_ERROR (Status)) {
1774
1775 if (IdeBlkIoDevice->Cache != NULL) {
1776 gBS->FreePool (IdeBlkIoDevice->Cache);
1777 IdeBlkIoDevice->Cache = NULL;
1778 }
1779
1780 return Status;
1781 }
1782 //
1783 // Get the intrinsic block size
1784 //
1785 Media = IdeBlkIoDevice->BlkIo.Media;
1786 BlockSize = Media->BlockSize;
1787
1788 NumberOfBlocks = BufferSize / BlockSize;
1789
1790 if (!(Media->MediaPresent)) {
1791
1792 if (IdeBlkIoDevice->Cache != NULL) {
1793 gBS->FreePool (IdeBlkIoDevice->Cache);
1794 IdeBlkIoDevice->Cache = NULL;
1795 }
1796 return EFI_NO_MEDIA;
1797
1798 }
1799
1800 if ((MediaId != Media->MediaId) || MediaChange) {
1801
1802 if (IdeBlkIoDevice->Cache != NULL) {
1803 gBS->FreePool (IdeBlkIoDevice->Cache);
1804 IdeBlkIoDevice->Cache = NULL;
1805 }
1806 return EFI_MEDIA_CHANGED;
1807 }
1808
1809 if (BufferSize % BlockSize != 0) {
1810 return EFI_BAD_BUFFER_SIZE;
1811 }
1812
1813 if (Lba > Media->LastBlock) {
1814 return EFI_INVALID_PARAMETER;
1815 }
1816
1817 if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
1818 return EFI_INVALID_PARAMETER;
1819 }
1820
1821 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
1822 return EFI_INVALID_PARAMETER;
1823 }
1824
1825 //
1826 // if all the parameters are valid, then perform read sectors command
1827 // to transfer data from device to host.
1828 //
1829 Status = AtapiReadSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);
1830 if (EFI_ERROR (Status)) {
1831 return EFI_DEVICE_ERROR;
1832 }
1833
1834 //
1835 // Read blocks succeeded
1836 //
1837
1838 //
1839 // save the first block to the cache for performance
1840 //
1841 if (Lba == 0 && (IdeBlkIoDevice->Cache == NULL)) {
1842 IdeBlkIoDevice->Cache = AllocatePool (BlockSize);
1843 if (IdeBlkIoDevice->Cache!= NULL) {
1844 CopyMem ((UINT8 *) IdeBlkIoDevice->Cache, (UINT8 *) Buffer, BlockSize);
1845 }
1846 }
1847
1848 return EFI_SUCCESS;
1849
1850}
1851/**
1852 This function is the ATAPI implementation for WriteBlocks in the
1853 Block I/O Protocol interface.
1854
1855 @param IdeBlkIoDevice Indicates the calling context.
1856 @param MediaId The media id that the write request is for.
1857 @param Lba The starting logical block address to write onto the device.
1858 @param BufferSize The size of the Buffer in bytes. This must be a multiple
1859 of the intrinsic block size of the device.
1860 @param Buffer A pointer to the source buffer for the data. The caller
1861 is responsible for either having implicit or explicit ownership
1862 of the memory that data is written from.
1863
1864 @retval EFI_SUCCESS Write Blocks successfully.
1865 @retval EFI_DEVICE_ERROR Write Blocks failed.
1866 @retval EFI_NO_MEDIA There is no media in the device.
1867 @retval EFI_MEDIA_CHANGE The MediaId is not for the current media.
1868 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
1869 intrinsic block size of the device.
1870 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
1871 or the data buffer is not valid.
1872
1873 @retval EFI_WRITE_PROTECTED The write protected is enabled or the media does not support write
1874**/
1875EFI_STATUS
1876AtapiBlkIoWriteBlocks (
1877 IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
1878 IN UINT32 MediaId,
1879 IN EFI_LBA Lba,
1880 IN UINTN BufferSize,
1881 OUT VOID *Buffer
1882 )
1883{
1884
1885 EFI_BLOCK_IO_MEDIA *Media;
1886 UINTN BlockSize;
1887 UINTN NumberOfBlocks;
1888 EFI_STATUS Status;
1889 BOOLEAN MediaChange;
1890
1891 if (Lba == 0 && IdeBlkIoDevice->Cache != NULL) {
1892 gBS->FreePool (IdeBlkIoDevice->Cache);
1893 IdeBlkIoDevice->Cache = NULL;
1894 }
1895
1896 if (Buffer == NULL) {
1897 return EFI_INVALID_PARAMETER;
1898 }
1899
1900 if (BufferSize == 0) {
1901 return EFI_SUCCESS;
1902 }
1903
1904 //
1905 // ATAPI device media is removable,
1906 // so it is a must to detect media first before write operation
1907 //
1908 MediaChange = FALSE;
1909 Status = AtapiDetectMedia (IdeBlkIoDevice, &MediaChange);
1910 if (EFI_ERROR (Status)) {
1911
1912 if (Lba == 0 && IdeBlkIoDevice->Cache != NULL) {
1913 gBS->FreePool (IdeBlkIoDevice->Cache);
1914 IdeBlkIoDevice->Cache = NULL;
1915 }
1916 return Status;
1917 }
1918
1919 //
1920 // Get the intrinsic block size
1921 //
1922 Media = IdeBlkIoDevice->BlkIo.Media;
1923 BlockSize = Media->BlockSize;
1924 NumberOfBlocks = BufferSize / BlockSize;
1925
1926 if (!(Media->MediaPresent)) {
1927
1928 if (Lba == 0 && IdeBlkIoDevice->Cache != NULL) {
1929 gBS->FreePool (IdeBlkIoDevice->Cache);
1930 IdeBlkIoDevice->Cache = NULL;
1931 }
1932 return EFI_NO_MEDIA;
1933 }
1934
1935 if ((MediaId != Media->MediaId) || MediaChange) {
1936
1937 if (Lba == 0 && IdeBlkIoDevice->Cache != NULL) {
1938 gBS->FreePool (IdeBlkIoDevice->Cache);
1939 IdeBlkIoDevice->Cache = NULL;
1940 }
1941 return EFI_MEDIA_CHANGED;
1942 }
1943
1944 if (Media->ReadOnly) {
1945 return EFI_WRITE_PROTECTED;
1946 }
1947
1948 if (BufferSize % BlockSize != 0) {
1949 return EFI_BAD_BUFFER_SIZE;
1950 }
1951
1952 if (Lba > Media->LastBlock) {
1953 return EFI_INVALID_PARAMETER;
1954 }
1955
1956 if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
1957 return EFI_INVALID_PARAMETER;
1958 }
1959
1960 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
1961 return EFI_INVALID_PARAMETER;
1962 }
1963
1964 //
1965 // if all the parameters are valid,
1966 // then perform write sectors command to transfer data from host to device.
1967 //
1968 Status = AtapiWriteSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);
1969 if (EFI_ERROR (Status)) {
1970 return EFI_DEVICE_ERROR;
1971 }
1972
1973 return EFI_SUCCESS;
1974
1975}
1976
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette