Index: linux/drivers/net/wireless/digi_wi_g.c
===================================================================
--- linux.orig/drivers/net/wireless/digi_wi_g.c	2007-12-05 19:56:42.000000000 +0100
+++ linux/drivers/net/wireless/digi_wi_g.c	2007-12-05 20:04:58.000000000 +0100
@@ -31,6 +31,15 @@
 #include <linux/vmalloc.h>      /* vmalloc */
 #include <linux/random.h>       /* get_random_bytes */
 
+#include <linux/version.h>
+
+#include <linux/mm.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/sysrq.h>
+#include <linux/smp.h>
+#include <linux/netpoll.h>
+
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>		/* NO_IRQ */
@@ -211,7 +220,9 @@
 #endif /* CONFIG_DIGI_WI_G_DEBUG */
 
 #define CLEAR( x )              memset( &(x), 0, sizeof( (x) ) )
-#define dw_rmw32( offs, op )    dw_iowrite32(dw_ioread32(offs) op,(offs))
+//#define dw_rmw32( offs, op )    dw_iowrite32(dw_ioread32(offs) op,(offs))
+#define dw_iosetbits32( offs, mask )    dw_iowrite32(dw_ioread32(offs)|(mask),(offs))
+#define dw_iocleanbits32( offs, mask )    dw_iowrite32(dw_ioread32(offs)&~(mask),(offs))
 
 #define BASIC_RATE_MASK( x ) ( (x) & ((unsigned char) ~IEEE80211_BASIC_RATE_MASK ))
 #define BASIC_RATE( x ) ( (x) | IEEE80211_BASIC_RATE_MASK )
@@ -335,6 +346,8 @@
 static int dw_close( struct net_device* dev );
 static void dw_set_multicast_list( struct net_device* dev );
 
+static void start_IBSS(struct dw_priv *priv);
+
 /* ********** Local Variables ********** */
 
 static const char* dw_version =
@@ -555,12 +568,16 @@
  *
  * no check for underrun is performed
  */
-static inline void dw_hw_read_fifo( void* _dst, int len )
+static inline void dw_hw_read_fifo( void * _dst, int _len )
 {
 	u32* dst = (u32 *) _dst;
+	int len = _len;
 
         DBG_MARK_VAL( RX_FIFO, len );
 
+	if ( dw_ioread32( HW_GEN_STATUS ) & STAT_RXFE )
+		printk("Reading from an EMPTY RX FIFO\n");
+
 	for( ; len >= 32; len -= 32 ) {
 		*dst++ = be32_to_cpu( dw_ioread32( HW_DATA_FIFO ) );
 		*dst++ = be32_to_cpu( dw_ioread32( HW_DATA_FIFO ) );
@@ -581,13 +598,17 @@
  *
  * no check for overrun is performed
  */
-static inline void dw_hw_write_fifo( const void* _src, int len)
+static inline void dw_hw_write_fifo( const void* _src, int _len )
 {
-	const u32* src = (const u32 *) _src;
-        
+    const u32* src = (const u32 *) _src;
+    int len = _len;
+
         DBG_MARK_VAL( TX_FIFO, len );
 
-	for( ; len >= 32; len -= 32 ) {
+    if ( dw_ioread32( HW_GEN_CONTROL ) & GEN_TXFIFOFULL )
+        printk("Writing to a FULL TX FIFO\n");
+
+    for( ; len >= 32; len -= 32 ) {
                 dw_iowrite32( cpu_to_be32( *src++ ), HW_DATA_FIFO );
                 dw_iowrite32( cpu_to_be32( *src++ ), HW_DATA_FIFO );
                 dw_iowrite32( cpu_to_be32( *src++ ), HW_DATA_FIFO );
@@ -596,9 +617,9 @@
                 dw_iowrite32( cpu_to_be32( *src++ ), HW_DATA_FIFO );
                 dw_iowrite32( cpu_to_be32( *src++ ), HW_DATA_FIFO );
                 dw_iowrite32( cpu_to_be32( *src++ ), HW_DATA_FIFO );
-	}
+    }
 
-	for( ; len > 0; len -= 4 )
+    for( ; len > 0; len -= 4 )
                 dw_iowrite32( cpu_to_be32( *src++ ), HW_DATA_FIFO );
 }
 
@@ -821,9 +842,9 @@
         priv->rx.pause = pause;
 
         if( pause )
-                dw_rmw32( HW_INTR_MASK, & ~INTR_RXFIFO );
+                dw_iocleanbits32( HW_INTR_MASK, INTR_RXFIFO );
         else
-                dw_rmw32( HW_INTR_MASK, | INTR_RXFIFO );
+                dw_iosetbits32( HW_INTR_MASK, INTR_RXFIFO );
 }
 
 /* ********** now the not inline stuff ********** */
@@ -1107,9 +1128,9 @@
         /* the reason of the error should have been reported already */
 
         /* give a pulse */
-	dw_rmw32( HW_GEN_CONTROL, | GEN_RXFIFORST );
+	dw_iosetbits32( HW_GEN_CONTROL, GEN_RXFIFORST );
         wmb();
-	dw_rmw32( HW_GEN_CONTROL, & ~GEN_RXFIFORST );
+	dw_iocleanbits32( HW_GEN_CONTROL, GEN_RXFIFORST );
         
 	priv->wstats.discard.misc++;
 }
@@ -1174,6 +1195,7 @@
                     default:
                         ERRORL( "Signal not defined %i %i", pskcck->signal,
                                 pskcck->length );
+
                         /* !TODO: Remove me when solved  */
                         dumpHexBuffer( hdr, sizeof( *hdr ) );
                         goto error;
@@ -1344,7 +1366,7 @@
         /* allocate next buffer */
         frame->skb = dev_alloc_skb( DW_MTU );
         if( unlikely( NULL == frame->skb ) ) {
-                dw_rmw32( HW_GEN_CONTROL, & ~GEN_RXEN );
+                dw_iocleanbits32( HW_GEN_CONTROL, GEN_RXEN );
                 panic( DRIVER_NAME ": Out of memory\n" );
         }
 
@@ -1361,6 +1383,8 @@
         int len;
         int ignore_frame = 0;
         u16 fc;
+	char spy_buf[2312];
+	unsigned int spy_len = 0;
 
         DBG_FN( DBG_RX | DBG_INT );
         DBG_MARK( RX_PROCESS_FRAME );
@@ -1383,8 +1407,11 @@
         element = priv->rx.queue.free.list.next;
         frame   = list_entry( element, dw_frame_rx_t, list );
 
+	memset(spy_buf, 0, sizeof(spy_buf)); spy_len = 0;
+
         /* copy frame header, swapped, we need it's header for length */
         dw_hw_read_fifo( &frame->hdr, sizeof( frame->hdr ) );
