aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChas Williams <chas@cmf.nrl.navy.mil>2008-06-17 19:19:24 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-17 19:19:24 -0400
commitdf3bc8bd8f8fd17e9b22859d82af38fa702e75b7 (patch)
treeff3172a18511fb244e8f8216dd6b344150b5c4f3
parent2be63b878f2a1e6d939b05f4f5cb733cb39bcd22 (diff)
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>
-rw-r--r--drivers/atm/suni.c121
-rw-r--r--drivers/atm/suni.h31
-rw-r--r--include/linux/sonet.h2
3 files changed, 133 insertions, 21 deletions
diff --git a/drivers/atm/suni.c b/drivers/atm/suni.c
index 6097f6877a44..6dd3f5919968 100644
--- a/drivers/atm/suni.c
+++ b/drivers/atm/suni.c
@@ -1,8 +1,14 @@
1/* drivers/atm/suni.c - PMC PM5346 SUNI (PHY) driver */ 1/*
2 * drivers/atm/suni.c - S/UNI PHY driver
3 *
4 * Supports the following:
5 * PMC PM5346 S/UNI LITE
6 * PMC PM5350 S/UNI 155 ULTRA
7 * PMC PM5355 S/UNI 622
8 */
2 9
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ 10/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4 11
5
6#include <linux/module.h> 12#include <linux/module.h>
7#include <linux/jiffies.h> 13#include <linux/jiffies.h>
8#include <linux/kernel.h> 14#include <linux/kernel.h>
@@ -146,25 +152,105 @@ static int get_diag(struct atm_dev *dev,void __user *arg)
146static int set_loopback(struct atm_dev *dev,int mode) 152static int set_loopback(struct atm_dev *dev,int mode)
147{ 153{
148 unsigned char control; 154 unsigned char control;
155 int reg, dle, lle;
156
157 if (PRIV(dev)->type == SUNI_MRI_TYPE_PM5355) {
158 reg = SUNI_MCM;
159 dle = SUNI_MCM_DLE;
160 lle = SUNI_MCM_LLE;
161 } else {
162 reg = SUNI_MCT;
163 dle = SUNI_MCT_DLE;
164 lle = SUNI_MCT_LLE;
165 }
149 166
150 control = GET(MCT) & ~(SUNI_MCT_DLE | SUNI_MCT_LLE); 167 control = dev->ops->phy_get(dev, reg) & ~(dle | lle);
151 switch (mode) { 168 switch (mode) {
152 case ATM_LM_NONE: 169 case ATM_LM_NONE:
153 break; 170 break;
154 case ATM_LM_LOC_PHY: 171 case ATM_LM_LOC_PHY:
155 control |= SUNI_MCT_DLE; 172 control |= dle;
156 break; 173 break;
157 case ATM_LM_RMT_PHY: 174 case ATM_LM_RMT_PHY:
158 control |= SUNI_MCT_LLE; 175 control |= lle;
159 break; 176 break;
160 default: 177 default:
161 return -EINVAL; 178 return -EINVAL;
162 } 179 }
163 PUT(control,MCT); 180 dev->ops->phy_put(dev, control, reg);
164 PRIV(dev)->loop_mode = mode; 181 PRIV(dev)->loop_mode = mode;
165 return 0; 182 return 0;
166} 183}
167 184
185/*
186 * SONET vs. SDH Configuration
187 *
188 * Z0INS (register 0x06): 0 for SONET, 1 for SDH
189 * ENSS (register 0x3D): 0 for SONET, 1 for SDH
190 * LEN16 (register 0x28): 0 for SONET, 1 for SDH (n/a for S/UNI 155 QUAD)
191 * LEN16 (register 0x50): 0 for SONET, 1 for SDH (n/a for S/UNI 155 QUAD)
192 * S[1:0] (register 0x46): 00 for SONET, 10 for SDH
193 */
194
195static int set_sonet(struct atm_dev *dev)
196{
197 if (PRIV(dev)->type == SUNI_MRI_TYPE_PM5355) {
198 PUT(GET(RPOP_RC) & ~SUNI_RPOP_RC_ENSS, RPOP_RC);
199 PUT(GET(SSTB_CTRL) & ~SUNI_SSTB_CTRL_LEN16, SSTB_CTRL);
200 PUT(GET(SPTB_CTRL) & ~SUNI_SPTB_CTRL_LEN16, SPTB_CTRL);
201 }
202
203 REG_CHANGE(SUNI_TPOP_APM_S, SUNI_TPOP_APM_S_SHIFT,
204 SUNI_TPOP_S_SONET, TPOP_APM);
205
206 return 0;
207}
208
209static int set_sdh(struct atm_dev *dev)
210{
211 if (PRIV(dev)->type == SUNI_MRI_TYPE_PM5355) {
212 PUT(GET(RPOP_RC) | SUNI_RPOP_RC_ENSS, RPOP_RC);
213 PUT(GET(SSTB_CTRL) | SUNI_SSTB_CTRL_LEN16, SSTB_CTRL);
214 PUT(GET(SPTB_CTRL) | SUNI_SPTB_CTRL_LEN16, SPTB_CTRL);
215 }
216
217 REG_CHANGE(SUNI_TPOP_APM_S, SUNI_TPOP_APM_S_SHIFT,
218 SUNI_TPOP_S_SDH, TPOP_APM);
219
220 return 0;
221}
222
223
224static int get_framing(struct atm_dev *dev, void __user *arg)
225{
226 int framing;
227 unsigned char s;
228
229
230 s = (GET(TPOP_APM) & SUNI_TPOP_APM_S) >> SUNI_TPOP_APM_S_SHIFT;
231 if (s == SUNI_TPOP_S_SONET)
232 framing = SONET_FRAME_SONET;
233 else
234 framing = SONET_FRAME_SDH;
235
236 return put_user(framing, (int __user *) arg) ? -EFAULT : 0;
237}
238
239static int set_framing(struct atm_dev *dev, void __user *arg)
240{
241 int mode;
242
243 if (get_user(mode, (int __user *) arg))
244 return -EFAULT;
245
246 if (mode == SONET_FRAME_SONET)
247 return set_sonet(dev);
248 else if (mode == SONET_FRAME_SDH)
249 return set_sdh(dev);
250
251 return -EINVAL;
252}
253
168 254
169static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) 255static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
170{ 256{
@@ -179,14 +265,16 @@ static int suni_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
179 case SONET_GETDIAG: 265 case SONET_GETDIAG:
180 return get_diag(dev,arg); 266 return get_diag(dev,arg);
181 case SONET_SETFRAMING: 267 case SONET_SETFRAMING:
182 if ((int)(unsigned long)arg != SONET_FRAME_SONET) return -EINVAL; 268 if (!capable(CAP_NET_ADMIN))
183 return 0; 269 return -EPERM;
270 return set_framing(dev, arg);
184 case SONET_GETFRAMING: 271 case SONET_GETFRAMING:
185 return put_user(SONET_FRAME_SONET,(int __user *)arg) ? 272 return get_framing(dev, arg);
186 -EFAULT : 0;
187 case SONET_GETFRSENSE: 273 case SONET_GETFRSENSE:
188 return -EINVAL; 274 return -EINVAL;
189 case ATM_SETLOOP: 275 case ATM_SETLOOP:
276 if (!capable(CAP_NET_ADMIN))
277 return -EPERM;
190 return set_loopback(dev,(int)(unsigned long)arg); 278 return set_loopback(dev,(int)(unsigned long)arg);
191 case ATM_GETLOOP: 279 case ATM_GETLOOP:
192 return put_user(PRIV(dev)->loop_mode,(int __user *)arg) ? 280 return put_user(PRIV(dev)->loop_mode,(int __user *)arg) ?
@@ -220,10 +308,6 @@ static int suni_start(struct atm_dev *dev)
220 unsigned long flags; 308 unsigned long flags;
221 int first; 309 int first;
222 310
223 if (!(dev->phy_data = kmalloc(sizeof(struct suni_priv),GFP_KERNEL)))
224 return -ENOMEM;
225
226 PRIV(dev)->dev = dev;
227 spin_lock_irqsave(&sunis_lock,flags); 311 spin_lock_irqsave(&sunis_lock,flags);
228 first = !sunis; 312 first = !sunis;
229 PRIV(dev)->next = sunis; 313 PRIV(dev)->next = sunis;
@@ -284,16 +368,21 @@ int suni_init(struct atm_dev *dev)
284{ 368{
285 unsigned char mri; 369 unsigned char mri;
286 370
371 if (!(dev->phy_data = kmalloc(sizeof(struct suni_priv),GFP_KERNEL)))
372 return -ENOMEM;
373 PRIV(dev)->dev = dev;
374
287 mri = GET(MRI); /* reset SUNI */ 375 mri = GET(MRI); /* reset SUNI */
376 PRIV(dev)->type = (mri & SUNI_MRI_TYPE) >> SUNI_MRI_TYPE_SHIFT;
288 PUT(mri | SUNI_MRI_RESET,MRI); 377 PUT(mri | SUNI_MRI_RESET,MRI);
289 PUT(mri,MRI); 378 PUT(mri,MRI);
290 PUT((GET(MT) & SUNI_MT_DS27_53),MT); /* disable all tests */ 379 PUT((GET(MT) & SUNI_MT_DS27_53),MT); /* disable all tests */
291 REG_CHANGE(SUNI_TPOP_APM_S,SUNI_TPOP_APM_S_SHIFT,SUNI_TPOP_S_SONET, 380 set_sonet(dev);
292 TPOP_APM); /* use SONET */
293 REG_CHANGE(SUNI_TACP_IUCHP_CLP,0,SUNI_TACP_IUCHP_CLP, 381 REG_CHANGE(SUNI_TACP_IUCHP_CLP,0,SUNI_TACP_IUCHP_CLP,
294 TACP_IUCHP); /* idle cells */ 382 TACP_IUCHP); /* idle cells */
295 PUT(SUNI_IDLE_PATTERN,TACP_IUCPOP); 383 PUT(SUNI_IDLE_PATTERN,TACP_IUCPOP);
296 dev->phy = &suni_ops; 384 dev->phy = &suni_ops;
385
297 return 0; 386 return 0;
298} 387}
299 388
diff --git a/drivers/atm/suni.h b/drivers/atm/suni.h
index efa79bfae75b..7e3e656b3993 100644
--- a/drivers/atm/suni.h
+++ b/drivers/atm/suni.h
@@ -1,7 +1,8 @@
1/* drivers/atm/suni.h - PMC PM5346 SUNI (PHY) declarations */ 1/*
2 * drivers/atm/suni.h - S/UNI PHY driver
3 */
2 4
3/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ 5/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
5 6
6#ifndef DRIVER_ATM_SUNI_H 7#ifndef DRIVER_ATM_SUNI_H
7#define DRIVER_ATM_SUNI_H 8#define DRIVER_ATM_SUNI_H
@@ -39,7 +40,8 @@
39#define SUNI_RLOP_LFM 0x1F /* RLOP Line FEBE MSB */ 40#define SUNI_RLOP_LFM 0x1F /* RLOP Line FEBE MSB */
40#define SUNI_TLOP_CTRL 0x20 /* TLOP Control */ 41#define SUNI_TLOP_CTRL 0x20 /* TLOP Control */
41#define SUNI_TLOP_DIAG 0x21 /* TLOP Diagnostic */ 42#define SUNI_TLOP_DIAG 0x21 /* TLOP Diagnostic */
42 /* 0x22-0x2F reserved */ 43 /* 0x22-0x27 reserved */
44#define SUNI_SSTB_CTRL 0x28
43#define SUNI_RPOP_SC 0x30 /* RPOP Status/Control */ 45#define SUNI_RPOP_SC 0x30 /* RPOP Status/Control */
44#define SUNI_RPOP_IS 0x31 /* RPOP Interrupt Status */ 46#define SUNI_RPOP_IS 0x31 /* RPOP Interrupt Status */
45 /* 0x32 reserved */ 47 /* 0x32 reserved */
@@ -52,6 +54,7 @@
52#define SUNI_RPOP_PFM 0x3B /* RPOP Path FEBE MSB */ 54#define SUNI_RPOP_PFM 0x3B /* RPOP Path FEBE MSB */
53 /* 0x3C reserved */ 55 /* 0x3C reserved */
54#define SUNI_RPOP_PBC 0x3D /* RPOP Path BIP-8 Configuration */ 56#define SUNI_RPOP_PBC 0x3D /* RPOP Path BIP-8 Configuration */
57#define SUNI_RPOP_RC 0x3D /* RPOP Ring Control (PM5355) */
55 /* 0x3E-0x3F reserved */ 58 /* 0x3E-0x3F reserved */
56#define SUNI_TPOP_CD 0x40 /* TPOP Control/Diagnostic */ 59#define SUNI_TPOP_CD 0x40 /* TPOP Control/Diagnostic */
57#define SUNI_TPOP_PC 0x41 /* TPOP Pointer Control */ 60#define SUNI_TPOP_PC 0x41 /* TPOP Pointer Control */
@@ -82,7 +85,8 @@
82#define SUNI_TACP_TCC 0x65 /* TACP Transmit Cell Counter */ 85#define SUNI_TACP_TCC 0x65 /* TACP Transmit Cell Counter */
83#define SUNI_TACP_TCCM 0x66 /* TACP Transmit Cell Counter MSB */ 86#define SUNI_TACP_TCCM 0x66 /* TACP Transmit Cell Counter MSB */
84#define SUNI_TACP_CFG 0x67 /* TACP Configuration */ 87#define SUNI_TACP_CFG 0x67 /* TACP Configuration */
85 /* 0x68-0x7F reserved */ 88#define SUNI_SPTB_CTRL 0x68 /* SPTB Control */
89 /* 0x69-0x7F reserved */
86#define SUNI_MT 0x80 /* Master Test */ 90#define SUNI_MT 0x80 /* Master Test */
87 /* 0x81-0xFF reserved */ 91 /* 0x81-0xFF reserved */
88 92
@@ -94,9 +98,18 @@
94#define SUNI_MRI_ID_SHIFT 0 98#define SUNI_MRI_ID_SHIFT 0
95#define SUNI_MRI_TYPE 0x70 /* R, SUNI type (lite is 011) */ 99#define SUNI_MRI_TYPE 0x70 /* R, SUNI type (lite is 011) */
96#define SUNI_MRI_TYPE_SHIFT 4 100#define SUNI_MRI_TYPE_SHIFT 4
101#define SUNI_MRI_TYPE_PM5346 0x3 /* S/UNI 155 LITE */
102#define SUNI_MRI_TYPE_PM5347 0x4 /* S/UNI 155 PLUS */
103#define SUNI_MRI_TYPE_PM5350 0x7 /* S/UNI 155 ULTRA */
104#define SUNI_MRI_TYPE_PM5355 0x1 /* S/UNI 622 */
97#define SUNI_MRI_RESET 0x80 /* RW, reset & power down chip 105#define SUNI_MRI_RESET 0x80 /* RW, reset & power down chip
98 0: normal operation 106 0: normal operation
99 1: reset & low power */ 107 1: reset & low power */
108
109/* MCM is reg 0x4 */
110#define SUNI_MCM_LLE 0x20 /* line loopback (PM5355) */
111#define SUNI_MCM_DLE 0x10 /* diagnostic loopback (PM5355) */
112
100/* MCT is reg 5 */ 113/* MCT is reg 5 */
101#define SUNI_MCT_LOOPT 0x01 /* RW, timing source, 0: from 114#define SUNI_MCT_LOOPT 0x01 /* RW, timing source, 0: from
102 TRCLK+/- */ 115 TRCLK+/- */
@@ -144,6 +157,12 @@
144/* TLOP_DIAG is reg 0x21 */ 157/* TLOP_DIAG is reg 0x21 */
145#define SUNI_TLOP_DIAG_DBIP 0x01 /* insert line BIP err (continuously) */ 158#define SUNI_TLOP_DIAG_DBIP 0x01 /* insert line BIP err (continuously) */
146 159
160/* SSTB_CTRL is reg 0x28 */
161#define SUNI_SSTB_CTRL_LEN16 0x01 /* path trace message length bit */
162
163/* RPOP_RC is reg 0x3D (PM5355) */
164#define SUNI_RPOP_RC_ENSS 0x40 /* enable size bit */
165
147/* TPOP_DIAG is reg 0x40 */ 166/* TPOP_DIAG is reg 0x40 */
148#define SUNI_TPOP_DIAG_PAIS 0x01 /* insert STS path alarm ind (cont) */ 167#define SUNI_TPOP_DIAG_PAIS 0x01 /* insert STS path alarm ind (cont) */
149#define SUNI_TPOP_DIAG_DB3 0x02 /* insert path BIP err (continuously) */ 168#define SUNI_TPOP_DIAG_DB3 0x02 /* insert path BIP err (continuously) */
@@ -191,6 +210,9 @@
191 pattern */ 210 pattern */
192#define SUNI_TACP_IUCHP_GFC_SHIFT 4 211#define SUNI_TACP_IUCHP_GFC_SHIFT 4
193 212
213/* SPTB_CTRL is reg 0x68 */
214#define SUNI_SPTB_CTRL_LEN16 0x01 /* path trace message length */
215
194/* MT is reg 0x80 */ 216/* MT is reg 0x80 */
195#define SUNI_MT_HIZIO 0x01 /* RW, all but data bus & MP interface 217#define SUNI_MT_HIZIO 0x01 /* RW, all but data bus & MP interface
196 tri-state */ 218 tri-state */
@@ -208,6 +230,7 @@
208struct suni_priv { 230struct suni_priv {
209 struct k_sonet_stats sonet_stats; /* link diagnostics */ 231 struct k_sonet_stats sonet_stats; /* link diagnostics */
210 int loop_mode; /* loopback mode */ 232 int loop_mode; /* loopback mode */
233 int type; /* phy type */
211 struct atm_dev *dev; /* device back-pointer */ 234 struct atm_dev *dev; /* device back-pointer */
212 struct suni_priv *next; /* next SUNI */ 235 struct suni_priv *next; /* next SUNI */
213}; 236};
diff --git a/include/linux/sonet.h b/include/linux/sonet.h
index 753680296e17..67ad11fcf88b 100644
--- a/include/linux/sonet.h
+++ b/include/linux/sonet.h
@@ -34,7 +34,7 @@ struct sonet_stats {
34 /* clear error insertion */ 34 /* clear error insertion */
35#define SONET_GETDIAG _IOR('a',ATMIOC_PHYTYP+4,int) 35#define SONET_GETDIAG _IOR('a',ATMIOC_PHYTYP+4,int)
36 /* query error insertion */ 36 /* query error insertion */
37#define SONET_SETFRAMING _IO('a',ATMIOC_PHYTYP+5) 37#define SONET_SETFRAMING _IOW('a',ATMIOC_PHYTYP+5,int)
38 /* set framing mode (SONET/SDH) */ 38 /* set framing mode (SONET/SDH) */
39#define SONET_GETFRAMING _IOR('a',ATMIOC_PHYTYP+6,int) 39#define SONET_GETFRAMING _IOR('a',ATMIOC_PHYTYP+6,int)
40 /* get framing mode */ 40 /* get framing mode */