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