+	memcpy( spy_buf + spy_len, &frame->hdr, sizeof( frame->hdr ) ); spy_len += sizeof( frame->hdr );
 
         len = dw_rx_frame_get_length( frame );
 
@@ -1400,7 +1427,12 @@
                 
 
                 /* reads data and keeps track of remaining_len */
-#define READ_FIFO( to_read ) do { dw_hw_read_fifo( data, to_read ); data += to_read; remaining_len -= to_read; ASSERT( remaining_len >= 0 ); } while( 0 )
+#define READ_FIFO( to_read ) do { \
+		dw_hw_read_fifo( data, to_read ); \
+		memcpy( spy_buf + spy_len, data, to_read ); spy_len += to_read; \
+		data += to_read; \
+		remaining_len -= to_read; \
+		ASSERT( remaining_len >= 0 ); } while( 0 )
 
                 /* read header */
                 READ_FIFO( sizeof( struct ieee80211_hdr ) );
@@ -1486,11 +1518,14 @@
                         /* retrieve remaining unencrypted data.
                            We read FCS, but stack will ignore it. */
                         dw_hw_read_fifo( data, remaining_len );
+			memcpy( spy_buf + spy_len, data, remaining_len ); spy_len += remaining_len;
                 }
         } else {
                 if( len > DW_MTU )
-                        ERROR( "Oversized frame with %i bytes, ignoring it\n",
-                               len );
+		{
+                        ERROR( "Oversized frame with %i bytes, ignoring it\n", len );
+
+		}
                 
                 spin_lock( &priv->ieee->lock );
                 priv->ieee->stats.rx_length_errors++;
@@ -1612,17 +1647,18 @@
 
         /* reset FIFO */
 
-        dw_rmw32( HW_GEN_CONTROL, | GEN_TXFIFORST );
+        dw_iosetbits32( HW_GEN_CONTROL, GEN_TXFIFORST );
         wmb();
-        dw_rmw32( HW_GEN_CONTROL, & ~GEN_TXFIFORST );
+        dw_iocleanbits32( HW_GEN_CONTROL, GEN_TXFIFORST );
 
         /* retransmit it */
 
         if( likely( !list_empty( &priv->tx.queued ) ) ) {
                 dw_frame_tx_t* frame = list_entry( priv->tx.queued.prev, dw_frame_tx_t, list );
                 dw_tx_fragment_send( priv, frame );
-        } else
+        } else {
                 ERROR( "Tx Queue is empty, but we have a tx timeout????" );
+        }
 }
 
 /**
@@ -1950,14 +1986,14 @@
         }
         /* sent frame, either bye AES or unencrypted engine */
         if( !frame->s.use_hw_encryption ) { 
-		/* Prevent transmitting until all data have been written into the tx fifo */
+        /* Prevent transmitting until all data have been written into the tx fifo */
                 dw_iowrite32( hw_gen_ctrl | GEN_TXHOLD, HW_GEN_CONTROL );
                 dw_hw_write_fifo( &frag->hdr, sizeof( frag->hdr ) );
                 dw_hw_write_fifo( skb->data,  skb->len );
-		dw_iowrite32( hw_gen_ctrl, HW_GEN_CONTROL );
+                dw_iowrite32( hw_gen_ctrl, HW_GEN_CONTROL );
         } else {
                 ccmp_data_t cdata;
-                u8          extiv[ EXTIV_SIZE ];
+                u8 extiv[ EXTIV_SIZE ];
 
                 dw_ccmp_get_data_tx( priv, hdr3, frag, &cdata, extiv, skb->len - sizeof( *hdr3 ) );
 
@@ -1965,11 +2001,11 @@
                 dw_hw_aes_wait();
                 
                 /* prevent transmitting until encrypted data is ready */
-                dw_rmw32( HW_GEN_CONTROL, | GEN_TXHOLD );
+                dw_iosetbits32( HW_GEN_CONTROL, GEN_TXHOLD );
 
                 /* write MAC, Frame Header and IV FIFO */
-                dw_hw_write_fifo( &frag->hdr, sizeof( frag->hdr ) );
-                dw_hw_write_fifo( hdr3,       sizeof( *hdr3 ) );
+                dw_hw_write_fifo( &frag->hdr, sizeof( frag->hdr )  );
+                dw_hw_write_fifo( hdr3, sizeof( *hdr3 )  );
                 dw_hw_write_fifo( &extiv, sizeof( extiv ) );
 
                 /* configure mode and key */
@@ -1980,7 +2016,7 @@
                 dw_hw_aes_write_fifo( &cdata, sizeof( cdata ) );
 
                 /* start transmit */
-                dw_rmw32( HW_GEN_CONTROL, & ~GEN_TXHOLD );
+                dw_iocleanbits32( HW_GEN_CONTROL, GEN_TXHOLD );
 
                 /* write plaintext data to AES FIFO */
                 dw_hw_aes_write_fifo( hdr3->payload, skb->len - sizeof( *hdr3 ) );
@@ -2132,6 +2168,15 @@
 
         if( status & ( INTR_TBTT | INTR_ATIM ) ) {
                 /* is emitted by hardware even if masked out :-(. */
+                // TBTT = Target Beacon Transmission Time
+                // ATIM = Announcement Traffic Indication Message
+                //if (status & INTR_TBTT) printk("TBTT / ATIM > Time to trasmit a beacon\n");
+                //else printk("TBTT / ATIM > End of ATIM interval\n");
+
+                // Beacon frame is already in beacon buffer.
+                // Only set backoff timer here.
+                dw_cw_set( priv, IEEE80211_STYPE_BEACON );
+
                 DBG_EXEC( status &= ~( INTR_TBTT | INTR_ATIM ) );
         }
         
@@ -2159,6 +2204,127 @@
         return IRQ_HANDLED;
 }
 
