]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/MptScsiDxe/MptScsi.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / MptScsiDxe / MptScsi.c
CommitLineData
feec20b2
NL
1/** @file\r
2\r
3 This driver produces Extended SCSI Pass Thru Protocol instances for\r
4 LSI Fusion MPT SCSI devices.\r
5\r
6 Copyright (C) 2020, Oracle and/or its affiliates.\r
7\r
8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9\r
10**/\r
11\r
f4707442
NL
12#include <IndustryStandard/FusionMptScsi.h>\r
13#include <IndustryStandard/Pci.h>\r
505812ae 14#include <Library/BaseLib.h>\r
093cceaf 15#include <Library/BaseMemoryLib.h>\r
a53e5b41
NL
16#include <Library/DebugLib.h>\r
17#include <Library/MemoryAllocationLib.h>\r
093cceaf 18#include <Library/PcdLib.h>\r
f4707442 19#include <Library/UefiBootServicesTableLib.h>\r
ad8f2d6b 20#include <Library/UefiLib.h>\r
f4707442 21#include <Protocol/PciIo.h>\r
505812ae 22#include <Protocol/PciRootBridgeIo.h>\r
a53e5b41 23#include <Protocol/ScsiPassThruExt.h>\r
feec20b2
NL
24#include <Uefi/UefiSpec.h>\r
25\r
ad8f2d6b
NL
26//\r
27// Higher versions will be used before lower, 0x10-0xffffffef is the version\r
28// range for IVH (Indie Hardware Vendors)\r
29//\r
ac0a286f 30#define MPT_SCSI_BINDING_VERSION 0x10\r
ad8f2d6b 31\r
a53e5b41
NL
32//\r
33// Runtime Structures\r
34//\r
35\r
505812ae 36typedef struct {\r
ac0a286f
MK
37 MPT_SCSI_REQUEST_ALIGNED IoRequest;\r
38 MPT_SCSI_IO_REPLY_ALIGNED IoReply;\r
505812ae
NL
39 //\r
40 // As EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.SenseDataLength is defined\r
41 // as UINT8, defining here SenseData size to MAX_UINT8 will guarantee it\r
42 // cannot overflow when passed to device.\r
43 //\r
ac0a286f 44 UINT8 Sense[MAX_UINT8];\r
505812ae
NL
45 //\r
46 // This size of the data is arbitrarily chosen.\r
47 // It seems to be sufficient for all I/O requests sent through\r
48 // EFI_SCSI_PASS_THRU_PROTOCOL.PassThru() for common boot scenarios.\r
49 //\r
ac0a286f 50 UINT8 Data[0x2000];\r
505812ae
NL
51} MPT_SCSI_DMA_BUFFER;\r
52\r
ac0a286f 53#define MPT_SCSI_DEV_SIGNATURE SIGNATURE_32 ('M','P','T','S')\r
a53e5b41 54typedef struct {\r
ac0a286f
MK
55 UINT32 Signature;\r
56 EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;\r
57 EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode;\r
58 UINT8 MaxTarget;\r
59 UINT32 StallPerPollUsec;\r
60 EFI_PCI_IO_PROTOCOL *PciIo;\r
61 UINT64 OriginalPciAttributes;\r
62 EFI_EVENT ExitBoot;\r
63 MPT_SCSI_DMA_BUFFER *Dma;\r
64 EFI_PHYSICAL_ADDRESS DmaPhysical;\r
65 VOID *DmaMapping;\r
66 BOOLEAN IoReplyEnqueued;\r
a53e5b41
NL
67} MPT_SCSI_DEV;\r
68\r
69#define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \\r
70 CR (PassThruPtr, MPT_SCSI_DEV, PassThru, MPT_SCSI_DEV_SIGNATURE)\r
71\r
505812ae
NL
72#define MPT_SCSI_DMA_ADDR(Dev, MemberName) \\r
73 (Dev->DmaPhysical + OFFSET_OF (MPT_SCSI_DMA_BUFFER, MemberName))\r
74\r
75#define MPT_SCSI_DMA_ADDR_HIGH(Dev, MemberName) \\r
76 ((UINT32)RShiftU64 (MPT_SCSI_DMA_ADDR (Dev, MemberName), 32))\r
77\r
78#define MPT_SCSI_DMA_ADDR_LOW(Dev, MemberName) \\r
79 ((UINT32)MPT_SCSI_DMA_ADDR (Dev, MemberName))\r
80\r
81cada98
NL
81//\r
82// Hardware functions\r
83//\r
84\r
85STATIC\r
86EFI_STATUS\r
87Out32 (\r
ac0a286f
MK
88 IN MPT_SCSI_DEV *Dev,\r
89 IN UINT32 Addr,\r
90 IN UINT32 Data\r
81cada98
NL
91 )\r
92{\r
93 return Dev->PciIo->Io.Write (\r
94 Dev->PciIo,\r
95 EfiPciIoWidthUint32,\r
96 PCI_BAR_IDX0,\r
97 Addr,\r
98 1,\r
99 &Data\r
100 );\r
101}\r
102\r
103STATIC\r
104EFI_STATUS\r
105In32 (\r
ac0a286f
MK
106 IN MPT_SCSI_DEV *Dev,\r
107 IN UINT32 Addr,\r
108 OUT UINT32 *Data\r
81cada98
NL
109 )\r
110{\r
111 return Dev->PciIo->Io.Read (\r
112 Dev->PciIo,\r
113 EfiPciIoWidthUint32,\r
114 PCI_BAR_IDX0,\r
115 Addr,\r
116 1,\r
117 Data\r
118 );\r
119}\r
120\r
121STATIC\r
122EFI_STATUS\r
123MptDoorbell (\r
ac0a286f
MK
124 IN MPT_SCSI_DEV *Dev,\r
125 IN UINT8 DoorbellFunc,\r
126 IN UINT8 DoorbellArg\r
81cada98
NL
127 )\r
128{\r
129 return Out32 (\r
130 Dev,\r
131 MPT_REG_DOORBELL,\r
132 (((UINT32)DoorbellFunc) << 24) | (DoorbellArg << 16)\r
133 );\r
134}\r
135\r
136STATIC\r
137EFI_STATUS\r
138MptScsiReset (\r
ac0a286f 139 IN MPT_SCSI_DEV *Dev\r
81cada98
NL
140 )\r
141{\r
ac0a286f 142 EFI_STATUS Status;\r
81cada98
NL
143\r
144 //\r
145 // Reset hardware\r
146 //\r
147 Status = MptDoorbell (Dev, MPT_DOORBELL_RESET, 0);\r
148 if (EFI_ERROR (Status)) {\r
149 return Status;\r
150 }\r
ac0a286f 151\r
81cada98
NL
152 //\r
153 // Mask interrupts\r
154 //\r
155 Status = Out32 (Dev, MPT_REG_IMASK, MPT_IMASK_DOORBELL | MPT_IMASK_REPLY);\r
156 if (EFI_ERROR (Status)) {\r
157 return Status;\r
158 }\r
ac0a286f 159\r
81cada98
NL
160 //\r
161 // Clear interrupt status\r
162 //\r
163 Status = Out32 (Dev, MPT_REG_ISTATUS, 0);\r
164 if (EFI_ERROR (Status)) {\r
165 return Status;\r
166 }\r
167\r
168 return EFI_SUCCESS;\r
169}\r
170\r
171STATIC\r
172EFI_STATUS\r
173MptScsiInit (\r
ac0a286f 174 IN MPT_SCSI_DEV *Dev\r
81cada98
NL
175 )\r
176{\r
ac0a286f
MK
177 EFI_STATUS Status;\r
178\r
81cada98 179 union {\r
ac0a286f
MK
180 MPT_IO_CONTROLLER_INIT_REQUEST Data;\r
181 UINT32 Uint32;\r
81cada98 182 } AlignedReq;\r
ac0a286f
MK
183 MPT_IO_CONTROLLER_INIT_REQUEST *Req;\r
184 MPT_IO_CONTROLLER_INIT_REPLY Reply;\r
185 UINT8 *ReplyBytes;\r
186 UINT32 ReplyWord;\r
81cada98
NL
187\r
188 Req = &AlignedReq.Data;\r
189\r
190 Status = MptScsiReset (Dev);\r
191 if (EFI_ERROR (Status)) {\r
192 return Status;\r
193 }\r
194\r
195 ZeroMem (Req, sizeof (*Req));\r
196 ZeroMem (&Reply, sizeof (Reply));\r
ac0a286f 197 Req->WhoInit = MPT_IOC_WHOINIT_ROM_BIOS;\r
81cada98
NL
198 Req->Function = MPT_MESSAGE_HDR_FUNCTION_IOC_INIT;\r
199 STATIC_ASSERT (\r
200 FixedPcdGet8 (PcdMptScsiMaxTargetLimit) < 255,\r
201 "Req supports 255 targets only (max target is 254)"\r
202 );\r
ac0a286f
MK
203 Req->MaxDevices = Dev->MaxTarget + 1;\r
204 Req->MaxBuses = 1;\r
205 Req->ReplyFrameSize = sizeof Dev->Dma->IoReply.Data;\r
206 Req->HostMfaHighAddr = MPT_SCSI_DMA_ADDR_HIGH (Dev, IoRequest);\r
505812ae 207 Req->SenseBufferHighAddr = MPT_SCSI_DMA_ADDR_HIGH (Dev, Sense);\r
81cada98
NL
208\r
209 //\r
210 // Send controller init through doorbell\r
211 //\r
212 STATIC_ASSERT (\r
213 sizeof (*Req) % sizeof (UINT32) == 0,\r
214 "Req must be multiple of UINT32"\r
215 );\r
216 STATIC_ASSERT (\r
217 sizeof (*Req) / sizeof (UINT32) <= MAX_UINT8,\r
218 "Req must fit in MAX_UINT8 Dwords"\r
219 );\r
220 Status = MptDoorbell (\r
221 Dev,\r
222 MPT_DOORBELL_HANDSHAKE,\r
223 (UINT8)(sizeof (*Req) / sizeof (UINT32))\r
224 );\r
225 if (EFI_ERROR (Status)) {\r
226 return Status;\r
227 }\r
ac0a286f 228\r
81cada98
NL
229 Status = Dev->PciIo->Io.Write (\r
230 Dev->PciIo,\r
231 EfiPciIoWidthFifoUint32,\r
232 PCI_BAR_IDX0,\r
233 MPT_REG_DOORBELL,\r
234 sizeof (*Req) / sizeof (UINT32),\r
235 Req\r
236 );\r
237 if (EFI_ERROR (Status)) {\r
238 return Status;\r
239 }\r
240\r
241 //\r
242 // Read reply through doorbell\r
243 // Each 32bit (Dword) read produces 16bit (Word) of data\r
244 //\r
245 // The reply is read back to complete the doorbell function but it\r
246 // isn't useful because it doesn't contain relevant data or status\r
247 // codes.\r
248 //\r
249 STATIC_ASSERT (\r
250 sizeof (Reply) % sizeof (UINT16) == 0,\r
251 "Reply must be multiple of UINT16"\r
252 );\r
253 ReplyBytes = (UINT8 *)&Reply;\r
254 while (ReplyBytes != (UINT8 *)(&Reply + 1)) {\r
255 Status = In32 (Dev, MPT_REG_DOORBELL, &ReplyWord);\r
256 if (EFI_ERROR (Status)) {\r
257 return Status;\r
258 }\r
ac0a286f 259\r
81cada98
NL
260 CopyMem (ReplyBytes, &ReplyWord, sizeof (UINT16));\r
261 ReplyBytes += sizeof (UINT16);\r
262 }\r
263\r
264 //\r
265 // Clear interrupts generated by doorbell reply\r
266 //\r
267 Status = Out32 (Dev, MPT_REG_ISTATUS, 0);\r
268 if (EFI_ERROR (Status)) {\r
269 return Status;\r
270 }\r
271\r
272 return EFI_SUCCESS;\r
273}\r
274\r
505812ae
NL
275STATIC\r
276EFI_STATUS\r
277ReportHostAdapterError (\r
ac0a286f 278 OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
505812ae
NL
279 )\r
280{\r
281 DEBUG ((DEBUG_ERROR, "%a: fatal error in scsi request\n", __FUNCTION__));\r
282 Packet->InTransferLength = 0;\r
283 Packet->OutTransferLength = 0;\r
284 Packet->SenseDataLength = 0;\r
285 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
286 Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED;\r
287 return EFI_DEVICE_ERROR;\r
288}\r
289\r
290STATIC\r
291EFI_STATUS\r
292ReportHostAdapterOverrunError (\r
ac0a286f 293 OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
505812ae
NL
294 )\r
295{\r
ac0a286f 296 Packet->SenseDataLength = 0;\r
505812ae 297 Packet->HostAdapterStatus =\r
ac0a286f 298 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;\r
505812ae
NL
299 Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;\r
300 return EFI_BAD_BUFFER_SIZE;\r
301}\r
302\r
303STATIC\r
304EFI_STATUS\r
305MptScsiPopulateRequest (\r
ac0a286f
MK
306 IN MPT_SCSI_DEV *Dev,\r
307 IN UINT8 Target,\r
308 IN UINT64 Lun,\r
309 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
505812ae
NL
310 )\r
311{\r
ac0a286f 312 MPT_SCSI_REQUEST_WITH_SG *Request;\r
505812ae
NL
313\r
314 Request = &Dev->Dma->IoRequest.Data;\r
315\r
ac0a286f
MK
316 if ((Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL) ||\r
317 ((Packet->InTransferLength > 0) && (Packet->OutTransferLength > 0)) ||\r
318 (Packet->CdbLength > sizeof (Request->Header.Cdb)))\r
319 {\r
505812ae
NL
320 return EFI_UNSUPPORTED;\r
321 }\r
322\r
ac0a286f
MK
323 if ((Target > Dev->MaxTarget) || (Lun > 0) ||\r
324 (Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL) ||\r
505812ae
NL
325 //\r
326 // Trying to receive, but destination pointer is NULL, or contradicting\r
327 // transfer direction\r
328 //\r
ac0a286f
MK
329 ((Packet->InTransferLength > 0) &&\r
330 ((Packet->InDataBuffer == NULL) ||\r
331 (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE)\r
332 )\r
333 ) ||\r
505812ae
NL
334\r
335 //\r
336 // Trying to send, but source pointer is NULL, or contradicting transfer\r
337 // direction\r
338 //\r
ac0a286f
MK
339 ((Packet->OutTransferLength > 0) &&\r
340 ((Packet->OutDataBuffer == NULL) ||\r
341 (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ)\r
342 )\r
343 )\r
344 )\r
345 {\r
505812ae
NL
346 return EFI_INVALID_PARAMETER;\r
347 }\r
348\r
349 if (Packet->InTransferLength > sizeof (Dev->Dma->Data)) {\r
350 Packet->InTransferLength = sizeof (Dev->Dma->Data);\r
351 return ReportHostAdapterOverrunError (Packet);\r
352 }\r
ac0a286f 353\r
505812ae
NL
354 if (Packet->OutTransferLength > sizeof (Dev->Dma->Data)) {\r
355 Packet->OutTransferLength = sizeof (Dev->Dma->Data);\r
356 return ReportHostAdapterOverrunError (Packet);\r
357 }\r
358\r
359 ZeroMem (Request, sizeof (*Request));\r
360 Request->Header.TargetId = Target;\r
361 //\r
362 // Only LUN 0 is currently supported, hence the cast is safe\r
363 //\r
ac0a286f
MK
364 Request->Header.Lun[1] = (UINT8)Lun;\r
365 Request->Header.Function = MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST;\r
505812ae
NL
366 Request->Header.MessageContext = 1; // We handle one request at a time\r
367\r
368 Request->Header.CdbLength = Packet->CdbLength;\r
369 CopyMem (Request->Header.Cdb, Packet->Cdb, Packet->CdbLength);\r
370\r
371 //\r
372 // SenseDataLength is UINT8, Sense[] is MAX_UINT8, so we can't overflow\r
373 //\r
374 ZeroMem (Dev->Dma->Sense, Packet->SenseDataLength);\r
ac0a286f 375 Request->Header.SenseBufferLength = Packet->SenseDataLength;\r
505812ae
NL
376 Request->Header.SenseBufferLowAddress = MPT_SCSI_DMA_ADDR_LOW (Dev, Sense);\r
377\r
ac0a286f
MK
378 Request->Sg.EndOfList = 1;\r
379 Request->Sg.EndOfBuffer = 1;\r
380 Request->Sg.LastElement = 1;\r
381 Request->Sg.ElementType = MPT_SG_ENTRY_TYPE_SIMPLE;\r
382 Request->Sg.Is64BitAddress = 1;\r
505812ae
NL
383 Request->Sg.DataBufferAddress = MPT_SCSI_DMA_ADDR (Dev, Data);\r
384\r
385 //\r
386 // "MPT_SG_ENTRY_SIMPLE.Length" is a 24-bit quantity.\r
387 //\r
388 STATIC_ASSERT (\r
389 sizeof (Dev->Dma->Data) < SIZE_16MB,\r
390 "MPT_SCSI_DMA_BUFFER.Data must be smaller than 16MB"\r
391 );\r
392\r
393 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
394 Request->Header.DataLength = Packet->InTransferLength;\r
ac0a286f
MK
395 Request->Sg.Length = Packet->InTransferLength;\r
396 Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ;\r
505812ae
NL
397 } else {\r
398 Request->Header.DataLength = Packet->OutTransferLength;\r
ac0a286f
MK
399 Request->Sg.Length = Packet->OutTransferLength;\r
400 Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE;\r
505812ae
NL
401\r
402 CopyMem (Dev->Dma->Data, Packet->OutDataBuffer, Packet->OutTransferLength);\r
403 Request->Sg.BufferContainsData = 1;\r
404 }\r
405\r
406 if (Request->Header.DataLength == 0) {\r
407 Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE;\r
408 }\r
409\r
410 return EFI_SUCCESS;\r
411}\r
412\r
413STATIC\r
414EFI_STATUS\r
415MptScsiSendRequest (\r
ac0a286f
MK
416 IN MPT_SCSI_DEV *Dev,\r
417 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
505812ae
NL
418 )\r
419{\r
ac0a286f 420 EFI_STATUS Status;\r
505812ae
NL
421\r
422 if (!Dev->IoReplyEnqueued) {\r
423 //\r
424 // Put one free reply frame on the reply queue, the hardware may use it to\r
425 // report an error to us.\r
426 //\r
427 Status = Out32 (Dev, MPT_REG_REP_Q, MPT_SCSI_DMA_ADDR_LOW (Dev, IoReply));\r
428 if (EFI_ERROR (Status)) {\r
429 return EFI_DEVICE_ERROR;\r
430 }\r
ac0a286f 431\r
505812ae
NL
432 Dev->IoReplyEnqueued = TRUE;\r
433 }\r
434\r
435 Status = Out32 (Dev, MPT_REG_REQ_Q, MPT_SCSI_DMA_ADDR_LOW (Dev, IoRequest));\r
436 if (EFI_ERROR (Status)) {\r
437 return EFI_DEVICE_ERROR;\r
438 }\r
439\r
440 return EFI_SUCCESS;\r
441}\r
442\r
443STATIC\r
444EFI_STATUS\r
445MptScsiGetReply (\r
ac0a286f
MK
446 IN MPT_SCSI_DEV *Dev,\r
447 OUT UINT32 *Reply\r
505812ae
NL
448 )\r
449{\r
ac0a286f
MK
450 EFI_STATUS Status;\r
451 UINT32 Istatus;\r
452 UINT32 EmptyReply;\r
505812ae
NL
453\r
454 //\r
455 // Timeouts are not supported for\r
456 // EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() in this implementation.\r
457 //\r
ac0a286f 458 for ( ; ;) {\r
505812ae
NL
459 Status = In32 (Dev, MPT_REG_ISTATUS, &Istatus);\r
460 if (EFI_ERROR (Status)) {\r
461 return Status;\r
462 }\r
463\r
464 //\r
465 // Interrupt raised\r
466 //\r
467 if (Istatus & MPT_IMASK_REPLY) {\r
468 break;\r
469 }\r
470\r
471 gBS->Stall (Dev->StallPerPollUsec);\r
472 }\r
473\r
474 Status = In32 (Dev, MPT_REG_REP_Q, Reply);\r
475 if (EFI_ERROR (Status)) {\r
476 return Status;\r
477 }\r
478\r
479 //\r
480 // The driver is supposed to fetch replies until 0xffffffff is returned, which\r
481 // will reset the interrupt status. We put only one request, so we expect the\r
482 // next read reply to be the last.\r
483 //\r
484 Status = In32 (Dev, MPT_REG_REP_Q, &EmptyReply);\r
ac0a286f 485 if (EFI_ERROR (Status) || (EmptyReply != MAX_UINT32)) {\r
505812ae
NL
486 return EFI_DEVICE_ERROR;\r
487 }\r
488\r
489 return EFI_SUCCESS;\r
490}\r
491\r
492STATIC\r
493EFI_STATUS\r
494MptScsiHandleReply (\r
ac0a286f
MK
495 IN MPT_SCSI_DEV *Dev,\r
496 IN UINT32 Reply,\r
497 OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
505812ae
NL
498 )\r
499{\r
500 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
501 CopyMem (Packet->InDataBuffer, Dev->Dma->Data, Packet->InTransferLength);\r
502 }\r
503\r
504 if (Reply == Dev->Dma->IoRequest.Data.Header.MessageContext) {\r
505 //\r
506 // This is a turbo reply, everything is good\r
507 //\r
ac0a286f 508 Packet->SenseDataLength = 0;\r
505812ae 509 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;\r
ac0a286f 510 Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;\r
505812ae
NL
511 } else if ((Reply & BIT31) != 0) {\r
512 DEBUG ((DEBUG_INFO, "%a: Full reply returned\n", __FUNCTION__));\r
513 //\r
514 // When reply MSB is set, we got a full reply. Since we submitted only one\r
515 // reply frame, we know it's IoReply.\r
516 //\r
517 Dev->IoReplyEnqueued = FALSE;\r
518\r
519 Packet->TargetStatus = Dev->Dma->IoReply.Data.ScsiStatus;\r
520 //\r
521 // Make sure device only lowers SenseDataLength before copying sense\r
522 //\r
523 ASSERT (Dev->Dma->IoReply.Data.SenseCount <= Packet->SenseDataLength);\r
524 Packet->SenseDataLength =\r
525 (UINT8)MIN (Dev->Dma->IoReply.Data.SenseCount, Packet->SenseDataLength);\r
526 CopyMem (Packet->SenseData, Dev->Dma->Sense, Packet->SenseDataLength);\r
527\r
528 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
529 Packet->InTransferLength = Dev->Dma->IoReply.Data.TransferCount;\r
530 } else {\r
531 Packet->OutTransferLength = Dev->Dma->IoReply.Data.TransferCount;\r
532 }\r
533\r
534 switch (Dev->Dma->IoReply.Data.IocStatus) {\r
ac0a286f
MK
535 case MPT_SCSI_IOCSTATUS_SUCCESS:\r
536 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;\r
537 break;\r
538 case MPT_SCSI_IOCSTATUS_DEVICE_NOT_THERE:\r
539 Packet->HostAdapterStatus =\r
540 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT;\r
541 return EFI_TIMEOUT;\r
542 case MPT_SCSI_IOCSTATUS_DATA_UNDERRUN:\r
543 case MPT_SCSI_IOCSTATUS_DATA_OVERRUN:\r
544 Packet->HostAdapterStatus =\r
545 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;\r
546 break;\r
547 default:\r
548 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
549 return EFI_DEVICE_ERROR;\r
505812ae 550 }\r
505812ae
NL
551 } else {\r
552 DEBUG ((DEBUG_ERROR, "%a: unexpected reply (%x)\n", __FUNCTION__, Reply));\r
553 return ReportHostAdapterError (Packet);\r
554 }\r
555\r
556 return EFI_SUCCESS;\r
557}\r
558\r
a53e5b41
NL
559//\r
560// Ext SCSI Pass Thru\r
561//\r
562\r
563STATIC\r
564EFI_STATUS\r
565EFIAPI\r
566MptScsiPassThru (\r
ac0a286f
MK
567 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
568 IN UINT8 *Target,\r
569 IN UINT64 Lun,\r
570 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,\r
571 IN EFI_EVENT Event OPTIONAL\r
a53e5b41
NL
572 )\r
573{\r
ac0a286f
MK
574 EFI_STATUS Status;\r
575 MPT_SCSI_DEV *Dev;\r
576 UINT32 Reply;\r
505812ae
NL
577\r
578 Dev = MPT_SCSI_FROM_PASS_THRU (This);\r
579 //\r
580 // We only use first byte of target identifer\r
581 //\r
582 Status = MptScsiPopulateRequest (Dev, *Target, Lun, Packet);\r
583 if (EFI_ERROR (Status)) {\r
584 //\r
585 // MptScsiPopulateRequest modified packet according to the error\r
586 //\r
587 return Status;\r
588 }\r
589\r
590 Status = MptScsiSendRequest (Dev, Packet);\r
591 if (EFI_ERROR (Status)) {\r
592 return ReportHostAdapterError (Packet);\r
593 }\r
594\r
595 Status = MptScsiGetReply (Dev, &Reply);\r
596 if (EFI_ERROR (Status)) {\r
597 return ReportHostAdapterError (Packet);\r
598 }\r
599\r
600 return MptScsiHandleReply (Dev, Reply, Packet);\r
a53e5b41
NL
601}\r
602\r
093cceaf
NL
603STATIC\r
604BOOLEAN\r
605IsTargetInitialized (\r
ac0a286f 606 IN UINT8 *Target\r
093cceaf
NL
607 )\r
608{\r
ac0a286f 609 UINTN Idx;\r
093cceaf
NL
610\r
611 for (Idx = 0; Idx < TARGET_MAX_BYTES; ++Idx) {\r
612 if (Target[Idx] != 0xFF) {\r
613 return TRUE;\r
614 }\r
615 }\r
ac0a286f 616\r
093cceaf
NL
617 return FALSE;\r
618}\r
619\r
a53e5b41
NL
620STATIC\r
621EFI_STATUS\r
622EFIAPI\r
623MptScsiGetNextTargetLun (\r
ac0a286f
MK
624 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
625 IN OUT UINT8 **Target,\r
626 IN OUT UINT64 *Lun\r
a53e5b41
NL
627 )\r
628{\r
ac0a286f 629 MPT_SCSI_DEV *Dev;\r
093cceaf
NL
630\r
631 Dev = MPT_SCSI_FROM_PASS_THRU (This);\r
632 //\r
633 // Currently support only LUN 0, so hardcode it\r
634 //\r
635 if (!IsTargetInitialized (*Target)) {\r
636 ZeroMem (*Target, TARGET_MAX_BYTES);\r
637 *Lun = 0;\r
ac0a286f 638 } else if ((**Target > Dev->MaxTarget) || (*Lun > 0)) {\r
093cceaf
NL
639 return EFI_INVALID_PARAMETER;\r
640 } else if (**Target < Dev->MaxTarget) {\r
641 //\r
642 // This device interface support 256 targets only, so it's enough to\r
643 // increment the LSB of Target, as it will never overflow.\r
644 //\r
645 **Target += 1;\r
646 } else {\r
647 return EFI_NOT_FOUND;\r
648 }\r
649\r
650 return EFI_SUCCESS;\r
a53e5b41
NL
651}\r
652\r
653STATIC\r
654EFI_STATUS\r
655EFIAPI\r
656MptScsiGetNextTarget (\r
ac0a286f
MK
657 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
658 IN OUT UINT8 **Target\r
a53e5b41
NL
659 )\r
660{\r
ac0a286f 661 MPT_SCSI_DEV *Dev;\r
093cceaf
NL
662\r
663 Dev = MPT_SCSI_FROM_PASS_THRU (This);\r
664 if (!IsTargetInitialized (*Target)) {\r
665 ZeroMem (*Target, TARGET_MAX_BYTES);\r
666 } else if (**Target > Dev->MaxTarget) {\r
667 return EFI_INVALID_PARAMETER;\r
668 } else if (**Target < Dev->MaxTarget) {\r
669 //\r
670 // This device interface support 256 targets only, so it's enough to\r
671 // increment the LSB of Target, as it will never overflow.\r
672 //\r
673 **Target += 1;\r
674 } else {\r
675 return EFI_NOT_FOUND;\r
676 }\r
677\r
678 return EFI_SUCCESS;\r
a53e5b41
NL
679}\r
680\r
681STATIC\r
682EFI_STATUS\r
683EFIAPI\r
684MptScsiBuildDevicePath (\r
ac0a286f
MK
685 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
686 IN UINT8 *Target,\r
687 IN UINT64 Lun,\r
688 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
a53e5b41
NL
689 )\r
690{\r
ac0a286f
MK
691 MPT_SCSI_DEV *Dev;\r
692 SCSI_DEVICE_PATH *ScsiDevicePath;\r
f9941d31
NL
693\r
694 if (DevicePath == NULL) {\r
695 return EFI_INVALID_PARAMETER;\r
696 }\r
697\r
698 //\r
699 // This device support 256 targets only, so it's enough to dereference\r
700 // the LSB of Target.\r
701 //\r
702 Dev = MPT_SCSI_FROM_PASS_THRU (This);\r
ac0a286f 703 if ((*Target > Dev->MaxTarget) || (Lun > 0)) {\r
f9941d31
NL
704 return EFI_NOT_FOUND;\r
705 }\r
706\r
707 ScsiDevicePath = AllocateZeroPool (sizeof (*ScsiDevicePath));\r
708 if (ScsiDevicePath == NULL) {\r
709 return EFI_OUT_OF_RESOURCES;\r
710 }\r
711\r
712 ScsiDevicePath->Header.Type = MESSAGING_DEVICE_PATH;\r
713 ScsiDevicePath->Header.SubType = MSG_SCSI_DP;\r
714 ScsiDevicePath->Header.Length[0] = (UINT8)sizeof (*ScsiDevicePath);\r
715 ScsiDevicePath->Header.Length[1] = (UINT8)(sizeof (*ScsiDevicePath) >> 8);\r
716 ScsiDevicePath->Pun = *Target;\r
717 ScsiDevicePath->Lun = (UINT16)Lun;\r
718\r
719 *DevicePath = &ScsiDevicePath->Header;\r
720 return EFI_SUCCESS;\r
a53e5b41
NL
721}\r
722\r
723STATIC\r
724EFI_STATUS\r
725EFIAPI\r
726MptScsiGetTargetLun (\r
ac0a286f
MK
727 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
728 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
729 OUT UINT8 **Target,\r
730 OUT UINT64 *Lun\r
a53e5b41
NL
731 )\r
732{\r
ac0a286f
MK
733 MPT_SCSI_DEV *Dev;\r
734 SCSI_DEVICE_PATH *ScsiDevicePath;\r
f9941d31 735\r
ac0a286f
MK
736 if ((DevicePath == NULL) ||\r
737 (Target == NULL) || (*Target == NULL) || (Lun == NULL))\r
738 {\r
f9941d31
NL
739 return EFI_INVALID_PARAMETER;\r
740 }\r
741\r
ac0a286f
MK
742 if ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||\r
743 (DevicePath->SubType != MSG_SCSI_DP))\r
744 {\r
f9941d31
NL
745 return EFI_UNSUPPORTED;\r
746 }\r
747\r
ac0a286f 748 Dev = MPT_SCSI_FROM_PASS_THRU (This);\r
f9941d31 749 ScsiDevicePath = (SCSI_DEVICE_PATH *)DevicePath;\r
ac0a286f
MK
750 if ((ScsiDevicePath->Pun > Dev->MaxTarget) ||\r
751 (ScsiDevicePath->Lun > 0))\r
752 {\r
f9941d31
NL
753 return EFI_NOT_FOUND;\r
754 }\r
755\r
756 ZeroMem (*Target, TARGET_MAX_BYTES);\r
757 //\r
758 // This device support 256 targets only, so it's enough to set the LSB\r
759 // of Target.\r
760 //\r
761 **Target = (UINT8)ScsiDevicePath->Pun;\r
ac0a286f 762 *Lun = ScsiDevicePath->Lun;\r
f9941d31
NL
763\r
764 return EFI_SUCCESS;\r
a53e5b41
NL
765}\r
766\r
767STATIC\r
768EFI_STATUS\r
769EFIAPI\r
770MptScsiResetChannel (\r
ac0a286f 771 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This\r
a53e5b41
NL
772 )\r
773{\r
774 return EFI_UNSUPPORTED;\r
775}\r
776\r
c635a563
NL
777STATIC\r
778VOID\r
779EFIAPI\r
780MptScsiExitBoot (\r
ac0a286f
MK
781 IN EFI_EVENT Event,\r
782 IN VOID *Context\r
c635a563
NL
783 )\r
784{\r
ac0a286f 785 MPT_SCSI_DEV *Dev;\r
c635a563
NL
786\r
787 Dev = Context;\r
788 DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));\r
789 MptScsiReset (Dev);\r
790}\r
ac0a286f 791\r
a53e5b41
NL
792STATIC\r
793EFI_STATUS\r
794EFIAPI\r
795MptScsiResetTargetLun (\r
ac0a286f
MK
796 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
797 IN UINT8 *Target,\r
798 IN UINT64 Lun\r
a53e5b41
NL
799 )\r
800{\r
801 return EFI_UNSUPPORTED;\r
802}\r
803\r
ad8f2d6b
NL
804//\r
805// Driver Binding\r
806//\r
807\r
808STATIC\r
809EFI_STATUS\r
810EFIAPI\r
811MptScsiControllerSupported (\r
ac0a286f
MK
812 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
813 IN EFI_HANDLE ControllerHandle,\r
814 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
ad8f2d6b
NL
815 )\r
816{\r
ac0a286f
MK
817 EFI_STATUS Status;\r
818 EFI_PCI_IO_PROTOCOL *PciIo;\r
819 PCI_TYPE00 Pci;\r
f4707442
NL
820\r
821 Status = gBS->OpenProtocol (\r
822 ControllerHandle,\r
823 &gEfiPciIoProtocolGuid,\r
824 (VOID **)&PciIo,\r
825 This->DriverBindingHandle,\r
826 ControllerHandle,\r
827 EFI_OPEN_PROTOCOL_BY_DRIVER\r
828 );\r
829 if (EFI_ERROR (Status)) {\r
830 return Status;\r
831 }\r
832\r
833 Status = PciIo->Pci.Read (\r
834 PciIo,\r
835 EfiPciIoWidthUint32,\r
836 0,\r
837 sizeof (Pci) / sizeof (UINT32),\r
838 &Pci\r
839 );\r
840 if (EFI_ERROR (Status)) {\r
841 goto Done;\r
842 }\r
843\r
ac0a286f
MK
844 if ((Pci.Hdr.VendorId == LSI_LOGIC_PCI_VENDOR_ID) &&\r
845 ((Pci.Hdr.DeviceId == LSI_53C1030_PCI_DEVICE_ID) ||\r
846 (Pci.Hdr.DeviceId == LSI_SAS1068_PCI_DEVICE_ID) ||\r
847 (Pci.Hdr.DeviceId == LSI_SAS1068E_PCI_DEVICE_ID)))\r
848 {\r
f4707442
NL
849 Status = EFI_SUCCESS;\r
850 } else {\r
851 Status = EFI_UNSUPPORTED;\r
852 }\r
853\r
854Done:\r
855 gBS->CloseProtocol (\r
856 ControllerHandle,\r
857 &gEfiPciIoProtocolGuid,\r
858 This->DriverBindingHandle,\r
859 ControllerHandle\r
860 );\r
861 return Status;\r
ad8f2d6b
NL
862}\r
863\r
864STATIC\r
865EFI_STATUS\r
866EFIAPI\r
867MptScsiControllerStart (\r
ac0a286f
MK
868 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
869 IN EFI_HANDLE ControllerHandle,\r
870 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
ad8f2d6b
NL
871 )\r
872{\r
ac0a286f
MK
873 EFI_STATUS Status;\r
874 MPT_SCSI_DEV *Dev;\r
875 UINTN Pages;\r
876 UINTN BytesMapped;\r
a53e5b41
NL
877\r
878 Dev = AllocateZeroPool (sizeof (*Dev));\r
879 if (Dev == NULL) {\r
880 return EFI_OUT_OF_RESOURCES;\r
881 }\r
882\r
883 Dev->Signature = MPT_SCSI_DEV_SIGNATURE;\r
884\r
ac0a286f 885 Dev->MaxTarget = PcdGet8 (PcdMptScsiMaxTargetLimit);\r
505812ae 886 Dev->StallPerPollUsec = PcdGet32 (PcdMptScsiStallPerPollUsec);\r
093cceaf 887\r
da8c0b8f
NL
888 Status = gBS->OpenProtocol (\r
889 ControllerHandle,\r
890 &gEfiPciIoProtocolGuid,\r
891 (VOID **)&Dev->PciIo,\r
892 This->DriverBindingHandle,\r
893 ControllerHandle,\r
894 EFI_OPEN_PROTOCOL_BY_DRIVER\r
895 );\r
896 if (EFI_ERROR (Status)) {\r
897 goto FreePool;\r
898 }\r
899\r
ecdbdba6
NL
900 Status = Dev->PciIo->Attributes (\r
901 Dev->PciIo,\r
902 EfiPciIoAttributeOperationGet,\r
903 0,\r
904 &Dev->OriginalPciAttributes\r
905 );\r
906 if (EFI_ERROR (Status)) {\r
907 goto CloseProtocol;\r
908 }\r
909\r
910 //\r
911 // Enable I/O Space & Bus-Mastering\r
912 //\r
913 Status = Dev->PciIo->Attributes (\r
914 Dev->PciIo,\r
915 EfiPciIoAttributeOperationEnable,\r
916 (EFI_PCI_IO_ATTRIBUTE_IO |\r
917 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),\r
918 NULL\r
919 );\r
920 if (EFI_ERROR (Status)) {\r
921 goto CloseProtocol;\r
922 }\r
923\r
924 //\r
925 // Signal device supports 64-bit DMA addresses\r
926 //\r
927 Status = Dev->PciIo->Attributes (\r
928 Dev->PciIo,\r
929 EfiPciIoAttributeOperationEnable,\r
930 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,\r
931 NULL\r
932 );\r
933 if (EFI_ERROR (Status)) {\r
934 //\r
935 // Warn user that device will only be using 32-bit DMA addresses.\r
936 //\r
937 // Note that this does not prevent the device/driver from working\r
938 // and therefore we only warn and continue as usual.\r
939 //\r
940 DEBUG ((\r
941 DEBUG_WARN,\r
942 "%a: failed to enable 64-bit DMA addresses\n",\r
943 __FUNCTION__\r
944 ));\r
945 }\r
946\r
505812ae
NL
947 //\r
948 // Create buffers for data transfer\r
949 //\r
ac0a286f 950 Pages = EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma));\r
505812ae
NL
951 Status = Dev->PciIo->AllocateBuffer (\r
952 Dev->PciIo,\r
953 AllocateAnyPages,\r
954 EfiBootServicesData,\r
955 Pages,\r
956 (VOID **)&Dev->Dma,\r
957 EFI_PCI_ATTRIBUTE_MEMORY_CACHED\r
958 );\r
81cada98
NL
959 if (EFI_ERROR (Status)) {\r
960 goto RestoreAttributes;\r
961 }\r
962\r
505812ae 963 BytesMapped = EFI_PAGES_TO_SIZE (Pages);\r
ac0a286f
MK
964 Status = Dev->PciIo->Map (\r
965 Dev->PciIo,\r
966 EfiPciIoOperationBusMasterCommonBuffer,\r
967 Dev->Dma,\r
968 &BytesMapped,\r
969 &Dev->DmaPhysical,\r
970 &Dev->DmaMapping\r
971 );\r
505812ae
NL
972 if (EFI_ERROR (Status)) {\r
973 goto FreeBuffer;\r
974 }\r
975\r
976 if (BytesMapped != EFI_PAGES_TO_SIZE (Pages)) {\r
977 Status = EFI_OUT_OF_RESOURCES;\r
978 goto Unmap;\r
979 }\r
980\r
981 Status = MptScsiInit (Dev);\r
982 if (EFI_ERROR (Status)) {\r
983 goto Unmap;\r
984 }\r
985\r
c635a563
NL
986 Status = gBS->CreateEvent (\r
987 EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
988 TPL_CALLBACK,\r
989 &MptScsiExitBoot,\r
990 Dev,\r
991 &Dev->ExitBoot\r
992 );\r
993 if (EFI_ERROR (Status)) {\r
994 goto UninitDev;\r
995 }\r
996\r
a53e5b41
NL
997 //\r
998 // Host adapter channel, doesn't exist\r
999 //\r
ac0a286f 1000 Dev->PassThruMode.AdapterId = MAX_UINT32;\r
a53e5b41
NL
1001 Dev->PassThruMode.Attributes =\r
1002 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |\r
1003 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;\r
1004\r
ac0a286f
MK
1005 Dev->PassThru.Mode = &Dev->PassThruMode;\r
1006 Dev->PassThru.PassThru = &MptScsiPassThru;\r
a53e5b41 1007 Dev->PassThru.GetNextTargetLun = &MptScsiGetNextTargetLun;\r
ac0a286f
MK
1008 Dev->PassThru.BuildDevicePath = &MptScsiBuildDevicePath;\r
1009 Dev->PassThru.GetTargetLun = &MptScsiGetTargetLun;\r
1010 Dev->PassThru.ResetChannel = &MptScsiResetChannel;\r
1011 Dev->PassThru.ResetTargetLun = &MptScsiResetTargetLun;\r
1012 Dev->PassThru.GetNextTarget = &MptScsiGetNextTarget;\r
a53e5b41
NL
1013\r
1014 Status = gBS->InstallProtocolInterface (\r
1015 &ControllerHandle,\r
1016 &gEfiExtScsiPassThruProtocolGuid,\r
1017 EFI_NATIVE_INTERFACE,\r
1018 &Dev->PassThru\r
1019 );\r
1020 if (EFI_ERROR (Status)) {\r
c635a563 1021 goto CloseExitBoot;\r
a53e5b41
NL
1022 }\r
1023\r
1024 return EFI_SUCCESS;\r
1025\r
c635a563
NL
1026CloseExitBoot:\r
1027 gBS->CloseEvent (Dev->ExitBoot);\r
1028\r
81cada98
NL
1029UninitDev:\r
1030 MptScsiReset (Dev);\r
1031\r
505812ae
NL
1032Unmap:\r
1033 Dev->PciIo->Unmap (\r
1034 Dev->PciIo,\r
1035 Dev->DmaMapping\r
1036 );\r
1037\r
1038FreeBuffer:\r
1039 Dev->PciIo->FreeBuffer (\r
1040 Dev->PciIo,\r
1041 Pages,\r
1042 Dev->Dma\r
1043 );\r
1044\r
ecdbdba6
NL
1045RestoreAttributes:\r
1046 Dev->PciIo->Attributes (\r
1047 Dev->PciIo,\r
1048 EfiPciIoAttributeOperationSet,\r
1049 Dev->OriginalPciAttributes,\r
1050 NULL\r
1051 );\r
1052\r
da8c0b8f
NL
1053CloseProtocol:\r
1054 gBS->CloseProtocol (\r
1055 ControllerHandle,\r
1056 &gEfiPciIoProtocolGuid,\r
1057 This->DriverBindingHandle,\r
1058 ControllerHandle\r
1059 );\r
1060\r
a53e5b41
NL
1061FreePool:\r
1062 FreePool (Dev);\r
1063\r
1064 return Status;\r
ad8f2d6b
NL
1065}\r
1066\r
1067STATIC\r
1068EFI_STATUS\r
1069EFIAPI\r
1070MptScsiControllerStop (\r
ac0a286f
MK
1071 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1072 IN EFI_HANDLE ControllerHandle,\r
1073 IN UINTN NumberOfChildren,\r
1074 IN EFI_HANDLE *ChildHandleBuffer\r
ad8f2d6b
NL
1075 )\r
1076{\r
ac0a286f
MK
1077 EFI_STATUS Status;\r
1078 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
1079 MPT_SCSI_DEV *Dev;\r
a53e5b41
NL
1080\r
1081 Status = gBS->OpenProtocol (\r
1082 ControllerHandle,\r
1083 &gEfiExtScsiPassThruProtocolGuid,\r
1084 (VOID **)&PassThru,\r
1085 This->DriverBindingHandle,\r
1086 ControllerHandle,\r
1087 EFI_OPEN_PROTOCOL_GET_PROTOCOL // Lookup only\r
1088 );\r
1089 if (EFI_ERROR (Status)) {\r
1090 return Status;\r
1091 }\r
1092\r
1093 Dev = MPT_SCSI_FROM_PASS_THRU (PassThru);\r
1094\r
1095 Status = gBS->UninstallProtocolInterface (\r
1096 ControllerHandle,\r
1097 &gEfiExtScsiPassThruProtocolGuid,\r
1098 &Dev->PassThru\r
1099 );\r
1100 if (EFI_ERROR (Status)) {\r
1101 return Status;\r
1102 }\r
1103\r
c635a563
NL
1104 gBS->CloseEvent (Dev->ExitBoot);\r
1105\r
81cada98
NL
1106 MptScsiReset (Dev);\r
1107\r
505812ae
NL
1108 Dev->PciIo->Unmap (\r
1109 Dev->PciIo,\r
1110 Dev->DmaMapping\r
1111 );\r
1112\r
1113 Dev->PciIo->FreeBuffer (\r
1114 Dev->PciIo,\r
1115 EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma)),\r
1116 Dev->Dma\r
1117 );\r
1118\r
ecdbdba6
NL
1119 Dev->PciIo->Attributes (\r
1120 Dev->PciIo,\r
1121 EfiPciIoAttributeOperationSet,\r
1122 Dev->OriginalPciAttributes,\r
1123 NULL\r
1124 );\r
1125\r
da8c0b8f
NL
1126 gBS->CloseProtocol (\r
1127 ControllerHandle,\r
1128 &gEfiPciIoProtocolGuid,\r
1129 This->DriverBindingHandle,\r
1130 ControllerHandle\r
1131 );\r
1132\r
a53e5b41
NL
1133 FreePool (Dev);\r
1134\r
1135 return Status;\r
ad8f2d6b
NL
1136}\r
1137\r
1138STATIC\r
ac0a286f 1139EFI_DRIVER_BINDING_PROTOCOL mMptScsiDriverBinding = {\r
ad8f2d6b
NL
1140 &MptScsiControllerSupported,\r
1141 &MptScsiControllerStart,\r
1142 &MptScsiControllerStop,\r
1143 MPT_SCSI_BINDING_VERSION,\r
1144 NULL, // ImageHandle, filled by EfiLibInstallDriverBindingComponentName2\r
1145 NULL, // DriverBindingHandle, filled as well\r
1146};\r
1147\r
be7fcaa1
NL
1148//\r
1149// Component Name\r
1150//\r
1151\r
1152STATIC\r
ac0a286f 1153EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
be7fcaa1 1154 { "eng;en", L"LSI Fusion MPT SCSI Driver" },\r
ac0a286f 1155 { NULL, NULL }\r
be7fcaa1
NL
1156};\r
1157\r
1158STATIC\r
ac0a286f 1159EFI_COMPONENT_NAME_PROTOCOL mComponentName;\r
be7fcaa1
NL
1160\r
1161EFI_STATUS\r
1162EFIAPI\r
1163MptScsiGetDriverName (\r
ac0a286f
MK
1164 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
1165 IN CHAR8 *Language,\r
1166 OUT CHAR16 **DriverName\r
be7fcaa1
NL
1167 )\r
1168{\r
1169 return LookupUnicodeString2 (\r
1170 Language,\r
1171 This->SupportedLanguages,\r
1172 mDriverNameTable,\r
1173 DriverName,\r
1174 (BOOLEAN)(This == &mComponentName) // Iso639Language\r
1175 );\r
1176}\r
1177\r
1178EFI_STATUS\r
1179EFIAPI\r
1180MptScsiGetDeviceName (\r
ac0a286f
MK
1181 IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
1182 IN EFI_HANDLE DeviceHandle,\r
1183 IN EFI_HANDLE ChildHandle,\r
1184 IN CHAR8 *Language,\r
1185 OUT CHAR16 **ControllerName\r
be7fcaa1
NL
1186 )\r
1187{\r
1188 return EFI_UNSUPPORTED;\r
1189}\r
1190\r
1191STATIC\r
ac0a286f 1192EFI_COMPONENT_NAME_PROTOCOL mComponentName = {\r
be7fcaa1
NL
1193 &MptScsiGetDriverName,\r
1194 &MptScsiGetDeviceName,\r
1195 "eng" // SupportedLanguages, ISO 639-2 language codes\r
1196};\r
1197\r
1198STATIC\r
ac0a286f
MK
1199EFI_COMPONENT_NAME2_PROTOCOL mComponentName2 = {\r
1200 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&MptScsiGetDriverName,\r
1201 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&MptScsiGetDeviceName,\r
be7fcaa1
NL
1202 "en" // SupportedLanguages, RFC 4646 language codes\r
1203};\r
1204\r
feec20b2
NL
1205//\r
1206// Entry Point\r
1207//\r
1208\r
1209EFI_STATUS\r
1210EFIAPI\r
1211MptScsiEntryPoint (\r
ac0a286f
MK
1212 IN EFI_HANDLE ImageHandle,\r
1213 IN EFI_SYSTEM_TABLE *SystemTable\r
feec20b2
NL
1214 )\r
1215{\r
ad8f2d6b
NL
1216 return EfiLibInstallDriverBindingComponentName2 (\r
1217 ImageHandle,\r
1218 SystemTable,\r
1219 &mMptScsiDriverBinding,\r
1220 ImageHandle, // The handle to install onto\r
be7fcaa1
NL
1221 &mComponentName,\r
1222 &mComponentName2\r
ad8f2d6b 1223 );\r
feec20b2 1224}\r