1/** @file
2
3  Copyright (c) 2004  - 2014, Intel Corporation. All rights reserved.<BR>
4
5
6  This program and the accompanying materials are licensed and made available under
7
8  the terms and conditions of the BSD License that accompanies this distribution.
9
10  The full text of the license may be found at
11
12  http://opensource.org/licenses/bsd-license.php.
13
14
15
16  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17
18  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19
20
21
22
23Module Name:
24
25
26  LegacyMetronome.c
27
28Abstract:
29
30  This contains the installation function for the driver.
31
32--*/
33
34#include "LegacyMetronome.h"
35
36//
37// Handle for the Metronome Architectural Protocol instance produced by this driver
38//
39EFI_HANDLE                  mMetronomeHandle = NULL;
40
41//
42// The Metronome Architectural Protocol instance produced by this driver
43//
44EFI_METRONOME_ARCH_PROTOCOL mMetronome = {
45  WaitForTick,
46  TICK_PERIOD
47};
48
49//
50// The CPU I/O Protocol used to access system hardware
51//
52EFI_CPU_IO_PROTOCOL         *mCpuIo = NULL;
53
54//
55// Worker Functions
56//
57
58/**
59  Write an 8 bit value to an I/O port and save it to the S3 script
60
61  @param Port  IO Port
62  @param Data  Data in IO Port
63
64  @retval None.
65
66**/
67VOID
68ScriptWriteIo8 (
69  UINT16  Port,
70  UINT8   Data
71  )
72{
73  mCpuIo->Io.Write (
74               mCpuIo,
75               EfiCpuIoWidthUint8,
76               Port,
77               1,
78               &Data
79               );
80
81}
82
83/**
84
85  Read the refresh bit from the REFRESH_PORT
86
87  @param None.
88
89  @retval Refresh bit.
90
91**/
92UINT8
93ReadRefresh (
94  VOID
95  )
96{
97  UINT8 Data;
98
99  mCpuIo->Io.Read (
100               mCpuIo,
101               EfiCpuIoWidthUint8,
102               REFRESH_PORT,
103               1,
104               &Data
105               );
106  return (UINT8) (Data & REFRESH_ON);
107}
108
109/**
110
111  Waits for the TickNumber of ticks from a known platform time source.
112
113  @param This                Pointer to the protocol instance.
114  @param TickNumber          Tick Number to be waited
115
116
117  @retval EFI_SUCCESS         If number of ticks occurred.
118  @retval EFI_NOT_FOUND       Could not locate CPU IO protocol
119
120**/
121EFI_STATUS
122EFIAPI
123WaitForTick (
124  IN EFI_METRONOME_ARCH_PROTOCOL  *This,
125  IN UINT32                       TickNumber
126  )
127{
128  //
129  // Wait for TickNumber toggles of the Refresh bit
130  //
131  for (; TickNumber != 0x00; TickNumber--) {
132    while (ReadRefresh () == REFRESH_ON)
133      ;
134    while (ReadRefresh () == REFRESH_OFF)
135      ;
136  }
137
138  return EFI_SUCCESS;
139}
140
141//
142// Driver Entry Point
143//
144/**
145  Install the LegacyMetronome driver.  Loads a Metronome Arch Protocol based
146  on the Port 61 timer.
147
148  @param ImageHandle      Handle for the image of this driver
149  @param SystemTable      Pointer to the EFI System Table
150
151  @retval EFI_SUCCESS     Metronome Architectural Protocol Installed
152
153**/
154EFI_STATUS
155EFIAPI
156InstallLegacyMetronome (
157  IN EFI_HANDLE        ImageHandle,
158  IN EFI_SYSTEM_TABLE  *SystemTable
159  )
160{
161  EFI_STATUS  Status;
162
163  //
164  // Make sure the Metronome Architectural Protocol is not already installed in the system
165  //
166  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiMetronomeArchProtocolGuid);
167
168  //
169  // Get the CPU I/O Protocol that this driver requires
170  // If the CPU I/O Protocol is not found, then ASSERT because the dependency expression
171  // should guarantee that it is present in the handle database.
172  //
173  Status = gBS->LocateProtocol (
174                  &gEfiCpuIoProtocolGuid,
175                  NULL,
176                  (void **)&mCpuIo
177                  );
178  ASSERT_EFI_ERROR (Status);
179
180  //
181  // Program port 61 timer 1 as refresh timer. We could use ACPI timer in the
182  // future.
183  //
184  ScriptWriteIo8 (TIMER1_CONTROL_PORT, LOAD_COUNTER1_LSB);
185  ScriptWriteIo8 (TIMER1_COUNT_PORT, COUNTER1_COUNT);
186
187  //
188  // Install on a new handle
189  //
190  Status = gBS->InstallMultipleProtocolInterfaces (
191                  &mMetronomeHandle,
192                  &gEfiMetronomeArchProtocolGuid,
193                  &mMetronome,
194                  NULL
195                  );
196  ASSERT_EFI_ERROR (Status);
197
198  return Status;
199}
200