+static int dw_ieee80211_handle_beacon (
+	struct net_device * dev,
+	struct ieee80211_beacon * beacon,
+	struct ieee80211_network * network)
+{
+//	printk("Beacon (0x%02X)\n", beacon->info_element->id);
+//	dumpHexBuffer(beacon->info_element->data, beacon->info_element->len);
+	return ieee80211softmac_handle_beacon(dev, beacon, network);
+}
+
+static int dw_ieee80211_handle_probe_response (
+	struct net_device * dev,
+	struct ieee80211_probe_response * resp,
+	struct ieee80211_network * network)
+{
+//	printk("Probe Response (0x%02X)\n", resp->info_element->id);
+//	dumpHexBuffer(resp->info_element->data, resp->info_element->len);
+	return ieee80211softmac_handle_probe_resp(dev, resp, network);
+}
+
+/* Allocate a management frame */
+static u8 * ieee80211softmac_alloc_mgt(u32 size)
+{
+	u8 * data;
+
+	/* Add the header and FCS to the size */
+	size = size + IEEE80211_3ADDR_LEN;
+	if(size > IEEE80211_DATA_LEN)
+		return NULL;
+	/* Allocate the frame */
+	data = kzalloc(size, GFP_ATOMIC);
+	return data;
+}
+
+static void 
+ieee80211softmac_hdr_2addr(struct ieee80211softmac_device *mac,
+	struct ieee80211_hdr_2addr *header, u32 type, u8 *dest)
+{
+	/* Fill in the frame control flags */
+	header->frame_ctl = cpu_to_le16(type);
+	/* Control packets always have WEP turned off */	
+	if(type > IEEE80211_STYPE_CFENDACK && type < IEEE80211_STYPE_PSPOLL)
+		header->frame_ctl |= mac->ieee->sec.level ? cpu_to_le16(IEEE80211_FCTL_PROTECTED) : 0;
+
+	/* Fill in the duration */
+	header->duration_id = 0;
+	/* FIXME: How do I find this?
+	 * calculate. But most drivers just fill in 0 (except if it's a station id of course) */
+
+	/* Fill in the Destination Address */
+	if(dest == NULL)
+		memset(header->addr1, 0xFF, ETH_ALEN);
+	else
+		memcpy(header->addr1, dest, ETH_ALEN);
+	/* Fill in the Source Address */
+	memcpy(header->addr2, mac->ieee->dev->dev_addr, ETH_ALEN);
+}
+
+static void 
+ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac,
+	struct ieee80211_hdr_3addr *header, u32 type, u8 *dest, u8 *bssid)
+{
+	/* This is common with 2addr, so use that instead */
+	ieee80211softmac_hdr_2addr(mac, (struct ieee80211_hdr_2addr *)header, type, dest);	
+	
+	/* Fill in the BSS ID */
+	if(bssid == NULL)
+		memset(header->addr3, 0xFF, ETH_ALEN);
+	else
+		memcpy(header->addr3, bssid, ETH_ALEN);
+
+	/* Fill in the sequence # */
+	/* FIXME: I need to add this to the softmac struct
+	 * shouldn't the sequence number be in ieee80211? */
+}
+
+static int dw_ieee80211_handle_probe_request (
+	struct net_device * dev,
+	struct ieee80211_probe_request * req,
+	struct ieee80211_rx_stats * stats)
+{
+	dw_priv_t* priv = ieee80211softmac_priv( dev );
+	if (priv->softmac->associnfo.associate_essid.len == req->info_element->len &&
+		memcmp(priv->softmac->associnfo.associate_essid.data, req->info_element->data, priv->softmac->associnfo.associate_essid.len) == 0)
+	{
+		struct ieee80211_probe_response *pkt = NULL;
+		struct ieee80211softmac_device *mac = priv->softmac;
+		struct ieee80211softmac_network *net = &priv->adhoc;
+		u8 *data;
+		u32 pkt_size = 0;
+		int encrypt_mpdu = 0;
+
+		if (!priv->beacon_ready) printk("Probe Request: Beacon not ready\n");
+		printk("Probe Request (0x%02X)\n", req->info_element->id);
+		dumpHexBuffer(req->info_element->data, req->info_element->len);
+		printk ("My Data: bssid=%02x:%02x:%02x:%02x:%02x:%02x "
+			"ssid=%.*s chan=%d\n",
+			priv->dev->dev_addr[0], priv->dev->dev_addr[1], priv->dev->dev_addr[2],
+			priv->dev->dev_addr[3], priv->dev->dev_addr[4], priv->dev->dev_addr[5],
+			priv->softmac->associnfo.req_essid.len, priv->softmac->associnfo.req_essid.data, priv->channel);
+
+		pkt = (struct ieee80211_probe_response *)ieee80211softmac_alloc_mgt( priv->beacon_body_length );
+
+		if (unlikely(pkt == NULL))
+		{
+			printk("Error, packet is nonexistant or 0 length\n");
+			return -ENOMEM;
+		}
+
+		ieee80211softmac_hdr_3addr(mac, &(pkt->header), IEEE80211_STYPE_PROBE_RESP, net->bssid, priv->adhoc.bssid);
+		data = (u8 *)pkt->info_element;
+		memcpy(pkt->info_element, priv->beacon_frame.body, priv->beacon_body_length);
+		data += priv->beacon_body_length;
+		pkt_size = (data - (u8 *)pkt);
+		ieee80211_tx_frame(priv->ieee, (struct ieee80211_hdr *)pkt, IEEE80211_3ADDR_LEN, pkt_size, encrypt_mpdu);
+		kfree(pkt);
+	}
+
+	return 0;
+}
+
 /**
  * dw_ieee80211_hard_start_xmit - prepares and sends a frame or put it in tx
  * queue for transmission when current frames are completed.
@@ -2366,6 +2532,108 @@
         spin_unlock( &priv->softmac->lock );
 }
 
+/* call this to do whatever is necessary when we're associated */
+static void dw_associate(struct ieee80211softmac_device *mac,
+	struct ieee80211_assoc_response * resp,
+	struct ieee80211softmac_network *net)
+{
+	u16 cap = 0;
+	u8 erp_value = net->erp_value;
+
+	if (resp != NULL)
+		cap = le16_to_cpu(resp->capability);
+	mac->associnfo.associating = 0;
+	mac->bssinfo.supported_rates = net->supported_rates;
+	ieee80211softmac_recalc_txrates(mac);
+
+	mac->associnfo.associated = 1;
+
+	if (resp != NULL)
+		mac->associnfo.short_preamble_available =
+		(cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0;
+	ieee80211softmac_process_erp(mac, erp_value);
+
+	if (mac->set_bssid_filter)
+		mac->set_bssid_filter(mac->dev, net->bssid);
+	memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN);
+	netif_carrier_on(mac->dev);
+
+	if (resp != NULL)
+		mac->association_id = le16_to_cpup(&resp->aid);
+}
+
+static void dw_handle_adhoc(dw_priv_t *priv)
+{
+	unsigned long flags;
+	int channel = priv->adhoc.channel;
+
+	if (!channel) channel = priv->channel;
+	if (!channel) channel = DW_IBSS_DEFAULT_CHANNEL;
+
+	if (
+			!priv->beacon_ready &&
+			!priv->softmac->scanning &&
+			!priv->softmac->associnfo.associating &&
+			//!priv->softmac->associnfo.associated &&
+			IW_MODE_ADHOC == priv->ieee->iw_mode
+		)
+	{
+		struct ieee80211softmac_network *net;
+		struct ieee80211softmac_device *mac = priv->softmac;
+
+		memset(&priv->adhoc, 0, sizeof(priv->adhoc));
+		get_random_bytes(priv->adhoc.bssid, ETH_ALEN); // Select a random BSSID
+		priv->adhoc.bssid[0] &= ~DW_MAC_GROUP;  // clear group bit
+		priv->adhoc.bssid[0] |=  DW_MAC_LOCAL;  // set local bit
+		priv->adhoc.channel = channel;
+		priv->adhoc.mode=IW_MODE_ADHOC;
+		priv->adhoc.essid.len = mac->associnfo.req_essid.len;
+		memcpy(priv->adhoc.essid.data, mac->associnfo.req_essid.data, IW_ESSID_MAX_SIZE + 1);
+
+		net = ieee80211softmac_get_network_by_essid_locked(priv->softmac, &priv->softmac->associnfo.associate_essid);
+		if (!net)
+		{
+			//printk ("!net\n");
+			net = &priv->adhoc;
+
+			mac->set_channel(mac->dev, net->channel);
+			if (mac->set_bssid_filter)
+				mac->set_bssid_filter(mac->dev, net->bssid);
+
+			spin_lock_irqsave(&mac->lock, flags);
+			dw_associate(mac, NULL, net);
+			ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATED, net);
+			spin_unlock_irqrestore(&mac->lock, flags);
+
+			mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
+			mac->associnfo.bssvalid = 1;
+			mac->associnfo.channel = net->channel;
+			memcpy(mac->associnfo.bssid, net->bssid, ETH_ALEN);
+			mac->associnfo.associate_essid.len = net->essid.len;
+			memcpy(mac->associnfo.associate_essid.data, net->essid.data, IW_ESSID_MAX_SIZE + 1);
+		}
+		else
+		{
+			memcpy(priv->adhoc.bssid, net->bssid, ETH_ALEN);
+			priv->adhoc.essid.len = net->essid.len;
+			memcpy(priv->adhoc.essid.data, net->essid.data, IW_ESSID_MAX_SIZE + 1);
+		}
+
+		//dprintk(KERN_INFO PFX "Associating to ad-hoc bssid " MAC_FMT "\n", MAC_ARG(net->bssid)); /* P3 */
+
+		//printk ("ADHOC: addr=%02x:%02x:%02x:%02x:%02x:%02x bssid=%02x:%02x:%02x:%02x:%02x:%02x ssid=%.*s chan=%d\n",
+		//	priv->dev->dev_addr[0], priv->dev->dev_addr[1], priv->dev->dev_addr[2],
+		//	priv->dev->dev_addr[3], priv->dev->dev_addr[4], priv->dev->dev_addr[5],
+		//	net->bssid[0], net->bssid[1], net->bssid[2],
+		//	net->bssid[3], net->bssid[4], net->bssid[5],
+		//	//priv->softmac->associnfo.req_essid.len, priv->softmac->associnfo.req_essid.data, priv->channel
+		//	mac->associnfo.req_essid.len, mac->associnfo.req_essid.data, net->channel
+		//);
+		start_IBSS(priv);
+		//priv->softmac->associnfo.associating = 1;
+	}
+}
+
 /**
  * dw_management_timer - performs all periodic background non tx/rx work 
  */
