ibmtr LAA support.

Rogier Wolff (R.E.Wolff@BitWizard.nl)
Wed, 9 Jun 1999 14:58:44 +0200 (MEST)


Hi,

I've worked a bit more on the ibmtr case, and tried implementing the
"right way to do it", as Alan convinced me.

However, some bugs in the hardware seem to prevent this. The patch
below contains my previous attempt as a workaround until someone can
get a better workaround for the hardware bug, and it contains my
attempt at "doing it right" as an annotation how it should eventually
be done.

Alan, Could you approve of this patch to go into the 2.0.x queue?
(Paul Norton gave me the go-ahead to submit this directly to you,
although he is listed as the maintainer).

Regards,

Roger.

diff -ur linux-2.0.36.clean/drivers/net/ibmtr.c linux-2.0.36.ibmtr/drivers/net/ibmtr.c
--- linux-2.0.36.clean/drivers/net/ibmtr.c Sun Nov 15 19:33:03 1998
+++ linux-2.0.36.ibmtr/drivers/net/ibmtr.c Wed Jun 9 14:51:51 1999
@@ -55,11 +55,47 @@
from being rudely overwritten before the transmit cycle is
complete. (August 15 1996)

+ Changes by Roger E. Wolff (R.E.Wolff@BitWizard.nl) :
+ - added support for Locally Administrated Adresses
+ (May 30 - Jun 3 1999)
+ (Thanks to Uwe Fisher for sponsoring this change!)
+
+
Warnings !!!!!!!!!!!!!!
This driver is only partially sanitized for support of multiple
adapters. It will almost definitely fail if more than one
active adapter is identified.
*/
+
+
+/* LAA means that you can decide the hardware MAC address
+ * locally. Because routing on token ring networks is based on the
+ * hardware MAC addresses, this can simplify routing tables
+ * enormously.
+ *
+ * Alan Cox convinced me that the way this is implemented here (with a
+ * module option "laa=....") is not the way to do this. However, the
+ * ibmtr card seems to dislike not being opened immediately after
+ * being initialized. So as a work around, the ibmtr card is opened
+ * immediately after getting initialized. (if you have a token ring
+ * hub (whatever they are called) you can see it come on the ring
+ * immediately too!). This however means that passing the mac address
+ * using ifconfig after initialization, but before opening the card is
+ * no longer possible. So setting the LAA using the module option is a
+ * temporary work around.
+ *
+ * In the meanwhile we can look for what in the initialization makes
+ * the card accept the open. (close/open (== ifconfig down // ifconfig
+ * up) doesn't work either, you need to rmmod/insmod the module to get
+ * the card working again.)
+ *
+ * The "way to go" is to implement "dev->set_mac_address", which
+ * allows ifconfig tr0 hw tr <laa> to work. This is also implemented,
+ * but alas, doesn't work for me.
+ *
+ * -- REW
+ * */
+

#ifdef PCMCIA
#define MODULE
@@ -173,7 +209,9 @@
static int tok_close(struct device *dev);
static int tok_send_packet(struct sk_buff *skb, struct device *dev);
static struct enet_statistics * tok_get_stats(struct device *dev);
+static int tok_set_mac_address (struct device *dev, void *addr);
void tr_readlog(struct device *dev);
+static char * get_laa (struct device *dev);

static struct timer_list tr_timer={NULL,NULL,0,0L,tok_open_adapter};

@@ -215,11 +253,12 @@

int tok_probe(struct device *dev)
{
- unsigned char segment=0, intr=0, irq=0, i=0, j=0, cardpresent=NOTOK,temp=0;
+ unsigned char segment=0, intr=0, irq=0, i=0, j=0, cardpresent=NOTOK, temp;
__u32 t_mmio=0;
short PIOaddr=0, iAddr;
struct tok_info *ti=0;
static struct tok_info *badti=0; /* if fail after kmalloc, reuse */
+ char *laa;

static unsigned char Shared_Ram_Base = IBMTR_SHARED_RAM_BASE;

@@ -387,25 +426,58 @@
}

