diff -ur --new-file old/linux/drivers/atm/atmtcp.c new/linux/drivers/atm/atmtcp.c --- old/linux/drivers/atm/atmtcp.c Tue Aug 4 22:51:46 1998 +++ new/linux/drivers/atm/atmtcp.c Tue Aug 4 22:52:13 1998 @@ -6,9 +6,17 @@ #include <linux/atmdev.h> #include <linux/atm_tcp.h> #include <asm/uaccess.h> -#include "../../net/atm/tunable.h" /* fix this */ -#include "../../net/atm/protocols.h" /* fix this */ -#include "../../net/atm/resources.h" /* fix this */ +#include "../../net/atm/tunable.h" /* @@@ fix this */ +#include "../../net/atm/protocols.h" /* @@@ fix this */ + + +#define PRIV(dev) ((struct atmtcp_dev_data *) ((dev)->dev_data)) + + +struct atmtcp_dev_data { + struct atm_vcc *vcc; /* control VCC; NULL if detached */ + int persist; /* non-zero if persistent */ +}; #define DEV_LABEL "atmtcp" @@ -64,15 +72,18 @@ static int atmtcp_v_send(struct atm_vcc *vcc,struct sk_buff *skb) { + struct atmtcp_dev_data *dev_data; struct atm_vcc *out_vcc; struct sk_buff *new_skb; struct atmtcp_hdr *hdr; int size; - out_vcc = vcc->dev->dev_data; - if (!out_vcc) { + dev_data = PRIV(vcc->dev); + if (dev_data) out_vcc = dev_data->vcc; + if (!dev_data || !out_vcc) { if (vcc->pop) vcc->pop(vcc,skb); else dev_kfree_skb(skb); + if (dev_data) return 0; vcc->stats->tx_err++; return -ENOLINK; } @@ -101,10 +112,28 @@ } +static int atmtcp_v_proc(struct atm_dev *dev,loff_t *pos,char *page) +{ + struct atmtcp_dev_data *dev_data = PRIV(dev); + + if (*pos) return 0; + if (!dev_data->persist) return sprintf(page,"ephemeral\n"); + return sprintf(page,"persistent, %sconnected\n", + dev_data->vcc ? "" : "dis"); +} + + static void atmtcp_c_close(struct atm_vcc *vcc) { - ((struct atm_dev *) vcc->dev_data)->dev_data = NULL; - shutdown_atm_dev(vcc->dev_data); + struct atm_dev *atmtcp_dev; + struct atmtcp_dev_data *dev_data; + + atmtcp_dev = (struct atm_dev *) vcc->dev_data; + dev_data = PRIV(atmtcp_dev); + dev_data->vcc = NULL; + if (dev_data->persist) return; + kfree(dev_data); + shutdown_atm_dev(atmtcp_dev); vcc->dev_data = NULL; } @@ -168,7 +197,8 @@ NULL, /* no phy_get */ NULL, /* no feedback */ NULL, /* no change_qos */ - NULL /* no free_rx_skb */ + NULL, /* no free_rx_skb */ + atmtcp_v_proc /* proc_read */ }; @@ -191,11 +221,12 @@ NULL, /* no phy_get */ NULL, /* no feedback */ NULL, /* no change_qos */ - NULL /* no free_rx_skb */ + NULL, /* no free_rx_skb */ + NULL /* no proc_read */ }; -static struct atm_dev atmtcp_dev = { +static struct atm_dev atmtcp_control_dev = { &atmtcp_c_dev_ops, NULL, /* no PHY */ "atmtcp", /* type */ @@ -208,19 +239,73 @@ }; -int atmtcp_attach(struct atm_vcc *vcc,int itf) +static int atmtcp_create(int itf,int persist,struct atm_dev **result) { + struct atmtcp_dev_data *dev_data; struct atm_dev *dev; + dev_data = kmalloc(sizeof(*dev_data),GFP_KERNEL); + if (!dev_data) return -ENOMEM; dev = atm_dev_register(DEV_LABEL,&atmtcp_v_dev_ops,itf,0); - if (!dev) return itf == -1 ? -ENOMEM : -EBUSY; + if (!dev) { + kfree(dev_data); + return itf == -1 ? -ENOMEM : -EBUSY; + } dev->ci_range.vpi_bits = MAX_VPI_BITS; dev->ci_range.vci_bits = MAX_VCI_BITS; - dev->dev_data = vcc; - bind_vcc(vcc,&atmtcp_dev); + PRIV(dev) = dev_data; + PRIV(dev)->vcc = NULL; + PRIV(dev)->persist = persist; + if (result) *result = dev; + return 0; +} + + +int atmtcp_attach(struct atm_vcc *vcc,int itf) +{ + struct atm_dev *dev; + + dev = NULL; + if (itf != -1) dev = atm_find_dev(itf); + if (dev) { + if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE; + if (PRIV(dev)->vcc) return -EBUSY; + } + else { + int error; + + error = atmtcp_create(itf,0,&dev); + if (error) return error; + } + PRIV(dev)->vcc = vcc; + bind_vcc(vcc,&atmtcp_control_dev); vcc->flags |= ATM_VF_READY | ATM_VF_META; vcc->dev_data = dev; (void) atm_init_aal5(vcc); /* @@@ losing AAL in transit ... */ - vcc->stats = &atmtcp_dev.stats.aal5; + vcc->stats = &atmtcp_control_dev.stats.aal5; return dev->number; +} + + +int atmtcp_create_persistent(int itf) +{ + return atmtcp_create(itf,1,NULL); +} + + +int atmtcp_remove_persistent(int itf) +{ + struct atm_dev *dev; + struct atmtcp_dev_data *dev_data; + + dev = atm_find_dev(itf); + if (!dev) return -ENODEV; + if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE; + dev_data = PRIV(dev); + if (!dev_data->persist) return 0; + dev_data->persist = 0; + if (PRIV(dev)->vcc) return 0; + kfree(dev_data); + shutdown_atm_dev(dev); + return 0; } diff -ur --new-file old/linux/drivers/atm/eni.c new/linux/drivers/atm/eni.c --- old/linux/drivers/atm/eni.c Tue Aug 4 22:51:46 1998 +++ new/linux/drivers/atm/eni.c Tue Aug 4 22:52:13 1998 @@ -1941,17 +1941,20 @@ DPRINTK(">eni_send\n"); if (!ENI_VCC(vcc)->tx) { - dev_kfree_skb(skb); + if (vcc->pop) vcc->pop(vcc,skb); + else dev_kfree_skb(skb); return -EINVAL; } if (!skb) { printk(KERN_CRIT "!skb in eni_send ?\n"); - dev_kfree_skb(skb); + if (vcc->pop) vcc->pop(vcc,skb); + else dev_kfree_skb(skb); return -EINVAL; } if (vcc->qos.aal == ATM_AAL0) { if (skb->len != ATM_CELL_SIZE-1) { - dev_kfree_skb(skb); + if (vcc->pop) vcc->pop(vcc,skb); + else dev_kfree_skb(skb); return -EINVAL; } *(u32 *) skb->data = htonl(*(u32 *) skb->data); diff -ur --new-file old/linux/drivers/atm/suni.c new/linux/drivers/atm/suni.c --- old/linux/drivers/atm/suni.c Tue Aug 4 22:51:46 1998 +++ new/linux/drivers/atm/suni.c Tue Aug 4 22:52:13 1998 @@ -14,6 +14,7 @@ #include <linux/delay.h> #include <linux/timer.h> #include <linux/init.h> +#include <linux/atm_suni.h> #include <asm/system.h> #include <asm/param.h> #include <asm/uaccess.h> @@ -239,6 +240,14 @@ suni_hz(0); /* clear SUNI counters */ (void) fetch_stats(dev,NULL,1); /* clear kernel counters */ cli(); +{ +int i; +printk("SUNI:\n"); +for (i = 0; i < 256; i++) { + printk(" %02x",dev->ops->phy_get(dev,i)); + if ((i & 15) == 15) printk("\n"); +} +} if (!start_timer) restore_flags(flags); else { start_timer = 0; diff -ur --new-file old/linux/drivers/atm/suni.h new/linux/drivers/atm/suni.h --- old/linux/drivers/atm/suni.h Tue Aug 4 22:51:46 1998 +++ new/linux/drivers/atm/suni.h Tue Aug 4 22:52:13 1998 @@ -1,6 +1,6 @@ /* drivers/atm/suni.h - PMC SUNI (PHY) declarations */ -/* Written 1995 by Werner Almesberger, EPFL LRC */ +/* Written 1995,1998 by Werner Almesberger, EPFL LRC/ICA */ #ifndef DRIVER_ATM_SUNI_H @@ -201,15 +201,6 @@ #define SUNI_IDLE_PATTERN 0x6a /* idle pattern */ - -/* ioctls */ - -#define SUNI_GETLOOP _IOR('a',ATMIOC_PHYPRV,int) /* get loopback mode */ -#define SUNI_SETLOOP _IO('a',ATMIOC_PHYPRV+1) /* set loopback mode */ - -#define SUNI_LM_NONE 0 /* no loopback */ -#define SUNI_LM_DIAG 1 /* diagnostic (i.e. loop TX to RX) */ -#define SUNI_LM_LOOP 2 /* line (i.e. loop RX to TX) */ #ifdef __KERNEL__ diff -ur --new-file old/linux/drivers/atm/zatm.c new/linux/drivers/atm/zatm.c --- old/linux/drivers/atm/zatm.c Tue Aug 4 22:51:46 1998 +++ new/linux/drivers/atm/zatm.c Tue Aug 4 22:52:13 1998 @@ -851,7 +851,8 @@ dsc = (u32 *) kmalloc(uPD98401_TXPD_SIZE*2+ uPD98401_TXBD_SIZE*skb->atm.iovcnt,GFP_ATOMIC); if (!dsc) { - dev_kfree_skb(skb); + if (vcc->pop) vcc->pop(vcc,skb); + else dev_kfree_skb(skb); return -EAGAIN; } /* @@@ should check alignment */ @@ -1743,12 +1744,14 @@ EVENT(">zatm_send 0x%lx\n",(unsigned long) skb,0); if (!ZATM_VCC(vcc)->tx_chan || !(vcc->flags & ATM_VF_READY)) { - dev_kfree_skb(skb); + if (vcc->pop) vcc->pop(vcc,skb); + else dev_kfree_skb(skb); return -EINVAL; } if (!skb) { printk(KERN_CRIT "!skb in zatm_send ?\n"); - dev_kfree_skb(skb); + if (vcc->pop) vcc->pop(vcc,skb); + else dev_kfree_skb(skb); return -EINVAL; } skb->atm.vcc = vcc; diff -ur --new-file old/linux/include/linux/atm.h new/linux/include/linux/atm.h --- old/linux/include/linux/atm.h Tue Aug 4 22:51:46 1998 +++ new/linux/include/linux/atm.h Tue Aug 4 22:52:13 1998 @@ -217,7 +217,6 @@ }; -#define SIOCSIFATMTCP _IO('a',ATMIOC_ITF) /* set ATMTCP mode */ #define ATM_CREATE_LEAF _IO('a',ATMIOC_SPECIAL+2) /* create a point-to-multipoint leaf socket */ diff -ur --new-file old/linux/include/linux/atm_suni.h new/linux/include/linux/atm_suni.h --- old/linux/include/linux/atm_suni.h Thu Jan 1 01:00:00 1970 +++ new/linux/include/linux/atm_suni.h Tue Aug 4 22:52:13 1998 @@ -0,0 +1,19 @@ +/* atm_suni.h - Driver-specific declarations of the SUNI driver (for use by + driver-specific utilities) */ + +/* Written 1998 by Werner Almesberger, EPFL ICA */ + + +#ifndef LINUX_ATM_SUNI_H +#define LINUX_ATM_SUNI_H + +#include <linux/atmioc.h> + +#define SUNI_GETLOOP _IOR('a',ATMIOC_PHYPRV,int) /* get loopback mode */ +#define SUNI_SETLOOP _IO('a',ATMIOC_PHYPRV+1) /* set loopback mode */ + +#define SUNI_LM_NONE 0 /* no loopback */ +#define SUNI_LM_DIAG 1 /* diagnostic (i.e. loop TX to RX) */ +#define SUNI_LM_LOOP 2 /* line (i.e. loop RX to TX) */ + +#endif diff -ur --new-file old/linux/include/linux/atm_tcp.h new/linux/include/linux/atm_tcp.h --- old/linux/include/linux/atm_tcp.h Tue Aug 4 22:51:46 1998 +++ new/linux/include/linux/atm_tcp.h Tue Aug 4 22:52:13 1998 @@ -7,7 +7,10 @@ #ifndef LINUX_ATM_TCP_H #define LINUX_ATM_TCP_H +#ifdef __KERNEL__ #include <linux/types.h> +#endif +#include <linux/atmioc.h> /* @@ -21,9 +24,18 @@ }; +#define SIOCSIFATMTCP _IO('a',ATMIOC_ITF) /* set ATMTCP mode */ +#define ATMTCP_CREATE _IO('a',ATMIOC_ITF+14) /* create persistent ATMTCP + interface */ +#define ATMTCP_REMOVE _IO('a',ATMIOC_ITF+15) /* destroy persistent ATMTCP + interface*/ + + #ifdef __KERNEL__ int atmtcp_attach(struct atm_vcc *vcc,int itf); +int atmtcp_create_persistent(int itf); +int atmtcp_remove_persistent(int itf); #endif diff -ur --new-file old/linux/include/linux/atmclip.h new/linux/include/linux/atmclip.h --- old/linux/include/linux/atmclip.h Tue Aug 4 22:51:46 1998 +++ new/linux/include/linux/atmclip.h Tue Aug 4 22:52:13 1998 @@ -1,6 +1,6 @@ /* atmclip.h - Classical IP over ATM */ -/* Written 1995-1997 by Werner Almesberger, EPFL LRC */ +/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ #ifndef LINUX_ATMCLIP_H @@ -17,5 +17,10 @@ #define CLIP_CHECK_INTERVAL 10 /* check every ten seconds */ #define SIOCMKCLIP _IO('a',ATMIOC_CLIP) /* create IP interface */ + + +#ifdef __KERNEL__ +void clip_xmit_vcc(struct sk_buff *skb,struct atm_vcc *vcc); +#endif #endif diff -ur --new-file old/linux/include/linux/atmdev.h new/linux/include/linux/atmdev.h --- old/linux/include/linux/atmdev.h Tue Aug 4 22:51:46 1998 +++ new/linux/include/linux/atmdev.h Tue Aug 4 22:52:13 1998 @@ -283,7 +283,10 @@ struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops, int number,unsigned long flags); /* number == -1: pick first available */ +struct atm_dev *atm_find_dev(int number); void atm_dev_deregister(struct atm_dev *dev); +void shutdown_atm_dev(struct atm_dev *dev); +void bind_vcc(struc