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