]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ata.c
IntelFrameworkModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / IdeBusDxe / Ata.c
... / ...
CommitLineData
1/** @file\r
2 This file contains all helper functions on the ATA command\r
3\r
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7 @par Revision Reference:\r
8 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including\r
9 update - ATAIdentity() func\r
10 update - AtaBlockIoReadBlocks() func\r
11 update - AtaBlockIoWriteBlocks() func\r
12 add - AtaAtapi6Identify() func\r
13 add - AtaReadSectorsExt() func\r
14 add - AtaWriteSectorsExt() func\r
15 add - AtaPioDataInExt() func\r
16 add - AtaPioDataOutExt() func\r
17\r
18**/\r
19\r
20#include "IdeBus.h"\r
21/**\r
22 This function is called by ATAIdentify() to identity whether this disk\r
23 supports ATA/ATAPI6 48bit addressing, ie support >120G capacity\r
24\r
25 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record\r
26 all the information of the IDE device.\r
27\r
28 @retval EFI_SUCCESS The disk specified by IdeDev is a Atapi6 supported one and\r
29 48-bit addressing must be used\r
30 @retval EFI_UNSUPPORTED The disk dosn't not support Atapi6 or it supports but the\r
31 capacity is below 120G, 48bit addressing is not needed\r
32 @retval EFI_DEVICE_ERROR The identify data in IdeDev is incorrect\r
33 @retval EFI_INVALID_PARAMETER The identify data in IdeDev is NULL.\r
34\r
35 @note This function must be called after DEVICE_IDENTITY command has been\r
36 successfully returned\r
37\r
38**/\r
39EFI_STATUS\r
40AtaAtapi6Identify (\r
41 IN IDE_BLK_IO_DEV *IdeDev\r
42 )\r
43{\r
44 UINT8 Index;\r
45 EFI_LBA TmpLba;\r
46 EFI_LBA Capacity;\r
47 EFI_IDENTIFY_DATA *Atapi6IdentifyStruct;\r
48\r
49 if (IdeDev->IdData == NULL) {\r
50 return EFI_INVALID_PARAMETER;\r
51 }\r
52\r
53 Atapi6IdentifyStruct = IdeDev->IdData;\r
54\r
55 if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & (BIT15 | BIT14)) != 0x4000) {\r
56 //\r
57 // Per ATA-6 spec, word83: bit15 is zero and bit14 is one\r
58 //\r
59 return EFI_DEVICE_ERROR;\r
60 }\r
61\r
62 if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & BIT10) == 0) {\r
63 //\r
64 // The device dosn't support 48 bit addressing\r
65 //\r
66 return EFI_UNSUPPORTED;\r
67 }\r
68\r
69 //\r
70 // 48 bit address feature set is supported, get maximum capacity\r
71 //\r
72 Capacity = Atapi6IdentifyStruct->AtaData.maximum_lba_for_48bit_addressing[0];\r
73 for (Index = 1; Index < 4; Index++) {\r
74 //\r
75 // Lower byte goes first: word[100] is the lowest word, word[103] is highest\r
76 //\r
77 TmpLba = Atapi6IdentifyStruct->AtaData.maximum_lba_for_48bit_addressing[Index];\r
78 Capacity |= LShiftU64 (TmpLba, 16 * Index);\r
79 }\r
80\r
81 if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) {\r
82 //\r
83 // Capacity exceeds 120GB. 48-bit addressing is really needed\r
84 //\r
85 IdeDev->Type = Ide48bitAddressingHardDisk;\r
86\r
87 //\r
88 // Fill block media information:Media->LogicalPartition ,\r
89 // Media->WriteCaching will be filledin the DiscoverIdeDevcie() function.\r
90 //\r
91 IdeDev->BlkIo.Media->IoAlign = 4;\r
92 IdeDev->BlkIo.Media->MediaId = 1;\r
93 IdeDev->BlkIo.Media->RemovableMedia = FALSE;\r
94 IdeDev->BlkIo.Media->MediaPresent = TRUE;\r
95 IdeDev->BlkIo.Media->ReadOnly = FALSE;\r
96 IdeDev->BlkIo.Media->BlockSize = 0x200;\r
97 IdeDev->BlkIo.Media->LastBlock = Capacity - 1;\r
98\r
99 return EFI_SUCCESS;\r
100 }\r
101\r
102 return EFI_UNSUPPORTED;\r
103}\r
104/**\r
105 Enable SMART of the disk if supported\r
106\r
107 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record\r
108 all the information of the IDE device.\r
109**/\r
110VOID\r
111AtaSMARTSupport (\r
112 IN IDE_BLK_IO_DEV *IdeDev\r
113 )\r
114{\r
115 EFI_STATUS Status;\r
116 BOOLEAN SMARTSupported;\r
117 UINT8 Device;\r
118 EFI_IDENTIFY_DATA *TmpAtaIdentifyPointer;\r
119 UINT8 DeviceSelect;\r
120 UINT8 LBAMid;\r
121 UINT8 LBAHigh;\r
122\r
123 //\r
124 // Detect if the device supports S.M.A.R.T.\r
125 //\r
126 if ((IdeDev->IdData->AtaData.command_set_supported_83 & 0xc000) != 0x4000) {\r
127 //\r
128 // Data in word 82 is not valid (bit15 shall be zero and bit14 shall be to one)\r
129 //\r
130 return ;\r
131 } else {\r
132 if ((IdeDev->IdData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) {\r
133 //\r
134 // S.M.A.R.T is not supported by the device\r
135 //\r
136 SMARTSupported = FALSE;\r
137 } else {\r
138 SMARTSupported = TRUE;\r
139 }\r
140 }\r
141\r
142 if (!SMARTSupported) {\r
143 //\r
144 // Report nonsupport status code\r
145 //\r
146 REPORT_STATUS_CODE (\r
147 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
148 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)\r
149 );\r
150 } else {\r
151 //\r
152 // Enable this feature\r
153 //\r
154 REPORT_STATUS_CODE (\r
155 EFI_PROGRESS_CODE,\r
156 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)\r
157 );\r
158\r
159 Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
160 Status = AtaNonDataCommandIn (\r
161 IdeDev,\r
162 ATA_CMD_SMART,\r
163 Device,\r
164 ATA_SMART_ENABLE_OPERATION,\r
165 0,\r
166 0,\r
167 ATA_CONSTANT_4F,\r
168 ATA_CONSTANT_C2\r
169 );\r
170 //\r
171 // Detect if this feature is enabled\r
172 //\r
173 TmpAtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA));\r
174 if (TmpAtaIdentifyPointer == NULL) {\r
175 return;\r
176 }\r
177\r
178 DeviceSelect = (UINT8) ((IdeDev->Device) << 4);\r
179 Status = AtaPioDataIn (\r
180 IdeDev,\r
181 (VOID *) TmpAtaIdentifyPointer,\r
182 sizeof (EFI_IDENTIFY_DATA),\r
183 ATA_CMD_IDENTIFY_DRIVE,\r
184 DeviceSelect,\r
185 0,\r
186 0,\r
187 0,\r
188 0\r
189 );\r
190 if (EFI_ERROR (Status)) {\r
191 gBS->FreePool (TmpAtaIdentifyPointer);\r
192 return ;\r
193 }\r
194\r
195 //\r
196 // Check if the feature is enabled\r
197 //\r
198 if ((TmpAtaIdentifyPointer->AtaData.command_set_feature_enb_85 & 0x0001) == 0x0001) {\r
199 //\r
200 // Read status data\r
201 //\r
202 AtaNonDataCommandIn (\r
203 IdeDev,\r
204 ATA_CMD_SMART,\r
205 Device,\r
206 ATA_SMART_RETURN_STATUS,\r
207 0,\r
208 0,\r
209 ATA_CONSTANT_4F,\r
210 ATA_CONSTANT_C2\r
211 );\r
212 LBAMid = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb);\r
213 LBAHigh = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb);\r
214\r
215 if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) {\r
216 //\r
217 // The threshold exceeded condition is not detected by the device\r
218 //\r
219 REPORT_STATUS_CODE (\r
220 EFI_PROGRESS_CODE,\r
221 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)\r
222 );\r
223\r
224 } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {\r
225 //\r
226 // The threshold exceeded condition is detected by the device\r
227 //\r
228 REPORT_STATUS_CODE (\r
229 EFI_PROGRESS_CODE,\r
230 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)\r
231 );\r
232 }\r
233\r
234 } else {\r
235 //\r
236 // Report disabled status code\r
237 //\r
238 REPORT_STATUS_CODE (\r
239 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
240 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)\r
241 );\r
242 }\r
243\r
244 gBS->FreePool (TmpAtaIdentifyPointer);\r
245 }\r
246\r
247 return ;\r
248}\r
249/**\r
250 Sends out an ATA Identify Command to the specified device.\r
251\r
252 This function is called by DiscoverIdeDevice() during its device\r
253 identification. It sends out the ATA Identify Command to the\r
254 specified device. Only ATA device responses to this command. If\r
255 the command succeeds, it returns the Identify data structure which\r
256 contains information about the device. This function extracts the\r
257 information it needs to fill the IDE_BLK_IO_DEV data structure,\r
258 including device type, media block size, media capacity, and etc.\r
259\r
260 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record\r
261 all the information of the IDE device.\r
262\r
263 @retval EFI_SUCCESS Identify ATA device successfully.\r
264 @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device.\r
265 @note parameter IdeDev will be updated in this function.\r
266\r
267**/\r
268EFI_STATUS\r
269ATAIdentify (\r
270 IN IDE_BLK_IO_DEV *IdeDev\r
271 )\r
272{\r
273 EFI_STATUS Status;\r
274 EFI_IDENTIFY_DATA *AtaIdentifyPointer;\r
275 UINT32 Capacity;\r
276 UINT8 DeviceSelect;\r
277 UINTN Retry;\r
278\r
279 //\r
280 // AtaIdentifyPointer is used for accommodating returned IDENTIFY data of\r
281 // the ATA Identify command\r
282 //\r
283 AtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA));\r
284 if (AtaIdentifyPointer == NULL) {\r
285 return EFI_OUT_OF_RESOURCES;\r
286 }\r
287\r
288 //\r
289 // use ATA PIO Data In protocol to send ATA Identify command\r
290 // and receive data from device\r
291 //\r
292 DeviceSelect = (UINT8) ((IdeDev->Device) << 4);\r
293\r
294\r
295 Retry = 3;\r
296 while (Retry > 0) {\r
297 Status = AtaPioDataIn (\r
298 IdeDev,\r
299 (VOID *) AtaIdentifyPointer,\r
300 sizeof (EFI_IDENTIFY_DATA),\r
301 ATA_CMD_IDENTIFY_DRIVE,\r
302 DeviceSelect,\r
303 0,\r
304 0,\r
305 0,\r
306 0\r
307 );\r
308 //\r
309 // If ATA Identify command succeeds, then according to the received\r
310 // IDENTIFY data,\r
311 // identify the device type ( ATA or not ).\r
312 // If ATA device, fill the information in IdeDev.\r
313 // If not ATA device, return IDE_DEVICE_ERROR\r
314 //\r
315 if (!EFI_ERROR (Status)) {\r
316\r
317 IdeDev->IdData = AtaIdentifyPointer;\r
318\r
319 //\r
320 // Print ATA Module Name\r
321 //\r
322 PrintAtaModuleName (IdeDev);\r
323\r
324 //\r
325 // bit 15 of pAtaIdentify->config is used to identify whether device is\r
326 // ATA device or ATAPI device.\r
327 // if 0, means ATA device; if 1, means ATAPI device.\r
328 //\r
329 if ((AtaIdentifyPointer->AtaData.config & 0x8000) == 0x00) {\r
330 //\r
331 // Detect if support S.M.A.R.T. If yes, enable it as default\r
332 //\r
333 AtaSMARTSupport (IdeDev);\r
334\r
335 //\r
336 // Check whether this device needs 48-bit addressing (ATAPI-6 ata device)\r
337 //\r
338 Status = AtaAtapi6Identify (IdeDev);\r
339 if (!EFI_ERROR (Status)) {\r
340 //\r
341 // It's a disk with >120GB capacity, initialized in AtaAtapi6Identify()\r
342 //\r
343 return EFI_SUCCESS;\r
344 } else if (Status == EFI_DEVICE_ERROR) {\r
345 //\r
346 // Some disk with big capacity (>200GB) is slow when being identified\r
347 // and will return all zero for word83.\r
348 // We try twice at first. If it fails, we do a SoftRest and try again.\r
349 //\r
350 Retry--;\r
351 if (Retry == 1) {\r
352 //\r
353 // Do a SoftRest before the third attempt.\r
354 //\r
355 AtaSoftReset (IdeDev);\r
356 }\r
357 continue;\r
358 }\r
359 //\r
360 // This is a hard disk <= 120GB capacity, treat it as normal hard disk\r
361 //\r
362 IdeDev->Type = IdeHardDisk;\r
363\r
364 //\r
365 // Block Media Information:\r
366 // Media->LogicalPartition , Media->WriteCaching will be filled\r
367 // in the DiscoverIdeDevcie() function.\r
368 //\r
369 IdeDev->BlkIo.Media->IoAlign = 4;\r
370 IdeDev->BlkIo.Media->MediaId = 1;\r
371 IdeDev->BlkIo.Media->RemovableMedia = FALSE;\r
372 IdeDev->BlkIo.Media->MediaPresent = TRUE;\r
373 IdeDev->BlkIo.Media->ReadOnly = FALSE;\r
374 IdeDev->BlkIo.Media->BlockSize = 0x200;\r
375\r
376 //\r
377 // Calculate device capacity\r
378 //\r
379 Capacity = ((UINT32)AtaIdentifyPointer->AtaData.user_addressable_sectors_hi << 16) |\r
380 AtaIdentifyPointer->AtaData.user_addressable_sectors_lo ;\r
381 IdeDev->BlkIo.Media->LastBlock = Capacity - 1;\r
382\r
383 return EFI_SUCCESS;\r
384 }\r
385\r
386 }\r
387 break;\r
388 }\r
389\r
390 gBS->FreePool (AtaIdentifyPointer);\r
391 //\r
392 // Make sure the pIdData will not be freed again.\r
393 //\r
394 IdeDev->IdData = NULL;\r
395\r
396 return EFI_DEVICE_ERROR;\r
397}\r
398\r
399/**\r
400 This function is a helper function used to change the char order in a string. It\r
401 is designed specially for the PrintAtaModuleName() function. After the IDE device\r
402 is detected, the IDE driver gets the device module name by sending ATA command\r
403 called ATA Identify Command or ATAPI Identify Command to the specified IDE device.\r
404 The module name returned is a string of ASCII characters: the first character is bit8--bit15\r
405 of the first word, the second character is BIT0--bit7 of the first word and so on. Thus\r
406 the string can not be print directly before it is preprocessed by this func to change\r
407 the order of characters in each word in the string.\r
408\r
409 @param Destination Indicates the destination string.\r
410 @param Source Indicates the source string.\r
411 @param Size the length of the string\r
412**/\r
413VOID\r
414SwapStringChars (\r
415 IN CHAR8 *Destination,\r
416 IN CHAR8 *Source,\r
417 IN UINT32 Size\r
418 )\r
419{\r
420 UINT32 Index;\r
421 CHAR8 Temp;\r
422\r
423 for (Index = 0; Index < Size; Index += 2) {\r
424\r
425 Temp = Source[Index + 1];\r
426 Destination[Index + 1] = Source[Index];\r
427 Destination[Index] = Temp;\r
428 }\r
429}\r
430/**\r
431 This function is called by ATAIdentify() or ATAPIIdentify() to print device's module name.\r
432\r
433 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record\r
434 all the information of the IDE device.\r
435**/\r
436VOID\r
437PrintAtaModuleName (\r
438 IN IDE_BLK_IO_DEV *IdeDev\r
439 )\r
440{\r
441 if (IdeDev->IdData == NULL) {\r
442 return ;\r
443 }\r
444\r
445 SwapStringChars (IdeDev->ModelName, IdeDev->IdData->AtaData.ModelName, 40);\r
446 IdeDev->ModelName[40] = 0x00;\r
447}\r
448\r
449/**\r
450 This function is used to send out ATA commands conforms to the PIO Data In Protocol.\r
451\r
452 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record\r
453 all the information of the IDE device.\r
454 @param Buffer buffer contained data transferred from device to host.\r
455 @param ByteCount data size in byte unit of the buffer.\r
456 @param AtaCommand value of the Command Register\r
457 @param Head value of the Head/Device Register\r
458 @param SectorCount value of the Sector Count Register\r
459 @param SectorNumber value of the Sector Number Register\r
460 @param CylinderLsb value of the low byte of the Cylinder Register\r
461 @param CylinderMsb value of the high byte of the Cylinder Register\r
462\r
463 @retval EFI_SUCCESS send out the ATA command and device send required data successfully.\r
464 @retval EFI_DEVICE_ERROR command sent failed.\r
465\r
466**/\r
467EFI_STATUS\r
468AtaPioDataIn (\r
469 IN IDE_BLK_IO_DEV *IdeDev,\r
470 IN VOID *Buffer,\r
471 IN UINT32 ByteCount,\r
472 IN UINT8 AtaCommand,\r
473 IN UINT8 Head,\r
474 IN UINT8 SectorCount,\r
475 IN UINT8 SectorNumber,\r
476 IN UINT8 CylinderLsb,\r
477 IN UINT8 CylinderMsb\r
478 )\r
479{\r
480 UINTN WordCount;\r
481 UINTN Increment;\r
482 UINT16 *Buffer16;\r
483 EFI_STATUS Status;\r
484\r
485 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
486 if (EFI_ERROR (Status)) {\r
487 return EFI_DEVICE_ERROR;\r
488 }\r
489\r
490 //\r
491 // e0:1110,0000-- bit7 and bit5 are reserved bits.\r
492 // bit6 set means LBA mode\r
493 //\r
494 IDEWritePortB (\r
495 IdeDev->PciIo,\r
496 IdeDev->IoPort->Head,\r
497 (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head)\r
498 );\r
499\r
500 //\r
501 // All ATAPI device's ATA commands can be issued regardless of the\r
502 // state of the DRDY\r
503 //\r
504 if (IdeDev->Type == IdeHardDisk) {\r
505\r
506 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
507 if (EFI_ERROR (Status)) {\r
508 return EFI_DEVICE_ERROR;\r
509 }\r
510 }\r
511 //\r
512 // set all the command parameters\r
513 // Before write to all the following registers, BSY and DRQ must be 0.\r
514 //\r
515 Status = DRQClear2 (IdeDev, ATATIMEOUT);\r
516 if (EFI_ERROR (Status)) {\r
517 return EFI_DEVICE_ERROR;\r
518 }\r
519\r
520 if (AtaCommand == ATA_CMD_SET_FEATURES) {\r
521 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);\r
522 }\r
523\r
524 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);\r
525 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber);\r
526 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb);\r
527 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb);\r
528\r
529 //\r
530 // send command via Command Register\r
531 //\r
532 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
533\r
534 Buffer16 = (UINT16 *) Buffer;\r
535\r
536 //\r
537 // According to PIO data in protocol, host can perform a series of reads to\r
538 // the data register after each time device set DRQ ready;\r
539 // The data size of "a series of read" is command specific.\r
540 // For most ATA command, data size received from device will not exceed\r
541 // 1 sector, hence the data size for "a series of read" can be the whole data\r
542 // size of one command request.\r
543 // For ATA command such as Read Sector command, the data size of one ATA\r
544 // command request is often larger than 1 sector, according to the\r
545 // Read Sector command, the data size of "a series of read" is exactly 1\r
546 // sector.\r
547 // Here for simplification reason, we specify the data size for\r
548 // "a series of read" to 1 sector (256 words) if data size of one ATA command\r
549 // request is larger than 256 words.\r
550 //\r
551 Increment = 256;\r
552\r
553 //\r
554 // used to record bytes of currently transfered data\r
555 //\r
556 WordCount = 0;\r
557\r
558 while (WordCount < ByteCount / 2) {\r
559 //\r
560 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.\r
561 //\r
562 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
563 if (EFI_ERROR (Status)) {\r
564 return EFI_DEVICE_ERROR;\r
565 }\r
566\r
567 Status = CheckErrorStatus (IdeDev);\r
568 if (EFI_ERROR (Status)) {\r
569 return EFI_DEVICE_ERROR;\r
570 }\r
571\r
572 //\r
573 // Get the byte count for one series of read\r
574 //\r
575 if ((WordCount + Increment) > ByteCount / 2) {\r
576 Increment = ByteCount / 2 - WordCount;\r
577 }\r
578\r
579 IDEReadPortWMultiple (\r
580 IdeDev->PciIo,\r
581 IdeDev->IoPort->Data,\r
582 Increment,\r
583 Buffer16\r
584 );\r
585\r
586 WordCount += Increment;\r
587 Buffer16 += Increment;\r
588\r
589 }\r
590\r
591 DRQClear (IdeDev, ATATIMEOUT);\r
592\r
593 return CheckErrorStatus (IdeDev);\r
594}\r
595\r
596/**\r
597 This function is used to send out ATA commands conforms to the\r
598 PIO Data Out Protocol.\r
599\r
600 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
601 to record all the information of the IDE device.\r
602 @param *Buffer buffer contained data transferred from host to device.\r
603 @param ByteCount data size in byte unit of the buffer.\r
604 @param AtaCommand value of the Command Register\r
605 @param Head value of the Head/Device Register\r
606 @param SectorCount value of the Sector Count Register\r
607 @param SectorNumber value of the Sector Number Register\r
608 @param CylinderLsb value of the low byte of the Cylinder Register\r
609 @param CylinderMsb value of the high byte of the Cylinder Register\r
610\r
611 @retval EFI_SUCCESS send out the ATA command and device received required\r
612 data successfully.\r
613 @retval EFI_DEVICE_ERROR command sent failed.\r
614\r
615**/\r
616EFI_STATUS\r
617AtaPioDataOut (\r
618 IN IDE_BLK_IO_DEV *IdeDev,\r
619 IN VOID *Buffer,\r
620 IN UINT32 ByteCount,\r
621 IN UINT8 AtaCommand,\r
622 IN UINT8 Head,\r
623 IN UINT8 SectorCount,\r
624 IN UINT8 SectorNumber,\r
625 IN UINT8 CylinderLsb,\r
626 IN UINT8 CylinderMsb\r
627 )\r
628{\r
629 UINTN WordCount;\r
630 UINTN Increment;\r
631 UINT16 *Buffer16;\r
632 EFI_STATUS Status;\r
633\r
634 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
635 if (EFI_ERROR (Status)) {\r
636 return EFI_DEVICE_ERROR;\r
637 }\r
638\r
639 //\r
640 // select device via Head/Device register.\r
641 // Before write Head/Device register, BSY and DRQ must be 0.\r
642 //\r
643 Status = DRQClear2 (IdeDev, ATATIMEOUT);\r
644 if (EFI_ERROR (Status)) {\r
645 return EFI_DEVICE_ERROR;\r
646 }\r
647\r
648 //\r
649 // e0:1110,0000-- bit7 and bit5 are reserved bits.\r
650 // bit6 set means LBA mode\r
651 //\r
652 IDEWritePortB (\r
653 IdeDev->PciIo,\r
654 IdeDev->IoPort->Head,\r
655 (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head)\r
656 );\r
657\r
658 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
659 if (EFI_ERROR (Status)) {\r
660 return EFI_DEVICE_ERROR;\r
661 }\r
662\r
663 //\r
664 // set all the command parameters\r
665 // Before write to all the following registers, BSY and DRQ must be 0.\r
666 //\r
667 Status = DRQClear2 (IdeDev, ATATIMEOUT);\r
668 if (EFI_ERROR (Status)) {\r
669 return EFI_DEVICE_ERROR;\r
670 }\r
671\r
672 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);\r
673 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber);\r
674 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb);\r
675 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb);\r
676\r
677 //\r
678 // send command via Command Register\r
679 //\r
680 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
681\r
682 Buffer16 = (UINT16 *) Buffer;\r
683\r
684 //\r
685 // According to PIO data out protocol, host can perform a series of\r
686 // writes to the data register after each time device set DRQ ready;\r
687 // The data size of "a series of read" is command specific.\r
688 // For most ATA command, data size written to device will not exceed 1 sector,\r
689 // hence the data size for "a series of write" can be the data size of one\r
690 // command request.\r
691 // For ATA command such as Write Sector command, the data size of one\r
692 // ATA command request is often larger than 1 sector, according to the\r
693 // Write Sector command, the data size of "a series of read" is exactly\r
694 // 1 sector.\r
695 // Here for simplification reason, we specify the data size for\r
696 // "a series of write" to 1 sector (256 words) if data size of one ATA command\r
697 // request is larger than 256 words.\r
698 //\r
699 Increment = 256;\r
700 WordCount = 0;\r
701\r
702 while (WordCount < ByteCount / 2) {\r
703\r
704 //\r
705 // DRQReady2-- read Alternate Status Register to determine the DRQ bit\r
706 // data transfer can be performed only when DRQ is ready.\r
707 //\r
708 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
709 if (EFI_ERROR (Status)) {\r
710 return EFI_DEVICE_ERROR;\r
711 }\r
712\r
713 Status = CheckErrorStatus (IdeDev);\r
714 if (EFI_ERROR (Status)) {\r
715 return EFI_DEVICE_ERROR;\r
716 }\r
717\r
718 //\r
719 // Check the remaining byte count is less than 512 bytes\r
720 //\r
721 if ((WordCount + Increment) > ByteCount / 2) {\r
722 Increment = ByteCount / 2 - WordCount;\r
723 }\r
724 //\r
725 // perform a series of write without check DRQ ready\r
726 //\r
727\r
728 IDEWritePortWMultiple (\r
729 IdeDev->PciIo,\r
730 IdeDev->IoPort->Data,\r
731 Increment,\r
732 Buffer16\r
733 );\r
734 WordCount += Increment;\r
735 Buffer16 += Increment;\r
736\r
737 }\r
738\r
739 DRQClear (IdeDev, ATATIMEOUT);\r
740\r
741 return CheckErrorStatus (IdeDev);\r
742}\r
743\r
744/**\r
745 This function is used to analyze the Status Register and print out\r
746 some debug information and if there is ERR bit set in the Status\r
747 Register, the Error Register's value is also be parsed and print out.\r
748\r
749 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to\r
750 record all the information of the IDE device.\r
751\r
752 @retval EFI_SUCCESS No err information in the Status Register.\r
753 @retval EFI_DEVICE_ERROR Any err information in the Status Register.\r
754\r
755**/\r
756EFI_STATUS\r
757CheckErrorStatus (\r
758 IN IDE_BLK_IO_DEV *IdeDev\r
759 )\r
760{\r
761 UINT8 StatusRegister;\r
762 UINT8 ErrorRegister;\r
763\r
764 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
765\r
766 DEBUG_CODE_BEGIN ();\r
767\r
768 if ((StatusRegister & ATA_STSREG_DWF) != 0) {\r
769 DEBUG (\r
770 (EFI_D_BLKIO,\r
771 "CheckErrorStatus()-- %02x : Error : Write Fault\n",\r
772 StatusRegister)\r
773 );\r
774 }\r
775\r
776 if ((StatusRegister & ATA_STSREG_CORR) != 0) {\r
777 DEBUG (\r
778 (EFI_D_BLKIO,\r
779 "CheckErrorStatus()-- %02x : Error : Corrected Data\n",\r
780 StatusRegister)\r
781 );\r
782 }\r
783\r
784 if ((StatusRegister & ATA_STSREG_ERR) != 0) {\r
785 ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
786\r
787 if ((ErrorRegister & ATA_ERRREG_BBK) != 0) {\r
788 DEBUG (\r
789 (EFI_D_BLKIO,\r
790 "CheckErrorStatus()-- %02x : Error : Bad Block Detected\n",\r
791 ErrorRegister)\r
792 );\r
793 }\r
794\r
795 if ((ErrorRegister & ATA_ERRREG_UNC) != 0) {\r
796 DEBUG (\r
797 (EFI_D_BLKIO,\r
798 "CheckErrorStatus()-- %02x : Error : Uncorrectable Data\n",\r
799 ErrorRegister)\r
800 );\r
801 }\r
802\r
803 if ((ErrorRegister & ATA_ERRREG_MC) != 0) {\r
804 DEBUG (\r
805 (EFI_D_BLKIO,\r
806 "CheckErrorStatus()-- %02x : Error : Media Change\n",\r
807 ErrorRegister)\r
808 );\r
809 }\r
810\r
811 if ((ErrorRegister & ATA_ERRREG_ABRT) != 0) {\r
812 DEBUG (\r
813 (EFI_D_BLKIO,\r
814 "CheckErrorStatus()-- %02x : Error : Abort\n",\r
815 ErrorRegister)\r
816 );\r
817 }\r
818\r
819 if ((ErrorRegister & ATA_ERRREG_TK0NF) != 0) {\r
820 DEBUG (\r
821 (EFI_D_BLKIO,\r
822 "CheckErrorStatus()-- %02x : Error : Track 0 Not Found\n",\r
823 ErrorRegister)\r
824 );\r
825 }\r
826\r
827 if ((ErrorRegister & ATA_ERRREG_AMNF) != 0) {\r
828 DEBUG (\r
829 (EFI_D_BLKIO,\r
830 "CheckErrorStatus()-- %02x : Error : Address Mark Not Found\n",\r
831 ErrorRegister)\r
832 );\r
833 }\r
834 }\r
835\r
836 DEBUG_CODE_END ();\r
837\r
838 if ((StatusRegister & (ATA_STSREG_ERR | ATA_STSREG_DWF | ATA_STSREG_CORR)) == 0) {\r
839 return EFI_SUCCESS;\r
840 }\r
841\r
842 return EFI_DEVICE_ERROR;\r
843\r
844}\r
845\r
846/**\r
847 This function is called by the AtaBlkIoReadBlocks() to perform reading from\r
848 media in block unit.\r
849\r
850 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record\r
851 all the information of the IDE device.\r
852 @param DataBuffer A pointer to the destination buffer for the data.\r
853 @param Lba The starting logical block address to read from on the device media.\r
854 @param NumberOfBlocks The number of transfer data blocks.\r
855\r
856 @return status is fully dependent on the return status of AtaPioDataIn() function.\r
857\r
858**/\r
859EFI_STATUS\r
860AtaReadSectors (\r
861 IN IDE_BLK_IO_DEV *IdeDev,\r
862 IN VOID *DataBuffer,\r
863 IN EFI_LBA Lba,\r
864 IN UINTN NumberOfBlocks\r
865 )\r
866{\r
867 EFI_STATUS Status;\r
868 UINTN BlocksRemaining;\r
869 UINT32 Lba32;\r
870 UINT8 Lba0;\r
871 UINT8 Lba1;\r
872 UINT8 Lba2;\r
873 UINT8 Lba3;\r
874 UINT8 AtaCommand;\r
875 UINT8 SectorCount8;\r
876 UINT16 SectorCount;\r
877 UINTN ByteCount;\r
878 VOID *Buffer;\r
879\r
880 Buffer = DataBuffer;\r
881\r
882 //\r
883 // Using ATA Read Sector(s) command (opcode=0x20) with PIO DATA IN protocol\r
884 //\r
885 AtaCommand = ATA_CMD_READ_SECTORS;\r
886\r
887\r
888 BlocksRemaining = NumberOfBlocks;\r
889\r
890 Lba32 = (UINT32) Lba;\r
891\r
892 Status = EFI_SUCCESS;\r
893\r
894 while (BlocksRemaining > 0) {\r
895\r
896 //\r
897 // in ATA-3 spec, LBA is in 28 bit width\r
898 //\r
899 Lba0 = (UINT8) Lba32;\r
900 Lba1 = (UINT8) (Lba32 >> 8);\r
901 Lba2 = (UINT8) (Lba32 >> 16);\r
902 //\r
903 // low 4 bit of Lba3 stands for LBA bit24~bit27.\r
904 //\r
905 Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f);\r
906\r
907 if (BlocksRemaining >= 0x100) {\r
908\r
909 //\r
910 // SectorCount8 is sent to Sector Count register, 0x00 means 256\r
911 // sectors to be read\r
912 //\r
913 SectorCount8 = 0x00;\r
914 //\r
915 // SectorCount is used to record the number of sectors to be read\r
916 //\r
917 SectorCount = 256;\r
918 } else {\r
919\r
920 SectorCount8 = (UINT8) BlocksRemaining;\r
921 SectorCount = (UINT16) BlocksRemaining;\r
922 }\r
923\r
924 //\r
925 // ByteCount is the number of bytes that will be read\r
926 //\r
927 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
928\r
929 //\r
930 // call AtaPioDataIn() to send Read Sector Command and receive data read\r
931 //\r
932 Status = AtaPioDataIn (\r
933 IdeDev,\r
934 Buffer,\r
935 (UINT32) ByteCount,\r
936 AtaCommand,\r
937 Lba3,\r
938 SectorCount8,\r
939 Lba0,\r
940 Lba1,\r
941 Lba2\r
942 );\r
943 if (EFI_ERROR (Status)) {\r
944 return Status;\r
945 }\r
946\r
947 Lba32 += SectorCount;\r
948 Buffer = ((UINT8 *) Buffer + ByteCount);\r
949 BlocksRemaining -= SectorCount;\r
950 }\r
951\r
952 return Status;\r
953}\r
954\r
955/**\r
956 This function is called by the AtaBlkIoWriteBlocks() to perform writing onto\r
957 media in block unit.\r
958\r
959 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used to record\r
960 all the information of the IDE device.\r
961 @param BufferData A pointer to the source buffer for the data.\r
962 @param Lba The starting logical block address to write onto the device media.\r
963 @param NumberOfBlocks The number of transfer data blocks.\r
964\r
965 @return status is fully dependent on the return status of AtaPioDataIn() function.\r
966\r
967**/\r
968EFI_STATUS\r
969AtaWriteSectors (\r
970 IN IDE_BLK_IO_DEV *IdeDev,\r
971 IN VOID *BufferData,\r
972 IN EFI_LBA Lba,\r
973 IN UINTN NumberOfBlocks\r
974 )\r
975{\r
976 EFI_STATUS Status;\r
977 UINTN BlocksRemaining;\r
978 UINT32 Lba32;\r
979 UINT8 Lba0;\r
980 UINT8 Lba1;\r
981 UINT8 Lba2;\r
982 UINT8 Lba3;\r
983 UINT8 AtaCommand;\r
984 UINT8 SectorCount8;\r
985 UINT16 SectorCount;\r
986 UINTN ByteCount;\r
987 VOID *Buffer;\r
988\r
989 Buffer = BufferData;\r
990\r
991 //\r
992 // Using Write Sector(s) command (opcode=0x30) with PIO DATA OUT protocol\r
993 //\r
994 AtaCommand = ATA_CMD_WRITE_SECTORS;\r
995\r
996 BlocksRemaining = NumberOfBlocks;\r
997\r
998 Lba32 = (UINT32) Lba;\r
999\r
1000 Status = EFI_SUCCESS;\r
1001\r
1002 while (BlocksRemaining > 0) {\r
1003\r
1004 Lba0 = (UINT8) Lba32;\r
1005 Lba1 = (UINT8) (Lba32 >> 8);\r
1006 Lba2 = (UINT8) (Lba32 >> 16);\r
1007 Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f);\r
1008\r
1009 if (BlocksRemaining >= 0x100) {\r
1010\r
1011 //\r
1012 // SectorCount8 is sent to Sector Count register, 0x00 means 256 sectors\r
1013 // to be written\r
1014 //\r
1015 SectorCount8 = 0x00;\r
1016 //\r
1017 // SectorCount is used to record the number of sectors to be written\r
1018 //\r
1019 SectorCount = 256;\r
1020 } else {\r
1021\r
1022 SectorCount8 = (UINT8) BlocksRemaining;\r
1023 SectorCount = (UINT16) BlocksRemaining;\r
1024 }\r
1025\r
1026 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
1027\r
1028 Status = AtaPioDataOut (\r
1029 IdeDev,\r
1030 Buffer,\r
1031 (UINT32) ByteCount,\r
1032 AtaCommand,\r
1033 Lba3,\r
1034 SectorCount8,\r
1035 Lba0,\r
1036 Lba1,\r
1037 Lba2\r
1038 );\r
1039 if (EFI_ERROR (Status)) {\r
1040 return Status;\r
1041 }\r
1042\r
1043 Lba32 += SectorCount;\r
1044 Buffer = ((UINT8 *) Buffer + ByteCount);\r
1045 BlocksRemaining -= SectorCount;\r
1046 }\r
1047\r
1048 return Status;\r
1049}\r
1050/**\r
1051 This function is used to implement the Soft Reset on the specified device. But,\r
1052 the ATA Soft Reset mechanism is so strong a reset method that it will force\r
1053 resetting on both devices connected to the same cable.\r
1054\r
1055 It is called by IdeBlkIoReset(), a interface function of Block\r
1056 I/O protocol.\r
1057\r
1058 This function can also be used by the ATAPI device to perform reset when\r
1059 ATAPI Reset command is failed.\r
1060\r
1061 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record\r
1062 all the information of the IDE device.\r
1063 @retval EFI_SUCCESS Soft reset completes successfully.\r
1064 @retval EFI_DEVICE_ERROR Any step during the reset process is failed.\r
1065\r
1066 @note The registers initial values after ATA soft reset are different\r
1067 to the ATA device and ATAPI device.\r
1068**/\r
1069EFI_STATUS\r
1070AtaSoftReset (\r
1071 IN IDE_BLK_IO_DEV *IdeDev\r
1072 )\r
1073{\r
1074\r
1075 UINT8 DeviceControl;\r
1076\r
1077 DeviceControl = 0;\r
1078 //\r
1079 // set SRST bit to initiate soft reset\r
1080 //\r
1081 DeviceControl |= ATA_CTLREG_SRST;\r
1082\r
1083 //\r
1084 // disable Interrupt\r
1085 //\r
1086 DeviceControl |= BIT1;\r
1087\r
1088 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
1089\r
1090 //\r
1091 // SRST should assert for at least 5 us, we use 10 us for\r
1092 // better compatibility\r
1093 //\r
1094 gBS->Stall (10);\r
1095\r
1096 //\r
1097 // Enable interrupt to support UDMA, and clear SRST bit\r
1098 //\r
1099 DeviceControl = 0;\r
1100 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
1101\r
1102 //\r
1103 // Wait for at least 2 ms to check BSY status, we use 10 ms\r
1104 // for better compatibility\r
1105 //\r
1106 gBS->Stall(10000);\r
1107 //\r
1108 // slave device needs at most 31s to clear BSY\r
1109 //\r
1110 if (WaitForBSYClear (IdeDev, 31000) == EFI_TIMEOUT) {\r
1111 return EFI_DEVICE_ERROR;\r
1112 }\r
1113\r
1114 return EFI_SUCCESS;\r
1115}\r
1116/**\r
1117 This function is used to send out ATA commands conforms to the PIO Data In\r
1118 Protocol, supporting ATA/ATAPI-6 standard\r
1119\r
1120 Comparing with ATA-3 data in protocol, we have two differents here:\r
1121 1. Do NOT wait for DRQ clear before sending command into IDE device.(the\r
1122 wait will frequently fail... cause writing function return error)\r
1123\r
1124 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly\r
1125 slow down writing performance by 100 times!)\r
1126\r
1127 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
1128 to record all the information of the IDE device.\r
1129 @param Buffer buffer contained data transferred from device to host.\r
1130 @param ByteCount data size in byte unit of the buffer.\r
1131 @param AtaCommand value of the Command Register\r
1132 @param StartLba the start LBA of this transaction\r
1133 @param SectorCount the count of sectors to be transfered\r
1134\r
1135 @retval EFI_SUCCESS send out the ATA command and device send required data successfully.\r
1136 @retval EFI_DEVICE_ERROR command sent failed.\r
1137\r
1138**/\r
1139EFI_STATUS\r
1140AtaPioDataInExt (\r
1141 IN IDE_BLK_IO_DEV *IdeDev,\r
1142 IN OUT VOID *Buffer,\r
1143 IN UINT32 ByteCount,\r
1144 IN UINT8 AtaCommand,\r
1145 IN EFI_LBA StartLba,\r
1146 IN UINT16 SectorCount\r
1147 )\r
1148{\r
1149 UINT8 DevSel;\r
1150 UINT8 SectorCount8;\r
1151 UINT8 LbaLow;\r
1152 UINT8 LbaMid;\r
1153 UINT8 LbaHigh;\r
1154 UINTN WordCount;\r
1155 UINTN Increment;\r
1156 UINT16 *Buffer16;\r
1157 EFI_STATUS Status;\r
1158\r
1159 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
1160 if (EFI_ERROR (Status)) {\r
1161 return EFI_DEVICE_ERROR;\r
1162 }\r
1163\r
1164 //\r
1165 // Select device, set bit6 as 1 to indicate LBA mode is used\r
1166 //\r
1167 DevSel = (UINT8) (IdeDev->Device << 4);\r
1168 DevSel |= 0x40;\r
1169 IDEWritePortB (\r
1170 IdeDev->PciIo,\r
1171 IdeDev->IoPort->Head,\r
1172 DevSel\r
1173 );\r
1174\r
1175 //\r
1176 // Wait for DRDY singnal asserting. ATAPI device needn't wait\r
1177 //\r
1178 if ( (IdeDev->Type == IdeHardDisk) ||\r
1179 (IdeDev->Type == Ide48bitAddressingHardDisk)) {\r
1180\r
1181 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
1182 if (EFI_ERROR (Status)) {\r
1183 return EFI_DEVICE_ERROR;\r
1184 }\r
1185 }\r
1186\r
1187 //\r
1188 // Fill feature register if needed\r
1189 //\r
1190 if (AtaCommand == ATA_CMD_SET_FEATURES) {\r
1191 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);\r
1192 }\r
1193\r
1194 //\r
1195 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
1196 //\r
1197 SectorCount8 = (UINT8) (SectorCount >> 8);\r
1198 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1199\r
1200 SectorCount8 = (UINT8) SectorCount;\r
1201 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1202\r
1203 //\r
1204 // Fill the start LBA registers, which are also two-byte FIFO\r
1205 //\r
1206 LbaLow = (UINT8) RShiftU64 (StartLba, 24);\r
1207 LbaMid = (UINT8) RShiftU64 (StartLba, 32);\r
1208 LbaHigh = (UINT8) RShiftU64 (StartLba, 40);\r
1209 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1210 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1211 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1212\r
1213 LbaLow = (UINT8) StartLba;\r
1214 LbaMid = (UINT8) RShiftU64 (StartLba, 8);\r
1215 LbaHigh = (UINT8) RShiftU64 (StartLba, 16);\r
1216 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1217 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1218 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1219\r
1220 //\r
1221 // Send command via Command Register, invoking the processing of this command\r
1222 //\r
1223 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
1224\r
1225 Buffer16 = (UINT16 *) Buffer;\r
1226\r
1227 //\r
1228 // According to PIO data in protocol, host can perform a series of reads to\r
1229 // the data register after each time device set DRQ ready;\r
1230 //\r
1231\r
1232 //\r
1233 // 256 words\r
1234 //\r
1235 Increment = 256;\r
1236\r
1237 //\r
1238 // used to record bytes of currently transfered data\r
1239 //\r
1240 WordCount = 0;\r
1241\r
1242 while (WordCount < ByteCount / 2) {\r
1243 //\r
1244 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.\r
1245 //\r
1246 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
1247 if (EFI_ERROR (Status)) {\r
1248 return EFI_DEVICE_ERROR;\r
1249 }\r
1250\r
1251 Status = CheckErrorStatus (IdeDev);\r
1252 if (EFI_ERROR (Status)) {\r
1253 return EFI_DEVICE_ERROR;\r
1254 }\r
1255\r
1256 //\r
1257 // Get the byte count for one series of read\r
1258 //\r
1259 if ((WordCount + Increment) > ByteCount / 2) {\r
1260 Increment = ByteCount / 2 - WordCount;\r
1261 }\r
1262\r
1263 IDEReadPortWMultiple (\r
1264 IdeDev->PciIo,\r
1265 IdeDev->IoPort->Data,\r
1266 Increment,\r
1267 Buffer16\r
1268 );\r
1269\r
1270 WordCount += Increment;\r
1271 Buffer16 += Increment;\r
1272\r
1273 }\r
1274\r
1275 return CheckErrorStatus (IdeDev);\r
1276}\r
1277/**\r
1278 Send ATA Ext command into device with NON_DATA protocol.\r
1279\r
1280 @param IdeDev Standard IDE device private data structure\r
1281 @param AtaCommand The ATA command to be sent\r
1282 @param Device The value in Device register\r
1283 @param Feature The value in Feature register\r
1284 @param SectorCount The value in SectorCount register\r
1285 @param LbaAddress The LBA address in 48-bit mode\r
1286\r
1287 @retval EFI_SUCCESS Reading succeed\r
1288 @retval EFI_DEVICE_ERROR Error executing commands on this device.\r
1289\r
1290**/\r
1291EFI_STATUS\r
1292AtaCommandIssueExt (\r
1293 IN IDE_BLK_IO_DEV *IdeDev,\r
1294 IN UINT8 AtaCommand,\r
1295 IN UINT8 Device,\r
1296 IN UINT16 Feature,\r
1297 IN UINT16 SectorCount,\r
1298 IN EFI_LBA LbaAddress\r
1299 )\r
1300{\r
1301 EFI_STATUS Status;\r
1302 UINT8 SectorCount8;\r
1303 UINT8 Feature8;\r
1304 UINT8 LbaLow;\r
1305 UINT8 LbaMid;\r
1306 UINT8 LbaHigh;\r
1307\r
1308 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
1309 if (EFI_ERROR (Status)) {\r
1310 return EFI_DEVICE_ERROR;\r
1311 }\r
1312\r
1313 //\r
1314 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
1315 //\r
1316 IDEWritePortB (\r
1317 IdeDev->PciIo,\r
1318 IdeDev->IoPort->Head,\r
1319 (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
1320 );\r
1321\r
1322 //\r
1323 // ATA commands for ATA device must be issued when DRDY is set\r
1324 //\r
1325 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
1326 if (EFI_ERROR (Status)) {\r
1327 return EFI_DEVICE_ERROR;\r
1328 }\r
1329\r
1330 //\r
1331 // Pass parameter into device register block\r
1332 //\r
1333 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
1334\r
1335 //\r
1336 // Fill the feature register, which is a two-byte FIFO. Need write twice.\r
1337 //\r
1338 Feature8 = (UINT8) (Feature >> 8);\r
1339 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
1340\r
1341 Feature8 = (UINT8) Feature;\r
1342 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
1343\r
1344 //\r
1345 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
1346 //\r
1347 SectorCount8 = (UINT8) (SectorCount >> 8);\r
1348 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1349\r
1350 SectorCount8 = (UINT8) SectorCount;\r
1351 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1352\r
1353 //\r
1354 // Fill the start LBA registers, which are also two-byte FIFO\r
1355 //\r
1356 LbaLow = (UINT8) RShiftU64 (LbaAddress, 24);\r
1357 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1358 LbaLow = (UINT8) LbaAddress;\r
1359 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
1360\r
1361 LbaMid = (UINT8) RShiftU64 (LbaAddress, 32);\r
1362 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1363 LbaMid = (UINT8) RShiftU64 (LbaAddress, 8);\r
1364 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
1365\r
1366 LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40);\r
1367 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1368 LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16);\r
1369 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
1370\r
1371 //\r
1372 // Work around for Segate 160G disk writing\r
1373 //\r
1374 gBS->Stall (1800);\r
1375\r
1376 //\r
1377 // Send command via Command Register\r
1378 //\r
1379 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
1380\r
1381 //\r
1382 // Stall at least 400ns\r
1383 //\r
1384 gBS->Stall (100);\r
1385\r
1386 return EFI_SUCCESS;\r
1387}\r
1388/**\r
1389 Send ATA Ext command into device with NON_DATA protocol\r
1390\r
1391 @param IdeDev Standard IDE device private data structure\r
1392 @param AtaCommand The ATA command to be sent\r
1393 @param Device The value in Device register\r
1394 @param Feature The value in Feature register\r
1395 @param SectorCount The value in SectorCount register\r
1396 @param LbaAddress The LBA address in 48-bit mode\r
1397\r
1398 @retval EFI_SUCCESS Reading succeed\r
1399 @retval EFI_DEVICE_ERROR Error executing commands on this device.\r
1400\r
1401**/\r
1402EFI_STATUS\r
1403AtaCommandIssue (\r
1404 IN IDE_BLK_IO_DEV *IdeDev,\r
1405 IN UINT8 AtaCommand,\r
1406 IN UINT8 Device,\r
1407 IN UINT16 Feature,\r
1408 IN UINT16 SectorCount,\r
1409 IN EFI_LBA LbaAddress\r
1410 )\r
1411{\r
1412 EFI_STATUS Status;\r
1413 UINT8 SectorCount8;\r
1414 UINT8 Feature8;\r
1415 UINT8 Lba0;\r
1416 UINT8 Lba1;\r
1417 UINT8 Lba2;\r
1418 UINT8 Lba3;\r
1419\r
1420 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
1421 if (EFI_ERROR (Status)) {\r
1422 return EFI_DEVICE_ERROR;\r
1423 }\r
1424\r
1425 //\r
1426 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
1427 //\r
1428 IDEWritePortB (\r
1429 IdeDev->PciIo,\r
1430 IdeDev->IoPort->Head,\r
1431 (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
1432 );\r
1433\r
1434 //\r
1435 // ATA commands for ATA device must be issued when DRDY is set\r
1436 //\r
1437 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
1438 if (EFI_ERROR (Status)) {\r
1439 return EFI_DEVICE_ERROR;\r
1440 }\r
1441\r
1442 Lba0 = (UINT8) LbaAddress;\r
1443 Lba1 = (UINT8) RShiftU64 (LbaAddress, 8);\r
1444 Lba2 = (UINT8) RShiftU64 (LbaAddress, 16);\r
1445 Lba3 = (UINT8) RShiftU64 (LbaAddress, 24);\r
1446 Device = (UINT8) (Device | Lba3);\r
1447\r
1448 //\r
1449 // Pass parameter into device register block\r
1450 //\r
1451 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
1452\r
1453 //\r
1454 // Fill the feature register, which is a two-byte FIFO. Need write twice.\r
1455 //\r
1456 Feature8 = (UINT8) Feature;\r
1457 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
1458\r
1459 //\r
1460 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
1461 //\r
1462 SectorCount8 = (UINT8) SectorCount;\r
1463 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
1464\r
1465 //\r
1466 // Fill the start LBA registers, which are also two-byte FIFO\r
1467 //\r
1468\r
1469 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, Lba0);\r
1470 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, Lba1);\r
1471 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, Lba2);\r
1472\r
1473 //\r
1474 // Send command via Command Register\r
1475 //\r
1476 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
1477\r
1478 //\r
1479 // Stall at least 400ns\r
1480 //\r
1481 gBS->Stall (100);\r
1482\r
1483 return EFI_SUCCESS;\r
1484}\r
1485/**\r
1486 Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).\r
1487\r
1488 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
1489 to record all the information of the IDE device.\r
1490 @param DataBuffer A pointer to the source buffer for the data.\r
1491 @param StartLba The starting logical block address to write to\r
1492 on the device media.\r
1493 @param NumberOfBlocks The number of transfer data blocks.\r
1494 @param UdmaOp The perform operations could be AtaUdmaReadOp, AtaUdmaReadExOp,\r
1495 AtaUdmaWriteOp, AtaUdmaWriteExOp\r
1496\r
1497 @retval EFI_SUCCESS the operation is successful.\r
1498 @retval EFI_OUT_OF_RESOURCES Build PRD table failed\r
1499 @retval EFI_UNSUPPORTED Unknown channel or operations command\r
1500 @retval EFI_DEVICE_ERROR Ata command execute failed\r
1501\r
1502**/\r
1503EFI_STATUS\r
1504DoAtaUdma (\r
1505 IN IDE_BLK_IO_DEV *IdeDev,\r
1506 IN VOID *DataBuffer,\r
1507 IN EFI_LBA StartLba,\r
1508 IN UINTN NumberOfBlocks,\r
1509 IN ATA_UDMA_OPERATION UdmaOp\r
1510 )\r
1511{\r
1512 IDE_DMA_PRD *PrdAddr;\r
1513 IDE_DMA_PRD *UsedPrdAddr;\r
1514 IDE_DMA_PRD *TempPrdAddr;\r
1515 UINT8 RegisterValue;\r
1516 UINT8 Device;\r
1517 UINT64 IoPortForBmic;\r
1518 UINT64 IoPortForBmis;\r
1519 UINT64 IoPortForBmid;\r
1520 EFI_STATUS Status;\r
1521 UINTN PrdTableNum;\r
1522 UINTN ByteCount;\r
1523 UINTN ByteAvailable;\r
1524 UINT8 *PrdBuffer;\r
1525 UINTN RemainBlockNum;\r
1526 UINT8 DeviceControl;\r
1527 UINT32 Count;\r
1528 UINTN PageCount;\r
1529 VOID *Map;\r
1530 VOID *MemPage;\r
1531 EFI_PHYSICAL_ADDRESS DeviceAddress;\r
1532 UINTN MaxDmaCommandSectors;\r
1533 EFI_PCI_IO_PROTOCOL_OPERATION PciIoProtocolOp;\r
1534 UINT8 AtaCommand;\r
1535\r
1536 switch (UdmaOp) {\r
1537 case AtaUdmaReadOp:\r
1538 MaxDmaCommandSectors = ATAPI_MAX_DMA_CMD_SECTORS;\r
1539 PciIoProtocolOp = EfiPciIoOperationBusMasterWrite;\r
1540 AtaCommand = ATA_CMD_READ_DMA;\r
1541 break;\r
1542 case AtaUdmaReadExtOp:\r
1543 MaxDmaCommandSectors = ATAPI_MAX_DMA_EXT_CMD_SECTORS;\r
1544 PciIoProtocolOp = EfiPciIoOperationBusMasterWrite;\r
1545 AtaCommand = ATA_CMD_READ_DMA_EXT;\r
1546 break;\r
1547 case AtaUdmaWriteOp:\r
1548 MaxDmaCommandSectors = ATAPI_MAX_DMA_CMD_SECTORS;\r
1549 PciIoProtocolOp = EfiPciIoOperationBusMasterRead;\r
1550 AtaCommand = ATA_CMD_WRITE_DMA;\r
1551 break;\r
1552 case AtaUdmaWriteExtOp:\r
1553 MaxDmaCommandSectors = ATAPI_MAX_DMA_EXT_CMD_SECTORS;\r
1554 PciIoProtocolOp = EfiPciIoOperationBusMasterRead;\r
1555 AtaCommand = ATA_CMD_WRITE_DMA_EXT;\r
1556 break;\r
1557 default:\r
1558 return EFI_UNSUPPORTED;\r
1559 break;\r
1560 }\r
1561\r
1562 //\r
1563 // Select device\r
1564 //\r
1565 Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
1566 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
1567\r
1568 //\r
1569 // Enable interrupt to support UDMA\r
1570 //\r
1571 DeviceControl = 0;\r
1572 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
1573\r
1574 if (IdePrimary == IdeDev->Channel) {\r
1575 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;\r
1576 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
1577 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;\r
1578 } else {\r
1579 if (IdeSecondary == IdeDev->Channel) {\r
1580 IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;\r
1581 IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
1582 IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;\r
1583 } else {\r
1584 return EFI_UNSUPPORTED;\r
1585 }\r
1586 }\r
1587\r
1588 //\r
1589 // Read BMIS register and clear ERROR and INTR bit\r
1590 //\r
1591 IdeDev->PciIo->Io.Read (\r
1592 IdeDev->PciIo,\r
1593 EfiPciIoWidthUint8,\r
1594 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1595 IoPortForBmis,\r
1596 1,\r
1597 &RegisterValue\r
1598 );\r
1599\r
1600 RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
1601\r
1602 IdeDev->PciIo->Io.Write (\r
1603 IdeDev->PciIo,\r
1604 EfiPciIoWidthUint8,\r
1605 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1606 IoPortForBmis,\r
1607 1,\r
1608 &RegisterValue\r
1609 );\r
1610\r
1611 Status = EFI_SUCCESS;\r
1612\r
1613 RemainBlockNum = NumberOfBlocks;\r
1614 while (RemainBlockNum > 0) {\r
1615\r
1616 if (RemainBlockNum >= MaxDmaCommandSectors) {\r
1617 //\r
1618 // SectorCount is used to record the number of sectors to be read\r
1619 // Max 65536 sectors can be transfered at a time.\r
1620 //\r
1621 NumberOfBlocks = MaxDmaCommandSectors;\r
1622 RemainBlockNum -= MaxDmaCommandSectors;\r
1623 } else {\r
1624 NumberOfBlocks = (UINT16) RemainBlockNum;\r
1625 RemainBlockNum = 0;\r
1626 }\r
1627\r
1628 //\r
1629 // Calculate the number of PRD table to make sure the memory region\r
1630 // not cross 64K boundary\r
1631 //\r
1632 ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
1633 PrdTableNum = ((ByteCount >> 16) + 1) + 1;\r
1634\r
1635 //\r
1636 // Build PRD table\r
1637 //\r
1638 PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));\r
1639 Status = IdeDev->PciIo->AllocateBuffer (\r
1640 IdeDev->PciIo,\r
1641 AllocateAnyPages,\r
1642 EfiBootServicesData,\r
1643 PageCount,\r
1644 &MemPage,\r
1645 0\r
1646 );\r
1647 if (EFI_ERROR (Status)) {\r
1648 return EFI_OUT_OF_RESOURCES;\r
1649 }\r
1650 ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));\r
1651\r
1652 PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);\r
1653 //\r
1654 // To make sure PRD is allocated in one 64K page\r
1655 //\r
1656 if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {\r
1657 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);\r
1658 } else {\r
1659 if ((UINTN) PrdAddr & 0x03) {\r
1660 UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);\r
1661 } else {\r
1662 UsedPrdAddr = PrdAddr;\r
1663 }\r
1664 }\r
1665\r
1666 //\r
1667 // Build the PRD table\r
1668 //\r
1669 Status = IdeDev->PciIo->Map (\r
1670 IdeDev->PciIo,\r
1671 PciIoProtocolOp,\r
1672 DataBuffer,\r
1673 &ByteCount,\r
1674 &DeviceAddress,\r
1675 &Map\r
1676 );\r
1677 if (EFI_ERROR (Status)) {\r
1678 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
1679 return EFI_OUT_OF_RESOURCES;\r
1680 }\r
1681 PrdBuffer = (VOID *) ((UINTN) DeviceAddress);\r
1682 TempPrdAddr = UsedPrdAddr;\r
1683 while (TRUE) {\r
1684\r
1685 ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);\r
1686\r
1687 if (ByteCount <= ByteAvailable) {\r
1688 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
1689 TempPrdAddr->ByteCount = (UINT16) ByteCount;\r
1690 TempPrdAddr->EndOfTable = 0x8000;\r
1691 break;\r
1692 }\r
1693\r
1694 TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
1695 TempPrdAddr->ByteCount = (UINT16) ByteAvailable;\r
1696\r
1697 ByteCount -= ByteAvailable;\r
1698 PrdBuffer += ByteAvailable;\r
1699 TempPrdAddr++;\r
1700 }\r
1701\r
1702 //\r
1703 // Set the base address to BMID register\r
1704 //\r
1705 IdeDev->PciIo->Io.Write (\r
1706 IdeDev->PciIo,\r
1707 EfiPciIoWidthUint32,\r
1708 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1709 IoPortForBmid,\r
1710 1,\r
1711 &UsedPrdAddr\r
1712 );\r
1713\r
1714 //\r
1715 // Set BMIC register to identify the operation direction\r
1716 //\r
1717 IdeDev->PciIo->Io.Read (\r
1718 IdeDev->PciIo,\r
1719 EfiPciIoWidthUint8,\r
1720 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1721 IoPortForBmic,\r
1722 1,\r
1723 &RegisterValue\r
1724 );\r
1725\r
1726 if (UdmaOp == AtaUdmaReadExtOp || UdmaOp == AtaUdmaReadOp) {\r
1727 RegisterValue |= BMIC_NREAD;\r
1728 } else {\r
1729 RegisterValue &= ~((UINT8) BMIC_NREAD);\r
1730 }\r
1731\r
1732 IdeDev->PciIo->Io.Write (\r
1733 IdeDev->PciIo,\r
1734 EfiPciIoWidthUint8,\r
1735 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1736 IoPortForBmic,\r
1737 1,\r
1738 &RegisterValue\r
1739 );\r
1740\r
1741 if (UdmaOp == AtaUdmaWriteExtOp || UdmaOp == AtaUdmaReadExtOp) {\r
1742 Status = AtaCommandIssueExt (\r
1743 IdeDev,\r
1744 AtaCommand,\r
1745 Device,\r
1746 0,\r
1747 (UINT16) NumberOfBlocks,\r
1748 StartLba\r
1749 );\r
1750 } else {\r
1751 Status = AtaCommandIssue (\r
1752 IdeDev,\r
1753 AtaCommand,\r
1754 Device,\r
1755 0,\r
1756 (UINT16) NumberOfBlocks,\r
1757 StartLba\r
1758 );\r
1759 }\r
1760\r
1761 if (EFI_ERROR (Status)) {\r
1762 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
1763 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
1764 return EFI_DEVICE_ERROR;\r
1765 }\r
1766\r
1767 //\r
1768 // Set START bit of BMIC register\r
1769 //\r
1770 IdeDev->PciIo->Io.Read (\r
1771 IdeDev->PciIo,\r
1772 EfiPciIoWidthUint8,\r
1773 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1774 IoPortForBmic,\r
1775 1,\r
1776 &RegisterValue\r
1777 );\r
1778\r
1779 RegisterValue |= BMIC_START;\r
1780\r
1781 IdeDev->PciIo->Io.Write (\r
1782 IdeDev->PciIo,\r
1783 EfiPciIoWidthUint8,\r
1784 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1785 IoPortForBmic,\r
1786 1,\r
1787 &RegisterValue\r
1788 );\r
1789\r
1790 //\r
1791 // Check the INTERRUPT and ERROR bit of BMIS\r
1792 // Max transfer number of sectors for one command is 65536(32Mbyte),\r
1793 // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
1794 // So set the variable Count to 2000, for about 2 second timeout time.\r
1795 //\r
1796 Status = EFI_SUCCESS;\r
1797 Count = 2000;\r
1798 while (TRUE) {\r
1799\r
1800 IdeDev->PciIo->Io.Read (\r
1801 IdeDev->PciIo,\r
1802 EfiPciIoWidthUint8,\r
1803 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1804 IoPortForBmis,\r
1805 1,\r
1806 &RegisterValue\r
1807 );\r
1808 if (((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) != 0) || (Count == 0)) {\r
1809 if (((RegisterValue & BMIS_ERROR) != 0) || (Count == 0)) {\r
1810 Status = EFI_DEVICE_ERROR;\r
1811 break;\r
1812 }\r
1813 break;\r
1814 }\r
1815\r
1816 gBS->Stall (1000);\r
1817 Count --;\r
1818 }\r
1819\r
1820 IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
1821 IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
1822 //\r
1823 // Read BMIS register and clear ERROR and INTR bit\r
1824 //\r
1825 IdeDev->PciIo->Io.Read (\r
1826 IdeDev->PciIo,\r
1827 EfiPciIoWidthUint8,\r
1828 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1829 IoPortForBmis,\r
1830 1,\r
1831 &RegisterValue\r
1832 );\r
1833\r
1834 RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
1835\r
1836 IdeDev->PciIo->Io.Write (\r
1837 IdeDev->PciIo,\r
1838 EfiPciIoWidthUint8,\r
1839 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1840 IoPortForBmis,\r
1841 1,\r
1842 &RegisterValue\r
1843 );\r
1844 //\r
1845 // Read Status Register of IDE device to clear interrupt\r
1846 //\r
1847 RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);\r
1848 //\r
1849 // Clear START bit of BMIC register\r
1850 //\r
1851 IdeDev->PciIo->Io.Read (\r
1852 IdeDev->PciIo,\r
1853 EfiPciIoWidthUint8,\r
1854 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1855 IoPortForBmic,\r
1856 1,\r
1857 &RegisterValue\r
1858 );\r
1859\r
1860 RegisterValue &= ~((UINT8) BMIC_START);\r
1861\r
1862 IdeDev->PciIo->Io.Write (\r
1863 IdeDev->PciIo,\r
1864 EfiPciIoWidthUint8,\r
1865 EFI_PCI_IO_PASS_THROUGH_BAR,\r
1866 IoPortForBmic,\r
1867 1,\r
1868 &RegisterValue\r
1869 );\r
1870\r
1871 if ((RegisterValue & BMIS_ERROR) != 0) {\r
1872 return EFI_DEVICE_ERROR;\r
1873 }\r
1874\r
1875 if (EFI_ERROR (Status)) {\r
1876 break;\r
1877 }\r
1878 DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
1879 StartLba += NumberOfBlocks;\r
1880 }\r
1881\r
1882 //\r
1883 // Disable interrupt of Select device\r
1884 //\r
1885 IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);\r
1886 DeviceControl |= ATA_CTLREG_IEN_L;\r
1887 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
1888\r
1889 return Status;\r
1890}\r
1891\r
1892\r
1893/**\r
1894 This function is called by the AtaBlkIoReadBlocks() to perform reading from\r
1895 media in block unit. The function has been enhanced to support >120GB access\r
1896 and transfer at most 65536 blocks per command\r
1897\r
1898 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record\r
1899 all the information of the IDE device.\r
1900 @param DataBuffer A pointer to the destination buffer for the data.\r
1901 @param StartLba The starting logical block address to read from on the device media.\r
1902 @param NumberOfBlocks The number of transfer data blocks.\r
1903\r
1904 @return status depends on the function DoAtaUdma() returns.\r
1905**/\r
1906EFI_STATUS\r
1907AtaUdmaReadExt (\r
1908 IN IDE_BLK_IO_DEV *IdeDev,\r
1909 IN VOID *DataBuffer,\r
1910 IN EFI_LBA StartLba,\r
1911 IN UINTN NumberOfBlocks\r
1912 )\r
1913{\r
1914 return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadExtOp);\r
1915}\r
1916/**\r
1917 This function is called by the AtaBlkIoReadBlocks() to perform\r
1918 reading from media in block unit. The function has been enhanced to\r
1919 support >120GB access and transfer at most 65536 blocks per command\r
1920\r
1921 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record\r
1922 all the information of the IDE device.\r
1923 @param DataBuffer A pointer to the destination buffer for the data.\r
1924 @param StartLba The starting logical block address to read from\r
1925 on the device media.\r
1926 @param NumberOfBlocks The number of transfer data blocks.\r
1927\r
1928 @return status depends on the function DoAtaUdma() returns.\r
1929**/\r
1930EFI_STATUS\r
1931AtaUdmaRead (\r
1932 IN IDE_BLK_IO_DEV *IdeDev,\r
1933 IN VOID *DataBuffer,\r
1934 IN EFI_LBA StartLba,\r
1935 IN UINTN NumberOfBlocks\r
1936 )\r
1937{\r
1938 return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadOp);\r
1939}\r
1940\r
1941/**\r
1942 This function is called by the AtaBlkIoReadBlocks() to perform\r
1943 reading from media in block unit. The function has been enhanced to\r
1944 support >120GB access and transfer at most 65536 blocks per command\r
1945\r
1946 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used to record\r
1947 all the information of the IDE device.\r
1948 @param DataBuffer A pointer to the destination buffer for the data.\r
1949 @param StartLba The starting logical block address to read from on the device media.\r
1950 @param NumberOfBlocks The number of transfer data blocks.\r
1951\r
1952 @return status is fully dependent on the return status of AtaPioDataInExt() function.\r
1953**/\r
1954EFI_STATUS\r
1955AtaReadSectorsExt (\r
1956 IN IDE_BLK_IO_DEV *IdeDev,\r
1957 IN VOID *DataBuffer,\r
1958 IN EFI_LBA StartLba,\r
1959 IN UINTN NumberOfBlocks\r
1960 )\r
1961{\r
1962 EFI_STATUS Status;\r
1963 UINTN BlocksRemaining;\r
1964 EFI_LBA Lba64;\r
1965 UINT8 AtaCommand;\r
1966 UINT16 SectorCount;\r
1967 UINT32 ByteCount;\r
1968 VOID *Buffer;\r
1969\r
1970 //\r
1971 // Using ATA "Read Sectors Ext" command(opcode=0x24) with PIO DATA IN protocol\r
1972 //\r
1973 AtaCommand = ATA_CMD_READ_SECTORS_EXT;\r
1974 Buffer = DataBuffer;\r
1975 BlocksRemaining = NumberOfBlocks;\r
1976 Lba64 = StartLba;\r
1977 Status = EFI_SUCCESS;\r
1978\r
1979 while (BlocksRemaining > 0) {\r
1980\r
1981 if (BlocksRemaining >= 0x10000) {\r
1982 //\r
1983 // SectorCount is used to record the number of sectors to be read\r
1984 // Max 65536 sectors can be transfered at a time.\r
1985 //\r
1986 SectorCount = 0xffff;\r
1987 } else {\r
1988 SectorCount = (UINT16) BlocksRemaining;\r
1989 }\r
1990\r
1991 //\r
1992 // ByteCount is the number of bytes that will be read\r
1993 //\r
1994 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
1995\r
1996 //\r
1997 // call AtaPioDataInExt() to send Read Sector Command and receive data read\r
1998 //\r
1999 Status = AtaPioDataInExt (\r
2000 IdeDev,\r
2001 Buffer,\r
2002 ByteCount,\r
2003 AtaCommand,\r
2004 Lba64,\r
2005 SectorCount\r
2006 );\r
2007 if (EFI_ERROR (Status)) {\r
2008 return Status;\r
2009 }\r
2010\r
2011 Lba64 += SectorCount;\r
2012 Buffer = ((UINT8 *) Buffer + ByteCount);\r
2013 BlocksRemaining -= SectorCount;\r
2014 }\r
2015\r
2016 return Status;\r
2017}\r
2018/**\r
2019 This function is the ATA implementation for ReadBlocks in the\r
2020 Block I/O Protocol interface.\r
2021\r
2022 @param IdeBlkIoDevice Indicates the calling context.\r
2023 @param MediaId The media id that the read request is for.\r
2024 @param Lba The starting logical block address to read from on the device.\r
2025 @param BufferSize The size of the Buffer in bytes. This must be a multiple\r
2026 of the intrinsic block size of the device.\r
2027\r
2028 @param Buffer A pointer to the destination buffer for the data. The caller\r
2029 is responsible for either having implicit or explicit ownership\r
2030 of the memory that data is read into.\r
2031\r
2032 @retval EFI_SUCCESS Read Blocks successfully.\r
2033 @retval EFI_DEVICE_ERROR Read Blocks failed.\r
2034 @retval EFI_NO_MEDIA There is no media in the device.\r
2035 @retval EFI_MEDIA_CHANGE The MediaId is not for the current media.\r
2036 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the\r
2037 intrinsic block size of the device.\r
2038 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,\r
2039 or the data buffer is not valid.\r
2040\r
2041 @note If Read Block error because of device error, this function will call\r
2042 AtaSoftReset() function to reset device.\r
2043\r
2044**/\r
2045EFI_STATUS\r
2046AtaBlkIoReadBlocks (\r
2047 IN IDE_BLK_IO_DEV *IdeBlkIoDevice,\r
2048 IN UINT32 MediaId,\r
2049 IN EFI_LBA Lba,\r
2050 IN UINTN BufferSize,\r
2051 OUT VOID *Buffer\r
2052 )\r
2053{\r
2054 EFI_BLOCK_IO_MEDIA *Media;\r
2055 UINTN BlockSize;\r
2056 UINTN NumberOfBlocks;\r
2057 EFI_STATUS Status;\r
2058\r
2059 if (Buffer == NULL) {\r
2060 return EFI_INVALID_PARAMETER;\r
2061 }\r
2062\r
2063 if (BufferSize == 0) {\r
2064 return EFI_SUCCESS;\r
2065 }\r
2066\r
2067 Status = EFI_SUCCESS;\r
2068\r
2069 //\r
2070 // Get the intrinsic block size\r
2071 //\r
2072 Media = IdeBlkIoDevice->BlkIo.Media;\r
2073 BlockSize = Media->BlockSize;\r
2074\r
2075 NumberOfBlocks = BufferSize / BlockSize;\r
2076\r
2077 if (MediaId != Media->MediaId) {\r
2078 return EFI_MEDIA_CHANGED;\r
2079 }\r
2080\r
2081 if (BufferSize % BlockSize != 0) {\r
2082 return EFI_BAD_BUFFER_SIZE;\r
2083 }\r
2084\r
2085 if (!(Media->MediaPresent)) {\r
2086 return EFI_NO_MEDIA;\r
2087 }\r
2088\r
2089 if (Lba > Media->LastBlock) {\r
2090 return EFI_INVALID_PARAMETER;\r
2091 }\r
2092\r
2093 if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {\r
2094 return EFI_INVALID_PARAMETER;\r
2095 }\r
2096\r
2097 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {\r
2098 return EFI_INVALID_PARAMETER;\r
2099 }\r
2100\r
2101 Status = EFI_SUCCESS;\r
2102 if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
2103 //\r
2104 // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism\r
2105 //\r
2106 if (IdeBlkIoDevice->UdmaMode.Valid) {\r
2107 Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
2108 } else {\r
2109 Status = AtaReadSectorsExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
2110 }\r
2111 } else {\r
2112 //\r
2113 // For ATA-3 compatible device, use ATA-3 read block mechanism\r
2114 //\r
2115 if (IdeBlkIoDevice->UdmaMode.Valid) {\r
2116 Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
2117 } else {\r
2118 Status = AtaReadSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
2119 }\r
2120 }\r
2121\r
2122 if (EFI_ERROR (Status)) {\r
2123 AtaSoftReset (IdeBlkIoDevice);\r
2124 return EFI_DEVICE_ERROR;\r
2125 }\r
2126\r
2127 return EFI_SUCCESS;\r
2128\r
2129}\r
2130/**\r
2131 This function is used to send out ATA commands conforms to the\r
2132 PIO Data Out Protocol, supporting ATA/ATAPI-6 standard\r
2133\r
2134 Comparing with ATA-3 data out protocol, we have two differents here:<BR>\r
2135 1. Do NOT wait for DRQ clear before sending command into IDE device.(the\r
2136 wait will frequently fail... cause writing function return error)\r
2137\r
2138 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly\r
2139 slow down writing performance by 100 times!)\r
2140\r
2141 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2142 to record all the information of the IDE device.\r
2143 @param Buffer buffer contained data transferred from host to device.\r
2144 @param ByteCount data size in byte unit of the buffer.\r
2145 @param AtaCommand value of the Command Register\r
2146 @param StartLba the start LBA of this transaction\r
2147 @param SectorCount the count of sectors to be transfered\r
2148\r
2149 @retval EFI_SUCCESS send out the ATA command and device receive required\r
2150 data successfully.\r
2151 @retval EFI_DEVICE_ERROR command sent failed.\r
2152\r
2153**/\r
2154EFI_STATUS\r
2155AtaPioDataOutExt (\r
2156 IN IDE_BLK_IO_DEV *IdeDev,\r
2157 IN VOID *Buffer,\r
2158 IN UINT32 ByteCount,\r
2159 IN UINT8 AtaCommand,\r
2160 IN EFI_LBA StartLba,\r
2161 IN UINT16 SectorCount\r
2162 )\r
2163{\r
2164 UINT8 DevSel;\r
2165 UINT8 SectorCount8;\r
2166 UINT8 LbaLow;\r
2167 UINT8 LbaMid;\r
2168 UINT8 LbaHigh;\r
2169 UINTN WordCount;\r
2170 UINTN Increment;\r
2171 UINT16 *Buffer16;\r
2172 EFI_STATUS Status;\r
2173\r
2174 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
2175 if (EFI_ERROR (Status)) {\r
2176 return EFI_DEVICE_ERROR;\r
2177 }\r
2178\r
2179 //\r
2180 // Select device. Set bit6 as 1 to indicate LBA mode is used\r
2181 //\r
2182 DevSel = (UINT8) (IdeDev->Device << 4);\r
2183 DevSel |= 0x40;\r
2184 IDEWritePortB (\r
2185 IdeDev->PciIo,\r
2186 IdeDev->IoPort->Head,\r
2187 DevSel\r
2188 );\r
2189\r
2190 //\r
2191 // Wait for DRDY singnal asserting.\r
2192 //\r
2193 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
2194 if (EFI_ERROR (Status)) {\r
2195 return EFI_DEVICE_ERROR;\r
2196 }\r
2197\r
2198 //\r
2199 // Fill feature register if needed\r
2200 //\r
2201 if (AtaCommand == ATA_CMD_SET_FEATURES) {\r
2202 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);\r
2203 }\r
2204\r
2205 //\r
2206 // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
2207 //\r
2208 SectorCount8 = (UINT8) (SectorCount >> 8);\r
2209 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
2210\r
2211 SectorCount8 = (UINT8) SectorCount;\r
2212 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
2213\r
2214 //\r
2215 // Fill the start LBA registers, which are also two-byte FIFO\r
2216 //\r
2217 LbaLow = (UINT8) RShiftU64 (StartLba, 24);\r
2218 LbaMid = (UINT8) RShiftU64 (StartLba, 32);\r
2219 LbaHigh = (UINT8) RShiftU64 (StartLba, 40);\r
2220 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
2221 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
2222 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
2223\r
2224 LbaLow = (UINT8) StartLba;\r
2225 LbaMid = (UINT8) RShiftU64 (StartLba, 8);\r
2226 LbaHigh = (UINT8) RShiftU64 (StartLba, 16);\r
2227 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
2228 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
2229 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
2230\r
2231 //\r
2232 // Send command via Command Register, invoking the processing of this command\r
2233 //\r
2234 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
2235\r
2236 Buffer16 = (UINT16 *) Buffer;\r
2237\r
2238 //\r
2239 // According to PIO Data Out protocol, host can perform a series of writes to\r
2240 // the data register after each time device set DRQ ready;\r
2241 //\r
2242 Increment = 256;\r
2243\r
2244 //\r
2245 // used to record bytes of currently transfered data\r
2246 //\r
2247 WordCount = 0;\r
2248\r
2249 while (WordCount < ByteCount / 2) {\r
2250 //\r
2251 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.\r
2252 //\r
2253 Status = DRQReady2 (IdeDev, ATATIMEOUT);\r
2254 if (EFI_ERROR (Status)) {\r
2255 return EFI_DEVICE_ERROR;\r
2256 }\r
2257\r
2258 Status = CheckErrorStatus (IdeDev);\r
2259 if (EFI_ERROR (Status)) {\r
2260 return EFI_DEVICE_ERROR;\r
2261 }\r
2262\r
2263 //\r
2264 // Write data into device by one series of writing to data register\r
2265 //\r
2266 if ((WordCount + Increment) > ByteCount / 2) {\r
2267 Increment = ByteCount / 2 - WordCount;\r
2268 }\r
2269\r
2270 IDEWritePortWMultiple (\r
2271 IdeDev->PciIo,\r
2272 IdeDev->IoPort->Data,\r
2273 Increment,\r
2274 Buffer16\r
2275 );\r
2276\r
2277 WordCount += Increment;\r
2278 Buffer16 += Increment;\r
2279\r
2280 }\r
2281 return CheckErrorStatus (IdeDev);\r
2282}\r
2283/**\r
2284 This function is called by the AtaBlkIoWriteBlocks() to perform\r
2285 writing to media in block unit. The function has been enhanced to\r
2286 support >120GB access and transfer at most 65536 blocks per command\r
2287\r
2288 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2289 to record all the information of the IDE device.\r
2290 @param DataBuffer A pointer to the source buffer for the data.\r
2291 @param StartLba The starting logical block address to write to\r
2292 on the device media.\r
2293 @param NumberOfBlocks The number of transfer data blocks.\r
2294\r
2295 @return status depends on the function DoAtaUdma() returns.\r
2296**/\r
2297EFI_STATUS\r
2298AtaUdmaWriteExt (\r
2299 IN IDE_BLK_IO_DEV *IdeDev,\r
2300 IN VOID *DataBuffer,\r
2301 IN EFI_LBA StartLba,\r
2302 IN UINTN NumberOfBlocks\r
2303 )\r
2304{\r
2305 return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteExtOp);\r
2306}\r
2307\r
2308/**\r
2309 This function is called by the AtaBlkIoWriteBlocks() to perform\r
2310 writing to media in block unit.\r
2311\r
2312 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
2313 to record all the information of the IDE device.\r
2314 @param DataBuffer A pointer to the source buffer for the data.\r
2315 @param StartLba The starting logical block address to write to\r
2316 on the device media.\r
2317 @param NumberOfBlocks The number of transfer data blocks.\r
2318\r
2319 @return status depends on the function DoAtaUdma() returns.\r
2320**/\r
2321EFI_STATUS\r
2322AtaUdmaWrite (\r
2323 IN IDE_BLK_IO_DEV *IdeDev,\r
2324 IN VOID *DataBuffer,\r
2325 IN EFI_LBA StartLba,\r
2326 IN UINTN NumberOfBlocks\r
2327 )\r
2328{\r
2329 return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteOp);\r
2330}\r
2331/**\r
2332 This function is called by the AtaBlkIoWriteBlocks() to perform\r
2333 writing onto media in block unit. The function has been enhanced to\r
2334 support >120GB access and transfer at most 65536 blocks per command\r
2335\r
2336 @param IdeDev pointer pointing to IDE_BLK_IO_DEV data structure,used\r
2337 to record all the information of the IDE device.\r
2338 @param DataBuffer A pointer to the source buffer for the data.\r
2339 @param StartLba The starting logical block address to write onto the device\r
2340 media.\r
2341 @param NumberOfBlocks The number of transfer data blocks.\r
2342\r
2343 @return status is fully dependent on the return status of AtaPioDataOutExt() function.\r
2344**/\r
2345EFI_STATUS\r
2346AtaWriteSectorsExt (\r
2347 IN IDE_BLK_IO_DEV *IdeDev,\r
2348 IN VOID *DataBuffer,\r
2349 IN EFI_LBA StartLba,\r
2350 IN UINTN NumberOfBlocks\r
2351 )\r
2352{\r
2353 EFI_STATUS Status;\r
2354 EFI_LBA Lba64;\r
2355 UINTN BlocksRemaining;\r
2356 UINT8 AtaCommand;\r
2357 UINT16 SectorCount;\r
2358 UINT32 ByteCount;\r
2359 VOID *Buffer;\r
2360\r
2361 //\r
2362 // Using ATA "Write Sectors Ext" cmd(opcode=0x24) with PIO DATA OUT protocol\r
2363 //\r
2364 AtaCommand = ATA_CMD_WRITE_SECTORS_EXT;\r
2365 Lba64 = StartLba;\r
2366 Buffer = DataBuffer;\r
2367 BlocksRemaining = NumberOfBlocks;\r
2368\r
2369 Status = EFI_SUCCESS;\r
2370\r
2371 while (BlocksRemaining > 0) {\r
2372\r
2373 if (BlocksRemaining >= 0x10000) {\r
2374 //\r
2375 // SectorCount is used to record the number of sectors to be written.\r
2376 // Max 65536 sectors can be transfered at a time.\r
2377 //\r
2378 SectorCount = 0xffff;\r
2379 } else {\r
2380 SectorCount = (UINT16) BlocksRemaining;\r
2381 }\r
2382\r
2383 //\r
2384 // ByteCount is the number of bytes that will be written\r
2385 //\r
2386 ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);\r
2387\r
2388 //\r
2389 // Call AtaPioDataOutExt() to send "Write Sectors Ext" Command\r
2390 //\r
2391 Status = AtaPioDataOutExt (\r
2392 IdeDev,\r
2393 Buffer,\r
2394 ByteCount,\r
2395 AtaCommand,\r
2396 Lba64,\r
2397 SectorCount\r
2398 );\r
2399 if (EFI_ERROR (Status)) {\r
2400 return Status;\r
2401 }\r
2402\r
2403 Lba64 += SectorCount;\r
2404 Buffer = ((UINT8 *) Buffer + ByteCount);\r
2405 BlocksRemaining -= SectorCount;\r
2406 }\r
2407\r
2408 return Status;\r
2409}\r
2410/**\r
2411 This function is the ATA implementation for WriteBlocks in the\r
2412 Block I/O Protocol interface.\r
2413\r
2414 @param IdeBlkIoDevice Indicates the calling context.\r
2415 @param MediaId The media id that the write request is for.\r
2416 @param Lba The starting logical block address to write onto the device.\r
2417 @param BufferSize The size of the Buffer in bytes. This must be a multiple\r
2418 of the intrinsic block size of the device.\r
2419 @param Buffer A pointer to the source buffer for the data.The caller\r
2420 is responsible for either having implicit or explicit\r
2421 ownership of the memory that data is written from.\r
2422\r
2423 @retval EFI_SUCCESS Write Blocks successfully.\r
2424 @retval EFI_DEVICE_ERROR Write Blocks failed.\r
2425 @retval EFI_NO_MEDIA There is no media in the device.\r
2426 @retval EFI_MEDIA_CHANGE The MediaId is not for the current media.\r
2427\r
2428 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the\r
2429 intrinsic block size of the device.\r
2430 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
2431 or the data buffer is not valid.\r
2432\r
2433 @note If Write Block error because of device error, this function will call\r
2434 AtaSoftReset() function to reset device.\r
2435**/\r
2436EFI_STATUS\r
2437AtaBlkIoWriteBlocks (\r
2438 IN IDE_BLK_IO_DEV *IdeBlkIoDevice,\r
2439 IN UINT32 MediaId,\r
2440 IN EFI_LBA Lba,\r
2441 IN UINTN BufferSize,\r
2442 OUT VOID *Buffer\r
2443 )\r
2444{\r
2445\r
2446 EFI_BLOCK_IO_MEDIA *Media;\r
2447 UINTN BlockSize;\r
2448 UINTN NumberOfBlocks;\r
2449 EFI_STATUS Status;\r
2450\r
2451 if (Buffer == NULL) {\r
2452 return EFI_INVALID_PARAMETER;\r
2453 }\r
2454\r
2455 if (BufferSize == 0) {\r
2456 return EFI_SUCCESS;\r
2457 }\r
2458\r
2459 Status = EFI_SUCCESS;\r
2460\r
2461 //\r
2462 // Get the intrinsic block size\r
2463 //\r
2464 Media = IdeBlkIoDevice->BlkIo.Media;\r
2465 BlockSize = Media->BlockSize;\r
2466 NumberOfBlocks = BufferSize / BlockSize;\r
2467\r
2468 if (MediaId != Media->MediaId) {\r
2469 return EFI_MEDIA_CHANGED;\r
2470 }\r
2471\r
2472 if (BufferSize % BlockSize != 0) {\r
2473 return EFI_BAD_BUFFER_SIZE;\r
2474 }\r
2475\r
2476 if (Lba > Media->LastBlock) {\r
2477 return EFI_INVALID_PARAMETER;\r
2478 }\r
2479\r
2480 if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {\r
2481 return EFI_INVALID_PARAMETER;\r
2482 }\r
2483\r
2484 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {\r
2485 return EFI_INVALID_PARAMETER;\r
2486 }\r
2487\r
2488 Status = EFI_SUCCESS;\r
2489 if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
2490 //\r
2491 // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism\r
2492 //\r
2493 if (IdeBlkIoDevice->UdmaMode.Valid) {\r
2494 Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
2495 } else {\r
2496 Status = AtaWriteSectorsExt (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
2497 }\r
2498 } else {\r
2499 //\r
2500 // For ATA-3 compatible device, use ATA-3 write block mechanism\r
2501 //\r
2502 if (IdeBlkIoDevice->UdmaMode.Valid) {\r
2503 Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
2504 } else {\r
2505 Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, Lba, NumberOfBlocks);\r
2506 }\r
2507 }\r
2508\r
2509 if (EFI_ERROR (Status)) {\r
2510 AtaSoftReset (IdeBlkIoDevice);\r
2511 return EFI_DEVICE_ERROR;\r
2512 }\r
2513\r
2514 return EFI_SUCCESS;\r
2515}\r
2516/**\r
2517 Enable Long Physical Sector Feature for ATA device.\r
2518\r
2519 @param IdeDev The IDE device data\r
2520\r
2521 @retval EFI_SUCCESS The ATA device supports Long Physical Sector feature\r
2522 and corresponding fields in BlockIo structure is updated.\r
2523 @retval EFI_UNSUPPORTED The device is not ATA device or Long Physical Sector\r
2524 feature is not supported.\r
2525**/\r
2526EFI_STATUS\r
2527AtaEnableLongPhysicalSector (\r
2528 IN IDE_BLK_IO_DEV *IdeDev\r
2529 )\r
2530{\r
2531 EFI_ATA_IDENTIFY_DATA *AtaIdentifyData;\r
2532 UINT16 PhyLogicSectorSupport;\r
2533\r
2534 ASSERT (IdeDev->IdData != NULL);\r
2535 //\r
2536 // Only valid for ATA device\r
2537 //\r
2538 AtaIdentifyData = (EFI_ATA_IDENTIFY_DATA *) &IdeDev->IdData->AtaData;\r
2539 if ((AtaIdentifyData->config & 0x8000) != 0) {\r
2540 return EFI_UNSUPPORTED;\r
2541 }\r
2542 PhyLogicSectorSupport = AtaIdentifyData->phy_logic_sector_support;\r
2543 //\r
2544 // Check whether Long Physical Sector Feature is supported\r
2545 //\r
2546 if ((PhyLogicSectorSupport & 0xc000) == 0x4000) {\r
2547 IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock = 1;\r
2548 IdeDev->BlkIo.Media->LowestAlignedLba = 0;\r
2549 //\r
2550 // Check whether one physical block contains multiple physical blocks\r
2551 //\r
2552 if ((PhyLogicSectorSupport & 0x2000) != 0) {\r
2553 IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock =\r
2554 (UINT32) (1 << (PhyLogicSectorSupport & 0x000f));\r
2555 //\r
2556 // Check lowest alignment of logical blocks within physical block\r
2557 //\r
2558 if ((AtaIdentifyData->alignment_logic_in_phy_blocks & 0xc000) == 0x4000) {\r
2559 IdeDev->BlkIo.Media->LowestAlignedLba =\r
2560 (EFI_LBA) ((IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock - ((UINT32)AtaIdentifyData->alignment_logic_in_phy_blocks & 0x3fff)) %\r
2561 IdeDev->BlkIo.Media->LogicalBlocksPerPhysicalBlock);\r
2562 }\r
2563 }\r
2564 //\r
2565 // Check logical block size\r
2566 //\r
2567 IdeDev->BlkIo.Media->BlockSize = 0x200;\r
2568 if ((PhyLogicSectorSupport & 0x1000) != 0) {\r
2569 IdeDev->BlkIo.Media->BlockSize = (UINT32) (\r
2570 ((AtaIdentifyData->logic_sector_size_hi << 16) |\r
2571 AtaIdentifyData->logic_sector_size_lo) * sizeof (UINT16)\r
2572 );\r
2573 }\r
2574 return EFI_SUCCESS;\r
2575 } else {\r
2576 return EFI_UNSUPPORTED;\r
2577 }\r
2578}\r
2579/**\r
2580 Send ATA command into device with NON_DATA protocol\r
2581\r
2582 @param IdeDev Standard IDE device private data structure\r
2583 @param AtaCommand The ATA command to be sent\r
2584 @param Device The value in Device register\r
2585 @param Feature The value in Feature register\r
2586 @param SectorCount The value in SectorCount register\r
2587 @param LbaLow The value in LBA_LOW register\r
2588 @param LbaMiddle The value in LBA_MIDDLE register\r
2589 @param LbaHigh The value in LBA_HIGH register\r
2590\r
2591 @retval EFI_SUCCESS Reading succeed\r
2592 @retval EFI_ABORTED Command failed\r
2593 @retval EFI_DEVICE_ERROR Device status error.\r
2594\r
2595**/\r
2596EFI_STATUS\r
2597AtaNonDataCommandIn (\r
2598 IN IDE_BLK_IO_DEV *IdeDev,\r
2599 IN UINT8 AtaCommand,\r
2600 IN UINT8 Device,\r
2601 IN UINT8 Feature,\r
2602 IN UINT8 SectorCount,\r
2603 IN UINT8 LbaLow,\r
2604 IN UINT8 LbaMiddle,\r
2605 IN UINT8 LbaHigh\r
2606 )\r
2607{\r
2608 EFI_STATUS Status;\r
2609 UINT8 StatusRegister;\r
2610\r
2611 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
2612 if (EFI_ERROR (Status)) {\r
2613 return EFI_DEVICE_ERROR;\r
2614 }\r
2615\r
2616 //\r
2617 // Select device (bit4), set Lba mode(bit6) (use 0xe0 for compatibility)\r
2618 //\r
2619 IDEWritePortB (\r
2620 IdeDev->PciIo,\r
2621 IdeDev->IoPort->Head,\r
2622 (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
2623 );\r
2624\r
2625 //\r
2626 // ATA commands for ATA device must be issued when DRDY is set\r
2627 //\r
2628 Status = DRDYReady (IdeDev, ATATIMEOUT);\r
2629 if (EFI_ERROR (Status)) {\r
2630 return EFI_DEVICE_ERROR;\r
2631 }\r
2632\r
2633 //\r
2634 // Pass parameter into device register block\r
2635 //\r
2636 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
2637 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature);\r
2638 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);\r
2639 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
2640 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMiddle);\r
2641 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
2642\r
2643 //\r
2644 // Send command via Command Register\r
2645 //\r
2646 IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
2647\r
2648 //\r
2649 // Wait for command completion\r
2650 // For ATAPI_SMART_CMD, we may need more timeout to let device\r
2651 // adjust internal states.\r
2652 //\r
2653 if (AtaCommand == ATA_CMD_SMART) {\r
2654 Status = WaitForBSYClear (IdeDev, ATASMARTTIMEOUT);\r
2655 } else {\r
2656 Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
2657 }\r
2658 if (EFI_ERROR (Status)) {\r
2659 return EFI_DEVICE_ERROR;\r
2660 }\r
2661\r
2662 StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
2663 if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {\r
2664 //\r
2665 // Failed to execute command, abort operation\r
2666 //\r
2667 return EFI_ABORTED;\r
2668 }\r
2669\r
2670 return EFI_SUCCESS;\r
2671}\r
2672\r
2673\r
2674\r