Commit d8950599 authored by Karl Relton's avatar Karl Relton Committed by Greg Kroah-Hartman

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: default avatarKarl Relton <karllinuxtest.relton@ntlworld.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c4004175
...@@ -47,83 +47,27 @@ ...@@ -47,83 +47,27 @@
/*================================================================*/ /*================================================================*/
/* System Includes */ /* System Includes */
#include <linux/sort.h> #include <linux/ihex.h>
#include <linux/firmware.h>
/*================================================================*/ /*================================================================*/
/* Local Constants */ /* Local Constants */
#define PRISM2_USB_FWFILE "prism2_ru.hex" #define PRISM2_USB_FWFILE "prism2_ru.fw"
#define S3DATA_MAX 5000 #define S3DATA_MAX 5000
#define S3PLUG_MAX 200 #define S3PLUG_MAX 200
#define S3CRC_MAX 200 #define S3CRC_MAX 200
#define S3INFO_MAX 50 #define S3INFO_MAX 50
#define SREC_LINE_MAX 264
#define S3LEN_TXTOFFSET 2
#define S3LEN_TXTLEN 2
#define S3ADDR_TXTOFFSET 4
#define S3ADDR_TXTLEN 8
#define S3DATA_TXTOFFSET 12
/*S3DATA_TXTLEN variable, depends on len field */
/*S3CKSUM_TXTOFFSET variable, depends on len field */
#define S3CKSUM_TXTLEN 2
#define SERNUM_LEN_MAX 12
#define S3PLUG_ITEMCODE_TXTOFFSET (S3DATA_TXTOFFSET)
#define S3PLUG_ITEMCODE_TXTLEN 8
#define S3PLUG_ADDR_TXTOFFSET (S3DATA_TXTOFFSET+8)
#define S3PLUG_ADDR_TXTLEN 8
#define S3PLUG_LEN_TXTOFFSET (S3DATA_TXTOFFSET+16)
#define S3PLUG_LEN_TXTLEN 8
#define S3CRC_ADDR_TXTOFFSET (S3DATA_TXTOFFSET)
#define S3CRC_ADDR_TXTLEN 8
#define S3CRC_LEN_TXTOFFSET (S3DATA_TXTOFFSET+8)
#define S3CRC_LEN_TXTLEN 8
#define S3CRC_DOWRITE_TXTOFFSET (S3DATA_TXTOFFSET+16)
#define S3CRC_DOWRITE_TXTLEN 8
#define S3INFO_LEN_TXTOFFSET (S3DATA_TXTOFFSET)
#define S3INFO_LEN_TXTLEN 4
#define S3INFO_TYPE_TXTOFFSET (S3DATA_TXTOFFSET+4)
#define S3INFO_TYPE_TXTLEN 4
#define S3INFO_DATA_TXTOFFSET (S3DATA_TXTOFFSET+8)
/* S3INFO_DATA_TXTLEN variable, depends on INFO_LEN field */
#define S3ADDR_PLUG (0xff000000UL) #define S3ADDR_PLUG (0xff000000UL)
#define S3ADDR_CRC (0xff100000UL) #define S3ADDR_CRC (0xff100000UL)
#define S3ADDR_INFO (0xff200000UL) #define S3ADDR_INFO (0xff200000UL)
#define S3ADDR_START (0xff400000UL)
#define PDAFILE_LINE_MAX 1024
#define CHUNKS_MAX 100 #define CHUNKS_MAX 100
#define WRITESIZE_MAX 4096 #define WRITESIZE_MAX 4096
/*================================================================*/
/* Local Macros */
#define bswap_16(x) \
(__extension__ \
({ register unsigned short int __v, __x = (x); \
__asm__ ("rorw $8, %w0" \
: "=r" (__v) \
: "0" (__x) \
: "cc"); \
__v; }))
#define bswap_32(x) \
(__extension__ \
({ register unsigned int __v, __x = (x); \
__asm__ ("rorw $8, %w0;" \
"rorl $16, %0;" \
"rorw $8, %w0" \
: "=r" (__v) \
: "0" (__x) \
: "cc"); \
__v; }))
/*================================================================*/ /*================================================================*/
/* Local Types */ /* Local Types */
...@@ -214,12 +158,11 @@ hfa384x_caplevel_t priid; ...@@ -214,12 +158,11 @@ hfa384x_caplevel_t priid;
/*================================================================*/ /*================================================================*/
/* Local Function Declarations */ /* Local Function Declarations */
int prism2_fwapply(char *rfptr, int rfsize, wlandevice_t * wlandev); int prism2_fwapply(const struct ihex_binrec *rfptr, wlandevice_t *wlandev);
int read_srecfile(char *rfptr, int rfsize); int read_fwfile(const struct ihex_binrec *rfptr);
int mkimage(imgchunk_t *clist, unsigned int *ccnt); int mkimage(imgchunk_t *clist, unsigned int *ccnt);
int read_cardpda(pda_t *pda, wlandevice_t *wlandev); int read_cardpda(pda_t *pda, wlandevice_t *wlandev);
int mkpdrlist(pda_t *pda); int mkpdrlist(pda_t *pda);
int s3datarec_compare(const void *p1, const void *p2);
int plugimage(imgchunk_t *fchunk, unsigned int nfchunks, int plugimage(imgchunk_t *fchunk, unsigned int nfchunks,
s3plugrec_t *s3plug, unsigned int ns3plug, pda_t * pda); s3plugrec_t *s3plug, unsigned int ns3plug, pda_t * pda);
int crcimage(imgchunk_t *fchunk, unsigned int nfchunks, int crcimage(imgchunk_t *fchunk, unsigned int nfchunks,
...@@ -253,7 +196,7 @@ int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev) ...@@ -253,7 +196,7 @@ int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev)
printk(KERN_INFO "prism2_usb: Checking for firmware %s\n", printk(KERN_INFO "prism2_usb: Checking for firmware %s\n",
PRISM2_USB_FWFILE); PRISM2_USB_FWFILE);
if (request_firmware(&fw_entry, PRISM2_USB_FWFILE, &udev->dev) != 0) { if (request_ihex_firmware(&fw_entry, PRISM2_USB_FWFILE, &udev->dev) != 0) {
printk(KERN_INFO printk(KERN_INFO
"prism2_usb: Firmware not available, but not essential\n"); "prism2_usb: Firmware not available, but not essential\n");
printk(KERN_INFO printk(KERN_INFO
...@@ -263,7 +206,7 @@ int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev) ...@@ -263,7 +206,7 @@ int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev)
printk(KERN_INFO "prism2_usb: %s will be processed, size %d\n", printk(KERN_INFO "prism2_usb: %s will be processed, size %d\n",
PRISM2_USB_FWFILE, fw_entry->size); PRISM2_USB_FWFILE, fw_entry->size);
prism2_fwapply((char *)fw_entry->data, fw_entry->size, wlandev); prism2_fwapply((const struct ihex_binrec *)fw_entry->data, wlandev);
release_firmware(fw_entry); release_firmware(fw_entry);
return 0; return 0;
...@@ -276,14 +219,13 @@ int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev) ...@@ -276,14 +219,13 @@ int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev)
* *
* Arguments: * Arguments:
* rfptr firmware image in kernel memory * rfptr firmware image in kernel memory
* rfsize firmware size in kernel memory
* wlandev device * wlandev device
* *
* Returns: * Returns:
* 0 - success * 0 - success
* ~0 - failure * ~0 - failure
----------------------------------------------------------------*/ ----------------------------------------------------------------*/
int prism2_fwapply(char *rfptr, int rfsize, wlandevice_t *wlandev) int prism2_fwapply(const struct ihex_binrec *rfptr, wlandevice_t *wlandev)
{ {
signed int result = 0; signed int result = 0;
p80211msg_dot11req_mibget_t getmsg; p80211msg_dot11req_mibget_t getmsg;
...@@ -356,13 +298,11 @@ int prism2_fwapply(char *rfptr, int rfsize, wlandevice_t *wlandev) ...@@ -356,13 +298,11 @@ int prism2_fwapply(char *rfptr, int rfsize, wlandevice_t *wlandev)
priid.top = *data++; priid.top = *data++;
/* Read the S3 file */ /* Read the S3 file */
result = read_srecfile(rfptr, rfsize); result = read_fwfile(rfptr);
if (result) { if (result) {
printk(KERN_ERR "Failed to read the data exiting.\n"); printk(KERN_ERR "Failed to read the data exiting.\n");
return (1); return (1);
} }
/* Sort the S3 data records */
sort(s3data, ns3data, sizeof(s3datarec_t), s3datarec_compare, NULL);
result = validate_identity(); result = validate_identity();
...@@ -516,10 +456,6 @@ void free_chunks(imgchunk_t *fchunk, unsigned int *nfchunks) ...@@ -516,10 +456,6 @@ void free_chunks(imgchunk_t *fchunk, unsigned int *nfchunks)
----------------------------------------------------------------*/ ----------------------------------------------------------------*/
void free_srecs(void) void free_srecs(void)
{ {
int i;
for (i = 0; i < ns3data; i++) {
kfree(s3data[i].data);
}
ns3data = 0; ns3data = 0;
memset(s3data, 0, sizeof(s3data)); memset(s3data, 0, sizeof(s3data));
ns3plug = 0; ns3plug = 0;
...@@ -598,10 +534,6 @@ int mkimage(imgchunk_t *clist, unsigned int *ccnt) ...@@ -598,10 +534,6 @@ int mkimage(imgchunk_t *clist, unsigned int *ccnt)
return (1); return (1);
} }
memset(clist[i].data, 0, clist[i].len); memset(clist[i].data, 0, clist[i].len);
}
/* Display chunks */
for (i = 0; i < *ccnt; i++) {
pr_debug("chunk[%d]: addr=0x%06x len=%d\n", pr_debug("chunk[%d]: addr=0x%06x len=%d\n",
i, clist[i].addr, clist[i].len); i, clist[i].addr, clist[i].len);
} }
...@@ -856,44 +788,20 @@ int read_cardpda(pda_t *pda, wlandevice_t *wlandev) ...@@ -856,44 +788,20 @@ int read_cardpda(pda_t *pda, wlandevice_t *wlandev)
} }
/*---------------------------------------------------------------- /*----------------------------------------------------------------
* copy_line * read_fwfile
* *
* Copies a line of text, up to \n, \0, or SREC_LINE_MAX, or limit of * Reads the given fw file which should have been compiled from an srec
* From array * file. Each record in the fw file will either be a plain data record,
* a start address record, or other records used for plugging.
* *
* Arguments: * Note that data records are expected to be sorted into
* from From addr * ascending address order in the fw file.
* to To addr
* limit Addr of last character in From array that can be copied
* *
* Returns: * Note also that the start address record, originally an S7 record in
* Num characters copied * the srec file, is expected in the fw file to be like a data record but
----------------------------------------------------------------*/ * with a certain address to make it identiable.
int copyline(char *from, char *to, char *limit)
{
int c = 0;
while ((c < SREC_LINE_MAX - 1) && (from + c <= limit) &&
(from[c] != '\n') && (from[c] != '\0')) {
to[c] = from[c];
c++;
}
to[c] = '\0';
return (c < SREC_LINE_MAX - 1) ? c + 1 : c;
}
/*----------------------------------------------------------------
* read_srecfile
* *
* Reads the given srecord file and loads the records into the * Here's the SREC format that the fw should have come from:
* s3xxx arrays. This function can be called repeatedly (once for
* each of a set of files), if necessary. This function performs
* no validation of the data except for the grossest of S-record
* line format checks. Don't forget that these will be DOS files...
* CR/LF at the end of each line.
*
* Here's the SREC format we're dealing with:
* S[37]nnaaaaaaaaddd...dddcc * S[37]nnaaaaaaaaddd...dddcc
* *
* nn - number of bytes starting with the address field * nn - number of bytes starting with the address field
...@@ -902,8 +810,9 @@ int copyline(char *from, char *to, char *limit) ...@@ -902,8 +810,9 @@ int copyline(char *from, char *to, char *limit)
* cc - checksum * cc - checksum
* *
* The S7 record's (there should be only one) address value gets * The S7 record's (there should be only one) address value gets
* saved in startaddr. It's the start execution address used * converted to an S3 record with address of 0xff400000, with the
* for RAM downloads. * start address being stored as a 4 byte data word. That address is
* the start execution address used for RAM downloads.
* *
* The S3 records have a collection of subformats indicated by the * The S3 records have a collection of subformats indicated by the
* value of aaaaaaaa: * value of aaaaaaaa:
...@@ -927,237 +836,124 @@ int copyline(char *from, char *to, char *limit) ...@@ -927,237 +836,124 @@ int copyline(char *from, char *to, char *limit)
* d - (s - 1) little endian words giving the contents of * d - (s - 1) little endian words giving the contents of
* the given info type. * the given info type.
* *
* 0xff400000 - Start address record, data field format:
* aaaaaaaa
* a - Address in load image to plug (little endian)
*
* Arguments: * Arguments:
* rfptr firmware image (s-record structure) in kernel memory * record firmware image (ihex record structure) in kernel memory
* rfsize firmware size in kernel memory
* *
* Returns: * Returns:
* 0 - success * 0 - success
* ~0 - failure (probably an errno) * ~0 - failure (probably an errno)
----------------------------------------------------------------*/ ----------------------------------------------------------------*/
int read_srecfile(char *rfptr, int rfsize) int read_fwfile(const struct ihex_binrec *record)
{ {
int result = 0; int i;
char buf[SREC_LINE_MAX]; int rcnt = 0;
char tmpbuf[30];
s3datarec_t tmprec;
int i, c;
int line = 0;
u16 *tmpinfo; u16 *tmpinfo;
char *endptr = rfptr + rfsize; u16 *ptr16;
u32 *ptr32, len, addr;
pr_debug("Reading S-record file ...\n"); pr_debug("Reading fw file ...\n");
while ((c = copyline(rfptr, buf, endptr)) >= 12) { while (record) {
rfptr = rfptr + c;
line++; rcnt++;
if (buf[0] != 'S') {
printk(KERN_ERR "%d warning: No initial \'S\'\n", line); len = be16_to_cpu(record->len);
return 1; addr = be32_to_cpu(record->addr);
}
if (buf[1] == '7') { /* S7 record, start address */ /* Point into data for different word lengths */
buf[12] = '\0'; ptr32 = (u32 *) record->data;
startaddr = simple_strtoul(buf + 4, NULL, 16); ptr16 = (u16 *) record->data;
pr_debug(" S7 start addr, line=%d "
" addr=0x%08x\n", line, startaddr); /* parse what was an S3 srec and put it in the right array */
continue; switch(addr) {
} else if (buf[1] == '3') { case S3ADDR_START:
/* Ok, it's an S3, parse and put it in the right array */ startaddr = *ptr32;
/* Record Length field (we only want datalen) */ pr_debug(" S7 start addr, record=%d "
memcpy(tmpbuf, buf + S3LEN_TXTOFFSET, S3LEN_TXTLEN); " addr=0x%08x\n",
tmpbuf[S3LEN_TXTLEN] = '\0'; rcnt,
tmprec.len = simple_strtoul(tmpbuf, NULL, 16) - 4 - 1; /* 4=addr, 1=cksum */ startaddr);
/* Address field */ break;
memcpy(tmpbuf, buf + S3ADDR_TXTOFFSET, S3ADDR_TXTLEN);
tmpbuf[S3ADDR_TXTLEN] = '\0';
tmprec.addr = simple_strtoul(tmpbuf, NULL, 16);
/* Checksum field */
tmprec.checksum =
simple_strtoul(buf + strlen(buf) - 2, NULL, 16);
switch (tmprec.addr) {
case S3ADDR_PLUG: case S3ADDR_PLUG:
memcpy(tmpbuf, buf + S3PLUG_ITEMCODE_TXTOFFSET, s3plug[ns3plug].itemcode = *ptr32;
S3PLUG_ITEMCODE_TXTLEN); s3plug[ns3plug].addr = *(ptr32 + 1);
tmpbuf[S3PLUG_ITEMCODE_TXTLEN] = '\0'; s3plug[ns3plug].len = *(ptr32 + 2);
s3plug[ns3plug].itemcode =
simple_strtoul(tmpbuf, NULL, 16); pr_debug(" S3 plugrec, record=%d "
s3plug[ns3plug].itemcode = "itemcode=0x%08x addr=0x%08x len=%d\n",
bswap_32(s3plug[ns3plug].itemcode); rcnt,
memcpy(tmpbuf, buf + S3PLUG_ADDR_TXTOFFSET,
S3PLUG_ADDR_TXTLEN);
tmpbuf[S3PLUG_ADDR_TXTLEN] = '\0';
s3plug[ns3plug].addr =
simple_strtoul(tmpbuf, NULL, 16);
s3plug[ns3plug].addr =
bswap_32(s3plug[ns3plug].addr);
memcpy(tmpbuf, buf + S3PLUG_LEN_TXTOFFSET,
S3PLUG_LEN_TXTLEN);
tmpbuf[S3PLUG_LEN_TXTLEN] = '\0';
s3plug[ns3plug].len =
simple_strtoul(tmpbuf, NULL, 16);
s3plug[ns3plug].len =
bswap_32(s3plug[ns3plug].len);
pr_debug(" S3 plugrec, line=%d "
"itemcode=0x%04x addr=0x%08x len=%d\n",
line,
s3plug[ns3plug].itemcode, s3plug[ns3plug].itemcode,
s3plug[ns3plug].addr, s3plug[ns3plug].addr,
s3plug[ns3plug].len); s3plug[ns3plug].len);
ns3plug++; ns3plug++;
if (ns3plug == S3PLUG_MAX) { if ( ns3plug == S3PLUG_MAX ) {
printk(KERN_ERR printk(KERN_ERR "S3 plugrec limit reached - aborting\n");
"S3 plugrec limit reached - aborting\n");
return 1; return 1;
} }
break; break;
case S3ADDR_CRC: case S3ADDR_CRC:
memcpy(tmpbuf, buf + S3CRC_ADDR_TXTOFFSET, s3crc[ns3crc].addr = *ptr32;
S3CRC_ADDR_TXTLEN); s3crc[ns3crc].len = *(ptr32 + 1);
tmpbuf[S3CRC_ADDR_TXTLEN] = '\0'; s3crc[ns3crc].dowrite = *(ptr32 + 2);
s3crc[ns3crc].addr =
simple_strtoul(tmpbuf, NULL, 16); pr_debug(" S3 crcrec, record=%d "
s3crc[ns3crc].addr =
bswap_32(s3crc[ns3crc].addr);
memcpy(tmpbuf, buf + S3CRC_LEN_TXTOFFSET,
S3CRC_LEN_TXTLEN);
tmpbuf[S3CRC_LEN_TXTLEN] = '\0';
s3crc[ns3crc].len =
simple_strtoul(tmpbuf, NULL, 16);
s3crc[ns3crc].len = bswap_32(s3crc[ns3crc].len);
memcpy(tmpbuf, buf + S3CRC_DOWRITE_TXTOFFSET,
S3CRC_DOWRITE_TXTLEN);
tmpbuf[S3CRC_DOWRITE_TXTLEN] = '\0';
s3crc[ns3crc].dowrite =
simple_strtoul(tmpbuf, NULL, 16);
s3crc[ns3crc].dowrite =
bswap_32(s3crc[ns3crc].dowrite);
pr_debug(" S3 crcrec, line=%d "
"addr=0x%08x len=%d write=0x%08x\n", "addr=0x%08x len=%d write=0x%08x\n",
line, rcnt,
s3crc[ns3crc].addr, s3crc[ns3crc].addr,
s3crc[ns3crc].len, s3crc[ns3crc].len,
s3crc[ns3crc].dowrite); s3crc[ns3crc].dowrite);
ns3crc++; ns3crc++;
if (ns3crc == S3CRC_MAX) { if ( ns3crc == S3CRC_MAX ) {
printk(KERN_ERR printk(KERN_ERR "S3 crcrec limit reached - aborting\n");
"S3 crcrec limit reached - aborting\n");
return 1; return 1;
} }
break; break;
case S3ADDR_INFO: case S3ADDR_INFO:
memcpy(tmpbuf, buf + S3INFO_LEN_TXTOFFSET, s3info[ns3info].len = *ptr16;
S3INFO_LEN_TXTLEN); s3info[ns3info].type = *(ptr16 + 1);
tmpbuf[S3INFO_LEN_TXTLEN] = '\0';
s3info[ns3info].len = pr_debug(" S3 inforec, record=%d "
simple_strtoul(tmpbuf, NULL, 16);
s3info[ns3info].len =
bswap_16(s3info[ns3info].len);
memcpy(tmpbuf, buf + S3INFO_TYPE_TXTOFFSET,
S3INFO_TYPE_TXTLEN);
tmpbuf[S3INFO_TYPE_TXTLEN] = '\0';
s3info[ns3info].type =
simple_strtoul(tmpbuf, NULL, 16);
s3info[ns3info].type =
bswap_16(s3info[ns3info].type);
pr_debug(" S3 inforec, line=%d "
"len=0x%04x type=0x%04x\n", "len=0x%04x type=0x%04x\n",
line, rcnt,
s3info[ns3info].len, s3info[ns3info].len,
s3info[ns3info].type); s3info[ns3info].type);
if (((s3info[ns3info].len - 1) * sizeof(u16)) > if ( ((s3info[ns3info].len - 1) * sizeof(u16)) > sizeof(s3info[ns3info].info) ) {
sizeof(s3info[ns3info].info)) { printk(KERN_ERR " S3 inforec length too long - aborting\n");
printk(KERN_ERR
" S3 inforec length too long - aborting\n");
return 1; return 1;
} }
tmpinfo = tmpinfo = (u16*)&(s3info[ns3info].info.version);
(u16 *) & (s3info[ns3info].info.version);
for (i = 0; i < s3info[ns3info].len - 1; i++) {
memcpy(tmpbuf,
buf + S3INFO_DATA_TXTOFFSET +
(i * 4), 4);
tmpbuf[4] = '\0';
tmpinfo[i] =
simple_strtoul(tmpbuf, NULL, 16);
tmpinfo[i] = bswap_16(tmpinfo[i]);
}
pr_debug(" info="); pr_debug(" info=");
for (i = 0; i < s3info[ns3info].len - 1; i++) { for (i = 0; i < s3info[ns3info].len - 1; i++) {
tmpinfo[i] = *(ptr16 + 2 + i);
pr_debug("%04x ", tmpinfo[i]); pr_debug("%04x ", tmpinfo[i]);
} }
pr_debug("\n"); pr_debug("\n");
ns3info++; ns3info++;
if (ns3info == S3INFO_MAX) { if ( ns3info == S3INFO_MAX ) {
printk(KERN_ERR printk(KERN_ERR "S3 inforec limit reached - aborting\n");
"S3 inforec limit reached - aborting\n");
return 1; return 1;
} }
break; break;
default: /* Data record */ default: /* Data record */
s3data[ns3data].addr = tmprec.addr; s3data[ns3data].addr = addr;
s3data[ns3data].len = tmprec.len; s3data[ns3data].len = len;
s3data[ns3data].checksum = tmprec.checksum; s3data[ns3data].data = (uint8_t *) record->data;
s3data[ns3data].data =
kmalloc(tmprec.len, GFP_KERNEL);
for (i = 0; i < tmprec.len; i++) {
memcpy(tmpbuf,
buf + S3DATA_TXTOFFSET + (i * 2),
2);
tmpbuf[2] = '\0';
s3data[ns3data].data[i] =
simple_strtoul(tmpbuf, NULL, 16);
}
ns3data++; ns3data++;
if (ns3data == S3DATA_MAX) { if ( ns3data == S3DATA_MAX ) {
printk(KERN_ERR printk(KERN_ERR "S3 datarec limit reached - aborting\n");
"S3 datarec limit reached - aborting\n");
return 1; return 1;
} }
break; break;
} }
} else { record = ihex_next_binrec(record);
printk(KERN_WARNING
"%d warning: Unknown S-record detected.\n",
line);
} }
}
return result;
}
/*----------------------------------------------------------------
* s3datarec_compare
*
* Comparison function for sort().
*
* Arguments:
* p1 ptr to the first item
* p2 ptr to the second item
* Returns:
* 0 items are equal
* <0 p1 < p2
* >0 p1 > p2
----------------------------------------------------------------*/
int s3datarec_compare(const void *p1, const void *p2)
{
const s3datarec_t *s1 = p1;
const s3datarec_t *s2 = p2;
if (s1->addr == s2->addr)
return 0; return 0;
if (s1->addr < s2->addr)
return -1;
return 1;
} }
/*---------------------------------------------------------------- /*----------------------------------------------------------------
...@@ -1316,6 +1112,7 @@ int validate_identity(void) ...@@ -1316,6 +1112,7 @@ int validate_identity(void)
{ {
int i; int i;
int result = 1; int result = 1;
int trump = 0;
pr_debug("NIC ID: %#x v%d.%d.%d\n", pr_debug("NIC ID: %#x v%d.%d.%d\n",
nicid.id, nicid.major, nicid.minor, nicid.variant); nicid.id, nicid.major, nicid.minor, nicid.variant);
...@@ -1389,8 +1186,7 @@ int validate_identity(void) ...@@ -1389,8 +1186,7 @@ int validate_identity(void)
(nicid.id != 0x8008)) (nicid.id != 0x8008))
continue; continue;
if (result != 2) trump = 1;
result = 0;
break; break;
case 0x8001: case 0x8001:
pr_debug("name inforec len %d\n", s3info[i].len); pr_debug("name inforec len %d\n", s3info[i].len);
...@@ -1402,5 +1198,6 @@ int validate_identity(void) ...@@ -1402,5 +1198,6 @@ int validate_identity(void)
} }
// walk through // walk through
if (trump && (result != 2)) result = 0;
return result; return result;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment