patch-2.2.15 linux/net/irda/irlap.c

Next file: linux/net/irda/irlap_comp.c
Previous file: linux/net/irda/irlan/irlan_provider_event.c
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from ../../exclude v2.2.14/net/irda/irlap.c linux/net/irda/irlap.c
@@ -6,7 +6,7 @@
  * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Mon May 31 21:43:55 1999
+ * Modified at:   Tue Dec 14 09:26:44 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -69,19 +69,20 @@
 
 #endif /* CONFIG_PROC_FS */
 
-__initfunc(int irlap_init(void))
+int __init irlap_init(void)
 {
 	/* Allocate master array */
 	irlap = hashbin_new(HB_LOCAL);
 	if (irlap == NULL) {
-		printk(KERN_WARNING "IrLAP: Can't allocate irlap hashbin!\n");
+	        ERROR(__FUNCTION__ "(), can't allocate irlap hashbin!\n");
 		return -ENOMEM;
 	}
 
 #ifdef CONFIG_IRDA_COMPRESSION
 	irlap_compressors = hashbin_new(HB_LOCAL);
 	if (irlap_compressors == NULL) {
-		printk(KERN_WARNING "IrLAP: Can't allocate compressors hashbin!\n");
+		WARNING(__FUNCTION__ 
+			"(), can't allocate compressors hashbin!\n");
 		return -ENOMEM;
 	}
 #endif
@@ -106,15 +107,12 @@
  *    Initialize IrLAP layer
  *
  */
-struct irlap_cb *irlap_open(struct irda_device *irdev)
+struct irlap_cb *irlap_open(struct device *dev, struct qos_info *qos)
 {
 	struct irlap_cb *self;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
-	ASSERT(irdev != NULL, return NULL;);
-	ASSERT(irdev->magic == IRDA_DEVICE_MAGIC, return NULL;);
-
 	/* Initialize the irlap structure. */
 	self = kmalloc(sizeof(struct irlap_cb), GFP_KERNEL);
 	if (self == NULL)
@@ -124,26 +122,22 @@
 	self->magic = LAP_MAGIC;
 
 	/* Make a binding between the layers */
-	self->irdev = irdev;
-	self->netdev = &irdev->netdev;
+	self->netdev = dev;
+	self->qos_dev = qos;
+
+	/* FIXME: should we get our own field? */
+	dev->atalk_ptr = self;
 
 	irlap_next_state(self, LAP_OFFLINE);
 
-	/* Initialize transmitt queue */
-	skb_queue_head_init(&self->tx_list);
+	/* Initialize transmit queue */
+	skb_queue_head_init(&self->txq);
+	skb_queue_head_init(&self->txq_ultra);
 	skb_queue_head_init(&self->wx_list);
 
 	/* My unique IrLAP device address! */
 	get_random_bytes(&self->saddr, sizeof(self->saddr));
-
-	/* 
-	 * Generate random connection address for this session, which must
-	 * be 7 bits wide and different from 0x00 and 0xfe 
-	 */
-	while ((self->caddr == 0x00) || (self->caddr == 0xfe)) {
-		get_random_bytes(&self->caddr, sizeof(self->caddr));
-		self->caddr &= 0xfe;
-	}
+	memcpy(dev->dev_addr, &self->saddr, 4);
 
 	init_timer(&self->slot_timer);
 	init_timer(&self->query_timer);
@@ -152,12 +146,15 @@
 	init_timer(&self->poll_timer);
 	init_timer(&self->wd_timer);
 	init_timer(&self->backoff_timer);
+	init_timer(&self->media_busy_timer);	
 
 	irlap_apply_default_connection_parameters(self);
+
+	self->N3 = 3; /* # connections attemts to try before giving up */
 	
 	irlap_next_state(self, LAP_NDM);
 
-	hashbin_insert(irlap, (QUEUE *) self, self->saddr, NULL);
+	hashbin_insert(irlap, (queue_t *) self, self->saddr, NULL);
 
 	irlmp_register_link(self, self->saddr, &self->notify);
 	
@@ -183,10 +180,10 @@
 	del_timer(&self->poll_timer);
 	del_timer(&self->wd_timer);
 	del_timer(&self->backoff_timer);
+	del_timer(&self->media_busy_timer);
 
 	irlap_flush_all_queues(self);
        
-	self->irdev = NULL;
 	self->magic = 0;
 	
 	kfree(self);
@@ -202,7 +199,7 @@
 {
 	struct irlap_cb *lap;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -215,7 +212,7 @@
 	/* Be sure that we manage to remove ourself from the hash */
 	lap = hashbin_remove(irlap, self->saddr, NULL);
 	if (!lap) {
-		DEBUG(1, __FUNCTION__ "(), Didn't find myself!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Didn't find myself!\n");
 		return;
 	}
 	__irlap_close(lap);
@@ -229,7 +226,7 @@
  */
 void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -248,7 +245,7 @@
  */
 void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	irlap_do_event(self, CONNECT_RESPONSE, skb, NULL);
 }
@@ -263,7 +260,7 @@
 void irlap_connect_request(struct irlap_cb *self, __u32 daddr, 
 			   struct qos_info *qos_user, int sniff) 
 {
-	DEBUG(3, __FUNCTION__ "(), daddr=0x%08x\n", daddr);
+	IRDA_DEBUG(3, __FUNCTION__ "(), daddr=0x%08x\n", daddr);
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -276,8 +273,7 @@
 	 */
 	irlap_init_qos_capabilities(self, qos_user);
 	
-	if ((self->state == LAP_NDM) && 
-	    !irda_device_is_media_busy(self->irdev))
+	if ((self->state == LAP_NDM) && !self->media_busy)
 		irlap_do_event(self, CONNECT_REQUEST, NULL, NULL);
 	else
 		self->connect_pending = TRUE;
@@ -291,7 +287,7 @@
  */
 void irlap_connect_confirm(struct irlap_cb *self, struct sk_buff *skb)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -306,7 +302,8 @@
  *    IrLMP for further processing
  *
  */
-inline void irlap_data_indication(struct irlap_cb *self, struct sk_buff *skb) 
+void irlap_data_indication(struct irlap_cb *self, struct sk_buff *skb,
+			   int unreliable) 
 {
 	/* Hide LAP header from IrLMP layer */
 	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
@@ -315,43 +312,14 @@
 	if (self->qos_tx.compression.value) {
 		skb = irlap_decompress_frame(self, skb);
 		if (!skb) {
-			DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
+			IRDA_DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
 			return;
 		}
 	}
 #endif
-	irlmp_link_data_indication(self->notify.instance, LAP_RELIABLE, skb);
+	irlmp_link_data_indication(self->notify.instance, skb, unreliable);
 }
 
-/*
- * Function irlap_unit_data_indication (self, skb)
- *
- *    Received some data that was sent unreliable
- *
- */
-void irlap_unit_data_indication(struct irlap_cb *self, struct sk_buff *skb)
-{
-	DEBUG(1, __FUNCTION__ "()\n"); 
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LAP_MAGIC, return;);
-	ASSERT(skb != NULL, return;);
-
-	/* Hide LAP header from IrLMP layer */
-	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
-
-#ifdef CONFIG_IRDA_COMPRESSION
-	if (self->qos_tx.compression.value) {
-		
-		skb = irlap_decompress_frame(self, skb);
-		if (!skb) {
-			DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
-			return;
-		}
-	}
-#endif
-	irlmp_link_data_indication(self->notify.instance, LAP_UNRELIABLE, skb);
-}
 
 /*
  * Function irlap_data_request (self, skb)
@@ -359,23 +327,23 @@
  *    Queue data for transmission, must wait until XMIT state
  *
  */
-inline void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb,
-				int reliable)
+void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb, 
+			int unreliable)
 {
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
-	ASSERT(skb != NULL, return;);
+
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 
 #ifdef CONFIG_IRDA_COMPRESSION
 	if (self->qos_tx.compression.value) {
 		skb = irlap_compress_frame(self, skb);
 		if (!skb) {
-			DEBUG(1, __FUNCTION__ "(), Compress error!\n");
+			IRDA_DEBUG(1, __FUNCTION__ "(), Compress error!\n");
 			return;
 		}
 	}
 #endif
-	
 	ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), 
 	       return;);
 	skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
