--- airo.c.orig	2004-04-20 23:28:26.000000000 +0200
+++ airo.c	2004-05-20 20:20:03.000000000 +0200
@@ -1097,6 +1097,7 @@
 static int mpi_send_packet (struct net_device *dev);
 static void mpi_unmap_card(struct pci_dev *pci);
 static void mpi_receive_802_3(struct airo_info *ai);
+static void mpi_receive_802_11(struct airo_info *ai);
 static int waitbusy (struct airo_info *ai);
 
 static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs
@@ -2776,8 +2777,7 @@
 		printk(KERN_ERR "airo: Couldn't register_netdev\n");
 		goto err_out_map;
 	}
-	if (!test_bit(FLAG_MPI,&ai->flags))
-		ai->wifidev = init_wifidev(ai, dev);
+        ai->wifidev = init_wifidev(ai, dev);
 
 	set_bit(FLAG_REGISTERED,&ai->flags);
 	printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n",
@@ -3101,7 +3101,10 @@
 			u16 *buffer;
 
 			if (test_bit(FLAG_MPI,&apriv->flags)) {
-				mpi_receive_802_3(apriv);
+                                if test_bit(FLAG_802_11, &apriv->flags)
+                                        mpi_receive_802_11(apriv);
+                                else
+                                        mpi_receive_802_3(apriv);
 				OUT4500(apriv, EVACK, EV_RX);
 				goto exitrx;
 			}
@@ -3483,6 +3486,112 @@
 	}
 }
 
