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