@@ -384,12 +352,10 @@
 	 *  Must set frame format now so that the rest of the code knows 
 	 *  if its dealing with an I or an UI frame
 	 */
-	if (reliable)
-		skb->data[1] = I_FRAME;
-	else {
-		DEBUG(4, __FUNCTION__ "(), queueing unreliable frame\n");
+	if (unreliable)
 		skb->data[1] = UI_FRAME;
-	}
+	else
+		skb->data[1] = I_FRAME;
 
 	/* 
 	 *  Send event if this frame only if we are in the right state 
@@ -400,16 +366,65 @@
 		 *  Check if the transmit queue contains some unsent frames,
 		 *  and if so, make sure they are sent first
 		 */
-		if (!skb_queue_empty(&self->tx_list)) {
-			skb_queue_tail(&self->tx_list, skb);
-			skb = skb_dequeue(&self->tx_list);
+		if (!skb_queue_empty(&self->txq)) {
+			skb_queue_tail(&self->txq, skb);
+			skb = skb_dequeue(&self->txq);
 			
 			ASSERT(skb != NULL, return;);
 		}
 		irlap_do_event(self, SEND_I_CMD, skb, NULL);
 	} else
-		skb_queue_tail(&self->tx_list, skb);	
+		skb_queue_tail(&self->txq, skb);
+}
+
+/*
+ * Function irlap_unitdata_request (self, skb)
+ *
+ *    Send Ultra data. This is data that must be sent outside any connection
+ *
+ */
+#ifdef CONFIG_IRDA_ULTRA
+void irlap_unitdata_request(struct irlap_cb *self, struct sk_buff *skb)
+{
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
+
+	ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), 
+	       return;);
+	skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
+
+	skb->data[0] = CBROADCAST;
+	skb->data[1] = UI_FRAME;
+
+	skb_queue_tail(&self->txq_ultra, skb);
+
+	irlap_do_event(self, SEND_UI_FRAME, NULL, NULL);
 }
