]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBotPei/BotPeim.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBotPei / BotPeim.c
CommitLineData
4b1bf81c 1/** @file\r
2BOT Transportation implementation.\r
3\r
d1102dba
LG
4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
5\r
4b1bf81c 6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions\r
8of the BSD License which accompanies this distribution. The\r
9full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "UsbBotPeim.h"\r
18#include "BotPeim.h"\r
19#include "PeiUsbLib.h"\r
20\r
21/**\r
22 Reset the given usb device.\r
23\r
24 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
25 @param PeiBotDev The instance to PEI_BOT_DEVICE.\r
26\r
27 @retval EFI_INVALID_PARAMETER Can not get usb io ppi.\r
28 @retval EFI_SUCCESS Failed to reset the given usb device.\r
29\r
30**/\r
31EFI_STATUS\r
32BotRecoveryReset (\r
33 IN EFI_PEI_SERVICES **PeiServices,\r
34 IN PEI_BOT_DEVICE *PeiBotDev\r
35 )\r
36{\r
37 EFI_USB_DEVICE_REQUEST DevReq;\r
38 UINT32 Timeout;\r
39 PEI_USB_IO_PPI *UsbIoPpi;\r
40 UINT8 EndpointAddr;\r
41 EFI_STATUS Status;\r
42\r
43 UsbIoPpi = PeiBotDev->UsbIoPpi;\r
44\r
45 if (UsbIoPpi == NULL) {\r
46 return EFI_INVALID_PARAMETER;\r
47 }\r
48\r
49 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));\r
50\r
51 DevReq.RequestType = 0x21;\r
52 DevReq.Request = 0xFF;\r
53 DevReq.Value = 0;\r
54 DevReq.Index = 0;\r
55 DevReq.Length = 0;\r
56\r
57 Timeout = 3000;\r
58\r
59 Status = UsbIoPpi->UsbControlTransfer (\r
60 PeiServices,\r
61 UsbIoPpi,\r
62 &DevReq,\r
63 EfiUsbNoData,\r
64 Timeout,\r
65 NULL,\r
66 0\r
67 );\r
68\r
69 //\r
70 // clear bulk in endpoint stall feature\r
71 //\r
72 EndpointAddr = (PeiBotDev->BulkInEndpoint)->EndpointAddress;\r
73 PeiUsbClearEndpointHalt (PeiServices, UsbIoPpi, EndpointAddr);\r
74\r
75 //\r
76 // clear bulk out endpoint stall feature\r
77 //\r
78 EndpointAddr = (PeiBotDev->BulkOutEndpoint)->EndpointAddress;\r
79 PeiUsbClearEndpointHalt (PeiServices, UsbIoPpi, EndpointAddr);\r
80\r
81 return Status;\r
82}\r
83\r
84/**\r
85 Send the command to the device using Bulk-Out endpoint.\r
86\r
87 This function sends the command to the device using Bulk-Out endpoint.\r
88 BOT transfer is composed of three phases: Command, Data, and Status.\r
89 This is the Command phase.\r
90\r
91 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
92 @param PeiBotDev The instance to PEI_BOT_DEVICE.\r
93 @param Command The command to transfer to device.\r
94 @param CommandSize The length of the command.\r
95 @param DataTransferLength The expected length of the data.\r
96 @param Direction The direction of the data.\r
97 @param Timeout Indicates the maximum time, in millisecond, which the\r
98 transfer is allowed to complete.\r
99\r
100 @retval EFI_DEVICE_ERROR Successful to send the command to device.\r
101 @retval EFI_SUCCESS Failed to send the command to device.\r
102\r
103**/\r
104EFI_STATUS\r
105BotCommandPhase (\r
106 IN EFI_PEI_SERVICES **PeiServices,\r
107 IN PEI_BOT_DEVICE *PeiBotDev,\r
108 IN VOID *Command,\r
109 IN UINT8 CommandSize,\r
110 IN UINT32 DataTransferLength,\r
111 IN EFI_USB_DATA_DIRECTION Direction,\r
112 IN UINT16 Timeout\r
113 )\r
114{\r
115 CBW Cbw;\r
116 EFI_STATUS Status;\r
117 PEI_USB_IO_PPI *UsbIoPpi;\r
118 UINTN DataSize;\r
119\r
120 UsbIoPpi = PeiBotDev->UsbIoPpi;\r
121\r
122 ZeroMem (&Cbw, sizeof (CBW));\r
123\r
124 //\r
125 // Fill the command block, detailed see BOT spec\r
126 //\r
127 Cbw.Signature = CBWSIG;\r
128 Cbw.Tag = 0x01;\r
129 Cbw.DataTransferLength = DataTransferLength;\r
130 Cbw.Flags = (UINT8) ((Direction == EfiUsbDataIn) ? 0x80 : 0);\r
131 Cbw.Lun = 0;\r
132 Cbw.CmdLen = CommandSize;\r
133\r
134 CopyMem (Cbw.CmdBlock, Command, CommandSize);\r
135\r
136 DataSize = sizeof (CBW);\r
137\r
138 Status = UsbIoPpi->UsbBulkTransfer (\r
139 PeiServices,\r
140 UsbIoPpi,\r
141 (PeiBotDev->BulkOutEndpoint)->EndpointAddress,\r
142 (UINT8 *) &Cbw,\r
143 &DataSize,\r
144 Timeout\r
145 );\r
146 if (EFI_ERROR (Status)) {\r
147 //\r
148 // Command phase fail, we need to recovery reset this device\r
149 //\r
150 BotRecoveryReset (PeiServices, PeiBotDev);\r
151 return EFI_DEVICE_ERROR;\r
152 }\r
153\r
154 return EFI_SUCCESS;\r
155}\r
156\r
157/**\r
158 Transfer the data between the device and host.\r
159\r
160 This function transfers the data between the device and host.\r
161 BOT transfer is composed of three phases: Command, Data, and Status.\r
162 This is the Data phase.\r
163\r
164 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
165 @param PeiBotDev The instance to PEI_BOT_DEVICE.\r
166 @param DataSize The length of the data.\r
167 @param DataBuffer The pointer to the data.\r
168 @param Direction The direction of the data.\r
169 @param Timeout Indicates the maximum time, in millisecond, which the\r
170 transfer is allowed to complete.\r
171\r
172 @retval EFI_DEVICE_ERROR Successful to send the data to device.\r
173 @retval EFI_SUCCESS Failed to send the data to device.\r
174\r
175**/\r
176EFI_STATUS\r
177BotDataPhase (\r
178 IN EFI_PEI_SERVICES **PeiServices,\r
179 IN PEI_BOT_DEVICE *PeiBotDev,\r
180 IN UINT32 *DataSize,\r
181 IN OUT VOID *DataBuffer,\r
182 IN EFI_USB_DATA_DIRECTION Direction,\r
183 IN UINT16 Timeout\r
184 )\r
185{\r
186 EFI_STATUS Status;\r
187 PEI_USB_IO_PPI *UsbIoPpi;\r
188 UINT8 EndpointAddr;\r
189 UINTN Remain;\r
190 UINTN Increment;\r
191 UINT32 MaxPacketLen;\r
192 UINT8 *BufferPtr;\r
193 UINTN TransferredSize;\r
194\r
195 UsbIoPpi = PeiBotDev->UsbIoPpi;\r
196\r
197 Remain = *DataSize;\r
198 BufferPtr = (UINT8 *) DataBuffer;\r
199 TransferredSize = 0;\r
200\r
201 //\r
202 // retrieve the the max packet length of the given endpoint\r
203 //\r
204 if (Direction == EfiUsbDataIn) {\r
205 MaxPacketLen = (PeiBotDev->BulkInEndpoint)->MaxPacketSize;\r
206 EndpointAddr = (PeiBotDev->BulkInEndpoint)->EndpointAddress;\r
207 } else {\r
208 MaxPacketLen = (PeiBotDev->BulkOutEndpoint)->MaxPacketSize;\r
209 EndpointAddr = (PeiBotDev->BulkOutEndpoint)->EndpointAddress;\r
210 }\r
211\r
212 while (Remain > 0) {\r
213 //\r
214 // Using 15 packets to avoid Bitstuff error\r
215 //\r
216 if (Remain > 16 * MaxPacketLen) {\r
217 Increment = 16 * MaxPacketLen;\r
218 } else {\r
219 Increment = Remain;\r
220 }\r
221\r
222 Status = UsbIoPpi->UsbBulkTransfer (\r
223 PeiServices,\r
224 UsbIoPpi,\r
225 EndpointAddr,\r
226 BufferPtr,\r
227 &Increment,\r
228 Timeout\r
229 );\r
230\r
231 TransferredSize += Increment;\r
232\r
233 if (EFI_ERROR (Status)) {\r
234 PeiUsbClearEndpointHalt (PeiServices, UsbIoPpi, EndpointAddr);\r
235 return Status;\r
236 }\r
237\r
238 BufferPtr += Increment;\r
239 Remain -= Increment;\r
240 }\r
241\r
242 *DataSize = (UINT32) TransferredSize;\r
243\r
244 return EFI_SUCCESS;\r
245}\r
246\r
247/**\r
248 Get the command execution status from device.\r
249\r
250 This function gets the command execution status from device.\r
251 BOT transfer is composed of three phases: Command, Data, and Status.\r
252 This is the Status phase.\r
253\r
254 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
255 @param PeiBotDev The instance to PEI_BOT_DEVICE.\r
256 @param TransferStatus The status of the transaction.\r
257 @param Timeout Indicates the maximum time, in millisecond, which the\r
258 transfer is allowed to complete.\r
259\r
260 @retval EFI_DEVICE_ERROR Successful to get the status of device.\r
261 @retval EFI_SUCCESS Failed to get the status of device.\r
262\r
263**/\r
264EFI_STATUS\r
265BotStatusPhase (\r
266 IN EFI_PEI_SERVICES **PeiServices,\r
267 IN PEI_BOT_DEVICE *PeiBotDev,\r
268 OUT UINT8 *TransferStatus,\r
269 IN UINT16 Timeout\r
270 )\r
271{\r
272 CSW Csw;\r
273 EFI_STATUS Status;\r
274 PEI_USB_IO_PPI *UsbIoPpi;\r
275 UINT8 EndpointAddr;\r
276 UINTN DataSize;\r
277\r
278 UsbIoPpi = PeiBotDev->UsbIoPpi;\r
279\r
280 ZeroMem (&Csw, sizeof (CSW));\r
281\r
282 EndpointAddr = (PeiBotDev->BulkInEndpoint)->EndpointAddress;\r
283\r
284 DataSize = sizeof (CSW);\r
285\r
286 //\r
287 // Get the status field from bulk transfer\r
288 //\r
289 Status = UsbIoPpi->UsbBulkTransfer (\r
290 PeiServices,\r
291 UsbIoPpi,\r
292 EndpointAddr,\r
293 &Csw,\r
294 &DataSize,\r
295 Timeout\r
296 );\r
297 if (EFI_ERROR (Status)) {\r
298 return Status;\r
299 }\r
300\r
301 if (Csw.Signature == CSWSIG) {\r
302 *TransferStatus = Csw.Status;\r
303 } else {\r
304 return EFI_DEVICE_ERROR;\r
305 }\r
306\r
307 return EFI_SUCCESS;\r
308}\r
309\r
310/**\r
311 Send ATAPI command using BOT protocol.\r
312\r
313 @param PeiServices The pointer of EFI_PEI_SERVICES.\r
314 @param PeiBotDev The instance to PEI_BOT_DEVICE.\r
315 @param Command The command to be sent to ATAPI device.\r
316 @param CommandSize The length of the data to be sent.\r
317 @param DataBuffer The pointer to the data.\r
318 @param BufferLength The length of the data.\r
319 @param Direction The direction of the data.\r
320 @param TimeOutInMilliSeconds Indicates the maximum time, in millisecond, which the\r
321 transfer is allowed to complete.\r
322\r
323 @retval EFI_DEVICE_ERROR Successful to get the status of device.\r
324 @retval EFI_SUCCESS Failed to get the status of device.\r
325\r
326**/\r
327EFI_STATUS\r
328PeiAtapiCommand (\r
329 IN EFI_PEI_SERVICES **PeiServices,\r
330 IN PEI_BOT_DEVICE *PeiBotDev,\r
331 IN VOID *Command,\r
332 IN UINT8 CommandSize,\r
333 IN VOID *DataBuffer,\r
334 IN UINT32 BufferLength,\r
335 IN EFI_USB_DATA_DIRECTION Direction,\r
336 IN UINT16 TimeOutInMilliSeconds\r
337 )\r
338{\r
339 EFI_STATUS Status;\r
340 EFI_STATUS BotDataStatus;\r
341 UINT8 TransferStatus;\r
342 UINT32 BufferSize;\r
343\r
344 BotDataStatus = EFI_SUCCESS;\r
345 //\r
346 // First send ATAPI command through Bot\r
347 //\r
348 Status = BotCommandPhase (\r
349 PeiServices,\r
350 PeiBotDev,\r
351 Command,\r
352 CommandSize,\r
353 BufferLength,\r
354 Direction,\r
355 TimeOutInMilliSeconds\r
356 );\r
357\r
358 if (EFI_ERROR (Status)) {\r
359 return EFI_DEVICE_ERROR;\r
360 }\r
361 //\r
362 // Send/Get Data if there is a Data Stage\r
363 //\r
364 switch (Direction) {\r
365 case EfiUsbDataIn:\r
366 case EfiUsbDataOut:\r
367 BufferSize = BufferLength;\r
368\r
369 BotDataStatus = BotDataPhase (\r
370 PeiServices,\r
371 PeiBotDev,\r
372 &BufferSize,\r
373 DataBuffer,\r
374 Direction,\r
375 TimeOutInMilliSeconds\r
376 );\r
377 break;\r
378\r
379 case EfiUsbNoData:\r
380 break;\r
381 }\r
382 //\r
383 // Status Phase\r
384 //\r
385 Status = BotStatusPhase (\r
386 PeiServices,\r
387 PeiBotDev,\r
388 &TransferStatus,\r
389 TimeOutInMilliSeconds\r
390 );\r
391 if (EFI_ERROR (Status)) {\r
392 BotRecoveryReset (PeiServices, PeiBotDev);\r
393 return EFI_DEVICE_ERROR;\r
394 }\r
395\r
396 if (TransferStatus == 0x01) {\r
397 return EFI_DEVICE_ERROR;\r
398 }\r
399\r
400 return BotDataStatus;\r
401}\r