@@ -2373,11 +2641,17 @@
 {
 	dw_priv_t*    priv = (dw_priv_t*) a;
 	unsigned long flags;
+	unsigned long j;
         
         DBG_FN( DBG_UPDATE_RATE );
 
 	dw_lock( priv, flags );
 
+	if (IW_MODE_ADHOC == priv->ieee->iw_mode && !priv->softmac->scanning)
+	{
+		dw_handle_adhoc(priv);
+	}
+
         dw_update_status_led( priv );
 
         if( priv->rate.have_activity ) {
@@ -2396,13 +2670,15 @@
                 /* we don't need to update rate each LED timer event */
                 dw_rate_update( priv );
 
-        if( priv->tx.pending && time_after( jiffies, priv->dev->trans_start + TX_TIMEOUT ) )
+        if( priv->tx.pending && time_after( j = jiffies, priv->dev->trans_start + TX_TIMEOUT ) )
+	{
                 /* we can't use tx_timeout. It only works when
                  * netif_carrier_ok, but that is set only when associated.
                  * But we could loose association and run into a tx
                  * hanger. Therefore we;d never get associated, and never
                  * reset.So do it homemade. */
                 dw_tx_reset( priv );
+	}
         
 	mod_timer( &priv->management_timer, jiffies + MANAGEMENT_JIFFIES );
 	dw_unlock( priv, flags );
@@ -2654,6 +2930,9 @@
 	priv->ieee->modulation = IEEE80211_OFDM_MODULATION | IEEE80211_CCK_MODULATION;
 	priv->ieee->hard_start_xmit = dw_ieee80211_hard_start_xmit;
 	priv->ieee->set_security    = dw_ieee80211_set_security;
+	priv->ieee->handle_beacon   = dw_ieee80211_handle_beacon;
+	priv->ieee->handle_probe_response = dw_ieee80211_handle_probe_response;
+	priv->ieee->handle_probe_request = dw_ieee80211_handle_probe_request;
 	priv->ieee->iw_mode         = IW_MODE_INFRA;
 	priv->ieee->freq_band       = IEEE80211_24GHZ_BAND;
 	priv->ieee->rts             = DW_MAX_RTS_THRESHOLD;
@@ -3307,7 +3586,9 @@
 
         if( !was_locked )
                 dw_lock( priv, flags );
-        
+
+        priv->beacon_ready = 0;
+
 	/* Set BSSID in hardware */
 	dw_hw_memcpy_to( HW_BSSID0, bssid, ETH_ALEN );
 
@@ -3339,7 +3620,7 @@
 
 		dw_hw_memcpy_to( HW_SSID, priv->softmac->associnfo.associate_essid.data, priv->softmac->associnfo.associate_essid.len);
 		/* Disable IBSS mode */
-		dw_rmw32( HW_MAC_CONTROL, & ~(CTRL_IBSS|CTRL_BEACONTX) );
+		//dw_iocleanbits32( HW_MAC_CONTROL, CTRL_IBSS | CTRL_BEACONTX );
 	} else {
                 /* reset it */
                 for( i = 0; i < ARRAY_SIZE( dw_rates ); i++ )
@@ -3372,8 +3653,8 @@
         DBG_MARK( SET_CHANNEL );
         REQUIRE_LOCKED( priv );
         
-	dw_rmw32( HW_GEN_CONTROL, & ~GEN_RXEN );
-
+	dw_iocleanbits32( HW_GEN_CONTROL, GEN_RXEN );
+	priv->beacon_ready = 0;
 
 	/* Set frequency divider for channel */
 	dw_hw_write_rf (1, freq_table[channel].integer);
@@ -3408,7 +3689,7 @@
         dw_hw_set_vco( channel );
 #endif
 	priv->channel = channel;
-	dw_rmw32( HW_GEN_CONTROL, | GEN_RXEN );
+	dw_iosetbits32( HW_GEN_CONTROL, GEN_RXEN );
 }
 
 /***********************************************************************
@@ -3419,15 +3700,19 @@
 static void dw_softmac_set_chan( struct net_device* dev, u8 channel )
 {
 	dw_priv_t*    priv = ieee80211softmac_priv(dev);
+	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
 	unsigned long flags;
 
         DBG_FN( DBG_INTERFACE | DBG_MINOR );
 
+        //if (IW_MODE_ADHOC == priv->ieee->iw_mode && !mac->scanning )
+        //    printk("Selected channel = %d\n", channel);
+
         /* we really don't want to change the channel while there is something
          * in the queue for a different channel */
         dw_tx_wait_for_idle_and_pause( priv );
         
-	dw_lock( priv, flags );
+        dw_lock( priv, flags );
         dw_set_channel(  priv, channel );
         dw_unlock( priv, flags );
 
@@ -3605,6 +3890,7 @@
 	return 0;
 }
 
