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