1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51#include <linux/ihex.h>
52#include <linux/slab.h>
53
54
55
56
57#define PRISM2_USB_FWFILE "prism2_ru.fw"
58MODULE_FIRMWARE(PRISM2_USB_FWFILE);
59
60#define S3DATA_MAX 5000
61#define S3PLUG_MAX 200
62#define S3CRC_MAX 200
63#define S3INFO_MAX 50
64
65#define S3ADDR_PLUG (0xff000000UL)
66#define S3ADDR_CRC (0xff100000UL)
67#define S3ADDR_INFO (0xff200000UL)
68#define S3ADDR_START (0xff400000UL)
69
70#define CHUNKS_MAX 100
71
72#define WRITESIZE_MAX 4096
73
74
75
76
77struct s3datarec {
78 u32 len;
79 u32 addr;
80 u8 checksum;
81 u8 *data;
82};
83
84struct s3plugrec {
85 u32 itemcode;
86 u32 addr;
87 u32 len;
88};
89
90struct s3crcrec {
91 u32 addr;
92 u32 len;
93 unsigned int dowrite;
94};
95
96struct s3inforec {
97 u16 len;
98 u16 type;
99 union {
100 struct hfa384x_compident version;
101 struct hfa384x_caplevel compat;
102 u16 buildseq;
103 struct hfa384x_compident platform;
104 } info;
105};
106
107struct pda {
108 u8 buf[HFA384x_PDA_LEN_MAX];
109 struct hfa384x_pdrec *rec[HFA384x_PDA_RECS_MAX];
110 unsigned int nrec;
111};
112
113struct imgchunk {
114 u32 addr;
115 u32 len;
116 u16 crc;
117 u8 *data;
118};
119
120
121
122
123
124
125
126
127static unsigned int ns3data;
128static struct s3datarec *s3data;
129
130
131static unsigned int ns3plug;
132static struct s3plugrec s3plug[S3PLUG_MAX];
133
134
135static unsigned int ns3crc;
136static struct s3crcrec s3crc[S3CRC_MAX];
137
138
139static unsigned int ns3info;
140static struct s3inforec s3info[S3INFO_MAX];
141
142
143static u32 startaddr;
144
145
146static unsigned int nfchunks;
147static struct imgchunk fchunk[CHUNKS_MAX];
148
149
150
151
152
153
154
155static struct pda pda;
156static struct hfa384x_compident nicid;
157static struct hfa384x_caplevel rfid;
158static struct hfa384x_caplevel macid;
159static struct hfa384x_caplevel priid;
160
161
162
163
164static int prism2_fwapply(const struct ihex_binrec *rfptr,
165 struct wlandevice *wlandev);
166
167static int read_fwfile(const struct ihex_binrec *rfptr);
168
169static int mkimage(struct imgchunk *clist, unsigned int *ccnt);
170
171static int read_cardpda(struct pda *pda, struct wlandevice *wlandev);
172
173static int mkpdrlist(struct pda *pda);
174
175static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks,
176 struct s3plugrec *s3plug, unsigned int ns3plug,
177 struct pda *pda);
178
179static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks,
180 struct s3crcrec *s3crc, unsigned int ns3crc);
181
182static int writeimage(struct wlandevice *wlandev, struct imgchunk *fchunk,
183 unsigned int nfchunks);
184
185static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks);
186
187static void free_srecs(void);
188
189static int validate_identity(void);
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208static int prism2_fwtry(struct usb_device *udev, struct wlandevice *wlandev)
209{
210 const struct firmware *fw_entry = NULL;
211
212 netdev_info(wlandev->netdev, "prism2_usb: Checking for firmware %s\n",
213 PRISM2_USB_FWFILE);
214 if (request_ihex_firmware(&fw_entry,
215 PRISM2_USB_FWFILE, &udev->dev) != 0) {
216 netdev_info(wlandev->netdev,
217 "prism2_usb: Firmware not available, but not essential\n");
218 netdev_info(wlandev->netdev,
219 "prism2_usb: can continue to use card anyway.\n");
220 return 1;
221 }
222
223 netdev_info(wlandev->netdev,
224 "prism2_usb: %s will be processed, size %zu\n",
225 PRISM2_USB_FWFILE, fw_entry->size);
226 prism2_fwapply((const struct ihex_binrec *)fw_entry->data, wlandev);
227
228 release_firmware(fw_entry);
229 return 0;
230}
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246static int prism2_fwapply(const struct ihex_binrec *rfptr,
247 struct wlandevice *wlandev)
248{
249 signed int result = 0;
250 struct p80211msg_dot11req_mibget getmsg;
251 struct p80211itemd *item;
252 u32 *data;
253
254
255 ns3data = 0;
256 s3data = kcalloc(S3DATA_MAX, sizeof(*s3data), GFP_KERNEL);
257 if (!s3data) {
258 result = -ENOMEM;
259 goto out;
260 }
261
262 ns3plug = 0;
263 memset(s3plug, 0, sizeof(s3plug));
264 ns3crc = 0;
265 memset(s3crc, 0, sizeof(s3crc));
266 ns3info = 0;
267 memset(s3info, 0, sizeof(s3info));
268 startaddr = 0;
269
270 nfchunks = 0;
271 memset(fchunk, 0, sizeof(fchunk));
272 memset(&nicid, 0, sizeof(nicid));
273 memset(&rfid, 0, sizeof(rfid));
274 memset(&macid, 0, sizeof(macid));
275 memset(&priid, 0, sizeof(priid));
276
277
278 memset(&pda, 0, sizeof(pda));
279 pda.rec[0] = (struct hfa384x_pdrec *)pda.buf;
280 pda.rec[0]->len = cpu_to_le16(2);
281 pda.rec[0]->code = cpu_to_le16(HFA384x_PDR_END_OF_PDA);
282 pda.nrec = 1;
283
284
285
286 prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
287
288
289 if (read_cardpda(&pda, wlandev)) {
290 netdev_err(wlandev->netdev, "load_cardpda failed, exiting.\n");
291 result = 1;
292 goto out;
293 }
294
295
296 memset(&getmsg, 0, sizeof(getmsg));
297 getmsg.msgcode = DIDmsg_dot11req_mibget;
298 getmsg.msglen = sizeof(getmsg);
299 strcpy(getmsg.devname, wlandev->name);
300
301 getmsg.mibattribute.did = DIDmsg_dot11req_mibget_mibattribute;
302 getmsg.mibattribute.status = P80211ENUM_msgitem_status_data_ok;
303 getmsg.resultcode.did = DIDmsg_dot11req_mibget_resultcode;
304 getmsg.resultcode.status = P80211ENUM_msgitem_status_no_value;
305
306 item = (struct p80211itemd *)getmsg.mibattribute.data;
307 item->did = DIDmib_p2_p2NIC_p2PRISupRange;
308 item->status = P80211ENUM_msgitem_status_no_value;
309
310 data = (u32 *)item->data;
311
312
313 prism2mgmt_mibset_mibget(wlandev, &getmsg);
314 if (getmsg.resultcode.data != P80211ENUM_resultcode_success)
315 netdev_err(wlandev->netdev, "Couldn't fetch PRI-SUP info\n");
316
317
318 priid.role = *data++;
319 priid.id = *data++;
320 priid.variant = *data++;
321 priid.bottom = *data++;
322 priid.top = *data++;
323
324
325 result = read_fwfile(rfptr);
326 if (result) {
327 netdev_err(wlandev->netdev,
328 "Failed to read the data exiting.\n");
329 goto out;
330 }
331
332 result = validate_identity();
333 if (result) {
334 netdev_err(wlandev->netdev, "Incompatible firmware image.\n");
335 goto out;
336 }
337
338 if (startaddr == 0x00000000) {
339 netdev_err(wlandev->netdev,
340 "Can't RAM download a Flash image!\n");
341 result = 1;
342 goto out;
343 }
344
345
346 result = mkimage(fchunk, &nfchunks);
347 if (result) {
348 netdev_err(wlandev->netdev, "Failed to make image chunk.\n");
349 goto free_chunks;
350 }
351
352
353 result = plugimage(fchunk, nfchunks, s3plug, ns3plug, &pda);
354 if (result) {
355 netdev_err(wlandev->netdev, "Failed to plug data.\n");
356 goto free_chunks;
357 }
358
359
360 result = crcimage(fchunk, nfchunks, s3crc, ns3crc);
361 if (result) {
362 netdev_err(wlandev->netdev, "Failed to insert all CRCs\n");
363 goto free_chunks;
364 }
365
366
367 result = writeimage(wlandev, fchunk, nfchunks);
368 if (result) {
369 netdev_err(wlandev->netdev, "Failed to ramwrite image data.\n");
370 goto free_chunks;
371 }
372
373 netdev_info(wlandev->netdev, "prism2_usb: firmware loading finished.\n");
374
375free_chunks:
376
377 free_chunks(fchunk, &nfchunks);
378 free_srecs();
379
380out:
381 return result;
382}
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks,
403 struct s3crcrec *s3crc, unsigned int ns3crc)
404{
405 int result = 0;
406 int i;
407 int c;
408 u32 crcstart;
409 u32 crcend;
410 u32 cstart = 0;
411 u32 cend;
412 u8 *dest;
413 u32 chunkoff;
414
415 for (i = 0; i < ns3crc; i++) {
416 if (!s3crc[i].dowrite)
417 continue;
418 crcstart = s3crc[i].addr;
419 crcend = s3crc[i].addr + s3crc[i].len;
420
421 for (c = 0; c < nfchunks; c++) {
422 cstart = fchunk[c].addr;
423 cend = fchunk[c].addr + fchunk[c].len;
424
425
426
427
428
429
430
431
432 if (crcstart - 2 >= cstart && crcstart < cend)
433 break;
434 }
435 if (c >= nfchunks) {
436 pr_err("Failed to find chunk for crcrec[%d], addr=0x%06x len=%d , aborting crc.\n",
437 i, s3crc[i].addr, s3crc[i].len);
438 return 1;
439 }
440
441
442 pr_debug("Adding crc @ 0x%06x\n", s3crc[i].addr - 2);
443 chunkoff = crcstart - cstart - 2;
444 dest = fchunk[c].data + chunkoff;
445 *dest = 0xde;
446 *(dest + 1) = 0xc0;
447 }
448 return result;
449}
450
451
452
453
454
455
456
457
458
459
460
461
462
463static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks)
464{
465 int i;
466
467 for (i = 0; i < *nfchunks; i++)
468 kfree(fchunk[i].data);
469
470 *nfchunks = 0;
471 memset(fchunk, 0, sizeof(*fchunk));
472}
473
474
475
476
477
478
479
480
481
482
483
484
485
486static void free_srecs(void)
487{
488 ns3data = 0;
489 kfree(s3data);
490 ns3plug = 0;
491 memset(s3plug, 0, sizeof(s3plug));
492 ns3crc = 0;
493 memset(s3crc, 0, sizeof(s3crc));
494 ns3info = 0;
495 memset(s3info, 0, sizeof(s3info));
496 startaddr = 0;
497}
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514static int mkimage(struct imgchunk *clist, unsigned int *ccnt)
515{
516 int result = 0;
517 int i;
518 int j;
519 int currchunk = 0;
520 u32 nextaddr = 0;
521 u32 s3start;
522 u32 s3end;
523 u32 cstart = 0;
524 u32 cend;
525 u32 coffset;
526
527
528 *ccnt = 0;
529
530
531 for (i = 0; i < ns3data; i++) {
532 if (s3data[i].addr == nextaddr) {
533
534 clist[currchunk].len += s3data[i].len;
535 nextaddr += s3data[i].len;
536 } else {
537
538 (*ccnt)++;
539 currchunk = *ccnt - 1;
540 clist[currchunk].addr = s3data[i].addr;
541 clist[currchunk].len = s3data[i].len;
542 nextaddr = s3data[i].addr + s3data[i].len;
543
544
545 for (j = 0; j < ns3crc; j++) {
546 if (s3crc[j].dowrite &&
547 s3crc[j].addr == clist[currchunk].addr) {
548 clist[currchunk].addr -= 2;
549 clist[currchunk].len += 2;
550 }
551 }
552 }
553 }
554
555
556
557
558
559 for (i = 0; i < *ccnt; i++) {
560 clist[i].data = kzalloc(clist[i].len, GFP_KERNEL);
561 if (!clist[i].data) {
562 pr_err("failed to allocate image space, exitting.\n");
563 return 1;
564 }
565 pr_debug("chunk[%d]: addr=0x%06x len=%d\n",
566 i, clist[i].addr, clist[i].len);
567 }
568
569
570 for (i = 0; i < ns3data; i++) {
571 s3start = s3data[i].addr;
572 s3end = s3start + s3data[i].len - 1;
573 for (j = 0; j < *ccnt; j++) {
574 cstart = clist[j].addr;
575 cend = cstart + clist[j].len - 1;
576 if (s3start >= cstart && s3end <= cend)
577 break;
578 }
579 if (((unsigned int)j) >= (*ccnt)) {
580 pr_err("s3rec(a=0x%06x,l=%d), no chunk match, exiting.\n",
581 s3start, s3data[i].len);
582 return 1;
583 }
584 coffset = s3start - cstart;
585 memcpy(clist[j].data + coffset, s3data[i].data, s3data[i].len);
586 }
587
588 return result;
589}
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606static int mkpdrlist(struct pda *pda)
607{
608 __le16 *pda16 = (__le16 *)pda->buf;
609 int curroff;
610
611 pda->nrec = 0;
612 curroff = 0;
613 while (curroff < (HFA384x_PDA_LEN_MAX / 2 - 1) &&
614 le16_to_cpu(pda16[curroff + 1]) != HFA384x_PDR_END_OF_PDA) {
615 pda->rec[pda->nrec] = (struct hfa384x_pdrec *)&pda16[curroff];
616
617 if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
618 HFA384x_PDR_NICID) {
619 memcpy(&nicid, &pda->rec[pda->nrec]->data.nicid,
620 sizeof(nicid));
621 le16_to_cpus(&nicid.id);
622 le16_to_cpus(&nicid.variant);
623 le16_to_cpus(&nicid.major);
624 le16_to_cpus(&nicid.minor);
625 }
626 if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
627 HFA384x_PDR_MFISUPRANGE) {
628 memcpy(&rfid, &pda->rec[pda->nrec]->data.mfisuprange,
629 sizeof(rfid));
630 le16_to_cpus(&rfid.id);
631 le16_to_cpus(&rfid.variant);
632 le16_to_cpus(&rfid.bottom);
633 le16_to_cpus(&rfid.top);
634 }
635 if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
636 HFA384x_PDR_CFISUPRANGE) {
637 memcpy(&macid, &pda->rec[pda->nrec]->data.cfisuprange,
638 sizeof(macid));
639 le16_to_cpus(&macid.id);
640 le16_to_cpus(&macid.variant);
641 le16_to_cpus(&macid.bottom);
642 le16_to_cpus(&macid.top);
643 }
644
645 (pda->nrec)++;
646 curroff += le16_to_cpu(pda16[curroff]) + 1;
647 }
648 if (curroff >= (HFA384x_PDA_LEN_MAX / 2 - 1)) {
649 pr_err("no end record found or invalid lengths in PDR data, exiting. %x %d\n",
650 curroff, pda->nrec);
651 return 1;
652 }
653 pda->rec[pda->nrec] = (struct hfa384x_pdrec *)&pda16[curroff];
654 (pda->nrec)++;
655 return 0;
656}
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks,
677 struct s3plugrec *s3plug, unsigned int ns3plug,
678 struct pda *pda)
679{
680 int result = 0;
681 int i;
682 int j;
683 int c;
684 u32 pstart;
685 u32 pend;
686 u32 cstart = 0;
687 u32 cend;
688 u32 chunkoff;
689 u8 *dest;
690
691
692 for (i = 0; i < ns3plug; i++) {
693 pstart = s3plug[i].addr;
694 pend = s3plug[i].addr + s3plug[i].len;
695
696 if (s3plug[i].itemcode != 0xffffffffUL) {
697 for (j = 0; j < pda->nrec; j++) {
698 if (s3plug[i].itemcode ==
699 le16_to_cpu(pda->rec[j]->code))
700 break;
701 }
702 } else {
703 j = -1;
704 }
705 if (j >= pda->nrec && j != -1) {
706 pr_warn("warning: Failed to find PDR for plugrec 0x%04x.\n",
707 s3plug[i].itemcode);
708 continue;
709#if 0
710
711
712
713
714
715
716
717 result = 1;
718 continue;
719#endif
720 }
721
722
723 if (j != -1 && s3plug[i].len < le16_to_cpu(pda->rec[j]->len)) {
724 pr_err("error: Plug vs. PDR len mismatch for plugrec 0x%04x, abort plugging.\n",
725 s3plug[i].itemcode);
726 result = 1;
727 continue;
728 }
729
730
731
732
733
734 for (c = 0; c < nfchunks; c++) {
735 cstart = fchunk[c].addr;
736 cend = fchunk[c].addr + fchunk[c].len;
737 if (pstart >= cstart && pend <= cend)
738 break;
739 }
740 if (c >= nfchunks) {
741 pr_err("error: Failed to find image chunk for plugrec 0x%04x.\n",
742 s3plug[i].itemcode);
743 result = 1;
744 continue;
745 }
746
747
748 chunkoff = pstart - cstart;
749 dest = fchunk[c].data + chunkoff;
750 pr_debug("Plugging item 0x%04x @ 0x%06x, len=%d, cnum=%d coff=0x%06x\n",
751 s3plug[i].itemcode, pstart, s3plug[i].len,
752 c, chunkoff);
753
754 if (j == -1) {
755 memset(dest, 0, s3plug[i].len);
756 strncpy(dest, PRISM2_USB_FWFILE, s3plug[i].len - 1);
757 } else {
758 memcpy(dest, &pda->rec[j]->data, s3plug[i].len);
759 }
760 }
761 return result;
762}
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783static int read_cardpda(struct pda *pda, struct wlandevice *wlandev)
784{
785 int result = 0;
786 struct p80211msg_p2req_readpda *msg;
787
788 msg = kzalloc(sizeof(*msg), GFP_KERNEL);
789 if (!msg)
790 return -ENOMEM;
791
792
793 msg->msgcode = DIDmsg_p2req_readpda;
794 msg->msglen = sizeof(msg);
795 strcpy(msg->devname, wlandev->name);
796 msg->pda.did = DIDmsg_p2req_readpda_pda;
797 msg->pda.len = HFA384x_PDA_LEN_MAX;
798 msg->pda.status = P80211ENUM_msgitem_status_no_value;
799 msg->resultcode.did = DIDmsg_p2req_readpda_resultcode;
800 msg->resultcode.len = sizeof(u32);
801 msg->resultcode.status = P80211ENUM_msgitem_status_no_value;
802
803 if (prism2mgmt_readpda(wlandev, msg) != 0) {
804
805 result = -1;
806 } else if (msg->resultcode.data == P80211ENUM_resultcode_success) {
807 memcpy(pda->buf, msg->pda.data, HFA384x_PDA_LEN_MAX);
808 result = mkpdrlist(pda);
809 } else {
810
811 result = -1;
812 }
813
814 kfree(msg);
815 return result;
816}
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879static int read_fwfile(const struct ihex_binrec *record)
880{
881 int i;
882 int rcnt = 0;
883 u16 *tmpinfo;
884 u16 *ptr16;
885 u32 *ptr32, len, addr;
886
887 pr_debug("Reading fw file ...\n");
888
889 while (record) {
890 rcnt++;
891
892 len = be16_to_cpu(record->len);
893 addr = be32_to_cpu(record->addr);
894
895
896 ptr32 = (u32 *)record->data;
897 ptr16 = (u16 *)record->data;
898
899
900 switch (addr) {
901 case S3ADDR_START:
902 startaddr = *ptr32;
903 pr_debug(" S7 start addr, record=%d addr=0x%08x\n",
904 rcnt,
905 startaddr);
906 break;
907 case S3ADDR_PLUG:
908 s3plug[ns3plug].itemcode = *ptr32;
909 s3plug[ns3plug].addr = *(ptr32 + 1);
910 s3plug[ns3plug].len = *(ptr32 + 2);
911
912 pr_debug(" S3 plugrec, record=%d itemcode=0x%08x addr=0x%08x len=%d\n",
913 rcnt,
914 s3plug[ns3plug].itemcode,
915 s3plug[ns3plug].addr,
916 s3plug[ns3plug].len);
917
918 ns3plug++;
919 if (ns3plug == S3PLUG_MAX) {
920 pr_err("S3 plugrec limit reached - aborting\n");
921 return 1;
922 }
923 break;
924 case S3ADDR_CRC:
925 s3crc[ns3crc].addr = *ptr32;
926 s3crc[ns3crc].len = *(ptr32 + 1);
927 s3crc[ns3crc].dowrite = *(ptr32 + 2);
928
929 pr_debug(" S3 crcrec, record=%d addr=0x%08x len=%d write=0x%08x\n",
930 rcnt,
931 s3crc[ns3crc].addr,
932 s3crc[ns3crc].len,
933 s3crc[ns3crc].dowrite);
934 ns3crc++;
935 if (ns3crc == S3CRC_MAX) {
936 pr_err("S3 crcrec limit reached - aborting\n");
937 return 1;
938 }
939 break;
940 case S3ADDR_INFO:
941 s3info[ns3info].len = *ptr16;
942 s3info[ns3info].type = *(ptr16 + 1);
943
944 pr_debug(" S3 inforec, record=%d len=0x%04x type=0x%04x\n",
945 rcnt,
946 s3info[ns3info].len,
947 s3info[ns3info].type);
948 if (((s3info[ns3info].len - 1) * sizeof(u16)) >
949 sizeof(s3info[ns3info].info)) {
950 pr_err("S3 inforec length too long - aborting\n");
951 return 1;
952 }
953
954 tmpinfo = (u16 *)&s3info[ns3info].info.version;
955 pr_debug(" info=");
956 for (i = 0; i < s3info[ns3info].len - 1; i++) {
957 tmpinfo[i] = *(ptr16 + 2 + i);
958 pr_debug("%04x ", tmpinfo[i]);
959 }
960 pr_debug("\n");
961
962 ns3info++;
963 if (ns3info == S3INFO_MAX) {
964 pr_err("S3 inforec limit reached - aborting\n");
965 return 1;
966 }
967 break;
968 default:
969 s3data[ns3data].addr = addr;
970 s3data[ns3data].len = len;
971 s3data[ns3data].data = (uint8_t *)record->data;
972 ns3data++;
973 if (ns3data == S3DATA_MAX) {
974 pr_err("S3 datarec limit reached - aborting\n");
975 return 1;
976 }
977 break;
978 }
979 record = ihex_next_binrec(record);
980 }
981 return 0;
982}
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000static int writeimage(struct wlandevice *wlandev, struct imgchunk *fchunk,
1001 unsigned int nfchunks)
1002{
1003 int result = 0;
1004 struct p80211msg_p2req_ramdl_state *rstmsg;
1005 struct p80211msg_p2req_ramdl_write *rwrmsg;
1006 u32 resultcode;
1007 int i;
1008 int j;
1009 unsigned int nwrites;
1010 u32 curroff;
1011 u32 currlen;
1012 u32 currdaddr;
1013
1014 rstmsg = kzalloc(sizeof(*rstmsg), GFP_KERNEL);
1015 rwrmsg = kzalloc(sizeof(*rwrmsg), GFP_KERNEL);
1016 if (!rstmsg || !rwrmsg) {
1017 kfree(rstmsg);
1018 kfree(rwrmsg);
1019 netdev_err(wlandev->netdev,
1020 "%s: no memory for firmware download, aborting download\n",
1021 __func__);
1022 return -ENOMEM;
1023 }
1024
1025
1026 strcpy(rstmsg->devname, wlandev->name);
1027 rstmsg->msgcode = DIDmsg_p2req_ramdl_state;
1028 rstmsg->msglen = sizeof(*rstmsg);
1029 rstmsg->enable.did = DIDmsg_p2req_ramdl_state_enable;
1030 rstmsg->exeaddr.did = DIDmsg_p2req_ramdl_state_exeaddr;
1031 rstmsg->resultcode.did = DIDmsg_p2req_ramdl_state_resultcode;
1032 rstmsg->enable.status = P80211ENUM_msgitem_status_data_ok;
1033 rstmsg->exeaddr.status = P80211ENUM_msgitem_status_data_ok;
1034 rstmsg->resultcode.status = P80211ENUM_msgitem_status_no_value;
1035 rstmsg->enable.len = sizeof(u32);
1036 rstmsg->exeaddr.len = sizeof(u32);
1037 rstmsg->resultcode.len = sizeof(u32);
1038
1039 strcpy(rwrmsg->devname, wlandev->name);
1040 rwrmsg->msgcode = DIDmsg_p2req_ramdl_write;
1041 rwrmsg->msglen = sizeof(*rwrmsg);
1042 rwrmsg->addr.did = DIDmsg_p2req_ramdl_write_addr;
1043 rwrmsg->len.did = DIDmsg_p2req_ramdl_write_len;
1044 rwrmsg->data.did = DIDmsg_p2req_ramdl_write_data;
1045 rwrmsg->resultcode.did = DIDmsg_p2req_ramdl_write_resultcode;
1046 rwrmsg->addr.status = P80211ENUM_msgitem_status_data_ok;
1047 rwrmsg->len.status = P80211ENUM_msgitem_status_data_ok;
1048 rwrmsg->data.status = P80211ENUM_msgitem_status_data_ok;
1049 rwrmsg->resultcode.status = P80211ENUM_msgitem_status_no_value;
1050 rwrmsg->addr.len = sizeof(u32);
1051 rwrmsg->len.len = sizeof(u32);
1052 rwrmsg->data.len = WRITESIZE_MAX;
1053 rwrmsg->resultcode.len = sizeof(u32);
1054
1055
1056 pr_debug("Sending dl_state(enable) message.\n");
1057 rstmsg->enable.data = P80211ENUM_truth_true;
1058 rstmsg->exeaddr.data = startaddr;
1059
1060 result = prism2mgmt_ramdl_state(wlandev, rstmsg);
1061 if (result) {
1062 netdev_err(wlandev->netdev,
1063 "%s state enable failed w/ result=%d, aborting download\n",
1064 __func__, result);
1065 goto free_result;
1066 }
1067 resultcode = rstmsg->resultcode.data;
1068 if (resultcode != P80211ENUM_resultcode_success) {
1069 netdev_err(wlandev->netdev,
1070 "%s()->xxxdl_state msg indicates failure, w/ resultcode=%d, aborting download.\n",
1071 __func__, resultcode);
1072 result = 1;
1073 goto free_result;
1074 }
1075
1076
1077 for (i = 0; i < nfchunks; i++) {
1078 nwrites = fchunk[i].len / WRITESIZE_MAX;
1079 nwrites += (fchunk[i].len % WRITESIZE_MAX) ? 1 : 0;
1080 curroff = 0;
1081 for (j = 0; j < nwrites; j++) {
1082
1083 int lenleft = fchunk[i].len - (WRITESIZE_MAX * j);
1084
1085 if (fchunk[i].len > WRITESIZE_MAX)
1086 currlen = WRITESIZE_MAX;
1087 else
1088 currlen = lenleft;
1089 curroff = j * WRITESIZE_MAX;
1090 currdaddr = fchunk[i].addr + curroff;
1091
1092 rwrmsg->addr.data = currdaddr;
1093 rwrmsg->len.data = currlen;
1094 memcpy(rwrmsg->data.data,
1095 fchunk[i].data + curroff, currlen);
1096
1097
1098 pr_debug
1099 ("Sending xxxdl_write message addr=%06x len=%d.\n",
1100 currdaddr, currlen);
1101
1102 result = prism2mgmt_ramdl_write(wlandev, rwrmsg);
1103
1104
1105 if (result) {
1106 netdev_err(wlandev->netdev,
1107 "%s chunk write failed w/ result=%d, aborting download\n",
1108 __func__, result);
1109 goto free_result;
1110 }
1111 resultcode = rstmsg->resultcode.data;
1112 if (resultcode != P80211ENUM_resultcode_success) {
1113 pr_err("%s()->xxxdl_write msg indicates failure, w/ resultcode=%d, aborting download.\n",
1114 __func__, resultcode);
1115 result = 1;
1116 goto free_result;
1117 }
1118 }
1119 }
1120
1121
1122 pr_debug("Sending dl_state(disable) message.\n");
1123 rstmsg->enable.data = P80211ENUM_truth_false;
1124 rstmsg->exeaddr.data = 0;
1125
1126 result = prism2mgmt_ramdl_state(wlandev, rstmsg);
1127 if (result) {
1128 netdev_err(wlandev->netdev,
1129 "%s state disable failed w/ result=%d, aborting download\n",
1130 __func__, result);
1131 goto free_result;
1132 }
1133 resultcode = rstmsg->resultcode.data;
1134 if (resultcode != P80211ENUM_resultcode_success) {
1135 netdev_err(wlandev->netdev,
1136 "%s()->xxxdl_state msg indicates failure, w/ resultcode=%d, aborting download.\n",
1137 __func__, resultcode);
1138 result = 1;
1139 goto free_result;
1140 }
1141
1142free_result:
1143 kfree(rstmsg);
1144 kfree(rwrmsg);
1145 return result;
1146}
1147
1148static int validate_identity(void)
1149{
1150 int i;
1151 int result = 1;
1152 int trump = 0;
1153
1154 pr_debug("NIC ID: %#x v%d.%d.%d\n",
1155 nicid.id, nicid.major, nicid.minor, nicid.variant);
1156 pr_debug("MFI ID: %#x v%d %d->%d\n",
1157 rfid.id, rfid.variant, rfid.bottom, rfid.top);
1158 pr_debug("CFI ID: %#x v%d %d->%d\n",
1159 macid.id, macid.variant, macid.bottom, macid.top);
1160 pr_debug("PRI ID: %#x v%d %d->%d\n",
1161 priid.id, priid.variant, priid.bottom, priid.top);
1162
1163 for (i = 0; i < ns3info; i++) {
1164 switch (s3info[i].type) {
1165 case 1:
1166 pr_debug("Version: ID %#x %d.%d.%d\n",
1167 s3info[i].info.version.id,
1168 s3info[i].info.version.major,
1169 s3info[i].info.version.minor,
1170 s3info[i].info.version.variant);
1171 break;
1172 case 2:
1173 pr_debug("Compat: Role %#x Id %#x v%d %d->%d\n",
1174 s3info[i].info.compat.role,
1175 s3info[i].info.compat.id,
1176 s3info[i].info.compat.variant,
1177 s3info[i].info.compat.bottom,
1178 s3info[i].info.compat.top);
1179
1180
1181 if ((s3info[i].info.compat.role == 1) &&
1182 (s3info[i].info.compat.id == 2)) {
1183 if (s3info[i].info.compat.variant !=
1184 macid.variant) {
1185 result = 2;
1186 }
1187 }
1188
1189
1190 if ((s3info[i].info.compat.role == 1) &&
1191 (s3info[i].info.compat.id == 3)) {
1192 if ((s3info[i].info.compat.bottom > priid.top)
1193 || (s3info[i].info.compat.top <
1194 priid.bottom)) {
1195 result = 3;
1196 }
1197 }
1198
1199 if ((s3info[i].info.compat.role == 1) &&
1200 (s3info[i].info.compat.id == 4)) {
1201
1202 }
1203
1204 break;
1205 case 3:
1206 pr_debug("Seq: %#x\n", s3info[i].info.buildseq);
1207
1208 break;
1209 case 4:
1210 pr_debug("Platform: ID %#x %d.%d.%d\n",
1211 s3info[i].info.version.id,
1212 s3info[i].info.version.major,
1213 s3info[i].info.version.minor,
1214 s3info[i].info.version.variant);
1215
1216 if (nicid.id != s3info[i].info.version.id)
1217 continue;
1218 if (nicid.major != s3info[i].info.version.major)
1219 continue;
1220 if (nicid.minor != s3info[i].info.version.minor)
1221 continue;
1222 if ((nicid.variant != s3info[i].info.version.variant) &&
1223 (nicid.id != 0x8008))
1224 continue;
1225
1226 trump = 1;
1227 break;
1228 case 0x8001:
1229 pr_debug("name inforec len %d\n", s3info[i].len);
1230
1231 break;
1232 default:
1233 pr_debug("Unknown inforec type %d\n", s3info[i].type);
1234 }
1235 }
1236
1237
1238 if (trump && (result != 2))
1239 result = 0;
1240 return result;
1241}
1242