aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorKarl Relton <karllinuxtest.relton@ntlworld.com>2009-08-19 03:06:39 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-15 15:01:35 -0400
commitd89505998e007f88e08e84381dcc720a8990507d (patch)
tree2a38c5cf189079d0b3f8af84d833db36268b81a8 /drivers/staging
parentc4004175eb51a40069b879d547e32fe8b4d6fde1 (diff)
Staging: wlan-ng: Convert firmware loading to load binary ihex format
Convert prism2_usb firmware loading to load firmware in pre-compiled binary 'ihex' format rather than ascii 'srec' format. This moves the srec processing and sorting of records out of kernel space into a pre-compiler. The driver now just works with the binary image, but still does the 'pda plugging' of that image at runtime, as required by the prism hardware. Some Notes: - The firmware is now expected to be in the same 'ihex' (.fw) format used by other drivers. - The now driver assumes the data records are already sorted into ascending address order. - Plug and crc records are still recognised by special address locations as in original srec processing. - The srec S7 start address record is assumed to have been converted into a data record with another special address location (0xff400000), with the original start address being stored as a 4 byte data word (little endian). Signed-off-by: Karl Relton <karllinuxtest.relton@ntlworld.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/wlan-ng/prism2fw.c465
1 files changed, 131 insertions, 334 deletions
diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c
index c62b4759b3d..7d76a7f92a3 100644
--- a/drivers/staging/wlan-ng/prism2fw.c
+++ b/drivers/staging/wlan-ng/prism2fw.c
@@ -47,84 +47,28 @@
47 47
48/*================================================================*/ 48/*================================================================*/
49/* System Includes */ 49/* System Includes */
50#include <linux/sort.h> 50#include <linux/ihex.h>
51#include <linux/firmware.h>
52 51
53/*================================================================*/ 52/*================================================================*/
54/* Local Constants */ 53/* Local Constants */
55 54
56#define PRISM2_USB_FWFILE "prism2_ru.hex" 55#define PRISM2_USB_FWFILE "prism2_ru.fw"
57 56
58#define S3DATA_MAX 5000 57#define S3DATA_MAX 5000
59#define S3PLUG_MAX 200 58#define S3PLUG_MAX 200
60#define S3CRC_MAX 200 59#define S3CRC_MAX 200
61#define S3INFO_MAX 50 60#define S3INFO_MAX 50
62#define SREC_LINE_MAX 264
63#define S3LEN_TXTOFFSET 2
64#define S3LEN_TXTLEN 2
65#define S3ADDR_TXTOFFSET 4
66#define S3ADDR_TXTLEN 8
67#define S3DATA_TXTOFFSET 12
68/*S3DATA_TXTLEN variable, depends on len field */
69/*S3CKSUM_TXTOFFSET variable, depends on len field */
70#define S3CKSUM_TXTLEN 2
71#define SERNUM_LEN_MAX 12
72
73#define S3PLUG_ITEMCODE_TXTOFFSET (S3DATA_TXTOFFSET)
74#define S3PLUG_ITEMCODE_TXTLEN 8
75#define S3PLUG_ADDR_TXTOFFSET (S3DATA_TXTOFFSET+8)
76#define S3PLUG_ADDR_TXTLEN 8
77#define S3PLUG_LEN_TXTOFFSET (S3DATA_TXTOFFSET+16)
78#define S3PLUG_LEN_TXTLEN 8
79
80#define S3CRC_ADDR_TXTOFFSET (S3DATA_TXTOFFSET)
81#define S3CRC_ADDR_TXTLEN 8
82#define S3CRC_LEN_TXTOFFSET (S3DATA_TXTOFFSET+8)
83#define S3CRC_LEN_TXTLEN 8
84#define S3CRC_DOWRITE_TXTOFFSET (S3DATA_TXTOFFSET+16)
85#define S3CRC_DOWRITE_TXTLEN 8
86
87#define S3INFO_LEN_TXTOFFSET (S3DATA_TXTOFFSET)
88#define S3INFO_LEN_TXTLEN 4
89#define S3INFO_TYPE_TXTOFFSET (S3DATA_TXTOFFSET+4)
90#define S3INFO_TYPE_TXTLEN 4
91#define S3INFO_DATA_TXTOFFSET (S3DATA_TXTOFFSET+8)
92/* S3INFO_DATA_TXTLEN variable, depends on INFO_LEN field */
93 61
94#define S3ADDR_PLUG (0xff000000UL) 62#define S3ADDR_PLUG (0xff000000UL)
95#define S3ADDR_CRC (0xff100000UL) 63#define S3ADDR_CRC (0xff100000UL)
96#define S3ADDR_INFO (0xff200000UL) 64#define S3ADDR_INFO (0xff200000UL)
97 65#define S3ADDR_START (0xff400000UL)
98#define PDAFILE_LINE_MAX 1024
99 66
100#define CHUNKS_MAX 100 67#define CHUNKS_MAX 100
101 68
102#define WRITESIZE_MAX 4096 69#define WRITESIZE_MAX 4096
103 70
104/*================================================================*/ 71/*================================================================*/
105/* Local Macros */
106
107#define bswap_16(x) \
108 (__extension__ \
109 ({ register unsigned short int __v, __x = (x); \
110 __asm__ ("rorw $8, %w0" \
111 : "=r" (__v) \
112 : "0" (__x) \
113 : "cc"); \
114 __v; }))
115
116#define bswap_32(x) \
117 (__extension__ \
118 ({ register unsigned int __v, __x = (x); \
119 __asm__ ("rorw $8, %w0;" \
120 "rorl $16, %0;" \
121 "rorw $8, %w0" \
122 : "=r" (__v) \
123 : "0" (__x) \
124 : "cc"); \
125 __v; }))
126
127/*================================================================*/
128/* Local Types */ 72/* Local Types */
129 73
130typedef struct s3datarec { 74typedef struct s3datarec {
@@ -214,12 +158,11 @@ hfa384x_caplevel_t priid;
214/*================================================================*/ 158/*================================================================*/
215/* Local Function Declarations */ 159/* Local Function Declarations */
216 160
217int prism2_fwapply(char *rfptr, int rfsize, wlandevice_t * wlandev); 161int prism2_fwapply(const struct ihex_binrec *rfptr, wlandevice_t *wlandev);
218int read_srecfile(char *rfptr, int rfsize); 162int read_fwfile(const struct ihex_binrec *rfptr);
219int mkimage(imgchunk_t *clist, unsigned int *ccnt); 163int mkimage(imgchunk_t *clist, unsigned int *ccnt);
220int read_cardpda(pda_t *pda, wlandevice_t *wlandev); 164int read_cardpda(pda_t *pda, wlandevice_t *wlandev);
221int mkpdrlist(pda_t *pda); 165int mkpdrlist(pda_t *pda);
222int s3datarec_compare(const void *p1, const void *p2);
223int plugimage(imgchunk_t *fchunk, unsigned int nfchunks, 166int plugimage(imgchunk_t *fchunk, unsigned int nfchunks,
224 s3plugrec_t *s3plug, unsigned int ns3plug, pda_t * pda); 167 s3plugrec_t *s3plug, unsigned int ns3plug, pda_t * pda);
225int crcimage(imgchunk_t *fchunk, unsigned int nfchunks, 168int crcimage(imgchunk_t *fchunk, unsigned int nfchunks,
@@ -253,7 +196,7 @@ int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev)
253 196
254 printk(KERN_INFO "prism2_usb: Checking for firmware %s\n", 197 printk(KERN_INFO "prism2_usb: Checking for firmware %s\n",
255 PRISM2_USB_FWFILE); 198 PRISM2_USB_FWFILE);
256 if (request_firmware(&fw_entry, PRISM2_USB_FWFILE, &udev->dev) != 0) { 199 if (request_ihex_firmware(&fw_entry, PRISM2_USB_FWFILE, &udev->dev) != 0) {
257 printk(KERN_INFO 200 printk(KERN_INFO
258 "prism2_usb: Firmware not available, but not essential\n"); 201 "prism2_usb: Firmware not available, but not essential\n");
259 printk(KERN_INFO 202 printk(KERN_INFO
@@ -263,7 +206,7 @@ int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev)
263 206
264 printk(KERN_INFO "prism2_usb: %s will be processed, size %d\n", 207 printk(KERN_INFO "prism2_usb: %s will be processed, size %d\n",
265 PRISM2_USB_FWFILE, fw_entry->size); 208 PRISM2_USB_FWFILE, fw_entry->size);
266 prism2_fwapply((char *)fw_entry->data, fw_entry->size, wlandev); 209 prism2_fwapply((const struct ihex_binrec *)fw_entry->data, wlandev);
267 210
268 release_firmware(fw_entry); 211 release_firmware(fw_entry);
269 return 0; 212 return 0;
@@ -276,14 +219,13 @@ int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev)
276* 219*
277* Arguments: 220* Arguments:
278* rfptr firmware image in kernel memory 221* rfptr firmware image in kernel memory
279* rfsize firmware size in kernel memory
280* wlandev device 222* wlandev device
281* 223*
282* Returns: 224* Returns:
283* 0 - success 225* 0 - success
284* ~0 - failure 226* ~0 - failure
285----------------------------------------------------------------*/ 227----------------------------------------------------------------*/
286int prism2_fwapply(char *rfptr, int rfsize, wlandevice_t *wlandev) 228int prism2_fwapply(const struct ihex_binrec *rfptr, wlandevice_t *wlandev)
287{ 229{
288 signed int result = 0; 230 signed int result = 0;
289 p80211msg_dot11req_mibget_t getmsg; 231 p80211msg_dot11req_mibget_t getmsg;
@@ -356,13 +298,11 @@ int prism2_fwapply(char *rfptr, int rfsize, wlandevice_t *wlandev)
356 priid.top = *data++; 298 priid.top = *data++;
357 299
358 /* Read the S3 file */ 300 /* Read the S3 file */
359 result = read_srecfile(rfptr, rfsize); 301 result = read_fwfile(rfptr);
360 if (result) { 302 if (result) {
361 printk(KERN_ERR "Failed to read the data exiting.\n"); 303 printk(KERN_ERR "Failed to read the data exiting.\n");
362 return (1); 304 return (1);
363 } 305 }
364 /* Sort the S3 data records */
365 sort(s3data, ns3data, sizeof(s3datarec_t), s3datarec_compare, NULL);
366 306
367 result = validate_identity(); 307 result = validate_identity();
368 308
@@ -516,10 +456,6 @@ void free_chunks(imgchunk_t *fchunk, unsigned int *nfchunks)
516----------------------------------------------------------------*/ 456----------------------------------------------------------------*/
517void free_srecs(void) 457void free_srecs(void)
518{ 458{
519 int i;
520 for (i = 0; i < ns3data; i++) {
521 kfree(s3data[i].data);
522 }
523 ns3data = 0; 459 ns3data = 0;
524 memset(s3data, 0, sizeof(s3data)); 460 memset(s3data, 0, sizeof(s3data));
525 ns3plug = 0; 461 ns3plug = 0;
@@ -598,10 +534,6 @@ int mkimage(imgchunk_t *clist, unsigned int *ccnt)
598 return (1); 534 return (1);
599 } 535 }
600 memset(clist[i].data, 0, clist[i].len); 536 memset(clist[i].data, 0, clist[i].len);
601 }
602
603 /* Display chunks */
604 for (i = 0; i < *ccnt; i++) {
605 pr_debug("chunk[%d]: addr=0x%06x len=%d\n", 537 pr_debug("chunk[%d]: addr=0x%06x len=%d\n",
606 i, clist[i].addr, clist[i].len); 538 i, clist[i].addr, clist[i].len);
607 } 539 }
@@ -856,44 +788,20 @@ int read_cardpda(pda_t *pda, wlandevice_t *wlandev)
856} 788}
857 789
858/*---------------------------------------------------------------- 790/*----------------------------------------------------------------
859* copy_line 791* read_fwfile
860* 792*
861* Copies a line of text, up to \n, \0, or SREC_LINE_MAX, or limit of 793* Reads the given fw file which should have been compiled from an srec
862* From array 794* file. Each record in the fw file will either be a plain data record,
795* a start address record, or other records used for plugging.
863* 796*
864* Arguments: 797* Note that data records are expected to be sorted into
865* from From addr 798* ascending address order in the fw file.
866* to To addr
867* limit Addr of last character in From array that can be copied
868*
869* Returns:
870* Num characters copied
871----------------------------------------------------------------*/
872int copyline(char *from, char *to, char *limit)
873{
874 int c = 0;
875
876 while ((c < SREC_LINE_MAX - 1) && (from + c <= limit) &&
877 (from[c] != '\n') && (from[c] != '\0')) {
878 to[c] = from[c];
879 c++;
880 }
881
882 to[c] = '\0';
883 return (c < SREC_LINE_MAX - 1) ? c + 1 : c;
884}
885
886/*----------------------------------------------------------------
887* read_srecfile
888* 799*
889* Reads the given srecord file and loads the records into the 800* Note also that the start address record, originally an S7 record in
890* s3xxx arrays. This function can be called repeatedly (once for 801* the srec file, is expected in the fw file to be like a data record but
891* each of a set of files), if necessary. This function performs 802* with a certain address to make it identiable.
892* no validation of the data except for the grossest of S-record
893* line format checks. Don't forget that these will be DOS files...
894* CR/LF at the end of each line.
895* 803*
896* Here's the SREC format we're dealing with: 804* Here's the SREC format that the fw should have come from:
897* S[37]nnaaaaaaaaddd...dddcc 805* S[37]nnaaaaaaaaddd...dddcc
898* 806*
899* nn - number of bytes starting with the address field 807* nn - number of bytes starting with the address field
@@ -902,8 +810,9 @@ int copyline(char *from, char *to, char *limit)
902* cc - checksum 810* cc - checksum
903* 811*
904* The S7 record's (there should be only one) address value gets 812* The S7 record's (there should be only one) address value gets
905* saved in startaddr. It's the start execution address used 813* converted to an S3 record with address of 0xff400000, with the
906* for RAM downloads. 814* start address being stored as a 4 byte data word. That address is
815* the start execution address used for RAM downloads.
907* 816*
908* The S3 records have a collection of subformats indicated by the 817* The S3 records have a collection of subformats indicated by the
909* value of aaaaaaaa: 818* value of aaaaaaaa:
@@ -927,237 +836,124 @@ int copyline(char *from, char *to, char *limit)
927* d - (s - 1) little endian words giving the contents of 836* d - (s - 1) little endian words giving the contents of
928* the given info type. 837* the given info type.
929* 838*
839* 0xff400000 - Start address record, data field format:
840* aaaaaaaa
841* a - Address in load image to plug (little endian)
842*
930* Arguments: 843* Arguments:
931* rfptr firmware image (s-record structure) in kernel memory 844* record firmware image (ihex record structure) in kernel memory
932* rfsize firmware size in kernel memory
933* 845*
934* Returns: 846* Returns:
935* 0 - success 847* 0 - success
936* ~0 - failure (probably an errno) 848* ~0 - failure (probably an errno)
937----------------------------------------------------------------*/ 849----------------------------------------------------------------*/
938int read_srecfile(char *rfptr, int rfsize) 850int read_fwfile(const struct ihex_binrec *record)
939{ 851{
940 int result = 0; 852 int i;
941 char buf[SREC_LINE_MAX]; 853 int rcnt = 0;
942 char tmpbuf[30]; 854 u16 *tmpinfo;
943 s3datarec_t tmprec; 855 u16 *ptr16;
944 int i, c; 856 u32 *ptr32, len, addr;
945 int line = 0;
946 u16 *tmpinfo;
947 char *endptr = rfptr + rfsize;
948
949 pr_debug("Reading S-record file ...\n");
950
951 while ((c = copyline(rfptr, buf, endptr)) >= 12) {
952 rfptr = rfptr + c;
953 line++;
954 if (buf[0] != 'S') {
955 printk(KERN_ERR "%d warning: No initial \'S\'\n", line);
956 return 1;
957 }
958 if (buf[1] == '7') { /* S7 record, start address */
959 buf[12] = '\0';
960 startaddr = simple_strtoul(buf + 4, NULL, 16);
961 pr_debug(" S7 start addr, line=%d "
962 " addr=0x%08x\n", line, startaddr);
963 continue;
964 } else if (buf[1] == '3') {
965 /* Ok, it's an S3, parse and put it in the right array */
966 /* Record Length field (we only want datalen) */
967 memcpy(tmpbuf, buf + S3LEN_TXTOFFSET, S3LEN_TXTLEN);
968 tmpbuf[S3LEN_TXTLEN] = '\0';
969 tmprec.len = simple_strtoul(tmpbuf, NULL, 16) - 4 - 1; /* 4=addr, 1=cksum */
970 /* Address field */
971 memcpy(tmpbuf, buf + S3ADDR_TXTOFFSET, S3ADDR_TXTLEN);
972 tmpbuf[S3ADDR_TXTLEN] = '\0';
973 tmprec.addr = simple_strtoul(tmpbuf, NULL, 16);
974 /* Checksum field */
975 tmprec.checksum =
976 simple_strtoul(buf + strlen(buf) - 2, NULL, 16);
977
978 switch (tmprec.addr) {
979 case S3ADDR_PLUG:
980 memcpy(tmpbuf, buf + S3PLUG_ITEMCODE_TXTOFFSET,
981 S3PLUG_ITEMCODE_TXTLEN);
982 tmpbuf[S3PLUG_ITEMCODE_TXTLEN] = '\0';
983 s3plug[ns3plug].itemcode =
984 simple_strtoul(tmpbuf, NULL, 16);
985 s3plug[ns3plug].itemcode =
986 bswap_32(s3plug[ns3plug].itemcode);
987
988 memcpy(tmpbuf, buf + S3PLUG_ADDR_TXTOFFSET,
989 S3PLUG_ADDR_TXTLEN);
990 tmpbuf[S3PLUG_ADDR_TXTLEN] = '\0';
991 s3plug[ns3plug].addr =
992 simple_strtoul(tmpbuf, NULL, 16);
993 s3plug[ns3plug].addr =
994 bswap_32(s3plug[ns3plug].addr);
995
996 memcpy(tmpbuf, buf + S3PLUG_LEN_TXTOFFSET,
997 S3PLUG_LEN_TXTLEN);
998 tmpbuf[S3PLUG_LEN_TXTLEN] = '\0';
999 s3plug[ns3plug].len =
1000 simple_strtoul(tmpbuf, NULL, 16);
1001 s3plug[ns3plug].len =
1002 bswap_32(s3plug[ns3plug].len);
1003
1004 pr_debug(" S3 plugrec, line=%d "
1005 "itemcode=0x%04x addr=0x%08x len=%d\n",
1006 line,
1007 s3plug[ns3plug].itemcode,
1008 s3plug[ns3plug].addr,
1009 s3plug[ns3plug].len);
1010
1011 ns3plug++;
1012 if (ns3plug == S3PLUG_MAX) {
1013 printk(KERN_ERR
1014 "S3 plugrec limit reached - aborting\n");
1015 return 1;
1016 }
1017 break;
1018 case S3ADDR_CRC:
1019 memcpy(tmpbuf, buf + S3CRC_ADDR_TXTOFFSET,
1020 S3CRC_ADDR_TXTLEN);
1021 tmpbuf[S3CRC_ADDR_TXTLEN] = '\0';
1022 s3crc[ns3crc].addr =
1023 simple_strtoul(tmpbuf, NULL, 16);
1024 s3crc[ns3crc].addr =
1025 bswap_32(s3crc[ns3crc].addr);
1026
1027 memcpy(tmpbuf, buf + S3CRC_LEN_TXTOFFSET,
1028 S3CRC_LEN_TXTLEN);
1029 tmpbuf[S3CRC_LEN_TXTLEN] = '\0';
1030 s3crc[ns3crc].len =
1031 simple_strtoul(tmpbuf, NULL, 16);
1032 s3crc[ns3crc].len = bswap_32(s3crc[ns3crc].len);
1033
1034 memcpy(tmpbuf, buf + S3CRC_DOWRITE_TXTOFFSET,
1035 S3CRC_DOWRITE_TXTLEN);
1036 tmpbuf[S3CRC_DOWRITE_TXTLEN] = '\0';
1037 s3crc[ns3crc].dowrite =
1038 simple_strtoul(tmpbuf, NULL, 16);
1039 s3crc[ns3crc].dowrite =
1040 bswap_32(s3crc[ns3crc].dowrite);
1041
1042 pr_debug(" S3 crcrec, line=%d "
1043 "addr=0x%08x len=%d write=0x%08x\n",
1044 line,
1045 s3crc[ns3crc].addr,
1046 s3crc[ns3crc].len,
1047 s3crc[ns3crc].dowrite);
1048 ns3crc++;
1049 if (ns3crc == S3CRC_MAX) {
1050 printk(KERN_ERR
1051 "S3 crcrec limit reached - aborting\n");
1052 return 1;
1053 }
1054 break;
1055 case S3ADDR_INFO:
1056 memcpy(tmpbuf, buf + S3INFO_LEN_TXTOFFSET,
1057 S3INFO_LEN_TXTLEN);
1058 tmpbuf[S3INFO_LEN_TXTLEN] = '\0';
1059 s3info[ns3info].len =
1060 simple_strtoul(tmpbuf, NULL, 16);
1061 s3info[ns3info].len =
1062 bswap_16(s3info[ns3info].len);
1063
1064 memcpy(tmpbuf, buf + S3INFO_TYPE_TXTOFFSET,
1065 S3INFO_TYPE_TXTLEN);
1066 tmpbuf[S3INFO_TYPE_TXTLEN] = '\0';
1067 s3info[ns3info].type =
1068 simple_strtoul(tmpbuf, NULL, 16);
1069 s3info[ns3info].type =
1070 bswap_16(s3info[ns3info].type);
1071
1072 pr_debug(" S3 inforec, line=%d "
1073 "len=0x%04x type=0x%04x\n",
1074 line,
1075 s3info[ns3info].len,
1076 s3info[ns3info].type);
1077 if (((s3info[ns3info].len - 1) * sizeof(u16)) >
1078 sizeof(s3info[ns3info].info)) {
1079 printk(KERN_ERR
1080 " S3 inforec length too long - aborting\n");
1081 return 1;
1082 }
1083 857
1084 tmpinfo = 858 pr_debug("Reading fw file ...\n");
1085 (u16 *) & (s3info[ns3info].info.version);
1086 for (i = 0; i < s3info[ns3info].len - 1; i++) {
1087 memcpy(tmpbuf,
1088 buf + S3INFO_DATA_TXTOFFSET +
1089 (i * 4), 4);
1090 tmpbuf[4] = '\0';
1091 tmpinfo[i] =
1092 simple_strtoul(tmpbuf, NULL, 16);
1093 tmpinfo[i] = bswap_16(tmpinfo[i]);
1094 }
1095 pr_debug(" info=");
1096 for (i = 0; i < s3info[ns3info].len - 1; i++) {
1097 pr_debug("%04x ", tmpinfo[i]);
1098 }
1099 pr_debug("\n");
1100 859
1101 ns3info++; 860 while (record) {
1102 if (ns3info == S3INFO_MAX) { 861
1103 printk(KERN_ERR 862 rcnt++;
1104 "S3 inforec limit reached - aborting\n"); 863
1105 return 1; 864 len = be16_to_cpu(record->len);
1106 } 865 addr = be32_to_cpu(record->addr);
1107 break; 866
1108 default: /* Data record */ 867 /* Point into data for different word lengths */
1109 s3data[ns3data].addr = tmprec.addr; 868 ptr32 = (u32 *) record->data;
1110 s3data[ns3data].len = tmprec.len; 869 ptr16 = (u16 *) record->data;
1111 s3data[ns3data].checksum = tmprec.checksum; 870
1112 s3data[ns3data].data = 871 /* parse what was an S3 srec and put it in the right array */
1113 kmalloc(tmprec.len, GFP_KERNEL); 872 switch(addr) {
1114 for (i = 0; i < tmprec.len; i++) { 873 case S3ADDR_START:
1115 memcpy(tmpbuf, 874 startaddr = *ptr32;
1116 buf + S3DATA_TXTOFFSET + (i * 2), 875 pr_debug(" S7 start addr, record=%d "
1117 2); 876 " addr=0x%08x\n",
1118 tmpbuf[2] = '\0'; 877 rcnt,
1119 s3data[ns3data].data[i] = 878 startaddr);
1120 simple_strtoul(tmpbuf, NULL, 16); 879 break;
1121 } 880 case S3ADDR_PLUG:
1122 ns3data++; 881 s3plug[ns3plug].itemcode = *ptr32;
1123 if (ns3data == S3DATA_MAX) { 882 s3plug[ns3plug].addr = *(ptr32 + 1);
1124 printk(KERN_ERR 883 s3plug[ns3plug].len = *(ptr32 + 2);
1125 "S3 datarec limit reached - aborting\n"); 884
1126 return 1; 885 pr_debug(" S3 plugrec, record=%d "
1127 } 886 "itemcode=0x%08x addr=0x%08x len=%d\n",
1128 break; 887 rcnt,
888 s3plug[ns3plug].itemcode,
889 s3plug[ns3plug].addr,
890 s3plug[ns3plug].len);
891
892 ns3plug++;
893 if ( ns3plug == S3PLUG_MAX ) {
894 printk(KERN_ERR "S3 plugrec limit reached - aborting\n");
895 return 1;
1129 } 896 }
1130 } else { 897 break;
1131 printk(KERN_WARNING 898 case S3ADDR_CRC:
1132 "%d warning: Unknown S-record detected.\n", 899 s3crc[ns3crc].addr = *ptr32;
1133 line); 900 s3crc[ns3crc].len = *(ptr32 + 1);
901 s3crc[ns3crc].dowrite = *(ptr32 + 2);
902
903 pr_debug(" S3 crcrec, record=%d "
904 "addr=0x%08x len=%d write=0x%08x\n",
905 rcnt,
906 s3crc[ns3crc].addr,
907 s3crc[ns3crc].len,
908 s3crc[ns3crc].dowrite);
909 ns3crc++;
910 if ( ns3crc == S3CRC_MAX ) {
911 printk(KERN_ERR "S3 crcrec limit reached - aborting\n");
912 return 1;
913 }
914 break;
915 case S3ADDR_INFO:
916 s3info[ns3info].len = *ptr16;
917 s3info[ns3info].type = *(ptr16 + 1);
918
919 pr_debug(" S3 inforec, record=%d "
920 "len=0x%04x type=0x%04x\n",
921 rcnt,
922 s3info[ns3info].len,
923 s3info[ns3info].type);
924 if ( ((s3info[ns3info].len - 1) * sizeof(u16)) > sizeof(s3info[ns3info].info) ) {
925 printk(KERN_ERR " S3 inforec length too long - aborting\n");
926 return 1;
927 }
928
929 tmpinfo = (u16*)&(s3info[ns3info].info.version);
930 pr_debug(" info=");
931 for (i = 0; i < s3info[ns3info].len - 1; i++) {
932 tmpinfo[i] = *(ptr16 + 2 + i);
933 pr_debug("%04x ", tmpinfo[i]);
934 }
935 pr_debug("\n");
936
937 ns3info++;
938 if ( ns3info == S3INFO_MAX ) {
939 printk(KERN_ERR "S3 inforec limit reached - aborting\n");
940 return 1;
941 }
942 break;
943 default: /* Data record */
944 s3data[ns3data].addr = addr;
945 s3data[ns3data].len = len;
946 s3data[ns3data].data = (uint8_t *) record->data;
947 ns3data++;
948 if ( ns3data == S3DATA_MAX ) {
949 printk(KERN_ERR "S3 datarec limit reached - aborting\n");
950 return 1;
951 }
952 break;
1134 } 953 }
954 record = ihex_next_binrec(record);
1135 } 955 }
1136 return result; 956 return 0;
1137}
1138
1139/*----------------------------------------------------------------
1140* s3datarec_compare
1141*
1142* Comparison function for sort().
1143*
1144* Arguments:
1145* p1 ptr to the first item
1146* p2 ptr to the second item
1147* Returns:
1148* 0 items are equal
1149* <0 p1 < p2
1150* >0 p1 > p2
1151----------------------------------------------------------------*/
1152int s3datarec_compare(const void *p1, const void *p2)
1153{
1154 const s3datarec_t *s1 = p1;
1155 const s3datarec_t *s2 = p2;
1156 if (s1->addr == s2->addr)
1157 return 0;
1158 if (s1->addr < s2->addr)
1159 return -1;
1160 return 1;
1161} 957}
1162 958
1163/*---------------------------------------------------------------- 959/*----------------------------------------------------------------
@@ -1316,6 +1112,7 @@ int validate_identity(void)
1316{ 1112{
1317 int i; 1113 int i;
1318 int result = 1; 1114 int result = 1;
1115 int trump = 0;
1319 1116
1320 pr_debug("NIC ID: %#x v%d.%d.%d\n", 1117 pr_debug("NIC ID: %#x v%d.%d.%d\n",
1321 nicid.id, nicid.major, nicid.minor, nicid.variant); 1118 nicid.id, nicid.major, nicid.minor, nicid.variant);
@@ -1389,8 +1186,7 @@ int validate_identity(void)
1389 (nicid.id != 0x8008)) 1186 (nicid.id != 0x8008))
1390 continue; 1187 continue;
1391 1188
1392 if (result != 2) 1189 trump = 1;
1393 result = 0;
1394 break; 1190 break;
1395 case 0x8001: 1191 case 0x8001:
1396 pr_debug("name inforec len %d\n", s3info[i].len); 1192 pr_debug("name inforec len %d\n", s3info[i].len);
@@ -1402,5 +1198,6 @@ int validate_identity(void)
1402 } 1198 }
1403 // walk through 1199 // walk through
1404 1200
1201 if (trump && (result != 2)) result = 0;
1405 return result; 1202 return result;
1406} 1203}