+static void MakeBeacon (dw_priv_t * priv, int interval);
 
 /***********************************************************************
  * @Function: dw_wx_set_mode
@@ -3622,9 +3908,25 @@
         DBG_FN( DBG_INTERFACE | DBG_MINOR );
 
 	spin_lock_irqsave(&priv->ieee->lock, ieeeflags);
+
 	priv->ieee->iw_mode = data->mode;
+
+	if (IW_MODE_ADHOC == priv->ieee->iw_mode)
+	{
+		if (priv->channel)
+			priv->adhoc.channel = priv->channel;
+	}
+	else
+	{
+		dw_iocleanbits32( HW_MAC_CONTROL, CTRL_IBSS|CTRL_BEACONTX ); /* Disable IBSS mode */
+	}
+
+	priv->beacon_ready = 0;
+	priv->beacon_body_length=0;
+
 	spin_unlock_irqrestore(&priv->ieee->lock, ieeeflags);
 
+
 	return 0;
 }
 
@@ -4236,7 +4538,7 @@
         }
         dw_list_move( &priv->tx.free, &priv->tx.queued );
 
-	dw_rmw32( HW_GEN_CONTROL, & ~GEN_RXEN );
+	dw_iocleanbits32( HW_GEN_CONTROL, GEN_RXEN );
 	dw_iowrite32( 0, HW_INTR_MASK );
 	dw_iowrite32( dw_ioread32( HW_INTR_STATUS ), HW_INTR_STATUS );
 
@@ -4274,6 +4576,11 @@
         priv->softmac->txrates.default_rate = priv->softmac->txrates.user_rate = IEEE80211_CCK_RATE_1MB;
 
         dw_lock( priv, flags );
+
+        priv->beacon_ready = 0;
+        priv->beacon_body_length=0;
+        priv->adhoc.channel = DW_IBSS_DEFAULT_CHANNEL;
+
         /* acknowledge pending interrupts */
 	dw_iowrite32( dw_ioread32( HW_INTR_STATUS ), HW_INTR_STATUS );
 	dw_iowrite32( INTR_ALL,       HW_INTR_MASK );
@@ -4282,7 +4589,7 @@
 
         enable_irq( dev->irq );
 
-	dw_rmw32( HW_GEN_CONTROL, | GEN_RXEN );
+	dw_iosetbits32( HW_GEN_CONTROL, GEN_RXEN );
 
         dw_unlock( priv, flags );
 
@@ -4303,9 +4610,9 @@
 
 	dw_lock(priv, flags);
         if(dev->flags & IFF_PROMISC) {
-		dw_rmw32( HW_MAC_CONTROL, | CTRL_PROMISC );
+		dw_iosetbits32( HW_MAC_CONTROL, CTRL_PROMISC );
 	} else {
-		dw_rmw32( HW_MAC_CONTROL, & ~CTRL_PROMISC );
+		dw_iocleanbits32( HW_MAC_CONTROL, CTRL_PROMISC );
 	}
 	dw_unlock(priv, flags);
 }
@@ -4516,3 +4823,284 @@
 #ifndef MODULE
 __setup( "dw_sw_aes=", dw_sw_cmdline );
 #endif /* MODULE */
