0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 #include <linux/ihex.h>
0052 #include <linux/slab.h>
0053
0054
0055
0056
0057 #define PRISM2_USB_FWFILE "prism2_ru.fw"
0058 MODULE_FIRMWARE(PRISM2_USB_FWFILE);
0059
0060 #define S3DATA_MAX 5000
0061 #define S3PLUG_MAX 200
0062 #define S3CRC_MAX 200
0063 #define S3INFO_MAX 50
0064
0065 #define S3ADDR_PLUG (0xff000000UL)
0066 #define S3ADDR_CRC (0xff100000UL)
0067 #define S3ADDR_INFO (0xff200000UL)
0068 #define S3ADDR_START (0xff400000UL)
0069
0070 #define CHUNKS_MAX 100
0071
0072 #define WRITESIZE_MAX 4096
0073
0074
0075
0076
0077 struct s3datarec {
0078 u32 len;
0079 u32 addr;
0080 u8 checksum;
0081 u8 *data;
0082 };
0083
0084 struct s3plugrec {
0085 u32 itemcode;
0086 u32 addr;
0087 u32 len;
0088 };
0089
0090 struct s3crcrec {
0091 u32 addr;
0092 u32 len;
0093 unsigned int dowrite;
0094 };
0095
0096 struct s3inforec {
0097 u16 len;
0098 u16 type;
0099 union {
0100 struct hfa384x_compident version;
0101 struct hfa384x_caplevel compat;
0102 u16 buildseq;
0103 struct hfa384x_compident platform;
0104 } info;
0105 };
0106
0107 struct pda {
0108 u8 buf[HFA384x_PDA_LEN_MAX];
0109 struct hfa384x_pdrec *rec[HFA384x_PDA_RECS_MAX];
0110 unsigned int nrec;
0111 };
0112
0113 struct imgchunk {
0114 u32 addr;
0115 u32 len;
0116 u16 crc;
0117 u8 *data;
0118 };
0119
0120
0121
0122
0123
0124
0125
0126
0127 static unsigned int ns3data;
0128 static struct s3datarec *s3data;
0129
0130
0131 static unsigned int ns3plug;
0132 static struct s3plugrec s3plug[S3PLUG_MAX];
0133
0134
0135 static unsigned int ns3crc;
0136 static struct s3crcrec s3crc[S3CRC_MAX];
0137
0138
0139 static unsigned int ns3info;
0140 static struct s3inforec s3info[S3INFO_MAX];
0141
0142
0143 static u32 startaddr;
0144
0145
0146 static unsigned int nfchunks;
0147 static struct imgchunk fchunk[CHUNKS_MAX];
0148
0149
0150
0151
0152
0153
0154
0155 static struct pda pda;
0156 static struct hfa384x_compident nicid;
0157 static struct hfa384x_caplevel rfid;
0158 static struct hfa384x_caplevel macid;
0159 static struct hfa384x_caplevel priid;
0160
0161
0162
0163
0164 static int prism2_fwapply(const struct ihex_binrec *rfptr,
0165 struct wlandevice *wlandev);
0166
0167 static int read_fwfile(const struct ihex_binrec *rfptr);
0168
0169 static int mkimage(struct imgchunk *clist, unsigned int *ccnt);
0170
0171 static int read_cardpda(struct pda *pda, struct wlandevice *wlandev);
0172
0173 static int mkpdrlist(struct pda *pda);
0174
0175 static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks,
0176 struct s3plugrec *s3plug, unsigned int ns3plug,
0177 struct pda *pda);
0178
0179 static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks,
0180 struct s3crcrec *s3crc, unsigned int ns3crc);
0181
0182 static int writeimage(struct wlandevice *wlandev, struct imgchunk *fchunk,
0183 unsigned int nfchunks);
0184
0185 static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks);
0186
0187 static void free_srecs(void);
0188
0189 static int validate_identity(void);
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 static int prism2_fwtry(struct usb_device *udev, struct wlandevice *wlandev)
0209 {
0210 const struct firmware *fw_entry = NULL;
0211
0212 netdev_info(wlandev->netdev, "prism2_usb: Checking for firmware %s\n",
0213 PRISM2_USB_FWFILE);
0214 if (request_ihex_firmware(&fw_entry,
0215 PRISM2_USB_FWFILE, &udev->dev) != 0) {
0216 netdev_info(wlandev->netdev,
0217 "prism2_usb: Firmware not available, but not essential\n");
0218 netdev_info(wlandev->netdev,
0219 "prism2_usb: can continue to use card anyway.\n");
0220 return 1;
0221 }
0222
0223 netdev_info(wlandev->netdev,
0224 "prism2_usb: %s will be processed, size %zu\n",
0225 PRISM2_USB_FWFILE, fw_entry->size);
0226 prism2_fwapply((const struct ihex_binrec *)fw_entry->data, wlandev);
0227
0228 release_firmware(fw_entry);
0229 return 0;
0230 }
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246 static int prism2_fwapply(const struct ihex_binrec *rfptr,
0247 struct wlandevice *wlandev)
0248 {
0249 signed int result = 0;
0250 struct p80211msg_dot11req_mibget getmsg;
0251 struct p80211itemd *item;
0252 u32 *data;
0253
0254
0255 ns3data = 0;
0256 s3data = kcalloc(S3DATA_MAX, sizeof(*s3data), GFP_KERNEL);
0257 if (!s3data) {
0258 result = -ENOMEM;
0259 goto out;
0260 }
0261
0262 ns3plug = 0;
0263 memset(s3plug, 0, sizeof(s3plug));
0264 ns3crc = 0;
0265 memset(s3crc, 0, sizeof(s3crc));
0266 ns3info = 0;
0267 memset(s3info, 0, sizeof(s3info));
0268 startaddr = 0;
0269
0270 nfchunks = 0;
0271 memset(fchunk, 0, sizeof(fchunk));
0272 memset(&nicid, 0, sizeof(nicid));
0273 memset(&rfid, 0, sizeof(rfid));
0274 memset(&macid, 0, sizeof(macid));
0275 memset(&priid, 0, sizeof(priid));
0276
0277
0278 memset(&pda, 0, sizeof(pda));
0279 pda.rec[0] = (struct hfa384x_pdrec *)pda.buf;
0280 pda.rec[0]->len = cpu_to_le16(2);
0281 pda.rec[0]->code = cpu_to_le16(HFA384x_PDR_END_OF_PDA);
0282 pda.nrec = 1;
0283
0284
0285
0286 prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
0287
0288
0289 if (read_cardpda(&pda, wlandev)) {
0290 netdev_err(wlandev->netdev, "load_cardpda failed, exiting.\n");
0291 result = 1;
0292 goto out;
0293 }
0294
0295
0296 memset(&getmsg, 0, sizeof(getmsg));
0297 getmsg.msgcode = DIDMSG_DOT11REQ_MIBGET;
0298 getmsg.msglen = sizeof(getmsg);
0299 strscpy(getmsg.devname, wlandev->name, sizeof(getmsg.devname));
0300
0301 getmsg.mibattribute.did = DIDMSG_DOT11REQ_MIBGET_MIBATTRIBUTE;
0302 getmsg.mibattribute.status = P80211ENUM_msgitem_status_data_ok;
0303 getmsg.resultcode.did = DIDMSG_DOT11REQ_MIBGET_RESULTCODE;
0304 getmsg.resultcode.status = P80211ENUM_msgitem_status_no_value;
0305
0306 item = (struct p80211itemd *)getmsg.mibattribute.data;
0307 item->did = DIDMIB_P2_NIC_PRISUPRANGE;
0308 item->status = P80211ENUM_msgitem_status_no_value;
0309
0310 data = (u32 *)item->data;
0311
0312
0313 prism2mgmt_mibset_mibget(wlandev, &getmsg);
0314 if (getmsg.resultcode.data != P80211ENUM_resultcode_success)
0315 netdev_err(wlandev->netdev, "Couldn't fetch PRI-SUP info\n");
0316
0317
0318 priid.role = *data++;
0319 priid.id = *data++;
0320 priid.variant = *data++;
0321 priid.bottom = *data++;
0322 priid.top = *data++;
0323
0324
0325 result = read_fwfile(rfptr);
0326 if (result) {
0327 netdev_err(wlandev->netdev,
0328 "Failed to read the data exiting.\n");
0329 goto out;
0330 }
0331
0332 result = validate_identity();
0333 if (result) {
0334 netdev_err(wlandev->netdev, "Incompatible firmware image.\n");
0335 goto out;
0336 }
0337
0338 if (startaddr == 0x00000000) {
0339 netdev_err(wlandev->netdev,
0340 "Can't RAM download a Flash image!\n");
0341 result = 1;
0342 goto out;
0343 }
0344
0345
0346 result = mkimage(fchunk, &nfchunks);
0347 if (result) {
0348 netdev_err(wlandev->netdev, "Failed to make image chunk.\n");
0349 goto free_chunks;
0350 }
0351
0352
0353 result = plugimage(fchunk, nfchunks, s3plug, ns3plug, &pda);
0354 if (result) {
0355 netdev_err(wlandev->netdev, "Failed to plug data.\n");
0356 goto free_chunks;
0357 }
0358
0359
0360 result = crcimage(fchunk, nfchunks, s3crc, ns3crc);
0361 if (result) {
0362 netdev_err(wlandev->netdev, "Failed to insert all CRCs\n");
0363 goto free_chunks;
0364 }
0365
0366
0367 result = writeimage(wlandev, fchunk, nfchunks);
0368 if (result) {
0369 netdev_err(wlandev->netdev, "Failed to ramwrite image data.\n");
0370 goto free_chunks;
0371 }
0372
0373 netdev_info(wlandev->netdev, "prism2_usb: firmware loading finished.\n");
0374
0375 free_chunks:
0376
0377 free_chunks(fchunk, &nfchunks);
0378 free_srecs();
0379
0380 out:
0381 return result;
0382 }
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402 static int crcimage(struct imgchunk *fchunk, unsigned int nfchunks,
0403 struct s3crcrec *s3crc, unsigned int ns3crc)
0404 {
0405 int result = 0;
0406 int i;
0407 int c;
0408 u32 crcstart;
0409 u32 cstart = 0;
0410 u32 cend;
0411 u8 *dest;
0412 u32 chunkoff;
0413
0414 for (i = 0; i < ns3crc; i++) {
0415 if (!s3crc[i].dowrite)
0416 continue;
0417 crcstart = s3crc[i].addr;
0418
0419 for (c = 0; c < nfchunks; c++) {
0420 cstart = fchunk[c].addr;
0421 cend = fchunk[c].addr + fchunk[c].len;
0422
0423
0424
0425
0426
0427
0428
0429
0430 if (crcstart - 2 >= cstart && crcstart < cend)
0431 break;
0432 }
0433 if (c >= nfchunks) {
0434 pr_err("Failed to find chunk for crcrec[%d], addr=0x%06x len=%d , aborting crc.\n",
0435 i, s3crc[i].addr, s3crc[i].len);
0436 return 1;
0437 }
0438
0439
0440 pr_debug("Adding crc @ 0x%06x\n", s3crc[i].addr - 2);
0441 chunkoff = crcstart - cstart - 2;
0442 dest = fchunk[c].data + chunkoff;
0443 *dest = 0xde;
0444 *(dest + 1) = 0xc0;
0445 }
0446 return result;
0447 }
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461 static void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks)
0462 {
0463 int i;
0464
0465 for (i = 0; i < *nfchunks; i++)
0466 kfree(fchunk[i].data);
0467
0468 *nfchunks = 0;
0469 memset(fchunk, 0, sizeof(*fchunk));
0470 }
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484 static void free_srecs(void)
0485 {
0486 ns3data = 0;
0487 kfree(s3data);
0488 ns3plug = 0;
0489 memset(s3plug, 0, sizeof(s3plug));
0490 ns3crc = 0;
0491 memset(s3crc, 0, sizeof(s3crc));
0492 ns3info = 0;
0493 memset(s3info, 0, sizeof(s3info));
0494 startaddr = 0;
0495 }
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512 static int mkimage(struct imgchunk *clist, unsigned int *ccnt)
0513 {
0514 int result = 0;
0515 int i;
0516 int j;
0517 int currchunk = 0;
0518 u32 nextaddr = 0;
0519 u32 s3start;
0520 u32 s3end;
0521 u32 cstart = 0;
0522 u32 cend;
0523 u32 coffset;
0524
0525
0526 *ccnt = 0;
0527
0528
0529 for (i = 0; i < ns3data; i++) {
0530 if (s3data[i].addr == nextaddr) {
0531
0532 clist[currchunk].len += s3data[i].len;
0533 nextaddr += s3data[i].len;
0534 } else {
0535
0536 (*ccnt)++;
0537 currchunk = *ccnt - 1;
0538 clist[currchunk].addr = s3data[i].addr;
0539 clist[currchunk].len = s3data[i].len;
0540 nextaddr = s3data[i].addr + s3data[i].len;
0541
0542
0543 for (j = 0; j < ns3crc; j++) {
0544 if (s3crc[j].dowrite &&
0545 s3crc[j].addr == clist[currchunk].addr) {
0546 clist[currchunk].addr -= 2;
0547 clist[currchunk].len += 2;
0548 }
0549 }
0550 }
0551 }
0552
0553
0554
0555
0556
0557 for (i = 0; i < *ccnt; i++) {
0558 clist[i].data = kzalloc(clist[i].len, GFP_KERNEL);
0559 if (!clist[i].data)
0560 return 1;
0561
0562 pr_debug("chunk[%d]: addr=0x%06x len=%d\n",
0563 i, clist[i].addr, clist[i].len);
0564 }
0565
0566
0567 for (i = 0; i < ns3data; i++) {
0568 s3start = s3data[i].addr;
0569 s3end = s3start + s3data[i].len - 1;
0570 for (j = 0; j < *ccnt; j++) {
0571 cstart = clist[j].addr;
0572 cend = cstart + clist[j].len - 1;
0573 if (s3start >= cstart && s3end <= cend)
0574 break;
0575 }
0576 if (((unsigned int)j) >= (*ccnt)) {
0577 pr_err("s3rec(a=0x%06x,l=%d), no chunk match, exiting.\n",
0578 s3start, s3data[i].len);
0579 return 1;
0580 }
0581 coffset = s3start - cstart;
0582 memcpy(clist[j].data + coffset, s3data[i].data, s3data[i].len);
0583 }
0584
0585 return result;
0586 }
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603 static int mkpdrlist(struct pda *pda)
0604 {
0605 __le16 *pda16 = (__le16 *)pda->buf;
0606 int curroff;
0607
0608 pda->nrec = 0;
0609 curroff = 0;
0610 while (curroff < (HFA384x_PDA_LEN_MAX / 2 - 1) &&
0611 le16_to_cpu(pda16[curroff + 1]) != HFA384x_PDR_END_OF_PDA) {
0612 pda->rec[pda->nrec] = (struct hfa384x_pdrec *)&pda16[curroff];
0613
0614 if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
0615 HFA384x_PDR_NICID) {
0616 memcpy(&nicid, &pda->rec[pda->nrec]->data.nicid,
0617 sizeof(nicid));
0618 le16_to_cpus(&nicid.id);
0619 le16_to_cpus(&nicid.variant);
0620 le16_to_cpus(&nicid.major);
0621 le16_to_cpus(&nicid.minor);
0622 }
0623 if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
0624 HFA384x_PDR_MFISUPRANGE) {
0625 memcpy(&rfid, &pda->rec[pda->nrec]->data.mfisuprange,
0626 sizeof(rfid));
0627 le16_to_cpus(&rfid.id);
0628 le16_to_cpus(&rfid.variant);
0629 le16_to_cpus(&rfid.bottom);
0630 le16_to_cpus(&rfid.top);
0631 }
0632 if (le16_to_cpu(pda->rec[pda->nrec]->code) ==
0633 HFA384x_PDR_CFISUPRANGE) {
0634 memcpy(&macid, &pda->rec[pda->nrec]->data.cfisuprange,
0635 sizeof(macid));
0636 le16_to_cpus(&macid.id);
0637 le16_to_cpus(&macid.variant);
0638 le16_to_cpus(&macid.bottom);
0639 le16_to_cpus(&macid.top);
0640 }
0641
0642 (pda->nrec)++;
0643 curroff += le16_to_cpu(pda16[curroff]) + 1;
0644 }
0645 if (curroff >= (HFA384x_PDA_LEN_MAX / 2 - 1)) {
0646 pr_err("no end record found or invalid lengths in PDR data, exiting. %x %d\n",
0647 curroff, pda->nrec);
0648 return 1;
0649 }
0650 pda->rec[pda->nrec] = (struct hfa384x_pdrec *)&pda16[curroff];
0651 (pda->nrec)++;
0652 return 0;
0653 }
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673 static int plugimage(struct imgchunk *fchunk, unsigned int nfchunks,
0674 struct s3plugrec *s3plug, unsigned int ns3plug,
0675 struct pda *pda)
0676 {
0677 int result = 0;
0678 int i;
0679 int j;
0680 int c;
0681 u32 pstart;
0682 u32 pend;
0683 u32 cstart = 0;
0684 u32 cend;
0685 u32 chunkoff;
0686 u8 *dest;
0687
0688
0689 for (i = 0; i < ns3plug; i++) {
0690 pstart = s3plug[i].addr;
0691 pend = s3plug[i].addr + s3plug[i].len;
0692
0693 if (s3plug[i].itemcode != 0xffffffffUL) {
0694 for (j = 0; j < pda->nrec; j++) {
0695 if (s3plug[i].itemcode ==
0696 le16_to_cpu(pda->rec[j]->code))
0697 break;
0698 }
0699 } else {
0700 j = -1;
0701 }
0702 if (j >= pda->nrec && j != -1) {
0703 pr_warn("warning: Failed to find PDR for plugrec 0x%04x.\n",
0704 s3plug[i].itemcode);
0705 continue;
0706
0707
0708
0709
0710
0711
0712
0713
0714 }
0715
0716
0717 if (j != -1 && s3plug[i].len < le16_to_cpu(pda->rec[j]->len)) {
0718 pr_err("error: Plug vs. PDR len mismatch for plugrec 0x%04x, abort plugging.\n",
0719 s3plug[i].itemcode);
0720 result = 1;
0721 continue;
0722 }
0723
0724
0725
0726
0727
0728 for (c = 0; c < nfchunks; c++) {
0729 cstart = fchunk[c].addr;
0730 cend = fchunk[c].addr + fchunk[c].len;
0731 if (pstart >= cstart && pend <= cend)
0732 break;
0733 }
0734 if (c >= nfchunks) {
0735 pr_err("error: Failed to find image chunk for plugrec 0x%04x.\n",
0736 s3plug[i].itemcode);
0737 result = 1;
0738 continue;
0739 }
0740
0741
0742 chunkoff = pstart - cstart;
0743 dest = fchunk[c].data + chunkoff;
0744 pr_debug("Plugging item 0x%04x @ 0x%06x, len=%d, cnum=%d coff=0x%06x\n",
0745 s3plug[i].itemcode, pstart, s3plug[i].len,
0746 c, chunkoff);
0747
0748 if (j == -1) {
0749 memset(dest, 0, s3plug[i].len);
0750 strncpy(dest, PRISM2_USB_FWFILE, s3plug[i].len - 1);
0751 } else {
0752 memcpy(dest, &pda->rec[j]->data, s3plug[i].len);
0753 }
0754 }
0755 return result;
0756 }
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777 static int read_cardpda(struct pda *pda, struct wlandevice *wlandev)
0778 {
0779 int result = 0;
0780 struct p80211msg_p2req_readpda *msg;
0781
0782 msg = kzalloc(sizeof(*msg), GFP_KERNEL);
0783 if (!msg)
0784 return -ENOMEM;
0785
0786
0787 msg->msgcode = DIDMSG_P2REQ_READPDA;
0788 msg->msglen = sizeof(msg);
0789 strscpy(msg->devname, wlandev->name, sizeof(msg->devname));
0790 msg->pda.did = DIDMSG_P2REQ_READPDA_PDA;
0791 msg->pda.len = HFA384x_PDA_LEN_MAX;
0792 msg->pda.status = P80211ENUM_msgitem_status_no_value;
0793 msg->resultcode.did = DIDMSG_P2REQ_READPDA_RESULTCODE;
0794 msg->resultcode.len = sizeof(u32);
0795 msg->resultcode.status = P80211ENUM_msgitem_status_no_value;
0796
0797 if (prism2mgmt_readpda(wlandev, msg) != 0) {
0798
0799 result = -1;
0800 } else if (msg->resultcode.data == P80211ENUM_resultcode_success) {
0801 memcpy(pda->buf, msg->pda.data, HFA384x_PDA_LEN_MAX);
0802 result = mkpdrlist(pda);
0803 } else {
0804
0805 result = -1;
0806 }
0807
0808 kfree(msg);
0809 return result;
0810 }
0811
0812
0813
0814
0815
0816
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873 static int read_fwfile(const struct ihex_binrec *record)
0874 {
0875 int i;
0876 int rcnt = 0;
0877 u16 *tmpinfo;
0878 u16 *ptr16;
0879 u32 *ptr32, len, addr;
0880
0881 pr_debug("Reading fw file ...\n");
0882
0883 while (record) {
0884 rcnt++;
0885
0886 len = be16_to_cpu(record->len);
0887 addr = be32_to_cpu(record->addr);
0888
0889
0890 ptr32 = (u32 *)record->data;
0891 ptr16 = (u16 *)record->data;
0892
0893
0894 switch (addr) {
0895 case S3ADDR_START:
0896 startaddr = *ptr32;
0897 pr_debug(" S7 start addr, record=%d addr=0x%08x\n",
0898 rcnt,
0899 startaddr);
0900 break;
0901 case S3ADDR_PLUG:
0902 s3plug[ns3plug].itemcode = *ptr32;
0903 s3plug[ns3plug].addr = *(ptr32 + 1);
0904 s3plug[ns3plug].len = *(ptr32 + 2);
0905
0906 pr_debug(" S3 plugrec, record=%d itemcode=0x%08x addr=0x%08x len=%d\n",
0907 rcnt,
0908 s3plug[ns3plug].itemcode,
0909 s3plug[ns3plug].addr,
0910 s3plug[ns3plug].len);
0911
0912 ns3plug++;
0913 if (ns3plug == S3PLUG_MAX) {
0914 pr_err("S3 plugrec limit reached - aborting\n");
0915 return 1;
0916 }
0917 break;
0918 case S3ADDR_CRC:
0919 s3crc[ns3crc].addr = *ptr32;
0920 s3crc[ns3crc].len = *(ptr32 + 1);
0921 s3crc[ns3crc].dowrite = *(ptr32 + 2);
0922
0923 pr_debug(" S3 crcrec, record=%d addr=0x%08x len=%d write=0x%08x\n",
0924 rcnt,
0925 s3crc[ns3crc].addr,
0926 s3crc[ns3crc].len,
0927 s3crc[ns3crc].dowrite);
0928 ns3crc++;
0929 if (ns3crc == S3CRC_MAX) {
0930 pr_err("S3 crcrec limit reached - aborting\n");
0931 return 1;
0932 }
0933 break;
0934 case S3ADDR_INFO:
0935 s3info[ns3info].len = *ptr16;
0936 s3info[ns3info].type = *(ptr16 + 1);
0937
0938 pr_debug(" S3 inforec, record=%d len=0x%04x type=0x%04x\n",
0939 rcnt,
0940 s3info[ns3info].len,
0941 s3info[ns3info].type);
0942 if (((s3info[ns3info].len - 1) * sizeof(u16)) >
0943 sizeof(s3info[ns3info].info)) {
0944 pr_err("S3 inforec length too long - aborting\n");
0945 return 1;
0946 }
0947
0948 tmpinfo = (u16 *)&s3info[ns3info].info.version;
0949 pr_debug(" info=");
0950 for (i = 0; i < s3info[ns3info].len - 1; i++) {
0951 tmpinfo[i] = *(ptr16 + 2 + i);
0952 pr_debug("%04x ", tmpinfo[i]);
0953 }
0954 pr_debug("\n");
0955
0956 ns3info++;
0957 if (ns3info == S3INFO_MAX) {
0958 pr_err("S3 inforec limit reached - aborting\n");
0959 return 1;
0960 }
0961 break;
0962 default:
0963 s3data[ns3data].addr = addr;
0964 s3data[ns3data].len = len;
0965 s3data[ns3data].data = (uint8_t *)record->data;
0966 ns3data++;
0967 if (ns3data == S3DATA_MAX) {
0968 pr_err("S3 datarec limit reached - aborting\n");
0969 return 1;
0970 }
0971 break;
0972 }
0973 record = ihex_next_binrec(record);
0974 }
0975 return 0;
0976 }
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994 static int writeimage(struct wlandevice *wlandev, struct imgchunk *fchunk,
0995 unsigned int nfchunks)
0996 {
0997 int result = 0;
0998 struct p80211msg_p2req_ramdl_state *rstmsg;
0999 struct p80211msg_p2req_ramdl_write *rwrmsg;
1000 u32 resultcode;
1001 int i;
1002 int j;
1003 unsigned int nwrites;
1004 u32 curroff;
1005 u32 currlen;
1006 u32 currdaddr;
1007
1008 rstmsg = kzalloc(sizeof(*rstmsg), GFP_KERNEL);
1009 rwrmsg = kzalloc(sizeof(*rwrmsg), GFP_KERNEL);
1010 if (!rstmsg || !rwrmsg) {
1011 kfree(rstmsg);
1012 kfree(rwrmsg);
1013 netdev_err(wlandev->netdev,
1014 "%s: no memory for firmware download, aborting download\n",
1015 __func__);
1016 return -ENOMEM;
1017 }
1018
1019
1020 strscpy(rstmsg->devname, wlandev->name, sizeof(rstmsg->devname));
1021 rstmsg->msgcode = DIDMSG_P2REQ_RAMDL_STATE;
1022 rstmsg->msglen = sizeof(*rstmsg);
1023 rstmsg->enable.did = DIDMSG_P2REQ_RAMDL_STATE_ENABLE;
1024 rstmsg->exeaddr.did = DIDMSG_P2REQ_RAMDL_STATE_EXEADDR;
1025 rstmsg->resultcode.did = DIDMSG_P2REQ_RAMDL_STATE_RESULTCODE;
1026 rstmsg->enable.status = P80211ENUM_msgitem_status_data_ok;
1027 rstmsg->exeaddr.status = P80211ENUM_msgitem_status_data_ok;
1028 rstmsg->resultcode.status = P80211ENUM_msgitem_status_no_value;
1029 rstmsg->enable.len = sizeof(u32);
1030 rstmsg->exeaddr.len = sizeof(u32);
1031 rstmsg->resultcode.len = sizeof(u32);
1032
1033 strscpy(rwrmsg->devname, wlandev->name, sizeof(rwrmsg->devname));
1034 rwrmsg->msgcode = DIDMSG_P2REQ_RAMDL_WRITE;
1035 rwrmsg->msglen = sizeof(*rwrmsg);
1036 rwrmsg->addr.did = DIDMSG_P2REQ_RAMDL_WRITE_ADDR;
1037 rwrmsg->len.did = DIDMSG_P2REQ_RAMDL_WRITE_LEN;
1038 rwrmsg->data.did = DIDMSG_P2REQ_RAMDL_WRITE_DATA;
1039 rwrmsg->resultcode.did = DIDMSG_P2REQ_RAMDL_WRITE_RESULTCODE;
1040 rwrmsg->addr.status = P80211ENUM_msgitem_status_data_ok;
1041 rwrmsg->len.status = P80211ENUM_msgitem_status_data_ok;
1042 rwrmsg->data.status = P80211ENUM_msgitem_status_data_ok;
1043 rwrmsg->resultcode.status = P80211ENUM_msgitem_status_no_value;
1044 rwrmsg->addr.len = sizeof(u32);
1045 rwrmsg->len.len = sizeof(u32);
1046 rwrmsg->data.len = WRITESIZE_MAX;
1047 rwrmsg->resultcode.len = sizeof(u32);
1048
1049
1050 pr_debug("Sending dl_state(enable) message.\n");
1051 rstmsg->enable.data = P80211ENUM_truth_true;
1052 rstmsg->exeaddr.data = startaddr;
1053
1054 result = prism2mgmt_ramdl_state(wlandev, rstmsg);
1055 if (result) {
1056 netdev_err(wlandev->netdev,
1057 "%s state enable failed w/ result=%d, aborting download\n",
1058 __func__, result);
1059 goto free_result;
1060 }
1061 resultcode = rstmsg->resultcode.data;
1062 if (resultcode != P80211ENUM_resultcode_success) {
1063 netdev_err(wlandev->netdev,
1064 "%s()->xxxdl_state msg indicates failure, w/ resultcode=%d, aborting download.\n",
1065 __func__, resultcode);
1066 result = 1;
1067 goto free_result;
1068 }
1069
1070
1071 for (i = 0; i < nfchunks; i++) {
1072 nwrites = fchunk[i].len / WRITESIZE_MAX;
1073 nwrites += (fchunk[i].len % WRITESIZE_MAX) ? 1 : 0;
1074 curroff = 0;
1075 for (j = 0; j < nwrites; j++) {
1076
1077 int lenleft = fchunk[i].len - (WRITESIZE_MAX * j);
1078
1079 if (fchunk[i].len > WRITESIZE_MAX)
1080 currlen = WRITESIZE_MAX;
1081 else
1082 currlen = lenleft;
1083 curroff = j * WRITESIZE_MAX;
1084 currdaddr = fchunk[i].addr + curroff;
1085
1086 rwrmsg->addr.data = currdaddr;
1087 rwrmsg->len.data = currlen;
1088 memcpy(rwrmsg->data.data,
1089 fchunk[i].data + curroff, currlen);
1090
1091
1092 pr_debug
1093 ("Sending xxxdl_write message addr=%06x len=%d.\n",
1094 currdaddr, currlen);
1095
1096 result = prism2mgmt_ramdl_write(wlandev, rwrmsg);
1097
1098
1099 if (result) {
1100 netdev_err(wlandev->netdev,
1101 "%s chunk write failed w/ result=%d, aborting download\n",
1102 __func__, result);
1103 goto free_result;
1104 }
1105 resultcode = rstmsg->resultcode.data;
1106 if (resultcode != P80211ENUM_resultcode_success) {
1107 pr_err("%s()->xxxdl_write msg indicates failure, w/ resultcode=%d, aborting download.\n",
1108 __func__, resultcode);
1109 result = 1;
1110 goto free_result;
1111 }
1112 }
1113 }
1114
1115
1116 pr_debug("Sending dl_state(disable) message.\n");
1117 rstmsg->enable.data = P80211ENUM_truth_false;
1118 rstmsg->exeaddr.data = 0;
1119
1120 result = prism2mgmt_ramdl_state(wlandev, rstmsg);
1121 if (result) {
1122 netdev_err(wlandev->netdev,
1123 "%s state disable failed w/ result=%d, aborting download\n",
1124 __func__, result);
1125 goto free_result;
1126 }
1127 resultcode = rstmsg->resultcode.data;
1128 if (resultcode != P80211ENUM_resultcode_success) {
1129 netdev_err(wlandev->netdev,
1130 "%s()->xxxdl_state msg indicates failure, w/ resultcode=%d, aborting download.\n",
1131 __func__, resultcode);
1132 result = 1;
1133 goto free_result;
1134 }
1135
1136 free_result:
1137 kfree(rstmsg);
1138 kfree(rwrmsg);
1139 return result;
1140 }
1141
1142 static int validate_identity(void)
1143 {
1144 int i;
1145 int result = 1;
1146 int trump = 0;
1147
1148 pr_debug("NIC ID: %#x v%d.%d.%d\n",
1149 nicid.id, nicid.major, nicid.minor, nicid.variant);
1150 pr_debug("MFI ID: %#x v%d %d->%d\n",
1151 rfid.id, rfid.variant, rfid.bottom, rfid.top);
1152 pr_debug("CFI ID: %#x v%d %d->%d\n",
1153 macid.id, macid.variant, macid.bottom, macid.top);
1154 pr_debug("PRI ID: %#x v%d %d->%d\n",
1155 priid.id, priid.variant, priid.bottom, priid.top);
1156
1157 for (i = 0; i < ns3info; i++) {
1158 switch (s3info[i].type) {
1159 case 1:
1160 pr_debug("Version: ID %#x %d.%d.%d\n",
1161 s3info[i].info.version.id,
1162 s3info[i].info.version.major,
1163 s3info[i].info.version.minor,
1164 s3info[i].info.version.variant);
1165 break;
1166 case 2:
1167 pr_debug("Compat: Role %#x Id %#x v%d %d->%d\n",
1168 s3info[i].info.compat.role,
1169 s3info[i].info.compat.id,
1170 s3info[i].info.compat.variant,
1171 s3info[i].info.compat.bottom,
1172 s3info[i].info.compat.top);
1173
1174
1175 if ((s3info[i].info.compat.role == 1) &&
1176 (s3info[i].info.compat.id == 2)) {
1177 if (s3info[i].info.compat.variant !=
1178 macid.variant) {
1179 result = 2;
1180 }
1181 }
1182
1183
1184 if ((s3info[i].info.compat.role == 1) &&
1185 (s3info[i].info.compat.id == 3)) {
1186 if ((s3info[i].info.compat.bottom >
1187 priid.top) ||
1188 (s3info[i].info.compat.top <
1189 priid.bottom)) {
1190 result = 3;
1191 }
1192 }
1193
1194 if ((s3info[i].info.compat.role == 1) &&
1195 (s3info[i].info.compat.id == 4)) {
1196
1197 }
1198
1199 break;
1200 case 3:
1201 pr_debug("Seq: %#x\n", s3info[i].info.buildseq);
1202
1203 break;
1204 case 4:
1205 pr_debug("Platform: ID %#x %d.%d.%d\n",
1206 s3info[i].info.version.id,
1207 s3info[i].info.version.major,
1208 s3info[i].info.version.minor,
1209 s3info[i].info.version.variant);
1210
1211 if (nicid.id != s3info[i].info.version.id)
1212 continue;
1213 if (nicid.major != s3info[i].info.version.major)
1214 continue;
1215 if (nicid.minor != s3info[i].info.version.minor)
1216 continue;
1217 if ((nicid.variant != s3info[i].info.version.variant) &&
1218 (nicid.id != 0x8008))
1219 continue;
1220
1221 trump = 1;
1222 break;
1223 case 0x8001:
1224 pr_debug("name inforec len %d\n", s3info[i].len);
1225
1226 break;
1227 default:
1228 pr_debug("Unknown inforec type %d\n", s3info[i].type);
1229 }
1230 }
1231
1232
1233 if (trump && (result != 2))
1234 result = 0;
1235 return result;
1236 }