rename to meet naming rules
[people/mcb30/edk2.git] / edk2 / IntelFrameworkModulePkg / Bus / Pci / IdeBusDxe / Atapi.c
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
43 STATIC\r
44 EFI_STATUS\r
45 LS120GetMediaStatus (\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
124 STATIC\r
125 EFI_STATUS\r
126 LS120EnableMediaStatus (\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
226 EFI_STATUS\r
227 ATAPIIdentify (\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             ATA_CMD_IDENTIFY_DEVICE,\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 (ATAPI_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
391 EFI_STATUS\r
392 AtapiInquiry (\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   ATAPI_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             = ATA_CMD_INQUIRY;\r
405   Packet.Inquiry.page_code          = 0;\r
406   Packet.Inquiry.allocation_length  = sizeof (ATAPI_INQUIRY_DATA);\r
407 \r
408   InquiryData                       = AllocatePool (sizeof (ATAPI_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 (ATAPI_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
463 EFI_STATUS\r
464 AtapiPacketCommandIn (\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) | ATA_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 ATAPI_MAX_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) (ATAPI_MAX_BYTE_COUNT & 0x00ff)\r
507     );\r
508   IDEWritePortB (\r
509     IdeDev->PciIo,\r
510     IdeDev->IoPort->CylinderMsb,\r
511     (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8)\r
512     );\r
513 \r
514   //\r
515   //  ATA_DEFAULT_CTL:0x0a (0000,1010)\r
516   //  Disable interrupt\r
517   //\r
518   IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, ATA_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, ATA_CMD_PACKET);\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
578 EFI_STATUS\r
579 AtapiPacketCommandOut (\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) | ATA_DEFAULT_CMD)   // ATA_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 ATAPI_MAX_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) (ATAPI_MAX_BYTE_COUNT & 0x00ff)\r
622     );\r
623   IDEWritePortB (\r
624     IdeDev->PciIo,\r
625     IdeDev->IoPort->CylinderMsb,\r
626     (UINT8) (ATAPI_MAX_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, ATA_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, ATA_CMD_PACKET);\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
693 EFI_STATUS\r
694 PioReadWriteData (\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 = 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
814 EFI_STATUS\r
815 AtapiTestUnitReady (\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 = ATA_CMD_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
875 EFI_STATUS\r
876 AtapiRequestSense (\r
877   IN  IDE_BLK_IO_DEV  *IdeDev,\r
878   OUT UINTN           *SenseCounts\r
879   )\r
880 {\r
881   EFI_STATUS            Status;\r
882   ATAPI_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 (ATAPI_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            = ATA_CMD_REQUEST_SENSE;\r
895   Packet.RequestSence.allocation_length = sizeof (ATAPI_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 = (ATAPI_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 (ATAPI_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 != ATA_SK_NO_SENSE) && ((*SenseCounts) < 20)) {\r
938       //\r
939       // Ptr is word-based pointer\r
940       //\r
941       Ptr += (sizeof (ATAPI_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
976 EFI_STATUS\r
977 AtapiReadCapacity (\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   ATAPI_READ_CAPACITY_DATA        Data;\r
993   ATAPI_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 = ATA_CMD_READ_CAPACITY;\r
1004     Status = AtapiPacketCommandIn (\r
1005                IdeDev,\r
1006                &Packet,\r
1007                (UINT16 *) &Data,\r
1008                sizeof (ATAPI_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                = ATA_CMD_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 (ATAPI_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
1137 EFI_STATUS\r
1138 AtapiDetectMedia (\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
1401 EFI_STATUS\r
1402 AtapiReadSectors (\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   ATAPI_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 = ATA_CMD_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
1526 EFI_STATUS\r
1527 AtapiWriteSectors (\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   ATAPI_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 = ATA_CMD_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
1643 EFI_STATUS\r
1644 AtapiSoftReset (\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 = ATA_CMD_SOFT_RESET;\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
1724 EFI_STATUS\r
1725 AtapiBlkIoReadBlocks (\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
1880 EFI_STATUS\r
1881 AtapiBlkIoWriteBlocks (\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
1994 EFI_STATUS\r
1995 ParseSenseData (\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   ATAPI_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 ATA_SK_NO_SENSE:\r
2015     *Result = SenseNoSenseKey;\r
2016     break;\r
2017   case ATA_SK_NOT_READY:\r
2018     switch (SenseData->addnl_sense_code) {\r
2019     case ATA_ASC_NO_MEDIA:\r
2020       *Result = SenseNoMedia;\r
2021       break;\r
2022     case ATA_ASC_MEDIA_UPSIDE_DOWN:\r
2023       *Result = SenseMediaError;\r
2024       break;\r
2025     case ATA_ASC_NOT_READY:\r
2026       if (SenseData->addnl_sense_code_qualifier == ATA_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 ATA_SK_UNIT_ATTENTION:\r
2035     if (SenseData->addnl_sense_code == ATA_ASC_MEDIA_CHANGE) {\r
2036       *Result = SenseMediaChange;\r
2037     }\r
2038     break;\r
2039   case ATA_SK_MEDIUM_ERROR:\r
2040     switch (SenseData->addnl_sense_code) {\r
2041     case ATA_ASC_MEDIA_ERR1:\r
2042     case ATA_ASC_MEDIA_ERR2:\r
2043     case ATA_ASC_MEDIA_ERR3:\r
2044     case ATA_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
2065 EFI_STATUS\r
2066 AtapiReadPendingData (\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 & ATA_STSREG_BSY) == ATA_STSREG_BSY) {\r
2075     return EFI_NOT_READY;\r
2076   }\r
2077   if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {\r
2078     TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus);\r
2079     while ((TempWordBuffer & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_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
2103 EFI_STATUS\r
2104 IsLS120orZipWriteProtected (\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