VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware2/VBoxPkg/VBoxIdeBusDxe/Atapi.c@ 33540

Last change on this file since 33540 was 33540, checked in by vboxsync, 14 years ago

*: spelling fixes, thanks Timeless!

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

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