]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Pei/FloppyPeim.c
Update DSC file.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaFloppy / Pei / FloppyPeim.c
CommitLineData
11f43dfd 1/*++\r
2\r
e72a8ec5 3 Copyright (c) 2006 - 2007, Intel Corporation<BR>\r
4 All rights reserved. This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution. The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11f43dfd 11\r
12\r
13Module Name:\r
14\r
15 FloppyPeim.c\r
16 \r
17Abstract: \r
18 \r
19\r
20Revision History\r
21--*/\r
22\r
23\r
24#include "FloppyPeim.h"\r
25#include "IndustryStandard/Pcat.h"\r
26//\r
27// #include "sio.h"\r
28//\r
29\r
30#define PageSize 4096\r
31#define ISA_MAX_MEMORY_ADDRESS 0x1000000 // 16 MB Memory Range\r
32UINT16 FdcBaseAddress = 0x3f0;\r
33\r
34static DISKET_PARA_TABLE DiskPara[9] = {\r
35 {\r
36 0x09,\r
37 0x50,\r
38 0xff,\r
39 0x2,\r
40 0x27,\r
41 0x4,\r
42 0x25,\r
43 0x14,\r
44 0x80\r
45 },\r
46 {\r
47 0x09,\r
48 0x2a,\r
49 0xff,\r
50 0x2,\r
51 0x27,\r
52 0x4,\r
53 0x25,\r
54 0x0f,\r
55 0x40\r
56 },\r
57 {\r
58 0x0f,\r
59 0x54,\r
60 0xff,\r
61 0x2,\r
62 0x4f,\r
63 0x4,\r
64 0x25,\r
65 0x0f,\r
66 0x0\r
67 },\r
68 {\r
69 0x09,\r
70 0x50,\r
71 0xff,\r
72 0x2,\r
73 0x4f,\r
74 0x4,\r
75 0x25,\r
76 0x0f,\r
77 0x80\r
78 },\r
79 {\r
80 0x09,\r
81 0x2a,\r
82 0xff,\r
83 0x2,\r
84 0x4f,\r
85 0x4,\r
86 0x25,\r
87 0x0f,\r
88 0x80\r
89 },\r
90 {\r
91 0x12,\r
92 0x1b,\r
93 0xff,\r
94 0x2,\r
95 0x4f,\r
96 0x4,\r
97 0x25,\r
98 0x0f,\r
99 0x0\r
100 },\r
101 {\r
102 0x09,\r
103 0x2a,\r
104 0xff,\r
105 0x2,\r
106 0x4f,\r
107 0x4,\r
108 0x25,\r
109 0x0f,\r
110 0x80\r
111 },\r
112 {\r
113 0x12,\r
114 0x1b,\r
115 0xff,\r
116 0x2,\r
117 0x4f,\r
118 0x4,\r
119 0x25,\r
120 0x0f,\r
121 0x0\r
122 },\r
123 {\r
124 0x24,\r
125 0x1b,\r
126 0xff,\r
127 0x2,\r
128 0x4f,\r
129 0x4,\r
130 0x25,\r
131 0x0f,\r
132 0xc0\r
133 }\r
134};\r
135\r
136static UINTN BytePerSector[6] = { 0, 256, 512, 1024, 2048, 4096 };\r
137\r
138//\r
139// PEIM Entry Ppint\r
140//\r
141\r
142EFI_STATUS\r
143FdcPeimEntry (\r
144 IN EFI_FFS_FILE_HEADER *FfsHeader,\r
145 IN EFI_PEI_SERVICES **PeiServices\r
146 )\r
147/*++\r
148\r
149Routine Description:\r
150\r
151 Initializes the Fdc Block Io PPI\r
152\r
153Arguments:\r
154\r
155 PeiServices - General purpose services available to every PEIM.\r
156 FfsHeader - Ffs header pointer\r
157 \r
158Returns:\r
159\r
160 EFI_UNSUPPORTED - Can't find neccessary Ppi.\r
161 EFI_OUT_OF_RESOURCES - Have no enough memory to create instance or descriptors.\r
162 EFI_SUCCESS - Success. \r
163\r
164--*/\r
165{\r
166 UINTN MemPages;\r
167 EFI_STATUS Status;\r
168 FDC_BLK_IO_DEV *FdcBlkIoDev;\r
169 EFI_PHYSICAL_ADDRESS TempPtr;\r
170\r
171 //\r
172 // Initializing PEI floppy driver.\r
173 //\r
174 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_PC_INIT);\r
175\r
176 //\r
177 // Data\r
178 //\r
179 // Allocate PEI instance data.\r
180 //\r
181 MemPages = sizeof (FDC_BLK_IO_DEV) / PageSize + 1;\r
182 Status = PeiServicesAllocatePages (\r
183 EfiConventionalMemory,\r
184 MemPages,\r
185 &TempPtr\r
186 );\r
187 if (EFI_ERROR (Status)) {\r
188 return EFI_OUT_OF_RESOURCES;\r
189 }\r
190\r
191 //\r
192 // Initialize PEI instance data.\r
193 //\r
194 FdcBlkIoDev = (FDC_BLK_IO_DEV *) ((UINTN) TempPtr);\r
195 FdcBlkIoDev->Signature = FDC_BLK_IO_DEV_SIGNATURE;\r
196 \r
197 //\r
198 // InitSio ();\r
199 //\r
200 FdcEnumeration (FdcBlkIoDev);\r
201\r
202 FdcBlkIoDev->FdcBlkIo.GetNumberOfBlockDevices = FdcGetNumberOfBlockDevices;\r
203 FdcBlkIoDev->FdcBlkIo.GetBlockDeviceMediaInfo = FdcGetBlockDeviceMediaInfo;\r
204 FdcBlkIoDev->FdcBlkIo.ReadBlocks = FdcReadBlocks;\r
205\r
206 FdcBlkIoDev->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
207 FdcBlkIoDev->PpiDescriptor.Guid = &gEfiPei144FloppyBlockIoPpiGuid;\r
208 FdcBlkIoDev->PpiDescriptor.Ppi = &FdcBlkIoDev->FdcBlkIo;\r
209\r
210 if (FdcBlkIoDev->DeviceCount != 0) {\r
211 Status = PeiServicesInstallPpi (&FdcBlkIoDev->PpiDescriptor);\r
212 if (EFI_ERROR (Status)) {\r
213 //\r
214 // PeiServicesFreePages (TempPtr, MemPages);\r
215 //\r
216 return EFI_OUT_OF_RESOURCES;\r
217 }\r
218 } else {\r
219 //\r
220 // PeiServicesFreePages (TempPtr, MemPages);\r
221 //\r
222 }\r
223\r
224 return EFI_SUCCESS;\r
225}\r
226\r
227EFI_STATUS\r
228EFIAPI\r
229FdcGetNumberOfBlockDevices (\r
230 IN EFI_PEI_SERVICES **PeiServices,\r
231 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
232 OUT UINTN *NumberBlockDevices\r
233 )\r
234/*++\r
235\r
236Routine Description:\r
237\r
238Arguments:\r
239 \r
240Returns:\r
241\r
242--*/\r
243// GC_TODO: This - add argument and description to function comment\r
244// GC_TODO: NumberBlockDevices - add argument and description to function comment\r
245// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
246// GC_TODO: EFI_SUCCESS - add return value to function comment\r
247{\r
248 FDC_BLK_IO_DEV *FdcBlkIoDev;\r
249\r
250 FdcBlkIoDev = NULL;\r
251 if (This == NULL) {\r
252 return EFI_INVALID_PARAMETER;\r
253 }\r
254\r
255 FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This);\r
256\r
257 *NumberBlockDevices = FdcBlkIoDev->DeviceCount;\r
258\r
259 return EFI_SUCCESS;\r
260}\r
261\r
262EFI_STATUS\r
263EFIAPI\r
264FdcGetBlockDeviceMediaInfo (\r
265 IN EFI_PEI_SERVICES **PeiServices,\r
266 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
267 IN UINTN DeviceIndex,\r
268 OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo\r
269 )\r
270/*++\r
271\r
272Routine Description:\r
273\r
274 GC_TODO: Add function description\r
275\r
276Arguments:\r
277\r
278 This - GC_TODO: add argument description\r
279 DeviceIndex - GC_TODO: add argument description\r
280 MediaInfo - GC_TODO: add argument description\r
281\r
282Returns:\r
283\r
284 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value\r
285 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value\r
286 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
287 EFI_SUCCESS - GC_TODO: Add description for return value\r
288\r
289--*/\r
290{\r
291 UINTN DeviceCount;\r
292 FDC_BLK_IO_DEV *FdcBlkIoDev;\r
293 BOOLEAN bStatus;\r
294\r
295 FdcBlkIoDev = NULL;\r
296\r
297 if (This == NULL || MediaInfo == NULL) {\r
298 return EFI_INVALID_PARAMETER;\r
299 }\r
300\r
301 FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This);\r
302\r
303 DeviceCount = FdcBlkIoDev->DeviceCount;\r
304\r
305 //\r
306 // DeviceIndex is zero-based value.\r
307 //\r
308 if (DeviceIndex > DeviceCount - 1) {\r
309 return EFI_INVALID_PARAMETER;\r
310 }\r
311 //\r
312 // probe media and retrieve latest media information\r
313 //\r
314 bStatus = DiscoverFdcDevice (\r
315 FdcBlkIoDev,\r
316 &FdcBlkIoDev->DeviceInfo[DeviceIndex],\r
317 MediaInfo\r
318 );\r
319\r
320 if (!bStatus) {\r
321 return EFI_DEVICE_ERROR;\r
322 }\r
323\r
324 CopyMem (\r
325 &(FdcBlkIoDev->DeviceInfo[DeviceIndex].MediaInfo),\r
326 MediaInfo,\r
327 sizeof (EFI_PEI_BLOCK_IO_MEDIA)\r
328 );\r
329 return EFI_SUCCESS;\r
330}\r
331\r
332EFI_STATUS\r
333EFIAPI\r
334FdcReadBlocks (\r
335 IN EFI_PEI_SERVICES **PeiServices,\r
336 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
337 IN UINTN DeviceIndex,\r
338 IN EFI_PEI_LBA StartLba,\r
339 IN UINTN BufferSize,\r
340 OUT VOID *Buffer\r
341 )\r
342/*++\r
343\r
344Routine Description:\r
345\r
346 GC_TODO: Add function description\r
347\r
348Arguments:\r
349\r
350 This - GC_TODO: add argument description\r
351 DeviceIndex - GC_TODO: add argument description\r
352 StartLba - GC_TODO: add argument description\r
353 BufferSize - GC_TODO: add argument description\r
354 Buffer - GC_TODO: add argument description\r
355\r
356Returns:\r
357\r
358 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value\r
359 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value\r
360 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value\r
361 EFI_NO_MEDIA - GC_TODO: Add description for return value\r
362 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
363 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
364 EFI_SUCCESS - GC_TODO: Add description for return value\r
365 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
366\r
367--*/\r
368{\r
369\r
370 EFI_PEI_BLOCK_IO_MEDIA MediaInfo;\r
371 EFI_STATUS Status;\r
372 UINTN i;\r
373 UINTN NumberOfBlocks;\r
374 UINTN BlockSize;\r
375 FDC_BLK_IO_DEV *FdcBlkIoDev;\r
376 EFI_PHYSICAL_ADDRESS MemPage;\r
377\r
378 FdcBlkIoDev = NULL;\r
379\r
380 if (This == NULL) {\r
381 return EFI_INVALID_PARAMETER;\r
382 }\r
383\r
384 FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This);\r
385\r
386 if (Buffer == NULL) {\r
387 return EFI_INVALID_PARAMETER;\r
388 }\r
389\r
390 Status = FdcGetBlockDeviceMediaInfo (PeiServices, This, DeviceIndex, &MediaInfo);\r
391 if (Status != EFI_SUCCESS) {\r
392 return Status;\r
393 }\r
394\r
395 BlockSize = MediaInfo.BlockSize;\r
396\r
397 if (BufferSize % BlockSize != 0) {\r
398 return EFI_INVALID_PARAMETER;\r
399 }\r
400\r
401 if (!MediaInfo.MediaPresent) {\r
402 return EFI_NO_MEDIA;\r
403 }\r
404\r
405 NumberOfBlocks = BufferSize / BlockSize;\r
406\r
407 //\r
408 // allocate 40 blocks: 5*4k=20k=20*1024=40blocks\r
409 //\r
410 MemPage = ISA_MAX_MEMORY_ADDRESS - 1;\r
411 Status = PeiServicesAllocatePages (\r
412 EfiConventionalMemory,\r
413 ((BufferSize % EFI_PAGE_SIZE) ? (BufferSize / EFI_PAGE_SIZE + 1) : (BufferSize / EFI_PAGE_SIZE)),\r
414 &MemPage\r
415 );\r
416 if (EFI_ERROR (Status) || (MemPage >= ISA_MAX_MEMORY_ADDRESS)) {\r
417 //\r
418 // If failed, designate the address space for DMA\r
419 //\r
420 MemPage = 0x0f00000;\r
421 //\r
422 // return EFI_OUT_OF_RESOURCES;\r
423 //\r
424 }\r
425 //\r
426 // MemPage = (EFI_PHYSICAL_ADDRESS)(UINTN)Temp;\r
427 //\r
428 Status = MotorOn (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex]));\r
429 if (Status != EFI_SUCCESS) {\r
430 return EFI_DEVICE_ERROR;\r
431 }\r
432\r
433 Status = Setup (FdcBlkIoDev, FdcBlkIoDev->DeviceInfo[DeviceIndex].DevPos);\r
434 if (Status != EFI_SUCCESS) {\r
435 MotorOff (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex]));\r
436 return EFI_DEVICE_ERROR;\r
437 }\r
438 //\r
439 // read blocks in the same cylinder.\r
440 // in a cylinder , there are 18 * 2 = 36 blocks\r
441 //\r
442 while ((i = GetTransferBlockCount (\r
443 &(FdcBlkIoDev->DeviceInfo[DeviceIndex]),\r
444 StartLba,\r
445 NumberOfBlocks\r
446 )) != 0 && Status == EFI_SUCCESS) {\r
447 Status = ReadWriteDataSector (\r
448 FdcBlkIoDev,\r
449 &(FdcBlkIoDev->DeviceInfo[DeviceIndex]),\r
450 (UINT8 *) (UINTN) MemPage,\r
451 StartLba,\r
452 i,\r
453 READ\r
454 );\r
455 CopyMem ((UINT8 *) Buffer, (UINT8 *) (UINTN) MemPage, BlockSize * i);\r
456 StartLba += i;\r
457 NumberOfBlocks -= i;\r
458 Buffer = (VOID *) ((UINTN) Buffer + i * BlockSize);\r
459 }\r
460 //\r
461 // PeiServicesFreePages (MemPage, 5);\r
462 //\r
463 MotorOff (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex]));\r
464\r
465 switch (Status) {\r
466 case EFI_SUCCESS:\r
467 return EFI_SUCCESS;\r
468\r
469 default:\r
470 FdcReset (FdcBlkIoDev, FdcBlkIoDev->DeviceInfo[DeviceIndex].DevPos);\r
471 return EFI_DEVICE_ERROR;\r
472 }\r
473 //\r
474 // return Status;\r
475 //\r
476}\r
477//\r
478// Internal function Implementation\r
479//\r
480UINT8\r
481FdcEnumeration (\r
482 IN FDC_BLK_IO_DEV *FdcBlkIoDev\r
483 )\r
484/*++\r
485\r
486Routine Description:\r
487\r
488 Enumerate floppy device\r
489\r
490Arguments:\r
491\r
492 FdcBlkIoDev - Instance of floppy device controller\r
493\r
494Returns:\r
495\r
496 DevNo - Device No.\r
497\r
498--*/\r
499{\r
500 UINT8 DevPos;\r
501 UINT8 DevNo;\r
502 EFI_PEI_BLOCK_IO_MEDIA MediaInfo;\r
503 EFI_STATUS Status;\r
504\r
505 DevNo = 0;\r
506\r
507 //\r
508 // DevPos=0 means A: 1 means B:\r
509 //\r
510 for (DevPos = 0; DevPos < 2; DevPos++) {\r
511 //\r
512 // Detecting device presence\r
513 //\r
514 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_PC_PRESENCE_DETECT);\r
515\r
516 //\r
517 // Data\r
518 //\r
519 // Reset FDC\r
520 //\r
521 Status = FdcReset (FdcBlkIoDev, DevPos);\r
522\r
523 if (EFI_ERROR (Status)) {\r
524 continue;\r
525 }\r
526\r
527 FdcBlkIoDev->DeviceInfo[DevPos].DevPos = DevPos;\r
528 FdcBlkIoDev->DeviceInfo[DevPos].Pcn = 0;\r
529 FdcBlkIoDev->DeviceInfo[DevPos].MotorOn = FALSE;\r
530 FdcBlkIoDev->DeviceInfo[DevPos].NeedRecalibrate = TRUE;\r
531 FdcBlkIoDev->DeviceInfo[DevPos].Type = _1440K_1440K;\r
532\r
533 //\r
534 // Discover FDC device\r
535 //\r
536 if (DiscoverFdcDevice (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DevPos]), &MediaInfo)) {\r
537 FdcBlkIoDev->DeviceInfo[DevNo].DevPos = DevPos;\r
538\r
539 FdcBlkIoDev->DeviceInfo[DevNo].Pcn = FdcBlkIoDev->DeviceInfo[DevPos].Pcn;\r
540 FdcBlkIoDev->DeviceInfo[DevNo].MotorOn = FdcBlkIoDev->DeviceInfo[DevPos].MotorOn;\r
541 FdcBlkIoDev->DeviceInfo[DevNo].NeedRecalibrate = FdcBlkIoDev->DeviceInfo[DevPos].NeedRecalibrate;\r
542 FdcBlkIoDev->DeviceInfo[DevNo].Type = FdcBlkIoDev->DeviceInfo[DevPos].Type;\r
543\r
544 CopyMem (\r
545 &(FdcBlkIoDev->DeviceInfo[DevNo].MediaInfo),\r
546 &MediaInfo,\r
547 sizeof (EFI_PEI_BLOCK_IO_MEDIA)\r
548 );\r
549\r
550 DevNo++;\r
551 } else {\r
552 //\r
553 // Assume controller error\r
554 //\r
555 REPORT_STATUS_CODE (\r
556 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
557 EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_EC_CONTROLLER_ERROR\r
558 );\r
559\r
560 //\r
561 // Data\r
562 //\r
563 }\r
564 }\r
565\r
566 FdcBlkIoDev->DeviceCount = DevNo;\r
567 return DevNo;\r
568}\r
569\r
570BOOLEAN\r
571DiscoverFdcDevice (\r
572 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
573 IN OUT PEI_FLOPPY_DEVICE_INFO *Info,\r
574 OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo\r
575 )\r
576/*++\r
577\r
578Routine Description:\r
579\r
580 GC_TODO: Add function description\r
581\r
582Arguments:\r
583\r
584 FdcBlkIoDev - GC_TODO: add argument description\r
585 Info - GC_TODO: add argument description\r
586 MediaInfo - GC_TODO: add argument description\r
587\r
588Returns:\r
589\r
590 GC_TODO: add return values\r
591\r
592--*/\r
593{\r
594 EFI_STATUS Status;\r
595 DISKET_PARA_TABLE *Para;\r
596\r
597 Status = MotorOn (FdcBlkIoDev, Info);\r
598 if (Status != EFI_SUCCESS) {\r
599 return FALSE;\r
600 }\r
601\r
602 Status = Recalibrate (FdcBlkIoDev, Info);\r
603\r
604 if (Status != EFI_SUCCESS) {\r
605 MotorOff (FdcBlkIoDev, Info);\r
606 return FALSE;\r
607 }\r
608 //\r
609 // Set Media Parameter\r
610 //\r
611 MediaInfo->DeviceType = LegacyFloppy;\r
612 MediaInfo->MediaPresent = TRUE;\r
613\r
614 //\r
615 // Check Media\r
616 //\r
617 Status = DisketChanged (FdcBlkIoDev, Info);\r
618 switch (Status) {\r
619 case EFI_NO_MEDIA:\r
620 MediaInfo->MediaPresent = FALSE;\r
621 break;\r
622\r
623 case EFI_MEDIA_CHANGED:\r
624 case EFI_SUCCESS:\r
625 break;\r
626\r
627 default:\r
628 //\r
629 // EFI_DEVICE_ERROR\r
630 //\r
631 MotorOff (FdcBlkIoDev, Info);\r
632 return FALSE;\r
633 }\r
634\r
635 MotorOff (FdcBlkIoDev, Info);\r
636\r
637 Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type);\r
638 MediaInfo->BlockSize = BytePerSector[Para->Number];\r
639 MediaInfo->LastBlock = Para->EOT * 2 * (Para->MaxTrackNum + 1) - 1;\r
640\r
641 return TRUE;\r
642}\r
643\r
644EFI_STATUS\r
645FdcReset (\r
646 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
647 IN UINT8 DevPos\r
648 )\r
649/*++\r
650\r
651Routine Description:\r
652\r
653 GC_TODO: Add function description\r
654\r
655Arguments:\r
656\r
657 FdcBlkIoDev - GC_TODO: add argument description\r
658 DevPos - GC_TODO: add argument description\r
659\r
660Returns:\r
661\r
662 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
663 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
664 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
665 EFI_SUCCESS - GC_TODO: Add description for return value\r
666\r
667--*/\r
668{\r
669 UINT8 data;\r
670 UINT8 sts0;\r
671 UINT8 pcn;\r
672 UINTN i;\r
673\r
674 //\r
675 // Reset specified Floppy Logic Drive according to Fdd -> Disk\r
676 // Set Digital Output Register(DOR) to do reset work\r
677 // bit0 & bit1 of DOR : Drive Select\r
678 // bit2 : Reset bit\r
679 // bit3 : DMA and Int bit\r
680 // Reset : A "0" written to bit2 resets the FDC, this reset will remain active until\r
681 // a "1" is written to this bit.\r
682 // Reset step 1:\r
683 // use bit0 & bit1 to select the logic drive\r
684 // write "0" to bit2\r
685 //\r
686 data = 0x0;\r
687 data = (UINT8) (data | (SELECT_DRV & DevPos));\r
688 IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DOR), data);\r
689\r
690 //\r
691 // wait some time,at least 120us\r
692 //\r
693 MicroSecondDelay (500);\r
694 //\r
695 // Reset step 2:\r
696 // write "1" to bit2\r
697 // write "1" to bit3 : enable DMA\r
698 //\r
699 data |= 0x0C;\r
700 IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DOR), data);\r
701\r
702 MicroSecondDelay (2000);\r
703 \r
704 //\r
705 // wait specified floppy logic drive is not busy\r
706 //\r
707 if (FdcWaitForBSYClear (FdcBlkIoDev, DevPos, 1) != EFI_SUCCESS) {\r
708 return EFI_DEVICE_ERROR;\r
709 }\r
710 //\r
711 // Set the Transfer Data Rate\r
712 //\r
713 IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_CCR), 0x0);\r
714\r
715 MicroSecondDelay (100);\r
716\r
717 //\r
718 // Issue Sense interrupt command for each drive (total 4 drives)\r
719 //\r
720 for (i = 0; i < 4; i++) {\r
721 if (SenseIntStatus (FdcBlkIoDev, &sts0, &pcn) != EFI_SUCCESS) {\r
722 return EFI_DEVICE_ERROR;\r
723 }\r
724 }\r
725 //\r
726 // issue Specify command\r
727 //\r
728 if (Specify (FdcBlkIoDev) != EFI_SUCCESS) {\r
729 return EFI_DEVICE_ERROR;\r
730 }\r
731\r
732 return EFI_SUCCESS;\r
733}\r
734\r
735EFI_STATUS\r
736FdcWaitForBSYClear (\r
737 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
738 IN UINT8 DevPos,\r
739 IN UINTN TimeoutInSeconds\r
740 )\r
741/*++\r
742\r
743Routine Description:\r
744\r
745 GC_TODO: Add function description\r
746\r
747Arguments:\r
748\r
749 FdcBlkIoDev - GC_TODO: add argument description\r
750 DevPos - GC_TODO: add argument description\r
751 TimeoutInSeconds - GC_TODO: add argument description\r
752\r
753Returns:\r
754\r
755 EFI_TIMEOUT - GC_TODO: Add description for return value\r
756 EFI_SUCCESS - GC_TODO: Add description for return value\r
757\r
758--*/\r
759{\r
760 UINTN Delay;\r
761 UINT8 StatusRegister;\r
762 UINT8 Mask;\r
763\r
764 //\r
765 // How to determine drive and command are busy or not: by the bits of Main Status Register\r
766 // bit0: Drive 0 busy (drive A)\r
767 // bit1: Drive 1 busy (drive B)\r
768 // bit4: Command busy\r
769 //\r
770 // set mask: for drive A set bit0 & bit4; for drive B set bit1 & bit4\r
771 //\r
772 Mask = (UINT8) ((DevPos == 0 ? MSR_DAB : MSR_DBB) | MSR_CB);\r
773\r
774 Delay = ((TimeoutInSeconds * STALL_1_MSECOND) / 50) + 1;\r
775\r
776 do {\r
777 StatusRegister = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_MSR));\r
778\r
779 if ((StatusRegister & Mask) == 0x00) {\r
780 break;\r
781 //\r
782 // not busy\r
783 //\r
784 }\r
785\r
786 MicroSecondDelay (50);\r
787 } while (--Delay);\r
788\r
789 if (Delay == 0) {\r
790 return EFI_TIMEOUT;\r
791 }\r
792\r
793 return EFI_SUCCESS;\r
794}\r
795\r
796EFI_STATUS\r
797SenseIntStatus (\r
798 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
799 IN OUT UINT8 *sts0,\r
800 IN OUT UINT8 *pcn\r
801 )\r
802/*++\r
803\r
804Routine Description:\r
805\r
806 GC_TODO: Add function description\r
807\r
808Arguments:\r
809\r
810 FdcBlkIoDev - GC_TODO: add argument description\r
811 sts0 - GC_TODO: add argument description\r
812 pcn - GC_TODO: add argument description\r
813\r
814Returns:\r
815\r
816 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
817 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
818 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
819 EFI_SUCCESS - GC_TODO: Add description for return value\r
820\r
821--*/\r
822{\r
823 UINT8 command;\r
824\r
825 command = SENSE_INT_STATUS_CMD;\r
826 if (DataOutByte (FdcBlkIoDev, &command) != EFI_SUCCESS) {\r
827 return EFI_DEVICE_ERROR;\r
828 }\r
829\r
830 if (DataInByte (FdcBlkIoDev, sts0) != EFI_SUCCESS) {\r
831 return EFI_DEVICE_ERROR;\r
832 }\r
833\r
834 if (DataInByte (FdcBlkIoDev, pcn) != EFI_SUCCESS) {\r
835 return EFI_DEVICE_ERROR;\r
836 }\r
837\r
838 return EFI_SUCCESS;\r
839}\r
840\r
841EFI_STATUS\r
842Specify (\r
843 IN FDC_BLK_IO_DEV *FdcBlkIoDev\r
844 )\r
845/*++\r
846\r
847Routine Description:\r
848\r
849 GC_TODO: Add function description\r
850\r
851Arguments:\r
852\r
853 FdcBlkIoDev - GC_TODO: add argument description\r
854\r
855Returns:\r
856\r
857 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
858 EFI_SUCCESS - GC_TODO: Add description for return value\r
859\r
860--*/\r
861{\r
862 FDC_SPECIFY_CMD Command;\r
863 UINTN i;\r
864 UINT8 *pt;\r
865\r
866 ZeroMem (&Command, sizeof (FDC_SPECIFY_CMD));\r
867 Command.CommandCode = SPECIFY_CMD;\r
868 //\r
869 // set SRT, HUT\r
870 //\r
871 Command.SrtHut = 0xdf;\r
872 //\r
873 // 0xdf;\r
874 // set HLT and DMA\r
875 //\r
876 Command.HltNd = 0x02;\r
877\r
878 pt = (UINT8 *) (&Command);\r
879 for (i = 0; i < sizeof (FDC_SPECIFY_CMD); i++) {\r
880 if (DataOutByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {\r
881 return EFI_DEVICE_ERROR;\r
882 }\r
883 }\r
884\r
885 return EFI_SUCCESS;\r
886}\r
887\r
888EFI_STATUS\r
889DataInByte (\r
890 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
891 IN OUT UINT8 *pt\r
892 )\r
893/*++\r
894\r
895Routine Description:\r
896\r
897 GC_TODO: Add function description\r
898\r
899Arguments:\r
900\r
901 FdcBlkIoDev - GC_TODO: add argument description\r
902 pt - GC_TODO: add argument description\r
903\r
904Returns:\r
905\r
906 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
907 EFI_SUCCESS - GC_TODO: Add description for return value\r
908\r
909--*/\r
910{\r
911 UINT8 data;\r
912\r
913 //\r
914 // wait for 1ms and detect the FDC is ready to be read\r
915 //\r
916 if (FdcDRQReady (FdcBlkIoDev, DATA_IN, 1) != EFI_SUCCESS) {\r
917 return EFI_DEVICE_ERROR;\r
918 //\r
919 // is not ready\r
920 //\r
921 }\r
922\r
923 data = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DTR));\r
924 MicroSecondDelay (50);\r
925 *pt = data;\r
926 return EFI_SUCCESS;\r
927}\r
928\r
929EFI_STATUS\r
930DataOutByte (\r
931 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
932 IN UINT8 *pt\r
933 )\r
934/*++\r
935\r
936Routine Description:\r
937\r
938 GC_TODO: Add function description\r
939\r
940Arguments:\r
941\r
942 FdcBlkIoDev - GC_TODO: add argument description\r
943 pt - GC_TODO: add argument description\r
944\r
945Returns:\r
946\r
947 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
948 EFI_SUCCESS - GC_TODO: Add description for return value\r
949\r
950--*/\r
951{\r
952 UINT8 data;\r
953\r
954 //\r
955 // wait for 1ms and detect the FDC is ready to be written\r
956 //\r
957 if (FdcDRQReady (FdcBlkIoDev, DATA_OUT, 1) != EFI_SUCCESS) {\r
958 return EFI_DEVICE_ERROR;\r
959 //\r
960 // is not ready\r
961 //\r
962 }\r
963\r
964 data = *pt;\r
965 IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DTR), data);\r
966 MicroSecondDelay (50);\r
967 return EFI_SUCCESS;\r
968}\r
969\r
970EFI_STATUS\r
971FdcDRQReady (\r
972 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
973 IN BOOLEAN Dio,\r
974 IN UINTN TimeoutInSeconds\r
975 )\r
976/*++\r
977\r
978Routine Description:\r
979\r
980 GC_TODO: Add function description\r
981\r
982Arguments:\r
983\r
984 FdcBlkIoDev - GC_TODO: add argument description\r
985 Dio - GC_TODO: add argument description\r
986 TimeoutInSeconds - GC_TODO: add argument description\r
987\r
988Returns:\r
989\r
990 EFI_NOT_READY - GC_TODO: Add description for return value\r
991 EFI_SUCCESS - GC_TODO: Add description for return value\r
992\r
993--*/\r
994{\r
995 UINTN Delay;\r
996 UINT8 StatusRegister;\r
997 UINT8 DataInOut;\r
998\r
999 //\r
1000 // Before writing to FDC or reading from FDC, the Host must examine\r
1001 // the bit7(RQM) and bit6(DIO) of the Main Status Register.\r
1002 // That is to say:\r
1003 // command bytes can not be written to Data Register unless RQM is 1 and DIO is 0\r
1004 // result bytes can not be read from Data Register unless RQM is 1 and DIO is 1\r
1005 //\r
1006 DataInOut = (UINT8) (Dio << 6);\r
1007 //\r
1008 // in order to compare bit6\r
1009 //\r
1010 Delay = ((TimeoutInSeconds * STALL_1_MSECOND) / 50) + 1;\r
1011 do {\r
1012 StatusRegister = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_MSR));\r
1013 if ((StatusRegister & MSR_RQM) == MSR_RQM && (StatusRegister & MSR_DIO) == DataInOut) {\r
1014 break;\r
1015 //\r
1016 // FDC is ready\r
1017 //\r
1018 }\r
1019\r
1020 MicroSecondDelay (50);\r
1021 } while (--Delay);\r
1022\r
1023 if (Delay == 0) {\r
1024 return EFI_NOT_READY;\r
1025 //\r
1026 // FDC is not ready within the specified time period\r
1027 //\r
1028 }\r
1029\r
1030 return EFI_SUCCESS;\r
1031}\r
1032\r
1033EFI_STATUS\r
1034MotorOn (\r
1035 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
1036 IN OUT PEI_FLOPPY_DEVICE_INFO *Info\r
1037 )\r
1038/*++\r
1039\r
1040Routine Description:\r
1041\r
1042 GC_TODO: Add function description\r
1043\r
1044Arguments:\r
1045\r
1046 FdcBlkIoDev - GC_TODO: add argument description\r
1047 Info - GC_TODO: add argument description\r
1048\r
1049Returns:\r
1050\r
1051 EFI_SUCCESS - GC_TODO: Add description for return value\r
1052 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1053 EFI_SUCCESS - GC_TODO: Add description for return value\r
1054\r
1055--*/\r
1056{\r
1057 //\r
1058 // EFI_STATUS Status;\r
1059 //\r
1060 UINT8 data;\r
1061 UINT8 DevPos;\r
1062\r
1063 //\r
1064 // Control of the floppy drive motors is a big pain. If motor is off, you have to turn it\r
1065 // on first. But you can not leave the motor on all the time, since that would wear out the\r
1066 // disk. On the other hand, if you turn the motor off after each operation, the system performance\r
1067 // will be awful. The compromise used in this driver is to leave the motor on for 2 seconds after\r
1068 // each operation. If a new operation is started in that interval(2s), the motor need not be\r
1069 // turned on again. If no new operation is started, a timer goes off and the motor is turned off\r
1070 //\r
1071 DevPos = Info->DevPos;\r
1072\r
1073 if (Info->MotorOn) {\r
1074 return EFI_SUCCESS;\r
1075 }\r
1076 //\r
1077 // The drive's motor is off, so need turn it on\r
1078 // first look at command and drive are busy or not\r
1079 //\r
1080 if (FdcWaitForBSYClear (FdcBlkIoDev, DevPos, 1) != EFI_SUCCESS) {\r
1081 return EFI_DEVICE_ERROR;\r
1082 }\r
1083 //\r
1084 // for drive A: 1CH, drive B: 2DH\r
1085 //\r
1086 data = 0x0C;\r
1087 data = (UINT8) (data | (SELECT_DRV & DevPos));\r
1088 if (DevPos == 0) {\r
1089 data |= DRVA_MOTOR_ON;\r
1090 //\r
1091 // FdcTimer[1].MotorOn = FALSE;\r
1092 // Info->MotorOn = FALSE;\r
1093 //\r
1094 } else {\r
1095 data |= DRVB_MOTOR_ON;\r
1096 //\r
1097 // FdcTimer[0].MotorOn = FALSE;\r
1098 // Info->MotorOn = FALSE;\r
1099 //\r
1100 }\r
1101\r
1102 Info->MotorOn = FALSE;\r
1103\r
1104 IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DOR), data);\r
1105\r
1106 MicroSecondDelay (4000);\r
1107 //\r
1108 // FdcTimer[DevPos].MotorOn = TRUE;\r
1109 //\r
1110 Info->MotorOn = TRUE;\r
1111 return EFI_SUCCESS;\r
1112}\r
1113\r
1114EFI_STATUS\r
1115MotorOff (\r
1116 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
1117 IN OUT PEI_FLOPPY_DEVICE_INFO *Info\r
1118 )\r
1119/*++\r
1120\r
1121Routine Description:\r
1122\r
1123 GC_TODO: Add function description\r
1124\r
1125Arguments:\r
1126\r
1127 FdcBlkIoDev - GC_TODO: add argument description\r
1128 Info - GC_TODO: add argument description\r
1129\r
1130Returns:\r
1131\r
1132 EFI_SUCCESS - GC_TODO: Add description for return value\r
1133 EFI_SUCCESS - GC_TODO: Add description for return value\r
1134\r
1135--*/\r
1136{\r
1137 UINT8 data;\r
1138 UINT8 DevPos;\r
1139\r
1140 DevPos = Info->DevPos;\r
1141\r
1142 if (!Info->MotorOn) {\r
1143 return EFI_SUCCESS;\r
1144 }\r
1145 //\r
1146 // the motor is on, so need motor off\r
1147 //\r
1148 data = 0x0C;\r
1149 data = (UINT8) (data | (SELECT_DRV & DevPos));\r
1150\r
1151 IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DOR), data);\r
1152 MicroSecondDelay (50);\r
1153 //\r
1154 // FdcTimer[DevPos].MotorOn = FALSE;\r
1155 //\r
1156 Info->MotorOn = FALSE;\r
1157\r
1158 return EFI_SUCCESS;\r
1159}\r
1160\r
1161EFI_STATUS\r
1162DisketChanged (\r
1163 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
1164 IN OUT PEI_FLOPPY_DEVICE_INFO *Info\r
1165 )\r
1166/*++\r
1167\r
1168Routine Description:\r
1169\r
1170 GC_TODO: Add function description\r
1171\r
1172Arguments:\r
1173\r
1174 FdcBlkIoDev - GC_TODO: add argument description\r
1175 Info - GC_TODO: add argument description\r
1176\r
1177Returns:\r
1178\r
1179 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1180 EFI_NO_MEDIA - GC_TODO: Add description for return value\r
1181 EFI_MEDIA_CHANGED - GC_TODO: Add description for return value\r
1182 EFI_SUCCESS - GC_TODO: Add description for return value\r
1183\r
1184--*/\r
1185{\r
1186 EFI_STATUS Status;\r
1187 UINT8 data;\r
1188\r
1189 //\r
1190 // Check change line\r
1191 //\r
1192 data = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DIR));\r
1193\r
1194 MicroSecondDelay (50);\r
1195\r
1196 if ((data & DIR_DCL) == 0x80) {\r
1197 if (Info->Pcn != 0) {\r
1198 Status = Recalibrate (FdcBlkIoDev, Info);\r
1199 } else {\r
1200 Status = Seek (FdcBlkIoDev, Info, 0x30);\r
1201 }\r
1202\r
1203 if (Status != EFI_SUCCESS) {\r
1204 return EFI_DEVICE_ERROR;\r
1205 //\r
1206 // Fail to do the seek or recalibrate operation\r
1207 //\r
1208 }\r
1209\r
1210 data = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DIR));\r
1211\r
1212 MicroSecondDelay (50);\r
1213\r
1214 if ((data & DIR_DCL) == 0x80) {\r
1215 return EFI_NO_MEDIA;\r
1216 }\r
1217\r
1218 return EFI_MEDIA_CHANGED;\r
1219 }\r
1220\r
1221 return EFI_SUCCESS;\r
1222}\r
1223\r
1224EFI_STATUS\r
1225Recalibrate (\r
1226 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
1227 IN OUT PEI_FLOPPY_DEVICE_INFO *Info\r
1228 )\r
1229/*++\r
1230\r
1231Routine Description:\r
1232\r
1233 GC_TODO: Add function description\r
1234\r
1235Arguments:\r
1236\r
1237 FdcBlkIoDev - GC_TODO: add argument description\r
1238 Info - GC_TODO: add argument description\r
1239\r
1240Returns:\r
1241\r
1242 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1243 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1244 EFI_SUCCESS - GC_TODO: Add description for return value\r
1245 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1246 EFI_SUCCESS - GC_TODO: Add description for return value\r
1247\r
1248--*/\r
1249{\r
1250 FDC_COMMAND_PACKET2 Command;\r
1251 UINTN i;\r
1252 UINT8 sts0;\r
1253 UINT8 pcn;\r
1254 UINT8 *pt;\r
1255 UINT8 Count;\r
1256 UINT8 DevPos;\r
1257\r
1258 Count = 2;\r
1259 DevPos = Info->DevPos;\r
1260\r
1261 while (Count > 0) {\r
1262 ZeroMem (&Command, sizeof (FDC_COMMAND_PACKET2));\r
1263 Command.CommandCode = RECALIBRATE_CMD;\r
1264 //\r
1265 // drive select\r
1266 //\r
1267 if (DevPos == 0) {\r
1268 Command.DiskHeadSel = 0;\r
1269 //\r
1270 // 0\r
1271 //\r
1272 } else {\r
1273 Command.DiskHeadSel = 1;\r
1274 //\r
1275 // 1\r
1276 //\r
1277 }\r
1278\r
1279 pt = (UINT8 *) (&Command);\r
1280 for (i = 0; i < sizeof (FDC_COMMAND_PACKET2); i++) {\r
1281 if (DataOutByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {\r
1282 return EFI_DEVICE_ERROR;\r
1283 }\r
1284 }\r
1285\r
1286 MicroSecondDelay (250000);\r
1287\r
1288 if (SenseIntStatus (FdcBlkIoDev, &sts0, &pcn) != EFI_SUCCESS) {\r
1289 return EFI_DEVICE_ERROR;\r
1290 }\r
1291\r
1292 if ((sts0 & 0xf0) == 0x20 && pcn == 0) {\r
1293 //\r
1294 // FdcTimer[DevPos].Pcn = 0;\r
1295 //\r
1296 Info->Pcn = 0;\r
1297 //\r
1298 // FdcTimer[DevPos].NeedRecalibrate = FALSE;\r
1299 //\r
1300 Info->NeedRecalibrate = FALSE;\r
1301 return EFI_SUCCESS;\r
1302 } else {\r
1303 Count--;\r
1304 if (Count == 0) {\r
1305 return EFI_DEVICE_ERROR;\r
1306 }\r
1307 }\r
1308 }\r
1309 //\r
1310 // end while\r
1311 //\r
1312 return EFI_SUCCESS;\r
1313}\r
1314\r
1315EFI_STATUS\r
1316Seek (\r
1317 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
1318 IN OUT PEI_FLOPPY_DEVICE_INFO *Info,\r
1319 IN EFI_PEI_LBA Lba\r
1320 )\r
1321/*++\r
1322\r
1323Routine Description:\r
1324\r
1325 GC_TODO: Add function description\r
1326\r
1327Arguments:\r
1328\r
1329 FdcBlkIoDev - GC_TODO: add argument description\r
1330 Info - GC_TODO: add argument description\r
1331 Lba - GC_TODO: add argument description\r
1332\r
1333Returns:\r
1334\r
1335 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1336 EFI_SUCCESS - GC_TODO: Add description for return value\r
1337 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1338 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1339 EFI_SUCCESS - GC_TODO: Add description for return value\r
1340 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1341\r
1342--*/\r
1343{\r
1344 FDC_SEEK_CMD Command;\r
1345 DISKET_PARA_TABLE *Para;\r
1346 UINT8 EndOfTrack;\r
1347 UINT8 Head;\r
1348 UINT8 Cylinder;\r
1349 UINT8 sts0;\r
1350 UINT8 *pt;\r
1351 UINT8 pcn;\r
1352 UINTN i;\r
1353 UINT8 x;\r
1354 UINT8 DevPos;\r
1355\r
1356 DevPos = Info->DevPos;\r
1357 if (Info->NeedRecalibrate) {\r
1358 if (Recalibrate (FdcBlkIoDev, Info) != EFI_SUCCESS) {\r
1359 return EFI_DEVICE_ERROR;\r
1360 }\r
1361 //\r
1362 // Recalibrate Success\r
1363 //\r
1364 Info->NeedRecalibrate = FALSE;\r
1365 }\r
1366\r
1367 Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type);\r
1368 EndOfTrack = Para->EOT;\r
1369 //\r
1370 // Calculate cylinder based on Lba and EOT\r
1371 //\r
1372 Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2);\r
1373\r
1374 //\r
1375 // if the dest cylinder is the present cylinder, unnecessary to do the seek operation\r
1376 //\r
1377 if (Info->Pcn == Cylinder) {\r
1378 return EFI_SUCCESS;\r
1379 }\r
1380 //\r
1381 // Calculate the head : 0 or 1\r
1382 //\r
1383 Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);\r
1384\r
1385 ZeroMem (&Command, sizeof (FDC_SEEK_CMD));\r
1386 Command.CommandCode = SEEK_CMD;\r
1387 if (DevPos == 0) {\r
1388 Command.DiskHeadSel = 0;\r
1389 //\r
1390 // 0\r
1391 //\r
1392 } else {\r
1393 Command.DiskHeadSel = 1;\r
1394 //\r
1395 // 1\r
1396 //\r
1397 }\r
1398\r
1399 Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2));\r
1400 Command.NewCylinder = Cylinder;\r
1401\r
1402 pt = (UINT8 *) (&Command);\r
1403 for (i = 0; i < sizeof (FDC_SEEK_CMD); i++) {\r
1404 if (DataOutByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {\r
1405 return EFI_DEVICE_ERROR;\r
1406 }\r
1407 }\r
1408\r
1409 MicroSecondDelay (50);\r
1410\r
1411 //\r
1412 // Calculate waiting time\r
1413 //\r
1414 if (Info->Pcn > Cylinder) {\r
1415 x = (UINT8) (Info->Pcn - Cylinder);\r
1416 } else {\r
1417 x = (UINT8) (Cylinder - Info->Pcn);\r
1418 }\r
1419\r
1420 MicroSecondDelay ((x + 1) * 4000);\r
1421\r
1422 if (SenseIntStatus (FdcBlkIoDev, &sts0, &pcn) != EFI_SUCCESS) {\r
1423 return EFI_DEVICE_ERROR;\r
1424 }\r
1425\r
1426 if ((sts0 & 0xf0) == 0x20) {\r
1427 Info->Pcn = Command.NewCylinder;\r
1428 Info->NeedRecalibrate = FALSE;\r
1429 return EFI_SUCCESS;\r
1430 } else {\r
1431 Info->NeedRecalibrate = TRUE;\r
1432 return EFI_DEVICE_ERROR;\r
1433 }\r
1434}\r
1435\r
1436UINTN\r
1437GetTransferBlockCount (\r
1438 IN PEI_FLOPPY_DEVICE_INFO *Info,\r
1439 IN EFI_PEI_LBA LBA,\r
1440 IN UINTN NumberOfBlocks\r
1441 )\r
1442/*++\r
1443\r
1444Routine Description:\r
1445\r
1446 GC_TODO: Add function description\r
1447\r
1448Arguments:\r
1449\r
1450 Info - GC_TODO: add argument description\r
1451 LBA - GC_TODO: add argument description\r
1452 NumberOfBlocks - GC_TODO: add argument description\r
1453\r
1454Returns:\r
1455\r
1456 GC_TODO: add return values\r
1457\r
1458--*/\r
1459{\r
1460 DISKET_PARA_TABLE *Para;\r
1461 UINT8 EndOfTrack;\r
1462 UINT8 Head;\r
1463 UINT8 SectorsInTrack;\r
1464\r
1465 Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type);\r
1466 EndOfTrack = Para->EOT;\r
1467 Head = (UINT8) ((UINTN) LBA / EndOfTrack % 2);\r
1468\r
1469 SectorsInTrack = (UINT8) (EndOfTrack * (2 - Head) - (UINT8) ((UINTN) LBA % EndOfTrack));\r
1470 if (SectorsInTrack < NumberOfBlocks) {\r
1471 return SectorsInTrack;\r
1472 } else {\r
1473 return NumberOfBlocks;\r
1474 }\r
1475}\r
1476\r
1477EFI_STATUS\r
1478ReadWriteDataSector (\r
1479 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
1480 IN OUT PEI_FLOPPY_DEVICE_INFO *Info,\r
1481 IN VOID *Buffer,\r
1482 IN EFI_PEI_LBA Lba,\r
1483 IN UINTN NumberOfBlocks,\r
1484 IN BOOLEAN Read\r
1485 )\r
1486/*++\r
1487\r
1488Routine Description:\r
1489\r
1490 GC_TODO: Add function description\r
1491\r
1492Arguments:\r
1493\r
1494 FdcBlkIoDev - GC_TODO: add argument description\r
1495 Info - GC_TODO: add argument description\r
1496 Buffer - GC_TODO: add argument description\r
1497 Lba - GC_TODO: add argument description\r
1498 NumberOfBlocks - GC_TODO: add argument description\r
1499 Read - GC_TODO: add argument description\r
1500\r
1501Returns:\r
1502\r
1503 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1504 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1505 EFI_TIMEOUT - GC_TODO: Add description for return value\r
1506 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1507\r
1508--*/\r
1509{\r
1510 EFI_STATUS Status;\r
1511 FDC_COMMAND_PACKET1 Command;\r
1512 FDC_RESULT_PACKET Result;\r
1513 UINTN i;\r
1514 UINTN Times;\r
1515 UINT8 *pt;\r
1516 //\r
1517 // UINT8 Temp;\r
1518 //\r
1519 Status = Seek (FdcBlkIoDev, Info, Lba);\r
1520 if (Status != EFI_SUCCESS) {\r
1521 return EFI_DEVICE_ERROR;\r
1522 }\r
1523 //\r
1524 // Set up DMA\r
1525 //\r
1526 SetDMA (FdcBlkIoDev, Buffer, NumberOfBlocks, Read);\r
1527\r
1528 //\r
1529 // Allocate Read or Write command packet\r
1530 //\r
1531 ZeroMem (&Command, sizeof (FDC_COMMAND_PACKET1));\r
1532 if (Read == READ) {\r
1533 Command.CommandCode = READ_DATA_CMD | CMD_MT | CMD_MFM | CMD_SK;\r
1534 }\r
1535 //\r
1536 // else\r
1537 // Command.CommandCode = WRITE_DATA_CMD | CMD_MT | CMD_MFM;\r
1538 //\r
1539 FillPara (Info, Lba, &Command);\r
1540\r
1541 //\r
1542 // Write command bytes to FDC\r
1543 //\r
1544 pt = (UINT8 *) (&Command);\r
1545 for (i = 0; i < sizeof (FDC_COMMAND_PACKET1); i++) {\r
1546 if (DataOutByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {\r
1547 return EFI_DEVICE_ERROR;\r
1548 }\r
1549 }\r
1550\r
1551 //\r
1552 // wait for some time\r
1553 //\r
1554 Times = (STALL_1_SECOND / 50) + 1;\r
1555 do {\r
1556 if ((IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_MSR)) & 0xc0) == 0xc0) {\r
1557 break;\r
1558 }\r
1559\r
1560 MicroSecondDelay (50);\r
1561 } while (--Times);\r
1562\r
1563 if (Times == 0) {\r
1564 return EFI_TIMEOUT;\r
1565 }\r
1566 //\r
1567 // Read result bytes from FDC\r
1568 //\r
1569 pt = (UINT8 *) (&Result);\r
1570 for (i = 0; i < sizeof (FDC_RESULT_PACKET); i++) {\r
1571 if (DataInByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {\r
1572 return EFI_DEVICE_ERROR;\r
1573 }\r
1574 }\r
1575\r
1576 return CheckResult (&Result, Info);\r
1577}\r
1578\r
1579EFI_STATUS\r
1580CheckResult (\r
1581 IN FDC_RESULT_PACKET *Result,\r
1582 IN OUT PEI_FLOPPY_DEVICE_INFO *Info\r
1583 )\r
1584/*++\r
1585\r
1586Routine Description:\r
1587\r
1588 GC_TODO: Add function description\r
1589\r
1590Arguments:\r
1591\r
1592 Result - GC_TODO: add argument description\r
1593 Info - GC_TODO: add argument description\r
1594\r
1595Returns:\r
1596\r
1597 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1598 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1599 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1600 EFI_SUCCESS - GC_TODO: Add description for return value\r
1601\r
1602--*/\r
1603{\r
1604 if ((Result->Status0 & STS0_IC) != IC_NT) {\r
1605 if ((Result->Status0 & STS0_SE) == 0x20) {\r
1606 //\r
1607 // seek error\r
1608 //\r
1609 Info->NeedRecalibrate = TRUE;\r
1610 }\r
1611\r
1612 Info->NeedRecalibrate = TRUE;\r
1613 return EFI_DEVICE_ERROR;\r
1614 }\r
1615 //\r
1616 // Check Status Register1\r
1617 //\r
1618 if (Result->Status1 & (STS1_EN | STS1_DE | STS1_OR | STS1_ND | STS1_NW | STS1_MA)) {\r
1619 Info->NeedRecalibrate = TRUE;\r
1620 return EFI_DEVICE_ERROR;\r
1621 }\r
1622 //\r
1623 // Check Status Register2\r
1624 //\r
1625 if (Result->Status2 & (STS2_CM | STS2_DD | STS2_WC | STS2_BC | STS2_MD)) {\r
1626 Info->NeedRecalibrate = TRUE;\r
1627 return EFI_DEVICE_ERROR;\r
1628 }\r
1629\r
1630 return EFI_SUCCESS;\r
1631}\r
1632\r
1633VOID\r
1634FillPara (\r
1635 IN PEI_FLOPPY_DEVICE_INFO *Info,\r
1636 IN EFI_PEI_LBA Lba,\r
1637 IN FDC_COMMAND_PACKET1 *Command\r
1638 )\r
1639/*++\r
1640\r
1641Routine Description:\r
1642\r
1643 GC_TODO: Add function description\r
1644\r
1645Arguments:\r
1646\r
1647 Info - GC_TODO: add argument description\r
1648 Lba - GC_TODO: add argument description\r
1649 Command - GC_TODO: add argument description\r
1650\r
1651Returns:\r
1652\r
1653 GC_TODO: add return values\r
1654\r
1655--*/\r
1656{\r
1657 DISKET_PARA_TABLE *Para;\r
1658 UINT8 EndOfTrack;\r
1659 UINT8 DevPos;\r
1660\r
1661 DevPos = Info->DevPos;\r
1662 Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type);\r
1663 EndOfTrack = Para->EOT;\r
1664\r
1665 if (DevPos == 0) {\r
1666 Command->DiskHeadSel = 0;\r
1667 } else {\r
1668 Command->DiskHeadSel = 1;\r
1669 }\r
1670\r
1671 Command->Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2);\r
1672 Command->Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);\r
1673 Command->Sector = (UINT8) ((UINT8) ((UINTN) Lba % EndOfTrack) + 1);\r
1674 Command->DiskHeadSel = (UINT8) (Command->DiskHeadSel | (Command->Head << 2));\r
1675 Command->Number = Para->Number;\r
1676 Command->EndOfTrack = Para->EOT;\r
1677 Command->GapLength = Para->GPL;\r
1678 Command->DataLength = Para->DTL;\r
1679}\r
1680\r
1681EFI_STATUS\r
1682Setup (\r
1683 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
1684 IN UINT8 DevPos\r
1685 )\r
1686/*++\r
1687\r
1688Routine Description:\r
1689\r
1690 GC_TODO: Add function description\r
1691\r
1692Arguments:\r
1693\r
1694 FdcBlkIoDev - GC_TODO: add argument description\r
1695 DevPos - GC_TODO: add argument description\r
1696\r
1697Returns:\r
1698\r
1699 EFI_SUCCESS - GC_TODO: Add description for return value\r
1700\r
1701--*/\r
1702{\r
1703 IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_CCR), 0x0);\r
1704\r
1705 MicroSecondDelay (100);\r
1706\r
1707 Specify (FdcBlkIoDev);\r
1708 return EFI_SUCCESS;\r
1709}\r
1710\r
1711EFI_STATUS\r
1712SetDMA (\r
1713 IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
1714 IN VOID *Buffer,\r
1715 IN UINTN NumberOfBlocks,\r
1716 IN BOOLEAN Read\r
1717 )\r
1718/*++\r
1719\r
1720Routine Description:\r
1721\r
1722 GC_TODO: Add function description\r
1723\r
1724Arguments:\r
1725\r
1726 FdcBlkIoDev - GC_TODO: add argument description\r
1727 Buffer - GC_TODO: add argument description\r
1728 NumberOfBlocks - GC_TODO: add argument description\r
1729 Read - GC_TODO: add argument description\r
1730\r
1731Returns:\r
1732\r
1733 EFI_SUCCESS - GC_TODO: Add description for return value\r
1734\r
1735--*/\r
1736{\r
1737 UINT8 data;\r
1738 UINTN count;\r
1739\r
1740 //\r
1741 // mask DMA channel 2;\r
1742 //\r
1743 IoWrite8 (R_8237_DMA_WRSMSK_CH0_3, B_8237_DMA_WRSMSK_CMS | 2);\r
1744\r
1745 //\r
1746 // clear first/last flip flop\r
1747 //\r
1748 IoWrite8 (R_8237_DMA_CBPR_CH0_3, B_8237_DMA_WRSMSK_CMS | 2);\r
1749\r
1750 //\r
1751 // set mode\r
1752 //\r
1753 if (Read == READ) {\r
1754 IoWrite8 (R_8237_DMA_CHMODE_CH0_3, V_8237_DMA_CHMODE_SINGLE | V_8237_DMA_CHMODE_IO2MEM | 2);\r
1755 } else {\r
1756 IoWrite8 (R_8237_DMA_CHMODE_CH0_3, V_8237_DMA_CHMODE_SINGLE | V_8237_DMA_CHMODE_MEM2IO | 2);\r
1757 }\r
1758 //\r
1759 // set base address and page register\r
1760 //\r
1761 data = (UINT8) (UINTN) Buffer;\r
1762 IoWrite8 (R_8237_DMA_BASE_CA_CH2, data);\r
1763 data = (UINT8) ((UINTN) Buffer >> 8);\r
1764 IoWrite8 (R_8237_DMA_BASE_CA_CH2, data);\r
1765\r
1766 data = (UINT8) ((UINTN) Buffer >> 16);\r
1767 IoWrite8 (R_8237_DMA_MEM_LP_CH2, data);\r
1768\r
1769 //\r
1770 // set count register\r
1771 //\r
1772 count = 512 * NumberOfBlocks - 1;\r
1773 data = (UINT8) (count & 0xff);\r
1774 IoWrite8 (R_8237_DMA_BASE_CC_CH2, data);\r
1775 data = (UINT8) (count >> 8);\r
1776 IoWrite8 (R_8237_DMA_BASE_CC_CH2, data);\r
1777\r
1778 //\r
1779 // clear channel 2 mask\r
1780 //\r
1781 IoWrite8 (R_8237_DMA_WRSMSK_CH0_3, 0x02);\r
1782\r
1783 return EFI_SUCCESS;\r
1784}\r
1785\r