]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Pei/FloppyPeim.c
Import IsaFloppy Dxe and Pei in IntelFrameworkModulePkg.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaFloppy / Pei / FloppyPeim.c
CommitLineData
11f43dfd 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation. All rights reserved. <BR> \r
4This software and associated documentation (if any) is furnished\r
5under a license and may only be used or copied in accordance\r
6with the terms of the license. Except as permitted by such\r
7license, no part of this software or documentation may be\r
8reproduced, stored in a retrieval system, or transmitted in any\r
9form or by any means without the express written consent of\r
10Intel Corporation.\r
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