+
+
+
+// Must be ordered by modulation type, then by increasing bit rate
+static const RateInfo rateInfo[] = {
+	{ 2,   0,   DW_LENGTH_uS (ACK_SIZE, 2)   },
+	{ 4,   0,   DW_LENGTH_uS (ACK_SIZE, 4)   },
+	{ 11,  0,   DW_LENGTH_uS (ACK_SIZE, 11)  },
+	{ 22,  0,   DW_LENGTH_uS (ACK_SIZE, 22)  },
+	{ 12,  0xb, DW_OFDM_DUR (ACK_SIZE, 12)  },
+	{ 18,  0xf, DW_OFDM_DUR (ACK_SIZE, 18)  },
+	{ 24,  0xa, DW_OFDM_DUR (ACK_SIZE, 24)  },
+	{ 36,  0xe, DW_OFDM_DUR (ACK_SIZE, 36)  },
+	{ 48,  0x9, DW_OFDM_DUR (ACK_SIZE, 48)  },
+	{ 72,  0xd, DW_OFDM_DUR (ACK_SIZE, 72)  },
+	{ 96,  0x8, DW_OFDM_DUR (ACK_SIZE, 96)  },
+	{ 108, 0xc, DW_OFDM_DUR (ACK_SIZE, 108) },
+};
+
+#define	RATE_NUM	((int)(sizeof rateInfo/sizeof rateInfo[0]))
+
+// Supported rates info elements
+static const u8 ratesA[]  = { DW_ELEM_SUPRATES, 8, DW_RATE_BASIC+12, 18, DW_RATE_BASIC+24, 36, DW_RATE_BASIC+48, 72, 96, 108 };
+static const u8 ratesB[]  = { DW_ELEM_SUPRATES, 4, DW_RATE_BASIC+2, DW_RATE_BASIC+4, 11, 22 };
+static const u8 ratesG[]  = { DW_ELEM_SUPRATES, 8, DW_RATE_BASIC+2, DW_RATE_BASIC+4, 11, 22, 12, 18, 24, 36 };
+static const u8 ratesGx[] = { DW_ELEM_EXTSUPRATES, 4, 48, 72, 96, 108 };
+
+#define	RATE_MIN_A		4
+#define	RATE_MIN_B		0
+
+#ifdef NODEF
+//
+// Set the frame and PLCP headers in a frame.
+// Buffer has its length field set.
+// @param buf Frame to modify
+// @param rate Transmit rate index
+//
+static void SetPLCP (dw_beacon_frame *buf, int rate)
+{
+	int length = buf->length;
+	
+	buf->frameHdr.hdr32 = 0;
+	
+	// Length in words, including Frame Header and PLCP Header, and excluding FCS, rounded up
+	buf->frameHdr.tx.length = ( length - DW_FCS_SIZE + 3) / 4;
+	
+	// OFDM rates
+	if (rateInfo[rate].ofdmCode)
+	{
+		buf->frameHdr.tx.mod_type = DW_MOD_OFDM;
+		buf->plcpHdr.plcp32 = 0;
+		buf->plcpHdr.ofdm.rate = rateInfo[rate].ofdmCode;
+		buf->plcpHdr.ofdm.length = length;
+
+		// Swap bytes of OFDM PLCP header
+		buf->plcpHdr.plcp32 = SWAP32 (buf->plcpHdr.plcp32);
+	}
+	
+	// PSK/CCK rates.
+	else
+	{
+		buf->frameHdr.tx.mod_type = MOD_PSKCCK;
+		buf->plcpHdr.pskcck.signal = 5*rateInfo[rate].bps;
+		buf->plcpHdr.pskcck.service = SERVICE_LOCKED;
+		
+		// Convert length from bytes to microseconds.
+		// Use a switch to avoid a long divide operation.
+		switch (rateInfo[rate].bps)
+		{
+			case 2:
+				length *= 8;
+				break;
+			case 4:
+				length *= 4;
+				break;
+			case 11:
+				length = (16*length+10)/11;
+				break;
+			case 22:
+				length = (8*length+10)/11;
+
+				// Set length extension bit if needed
+				if ((11*length)/8 > buf->length)
+					buf->plcpHdr.pskcck.service |= SERVICE_LENEXT;
+				break;
+		}
+			
+		buf->plcpHdr.pskcck.length = cpu_to_le16(length);
+	}
+	
+	// Swap bytes of frame header
+	buf->frameHdr.hdr32 = SWAP32 (buf->frameHdr.hdr32);
+}
+#endif
+
+#define DW_FCS_SIZE 4 // FCS (CRC-32) size
+
+static void SetPLCP(dw_hw_hdr_tx_t * hdr, int rate, size_t phys_len)
+{
+        size_t length = phys_len;
+        memset( hdr, 0, sizeof( *hdr ) );
+
+	// Length in words, including Frame Header and PLCP Header, and excluding FCS, rounded up
+	// FCS is added automatically
+        hdr->mod.length = ( phys_len - DW_FCS_SIZE + 3) / 4;
+
+        /* FCS length is required for signal */
+        length += IEEE80211_FCS_LEN;
+        if( !ieee80211_is_cck_rate( rate ) ) {
+                hdr->mod.mod_type     = MOD_OFDM;
+                hdr->plcp.ofdm.rate   = dw_plcp_get_ratecode_ofdm( rate );
+                hdr->plcp.ofdm.length = length;
+                hdr->plcp.ofdm.raw32  = cpu_to_le32( hdr->plcp.ofdm.raw32 );
+        } else {
+                int signal = dw_plcp_get_ratecode_cck( rate );
+                hdr->mod.mod_type        = MOD_PSKCCK;
+                hdr->plcp.pskcck.signal  = signal;
+                hdr->plcp.pskcck.service = SERVICE_LOCKED;
+
+                /* convert length from bytes to microseconds */
+                switch( signal ) {
+                    case 10:  length *= 8; break;
+                    case 20:  length *= 4; break;
+                    case 55:  length = ( 16 * length + 10 ) / 11; break;
+                    case 110:
+                        length = ( 8 * length + 10 ) / 11;
+                        /* set length extension bit if needed */
+                        if( ( 11 * length ) / 8 > (  phys_len + IEEE80211_FCS_LEN ) )
+                                hdr->plcp.pskcck.service |= SERVICE_LENEXT;
+                        break;
+                    default:
+                        ERRORL( "Unsupported signal/rate %i/%i", signal, rate );
+                        break;
+                }
+                hdr->plcp.pskcck.length = cpu_to_le16( length );
+                hdr->plcp.pskcck.raw32  = cpu_to_le32( hdr->plcp.pskcck.raw32);
+        }
+        hdr->mod.raw32 = cpu_to_le32( hdr->mod.raw32 );
+}
+
+//
+// Store supported rates elements into a buffer
+// @param bp Pointer into buffer
+// @param elem Element to store: DW_ELEM_SUPRATES, DW_ELEM_EXTSUPRATES, or 0 for both
+// @param channel Channel number
+// @return Updated buffer pointer
+//
+static u8 *SetRates (u8 *bp, int elem, int channel)
+{
+	const u8 *sr;
+	
+	// Select rate set
+	if (DW_CHAN_5G (channel))
+		sr = ratesA;
+	//else if (OPT_BONLY)
+	//	sr = ratesB;
+	else
+		sr = ratesG;
+
+	// Store up to 8 supported rates
+	if (elem != DW_ELEM_EXTSUPRATES)
+	{
+		memcpy (bp, sr, sr[1]+2);
+		bp += bp[1] + 2;
+	}
+	
+	// Store remaining extended supported rates
+	if (elem != DW_ELEM_SUPRATES && sr == ratesG)
+	{
+		memcpy (bp, ratesGx, ratesGx[1]+2);
+		bp += bp[1] + 2;
+	}
+
+	return bp;
+}
+
+//
+// Create beacon and probe response frames to send in an IBSS
+// @param interval Beacon interval in TU
+// @return 1 if success, 0 if error
+//
+static void MakeBeacon (dw_priv_t * priv, int interval)
+{
+    dw_beacon_frame * bcnFrame = &priv->beacon_frame;
+    u16 atimWindow = 0; // ATIM window size, 0 if none
+
+    u8 *bp = bcnFrame->body;
+    u16 bss_caps = 0, caps;
+
+    u8 bss_addr[ ETH_ALEN ];
+
+    priv->beacon_body_length = 0;
+
+    bss_caps = DW_CAP_IBSS;
+    //if (!(macParams.encrypt & WLN_ENCR_OPEN))
+    //    bss_caps |= CAP_PRIVACY;
+    //if (OPT_SHORTPRE)
+    //    bss_caps |= CAP_SHORTPRE;
+
+    memcpy(bss_addr, priv->adhoc.bssid, ETH_ALEN);
+
+    // Init beacon MAC header
+    memset (bcnFrame, 0, sizeof (dw_beacon_frame));
+    bcnFrame->fc = IEEE80211_STYPE_BEACON;
+    memset (bcnFrame->addr1, 0xff, ETH_ALEN);
+    DW_SET_ADDR (bcnFrame->addr2, priv->dev->dev_addr); // station MAC address
+    DW_SET_ADDR (bcnFrame->addr3, bss_addr); // BSS to associate with
+
+    // Set fixed params
+    // Timestamp is set by hardware
+    SET16 (&bp[8], interval);
+
+    // Set capabilities
+    caps = bss_caps & (DW_CAP_ESS|DW_CAP_IBSS|DW_CAP_PRIVACY);
+    // Use short preamble if allowed in BSS and params and rate > 1 mbps.
+    // caps |= DW_CAP_SHORTPRE;
+    SET16 (&bp[10], caps);
+    bp += 12;
+
+    // Set SSID
+    bp[0] = DW_ELEM_SSID;
+    bp[1] = priv->softmac->associnfo.req_essid.len;
+    memcpy (&bp[2], priv->softmac->associnfo.req_essid.data, priv->softmac->associnfo.req_essid.len);
+    bp += bp[1] + 2;
+
+    // Set supported rates
+    bp = SetRates (bp, DW_ELEM_SUPRATES, priv->adhoc.channel);
+
+    // Set channel number
+    if (!DW_CHAN_5G (priv->adhoc.channel))
+    {
+        bp[0] = DW_ELEM_DSPARAM;
+        bp[1] = 1;
+        bp[2] = priv->adhoc.channel;
+        bp += bp[1] + 2;
+    }
+
+    // Set IBSS ATIM window
+    bp[0] = DW_ELEM_IBSSPARAM;
+    bp[1] = 2;
+    SET16 (&bp[2], atimWindow);
+    bp += bp[1] + 2;
+
+    // Set ERP info.
+    //if (!DW_CHAN_5G (priv->adhoc.channel) && !(OPT_BONLY)))
+    {
+        bp[0] = DW_ELEM_ERPINFO;
+        bp[1] = 1;
+        bp[2] = 0;
+        bp += bp[1] + 2;
+    }
+
+    // Set extended supported rates
+    bp = SetRates (bp, DW_ELEM_EXTSUPRATES, priv->adhoc.channel);
+
+    priv->beacon_body_length = ((u8 *)bp - (u8 *)bcnFrame->body);
+
+    SetPLCP (&bcnFrame->hwHdr, IEEE80211_CCK_RATE_1MB , priv->beacon_body_length + sizeof(dw_beacon_frame) - BEACON_BODY_SIZE + DW_FCS_SIZE);
+    bcnFrame->hwHdr.plcp.pskcck.raw32 = cpu_to_be32( 0x0a046802 );
+
+    //dumpHexBuffer(&priv->beacon_frame, priv->beacon_length + sizeof(dw_beacon_frame) - BEACON_BODY_SIZE);
+
+    priv->beacon_ready = 1;
+}
+
+static void start_IBSS(struct dw_priv *priv)
+{
+	int atim = 0;
+	MakeBeacon (priv, DW_BEACON_INT);
+	/* If starting IBSS, set beacon and ATIM intervals */
+	dw_iowrite32( atim | (DW_BEACON_INT << 16), HW_CFP_ATIM );
+	dw_cw_set( priv, IEEE80211_STYPE_BEACON );
+	/* Write beacon frame to beacon buffer */
+	dw_iosetbits32( HW_GEN_CONTROL, GEN_BEACEN );
+	dw_hw_write_fifo( (void *)&priv->beacon_frame, priv->beacon_body_length + sizeof(dw_beacon_frame) - BEACON_BODY_SIZE);
+	dw_iocleanbits32( HW_GEN_CONTROL, GEN_BEACEN );
+	/* Set interrupt mask to enable TBTT and ATIM interrupts */
+	dw_iosetbits32( HW_INTR_MASK, INTR_TBTT|INTR_ATIM );
+	/* Enable IBSS mode */
+	dw_iosetbits32( HW_MAC_CONTROL, CTRL_IBSS|CTRL_BEACONTX );
+}
Index: linux/drivers/net/wireless/digi_wi_g.h
===================================================================
--- linux.orig/drivers/net/wireless/digi_wi_g.h	2007-12-05 19:56:42.000000000 +0100
+++ linux/drivers/net/wireless/digi_wi_g.h	2007-12-05 20:04:58.000000000 +0100
@@ -144,6 +144,8 @@
 #define	GEN_TXFIFORST	0x00000040	/* Transmit FIFO reset */
 #define	GEN_TXHOLD	0x00000080	/* Transmit FIFO hold */
 #define	GEN_BEACEN	0x00000100	/* Beacon enable */