+void mpi_receive_802_11 (struct airo_info *ai)
+{
+        RxFid rxd;
+        struct sk_buff *skb = NULL;
+        u16 fc, len, hdrlen = 0;
+#pragma pack(1)
+        struct {
+                u16 status, len;
+                u8 rssi[2];
+                u8 rate;
+                u8 freq;
+                u16 tmp[4];
+        } hdr;
+#pragma pack()
+        u16 gap;
+        u16 *buffer;
+        char *ptr = ai->rxfids[0].virtual_host_addr+4;
+
+        memcpy ((char *)&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
+        memcpy ((char *)&hdr, ptr, sizeof(hdr));
+        ptr += sizeof(hdr);
+        /* Bad CRC. Ignore packet */
+        if (le16_to_cpu(hdr.status) & 2)
+                hdr.len = 0;
+        if (ai->wifidev == NULL)
+                hdr.len = 0;
+        len = le16_to_cpu(hdr.len);
+        if (len > 2312) {
+                printk( KERN_ERR "airo: Bad size %d\n", len );
+                goto badrx;
+        }
+        if (len == 0) 
+                goto badrx;
+
+        memcpy ((char *)&fc, ptr, sizeof(fc));
+        fc = le16_to_cpu(fc);
+        switch (fc & 0xc) {
+                case 4:
+                        if ((fc & 0xe0) == 0xc0)
+                                hdrlen = 10;
+                        else
+                                hdrlen = 16;
+                        break;
+                case 8:
+                        if ((fc&0x300)==0x300){
+                                hdrlen = 30;
+                                break;
+                        }
+                default:
+                        hdrlen = 24;
+        }
+
+        skb = dev_alloc_skb( len + hdrlen + 2 );
+        if ( !skb ) {
+                ai->stats.rx_dropped++;
+                goto badrx;
+        }
+        buffer = (u16*)skb_put (skb, len + hdrlen); 
+        memcpy ((char *)buffer, ptr, hdrlen);
+        ptr += hdrlen;
+        if (hdrlen == 24)
+                ptr += 6;
+        memcpy ((char *)&gap, ptr, sizeof(gap));
+        ptr += sizeof(gap);
+        gap = le16_to_cpu(gap);
+        if (gap) {
+                if (gap <= 8)
+                        ptr += gap;
+                else
+                        printk(KERN_ERR 
+                            "airo: gaplen too big. Problems will follow...\n");
+        }
+        memcpy ((char *)buffer + hdrlen, ptr, len);
+        ptr += len;
+#ifdef IW_WIRELESS_SPY          /* defined in iw_handler.h */
+        if (ai->spy_data.spy_number > 0) {
+                char *sa;
+                struct iw_quality wstats;
+                /* Prepare spy data : addr + qual */
+                sa = (char*)buffer + 10;
+                wstats.qual = hdr.rssi[0];
+                if (ai->rssi)
+                        wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm;
+                else
+                        wstats.level = (hdr.rssi[1] + 321) / 2;
+                wstats.updated = 3;
+                /* Update spy records */
+                wireless_spy_update(ai->dev, sa, &wstats);
+        }
+#endif /* IW_WIRELESS_SPY */
+        skb->mac.raw = skb->data;
+        skb->pkt_type = PACKET_OTHERHOST;
+        skb->dev = ai->wifidev;
+        skb->protocol = htons(ETH_P_802_2);
+        skb->dev->last_rx = jiffies;
+        skb->ip_summed = CHECKSUM_NONE;
+        netif_rx( skb );
+badrx:
+        if (rxd.valid == 0) {
+                rxd.valid = 1;
+                rxd.rdy = 0;
+                rxd.len = PKTSIZE;
+                memcpy (ai->rxfids[0].card_ram_off, (char *)&rxd, sizeof(rxd));
+        }
+}
+
 static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
 {
 	Cmd cmd;
@@ -3550,10 +3659,16 @@
 		status = readCapabilityRid(ai, &cap_rid, lock);
 		if ( status != SUCCESS ) return ERROR;
 
+                /*
+                 * This driver supports MPI350 firmwares up to, and
+                 * including 5.30.17
+                 */
 		if (test_bit(FLAG_MPI, &ai->flags) &&
-		    strcmp (cap_rid.prodVer, "5.00.01") &&
-		    strcmp (cap_rid.prodVer, "5.00.03") &&
-		    strcmp (cap_rid.prodVer, "5b00.08"))
+		    strncmp (cap_rid.prodVer, "5.00.", 5) &&
+		    strncmp (cap_rid.prodVer, "5b00.", 5) &&
+		    strncmp (cap_rid.prodVer, "5.02.", 5) &&
+		    strncmp (cap_rid.prodVer, "5.20.", 5) &&
+		    strncmp (cap_rid.prodVer, "5.30.", 5))
 			printk(KERN_ERR "airo: Firmware version %s is not supported. Use it at your own risk!\n", cap_rid.prodVer);
 
 		status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock);
@@ -3934,7 +4049,7 @@
 		memset(&rsp, 0, sizeof(rsp));
 
 		ai->config_desc.rid_desc.valid = 1;
-		ai->config_desc.rid_desc.len = RIDSIZE;
+		ai->config_desc.rid_desc.len = *((u16 *)pBuf);
 		ai->config_desc.rid_desc.rid = 0;
 
 		cmd.cmd = CMD_WRITERID;
@@ -4565,7 +4680,8 @@
 /*** Mode processing */
 		if ( !strncmp( line, "Mode: ", 6 ) ) {
 			line += 6;
-			if ((ai->config.rmode & 0xff) >= RXMODE_RFMON)
+			if ((ai->config.rmode & 0xff) >= RXMODE_RFMON &&
+                                !test_bit(FLAG_MPI,&ai->flags))
 					set_bit (FLAG_RESET, &ai->flags);
 			ai->config.rmode &= 0xfe00;
 			clear_bit (FLAG_802_11, &ai->flags);
@@ -5936,7 +6052,8 @@
 	int reset = 0;
 
 	readConfigRid(local, 1);
-	if ((local->config.rmode & 0xff) >= RXMODE_RFMON)
+	if ((local->config.rmode & 0xff) >= RXMODE_RFMON &&
+            !test_bit(FLAG_MPI,&local->flags))
 		reset = 1;
 
 	switch(*uwrq) {
