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