linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* STRIP Starmode Patch
@ 2005-01-09  1:45 Michael Ryan
  2005-01-09 10:39 ` Russell King
  0 siblings, 1 reply; 2+ messages in thread
From: Michael Ryan @ 2005-01-09  1:45 UTC (permalink / raw)
  To: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1275 bytes --]

The Linux kernel STRIP module was updated to support the newer series of Ricochet modems in January of 2002 by a person about whom I can find nothing more than a username of `abelits'. Anyway, he wasn't smart about it and didn't submit his patch to the LKML. When the existing drivers were migrated to the 2.6 tree, the old version of the module was migrated, and that's where the problems began.

`abelits' provides a patch for 2.4.1, though it applies cleanly to the recent 2.4 kernels with just a little fuzz. However, the 2.6 version of strip.c is significantly different from the 2.4 version. Most structures in the diff are easy enough to find in the new version of the source, so I tried hand-merging the differences. Unfortunately, given my limited knowledge of C, I wasn't able to get anywhere with it.

I attached copy of the patch and the link to the source of the patch's origin in the hopes that someone can migrate this driver to the current source tree and possibly merge it into both 2.4 and 2.6 production kernels. I can UPS a modem to someone if that's the real problem. If this idea is feasible at all, please reply.

http://mars.illtel.denver.co.us/~abelits/metricom/
Look near the bottom, section 8.4.

-- 
I am not on the list, please CC replies to me.

[-- Attachment #2: linux-2.4.1-strip.patch --]
[-- Type: application/octet-stream, Size: 10904 bytes --]

--- linux-2.4.1-orig/drivers/net/strip.c	Tue Jul 11 11:12:24 2000
+++ linux/drivers/net/strip.c	Sun Feb 11 16:21:51 2001
@@ -14,7 +14,7 @@
  *		for kernel-based devices like TTY.  It interfaces between a
  *		raw TTY, and the kernel's INET protocol layers (via DDI).
  *
- * Version:	@(#)strip.c	1.3	July 1997
+ * Version:	@(#)strip.c	1.4.2	February 2001
  *
  * Author:	Stuart Cheshire <cheshire@cs.stanford.edu>
  *
@@ -66,15 +66,28 @@
  *              It is no longer necessarily to manually set the radio's
  *              rate permanently to 115200 -- the driver handles setting
  *              the rate automatically.
+ *
+ * Alex Belits: v1.4 September 2000 (AB)
+ *              Added support for long serial numbers.
+ *
+ *              v1.4.1 December 2000 (AB)
+ *              Added tx_bytes and rx_bytes reporting in strip_get_stats(),
+ *              removed packets rate warnings unless STRIP_VERBOSE_MESSAGES
+ *              is enablled.
+ *
+ *              v1.4.2 February 2001 (AB)
+ *              Added support for longer (000-0000-0000) serial numbers.
+ *
  */
 
 #ifdef MODULE
-static const char StripVersion[] = "1.3-STUART.CHESHIRE-MODULAR";
+static const char StripVersion[] = "1.4.2-STUART.CHESHIRE-MODULAR";
 #else
-static const char StripVersion[] = "1.3-STUART.CHESHIRE";
+static const char StripVersion[] = "1.4.2-STUART.CHESHIRE";
 #endif
 
 #define TICKLE_TIMERS 0
+#define STRIP_VERBOSE_MESSAGES 0
 #define EXT_COUNTERS 1
 
 
@@ -288,6 +301,8 @@
 
     struct strip      *next;			/* The next struct in the list	*/
     struct strip     **referrer;		/* The pointer that points to us*/
+    int                pushing;			/* Set when data is being pushed*/
+    int                woke_up;			/* Set if woken up while pushing*/
     int                discard;			/* Set if serial error		*/
     int                working;			/* Is radio working correctly?	*/
     int                firmware_level;		/* Message structuring level	*/
@@ -517,8 +532,10 @@
 	if (neighbor_entry->nud_state & NUD_VALID)
 	{
 	    memcpy(haddr, neighbor_entry->ha, dev->addr_len);
+	    neigh_release(neighbor_entry);
 	    return 1;
 	}
+        neigh_release(neighbor_entry); 
     }
     return 0;
 }
@@ -897,20 +914,56 @@
  * Convert a string to a Metricom Address.
  */
 
-#define IS_RADIO_ADDRESS(p) (                                                 \
+#define IS_RADIO_ADDRESS_1(p) (                                               \
   isdigit((p)[0]) && isdigit((p)[1]) && isdigit((p)[2]) && isdigit((p)[3]) && \
   (p)[4] == '-' &&                                                            \
   isdigit((p)[5]) && isdigit((p)[6]) && isdigit((p)[7]) && isdigit((p)[8])    )
 
+#define IS_RADIO_ADDRESS_2(p) (                                               \
+  isdigit((p)[0]) && isdigit((p)[1]) &&                                       \
+  (p)[2] == '-' &&                                                            \
+  isdigit((p)[3]) && isdigit((p)[4]) && isdigit((p)[5]) && isdigit((p)[6]) && \
+  (p)[7] == '-' &&                                                            \
+  isdigit((p)[8]) && isdigit((p)[9]) && isdigit((p)[10]) && isdigit((p)[11])  )
+
+#define IS_RADIO_ADDRESS_3(p) (                                               \
+  isdigit((p)[0]) && isdigit((p)[1]) && isdigit((p)[2]) &&                    \
+  (p)[3] == '-' &&                                                            \
+  isdigit((p)[4]) && isdigit((p)[5]) && isdigit((p)[6]) && isdigit((p)[7]) && \
+  (p)[8] == '-' &&                                                            \
+  isdigit((p)[9]) && isdigit((p)[10]) && isdigit((p)[11]) && isdigit((p)[12]) )
+
 static int string_to_radio_address(MetricomAddress *addr, __u8 *p)
 {
-    if (!IS_RADIO_ADDRESS(p)) return(1);
+  
+  if (IS_RADIO_ADDRESS_3(p))
+    {
+      addr->c[0] = (READHEX(p[0]))^0xF;
+      addr->c[1] = (READHEX(p[1]) << 4 | READHEX(p[2])) ^ 0xFF;
+      addr->c[2] = READHEX(p[4]) << 4 | READHEX(p[5]);
+      addr->c[3] = READHEX(p[6]) << 4 | READHEX(p[7]);
+      addr->c[4] = READHEX(p[9]) << 4 | READHEX(p[10]);
+      addr->c[5] = READHEX(p[11]) << 4 | READHEX(p[12]);
+    }else{
+
+      if (IS_RADIO_ADDRESS_2(p))
+	{
+	  addr->c[0] = 0;
+	  addr->c[1] = (READHEX(p[0]) << 4 | READHEX(p[1])) ^ 0xFF;
+	  addr->c[2] = READHEX(p[3]) << 4 | READHEX(p[4]);
+	  addr->c[3] = READHEX(p[5]) << 4 | READHEX(p[6]);
+	  addr->c[4] = READHEX(p[8]) << 4 | READHEX(p[9]);
+	  addr->c[5] = READHEX(p[10]) << 4 | READHEX(p[11]);
+	}else{
+	  if(!IS_RADIO_ADDRESS_1(p)) return(1);
     addr->c[0] = 0;
     addr->c[1] = 0;
     addr->c[2] = READHEX(p[0]) << 4 | READHEX(p[1]);
     addr->c[3] = READHEX(p[2]) << 4 | READHEX(p[3]);
     addr->c[4] = READHEX(p[5]) << 4 | READHEX(p[6]);
     addr->c[5] = READHEX(p[7]) << 4 | READHEX(p[8]);
+	}
+    }
     return(0);
 }
 
@@ -920,7 +973,17 @@
 
 static __u8 *radio_address_to_string(const MetricomAddress *addr, MetricomAddressString *p)
 {
+    if(addr->c[0])
+      {
+	sprintf(p->c, "%01X%02X-%02X%02X-%02X%02X", (addr->c[0] & 0xF)^ 0xF, addr->c[1] ^ 0xFF, addr->c[2], addr->c[3], addr->c[4], addr->c[5]);
+      }else{
+	if(addr->c[1])
+	  {
+	  sprintf(p->c, "%02X-%02X%02X-%02X%02X", addr->c[1] ^ 0xFF, addr->c[2], addr->c[3], addr->c[4], addr->c[5]);
+	  }else{
     sprintf(p->c, "%02X%02X-%02X%02X", addr->c[2], addr->c[3], addr->c[4], addr->c[5]);
+	  }
+      }
     return(p->c);
 }
 
@@ -1343,6 +1406,45 @@
 }
 
 /*
+ * Called to send the data through the tty driver
+ *
+ */
+
+static void strip_push(struct strip *strip_info, struct tty_struct *tty)
+{
+  InterruptStatus intstat;
+  int num_written;
+
+  if(strip_info->pushing)
+    {
+      printk(KERN_ERR 
+	     "%s: strip_push: pushing recursively -- should not happen\n",
+	     strip_info->dev.name);
+    }
+
+  intstat = DisableInterrupts();
+  strip_info->pushing = 1;
+  do
+    {
+      strip_info->woke_up = 0;
+      RestoreInterrupts(intstat);
+      num_written = tty->driver.write(tty, 0, strip_info->tx_head, strip_info->tx_left);
+      intstat = DisableInterrupts();
+      strip_info->tx_left -= num_written;
+      strip_info->tx_head += num_written;
+#ifdef EXT_COUNTERS
+      strip_info->tx_sbytes += num_written;
+#endif
+    }
+  while (strip_info->woke_up && strip_info->tx_left > 0); 
+  /* Repeat if wakeup happened while pushing */
+
+  strip_info->pushing = 0;
+  RestoreInterrupts(intstat);
+}
+
+
+/*
  * Called by the driver when there's room for more data.  If we have
  * more packets to send, we send them here.
  */
@@ -1356,6 +1458,16 @@
     	!netif_running(&strip_info->dev))
         return;
 
+    /* Then check if we aren't already pushing something */
+
+    if (strip_info->pushing)
+    {
+      /* And if we are, we should set the flag and get out */
+      strip_info->woke_up = 1;
+      return;
+    }
+    
+
     if (strip_info->tx_left > 0)
     {
         /*
@@ -1372,6 +1484,14 @@
          * I disable interrupts around the call to tty->driver.write, although even
          * this might not work on a symmetric multi-processor system.
          */
+
+        /*
+         * Bug is in the eye of the beholder. In this case the original author
+         * severely misunderstood the techniques of dealing with this kind of
+         * kernel design.
+         */
+
+      /* 
         InterruptStatus intstat = DisableInterrupts();
         int num_written = tty->driver.write(tty, 0, strip_info->tx_head, strip_info->tx_left);
         strip_info->tx_left -= num_written;
@@ -1380,6 +1500,10 @@
         strip_info->tx_sbytes += num_written;
 #endif
         RestoreInterrupts(intstat);
+      */
+
+      strip_push(strip_info, tty);
+
     }
     else            /* Else start transmission of another packet */
     {
@@ -1439,9 +1563,10 @@
 
     /*
      * If this is a broadcast packet, send it to our designated Metricom
-     * 'broadcast hub' radio (First byte of address being 0xFF means broadcast)
+     * 'broadcast hub' radio (First byte of address being 0xF<something>
+     *  means broadcast)
      */
-    if (haddr.c[0] == 0xFF)
+    if ((haddr.c[0] & 0xF0) == 0xF0)
     {
 	u32 brd = 0;
  	struct in_device *in_dev = in_dev_get(&strip_info->dev);
@@ -1469,6 +1594,16 @@
 
     *ptr++ = 0x0D;
     *ptr++ = '*';
+    if(haddr.c[0])
+    {
+        *ptr++ = hextable[(haddr.c[0] & 0xF) ^ 0xF];
+    }
+    if(haddr.c[1])
+    {
+        *ptr++ = hextable[(haddr.c[1] >> 4) ^ 0xF];
+        *ptr++ = hextable[(haddr.c[1] & 0xF) ^ 0xF];
+        *ptr++ = '-';
+    }
     *ptr++ = hextable[haddr.c[2] >> 4];
     *ptr++ = hextable[haddr.c[2] & 0xF];
     *ptr++ = hextable[haddr.c[3] >> 4];
@@ -1494,6 +1629,7 @@
 
 static void strip_send(struct strip *strip_info, struct sk_buff *skb)
 {
+    InterruptStatus intstat;
     MetricomAddress haddr;
     unsigned char *ptr = strip_info->tx_buff;
     int doreset = (long)jiffies - strip_info->watchdog_doreset >= 0;
@@ -1565,6 +1701,7 @@
     /*
      * 3. Set up the strip_info ready to send the data (if any).
      */
+    intstat = DisableInterrupts();
     strip_info->tx_head = strip_info->tx_buff;
     strip_info->tx_left = ptr - strip_info->tx_buff;
     strip_info->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
@@ -1575,6 +1712,7 @@
     if (strip_info->tx_size - strip_info->tx_left < 20)
         printk(KERN_ERR "%s: Sending%5d bytes;%5d bytes free.\n", strip_info->dev.name,
             strip_info->tx_left, strip_info->tx_size - strip_info->tx_left);
+    RestoreInterrupts(intstat);
 
     /*
      * 5. If watchdog has expired, reset the radio. Note: if there's data waiting in
@@ -1673,6 +1811,7 @@
         strip_info->tx_average_pps = (strip_info->tx_average_pps + tx_pps_count + 1) / 2;
         strip_info->sx_average_pps = (strip_info->sx_average_pps + sx_pps_count + 1) / 2;
 
+#if STRIP_VERBOSE_MESSAGES
         if (rx_pps_count / 8 >= 10)
             printk(KERN_INFO "%s: WARNING: Receiving %ld packets per second.\n",
                 strip_info->dev.name, rx_pps_count / 8);
@@ -1682,6 +1821,7 @@
         if (sx_pps_count / 8 >= 10)
             printk(KERN_INFO "%s: WARNING: Sending   %ld packets per second.\n",
                 strip_info->dev.name, sx_pps_count / 8);
+#endif
     }
 
     strip_send(strip_info, skb);
@@ -2439,6 +2579,12 @@
 
     stats.rx_packets     = strip_info->rx_packets;
     stats.tx_packets     = strip_info->tx_packets;
+
+#ifdef EXT_COUNTERS
+    stats.rx_bytes       = strip_info->rx_bytes;
+    stats.tx_bytes       = strip_info->tx_bytes;
+#endif
+
     stats.rx_dropped     = strip_info->rx_dropped;
     stats.tx_dropped     = strip_info->tx_dropped;
     stats.tx_errors      = strip_info->tx_errors;
@@ -2490,6 +2636,9 @@
 
     strip_info->sx_count = 0;
     strip_info->tx_left  = 0;
+
+    strip_info->pushing  = 0;
+    strip_info->woke_up  = 0;
 
     strip_info->discard  = 0;
     strip_info->working  = FALSE;

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2005-01-09 10:39 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-01-09  1:45 STRIP Starmode Patch Michael Ryan
2005-01-09 10:39 ` Russell King

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).