diff options
author | Dhananjay Phadke <dhananjay@netxen.com> | 2009-02-24 19:38:22 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-24 19:38:22 -0500 |
commit | ba599d4f0d2071abc049cb6345eab510a8a3643e (patch) | |
tree | e42bac74b45238e373d8d4b4de779ce83c1fd833 /drivers/net/netxen/netxen_nic_hw.c | |
parent | 32344a394029baeca5bcc9fa839694b23a82cc64 (diff) |
netxen: firmware download support
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_hw.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 175 |
1 files changed, 164 insertions, 11 deletions
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index b2f67b98c93..aef39e7a5e2 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include "netxen_nic_hw.h" | 35 | #include "netxen_nic_hw.h" |
36 | #include "netxen_nic_phan_reg.h" | 36 | #include "netxen_nic_phan_reg.h" |
37 | 37 | ||
38 | 38 | #include <linux/firmware.h> | |
39 | #include <net/ip.h> | 39 | #include <net/ip.h> |
40 | 40 | ||
41 | #define MASK(n) ((1ULL<<(n))-1) | 41 | #define MASK(n) ((1ULL<<(n))-1) |
@@ -951,24 +951,69 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off) | |||
951 | (ulong)adapter->ahw.pci_base0; | 951 | (ulong)adapter->ahw.pci_base0; |
952 | } | 952 | } |
953 | 953 | ||
954 | int netxen_load_firmware(struct netxen_adapter *adapter) | 954 | static int |
955 | netxen_do_load_firmware(struct netxen_adapter *adapter, const char *fwname, | ||
956 | const struct firmware *fw) | ||
955 | { | 957 | { |
956 | int i; | 958 | u64 *ptr64; |
957 | u32 data, size = 0; | 959 | u32 i, flashaddr, size; |
958 | u32 flashaddr = NETXEN_BOOTLD_START; | 960 | struct pci_dev *pdev = adapter->pdev; |
959 | 961 | ||
960 | size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START)/4; | 962 | if (fw) |
963 | dev_info(&pdev->dev, "loading firmware from file %s\n", fwname); | ||
964 | else | ||
965 | dev_info(&pdev->dev, "loading firmware from flash\n"); | ||
961 | 966 | ||
962 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | 967 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) |
963 | adapter->pci_write_normalize(adapter, | 968 | adapter->pci_write_normalize(adapter, |
964 | NETXEN_ROMUSB_GLB_CAS_RST, 1); | 969 | NETXEN_ROMUSB_GLB_CAS_RST, 1); |
965 | 970 | ||
966 | for (i = 0; i < size; i++) { | 971 | if (fw) { |
967 | if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) | 972 | __le64 data; |
968 | return -EIO; | 973 | |
974 | size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8; | ||
975 | |||
976 | ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START]; | ||
977 | flashaddr = NETXEN_BOOTLD_START; | ||
978 | |||
979 | for (i = 0; i < size; i++) { | ||
980 | data = cpu_to_le64(ptr64[i]); | ||
981 | adapter->pci_mem_write(adapter, flashaddr, &data, 8); | ||
982 | flashaddr += 8; | ||
983 | } | ||
984 | |||
985 | size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET]; | ||
986 | size = (__force u32)cpu_to_le32(size) / 8; | ||
987 | |||
988 | ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START]; | ||
989 | flashaddr = NETXEN_IMAGE_START; | ||
990 | |||
991 | for (i = 0; i < size; i++) { | ||
992 | data = cpu_to_le64(ptr64[i]); | ||
993 | |||
994 | if (adapter->pci_mem_write(adapter, | ||
995 | flashaddr, &data, 8)) | ||
996 | return -EIO; | ||
997 | |||
998 | flashaddr += 8; | ||
999 | } | ||
1000 | } else { | ||
1001 | u32 data; | ||
1002 | |||
1003 | size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4; | ||
1004 | flashaddr = NETXEN_BOOTLD_START; | ||
969 | 1005 | ||
970 | adapter->pci_mem_write(adapter, flashaddr, &data, 4); | 1006 | for (i = 0; i < size; i++) { |
971 | flashaddr += 4; | 1007 | if (netxen_rom_fast_read(adapter, |
1008 | flashaddr, (int *)&data) != 0) | ||
1009 | return -EIO; | ||
1010 | |||
1011 | if (adapter->pci_mem_write(adapter, | ||
1012 | flashaddr, &data, 4)) | ||
1013 | return -EIO; | ||
1014 | |||
1015 | flashaddr += 4; | ||
1016 | } | ||
972 | } | 1017 | } |
973 | msleep(1); | 1018 | msleep(1); |
974 | 1019 | ||
@@ -985,6 +1030,114 @@ int netxen_load_firmware(struct netxen_adapter *adapter) | |||
985 | return 0; | 1030 | return 0; |
986 | } | 1031 | } |
987 | 1032 | ||
1033 | static int | ||
1034 | netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname, | ||
1035 | const struct firmware *fw) | ||
1036 | { | ||
1037 | __le32 val; | ||
1038 | u32 major, minor, build, ver, min_ver, bios; | ||
1039 | struct pci_dev *pdev = adapter->pdev; | ||
1040 | |||
1041 | if (fw->size < NX_FW_MIN_SIZE) | ||
1042 | return -EINVAL; | ||
1043 | |||
1044 | val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]); | ||
1045 | if ((__force u32)val != NETXEN_BDINFO_MAGIC) | ||
1046 | return -EINVAL; | ||
1047 | |||
1048 | val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); | ||
1049 | major = (__force u32)val & 0xff; | ||
1050 | minor = ((__force u32)val >> 8) & 0xff; | ||
1051 | build = (__force u32)val >> 16; | ||
1052 | |||
1053 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
1054 | min_ver = NETXEN_VERSION_CODE(4, 0, 216); | ||
1055 | else | ||
1056 | min_ver = NETXEN_VERSION_CODE(3, 4, 216); | ||
1057 | |||
1058 | ver = NETXEN_VERSION_CODE(major, minor, build); | ||
1059 | |||
1060 | if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { | ||
1061 | dev_err(&pdev->dev, | ||
1062 | "%s: firmware version %d.%d.%d unsupported\n", | ||
1063 | fwname, major, minor, build); | ||
1064 | return -EINVAL; | ||
1065 | } | ||
1066 | |||
1067 | val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]); | ||
1068 | netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios); | ||
1069 | if ((__force u32)val != bios) { | ||
1070 | dev_err(&pdev->dev, "%s: firmware bios is incompatible\n", | ||
1071 | fwname); | ||
1072 | return -EINVAL; | ||
1073 | } | ||
1074 | |||
1075 | netxen_nic_reg_write(adapter, NETXEN_CAM_RAM(0x1fc), | ||
1076 | NETXEN_BDINFO_MAGIC); | ||
1077 | return 0; | ||
1078 | } | ||
1079 | |||
1080 | int netxen_load_firmware(struct netxen_adapter *adapter) | ||
1081 | { | ||
1082 | u32 capability, flashed_ver; | ||
1083 | const struct firmware *fw; | ||
1084 | char *fw_name = NULL; | ||
1085 | struct pci_dev *pdev = adapter->pdev; | ||
1086 | int rc = 0; | ||
1087 | |||
1088 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
1089 | fw_name = NX_P2_MN_ROMIMAGE; | ||
1090 | goto request_fw; | ||
1091 | } | ||
1092 | |||
1093 | capability = 0; | ||
1094 | |||
1095 | netxen_rom_fast_read(adapter, | ||
1096 | NX_FW_VERSION_OFFSET, (int *)&flashed_ver); | ||
1097 | if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { | ||
1098 | adapter->hw_read_wx(adapter, | ||
1099 | NX_PEG_TUNE_CAPABILITY, &capability, 4); | ||
1100 | if (capability & NX_PEG_TUNE_MN_PRESENT) { | ||
1101 | fw_name = NX_P3_MN_ROMIMAGE; | ||
1102 | goto request_fw; | ||
1103 | } | ||
1104 | } | ||
1105 | |||
1106 | request_ct: | ||
1107 | fw_name = NX_P3_CT_ROMIMAGE; | ||
1108 | |||
1109 | request_fw: | ||
1110 | rc = request_firmware(&fw, fw_name, &pdev->dev); | ||
1111 | if (rc != 0) { | ||
1112 | if (fw_name == NX_P3_MN_ROMIMAGE) { | ||
1113 | msleep(1); | ||
1114 | goto request_ct; | ||
1115 | } | ||
1116 | |||
1117 | fw = NULL; | ||
1118 | goto load_fw; | ||
1119 | } | ||
1120 | |||
1121 | rc = netxen_validate_firmware(adapter, fw_name, fw); | ||
1122 | if (rc != 0) { | ||
1123 | release_firmware(fw); | ||
1124 | |||
1125 | if (fw_name == NX_P3_MN_ROMIMAGE) { | ||
1126 | msleep(1); | ||
1127 | goto request_ct; | ||
1128 | } | ||
1129 | |||
1130 | fw = NULL; | ||
1131 | } | ||
1132 | |||
1133 | load_fw: | ||
1134 | rc = netxen_do_load_firmware(adapter, fw_name, fw); | ||
1135 | |||
1136 | if (fw) | ||
1137 | release_firmware(fw); | ||
1138 | return rc; | ||
1139 | } | ||
1140 | |||
988 | int | 1141 | int |
989 | netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, | 1142 | netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, |
990 | ulong off, void *data, int len) | 1143 | ulong off, void *data, int len) |