/* Get hw address of token ring card */
+ dev->dev_addr[0] = 0; /* Make sure this is initialized */
+ laa = get_laa (dev);
+ if (laa && strlen (laa) > 0) {
+ char *p = laa;
+ char *newp;
+ int j;
+ u8 laa_mac[6];
+
+ for (j=0; (*p && (j<6)); j++) {
+ laa_mac[j] = simple_strtoul(p, &newp, 16);
+ if (*newp == '.') p=++newp;
+ else {
+ if (j < 5) laa_mac[0] = 0; /* Not enough numbers */
+ break;
+ }
+ }
+
+ if ((laa_mac[0] >= 0x40) && (laa_mac[0] <= 0x7f)) {
+ /* Valid LAA, use it */
+ printk(KERN_DEBUG "%s: Using locally administered address %x.%x.%x.%x.%x.%x\n",
+ dev->name, laa_mac[0],laa_mac[1],laa_mac[2],
+ laa_mac[3], laa_mac[4],laa_mac[5]);
+
+ for (j=0; j < 6;j++)
+ dev->dev_addr[j] = laa_mac[j];
+ } else
+ printk(KERN_WARNING "%s: Invalid locally administered address %s\n", dev->name, laa);
+ }
+ if (!dev->dev_addr[0]) {
+ /* Get hw address of token ring card */
+
#if !TR_NEWFORMAT
- DPRINTK("hw address: ");
+ DPRINTK("hw address: ");
#endif
- j=0;
- for (i=0; i<0x18; i=i+2) {
- /* technical reference states to do this */
- temp = readb(ti->mmio + AIP + i) & 0x0f;
+
+ j=0;
+ for (i=0; i<0x18; i=i+2) {
+ /* technical reference states to do this */
+ temp = readb(ti->mmio + AIP + i) & 0x0f;
#if !TR_NEWFORMAT
- printk("%1X",ti->hw_address[j]=temp);
+ printk("%1X",ti->hw_address[j]=temp);
#else
- ti->hw_address[j]=temp;
+ ti->hw_address[j]=temp;
#endif
- if(j&1)
- dev->dev_addr[(j/2)]=ti->hw_address[j]+(ti->hw_address[j-1]<<4);
- ++j;
- }
+ if(j&1)
+ dev->dev_addr[(j/2)]=ti->hw_address[j]+(ti->hw_address[j-1]<<4);
+ ++j;
+ }
#ifndef TR_NEWFORMAT
- printk("\n");
+ printk("\n");
#endif
+ }

/* get Adapter type: 'F' = Adapter/A, 'E' = 16/4 Adapter II,...*/
ti->adapter_type = readb(ti->mmio + AIPADAPTYPE);
@@ -591,6 +663,7 @@
dev->get_stats = NULL;
dev->get_stats = tok_get_stats;
dev->set_multicast_list = NULL;
+ dev->set_mac_address = tok_set_mac_address;
tr_setup(dev);

return 0;
@@ -1164,6 +1237,10 @@

writeb(DIR_OPEN_ADAPTER,
ti->init_srb + offsetof(struct dir_open_adapter, command));
+ for (i=0;i<6;i++)
+ writeb (dev->dev_addr[i],
+ ti->init_srb + offsetof(struct dir_open_adapter, node_address) + i);
+
writew(htons(OPEN_PASS_BCON_MAC),
ti->init_srb + offsetof(struct dir_open_adapter, open_options));
writew(htons(NUM_RCV_BUF),
@@ -1488,6 +1565,30 @@
dev->tbusy=1; /* really srb busy... */
}

+
+
+static int tok_set_mac_address (struct device *dev, void *addr)
+{
+ /* This doesn't work yet. Closing/reopening doesn't work on my card. */
+#ifdef NOTYET
+ struct sockaddr *saddr = addr;
+
+ if (dev->start) {
+ DPRINTK ("Cannot set mac address while card is open.\n");
+ return -EIO;
+ }
+
+ memcpy (dev->dev_addr, saddr->sa_data, dev->addr_len);
+ tok_close (dev);
+
+ return 0;
+#else
+ return -EIO;
+#endif
+}
+
+
+
/* tok_get_stats(): Basically a scaffold routine which will return
the address of the tr_statistics structure associated with
this device -- the tr.... structure is a ethnet look-alike
@@ -1512,6 +1613,7 @@

static int io = 0xa20;
static char *device = NULL;
+static char *laa;

int init_module(void)
{
@@ -1540,4 +1642,20 @@
irq2dev_map[dev_ibmtr.irq] = NULL;
release_region(dev_ibmtr.base_addr, TR_IO_EXTENT);
}
+
+
+/* This driver DOES NOT support more than one card yet. */
+char *get_laa (struct device *dev)
+{
+ return laa;
+}
+
+#else
+
+/* Not module: laa not supported. */
+char *get_laa (struct device *dev)
+{
+ return NULL;
+}
+
#endif /* MODULE */

-- 
** R.E.Wolff@BitWizard.nl ** http://www.BitWizard.nl/ ** +31-15-2137555 **
*-- BitWizard writes Linux device drivers for any device you may have! --*
------ Microsoft SELLS you Windows, Linux GIVES you the whole house ------

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/