|
@@ -36,6 +36,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
36
|
36
|
#include <ipxe/uri.h>
|
37
|
37
|
#include <ipxe/acpi.h>
|
38
|
38
|
#include <ipxe/scsi.h>
|
|
39
|
+#include <ipxe/device.h>
|
|
40
|
+#include <ipxe/edd.h>
|
39
|
41
|
#include <ipxe/fc.h>
|
40
|
42
|
#include <ipxe/fcels.h>
|
41
|
43
|
#include <ipxe/fcp.h>
|
|
@@ -152,6 +154,11 @@ struct fcp_device {
|
152
|
154
|
struct interface scsi;
|
153
|
155
|
/** List of active commands */
|
154
|
156
|
struct list_head fcpcmds;
|
|
157
|
+
|
|
158
|
+ /** Fibre Channel WWN (for boot firmware table) */
|
|
159
|
+ struct fc_name wwn;
|
|
160
|
+ /** SCSI LUN (for boot firmware table) */
|
|
161
|
+ struct scsi_lun lun;
|
155
|
162
|
};
|
156
|
163
|
|
157
|
164
|
/** An FCP command */
|
|
@@ -840,9 +847,9 @@ static size_t fcpdev_window ( struct fcp_device *fcpdev ) {
|
840
|
847
|
* @v len Length of ACPI table
|
841
|
848
|
* @ret rc Return status code
|
842
|
849
|
*/
|
843
|
|
-static int fcpdev_describe ( struct fcp_device *fcpdev,
|
844
|
|
- struct acpi_description_header *acpi,
|
845
|
|
- size_t len ) {
|
|
850
|
+static int fcpdev_acpi_describe ( struct fcp_device *fcpdev,
|
|
851
|
+ struct acpi_description_header *acpi,
|
|
852
|
+ size_t len ) {
|
846
|
853
|
|
847
|
854
|
DBGC ( fcpdev, "FCP %p cannot yet describe device in an ACPI table\n",
|
848
|
855
|
fcpdev );
|
|
@@ -851,12 +858,65 @@ static int fcpdev_describe ( struct fcp_device *fcpdev,
|
851
|
858
|
return 0;
|
852
|
859
|
}
|
853
|
860
|
|
|
861
|
+/**
|
|
862
|
+ * Describe FCP device using EDD
|
|
863
|
+ *
|
|
864
|
+ * @v fcpdev FCP device
|
|
865
|
+ * @v type EDD interface type
|
|
866
|
+ * @v path EDD device path
|
|
867
|
+ * @ret rc Return status code
|
|
868
|
+ */
|
|
869
|
+static int fcpdev_edd_describe ( struct fcp_device *fcpdev,
|
|
870
|
+ struct edd_interface_type *type,
|
|
871
|
+ union edd_device_path *path ) {
|
|
872
|
+ union {
|
|
873
|
+ struct fc_name fc;
|
|
874
|
+ uint64_t u64;
|
|
875
|
+ } wwn;
|
|
876
|
+ union {
|
|
877
|
+ struct scsi_lun scsi;
|
|
878
|
+ uint64_t u64;
|
|
879
|
+ } lun;
|
|
880
|
+
|
|
881
|
+ type->type = cpu_to_le64 ( EDD_INTF_TYPE_FIBRE );
|
|
882
|
+ memcpy ( &wwn.fc, &fcpdev->wwn, sizeof ( wwn.fc ) );
|
|
883
|
+ path->fibre.wwn = be64_to_cpu ( wwn.u64 );
|
|
884
|
+ memcpy ( &lun.scsi, &fcpdev->lun, sizeof ( lun.scsi ) );
|
|
885
|
+ path->fibre.lun = be64_to_cpu ( lun.u64 );
|
|
886
|
+ return 0;
|
|
887
|
+}
|
|
888
|
+
|
|
889
|
+/**
|
|
890
|
+ * Identify device underlying FCP device
|
|
891
|
+ *
|
|
892
|
+ * @v fcpdev FCP device
|
|
893
|
+ * @ret device Underlying device
|
|
894
|
+ */
|
|
895
|
+static struct device * fcpdev_identify_device ( struct fcp_device *fcpdev ) {
|
|
896
|
+
|
|
897
|
+ /* We know the underlying device only if the link is up;
|
|
898
|
+ * otherwise we don't have a port to examine.
|
|
899
|
+ */
|
|
900
|
+ if ( ! fc_link_ok ( &fcpdev->ulp->link ) ) {
|
|
901
|
+ DBGC ( fcpdev, "FCP %p doesn't know underlying device "
|
|
902
|
+ "until link is up\n", fcpdev );
|
|
903
|
+ return NULL;
|
|
904
|
+ }
|
|
905
|
+
|
|
906
|
+ /* Hand off to port's transport interface */
|
|
907
|
+ assert ( fcpdev->ulp->peer->port != NULL );
|
|
908
|
+ return identify_device ( &fcpdev->ulp->peer->port->transport );
|
|
909
|
+}
|
|
910
|
+
|
854
|
911
|
/** FCP device SCSI interface operations */
|
855
|
912
|
static struct interface_operation fcpdev_scsi_op[] = {
|
856
|
913
|
INTF_OP ( scsi_command, struct fcp_device *, fcpdev_scsi_command ),
|
857
|
914
|
INTF_OP ( xfer_window, struct fcp_device *, fcpdev_window ),
|
858
|
915
|
INTF_OP ( intf_close, struct fcp_device *, fcpdev_close ),
|
859
|
|
- INTF_OP ( acpi_describe, struct fcp_device *, fcpdev_describe ),
|
|
916
|
+ INTF_OP ( acpi_describe, struct fcp_device *, fcpdev_acpi_describe ),
|
|
917
|
+ INTF_OP ( edd_describe, struct fcp_device *, fcpdev_edd_describe ),
|
|
918
|
+ INTF_OP ( identify_device, struct fcp_device *,
|
|
919
|
+ fcpdev_identify_device ),
|
860
|
920
|
};
|
861
|
921
|
|
862
|
922
|
/** FCP device SCSI interface descriptor */
|
|
@@ -898,6 +958,10 @@ static int fcpdev_open ( struct interface *parent, struct fc_name *wwn,
|
898
|
958
|
|
899
|
959
|
DBGC ( fcpdev, "FCP %p opened for %s\n", fcpdev, fc_ntoa ( wwn ) );
|
900
|
960
|
|
|
961
|
+ /* Preserve parameters required for boot firmware table */
|
|
962
|
+ memcpy ( &fcpdev->wwn, wwn, sizeof ( fcpdev->wwn ) );
|
|
963
|
+ memcpy ( &fcpdev->lun, lun, sizeof ( fcpdev->lun ) );
|
|
964
|
+
|
901
|
965
|
/* Attach SCSI device to parent interface */
|
902
|
966
|
if ( ( rc = scsi_open ( parent, &fcpdev->scsi, lun ) ) != 0 ) {
|
903
|
967
|
DBGC ( fcpdev, "FCP %p could not create SCSI device: %s\n",
|