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