patch-2.4.23 linux-2.4.23/drivers/net/wan/n2.c

Next file: linux-2.4.23/drivers/net/wan/sdla_chdlc.c
Previous file: linux-2.4.23/drivers/net/wan/lmc/lmc_proto.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.22/drivers/net/wan/n2.c linux-2.4.23/drivers/net/wan/n2.c
@@ -1,12 +1,11 @@
 /*
  * SDL Inc. RISCom/N2 synchronous serial card driver for Linux
  *
- * Copyright (C) 1998-2002 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1998-2003 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
  *
  * For information see http://hq.pm.waw.pl/hdlc/
  *
@@ -34,14 +33,21 @@
 #include "hd64570.h"
 
 
-static const char* version = "SDL RISCom/N2 driver version: 1.10";
+static const char* version = "SDL RISCom/N2 driver version: 1.14";
 static const char* devname = "RISCom/N2";
 
 #define USE_WINDOWSIZE 16384
 #define USE_BUS16BITS 1
 #define CLOCK_BASE 9830400	/* 9.8304 MHz */
-
+#define MAX_PAGES      16	/* 16 RAM pages at max */
+#define MAX_RAM_SIZE 0x80000	/* 512 KB */
+#if MAX_RAM_SIZE > MAX_PAGES * USE_WINDOWSIZE
+#undef MAX_RAM_SIZE
+#define MAX_RAM_SIZE (MAX_PAGES * USE_WINDOWSIZE)
+#endif
 #define N2_IOPORTS 0x10
+#define NEED_DETECT_RAM
+#define MAX_TX_BUFFERS 10
 
 static char *hw = NULL;	/* pointer to hw=xxx command line string */
 
@@ -86,16 +92,16 @@
 	struct card_s *card;
 	spinlock_t lock;	/* TX lock */
 	sync_serial_settings settings;
+	int valid;		/* port enabled */
+	int rxpart;		/* partial frame received, next frame invalid*/
 	unsigned short encoding;
 	unsigned short parity;
+	u16 rxin;		/* rx ring buffer 'in' pointer */
+	u16 txin;		/* tx ring buffer 'in' and 'last' pointers */
+	u16 txlast;
 	u8 rxs, txs, tmc;	/* SCA registers */
-	u8 valid;		/* port enabled */
 	u8 phy_node;		/* physical port # - 0 or 1 */
 	u8 log_node;		/* logical port # */
-	u8 rxin;		/* rx ring buffer 'in' pointer */
-	u8 txin;		/* tx ring buffer 'in' and 'last' pointers */
-	u8 txlast;
-	u8 rxpart;		/* partial frame received, next frame invalid*/
 }port_t;
 
 
@@ -106,8 +112,9 @@
 	u32 ram_size;		/* number of bytes */
 	u16 io;			/* IO Base address */
 	u16 buff_offset;	/* offset of first buffer of first channel */
+	u16 rx_ring_buffers;	/* number of buffers in a ring */
+	u16 tx_ring_buffers;
 	u8 irq;			/* IRQ (3-15) */
-	u8 ring_buffers;	/* number of buffers in a ring */
 
 	port_t ports[2];
 	struct card_s *next_card;
@@ -216,7 +223,7 @@
 	MOD_INC_USE_COUNT;
 	mcr &= port->phy_node ? ~DTR_PORT1 : ~DTR_PORT0; /* set DTR ON */
 	outb(mcr, io + N2_MCR);
-  
+
 	outb(inb(io + N2_PCR) | PCR_ENWIN, io + N2_PCR); /* open window */
 	outb(inb(io + N2_PSR) | PSR_DMAEN, io + N2_PSR); /* enable dma */
 	sca_open(hdlc);
@@ -297,62 +304,6 @@
 
 
 