+#endif /*CONFIG_IRDA_ULTRA */
+
+/*
+ * Function irlap_udata_indication (self, skb)
+ *
+ *    Receive Ultra data. This is data that is received outside any connection
+ *
+ */
+#ifdef CONFIG_IRDA_ULTRA
+void irlap_unitdata_indication(struct irlap_cb *self, struct sk_buff *skb)
+{
+	IRDA_DEBUG(1, __FUNCTION__ "()\n"); 
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+
+	/* Hide LAP header from IrLMP layer */
+	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
+
+	irlmp_link_unitdata_indication(self->notify.instance, skb);
+}
+#endif /* CONFIG_IRDA_ULTRA */
 
 /*
  * Function irlap_disconnect_request (void)
@@ -418,11 +433,19 @@
  */
 void irlap_disconnect_request(struct irlap_cb *self) 
 {
-	DEBUG(3, __FUNCTION__ "()\n");
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 	
+	/* Don't disconnect until all data frames are successfully sent */
+	if (skb_queue_len(&self->txq) > 0) {
+		self->disconnect_pending = TRUE;
+		
+		return;
+	}
+
+	/* Check if we are in the right state for disconnecting */
 	switch (self->state) {
 	case LAP_XMIT_P:        /* FALLTROUGH */
 	case LAP_XMIT_S:        /* FALLTROUGH */
@@ -432,7 +455,7 @@
 		irlap_do_event(self, DISCONNECT_REQUEST, NULL, NULL);
 		break;
 	default:
-		DEBUG(0, __FUNCTION__ "(), disconnect pending!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), disconnect pending!\n");
 		self->disconnect_pending = TRUE;
 		break;
 	}
@@ -446,7 +469,7 @@
  */
 void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason) 
 {
-	DEBUG(1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]); 
+	IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]); 
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -457,21 +480,20 @@
 	/* Flush queues */
 	irlap_flush_all_queues(self);
 	
-	switch(reason) {
+	switch (reason) {
 	case LAP_RESET_INDICATION:
-		DEBUG(1, __FUNCTION__ "(), Sending reset request!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Sending reset request!\n");
 		irlap_do_event(self, RESET_REQUEST, NULL, NULL);
 		break;
 	case LAP_NO_RESPONSE:	   /* FALLTROUGH */	
 	case LAP_DISC_INDICATION:  /* FALLTROUGH */
 	case LAP_FOUND_NONE:       /* FALLTROUGH */
 	case LAP_MEDIA_BUSY:
-		irlmp_link_disconnect_indication(self->notify.instance, 
-						  self, reason, NULL);
+		irlmp_link_disconnect_indication(self->notify.instance, self, 
+						 reason, NULL);
 		break;
 	default:
-		DEBUG(1, __FUNCTION__ "(), Reason %d not implemented!\n", 
-		       reason);
+		ERROR(__FUNCTION__ "(), Unknown reason %d\n", reason);
 	}
 }
 
@@ -489,49 +511,53 @@
 	ASSERT(self->magic == LAP_MAGIC, return;);
 	ASSERT(discovery != NULL, return;);
 	
-	DEBUG(4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots);
+	IRDA_DEBUG(4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots);
 
 	ASSERT((discovery->nslots == 1) || (discovery->nslots == 6) ||
 	       (discovery->nslots == 8) || (discovery->nslots == 16), 
 	       return;);
 	
