[PATCH] Flash download works!!!

Pavel Roskin proski at gnu.org
Sun Apr 13 20:04:04 EDT 2003


Hello!

The problem with flash download appears to lie in the userspace.  When
dumping the actual data written to the card, I have found that the data is
different from the data written by prism2dl.  It was shifted by 4 bytes.

It turned out that the wrong data comes from the prism2_srec.  Function
combine_info() moves data in the wrong direction when it prepends the
checksum.

The patch is attached.  After applying the patch, my download code worked
right away, and I was able to upgrade secondary firmware on SMC2632W from
0.7.6 to 1.4.9.

The patch for firmware download is also attached, but it needs some work.
The card cannot be reset after download, so prism2_srec reports an error.
It's sufficient to eject and insert the card to see the new firmware.
Also, maxtimeout needs to be used in hfa384x_cmd_wait(), and it should be
done in a more graceful way.  At least this patch doesn't kill the card.

Testing shows that RAM download is not affected.  RAM download for primary
firmware still doesn't work.  Secondary firmware is still OK.

If we want to update primary firmware in the flash, prism2_srec should be
able to process primary and secondary firmware in one operation.  Flashing
only primary firmware makes the card unusable.  This was tested both with
prism2dl and prism2_srec.

-- 
Regards,
Pavel Roskin
-------------- next part --------------
--- utils/prism2_srec.c
+++ utils/prism2_srec.c
@@ -1315,7 +1315,7 @@ int combine_info(struct wlan_info *wlan,
 
 			s->data = realloc(s->data, s->len + 2);
 			assert(s->data != NULL);
-			memmove(s->data, s->data + 2, s->len);
+			memmove(s->data + 2, s->data, s->len);
 			s->addr -= 2;
 			s->len += 2;
 			s->data[0] = 0xDE;
-------------- next part --------------
--- driver/modules/hostap_download.c
+++ driver/modules/hostap_download.c
@@ -304,6 +304,154 @@ static int prism2_download_volatile(loca
 }
 
 
+static int prism2_download_nonvolatile(local_info_t *local,
+				       struct prism2_download_param *param,
+				       u8 **copied_data)
+{
+	struct net_device *dev = local->dev;
+	int ret = 0, i;
+	u16 maxloadtime;
+	struct {
+		u16 page;
+		u16 offset;
+		u16 len;
+	} dlbuffer;
+	u32 bufaddr;
+
+	if (local->hw_downloading) {
+		printk(KERN_WARNING "%s: Already downloading - aborting new "
+		       "request\n", dev->name);
+		return -1;
+	}
+
+	local->hw_downloading = 1;
+
+	ret = local->func->get_rid(dev, HFA384X_RID_MAXLOADTIME,
+				   &maxloadtime, 2, 0);
+
+	if (ret < 0) {
+		printk(KERN_WARNING "%s: Could not read maxloadtime\n",
+		       dev->name);
+		goto out;
+	}
+
+	printk(KERN_DEBUG "%s: Flash download timeout: %d msec\n",
+	       dev->name, maxloadtime);
+
+	ret = local->func->get_rid(dev, HFA384X_RID_DOWNLOADBUFFER,
+				   &dlbuffer, 6, 0);
+
+	if (ret < 0) {
+		printk(KERN_WARNING "%s: Could not read download buffer parameters\n",
+		       dev->name);
+		goto out;
+	}
+
+	printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n",
+	       dlbuffer.len, dlbuffer.page, dlbuffer.offset);
+
+	bufaddr = (dlbuffer.page << 7) + dlbuffer.offset;
+
+	prism2_hw_shutdown(dev, 0);
+
+	if (prism2_hw_init(dev, 0)) {
+		printk(KERN_WARNING "%s: Could not initialize card for "
+		       "download\n", dev->name);
+		ret = -1;
+		goto out;
+	}
+
+	hfa384x_disable_interrupts(dev);
+
+	if (prism2_enable_aux_port(dev, 1)) {
+		printk(KERN_WARNING "%s: Could not enable AUX port\n",
+		       dev->name);
+		ret = -1;
+		goto out;
+	}
+
+	for (i = 0; i < param->num_areas; i++) {
+		int rest_len = param->data[i].len;
+		int data_off = 0;
+
+		while (rest_len > 0) {
+			int block_len;
+			u16 param0, param1;
+
+			block_len = min_t (int, rest_len, 4096);
+
+			param0 = (param->data[i].addr + data_off) & 0xffff;
+			param1 = (param->data[i].addr + data_off) >> 16;
+
+			HFA384X_OUTW(block_len, HFA384X_PARAM2_OFF);
+			HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
+
+			if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
+						(HFA384X_PROGMODE_ENABLE_NON_VOLATILE << 8),
+						param0)) {
+				printk(KERN_WARNING "%s: Flash download command execution failed\n",
+				       dev->name);
+				ret = -1;
+				goto out;
+			}
+
+			if (hfa384x_to_aux(dev, bufaddr,
+					   block_len, copied_data[i] + data_off)) {
+				printk(KERN_WARNING "%s: flash download at 0x%08x "
+				       "(len=%d) failed\n", dev->name,
+				       param->data[i].addr, param->data[i].len);
+				ret = -1;
+				goto out;
+			}
+
+			HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
+			HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
+			if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
+						(HFA384X_PROGMODE_PROGRAM_NON_VOLATILE << 8),
+						0)) {
+				printk(KERN_WARNING "%s: Flash write command execution failed\n",
+				       dev->name);
+				ret = -1;
+				goto out;
+			}
+
+			rest_len -= block_len;
+			data_off += block_len;
+		}
+	}
+
+	HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
+	HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
+	if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
+				(HFA384X_PROGMODE_DISABLE << 8), 0)) {
+		printk(KERN_WARNING "%s: Download command execution failed\n",
+		       dev->name);
+		ret = -1;
+		goto out;
+	}
+
+	if (prism2_enable_aux_port(dev, 0)) {
+		printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
+		       dev->name);
+		/* continue anyway.. restart should have taken care of this */
+	}
+
+	mdelay(5);
+
+	local->func->hw_reset(dev);
+	if (prism2_hw_config(dev, 2)) {
+		printk(KERN_WARNING "%s: Card configuration after flash "
+		       "download failed\n", dev->name);
+		ret = -1;
+	}
+
+ out:
+
+	local->hw_downloading = 0;
+	return ret;
+}
+
+
 static int prism2_download(local_info_t *local,
 			   struct prism2_download_param *param)
 {
@@ -354,7 +502,7 @@ static int prism2_download(local_info_t 
 		ret = prism2_download_volatile(local, param, copied_data);
 		break;
 	case PRISM2_DOWNLOAD_NON_VOLATILE:
-		ret = -EOPNOTSUPP;
+		ret = prism2_download_nonvolatile(local, param, copied_data);
 		break;
 	default:
 		ret = -EINVAL;
--- driver/modules/hostap_hw.c
+++ driver/modules/hostap_hw.c
@@ -150,6 +150,7 @@ static unsigned char bridge_tunnel_heade
 /* ca. 10 usec */
 #define HFA384X_INIT_TIMEOUT 50000
 #define HFA384X_CMD_COMPL_TIMEOUT 20000
+#define HFA384X_DL_COMPL_TIMEOUT 1000000
 #define HFA384X_ALLOC_COMPL_TIMEOUT 1000
 
 
@@ -507,7 +508,12 @@ static int hfa384x_cmd_wait(struct net_d
 	HFA384X_OUTW(cmd, HFA384X_CMD_OFF);
 
         /* wait for command completion */
-        tries = HFA384X_CMD_COMPL_TIMEOUT;
+	if ((cmd & 0x3f) == HFA384X_CMDCODE_DOWNLOAD)
+		tries = HFA384X_DL_COMPL_TIMEOUT;
+	else
+	        tries = HFA384X_CMD_COMPL_TIMEOUT;
+
+
         while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD) &&
                tries > 0) {
                 tries--;


More information about the HostAP mailing list