+#define	GEN_BST		0x00001000	/* Boot status */
+#define	GEN_CLKEN	0x00002000	/* Clock enable */
 #define	GEN_TXFIFOEMPTY	0x00004000	/* Transmit FIFO empty */
 #define	GEN_TXFIFOFULL	0x00008000	/* Transmit FIFO full */
 
@@ -355,6 +357,162 @@
         dw_frame_tx_info_t s;
 } dw_frame_tx_t;
 
+// IBSS
+
+#define	DW_BEACON_INT		500		// IBSS Beacon interval (in TU)
+
+//
+// 802.11 MIB constants
+//
+#define	DW_SHORT_RETRY_LIMIT	7		// Small frame transmit retry limit
+#define	DW_LONG_RETRY_LIMIT	4		// Large frame transmit retry limit
+
+#define	DW_TU				1024L/1000	// Time unit (in msecs)
+#define	DW_MAX_TX_LIFETIME		(512*TU)	// Transmit lifetime limit (in msecs)
+#define	DW_MAX_RX_LIFETIME		(512*TU)	// Receive lifetime limit (in msecs)
+
+// Max number of fragments
+#define	DW_MAX_FRAGS			16
+
+// Frame header modulation type field
+#define	DW_MOD_PSKCCK		0x00	// PSK/CCK modulation
+#define	DW_MOD_OFDM			0xee	// OFDM modulation
+
+// PSK/CCK PLCP service field bits
+#define	DW_SERVICE_LOCKED		0x04	// Locked clocks
+#define	DW_SERVICE_MODSEL		0x08	// Modulation selection
+#define	DW_SERVICE_LENEXT		0x80	// Length extension
+
+// MAC type field values
+#define	DW_TYPE_ASSOC_REQ	0x00	// Association request
+#define	DW_TYPE_ASSOC_RESP	0x10	// Association response
+#define	DW_TYPE_REASSOC_REQ	0x20	// Reassociation request
+#define	DW_TYPE_REASSOC_RESP	0x30	// Reassociation response
+#define	DW_TYPE_PROBE_REQ	0x40	// Probe request
+#define	DW_TYPE_PROBE_RESP	0x50	// Probe response
+
+#define	DW_TYPE_BEACON		0x80	// Beacon
+#define	DW_TYPE_ATIM			0x90	// Annoucement traffice indication
+#define	DW_TYPE_DISASSOC		0xa0	// Disassociation
+#define	DW_TYPE_AUTH			0xb0	// Authentication
+#define	DW_TYPE_DEAUTH		0xc0	// Deauthentication
+
+#define	DW_TYPE_RTS			0xb4	// Request to send
+#define	DW_TYPE_CTS			0xc4	// Clear to send
+#define	DW_TYPE_ACK			0xd4	// Acknowledgement
+#define	DW_TYPE_PSPOLL		0xa4	// Power Save(PS)-Poll
+
+#define	DW_TYPE_DATA			0x08	// Data
+
+// TRUE if buf is data or management frame
+#define	DW_IS_DATA(buf)			(((buf)->macHdr.fc.type & 0xcf) == TYPE_DATA)
+#define	DW_IS_MGMT(buf)		(((buf)->macHdr.fc.type & 0x0f) == 0)
+
+// MAC address macros
+#define	DW_MAC_GROUP			0x01	// Broadcast or multicast address
+#define	DW_MAC_LOCAL			0x02	// Locally administered address
+
+#define	DW_EQUAL_ADDR(a1, a2)	(memcmp (a1, a2, ETH_ALEN) == 0)
+#define	DW_SET_ADDR(a1, a2)		(memcpy (a1, a2, ETH_ALEN))
+
+// Authentication algorithm number field values
+#define	DW_AUTH_OPEN			0x00	// Open system
+#define	DW_AUTH_SHAREDKEY		0x01	// Shared key
+#define	DW_AUTH_LEAP			0x80	// LEAP
+
+// Capability information field bits
+#define	DW_CAP_ESS			0x0001	// Extended service set (infrastructure)
+#define	DW_CAP_IBSS			0x0002	// Independent BSS (ad hoc)
+#define	DW_CAP_POLLABLE		0x0004	// Contention free pollable
+#define	DW_CAP_POLLREQ		0x0008	// Contention free poll request
+#define	DW_CAP_PRIVACY		0x0010	// Privacy (WEP) required
+#define	DW_CAP_SHORTPRE		0x0020	// Short preambles allowed
+#define	DW_CAP_PBCC			0x0040	// PBCC modulation allowed
+#define	DW_CAP_AGILITY			0x0080	// Channel agility in use
+#define	DW_CAP_SHORTSLOT		0x0400	// Short slot time in use
+#define	DW_CAP_DSSSOFDM		0x2000	// DSSS-OFDM in use
+
+// Status code field values
+#define	DW_STAT_SUCCESS		0
+
+// Reason code field values
+#define	DW_REAS_NOLONGERVALID	2
+#define	DW_REAS_DEAUTH_LEAVING	3
+#define	DW_REAS_INACTIVITY		4
+#define	DW_REAS_INCORRECT_FRAME_UNAUTH 6
+#define	DW_REAS_INCORRECT_FRAME_UNASSO 7
+
+// Information element IDs
+#define	DW_ELEM_SSID			0		// Service set ID
+#define	DW_ELEM_SUPRATES		1		// Supported rates
+#define	DW_ELEM_DSPARAM		3		// DS parameter set
+#define	DW_ELEM_IBSSPARAM		6		// IBSS parameter set
+#define	DW_ELEM_COUNTRY      	7		// Country information
+#define	DW_ELEM_CHALLENGE		16		// Challenge text
+#define	DW_ELEM_ERPINFO		42		// Extended rate PHY info
+#define	DW_ELEM_RSN			48		// Robust security network (WPA2)
+#define	DW_ELEM_EXTSUPRATES	50		// Extended supported rates
+#define	DW_ELEM_VENDOR		221		// Vendor extension (WPA)
+
+// 802.11d related defines
+// minimum length field value in country information elelment
+#define	DW_COUNTRY_INFO_MIN_LEN   6
+
+// Supported rates bits
+#define	DW_RATE_BASIC			0x80	// Bit set if basic rate
+
+// TRUE if channel number in 5 GHz band
+#define	DW_CHAN_5G(chan)		((chan) > 14)
+
+// ERP info bits
+#define	DW_ERP_NONERP			0x01	// Non-ERP present
+#define	DW_ERP_USEPROTECT		0x02	// Use protection
+#define	DW_ERP_BARKER			0x04	// Barker (long) preamble mode
+
+// Key ID byte in data frame body
+#define	DW_EXT_IV				0x20	// Extended IV is present
+
+// Correct CRC-32 check value
+#define	DW_GOOD_CRC32			0x2144df1c
+
+#pragma pack()
+
+#define BEACON_BODY_SIZE 64
+
+// MAC buffer, including complete MAC frame
+typedef struct {
+	dw_hw_hdr_tx_t hwHdr; // Frame and PLCP headers
+	u16 fc; // Frame control
+	u16 duration; // Duration/ID (needs byte swap)
+	u8 addr1[ ETH_ALEN ]; // Address 1
+	u8 addr2[ ETH_ALEN ]; // Address 2
+	u8 addr3[ ETH_ALEN ]; // Address 3
+	u16 seq_ctl; // Sequence control fields
+	u8 body[BEACON_BODY_SIZE];
+} __attribute__ ((packed)) dw_beacon_frame;
+
+// Length (in usecs) of a MAC frame of bytes at rate (in 500kbps units)
+// not including SIFS and PLCP preamble/header
+#define	DW_LENGTH_uS(bytes, rate)		((16*(bytes)+(rate)-1)/(rate))
+
+// Length (in usecs) of SIFS and PLCP preamble/header.
+#define	DW_PRE_LEN_uS(rate)			(USE_SHORTPRE(rate) ? 106 : 202)
+
+// Duration (in usecs) of an OFDM frame at rate (in 500kbps units)
+// including SIFS and PLCP preamble/header
+#define	DW_OFDM_DUR(bytes, rate)	(36 + 4*((4*(bytes)+(rate)+10)/(rate)))
+
+// Information on each supported rate
+typedef struct {
+	u8	bps; // Bit rate in 500kbps units
+	u8	ofdmCode; // OFDM rate code, 0 if not OFDM
+	u16	ackLen; // Duration of ACK or CTS in usecs
+} RateInfo;
+
+#define DW_IBSS_DEFAULT_CHANNEL 6
+
+// End of IBSS
+
 typedef struct dw_priv {
         struct net_device*              dev;
 	struct ieee80211_device*        ieee;
@@ -427,6 +585,11 @@
                 char                  last_was_data;
                 int                   basics[ RATES_SUPPORTED ];
         } tx;
+
+        int beacon_ready;
+        int beacon_body_length;
+        dw_beacon_frame beacon_frame;
+        struct ieee80211softmac_network adhoc;
 }  dw_priv_t;
 
 /* dw_(un)lock() protect struct dw_private.