-  	/*
-	 *  Discovery is only possible in NDM mode
-	 */ 
-	if (self->state == LAP_NDM) {
-		ASSERT(self->discovery_log == NULL, return;);
-		self->discovery_log= hashbin_new(HB_LOCAL);
-		
-		info.S = discovery->nslots; /* Number of slots */
-		info.s = 0; /* Current slot */
-		
-		self->discovery_cmd = discovery;
-		info.discovery = discovery;
-		
-		/* Check if the slot timeout is within limits */
-		if (sysctl_slot_timeout < 20) {
-			ERROR(__FUNCTION__ 
-			      "(), to low value for slot timeout!\n");
-			sysctl_slot_timeout = 20;
-		}
-		/* 
-		 * Highest value is actually 8, but we allow higher since
-		 * some devices seems to require it.
-		 */
-		if (sysctl_slot_timeout > 160) {
-			ERROR(__FUNCTION__ 
-			      "(), to high value for slot timeout!\n");
-			sysctl_slot_timeout = 160;
-		}
-
-		self->slot_timeout = sysctl_slot_timeout * HZ / 1000;
-		
-		irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
-	} else { 
- 		DEBUG(4, __FUNCTION__ 
-		       "(), discovery only possible in NDM mode\n");
+  	/* Discovery is only possible in NDM mode */
+	if (self->state != LAP_NDM) {
+		IRDA_DEBUG(4, __FUNCTION__ 
+			   "(), discovery only possible in NDM mode\n");
 		irlap_discovery_confirm(self, NULL);
- 	} 
+		return;
+	}
+
+	/* Check if last discovery request finished in time */
+	if (self->discovery_log != NULL) {
+		hashbin_delete(self->discovery_log, (FREE_FUNC) kfree);
+		self->discovery_log = NULL;
+	}
+	
+	self->discovery_log= hashbin_new(HB_LOCAL);
+	
+	info.S = discovery->nslots; /* Number of slots */
+	info.s = 0; /* Current slot */
+	
+	self->discovery_cmd = discovery;
+	info.discovery = discovery;
+	
+	/* Check if the slot timeout is within limits */
+	if (sysctl_slot_timeout < 20) {
+		ERROR(__FUNCTION__ 
+		      "(), to low value for slot timeout!\n");
+		sysctl_slot_timeout = 20;
+	}
+	/* 
+	 * Highest value is actually 8, but we allow higher since
+	 * some devices seems to require it.
+	 */
+	if (sysctl_slot_timeout > 160) {
+		ERROR(__FUNCTION__ 
+		      "(), to high value for slot timeout!\n");
+		sysctl_slot_timeout = 160;
+	}
+	
+	self->slot_timeout = sysctl_slot_timeout * HZ / 1000;
+	
+	irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
 }
 
 /*
@@ -552,16 +578,11 @@
 	 * the media busy condition (irlap p.94). This should allow us to make 
 	 * connection attempts much easier.
 	 */
-	if (discovery_log && hashbin_get_size(discovery_log) > 0)
-		irda_device_set_media_busy(self->irdev, FALSE);
+	if (discovery_log && HASHBIN_GET_SIZE(discovery_log) > 0)
+		irda_device_set_media_busy(self->netdev, FALSE);
 	
 	/* Inform IrLMP */
 	irlmp_link_discovery_confirm(self->notify.instance, discovery_log);
