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