-static u8 n2_count_page(card_t *card)
-{
-	u8 page;
-	int i, bcount = USE_WINDOWSIZE, wcount = USE_WINDOWSIZE/2;
-	u16 *dp = (u16*)card->winbase;
-	u8 *bp = (u8*)card->winbase;
-	u8 psr = inb(card->io + N2_PSR) & PSR_WINBITS;
-
-
-	for (page = 0; page < 16; page++) {
-		outb(psr | page, card->io + N2_PSR); /* select a page */
-		writeb(page, dp);
-		if (readb(dp) != page)
-			break;	/* If can't read back, no good memory */
-
-		outb(psr, card->io + N2_PSR); /* goto page 0 */
-		if (readb(dp))
-			break;	/* If page 0 changed, then wrapped around */
-
-		outb(psr | page, card->io + N2_PSR); /* select page again */
-
-		/*  first do byte tests */
-		for (i = 0; i < bcount; i++)
-			writeb(i, bp + i);
-		for (i = 0; i < bcount; i++)
-			if (readb(bp + i) != (i & 0xff))
-				return 0;
-
-		for (i = 0; i < bcount; i++)
-			writeb(~i, bp + i);
-		for (i = 0; i < bcount; i++)
-			if (readb(bp + i) != (~i & 0xff))
-				return 0;
-
-		/* next do 16-bit tests */
-		for (i = 0; i < wcount; i++)
-			writew(0x55AA, dp + i);
-		for (i = 0; i < wcount; i++)
-			if (readw(dp + i) != 0x55AA)
-				return 0;
-
-		for (i = 0; i < wcount; i++)
-			writew(0xAA55, dp + i);
-		for (i = 0; i < wcount; i++)
-			if (readw(dp + i) != 0xAA55)
-				return 0;
-
-		for (i = 0; i < wcount; i++)
-			writew(page, dp + i);
-	}
-
-	return page;
-}
-
-
-
 static void n2_destroy_card(card_t *card)
 {
 	int cnt;
@@ -376,11 +327,12 @@
 
 
 
-static int n2_run(unsigned long io, unsigned long irq, unsigned long winbase,
-		  long valid0, long valid1)
+static int __init n2_run(unsigned long io, unsigned long irq,
+			 unsigned long winbase, long valid0, long valid1)
 {
 	card_t *card;
 	u8 cnt, pcr;
+	int i;
 
 	if (io < 0x200 || io > 0x3FF || (io % N2_IOPORTS) != 0) {
 		printk(KERN_ERR "n2: invalid I/O port value\n");
@@ -391,7 +343,7 @@
 		printk(KERN_ERR "n2: invalid IRQ value\n");
 		return -ENODEV;
 	}
-    
+
 	if (winbase < 0xA0000 || winbase > 0xFFFFF || (winbase & 0xFFF) != 0) {
 		printk(KERN_ERR "n2: invalid RAM value\n");
 		return -ENODEV;
@@ -451,25 +403,27 @@
 	pcr = PCR_ENWIN | PCR_VPM | (USE_BUS16BITS ? PCR_BUS16 : 0);
 	outb(pcr, io + N2_PCR);
 
-	cnt = n2_count_page(card);
-	if (!cnt) {
-		printk(KERN_ERR "n2: memory test failed.\n");
-		n2_destroy_card(card);
-		return -EIO;
-	}
+	card->ram_size = sca_detect_ram(card, card->winbase, MAX_RAM_SIZE);
 
-	card->ram_size = cnt * USE_WINDOWSIZE;
+	/* number of TX + RX buffers for one port */
+	i = card->ram_size / ((valid0 + valid1) * (sizeof(pkt_desc) +
+						   HDLC_MAX_MRU));
 
-	/* 4 rings required for 2 ports, 2 rings for one port */
-	card->ring_buffers = card->ram_size /
-		((valid0 + valid1) * 2 * (sizeof(pkt_desc) + HDLC_MAX_MRU));
+	card->tx_ring_buffers = min(i / 2, MAX_TX_BUFFERS);
+	card->rx_ring_buffers = i - card->tx_ring_buffers;
 
-	card->buff_offset = (valid0 + valid1) * 2 * (sizeof(pkt_desc))
-		* card->ring_buffers;
+	card->buff_offset = (valid0 + valid1) * sizeof(pkt_desc) *
+		(card->tx_ring_buffers + card->rx_ring_buffers);
 
 	printk(KERN_DEBUG "n2: RISCom/N2 %u KB RAM, IRQ%u, "
-	       "using %u packets rings\n", card->ram_size / 1024, card->irq,
-	       card->ring_buffers);
+	       "using %u TX + %u RX packets rings\n", card->ram_size / 1024,
+	       card->irq, card->tx_ring_buffers, card->rx_ring_buffers);
+
+	if (card->tx_ring_buffers < 1) {
+		printk(KERN_ERR "n2: RAM test failed\n");
+		n2_destroy_card(card);
+		return -EIO;
+	}
 
 	pcr |= PCR_RUNSCA;		/* run SCA */
 	outb(pcr, io + N2_PCR);
@@ -531,7 +485,7 @@
 		return -ENOSYS;	/* no parameters specified, abort */
 	}
 
-	printk(KERN_INFO "%s (SCA-%s)\n", version, sca_version);
+	printk(KERN_INFO "%s\n", version);
 
 	do {
 		unsigned long io, irq, ram;
@@ -558,7 +512,7 @@
 				break;
 			hw++;
 		}
-      
+
 		if (!valid[0] && !valid[1])
 			break;	/* at least one port must be used */
 
@@ -566,7 +520,7 @@
 			n2_run(io, irq, ram, valid[0], valid[1]);
 
 		if (*hw == '\x0')
-			return 0;
+			return first_card ? 0 : -ENOSYS;
 	}while(*hw++ == ':');
 
 	printk(KERN_ERR "n2: invalid hardware parameters\n");
@@ -602,6 +556,6 @@
 
 MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
 MODULE_DESCRIPTION("RISCom/N2 serial port driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_PARM(hw, "s");		/* hw=io,irq,ram,ports:io,irq,... */
 EXPORT_NO_SYMBOLS;

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