878ddf1f |
1 | /*++\r |
2 | \r |
3 | Copyright (c) 2006, Intel Corporation \r |
4 | All rights reserved. This program and the accompanying materials \r |
5 | are licensed and made available under the terms and conditions of the BSD License \r |
6 | which accompanies this distribution. The full text of the license may be found at \r |
7 | http://opensource.org/licenses/bsd-license.php \r |
8 | \r |
9 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r |
10 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r |
11 | \r |
12 | Module Name:\r |
13 | \r |
14 | scsibus.c\r |
15 | \r |
16 | Abstract: \r |
17 | \r |
18 | \r |
19 | Revision History\r |
20 | --*/\r |
21 | \r |
22 | #include "scsibus.h"\r |
23 | \r |
24 | EFI_STATUS\r |
25 | EFIAPI\r |
26 | SCSIBusDriverBindingSupported (\r |
27 | IN EFI_DRIVER_BINDING_PROTOCOL *This,\r |
28 | IN EFI_HANDLE Controller,\r |
29 | IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r |
30 | );\r |
31 | \r |
32 | EFI_STATUS\r |
33 | EFIAPI\r |
34 | SCSIBusDriverBindingStart (\r |
35 | IN EFI_DRIVER_BINDING_PROTOCOL *This,\r |
36 | IN EFI_HANDLE Controller,\r |
37 | IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r |
38 | );\r |
39 | \r |
40 | EFI_STATUS\r |
41 | EFIAPI\r |
42 | SCSIBusDriverBindingStop (\r |
43 | IN EFI_DRIVER_BINDING_PROTOCOL *This,\r |
44 | IN EFI_HANDLE Controller,\r |
45 | IN UINTN NumberOfChildren,\r |
46 | IN EFI_HANDLE *ChildHandleBuffer\r |
47 | );\r |
48 | \r |
49 | EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {\r |
50 | SCSIBusDriverBindingSupported,\r |
51 | SCSIBusDriverBindingStart,\r |
52 | SCSIBusDriverBindingStop,\r |
53 | 0x10,\r |
54 | NULL,\r |
55 | NULL\r |
56 | };\r |
57 | \r |
58 | EFI_STATUS\r |
59 | EFIAPI\r |
60 | SCSIBusDriverBindingSupported (\r |
61 | IN EFI_DRIVER_BINDING_PROTOCOL *This,\r |
62 | IN EFI_HANDLE Controller,\r |
63 | IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r |
64 | )\r |
65 | /*++\r |
66 | \r |
67 | Routine Description:\r |
68 | \r |
69 | Arguments:\r |
70 | \r |
71 | Returns:\r |
72 | \r |
73 | --*/\r |
74 | // TODO: This - add argument and description to function comment\r |
75 | // TODO: Controller - add argument and description to function comment\r |
76 | // TODO: RemainingDevicePath - add argument and description to function comment\r |
77 | // TODO: EFI_UNSUPPORTED - add return value to function comment\r |
78 | // TODO: EFI_UNSUPPORTED - add return value to function comment\r |
79 | // TODO: EFI_SUCCESS - add return value to function comment\r |
80 | {\r |
81 | EFI_STATUS Status;\r |
82 | \r |
83 | //\r |
84 | // If RemainingDevicePath is not NULL, it should verify that the first device\r |
85 | // path node in RemainingDevicePath is an ATAPI Device path node.\r |
86 | //\r |
87 | if (RemainingDevicePath != NULL) {\r |
88 | if ((RemainingDevicePath->Type != MESSAGING_DEVICE_PATH) ||\r |
89 | (RemainingDevicePath->SubType != MSG_ATAPI_DP) ||\r |
90 | (DevicePathNodeLength (RemainingDevicePath) != sizeof(ATAPI_DEVICE_PATH))) {\r |
91 | return EFI_UNSUPPORTED;\r |
92 | }\r |
93 | }\r |
94 | //\r |
95 | // check for the existence of SCSI Pass Thru Protocol\r |
96 | //\r |
97 | Status = gBS->OpenProtocol (\r |
98 | Controller,\r |
99 | &gEfiScsiPassThruProtocolGuid,\r |
100 | NULL,\r |
101 | This->DriverBindingHandle,\r |
102 | Controller,\r |
103 | EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r |
104 | );\r |
105 | if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r |
106 | return EFI_UNSUPPORTED;\r |
107 | }\r |
108 | \r |
109 | return EFI_SUCCESS;\r |
110 | }\r |
111 | \r |
112 | EFI_STATUS\r |
113 | EFIAPI\r |
114 | SCSIBusDriverBindingStart (\r |
115 | IN EFI_DRIVER_BINDING_PROTOCOL *This,\r |
116 | IN EFI_HANDLE Controller,\r |
117 | IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r |
118 | )\r |
119 | /*++\r |
120 | \r |
121 | Routine Description:\r |
122 | \r |
123 | Arguments:\r |
124 | \r |
125 | Returns:\r |
126 | \r |
127 | --*/\r |
128 | // TODO: This - add argument and description to function comment\r |
129 | // TODO: Controller - add argument and description to function comment\r |
130 | // TODO: RemainingDevicePath - add argument and description to function comment\r |
131 | {\r |
132 | EFI_STATUS Status;\r |
133 | EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r |
134 | EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru;\r |
135 | UINT32 StartPun;\r |
136 | UINT64 StartLun;\r |
137 | UINT32 Pun;\r |
138 | UINT64 Lun;\r |
139 | BOOLEAN ScanOtherPuns;\r |
140 | \r |
141 | StartPun = 0;\r |
142 | StartLun = 0;\r |
143 | Status = gBS->OpenProtocol (\r |
144 | Controller,\r |
145 | &gEfiDevicePathProtocolGuid,\r |
146 | (VOID **) &ParentDevicePath,\r |
147 | This->DriverBindingHandle,\r |
148 | Controller,\r |
149 | EFI_OPEN_PROTOCOL_BY_DRIVER\r |
150 | );\r |
151 | if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r |
152 | return Status;\r |
153 | }\r |
154 | \r |
155 | //\r |
156 | // Consume SCSI Pass Thru protocol.\r |
157 | //\r |
158 | Status = gBS->OpenProtocol (\r |
159 | Controller,\r |
160 | &gEfiScsiPassThruProtocolGuid,\r |
161 | (VOID **) &ScsiPassThru,\r |
162 | This->DriverBindingHandle,\r |
163 | Controller,\r |
164 | EFI_OPEN_PROTOCOL_BY_DRIVER\r |
165 | );\r |
166 | if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r |
167 | gBS->CloseProtocol (\r |
168 | Controller,\r |
169 | &gEfiDevicePathProtocolGuid,\r |
170 | This->DriverBindingHandle,\r |
171 | Controller\r |
172 | );\r |
173 | return Status;\r |
174 | }\r |
175 | \r |
176 | if (RemainingDevicePath == NULL) {\r |
177 | StartPun = 0xFFFFFFFF;\r |
178 | StartLun = 0;\r |
179 | } else {\r |
180 | ScsiPassThru->GetTargetLun (ScsiPassThru, RemainingDevicePath, &StartPun, &StartLun);\r |
181 | }\r |
182 | \r |
183 | for (Pun = StartPun, ScanOtherPuns = TRUE; ScanOtherPuns;) {\r |
184 | \r |
185 | if (StartPun == 0xFFFFFFFF) {\r |
186 | //\r |
187 | // Remaining Device Path is NULL, scan all the possible Puns in the\r |
188 | // SCSI Channel.\r |
189 | //\r |
190 | Status = ScsiPassThru->GetNextDevice (ScsiPassThru, &Pun, &Lun);\r |
191 | if (EFI_ERROR (Status)) {\r |
192 | //\r |
193 | // no legal Pun and Lun found any more\r |
194 | //\r |
195 | break;\r |
196 | }\r |
197 | } else {\r |
198 | //\r |
199 | // Remaining Device Path is not NULL, only scan the specified Pun.\r |
200 | //\r |
201 | Pun = StartPun;\r |
202 | Lun = StartLun;\r |
203 | ScanOtherPuns = FALSE;\r |
204 | }\r |
205 | \r |
206 | //\r |
207 | // Avoid creating handle for the host adapter.\r |
208 | //\r |
209 | if (Pun == ScsiPassThru->Mode->AdapterId) {\r |
210 | continue;\r |
211 | }\r |
212 | \r |
213 | //\r |
214 | // Scan for the scsi device, if it attaches to the scsi bus,\r |
215 | // then create handle and install scsi i/o protocol.\r |
216 | //\r |
217 | Status = ScsiScanCreateDevice (This, Controller, Pun, Lun, ScsiPassThru, ParentDevicePath);\r |
218 | }\r |
219 | \r |
220 | return Status;\r |
221 | }\r |
222 | \r |
223 | EFI_STATUS\r |
224 | EFIAPI\r |
225 | SCSIBusDriverBindingStop (\r |
226 | IN EFI_DRIVER_BINDING_PROTOCOL *This,\r |
227 | IN EFI_HANDLE Controller,\r |
228 | IN UINTN NumberOfChildren,\r |
229 | IN EFI_HANDLE *ChildHandleBuffer\r |
230 | )\r |
231 | /*++\r |
232 | \r |
233 | Routine Description:\r |
234 | \r |
235 | Arguments:\r |
236 | \r |
237 | Returns:\r |
238 | \r |
239 | --*/\r |
240 | // TODO: This - add argument and description to function comment\r |
241 | // TODO: Controller - add argument and description to function comment\r |
242 | // TODO: NumberOfChildren - add argument and description to function comment\r |
243 | // TODO: ChildHandleBuffer - add argument and description to function comment\r |
244 | // TODO: EFI_SUCCESS - add return value to function comment\r |
245 | // TODO: EFI_DEVICE_ERROR - add return value to function comment\r |
246 | // TODO: EFI_SUCCESS - add return value to function comment\r |
247 | {\r |
248 | EFI_STATUS Status;\r |
249 | BOOLEAN AllChildrenStopped;\r |
250 | UINTN Index;\r |
251 | EFI_SCSI_IO_PROTOCOL *ScsiIo;\r |
252 | SCSI_IO_DEV *ScsiIoDevice;\r |
253 | EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru;\r |
254 | \r |
255 | if (NumberOfChildren == 0) {\r |
256 | //\r |
257 | // Close the bus driver\r |
258 | //\r |
259 | gBS->CloseProtocol (\r |
260 | Controller,\r |
261 | &gEfiScsiPassThruProtocolGuid,\r |
262 | This->DriverBindingHandle,\r |
263 | Controller\r |
264 | );\r |
265 | gBS->CloseProtocol (\r |
266 | Controller,\r |
267 | &gEfiDevicePathProtocolGuid,\r |
268 | This->DriverBindingHandle,\r |
269 | Controller\r |
270 | );\r |
271 | \r |
272 | return EFI_SUCCESS;\r |
273 | }\r |
274 | \r |
275 | AllChildrenStopped = TRUE;\r |
276 | \r |
277 | for (Index = 0; Index < NumberOfChildren; Index++) {\r |
278 | \r |
279 | Status = gBS->OpenProtocol (\r |
280 | ChildHandleBuffer[Index],\r |
281 | &gEfiScsiIoProtocolGuid,\r |
282 | (VOID **) &ScsiIo,\r |
283 | This->DriverBindingHandle,\r |
284 | Controller,\r |
285 | EFI_OPEN_PROTOCOL_GET_PROTOCOL\r |
286 | );\r |
287 | if (EFI_ERROR (Status)) {\r |
288 | AllChildrenStopped = FALSE;\r |
289 | continue;\r |
290 | }\r |
291 | \r |
292 | ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (ScsiIo);\r |
293 | //\r |
294 | // Close the child handle\r |
295 | //\r |
296 | Status = gBS->CloseProtocol (\r |
297 | Controller,\r |
298 | &gEfiScsiPassThruProtocolGuid,\r |
299 | This->DriverBindingHandle,\r |
300 | ChildHandleBuffer[Index]\r |
301 | );\r |
302 | \r |
303 | Status = gBS->UninstallMultipleProtocolInterfaces (\r |
304 | ChildHandleBuffer[Index],\r |
305 | &gEfiDevicePathProtocolGuid,\r |
306 | ScsiIoDevice->DevicePath,\r |
307 | &gEfiScsiIoProtocolGuid,\r |
308 | &ScsiIoDevice->ScsiIo,\r |
309 | NULL\r |
310 | );\r |
311 | if (EFI_ERROR (Status)) {\r |
312 | AllChildrenStopped = FALSE;\r |
313 | gBS->OpenProtocol (\r |
314 | Controller,\r |
315 | &gEfiScsiPassThruProtocolGuid,\r |
316 | (VOID **) &ScsiPassThru,\r |
317 | This->DriverBindingHandle,\r |
318 | ChildHandleBuffer[Index],\r |
319 | EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r |
320 | );\r |
321 | } else {\r |
322 | gBS->FreePool (ScsiIoDevice);\r |
323 | }\r |
324 | }\r |
325 | \r |
326 | if (!AllChildrenStopped) {\r |
327 | return EFI_DEVICE_ERROR;\r |
328 | }\r |
329 | \r |
330 | return EFI_SUCCESS;\r |
331 | }\r |
332 | \r |
333 | EFI_STATUS\r |
334 | EFIAPI\r |
335 | ScsiGetDeviceType (\r |
336 | IN EFI_SCSI_IO_PROTOCOL *This,\r |
337 | OUT UINT8 *DeviceType\r |
338 | )\r |
339 | /*++\r |
340 | \r |
341 | Routine Description:\r |
342 | Retrieves the device type information of the SCSI Controller.\r |
343 | \r |
344 | Arguments:\r |
345 | This - Protocol instance pointer.\r |
346 | DeviceType - A pointer to the device type information\r |
347 | retrieved from the SCSI Controller. \r |
348 | \r |
349 | Returns:\r |
350 | EFI_SUCCESS - Retrieves the device type information successfully.\r |
351 | EFI_INVALID_PARAMETER - The DeviceType is NULL.\r |
352 | --*/\r |
353 | {\r |
354 | SCSI_IO_DEV *ScsiIoDevice;\r |
355 | \r |
356 | if (DeviceType == NULL) {\r |
357 | return EFI_INVALID_PARAMETER;\r |
358 | }\r |
359 | \r |
360 | ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r |
361 | *DeviceType = ScsiIoDevice->ScsiDeviceType;\r |
362 | return EFI_SUCCESS;\r |
363 | }\r |
364 | \r |
365 | EFI_STATUS\r |
366 | EFIAPI\r |
367 | ScsiGetDeviceLocation (\r |
368 | IN EFI_SCSI_IO_PROTOCOL *This,\r |
369 | OUT UINT8 **Target,\r |
370 | OUT UINT64 *Lun\r |
371 | )\r |
372 | /*++\r |
373 | Routine Description:\r |
374 | Retrieves the device location in the SCSI channel.\r |
375 | \r |
376 | Arguments:\r |
377 | This - Protocol instance pointer.\r |
378 | Target - A pointer to the Target ID of a SCSI device \r |
379 | on the SCSI channel. \r |
380 | Lun - A pointer to the LUN of the SCSI device on \r |
381 | the SCSI channel.\r |
382 | \r |
383 | Returns:\r |
384 | EFI_SUCCESS - Retrieves the device location successfully.\r |
385 | EFI_INVALID_PARAMETER - The Target or Lun is NULL.\r |
386 | --*/\r |
387 | {\r |
388 | SCSI_IO_DEV *ScsiIoDevice;\r |
389 | \r |
390 | if (Target == NULL || Lun == NULL) {\r |
391 | return EFI_INVALID_PARAMETER;\r |
392 | }\r |
393 | \r |
394 | ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r |
395 | \r |
396 | *Target = (UINT8 *) (UINTN) ScsiIoDevice->Pun;\r |
397 | *Lun = ScsiIoDevice->Lun;\r |
398 | \r |
399 | return EFI_SUCCESS;\r |
400 | }\r |
401 | \r |
402 | EFI_STATUS\r |
403 | EFIAPI\r |
404 | ScsiResetBus (\r |
405 | IN EFI_SCSI_IO_PROTOCOL *This\r |
406 | )\r |
407 | /*++\r |
408 | \r |
409 | Routine Description:\r |
410 | Resets the SCSI Bus that the SCSI Controller is attached to.\r |
411 | \r |
412 | Arguments:\r |
413 | This - Protocol instance pointer.\r |
414 | \r |
415 | Returns:\r |
416 | EFI_SUCCESS - The SCSI bus is reset successfully.\r |
417 | EFI_DEVICE_ERROR - Errors encountered when resetting the SCSI bus.\r |
418 | EFI_UNSUPPORTED - The bus reset operation is not supported by the\r |
419 | SCSI Host Controller.\r |
420 | EFI_TIMEOUT - A timeout occurred while attempting to reset \r |
421 | the SCSI bus.\r |
422 | --*/\r |
423 | {\r |
424 | SCSI_IO_DEV *ScsiIoDevice;\r |
425 | \r |
426 | ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r |
427 | \r |
428 | return ScsiIoDevice->ScsiPassThru->ResetChannel (ScsiIoDevice->ScsiPassThru);\r |
429 | \r |
430 | }\r |
431 | \r |
432 | EFI_STATUS\r |
433 | EFIAPI\r |
434 | ScsiResetDevice (\r |
435 | IN EFI_SCSI_IO_PROTOCOL *This\r |
436 | )\r |
437 | /*++\r |
438 | \r |
439 | Routine Description:\r |
440 | Resets the SCSI Controller that the device handle specifies.\r |
441 | \r |
442 | Arguments:\r |
443 | This - Protocol instance pointer.\r |
444 | \r |
445 | \r |
446 | Returns:\r |
447 | EFI_SUCCESS - Reset the SCSI controller successfully.\r |
448 | EFI_DEVICE_ERROR - Errors are encountered when resetting the\r |
449 | SCSI Controller.\r |
450 | EFI_UNSUPPORTED - The SCSI bus does not support a device \r |
451 | reset operation.\r |
452 | EFI_TIMEOUT - A timeout occurred while attempting to \r |
453 | reset the SCSI Controller.\r |
454 | --*/\r |
455 | {\r |
456 | SCSI_IO_DEV *ScsiIoDevice;\r |
457 | \r |
458 | ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r |
459 | \r |
460 | return ScsiIoDevice->ScsiPassThru->ResetTarget (\r |
461 | ScsiIoDevice->ScsiPassThru,\r |
462 | ScsiIoDevice->Pun,\r |
463 | ScsiIoDevice->Lun\r |
464 | );\r |
465 | }\r |
466 | \r |
467 | EFI_STATUS\r |
468 | EFIAPI\r |
469 | ScsiExecuteSCSICommand (\r |
470 | IN EFI_SCSI_IO_PROTOCOL *This,\r |
471 | IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,\r |
472 | IN EFI_EVENT Event OPTIONAL\r |
473 | )\r |
474 | /*++\r |
475 | \r |
476 | Routine Description:\r |
477 | Sends a SCSI Request Packet to the SCSI Controller for execution.\r |
478 | \r |
479 | Arguments:\r |
480 | This - Protocol instance pointer.\r |
481 | Packet - The SCSI request packet to send to the SCSI \r |
482 | Controller specified by the device handle.\r |
483 | Event - If the SCSI bus where the SCSI device is attached\r |
484 | does not support non-blocking I/O, then Event is \r |
485 | ignored, and blocking I/O is performed. \r |
486 | If Event is NULL, then blocking I/O is performed.\r |
487 | If Event is not NULL and non-blocking I/O is \r |
488 | supported, then non-blocking I/O is performed,\r |
489 | and Event will be signaled when the SCSI Request\r |
490 | Packet completes.\r |
491 | Returns:\r |
492 | EFI_SUCCESS - The SCSI Request Packet was sent by the host \r |
493 | successfully, and TransferLength bytes were \r |
494 | transferred to/from DataBuffer.See \r |
495 | HostAdapterStatus, TargetStatus, \r |
496 | SenseDataLength, and SenseData in that order\r |
497 | for additional status information.\r |
498 | EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, \r |
499 | but the entire DataBuffer could not be transferred.\r |
500 | The actual number of bytes transferred is returned\r |
501 | in TransferLength. See HostAdapterStatus, \r |
502 | TargetStatus, SenseDataLength, and SenseData in \r |
503 | that order for additional status information.\r |
504 | EFI_NOT_READY - The SCSI Request Packet could not be sent because \r |
505 | there are too many SCSI Command Packets already \r |
506 | queued.The caller may retry again later.\r |
507 | EFI_DEVICE_ERROR - A device error occurred while attempting to send \r |
508 | the SCSI Request Packet. See HostAdapterStatus, \r |
509 | TargetStatus, SenseDataLength, and SenseData in \r |
510 | that order for additional status information.\r |
511 | EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. \r |
512 | The SCSI Request Packet was not sent, so no \r |
513 | additional status information is available.\r |
514 | EFI_UNSUPPORTED - The command described by the SCSI Request Packet\r |
515 | is not supported by the SCSI initiator(i.e., SCSI \r |
516 | Host Controller). The SCSI Request Packet was not\r |
517 | sent, so no additional status information is \r |
518 | available.\r |
519 | EFI_TIMEOUT - A timeout occurred while waiting for the SCSI \r |
520 | Request Packet to execute. See HostAdapterStatus,\r |
521 | TargetStatus, SenseDataLength, and SenseData in \r |
522 | that order for additional status information.\r |
523 | --*/\r |
524 | {\r |
525 | SCSI_IO_DEV *ScsiIoDevice;\r |
526 | EFI_STATUS Status;\r |
527 | \r |
528 | EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *RequestPacket;\r |
529 | \r |
530 | if (Packet == NULL) {\r |
531 | return EFI_INVALID_PARAMETER;\r |
532 | }\r |
533 | \r |
534 | ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r |
535 | \r |
536 | RequestPacket = (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *) Packet;\r |
537 | \r |
538 | Status = ScsiIoDevice->ScsiPassThru->PassThru (\r |
539 | ScsiIoDevice->ScsiPassThru,\r |
540 | ScsiIoDevice->Pun,\r |
541 | ScsiIoDevice->Lun,\r |
542 | RequestPacket,\r |
543 | Event\r |
544 | );\r |
545 | return Status;\r |
546 | }\r |
547 | \r |
548 | EFI_STATUS\r |
549 | ScsiScanCreateDevice (\r |
550 | EFI_DRIVER_BINDING_PROTOCOL *This,\r |
551 | EFI_HANDLE Controller,\r |
552 | UINT32 Pun,\r |
553 | UINT64 Lun,\r |
554 | EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru,\r |
555 | EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r |
556 | )\r |
557 | /*++\r |
558 | \r |
559 | Routine Description:\r |
560 | \r |
561 | TODO: Add function description\r |
562 | \r |
563 | Arguments:\r |
564 | \r |
565 | This - TODO: add argument description\r |
566 | Controller - TODO: add argument description\r |
567 | Pun - TODO: add argument description\r |
568 | Lun - TODO: add argument description\r |
569 | ScsiPassThru - TODO: add argument description\r |
570 | ParentDevicePath - TODO: add argument description\r |
571 | \r |
572 | Returns:\r |
573 | \r |
574 | EFI_SUCCESS - TODO: Add description for return value\r |
575 | EFI_OUT_OF_RESOURCES - TODO: Add description for return value\r |
576 | EFI_SUCCESS - TODO: Add description for return value\r |
577 | \r |
578 | --*/\r |
579 | {\r |
580 | EFI_STATUS Status;\r |
581 | SCSI_IO_DEV *ScsiIoDevice;\r |
582 | EFI_DEVICE_PATH_PROTOCOL *ScsiDevicePath;\r |
583 | \r |
584 | Status = gBS->AllocatePool (\r |
585 | EfiBootServicesData,\r |
586 | sizeof (SCSI_IO_DEV),\r |
587 | (VOID **) &ScsiIoDevice\r |
588 | );\r |
589 | if (EFI_ERROR (Status)) {\r |
590 | return Status;\r |
591 | }\r |
592 | \r |
593 | ZeroMem (ScsiIoDevice, sizeof (SCSI_IO_DEV));\r |
594 | \r |
595 | ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE;\r |
596 | ScsiIoDevice->ScsiPassThru = ScsiPassThru;\r |
597 | ScsiIoDevice->Pun = Pun;\r |
598 | ScsiIoDevice->Lun = Lun;\r |
599 | \r |
600 | ScsiIoDevice->ScsiIo.GetDeviceType = ScsiGetDeviceType;\r |
601 | ScsiIoDevice->ScsiIo.GetDeviceLocation = ScsiGetDeviceLocation;\r |
602 | ScsiIoDevice->ScsiIo.ResetBus = ScsiResetBus;\r |
603 | ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice;\r |
604 | ScsiIoDevice->ScsiIo.ExecuteSCSICommand = ScsiExecuteSCSICommand;\r |
605 | \r |
606 | if (!DiscoverScsiDevice (ScsiIoDevice)) {\r |
607 | gBS->FreePool (ScsiIoDevice);\r |
608 | return EFI_SUCCESS;\r |
609 | }\r |
610 | \r |
611 | //\r |
612 | // Set Device Path\r |
613 | //\r |
614 | Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath (\r |
615 | ScsiIoDevice->ScsiPassThru,\r |
616 | ScsiIoDevice->Pun,\r |
617 | ScsiIoDevice->Lun,\r |
618 | &ScsiDevicePath\r |
619 | );\r |
620 | if (Status == EFI_OUT_OF_RESOURCES) {\r |
621 | gBS->FreePool (ScsiIoDevice);\r |
622 | return Status;\r |
623 | }\r |
624 | \r |
625 | ScsiIoDevice->DevicePath = AppendDevicePathNode (\r |
626 | ParentDevicePath,\r |
627 | ScsiDevicePath\r |
628 | );\r |
629 | //\r |
630 | // The memory space for ScsiDevicePath is allocated in\r |
631 | // ScsiPassThru->BuildDevicePath() function; It is no longer used\r |
632 | // after EfiAppendDevicePathNode,so free the memory it occupies.\r |
633 | //\r |
634 | gBS->FreePool (ScsiDevicePath);\r |
635 | \r |
636 | if (ScsiIoDevice->DevicePath == NULL) {\r |
637 | gBS->FreePool (ScsiIoDevice);\r |
638 | return EFI_OUT_OF_RESOURCES;\r |
639 | }\r |
640 | \r |
641 | Status = gBS->InstallMultipleProtocolInterfaces (\r |
642 | &ScsiIoDevice->Handle,\r |
643 | &gEfiDevicePathProtocolGuid,\r |
644 | ScsiIoDevice->DevicePath,\r |
645 | &gEfiScsiIoProtocolGuid,\r |
646 | &ScsiIoDevice->ScsiIo,\r |
647 | NULL\r |
648 | );\r |
649 | if (EFI_ERROR (Status)) {\r |
650 | gBS->FreePool (ScsiIoDevice);\r |
651 | } else {\r |
652 | gBS->OpenProtocol (\r |
653 | Controller,\r |
654 | &gEfiScsiPassThruProtocolGuid,\r |
655 | (VOID **) &ScsiPassThru,\r |
656 | This->DriverBindingHandle,\r |
657 | ScsiIoDevice->Handle,\r |
658 | EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r |
659 | );\r |
660 | }\r |
661 | \r |
662 | return EFI_SUCCESS;\r |
663 | }\r |
664 | \r |
665 | BOOLEAN\r |
666 | DiscoverScsiDevice (\r |
667 | SCSI_IO_DEV *ScsiIoDevice\r |
668 | )\r |
669 | /*++\r |
670 | \r |
671 | Routine Description:\r |
672 | \r |
673 | TODO: Add function description\r |
674 | \r |
675 | Arguments:\r |
676 | \r |
677 | ScsiIoDevice - TODO: add argument description\r |
678 | \r |
679 | Returns:\r |
680 | \r |
681 | TODO: add return values\r |
682 | \r |
683 | --*/\r |
684 | {\r |
685 | EFI_STATUS Status;\r |
686 | EFI_SCSI_INQUIRY_DATA InquiryData;\r |
687 | UINT32 InquiryDataLength;\r |
688 | EFI_SCSI_SENSE_DATA SenseData;\r |
689 | UINT8 SenseDataLength;\r |
690 | UINT8 HostAdapterStatus;\r |
691 | UINT8 TargetStatus;\r |
692 | \r |
693 | HostAdapterStatus = 0;\r |
694 | TargetStatus = 0;\r |
695 | //\r |
696 | // Using Inquiry command to scan for the device\r |
697 | //\r |
698 | InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);\r |
699 | SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA);\r |
700 | \r |
701 | Status = SubmitInquiryCommand (\r |
702 | &ScsiIoDevice->ScsiIo,\r |
703 | EfiScsiStallSeconds (1),\r |
704 | (VOID *) &SenseData,\r |
705 | &SenseDataLength,\r |
706 | &HostAdapterStatus,\r |
707 | &TargetStatus,\r |
708 | (VOID *) &InquiryData,\r |
709 | &InquiryDataLength,\r |
710 | FALSE\r |
711 | );\r |
712 | if (EFI_ERROR (Status)) {\r |
713 | //\r |
714 | // ParseSenseData (&SenseData,SenseDataLength);\r |
715 | //\r |
716 | return FALSE;\r |
717 | }\r |
718 | //\r |
719 | // Retrieved inquiry data successfully\r |
720 | //\r |
721 | if ((InquiryData.Peripheral_Qualifier != 0) &&\r |
722 | (InquiryData.Peripheral_Qualifier != 3)) {\r |
723 | return FALSE;\r |
724 | }\r |
725 | \r |
726 | if (InquiryData.Peripheral_Qualifier == 3) {\r |
727 | if (InquiryData.Peripheral_Type != 0x1f) {\r |
728 | return FALSE;\r |
729 | }\r |
730 | }\r |
731 | \r |
732 | if ((0x1e >= InquiryData.Peripheral_Type) && (InquiryData.Peripheral_Type >= 0xa)) {\r |
733 | return FALSE;\r |
734 | }\r |
735 | \r |
736 | //\r |
737 | // valid device type and peripheral qualifier combination.\r |
738 | //\r |
739 | ScsiIoDevice->ScsiDeviceType = InquiryData.Peripheral_Type;\r |
740 | ScsiIoDevice->RemovableDevice = InquiryData.RMB;\r |
741 | if (InquiryData.Version == 0) {\r |
742 | ScsiIoDevice->ScsiVersion = 0;\r |
743 | } else {\r |
744 | //\r |
745 | // ANSI-approved version\r |
746 | //\r |
747 | ScsiIoDevice->ScsiVersion = (UINT8) (InquiryData.Version & 0x03);\r |
748 | }\r |
749 | \r |
750 | return TRUE;\r |
751 | }\r |