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