-	
-	/* 
-	 *  IrLMP has now the responsibilities for the discovery_log 
-	 */
-	self->discovery_log = NULL;
 }
 
 /*
@@ -572,7 +593,7 @@
  */
 void irlap_discovery_indication(struct irlap_cb *self, discovery_t *discovery) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -591,12 +612,12 @@
  */
 void irlap_status_indication(int quality_of_link) 
 {
-	switch(quality_of_link) {
+	switch (quality_of_link) {
 	case STATUS_NO_ACTIVITY:
-		printk(KERN_INFO "IrLAP, no activity on link!\n");
+		MESSAGE("IrLAP, no activity on link!\n");
 		break;
 	case STATUS_NOISY:
-		printk(KERN_INFO "IrLAP, noisy link!\n");
+		MESSAGE("IrLAP, noisy link!\n");
 		break;
 	default:
 		break;
@@ -612,7 +633,7 @@
  */
 void irlap_reset_indication(struct irlap_cb *self)
 {
-	DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -631,7 +652,7 @@
  */
 void irlap_reset_confirm(void)
 {
- 	DEBUG(1, __FUNCTION__ "()\n");
+ 	IRDA_DEBUG(1, __FUNCTION__ "()\n");
 }
 
 /*
@@ -666,16 +687,10 @@
 	struct sk_buff *skb = NULL;
 	int count = 0;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LAP_MAGIC, return;);
-
 	/*
          * Remove all the ack-ed frames from the window queue.
          */
 
-	DEBUG(4, "--> wx_list=%d, va=%d, nr=%d\n", 
-	       skb_queue_len(&self->wx_list), self->va, nr);
-
 	/* 
 	 *  Optimize for the common case. It is most likely that the receiver
 	 *  will acknowledge all the frames we have sent! So in that case we
@@ -683,7 +698,7 @@
 	 */
 	if (nr == self->vs) {
 		while ((skb = skb_dequeue(&self->wx_list)) != NULL) {
-		     dev_kfree_skb(skb);
+			dev_kfree_skb(skb);
 		}
 		/* The last acked frame is the next to send minus one */
 		self->va = nr - 1;
@@ -698,10 +713,6 @@
 			self->va = (self->va + 1) % 8;
 			count++;
 		}
-		
-		DEBUG(4, "irlap_update_nr_received(), removed %d\n", count);
-		DEBUG(4, "wx_list=%d, va=%d, nr=%d -->\n", 
-		       skb_queue_len(&self->wx_list), self->va, nr);
 	}
 	
 	/* Advance window */
@@ -715,20 +726,15 @@
  */
 int irlap_validate_ns_received(struct irlap_cb *self, int ns) 
 {
-	ASSERT(self != NULL, return -ENODEV;);
-	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
-
 	/*  ns as expected?  */
-	if (ns == self->vr) {
-		DEBUG(4, __FUNCTION__ "(), expected!\n");
+	if (ns == self->vr)
 		return NS_EXPECTED;
-	}
 	/*
 	 *  Stations are allowed to treat invalid NS as unexpected NS
 	 *  IrLAP, Recv ... with-invalid-Ns. p. 84
 	 */
 	return NS_UNEXPECTED;
-
+	
 	/* return NR_INVALID; */
 }
 /*
@@ -739,12 +745,9 @@
  */
 int irlap_validate_nr_received(struct irlap_cb *self, int nr) 
 {
-	ASSERT(self != NULL, return -ENODEV;);
-	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
-
 	/*  nr as expected?  */
 	if (nr == self->vs) {
-		DEBUG(4, __FUNCTION__ "(), expected!\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), expected!\n");
 		return NR_EXPECTED;
 	}
 
@@ -772,7 +775,7 @@
  */
 void irlap_initiate_connection_state(struct irlap_cb *self) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -799,17 +802,16 @@
  */
 void irlap_wait_min_turn_around(struct irlap_cb *self, struct qos_info *qos) 
 {
-	int usecs;
-	int speed;
-	int bytes ;
+	__u32 min_turn_time;
+	__u32 speed;
 	
 	/* Get QoS values.  */
 	speed = qos->baud_rate.value;
-	usecs = qos->min_turn_time.value;
+	min_turn_time = qos->min_turn_time.value;
 
 	/* No need to calculate XBOFs for speeds over 115200 bps */
 	if (speed > 115200) {
-		self->mtt_required = usecs;
+		self->mtt_required = min_turn_time;
 		return;
 	}
 	
@@ -818,9 +820,7 @@
 	 *  min turn time, so now we must calculate how many chars (XBOF's) we 
 	 *  must send for the requested time period (min turn time)
 	 */
-	bytes = speed * usecs / 10000000;
-
-	self->xbofs_delay = bytes;
+	self->xbofs_delay = irlap_min_turn_time_in_bytes(speed, min_turn_time);
 }
 
 /*
@@ -837,9 +837,12 @@
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
 	/* Free transmission queue */
-	while ((skb = skb_dequeue(&self->tx_list)) != NULL)
+	while ((skb = skb_dequeue(&self->txq)) != NULL)
 		dev_kfree_skb(skb);
 	
+	while ((skb = skb_dequeue(&self->txq_ultra)) != NULL)
+		dev_kfree_skb(skb);
+
 	/* Free sliding window buffered packets */
 	while ((skb = skb_dequeue(&self->wx_list)) != NULL)
 		dev_kfree_skb(skb);
@@ -858,22 +861,18 @@
  *    Change the speed of the IrDA port
  *
  */
-void irlap_change_speed(struct irlap_cb *self, int speed)
+void irlap_change_speed(struct irlap_cb *self, __u32 speed, int now)
 {
-	DEBUG(4, __FUNCTION__ "(), setting speed to %d\n", speed);
+	IRDA_DEBUG(0, __FUNCTION__ "(), setting speed to %d\n", speed);
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	if (!self->irdev) {
-		DEBUG(1, __FUNCTION__ "(), driver missing!\n");
-		return;
-	}
-
-	irda_device_change_speed(self->irdev, speed);
+	self->speed = speed;
 
-	self->qos_rx.baud_rate.value = speed;
-	self->qos_tx.baud_rate.value = speed;
+	/* Change speed now, or just piggyback speed on frames */
+	if (now)
+		irda_device_change_speed(self->netdev, speed);
 }
 
 #ifdef CONFIG_IRDA_COMPRESSION
@@ -885,33 +884,33 @@
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
-
+	
 	/* 
 	 *  Find out which compressors we support. We do this be checking that
 	 *  the corresponding compressor for each bit set in the QoS bits has 
 	 *  actually been loaded. Ths is sort of hairy code but that is what 
 	 *  you get when you do a little bit flicking :-)
 	 */
-	DEBUG(4, __FUNCTION__ "(), comp bits 0x%02x\n", 
-	       self->qos_rx.compression.bits); 
+	IRDA_DEBUG(4, __FUNCTION__ "(), comp bits 0x%02x\n", 
+		   self->qos_rx.compression.bits); 
 	mask = 0x80; /* Start with testing MSB */
 	for (i=0;i<8;i++) {
-		DEBUG(4, __FUNCTION__ "(), testing bit %d\n", 8-i);
+		IRDA_DEBUG(4, __FUNCTION__ "(), testing bit %d\n", 8-i);
 		if (self->qos_rx.compression.bits & mask) {
-			DEBUG(4, __FUNCTION__ "(), bit %d is set by defalt\n",
-			       8-i);
+			IRDA_DEBUG(4, __FUNCTION__ 
+				   "(), bit %d is set by defalt\n", 8-i);
 			comp = hashbin_find(irlap_compressors, 
-					     compression[ msb_index(mask)], 
-					     NULL);
+					    compressions[msb_index(mask)], 
+					    NULL);
 			if (!comp) {
 				/* Protocol not supported, so clear the bit */
-				DEBUG(4, __FUNCTION__ "(), Compression "
-				       "protocol %d has not been loaded!\n", 
-				       compression[msb_index(mask)]);
+				IRDA_DEBUG(4, __FUNCTION__ "(), Compression "
+					   "protocol %d has not been loaded!\n", 
+					   compressions[msb_index(mask)]);
 				self->qos_rx.compression.bits &= ~mask;
-				DEBUG(4, __FUNCTION__ 
-				       "(), comp bits 0x%02x\n", 
-				       self->qos_rx.compression.bits); 
+				IRDA_DEBUG(4, __FUNCTION__ 
+					   "(), comp bits 0x%02x\n", 
+					   self->qos_rx.compression.bits); 
 			}
 		}
 		/* Try the next bit */
@@ -933,7 +932,7 @@
 {
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
-	ASSERT(self->irdev != NULL, return;);
+	ASSERT(self->netdev != NULL, return;);
 
 	/* Start out with the maximum QoS support possible */
 	irda_init_max_qos_capabilies(&self->qos_rx);
@@ -943,8 +942,7 @@
 #endif
 
 	/* Apply drivers QoS capabilities */
-	irda_qos_compute_intersection(&self->qos_rx, 
-				      irda_device_get_qos(self->irdev));
+	irda_qos_compute_intersection(&self->qos_rx, self->qos_dev);
 
 	/*
 	 *  Check for user supplied QoS parameters. The service user is only 
@@ -952,7 +950,7 @@
 	 *  user may not have set all of them.
 	 */
 	if (qos_user) {
-		DEBUG(1, __FUNCTION__ "(), Found user specified QoS!\n");
+		IRDA_DEBUG(1, __FUNCTION__ "(), Found user specified QoS!\n");
 
 		if (qos_user->baud_rate.bits)
 			self->qos_rx.baud_rate.bits &= qos_user->baud_rate.bits;
@@ -969,17 +967,11 @@
 #endif
 	}
 
-	/* 
-	 *  Make the intersection between IrLAP and drivers QoS
-	 *  capabilities 
-	 */
-
 	/* Use 500ms in IrLAP for now */
-	self->qos_rx.max_turn_time.bits &= 0x03;
 	self->qos_rx.max_turn_time.bits &= 0x01;
 
 	/* Set data size */
-	/* self->qos_rx.data_size.bits &= 0x03; */
+	/*self->qos_rx.data_size.bits &= 0x03;*/
 
 	/* Set disconnect time */
 	self->qos_rx.link_disc_time.bits &= 0x07;
@@ -995,28 +987,54 @@
  */
 void irlap_apply_default_connection_parameters(struct irlap_cb *self)
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	irlap_change_speed(self, 9600);
+	irlap_change_speed(self, 9600, TRUE);
+
+	/* Set mbusy when going to NDM state */
+	irda_device_set_media_busy(self->netdev, TRUE);
 
 	/* Default value in NDM */
 	self->bofs_count = 11;
 
-	/* Use these until connection has been made */
+	/* 
+	 * Generate random connection address for this session, which must
+	 * be 7 bits wide and different from 0x00 and 0xfe 
+	 */
+	while ((self->caddr == 0x00) || (self->caddr == 0xfe)) {
+		get_random_bytes(&self->caddr, sizeof(self->caddr));
+		self->caddr &= 0xfe;
+	}
+
+	/* Use default values until connection has been negitiated */
 	self->slot_timeout = sysctl_slot_timeout;
 	self->final_timeout = FINAL_TIMEOUT;
 	self->poll_timeout = POLL_TIMEOUT;
 	self->wd_timeout = WD_TIMEOUT;
 
+	/* Set some default values */
+	self->qos_tx.baud_rate.value = 9600;
+	self->qos_rx.baud_rate.value = 9600;
+	self->qos_tx.max_turn_time.value = 0;
+	self->qos_rx.max_turn_time.value = 0;
+	self->qos_tx.min_turn_time.value = 0;
+	self->qos_rx.min_turn_time.value = 0;
 	self->qos_tx.data_size.value = 64;
+	self->qos_rx.data_size.value = 64;
+	self->qos_tx.window_size.value = 1;
+	self->qos_rx.window_size.value = 1;
 	self->qos_tx.additional_bofs.value = 11;
+	self->qos_rx.additional_bofs.value = 11;
+	self->qos_tx.link_disc_time.value = 0;
+	self->qos_rx.link_disc_time.value = 0;
 
 	irlap_flush_all_queues(self);
 
 	self->disconnect_pending = FALSE;
+	self->connect_pending = FALSE;
 }
 
 /*
@@ -1025,62 +1043,86 @@
  *    Initialize IrLAP with the negotiated QoS values
  *
  */
-void irlap_apply_connection_parameters(struct irlap_cb *self, 
-				       struct qos_info *qos) 
+void irlap_apply_connection_parameters(struct irlap_cb *self) 
 {
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	irlap_change_speed(self, qos->baud_rate.value);
+	irlap_change_speed(self, self->qos_tx.baud_rate.value, FALSE);
 
-	self->window_size = qos->window_size.value;
-	self->window      = qos->window_size.value;
-	self->bofs_count  = qos->additional_bofs.value;
+	self->window_size = self->qos_tx.window_size.value;
+	self->window      = self->qos_tx.window_size.value;
+	self->bofs_count  = self->qos_tx.additional_bofs.value;
 
 	/*
 	 *  Calculate how many bytes it is possible to transmit before the
-	 *  link must be turned around wb = baud * mtt/1000 * 1/2
+	 *  link must be turned around
 	 */
-	self->window_bytes = qos->baud_rate.value 
-		* qos->max_turn_time.value / 10000;
-	DEBUG(4, "Setting window_bytes = %d\n", self->window_bytes);
-
+	self->line_capacity = 
+		irlap_max_line_capacity(self->qos_tx.baud_rate.value,
+					self->qos_tx.max_turn_time.value);
 	/*
 	 *  Set N1 to 0 if Link Disconnect/Threshold Time = 3 and set it to 
 	 *  3 seconds otherwise. See page 71 in IrLAP for more details.
 	 *  TODO: these values should be calculated from the final timer
          *  as well
 	 */
-	if (qos->link_disc_time.value == 3)
+	ASSERT(self->qos_tx.max_turn_time.value != 0, return;);
+	if (self->qos_tx.link_disc_time.value == 3)
 		self->N1 = 0;
 	else
-		self->N1 = 3000 / qos->max_turn_time.value;
+		self->N1 = 3000 / self->qos_tx.max_turn_time.value;
+	
+	IRDA_DEBUG(4, "Setting N1 = %d\n", self->N1);
 	
-	DEBUG(4, "Setting N1 = %d\n", self->N1);
 	
-	self->N2 = qos->link_disc_time.value * 1000 / qos->max_turn_time.value;
-	DEBUG(4, "Setting N2 = %d\n", self->N2);
+	self->N2 = self->qos_tx.link_disc_time.value * 1000 / 
+		self->qos_tx.max_turn_time.value;
+	IRDA_DEBUG(4, "Setting N2 = %d\n", self->N2);
 
 	/* 
 	 *  Initialize timeout values, some of the rules are listed on 
 	 *  page 92 in IrLAP.
 	 */
-	self->poll_timeout = qos->max_turn_time.value * HZ / 1000;
-	self->final_timeout = qos->max_turn_time.value * HZ / 1000;
+	self->poll_timeout = self->qos_tx.max_turn_time.value * HZ / 1000;
 	self->wd_timeout = self->poll_timeout * 2;
 
+	/* 
+	 * Be careful to keep our promises to the peer device about how long
+	 * time it can keep the pf bit. So here we must use the rx_qos value
+	 */
+	self->final_timeout = self->qos_rx.max_turn_time.value * HZ / 1000;
+
 #ifdef CONFIG_IRDA_COMPRESSION
-	if (qos->compression.value) {
-		DEBUG(1, __FUNCTION__ "(), Initializing compression\n");
-		irda_set_compression(self, qos->compression.value);
+	if (self->qos_tx.compression.value) {
+		IRDA_DEBUG(1, __FUNCTION__ "(), Initializing compression\n");
+		irda_set_compression(self, self->qos_tx.compression.value);
 
 		irlap_compressor_init(self, 0);
 	}
 #endif
 }
 
+/*
+ * Function irlap_set_local_busy (self, status)
+ *
+ *    
+ *
+ */
+void irlap_set_local_busy(struct irlap_cb *self, int status)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	self->local_busy = status;
+	
+	if (status)
+		IRDA_DEBUG(0, __FUNCTION__ "(), local busy ON\n");
+	else
+		IRDA_DEBUG(0, __FUNCTION__ "(), local busy OFF\n");
+}
+
 #ifdef CONFIG_PROC_FS
 /*
  * Function irlap_proc_read (buf, start, offset, len, unused)
@@ -1089,7 +1131,7 @@
  *
  */
 int irlap_proc_read(char *buf, char **start, off_t offset, int len, 
-		     int unused)
+		    int unused)
 {
 	struct irlap_cb *self;
 	unsigned long flags;
@@ -1105,27 +1147,30 @@
 		ASSERT(self != NULL, return -ENODEV;);
 		ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
 
-		len += sprintf(buf+len, "irlap%d <-> %s ",
-				i++, self->irdev->name);
+		len += sprintf(buf+len, "irlap%d ", i++);
 		len += sprintf(buf+len, "state: %s\n", 
-				irlap_state[ self->state]);
+			       irlap_state[self->state]);
 		
 		len += sprintf(buf+len, "  caddr: %#02x, ", self->caddr);
 		len += sprintf(buf+len, "saddr: %#08x, ", self->saddr);
 		len += sprintf(buf+len, "daddr: %#08x\n", self->daddr);
 		
 		len += sprintf(buf+len, "  win size: %d, ", 
-				self->window_size);
+			       self->window_size);
 		len += sprintf(buf+len, "win: %d, ", self->window);
-		len += sprintf(buf+len, "win bytes: %d, ", self->window_bytes);
+#if CONFIG_IRDA_DYNAMIC_WINDOW
+		len += sprintf(buf+len, "line capacity: %d, ", 
+			       self->line_capacity);
 		len += sprintf(buf+len, "bytes left: %d\n", self->bytes_left);
-
+#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
 		len += sprintf(buf+len, "  tx queue len: %d ", 
-				skb_queue_len(&self->tx_list));
+			       skb_queue_len(&self->txq));
 		len += sprintf(buf+len, "win queue len: %d ", 
-				skb_queue_len(&self->wx_list));
-		len += sprintf(buf+len, "rbusy: %s\n", self->remote_busy ? 
-				"TRUE" : "FALSE");
+			       skb_queue_len(&self->wx_list));
+		len += sprintf(buf+len, "rbusy: %s", self->remote_busy ?
+			       "TRUE" : "FALSE");
+		len += sprintf(buf+len, " mbusy: %s\n", self->media_busy ?
+			       "TRUE" : "FALSE");
 		
 		len += sprintf(buf+len, "  retrans: %d ", self->retry_count);
 		len += sprintf(buf+len, "vs: %d ", self->vs);
@@ -1135,42 +1180,42 @@
 		len += sprintf(buf+len, "  qos\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\tcomp\n");
 		
 		len += sprintf(buf+len, "  tx\t%d\t", 
-				self->qos_tx.baud_rate.value);
+			       self->qos_tx.baud_rate.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_tx.max_turn_time.value);
+			       self->qos_tx.max_turn_time.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_tx.data_size.value);
+			       self->qos_tx.data_size.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_tx.window_size.value);
+			       self->qos_tx.window_size.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_tx.additional_bofs.value);
+			       self->qos_tx.additional_bofs.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_tx.min_turn_time.value);
+			       self->qos_tx.min_turn_time.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_tx.link_disc_time.value);
+			       self->qos_tx.link_disc_time.value);
 #ifdef CONFIG_IRDA_COMPRESSION
 		len += sprintf(buf+len, "%d",
-				self->qos_tx.compression.value);
+			       self->qos_tx.compression.value);
 #endif
 		len += sprintf(buf+len, "\n");
 
 		len += sprintf(buf+len, "  rx\t%d\t", 
-				self->qos_rx.baud_rate.value);
+			       self->qos_rx.baud_rate.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_rx.max_turn_time.value);
+			       self->qos_rx.max_turn_time.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_rx.data_size.value);
+			       self->qos_rx.data_size.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_rx.window_size.value);
+			       self->qos_rx.window_size.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_rx.additional_bofs.value);
+			       self->qos_rx.additional_bofs.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_rx.min_turn_time.value);
+			       self->qos_rx.min_turn_time.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_rx.link_disc_time.value);
+			       self->qos_rx.link_disc_time.value);
 #ifdef CONFIG_IRDA_COMPRESSION
 		len += sprintf(buf+len, "%d",
-				self->qos_rx.compression.value);
+			       self->qos_rx.compression.value);
 #endif
 		len += sprintf(buf+len, "\n");
 		

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)