1 /** @file
2 
3 The definition for SD media device driver model and blkio protocol routines.
4 
5 Copyright (c) 2013-2015 Intel Corporation.
6 
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution.  The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11 
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 
15 **/
16 
17 
18 #include "SDMediaDevice.h"
19 
20 
21 EFI_DRIVER_BINDING_PROTOCOL gSDMediaDeviceDriverBinding = {
22   SDMediaDeviceSupported,
23   SDMediaDeviceStart,
24   SDMediaDeviceStop,
25   0x20,
26   NULL,
27   NULL
28 };
29 
30 /**
31   Entry point for EFI drivers.
32 
33   @param  ImageHandle      EFI_HANDLE.
34   @param  SystemTable      EFI_SYSTEM_TABLE.
35 
36   @retval EFI_SUCCESS      Driver is successfully loaded.
37   @return Others           Failed.
38 
39 **/
40 EFI_STATUS
41 EFIAPI
InitializeSDMediaDevice(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)42 InitializeSDMediaDevice (
43   IN EFI_HANDLE           ImageHandle,
44   IN EFI_SYSTEM_TABLE     *SystemTable
45   )
46 {
47   return EfiLibInstallDriverBindingComponentName2 (
48            ImageHandle,
49            SystemTable,
50            &gSDMediaDeviceDriverBinding,
51            ImageHandle,
52            &gSDMediaDeviceName,
53            &gSDMediaDeviceName2
54            );
55 }
56 
57 
58 /**
59   Test to see if this driver supports ControllerHandle. Any
60   ControllerHandle that has BlockIoProtocol installed will be supported.
61 
62   @param  This                 Protocol instance pointer.
63   @param  Controller           Handle of device to test.
64   @param  RemainingDevicePath  Not used.
65 
66   @return EFI_SUCCESS          This driver supports this device.
67   @return EFI_UNSUPPORTED      This driver does not support this device.
68 
69 **/
70 EFI_STATUS
71 EFIAPI
SDMediaDeviceSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)72 SDMediaDeviceSupported (
73   IN EFI_DRIVER_BINDING_PROTOCOL     *This,
74   IN EFI_HANDLE                      Controller,
75   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
76   )
77 {
78   EFI_STATUS                Status;
79   EFI_SD_HOST_IO_PROTOCOL   *SDHostIo;
80 
81   //
82   // Test whether there is PCI IO Protocol attached on the controller handle.
83   //
84   Status = gBS->OpenProtocol (
85                   Controller,
86                   &gEfiSDHostIoProtocolGuid,
87                   (VOID **)&SDHostIo,
88                   This->DriverBindingHandle,
89                   Controller,
90                   EFI_OPEN_PROTOCOL_BY_DRIVER
91                   );
92   if (EFI_ERROR (Status)) {
93     goto Exit;
94   }
95 
96   gBS->CloseProtocol (
97          Controller,
98          &gEfiSDHostIoProtocolGuid,
99          This->DriverBindingHandle,
100          Controller
101          );
102 
103 Exit:
104   return Status;
105 }
106 
107 /**
108   Starting the SD Media Device Driver.
109 
110   @param  This                 Protocol instance pointer.
111   @param  Controller           Handle of device to test.
112   @param  RemainingDevicePath  Not used.
113 
114   @retval EFI_SUCCESS          This driver supports this device.
115   @retval EFI_UNSUPPORTED      This driver does not support this device.
116   @retval EFI_DEVICE_ERROR     This driver cannot be started due to device Error.
117                                EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
118 
119 **/
120 EFI_STATUS
121 EFIAPI
SDMediaDeviceStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)122 SDMediaDeviceStart (
123   IN EFI_DRIVER_BINDING_PROTOCOL     *This,
124   IN EFI_HANDLE                      Controller,
125   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
126   )
127 {
128   EFI_STATUS                Status;
129   EFI_SD_HOST_IO_PROTOCOL   *SDHostIo;
130   CARD_DATA                 *CardData;
131 
132   CardData = NULL;
133 
134   //
135   // Open PCI I/O Protocol and save pointer to open protocol
136   // in private data area.
137   //
138   Status = gBS->OpenProtocol (
139                   Controller,
140                   &gEfiSDHostIoProtocolGuid,
141                   (VOID **) &SDHostIo,
142                   This->DriverBindingHandle,
143                   Controller,
144                   EFI_OPEN_PROTOCOL_BY_DRIVER
145                   );
146   if (EFI_ERROR (Status)) {
147     DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to open gEfiSDHostIoProtocolGuid \r\n"));
148     goto Exit;
149   }
150 
151   Status = SDHostIo->DetectCardAndInitHost (SDHostIo);
152   if (EFI_ERROR (Status)) {
153     DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: Fail to DetectCardAndInitHost \r\n"));
154     goto Exit;
155   }
156 
157   CardData = (CARD_DATA*)AllocateZeroPool(sizeof (CARD_DATA));
158   if (CardData == NULL) {
159     Status =  EFI_OUT_OF_RESOURCES;
160     DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to AllocateZeroPool(CARD_DATA) \r\n"));
161     goto Exit;
162   }
163 
164   ASSERT (SDHostIo->HostCapability.BoundarySize >= 4 * 1024);
165   CardData->RawBufferPointer = (UINT8*)((UINTN)DMA_MEMORY_TOP);
166   Status = gBS->AllocatePages (
167                   AllocateMaxAddress,
168                   EfiBootServicesData,
169                   EFI_SIZE_TO_PAGES (2 * SDHostIo->HostCapability.BoundarySize),
170                   (EFI_PHYSICAL_ADDRESS *)(&CardData->RawBufferPointer)
171                   );
172 
173   if (CardData->RawBufferPointer == NULL) {
174     DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to AllocateZeroPool(2*x) \r\n"));
175     Status =  EFI_OUT_OF_RESOURCES;
176     goto Exit;
177   }
178   CardData->AlignedBuffer = CardData->RawBufferPointer - ((UINTN)(CardData->RawBufferPointer) & (SDHostIo->HostCapability.BoundarySize - 1)) + SDHostIo->HostCapability.BoundarySize;
179 
180   CardData->Signature = CARD_DATA_SIGNATURE;
181   CardData->SDHostIo  = SDHostIo;
182 
183   Status = MMCSDCardInit (CardData);
184   if (EFI_ERROR (Status)) {
185     DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to MMCSDCardInit \r\n"));
186     goto Exit;
187   }
188   DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: MMCSDCardInit SuccessFul\n"));
189 
190   if (CardData->CardType == CEATACard) {
191     Status = CEATABlockIoInit (CardData);
192   } else {
193     Status = MMCSDBlockIoInit (CardData);
194   }
195 
196   if (EFI_ERROR (Status)) {
197     DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to BlockIoInit \r\n"));
198     goto Exit;
199   }
200   DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: BlockIo is successfully installed\n"));
201 
202 
203   Status = gBS->InstallProtocolInterface (
204                   &Controller,
205                   &gEfiBlockIoProtocolGuid,
206                   EFI_NATIVE_INTERFACE,
207                   &CardData->BlockIo
208                   );
209   if (EFI_ERROR (Status)) {
210     DEBUG ((EFI_D_ERROR, "SDMediaDeviceStart: Fail to install gEfiBlockIoProtocolGuid \r\n"));
211     goto Exit;
212   }
213 
214   //
215   // Install the component name protocol
216   //
217   CardData->ControllerNameTable = NULL;
218 
219   AddUnicodeString2 (
220     "eng",
221     gSDMediaDeviceName.SupportedLanguages,
222     &CardData->ControllerNameTable,
223     L"MMC/SD Media Device",
224     TRUE
225     );
226   AddUnicodeString2 (
227     "en",
228     gSDMediaDeviceName2.SupportedLanguages,
229     &CardData->ControllerNameTable,
230     L"MMC/SD Media Device",
231     FALSE
232     );
233 
234 Exit:
235   if (EFI_ERROR (Status)) {
236     DEBUG ((EFI_D_INFO, "SDMediaDeviceStart: End with failure\r\n"));
237     if (CardData != NULL) {
238       if (CardData->RawBufferPointer != NULL) {
239         gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * SDHostIo->HostCapability.BoundarySize));
240       }
241       FreePool (CardData);
242     }
243   }
244 
245   return Status;
246 }
247 
248 
249 /**
250   Stop this driver on ControllerHandle. Support stoping any child handles
251   created by this driver.
252 
253   @param  This                 Protocol instance pointer.
254   @param  Controller           Handle of device to stop driver on.
255   @param  NumberOfChildren     Number of Children in the ChildHandleBuffer.
256   @param  ChildHandleBuffer    List of handles for the children we need to stop.
257 
258   @return EFI_SUCCESS
259   @return others
260 
261 **/
262 EFI_STATUS
263 EFIAPI
SDMediaDeviceStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)264 SDMediaDeviceStop (
265   IN EFI_DRIVER_BINDING_PROTOCOL     *This,
266   IN EFI_HANDLE                      Controller,
267   IN UINTN                           NumberOfChildren,
268   IN EFI_HANDLE                      *ChildHandleBuffer
269   )
270 {
271   EFI_STATUS                Status;
272   CARD_DATA                 *CardData;
273   EFI_BLOCK_IO_PROTOCOL     *BlockIo;
274 
275   //
276   // First find BlockIo Protocol
277   //
278   Status = gBS->OpenProtocol (
279                   Controller,
280                   &gEfiBlockIoProtocolGuid,
281                   (VOID **)&BlockIo,
282                   This->DriverBindingHandle,
283                   Controller,
284                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
285                   );
286   if (EFI_ERROR (Status)) {
287     return Status;
288   }
289 
290   CardData  = CARD_DATA_FROM_THIS(BlockIo);
291 
292   //
293   // Uninstall Block I/O protocol from the device handle
294   //
295   Status = gBS->UninstallProtocolInterface (
296                   Controller,
297                   &gEfiBlockIoProtocolGuid,
298                   BlockIo
299                   );
300   if (EFI_ERROR (Status)) {
301     return Status;
302   }
303 
304   if (CardData != NULL) {
305     if (CardData->RawBufferPointer != NULL) {
306       gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) CardData->RawBufferPointer, EFI_SIZE_TO_PAGES (2 * CardData->SDHostIo->HostCapability.BoundarySize));
307     }
308     FreeUnicodeStringTable (CardData->ControllerNameTable);
309     FreePool (CardData);
310   }
311 
312   gBS->CloseProtocol (
313          Controller,
314          &gEfiSDHostIoProtocolGuid,
315          This->DriverBindingHandle,
316          Controller
317          );
318 
319   return EFI_SUCCESS;
320 }
321 
322 
323 
324