51 #include <linux/slab.h>
56 #define PRISM2_USB_FWFILE "prism2_ru.fw"
59 #define S3DATA_MAX 5000
60 #define S3PLUG_MAX 200
64 #define S3ADDR_PLUG (0xff000000UL)
65 #define S3ADDR_CRC (0xff100000UL)
66 #define S3ADDR_INFO (0xff200000UL)
67 #define S3ADDR_START (0xff400000UL)
69 #define CHUNKS_MAX 100
71 #define WRITESIZE_MAX 4096
126 static unsigned int ns3data;
130 static unsigned int ns3plug;
134 static unsigned int ns3crc;
138 static unsigned int ns3info;
142 static u32 startaddr;
145 static unsigned int nfchunks;
163 static int prism2_fwapply(
const struct ihex_binrec *rfptr,
166 static int read_fwfile(
const struct ihex_binrec *rfptr);
168 static int mkimage(
struct imgchunk *clist,
unsigned int *
ccnt);
172 static int mkpdrlist(
struct pda *
pda);
174 static int plugimage(
struct imgchunk *fchunk,
unsigned int nfchunks,
177 static int crcimage(
struct imgchunk *fchunk,
unsigned int nfchunks,
178 struct s3crcrec *s3crc,
unsigned int ns3crc);
181 unsigned int nfchunks);
182 static void free_chunks(
struct imgchunk *fchunk,
unsigned int *nfchunks);
184 static void free_srecs(
void);
186 static int validate_identity(
void);
210 if (request_ihex_firmware(&fw_entry,
213 "prism2_usb: Firmware not available, but not essential\n");
215 "prism2_usb: can continue to use card anyway.\n");
249 memset(s3data, 0,
sizeof(s3data));
251 memset(s3plug, 0,
sizeof(s3plug));
253 memset(s3crc, 0,
sizeof(s3crc));
255 memset(s3info, 0,
sizeof(s3info));
259 memset(fchunk, 0,
sizeof(fchunk));
260 memset(&nicid, 0,
sizeof(nicid));
261 memset(&rfid, 0,
sizeof(rfid));
262 memset(&macid, 0,
sizeof(macid));
263 memset(&priid, 0,
sizeof(priid));
277 if (read_cardpda(&
pda, wlandev)) {
283 memset(&getmsg, 0,
sizeof(getmsg));
285 getmsg.msglen =
sizeof(getmsg);
297 data = (
u32 *) item->data;
305 priid.
role = *data++;
312 result = read_fwfile(rfptr);
318 result = validate_identity();
325 if (startaddr == 0x00000000) {
331 result = mkimage(fchunk, &nfchunks);
334 result = plugimage(fchunk, nfchunks, s3plug, ns3plug, &
pda);
341 if (crcimage(fchunk, nfchunks, s3crc, ns3crc)) {
347 result = writeimage(wlandev, fchunk, nfchunks);
354 free_chunks(fchunk, &nfchunks);
379 static int crcimage(
struct imgchunk *fchunk,
unsigned int nfchunks,
380 struct s3crcrec *s3crc,
unsigned int ns3crc)
392 for (i = 0; i < ns3crc; i++) {
393 if (!s3crc[i].dowrite)
395 crcstart = s3crc[
i].
addr;
398 for (c = 0; c < nfchunks; c++) {
399 cstart = fchunk[
c].
addr;
409 if (crcstart - 2 >= cstart && crcstart < cend)
414 "Failed to find chunk for "
415 "crcrec[%d], addr=0x%06x len=%d , "
417 i, s3crc[i].
addr, s3crc[i].len);
423 chunkoff = crcstart - cstart - 2;
424 dest = fchunk[
c].
data + chunkoff;
443 static void free_chunks(
struct imgchunk *fchunk,
unsigned int *nfchunks)
446 for (i = 0; i < *nfchunks; i++)
447 kfree(fchunk[i].data);
450 memset(fchunk, 0,
sizeof(*fchunk));
465 static void free_srecs(
void)
468 memset(s3data, 0,
sizeof(s3data));
470 memset(s3plug, 0,
sizeof(s3plug));
472 memset(s3crc, 0,
sizeof(s3crc));
474 memset(s3info, 0,
sizeof(s3info));
492 static int mkimage(
struct imgchunk *clist,
unsigned int *
ccnt)
509 for (i = 0; i < ns3data; i++) {
510 if (s3data[i].
addr == nextaddr) {
512 clist[currchunk].
len += s3data[
i].len;
513 nextaddr += s3data[
i].len;
517 currchunk = *ccnt - 1;
518 clist[currchunk].
addr = s3data[
i].addr;
519 clist[currchunk].
len = s3data[
i].len;
520 nextaddr = s3data[
i].addr + s3data[
i].len;
523 for (j = 0; j < ns3crc; j++) {
524 if (s3crc[j].dowrite &&
525 s3crc[j].
addr == clist[currchunk].
addr) {
526 clist[currchunk].
addr -= 2;
527 clist[currchunk].
len += 2;
537 for (i = 0; i < *ccnt; i++) {
539 if (clist[i].data ==
NULL) {
541 "failed to allocate image space, exitting.\n");
544 pr_debug(
"chunk[%d]: addr=0x%06x len=%d\n",
545 i, clist[i].
addr, clist[i].len);
549 for (i = 0; i < ns3data; i++) {
550 s3start = s3data[
i].addr;
551 s3end = s3start + s3data[
i].len - 1;
552 for (j = 0; j < *ccnt; j++) {
553 cstart = clist[
j].
addr;
554 cend = cstart + clist[
j].
len - 1;
555 if (s3start >= cstart && s3end <= cend)
558 if (((
unsigned int)j) >= (*ccnt)) {
560 "s3rec(a=0x%06x,l=%d), no chunk match, exiting.\n",
561 s3start, s3data[i].len);
564 coffset = s3start - cstart;
565 memcpy(clist[j].data + coffset, s3data[i].data, s3data[i].len);
585 static int mkpdrlist(
struct pda *
pda)
631 "no end record found or invalid lengths in "
632 "PDR data, exiting. %x %d\n", curroff, pda->
nrec);
659 static int plugimage(
struct imgchunk *fchunk,
unsigned int nfchunks,
660 struct s3plugrec *s3plug,
unsigned int ns3plug,
struct pda *pda)
674 for (i = 0; i < ns3plug; i++) {
675 pstart = s3plug[
i].
addr;
678 if (s3plug[i].itemcode != 0xffffffffUL) {
679 for (j = 0; j < pda->
nrec; j++) {
680 if (s3plug[i].itemcode ==
687 if (j >= pda->
nrec && j != -1) {
689 "warning: Failed to find PDR for "
690 "plugrec 0x%04x.\n", s3plug[i].itemcode);
708 "error: Plug vs. PDR len mismatch for "
709 "plugrec 0x%04x, abort plugging.\n",
716 for (c = 0; c < nfchunks; c++) {
717 cstart = fchunk[
c].
addr;
719 if (pstart >= cstart && pend <= cend)
724 "error: Failed to find image chunk for "
725 "plugrec 0x%04x.\n", s3plug[i].itemcode);
731 chunkoff = pstart - cstart;
732 dest = fchunk[
c].
data + chunkoff;
733 pr_debug(
"Plugging item 0x%04x @ 0x%06x, len=%d, "
734 "cnum=%d coff=0x%06x\n",
735 s3plug[i].itemcode, pstart, s3plug[i].len,
739 memset(dest, 0, s3plug[i].len);
767 static int read_cardpda(
struct pda *pda,
wlandevice_t *wlandev)
780 msg.resultcode.len =
sizeof(
u32);
788 result = mkpdrlist(pda);
882 pr_debug(
" S7 start addr, record=%d "
889 s3plug[ns3plug].
addr = *(ptr32 + 1);
890 s3plug[ns3plug].
len = *(ptr32 + 2);
893 "itemcode=0x%08x addr=0x%08x len=%d\n",
895 s3plug[ns3plug].itemcode,
896 s3plug[ns3plug].addr,
897 s3plug[ns3plug].len);
906 s3crc[ns3crc].
addr = *ptr32;
907 s3crc[ns3crc].
len = *(ptr32 + 1);
908 s3crc[ns3crc].
dowrite = *(ptr32 + 2);
911 "addr=0x%08x len=%d write=0x%08x\n",
915 s3crc[ns3crc].dowrite);
923 s3info[ns3info].len = *ptr16;
924 s3info[ns3info].type = *(ptr16 + 1);
927 "len=0x%04x type=0x%04x\n",
930 s3info[ns3info].
type);
931 if (((s3info[ns3info].len - 1) *
sizeof(
u16)) >
sizeof(s3info[ns3info].
info)) {
936 tmpinfo = (
u16 *)&(s3info[ns3info].info.version);
938 for (i = 0; i < s3info[ns3info].len - 1; i++) {
939 tmpinfo[
i] = *(ptr16 + 2 +
i);
951 s3data[ns3data].addr =
addr;
952 s3data[ns3data].len = len;
961 record = ihex_next_binrec(record);
982 unsigned int nfchunks)
990 unsigned int nwrites;
997 if (!rstmsg || !rwrmsg) {
1001 "writeimage: no memory for firmware download, "
1002 "aborting download\n");
1007 memset(rstmsg, 0,
sizeof(*rstmsg));
1010 rstmsg->
msglen =
sizeof(*rstmsg);
1021 memset(rwrmsg, 0,
sizeof(*rwrmsg));
1024 rwrmsg->
msglen =
sizeof(*rwrmsg);
1039 pr_debug(
"Sending dl_state(enable) message.\n");
1046 "writeimage state enable failed w/ result=%d, "
1047 "aborting download\n", result);
1053 "writeimage()->xxxdl_state msg indicates failure, "
1054 "w/ resultcode=%d, aborting download.\n", resultcode);
1060 for (i = 0; i < nfchunks; i++) {
1064 for (j = 0; j < nwrites; j++) {
1072 currdaddr = fchunk[
i].
addr + curroff;
1077 fchunk[i].
data + curroff, currlen);
1081 (
"Sending xxxdl_write message addr=%06x len=%d.\n",
1082 currdaddr, currlen);
1089 "writeimage chunk write failed w/ result=%d, "
1090 "aborting download\n", result);
1096 "writeimage()->xxxdl_write msg indicates failure, "
1097 "w/ resultcode=%d, aborting download.\n",
1107 pr_debug(
"Sending dl_state(disable) message.\n");
1114 "writeimage state disable failed w/ result=%d, "
1115 "aborting download\n", result);
1121 "writeimage()->xxxdl_state msg indicates failure, "
1122 "w/ resultcode=%d, aborting download.\n", resultcode);
1133 static int validate_identity(
void)
1139 pr_debug(
"NIC ID: %#x v%d.%d.%d\n",
1141 pr_debug(
"MFI ID: %#x v%d %d->%d\n",
1143 pr_debug(
"CFI ID: %#x v%d %d->%d\n",
1145 pr_debug(
"PRI ID: %#x v%d %d->%d\n",
1148 for (i = 0; i < ns3info; i++) {
1149 switch (s3info[i].
type) {
1151 pr_debug(
"Version: ID %#x %d.%d.%d\n",
1152 s3info[i].info.version.id,
1153 s3info[i].info.version.major,
1154 s3info[i].info.version.minor,
1155 s3info[i].info.version.variant);
1158 pr_debug(
"Compat: Role %#x Id %#x v%d %d->%d\n",
1159 s3info[i].info.compat.role,
1160 s3info[i].info.compat.id,
1161 s3info[i].info.compat.variant,
1162 s3info[i].info.compat.bottom,
1163 s3info[i].info.compat.top);
1166 if ((s3info[i].info.compat.role == 1) &&
1167 (s3info[i].info.compat.id == 2)) {
1168 if (s3info[i].info.compat.variant !=
1175 if ((s3info[i].info.compat.role == 1) &&
1176 (s3info[i].info.compat.id == 3)) {
1177 if ((s3info[i].info.compat.bottom > priid.
top)
1178 || (s3info[i].info.compat.top <
1184 if ((s3info[i].info.compat.role == 1) &&
1185 (s3info[i].info.compat.id == 4)) {
1191 pr_debug(
"Seq: %#x\n", s3info[i].info.buildseq);
1195 pr_debug(
"Platform: ID %#x %d.%d.%d\n",
1196 s3info[i].info.version.id,
1197 s3info[i].info.version.major,
1198 s3info[i].info.version.minor,
1199 s3info[i].info.version.variant);
1201 if (nicid.
id != s3info[i].info.version.id)
1203 if (nicid.
major != s3info[i].info.version.major)
1205 if (nicid.
minor != s3info[i].info.version.minor)
1207 if ((nicid.
variant != s3info[i].info.version.variant) &&
1208 (nicid.
id != 0x8008))
1214 pr_debug(
"name inforec len %d\n", s3info[i].len);
1218 pr_debug(
"Unknown inforec type %d\n", s3info[i].type);
1223 if (trump && (result != 2))