atm: [suni] add support for setting loopback and framing modes
Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2be63b878f
commit
df3bc8bd8f
3 changed files with 133 additions and 21 deletions
|
@ -1,8 +1,14 @@
|
||||||
/* drivers/atm/suni.c - PMC PM5346 SUNI (PHY) driver */
|
/*
|
||||||
|
* drivers/atm/suni.c - S/UNI PHY driver
|
||||||
|
*
|
||||||
|
* Supports the following:
|
||||||
|
* PMC PM5346 S/UNI LITE
|
||||||
|
* PMC PM5350 S/UNI 155 ULTRA
|
||||||
|
* PMC PM5355 S/UNI 622
|
||||||
|
*/
|
||||||
|
|
||||||
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
|
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
|
||||||
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
@ -146,25 +152,105 @@ static int get_diag(struct atm_dev *dev,void __user *arg)
|
||||||
static int set_loopback(struct atm_dev *dev,int mode)
|
static int set_loopback(struct atm_dev *dev,int mode)
|
||||||
{
|
{
|
||||||
unsigned char control;
|
unsigned char control;
|
||||||
|
int reg, dle, lle;
|
||||||
|
|
||||||
control = GET(MCT) & ~(SUNI_MCT_DLE | SUNI_MCT_LLE);
|
if (PRIV(dev)->type == SUNI_MRI_TYPE_PM5355) {
|
||||||
|
reg = SUNI_MCM;
|
||||||
|
dle = SUNI_MCM_DLE;
|
||||||
|
lle = SUNI_MCM_LLE;
|
||||||
|
} else {
|
||||||
|
reg = SUNI_MCT;
|
||||||
|
dle = SUNI_MCT_DLE;
|
||||||
|
lle = SUNI_MCT_LLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
control = dev->ops->phy_get(dev, reg) & ~(dle | lle);
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case ATM_LM_NONE:
|
case ATM_LM_NONE:
|
||||||
break;
|
break;
|
||||||
case ATM_LM_LOC_PHY:
|
case ATM_LM_LOC_PHY:
|
||||||
control |= SUNI_MCT_DLE;
|
control |= dle;
|
||||||
break;
|
break;
|
||||||
case ATM_LM_RMT_PHY:
|
case ATM_LM_RMT_PHY:
|
||||||
control |= SUNI_MCT_LLE;
|
control |= lle;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
PUT(control,MCT);
|
dev->ops->phy_put(dev, control, reg);
|
||||||
PRIV(dev)->loop_mode = mode;
|
PRIV(dev)->loop_mode = mode;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SONET vs. SDH Configuration
|
||||||
|
*
|
||||||
|
* Z0INS (register 0x06): 0 for SONET, 1 for SDH
|
||||||
|
* ENSS (register 0x3D): 0 for SONET, 1 for SDH
|
||||||
|
* LEN16 (register 0x28): 0 for SONET, 1 for SDH (n/a for S/UNI 155 QUAD)
|
||||||
|
* LEN16 (register 0x50): 0 for SONET, 1 for SDH (n/a for S/UNI 155 QUAD)
|
||||||
|
* S[1:0] (register 0x46): 00 for SONET, 10 for SDH
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int set_sonet(struct atm_dev *dev)
|
||||||
|
{
|
||||||
|
if (PRIV(dev)->type == SUNI_MRI_TYPE_PM5355) {
|
||||||
|
PUT(GET(RPOP_RC) & ~SUNI_RPOP_RC_ENSS, RPOP_RC);
|
||||||
|
PUT(GET(SSTB_CTRL) & ~SUNI_SSTB_CTRL_LEN16, SSTB_CTRL);
|
||||||
|
PUT(GET(SPTB_CTRL) & ~SUNI_SPTB_CTRL_LEN16, SPTB_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
REG_CHANGE(SUNI_TPOP_APM_S, SUNI_TPOP_APM_S_SHIFT,
|
||||||
|
SUNI_TPOP_S_SONET, TPOP_APM);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_sdh(struct atm_dev *dev)
|
||||||
|
{
|
||||||
|
if (PRIV(dev)->type == SUNI_MRI_TYPE_PM5355) {
|
||||||
|
PUT(GET(RPOP_RC) | SUNI_RPOP_RC_ENSS, RPOP_RC);
|
||||||
|
PUT(GET(SSTB_CTRL) | SUNI_SSTB_CTRL_LEN16, SSTB_CTRL);
|
||||||
|
PUT(GET(SPTB_CTRL) | SUNI_SPTB_CTRL_LEN16, SPTB_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
REG_CHANGE(SUNI_TPOP_APM_S, SUNI_TPOP_APM_S_SHIFT,
|
||||||
|
SUNI_TPOP_S_SDH, TPOP_APM);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int get_framing(struct atm_dev *dev, void __user *arg)
|
||||||
|
{
|
||||||
|
int framing;
|
||||||
|
unsigned char s;
|
||||||
|
|
||||||
|
|
||||||
|
s = (GET(TPOP_APM) & SUNI_TPOP_APM_S) >> SUNI_TPOP_APM_S_SHIFT;
|
||||||
|
if (s == SUNI_TPOP_S_SONET)
|
||||||
|
framing = SONET_FRAME_SONET;
|
||||||
|
else
|
||||||
|
framing = SONET_FRAME_SDH;
|
||||||
|
|
||||||
|
return put_user(framing, (int __user *) arg) ? -EFAULT : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_framing(struct atm_dev *dev, void __user *arg)
|
||||||
|
{
|
||||||
|
int mode;
|
||||||
|
|
||||||
|
if (get_user(mode, (int __user *) arg))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
if (mode == SONET_FRAME_SONET)
|
||||||
|
return set_sonet(dev);
|
||||||
|
else if (mode == SONET_FRAME_SDH)
|
||||||
|
return set_sdh(dev);
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
|
static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
|
||||||
{
|
{
|
||||||
|
@ -179,14 +265,16 @@ static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
|
||||||
case SONET_GETDIAG:
|
case SONET_GETDIAG:
|
||||||
return get_diag(dev,arg);
|
return get_diag(dev,arg);
|
||||||
case SONET_SETFRAMING:
|
case SONET_SETFRAMING:
|
||||||
if ((int)(unsigned long)arg != SONET_FRAME_SONET) return -EINVAL;
|
if (!capable(CAP_NET_ADMIN))
|
||||||
return 0;
|
return -EPERM;
|
||||||
|
return set_framing(dev, arg);
|
||||||
case SONET_GETFRAMING:
|
case SONET_GETFRAMING:
|
||||||
return put_user(SONET_FRAME_SONET,(int __user *)arg) ?
|
return get_framing(dev, arg);
|
||||||
-EFAULT : 0;
|
|
||||||
case SONET_GETFRSENSE:
|
case SONET_GETFRSENSE:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
case ATM_SETLOOP:
|
case ATM_SETLOOP:
|
||||||
|
if (!capable(CAP_NET_ADMIN))
|
||||||
|
return -EPERM;
|
||||||
return set_loopback(dev,(int)(unsigned long)arg);
|
return set_loopback(dev,(int)(unsigned long)arg);
|
||||||
case ATM_GETLOOP:
|
case ATM_GETLOOP:
|
||||||
return put_user(PRIV(dev)->loop_mode,(int __user *)arg) ?
|
return put_user(PRIV(dev)->loop_mode,(int __user *)arg) ?
|
||||||
|
@ -220,10 +308,6 @@ static int suni_start(struct atm_dev *dev)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int first;
|
int first;
|
||||||
|
|
||||||
if (!(dev->phy_data = kmalloc(sizeof(struct suni_priv),GFP_KERNEL)))
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
PRIV(dev)->dev = dev;
|
|
||||||
spin_lock_irqsave(&sunis_lock,flags);
|
spin_lock_irqsave(&sunis_lock,flags);
|
||||||
first = !sunis;
|
first = !sunis;
|
||||||
PRIV(dev)->next = sunis;
|
PRIV(dev)->next = sunis;
|
||||||
|
@ -284,16 +368,21 @@ int suni_init(struct atm_dev *dev)
|
||||||
{
|
{
|
||||||
unsigned char mri;
|
unsigned char mri;
|
||||||
|
|
||||||
|
if (!(dev->phy_data = kmalloc(sizeof(struct suni_priv),GFP_KERNEL)))
|
||||||
|
return -ENOMEM;
|
||||||
|
PRIV(dev)->dev = dev;
|
||||||
|
|
||||||
mri = GET(MRI); /* reset SUNI */
|
mri = GET(MRI); /* reset SUNI */
|
||||||
|
PRIV(dev)->type = (mri & SUNI_MRI_TYPE) >> SUNI_MRI_TYPE_SHIFT;
|
||||||
PUT(mri | SUNI_MRI_RESET,MRI);
|
PUT(mri | SUNI_MRI_RESET,MRI);
|
||||||
PUT(mri,MRI);
|
PUT(mri,MRI);
|
||||||
PUT((GET(MT) & SUNI_MT_DS27_53),MT); /* disable all tests */
|
PUT((GET(MT) & SUNI_MT_DS27_53),MT); /* disable all tests */
|
||||||
REG_CHANGE(SUNI_TPOP_APM_S,SUNI_TPOP_APM_S_SHIFT,SUNI_TPOP_S_SONET,
|
set_sonet(dev);
|
||||||
TPOP_APM); /* use SONET */
|
|
||||||
REG_CHANGE(SUNI_TACP_IUCHP_CLP,0,SUNI_TACP_IUCHP_CLP,
|
REG_CHANGE(SUNI_TACP_IUCHP_CLP,0,SUNI_TACP_IUCHP_CLP,
|
||||||
TACP_IUCHP); /* idle cells */
|
TACP_IUCHP); /* idle cells */
|
||||||
PUT(SUNI_IDLE_PATTERN,TACP_IUCPOP);
|
PUT(SUNI_IDLE_PATTERN,TACP_IUCPOP);
|
||||||
dev->phy = &suni_ops;
|
dev->phy = &suni_ops;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/* drivers/atm/suni.h - PMC PM5346 SUNI (PHY) declarations */
|
/*
|
||||||
|
* drivers/atm/suni.h - S/UNI PHY driver
|
||||||
|
*/
|
||||||
|
|
||||||
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
|
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
|
||||||
|
|
||||||
|
|
||||||
#ifndef DRIVER_ATM_SUNI_H
|
#ifndef DRIVER_ATM_SUNI_H
|
||||||
#define DRIVER_ATM_SUNI_H
|
#define DRIVER_ATM_SUNI_H
|
||||||
|
|
||||||
|
@ -39,7 +40,8 @@
|
||||||
#define SUNI_RLOP_LFM 0x1F /* RLOP Line FEBE MSB */
|
#define SUNI_RLOP_LFM 0x1F /* RLOP Line FEBE MSB */
|
||||||
#define SUNI_TLOP_CTRL 0x20 /* TLOP Control */
|
#define SUNI_TLOP_CTRL 0x20 /* TLOP Control */
|
||||||
#define SUNI_TLOP_DIAG 0x21 /* TLOP Diagnostic */
|
#define SUNI_TLOP_DIAG 0x21 /* TLOP Diagnostic */
|
||||||
/* 0x22-0x2F reserved */
|
/* 0x22-0x27 reserved */
|
||||||
|
#define SUNI_SSTB_CTRL 0x28
|
||||||
#define SUNI_RPOP_SC 0x30 /* RPOP Status/Control */
|
#define SUNI_RPOP_SC 0x30 /* RPOP Status/Control */
|
||||||
#define SUNI_RPOP_IS 0x31 /* RPOP Interrupt Status */
|
#define SUNI_RPOP_IS 0x31 /* RPOP Interrupt Status */
|
||||||
/* 0x32 reserved */
|
/* 0x32 reserved */
|
||||||
|
@ -52,6 +54,7 @@
|
||||||
#define SUNI_RPOP_PFM 0x3B /* RPOP Path FEBE MSB */
|
#define SUNI_RPOP_PFM 0x3B /* RPOP Path FEBE MSB */
|
||||||
/* 0x3C reserved */
|
/* 0x3C reserved */
|
||||||
#define SUNI_RPOP_PBC 0x3D /* RPOP Path BIP-8 Configuration */
|
#define SUNI_RPOP_PBC 0x3D /* RPOP Path BIP-8 Configuration */
|
||||||
|
#define SUNI_RPOP_RC 0x3D /* RPOP Ring Control (PM5355) */
|
||||||
/* 0x3E-0x3F reserved */
|
/* 0x3E-0x3F reserved */
|
||||||
#define SUNI_TPOP_CD 0x40 /* TPOP Control/Diagnostic */
|
#define SUNI_TPOP_CD 0x40 /* TPOP Control/Diagnostic */
|
||||||
#define SUNI_TPOP_PC 0x41 /* TPOP Pointer Control */
|
#define SUNI_TPOP_PC 0x41 /* TPOP Pointer Control */
|
||||||
|
@ -82,7 +85,8 @@
|
||||||
#define SUNI_TACP_TCC 0x65 /* TACP Transmit Cell Counter */
|
#define SUNI_TACP_TCC 0x65 /* TACP Transmit Cell Counter */
|
||||||
#define SUNI_TACP_TCCM 0x66 /* TACP Transmit Cell Counter MSB */
|
#define SUNI_TACP_TCCM 0x66 /* TACP Transmit Cell Counter MSB */
|
||||||
#define SUNI_TACP_CFG 0x67 /* TACP Configuration */
|
#define SUNI_TACP_CFG 0x67 /* TACP Configuration */
|
||||||
/* 0x68-0x7F reserved */
|
#define SUNI_SPTB_CTRL 0x68 /* SPTB Control */
|
||||||
|
/* 0x69-0x7F reserved */
|
||||||
#define SUNI_MT 0x80 /* Master Test */
|
#define SUNI_MT 0x80 /* Master Test */
|
||||||
/* 0x81-0xFF reserved */
|
/* 0x81-0xFF reserved */
|
||||||
|
|
||||||
|
@ -94,9 +98,18 @@
|
||||||
#define SUNI_MRI_ID_SHIFT 0
|
#define SUNI_MRI_ID_SHIFT 0
|
||||||
#define SUNI_MRI_TYPE 0x70 /* R, SUNI type (lite is 011) */
|
#define SUNI_MRI_TYPE 0x70 /* R, SUNI type (lite is 011) */
|
||||||
#define SUNI_MRI_TYPE_SHIFT 4
|
#define SUNI_MRI_TYPE_SHIFT 4
|
||||||
|
#define SUNI_MRI_TYPE_PM5346 0x3 /* S/UNI 155 LITE */
|
||||||
|
#define SUNI_MRI_TYPE_PM5347 0x4 /* S/UNI 155 PLUS */
|
||||||
|
#define SUNI_MRI_TYPE_PM5350 0x7 /* S/UNI 155 ULTRA */
|
||||||
|
#define SUNI_MRI_TYPE_PM5355 0x1 /* S/UNI 622 */
|
||||||
#define SUNI_MRI_RESET 0x80 /* RW, reset & power down chip
|
#define SUNI_MRI_RESET 0x80 /* RW, reset & power down chip
|
||||||
0: normal operation
|
0: normal operation
|
||||||
1: reset & low power */
|
1: reset & low power */
|
||||||
|
|
||||||
|
/* MCM is reg 0x4 */
|
||||||
|
#define SUNI_MCM_LLE 0x20 /* line loopback (PM5355) */
|
||||||
|
#define SUNI_MCM_DLE 0x10 /* diagnostic loopback (PM5355) */
|
||||||
|
|
||||||
/* MCT is reg 5 */
|
/* MCT is reg 5 */
|
||||||
#define SUNI_MCT_LOOPT 0x01 /* RW, timing source, 0: from
|
#define SUNI_MCT_LOOPT 0x01 /* RW, timing source, 0: from
|
||||||
TRCLK+/- */
|
TRCLK+/- */
|
||||||
|
@ -144,6 +157,12 @@
|
||||||
/* TLOP_DIAG is reg 0x21 */
|
/* TLOP_DIAG is reg 0x21 */
|
||||||
#define SUNI_TLOP_DIAG_DBIP 0x01 /* insert line BIP err (continuously) */
|
#define SUNI_TLOP_DIAG_DBIP 0x01 /* insert line BIP err (continuously) */
|
||||||
|
|
||||||
|
/* SSTB_CTRL is reg 0x28 */
|
||||||
|
#define SUNI_SSTB_CTRL_LEN16 0x01 /* path trace message length bit */
|
||||||
|
|
||||||
|
/* RPOP_RC is reg 0x3D (PM5355) */
|
||||||
|
#define SUNI_RPOP_RC_ENSS 0x40 /* enable size bit */
|
||||||
|
|
||||||
/* TPOP_DIAG is reg 0x40 */
|
/* TPOP_DIAG is reg 0x40 */
|
||||||
#define SUNI_TPOP_DIAG_PAIS 0x01 /* insert STS path alarm ind (cont) */
|
#define SUNI_TPOP_DIAG_PAIS 0x01 /* insert STS path alarm ind (cont) */
|
||||||
#define SUNI_TPOP_DIAG_DB3 0x02 /* insert path BIP err (continuously) */
|
#define SUNI_TPOP_DIAG_DB3 0x02 /* insert path BIP err (continuously) */
|
||||||
|
@ -191,6 +210,9 @@
|
||||||
pattern */
|
pattern */
|
||||||
#define SUNI_TACP_IUCHP_GFC_SHIFT 4
|
#define SUNI_TACP_IUCHP_GFC_SHIFT 4
|
||||||
|
|
||||||
|
/* SPTB_CTRL is reg 0x68 */
|
||||||
|
#define SUNI_SPTB_CTRL_LEN16 0x01 /* path trace message length */
|
||||||
|
|
||||||
/* MT is reg 0x80 */
|
/* MT is reg 0x80 */
|
||||||
#define SUNI_MT_HIZIO 0x01 /* RW, all but data bus & MP interface
|
#define SUNI_MT_HIZIO 0x01 /* RW, all but data bus & MP interface
|
||||||
tri-state */
|
tri-state */
|
||||||
|
@ -208,6 +230,7 @@
|
||||||
struct suni_priv {
|
struct suni_priv {
|
||||||
struct k_sonet_stats sonet_stats; /* link diagnostics */
|
struct k_sonet_stats sonet_stats; /* link diagnostics */
|
||||||
int loop_mode; /* loopback mode */
|
int loop_mode; /* loopback mode */
|
||||||
|
int type; /* phy type */
|
||||||
struct atm_dev *dev; /* device back-pointer */
|
struct atm_dev *dev; /* device back-pointer */
|
||||||
struct suni_priv *next; /* next SUNI */
|
struct suni_priv *next; /* next SUNI */
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,7 +34,7 @@ struct sonet_stats {
|
||||||
/* clear error insertion */
|
/* clear error insertion */
|
||||||
#define SONET_GETDIAG _IOR('a',ATMIOC_PHYTYP+4,int)
|
#define SONET_GETDIAG _IOR('a',ATMIOC_PHYTYP+4,int)
|
||||||
/* query error insertion */
|
/* query error insertion */
|
||||||
#define SONET_SETFRAMING _IO('a',ATMIOC_PHYTYP+5)
|
#define SONET_SETFRAMING _IOW('a',ATMIOC_PHYTYP+5,int)
|
||||||
/* set framing mode (SONET/SDH) */
|
/* set framing mode (SONET/SDH) */
|
||||||
#define SONET_GETFRAMING _IOR('a',ATMIOC_PHYTYP+6,int)
|
#define SONET_GETFRAMING _IOR('a',ATMIOC_PHYTYP+6,int)
|
||||||
/* get framing mode */
|
/* get framing mode */
|
||||||
|
|
Loading…
Reference in a new issue