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
204int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev)
205{
206 const struct firmware *fw_entry = NULL;
207
208 printk(KERN_INFO "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 printk(KERN_INFO
213 "prism2_usb: Firmware not available, but not essential\n");
214 printk(KERN_INFO
215 "prism2_usb: can continue to use card anyway.\n");
216 return 1;
217 }
218
219 printk(KERN_INFO "prism2_usb: %s will be processed, size %zu\n",
220 PRISM2_USB_FWFILE, fw_entry->size);
221 prism2_fwapply((const struct ihex_binrec *)fw_entry->data, wlandev);
222
223 release_firmware(fw_entry);
224 return 0;
225}
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240static int prism2_fwapply(const struct ihex_binrec *rfptr, wlandevice_t *wlandev)
241{
242 signed int result = 0;
243 struct p80211msg_dot11req_mibget getmsg;
244 p80211itemd_t *item;
245 u32 *data;
246
247
248 ns3data = 0;
249 memset(s3data, 0, sizeof(s3data));
250 ns3plug = 0;
251 memset(s3plug, 0, sizeof(s3plug));
252 ns3crc = 0;
253 memset(s3crc, 0, sizeof(s3crc));
254 ns3info = 0;
255 memset(s3info, 0, sizeof(s3info));
256 startaddr = 0;
257
258 nfchunks = 0;
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));
264
265
266 memset(&pda, 0, sizeof(pda));
267 pda.rec[0] = (hfa384x_pdrec_t *) pda.buf;
268 pda.rec[0]->len = cpu_to_le16(2);
269 pda.rec[0]->code = cpu_to_le16(HFA384x_PDR_END_OF_PDA);
270 pda.nrec = 1;
271
272
273
274 prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
275
276
277 if (read_cardpda(&pda, wlandev)) {
278 printk(KERN_ERR "load_cardpda failed, exiting.\n");
279 return 1;
280 }
281
282
283 memset(&getmsg, 0, sizeof(getmsg));
284 getmsg.msgcode = DIDmsg_dot11req_mibget;
285 getmsg.msglen = sizeof(getmsg);
286 strcpy(getmsg.devname, wlandev->name);
287
288 getmsg.mibattribute.did = DIDmsg_dot11req_mibget_mibattribute;
289 getmsg.mibattribute.status = P80211ENUM_msgitem_status_data_ok;
290 getmsg.resultcode.did = DIDmsg_dot11req_mibget_resultcode;
291 getmsg.resultcode.status = P80211ENUM_msgitem_status_no_value;
292
293 item = (p80211itemd_t *) getmsg.mibattribute.data;
294 item->did = DIDmib_p2_p2NIC_p2PRISupRange;
295 item->status = P80211ENUM_msgitem_status_no_value;
296
297 data = (u32 *) item->data;
298
299
300 prism2mgmt_mibset_mibget(wlandev, &getmsg);
301 if (getmsg.resultcode.data != P80211ENUM_resultcode_success)
302 printk(KERN_ERR "Couldn't fetch PRI-SUP info\n");
303
304
305 priid.role = *data++;
306 priid.id = *data++;
307 priid.variant = *data++;
308 priid.bottom = *data++;
309 priid.top = *data++;
310
311
312 result = read_fwfile(rfptr);
313 if (result) {
314 printk(KERN_ERR "Failed to read the data exiting.\n");
315 return 1;
316 }
317
318 result = validate_identity();
319
320 if (result) {
321 printk(KERN_ERR "Incompatible firmware image.\n");
322 return 1;
323 }
324
325 if (startaddr == 0x00000000) {
326 printk(KERN_ERR "Can't RAM download a Flash image!\n");
327 return 1;
328 }
329
330
331 result = mkimage(fchunk, &nfchunks);
332
333
334 result = plugimage(fchunk, nfchunks, s3plug, ns3plug, &pda);
335 if (result) {
336 printk(KERN_ERR "Failed to plug data.\n");
337 return 1;
338 }
339
340
341 if (crcimage(fchunk, nfchunks, s3crc, ns3crc)) {
342 printk(KERN_ERR "Failed to insert all CRCs\n");
343 return 1;
344 }
345
346
347 result = writeimage(wlandev, fchunk, nfchunks);
348 if (result) {
349 printk(KERN_ERR "Failed to ramwrite image data.\n");
350 return 1;
351 }
352
353
354 free_chunks(fchunk, &nfchunks);
355 free_srecs();
356
357 printk(KERN_INFO "prism2_usb: firmware loading finished.\n");
358
359 return result;
360}
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks,
380 struct s3crcrec *s3crc, unsigned int ns3crc)
381{
382 int result = 0;
383 int i;
384 int c;
385 u32 crcstart;
386 u32 crcend;
387 u32 cstart = 0;
388 u32 cend;
389 u8 *dest;
390 u32 chunkoff;
391
392 for (i = 0; i < ns3crc; i++) {
393 if (!s3crc[i].dowrite)
394 continue;
395 crcstart = s3crc[i].addr;
396 crcend = s3crc[i].addr + s3crc[i].len;
397
398 for (c = 0; c < nfchunks; c++) {
399 cstart = fchunk[c].addr;
400 cend = fchunk[c].addr + fchunk[c].len;
401
402
403
404
405
406
407
408
409 if (crcstart - 2 >= cstart && crcstart < cend)
410 break;
411 }
412 if (c >= nfchunks) {
413 printk(KERN_ERR
414 "Failed to find chunk for "
415 "crcrec[%d], addr=0x%06x len=%d , "
416 "aborting crc.\n",
417 i, s3crc[i].addr, s3crc[i].len);
418 return 1;
419 }
420
421
422 pr_debug("Adding crc @ 0x%06x\n", s3crc[i].addr - 2);
423 chunkoff = crcstart - cstart - 2;
424 dest = fchunk[c].data + chunkoff;
425 *dest = 0xde;
426 *(dest + 1) = 0xc0;
427
428 }
429 return result;
430}
431
432
433
434
435
436
437
438
439
440
441
442
443static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks)
444{
445 int i;
446 for (i = 0; i < *nfchunks; i++)
447 kfree(fchunk[i].data);
448
449 *nfchunks = 0;
450 memset(fchunk, 0, sizeof(*fchunk));
451
452}
453
454
455
456
457
458
459
460
461
462
463
464
465static void free_srecs(void)
466{
467 ns3data = 0;
468 memset(s3data, 0, sizeof(s3data));
469 ns3plug = 0;
470 memset(s3plug, 0, sizeof(s3plug));
471 ns3crc = 0;
472 memset(s3crc, 0, sizeof(s3crc));
473 ns3info = 0;
474 memset(s3info, 0, sizeof(s3info));
475 startaddr = 0;
476}
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492static int mkimage(struct imgchunk *clist, unsigned int *ccnt)
493{
494 int result = 0;
495 int i;
496 int j;
497 int currchunk = 0;
498 u32 nextaddr = 0;
499 u32 s3start;
500 u32 s3end;
501 u32 cstart = 0;
502 u32 cend;
503 u32 coffset;
504
505
506 *ccnt = 0;
507
508
509 for (i = 0; i < ns3data; i++) {
510 if (s3data[i].addr == nextaddr) {
511
512 clist[currchunk].len += s3data[i].len;
513 nextaddr += s3data[i].len;
514 } else {
515
516 (*ccnt)++;
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;
521
522
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;
528 }
529 }
530 }
531 }
532
533
534
535
536
537 for (i = 0; i < *ccnt; i++) {
538 clist[i].data = kzalloc(clist[i].len, GFP_KERNEL);
539 if (clist[i].data == NULL) {
540 printk(KERN_ERR
541 "failed to allocate image space, exitting.\n");
542 return 1;
543 }
544 pr_debug("chunk[%d]: addr=0x%06x len=%d\n",
545 i, clist[i].addr, clist[i].len);
546 }
547
548
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)
556 break;
557 }
558 if (((unsigned int)j) >= (*ccnt)) {
559 printk(KERN_ERR
560 "s3rec(a=0x%06x,l=%d), no chunk match, exiting.\n",
561 s3start, s3data[i].len);
562 return 1;
563 }
564 coffset = s3start - cstart;
565 memcpy(clist[j].data + coffset, s3data[i].data, s3data[i].len);
566 }
567
568 return result;
569}
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585static int mkpdrlist(struct pda *pda)
586{
587 int result = 0;
588 u16 *pda16 = (u16 *) pda->buf;
589 int curroff;
590
591 pda->nrec = 0;
592 curroff = 0;
593 while (curroff < (HFA384x_PDA_LEN_MAX / 2) &&
594 le16_to_cpu(pda16[curroff + 1]) != HFA384x_PDR_END_OF_PDA) {
595 pda->rec[pda->nrec] = (hfa384x_pdrec_t *) &(pda16[curroff]);
596
597 if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
598 HFA384x_PDR_NICID) {
599 memcpy(&nicid, &pda->rec[pda->nrec]->data.nicid,
600 sizeof(nicid));
601 nicid.id = le16_to_cpu(nicid.id);
602 nicid.variant = le16_to_cpu(nicid.variant);
603 nicid.major = le16_to_cpu(nicid.major);
604 nicid.minor = le16_to_cpu(nicid.minor);
605 }
606 if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
607 HFA384x_PDR_MFISUPRANGE) {
608 memcpy(&rfid, &pda->rec[pda->nrec]->data.mfisuprange,
609 sizeof(rfid));
610 rfid.id = le16_to_cpu(rfid.id);
611 rfid.variant = le16_to_cpu(rfid.variant);
612 rfid.bottom = le16_to_cpu(rfid.bottom);
613 rfid.top = le16_to_cpu(rfid.top);
614 }
615 if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
616 HFA384x_PDR_CFISUPRANGE) {
617 memcpy(&macid, &pda->rec[pda->nrec]->data.cfisuprange,
618 sizeof(macid));
619 macid.id = le16_to_cpu(macid.id);
620 macid.variant = le16_to_cpu(macid.variant);
621 macid.bottom = le16_to_cpu(macid.bottom);
622 macid.top = le16_to_cpu(macid.top);
623 }
624
625 (pda->nrec)++;
626 curroff += le16_to_cpu(pda16[curroff]) + 1;
627
628 }
629 if (curroff >= (HFA384x_PDA_LEN_MAX / 2)) {
630 printk(KERN_ERR
631 "no end record found or invalid lengths in "
632 "PDR data, exiting. %x %d\n", curroff, pda->nrec);
633 return 1;
634 }
635 if (le16_to_cpu(pda16[curroff + 1]) == HFA384x_PDR_END_OF_PDA) {
636 pda->rec[pda->nrec] = (hfa384x_pdrec_t *) &(pda16[curroff]);
637 (pda->nrec)++;
638 }
639 return result;
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 printk(KERN_WARNING
689 "warning: Failed to find PDR for "
690 "plugrec 0x%04x.\n", s3plug[i].itemcode);
691 continue;
692#if 0
693
694
695
696
697
698
699
700 result = 1;
701 continue;
702#endif
703 }
704
705
706 if (j != -1 && s3plug[i].len < le16_to_cpu(pda->rec[j]->len)) {
707 printk(KERN_ERR
708 "error: Plug vs. PDR len mismatch for "
709 "plugrec 0x%04x, abort plugging.\n",
710 s3plug[i].itemcode);
711 result = 1;
712 continue;
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 printk(KERN_ERR
724 "error: Failed to find image chunk for "
725 "plugrec 0x%04x.\n", s3plug[i].itemcode);
726 result = 1;
727 continue;
728 }
729
730
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,
736 c, chunkoff);
737
738 if (j == -1) {
739 memset(dest, 0, s3plug[i].len);
740 strncpy(dest, PRISM2_USB_FWFILE, s3plug[i].len - 1);
741 } else {
742 memcpy(dest, &(pda->rec[j]->data), s3plug[i].len);
743 }
744 }
745 return result;
746
747}
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767static int read_cardpda(struct pda *pda, wlandevice_t *wlandev)
768{
769 int result = 0;
770 struct p80211msg_p2req_readpda msg;
771
772
773 msg.msgcode = DIDmsg_p2req_readpda;
774 msg.msglen = sizeof(msg);
775 strcpy(msg.devname, wlandev->name);
776 msg.pda.did = DIDmsg_p2req_readpda_pda;
777 msg.pda.len = HFA384x_PDA_LEN_MAX;
778 msg.pda.status = P80211ENUM_msgitem_status_no_value;
779 msg.resultcode.did = DIDmsg_p2req_readpda_resultcode;
780 msg.resultcode.len = sizeof(u32);
781 msg.resultcode.status = P80211ENUM_msgitem_status_no_value;
782
783 if (prism2mgmt_readpda(wlandev, &msg) != 0) {
784
785 result = -1;
786 } else if (msg.resultcode.data == P80211ENUM_resultcode_success) {
787 memcpy(pda->buf, msg.pda.data, HFA384x_PDA_LEN_MAX);
788 result = mkpdrlist(pda);
789 } else {
790
791 result = -1;
792 }
793
794 return result;
795}
796
797
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
857static int read_fwfile(const struct ihex_binrec *record)
858{
859 int i;
860 int rcnt = 0;
861 u16 *tmpinfo;
862 u16 *ptr16;
863 u32 *ptr32, len, addr;
864
865 pr_debug("Reading fw file ...\n");
866
867 while (record) {
868
869 rcnt++;
870
871 len = be16_to_cpu(record->len);
872 addr = be32_to_cpu(record->addr);
873
874
875 ptr32 = (u32 *) record->data;
876 ptr16 = (u16 *) record->data;
877
878
879 switch (addr) {
880 case S3ADDR_START:
881 startaddr = *ptr32;
882 pr_debug(" S7 start addr, record=%d "
883 " addr=0x%08x\n",
884 rcnt,
885 startaddr);
886 break;
887 case S3ADDR_PLUG:
888 s3plug[ns3plug].itemcode = *ptr32;
889 s3plug[ns3plug].addr = *(ptr32 + 1);
890 s3plug[ns3plug].len = *(ptr32 + 2);
891
892 pr_debug(" S3 plugrec, record=%d "
893 "itemcode=0x%08x addr=0x%08x len=%d\n",
894 rcnt,
895 s3plug[ns3plug].itemcode,
896 s3plug[ns3plug].addr,
897 s3plug[ns3plug].len);
898
899 ns3plug++;
900 if (ns3plug == S3PLUG_MAX) {
901 printk(KERN_ERR "S3 plugrec limit reached - aborting\n");
902 return 1;
903 }
904 break;
905 case S3ADDR_CRC:
906 s3crc[ns3crc].addr = *ptr32;
907 s3crc[ns3crc].len = *(ptr32 + 1);
908 s3crc[ns3crc].dowrite = *(ptr32 + 2);
909
910 pr_debug(" S3 crcrec, record=%d "
911 "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 printk(KERN_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 "
927 "len=0x%04x type=0x%04x\n",
928 rcnt,
929 s3info[ns3info].len,
930 s3info[ns3info].type);
931 if (((s3info[ns3info].len - 1) * sizeof(u16)) > sizeof(s3info[ns3info].info)) {
932 printk(KERN_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 printk(KERN_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 printk(KERN_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 = kmalloc(sizeof(*rstmsg), GFP_KERNEL);
996 rwrmsg = kmalloc(sizeof(*rwrmsg), GFP_KERNEL);
997 if (!rstmsg || !rwrmsg) {
998 kfree(rstmsg);
999 kfree(rwrmsg);
1000 printk(KERN_ERR
1001 "writeimage: no memory for firmware download, "
1002 "aborting download\n");
1003 return -ENOMEM;
1004 }
1005
1006
1007 memset(rstmsg, 0, sizeof(*rstmsg));
1008 strcpy(rstmsg->devname, wlandev->name);
1009 rstmsg->msgcode = DIDmsg_p2req_ramdl_state;
1010 rstmsg->msglen = sizeof(*rstmsg);
1011 rstmsg->enable.did = DIDmsg_p2req_ramdl_state_enable;
1012 rstmsg->exeaddr.did = DIDmsg_p2req_ramdl_state_exeaddr;
1013 rstmsg->resultcode.did = DIDmsg_p2req_ramdl_state_resultcode;
1014 rstmsg->enable.status = P80211ENUM_msgitem_status_data_ok;
1015 rstmsg->exeaddr.status = P80211ENUM_msgitem_status_data_ok;
1016 rstmsg->resultcode.status = P80211ENUM_msgitem_status_no_value;
1017 rstmsg->enable.len = sizeof(u32);
1018 rstmsg->exeaddr.len = sizeof(u32);
1019 rstmsg->resultcode.len = sizeof(u32);
1020
1021 memset(rwrmsg, 0, sizeof(*rwrmsg));
1022 strcpy(rwrmsg->devname, wlandev->name);
1023 rwrmsg->msgcode = DIDmsg_p2req_ramdl_write;
1024 rwrmsg->msglen = sizeof(*rwrmsg);
1025 rwrmsg->addr.did = DIDmsg_p2req_ramdl_write_addr;
1026 rwrmsg->len.did = DIDmsg_p2req_ramdl_write_len;
1027 rwrmsg->data.did = DIDmsg_p2req_ramdl_write_data;
1028 rwrmsg->resultcode.did = DIDmsg_p2req_ramdl_write_resultcode;
1029 rwrmsg->addr.status = P80211ENUM_msgitem_status_data_ok;
1030 rwrmsg->len.status = P80211ENUM_msgitem_status_data_ok;
1031 rwrmsg->data.status = P80211ENUM_msgitem_status_data_ok;
1032 rwrmsg->resultcode.status = P80211ENUM_msgitem_status_no_value;
1033 rwrmsg->addr.len = sizeof(u32);
1034 rwrmsg->len.len = sizeof(u32);
1035 rwrmsg->data.len = WRITESIZE_MAX;
1036 rwrmsg->resultcode.len = sizeof(u32);
1037
1038
1039 pr_debug("Sending dl_state(enable) message.\n");
1040 rstmsg->enable.data = P80211ENUM_truth_true;
1041 rstmsg->exeaddr.data = startaddr;
1042
1043 result = prism2mgmt_ramdl_state(wlandev, rstmsg);
1044 if (result) {
1045 printk(KERN_ERR
1046 "writeimage state enable failed w/ result=%d, "
1047 "aborting download\n", result);
1048 goto free_result;
1049 }
1050 resultcode = rstmsg->resultcode.data;
1051 if (resultcode != P80211ENUM_resultcode_success) {
1052 printk(KERN_ERR
1053 "writeimage()->xxxdl_state msg indicates failure, "
1054 "w/ resultcode=%d, aborting download.\n", resultcode);
1055 result = 1;
1056 goto free_result;
1057 }
1058
1059
1060 for (i = 0; i < nfchunks; i++) {
1061 nwrites = fchunk[i].len / WRITESIZE_MAX;
1062 nwrites += (fchunk[i].len % WRITESIZE_MAX) ? 1 : 0;
1063 curroff = 0;
1064 for (j = 0; j < nwrites; j++) {
1065
1066 int lenleft = fchunk[i].len - (WRITESIZE_MAX * j);
1067 if (fchunk[i].len > WRITESIZE_MAX)
1068 currlen = WRITESIZE_MAX;
1069 else
1070 currlen = lenleft;
1071 curroff = j * WRITESIZE_MAX;
1072 currdaddr = fchunk[i].addr + curroff;
1073
1074 rwrmsg->addr.data = currdaddr;
1075 rwrmsg->len.data = currlen;
1076 memcpy(rwrmsg->data.data,
1077 fchunk[i].data + curroff, currlen);
1078
1079
1080 pr_debug
1081 ("Sending xxxdl_write message addr=%06x len=%d.\n",
1082 currdaddr, currlen);
1083
1084 result = prism2mgmt_ramdl_write(wlandev, rwrmsg);
1085
1086
1087 if (result) {
1088 printk(KERN_ERR
1089 "writeimage chunk write failed w/ result=%d, "
1090 "aborting download\n", result);
1091 goto free_result;
1092 }
1093 resultcode = rstmsg->resultcode.data;
1094 if (resultcode != P80211ENUM_resultcode_success) {
1095 printk(KERN_ERR
1096 "writeimage()->xxxdl_write msg indicates failure, "
1097 "w/ resultcode=%d, aborting download.\n",
1098 resultcode);
1099 result = 1;
1100 goto free_result;
1101 }
1102
1103 }
1104 }
1105
1106
1107 pr_debug("Sending dl_state(disable) message.\n");
1108 rstmsg->enable.data = P80211ENUM_truth_false;
1109 rstmsg->exeaddr.data = 0;
1110
1111 result = prism2mgmt_ramdl_state(wlandev, rstmsg);
1112 if (result) {
1113 printk(KERN_ERR
1114 "writeimage state disable failed w/ result=%d, "
1115 "aborting download\n", result);
1116 goto free_result;
1117 }
1118 resultcode = rstmsg->resultcode.data;
1119 if (resultcode != P80211ENUM_resultcode_success) {
1120 printk(KERN_ERR
1121 "writeimage()->xxxdl_state msg indicates failure, "
1122 "w/ resultcode=%d, aborting download.\n", resultcode);
1123 result = 1;
1124 goto free_result;
1125 }
1126
1127free_result:
1128 kfree(rstmsg);
1129 kfree(rwrmsg);
1130 return result;
1131}
1132
1133static int validate_identity(void)
1134{
1135 int i;
1136 int result = 1;
1137 int trump = 0;
1138
1139 pr_debug("NIC ID: %#x v%d.%d.%d\n",
1140 nicid.id, nicid.major, nicid.minor, nicid.variant);
1141 pr_debug("MFI ID: %#x v%d %d->%d\n",
1142 rfid.id, rfid.variant, rfid.bottom, rfid.top);
1143 pr_debug("CFI ID: %#x v%d %d->%d\n",
1144 macid.id, macid.variant, macid.bottom, macid.top);
1145 pr_debug("PRI ID: %#x v%d %d->%d\n",
1146 priid.id, priid.variant, priid.bottom, priid.top);
1147
1148 for (i = 0; i < ns3info; i++) {
1149 switch (s3info[i].type) {
1150 case 1:
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);
1156 break;
1157 case 2:
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);
1164
1165
1166 if ((s3info[i].info.compat.role == 1) &&
1167 (s3info[i].info.compat.id == 2)) {
1168 if (s3info[i].info.compat.variant !=
1169 macid.variant) {
1170 result = 2;
1171 }
1172 }
1173
1174
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 <
1179 priid.bottom)) {
1180 result = 3;
1181 }
1182 }
1183
1184 if ((s3info[i].info.compat.role == 1) &&
1185 (s3info[i].info.compat.id == 4)) {
1186
1187 }
1188
1189 break;
1190 case 3:
1191 pr_debug("Seq: %#x\n", s3info[i].info.buildseq);
1192
1193 break;
1194 case 4:
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);
1200
1201 if (nicid.id != s3info[i].info.version.id)
1202 continue;
1203 if (nicid.major != s3info[i].info.version.major)
1204 continue;
1205 if (nicid.minor != s3info[i].info.version.minor)
1206 continue;
1207 if ((nicid.variant != s3info[i].info.version.variant) &&
1208 (nicid.id != 0x8008))
1209 continue;
1210
1211 trump = 1;
1212 break;
1213 case 0x8001:
1214 pr_debug("name inforec len %d\n", s3info[i].len);
1215
1216 break;
1217 default:
1218 pr_debug("Unknown inforec type %d\n", s3info[i].type);
1219 }
1220 }
1221
1222
1223 if (trump && (result != 2))
1224 result = 0;
1225 return result;
1226}
1227