/* drivers/atm/uPD98402.c - NEC uPD98402 (PHY) declarations */
 
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
 

#include <linux/module.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/atmdev.h>
#include <linux/sonet.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/atomic.h>

#include "uPD98402.h"


#if 0
#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
#else
#define DPRINTK(format,args...)
#endif


struct uPD98402_priv {
	struct k_sonet_stats sonet_stats;/* link diagnostics */
	unsigned char framing;		/* SONET/SDH framing */
	int loop_mode;			/* loopback mode */
	spinlock_t lock;
};


#define PRIV(dev) ((struct uPD98402_priv *) dev->phy_data)

#define PUT(val,reg) dev->ops->phy_put(dev,val,uPD98402_##reg)
#define GET(reg) dev->ops->phy_get(dev,uPD98402_##reg)


static int fetch_stats(struct atm_dev *dev,struct sonet_stats __user *arg,int zero)
{
	struct sonet_stats tmp;
 	int error = 0;

	atomic_add(GET(HECCT),&PRIV(dev)->sonet_stats.uncorr_hcs);
	sonet_copy_stats(&PRIV(dev)->sonet_stats,&tmp);
	if (arg) error = copy_to_user(arg,&tmp,sizeof(tmp));
	if (zero && !error) {
		/* unused fields are reported as -1, but we must not "adjust"
		   them */
		tmp.corr_hcs = tmp.tx_cells = tmp.rx_cells = 0;
		sonet_subtract_stats(&PRIV(dev)->sonet_stats,&tmp);
	}
	return error ? -EFAULT : 0;
}


static int set_framing(struct atm_dev *dev,unsigned char framing)
{
	static const unsigned char sonet[] = { 1,2,3,0 };
	static const unsigned char sdh[] = { 1,0,0,2 };
	const char *set;
	unsigned long flags;
 
	switch (framing) {
		case SONET_FRAME_SONET:
			set = sonet;
			break;
		case SONET_FRAME_SDH:
			set = sdh;
			break;
		default:
			return -EINVAL;
	}
	spin_lock_irqsave(&PRIV(dev)->lock, flags);
	PUT(set[0],C11T);
	PUT(set[1],C12T);
	PUT(set[2],C13T);
	PUT((GET(MDR) & ~uPD98402_MDR_SS_MASK) | (set[3] <<
	    uPD98402_MDR_SS_SHIFT),MDR);
	spin_unlock_irqrestore(&PRIV(dev)->lock, flags);
	return 0;
}


static int get_sense(struct atm_dev *dev,u8 __user *arg)
{
	unsigned long flags;
	unsigned char s[3];

	spin_lock_irqsave(&PRIV(dev)->lock, flags);
	s[0] = GET(C11R);
	s[1] = GET(C12R);
	s[2] = GET(C13R);
	spin_unlock_irqrestore(&PRIV(dev)->lock, flags);
	return (put_user(s[0], arg) || put_user(s[1], arg+1) ||
	    put_user(s[2], arg+2) || put_user(0xff, arg+3) ||
	    put_user(0xff, arg+4) || put_user(0xff, arg+5)) ? -EFAULT : 0;
}


static int set_loopback(struct atm_dev *dev,int mode)
{
	unsigned char mode_reg;

	mode_reg = GET(MDR) & ~(uPD98402_MDR_TPLP | uPD98402_MDR_ALP |
	    uPD98402_MDR_RPLP);
	switch (__ATM_LM_XTLOC(mode)) {
		case __ATM_LM_NONE:
			break;
		case __ATM_LM_PHY:
			mode_reg |= uPD98402_MDR_TPLP;
			break;
		case __ATM_LM_ATM:
			mode_reg |= uPD98402_MDR_ALP;
			break;
		default:
			return -EINVAL;
	}
	switch (__ATM_LM_XTRMT(mode)) {
		case __ATM_LM_NONE:
			break;
		case __ATM_LM_PHY:
			mode_reg |= uPD98402_MDR_RPLP;
			break;
		default:
			return -EINVAL;
	}
	PUT(mode_reg,MDR);
	PRIV(dev)->loop_mode = mode;
	return 0;
}


static int uPD98402_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
{
	switch (cmd) {

		case SONET_GETSTATZ:
                case SONET_GETSTAT:
			return fetch_stats(dev,arg, cmd == SONET_GETSTATZ);
		case SONET_SETFRAMING:
			return set_framing(dev, (int)(unsigned long)arg);
		case SONET_GETFRAMING:
			return put_user(PRIV(dev)->framing,(int __user *)arg) ?
			    -EFAULT : 0;
		case SONET_GETFRSENSE:
			return get_sense(dev,arg);
		case ATM_SETLOOP:
			return set_loopback(dev, (int)(unsigned long)arg);
		case ATM_GETLOOP:
			return put_user(PRIV(dev)->loop_mode,(int __user *)arg) ?
			    -EFAULT : 0;
		case ATM_QUERYLOOP:
			return put_user(ATM_LM_LOC_PHY | ATM_LM_LOC_ATM |
			    ATM_LM_RMT_PHY,(int __user *)arg) ? -EFAULT : 0;
		default:
			return -ENOIOCTLCMD;
	}
}


#define ADD_LIMITED(s,v) \
    { atomic_add(GET(v),&PRIV(dev)->sonet_stats.s); \
    if (atomic_read(&PRIV(dev)->sonet_stats.s) < 0) \
	atomic_set(&PRIV(dev)->sonet_stats.s,INT_MAX); }


static void stat_event(struct atm_dev *dev)
{
	unsigned char events;

	events = GET(PCR);
	if (events & uPD98402_PFM_PFEB) ADD_LIMITED(path_febe,PFECB);
	if (events & uPD98402_PFM_LFEB) ADD_LIMITED(line_febe,LECCT);
	if (events & uPD98402_PFM_B3E) ADD_LIMITED(path_bip,B3ECT);
	if (events & uPD98402_PFM_B2E) ADD_LIMITED(line_bip,B2ECT);
	if (events & uPD98402_PFM_B1E) ADD_LIMITED(section_bip,B1ECT);
}


#undef ADD_LIMITED


static void uPD98402_int(struct atm_dev *dev)
{
	static unsigned long silence = 0;
	unsigned char reason;

	while ((reason = GET(PICR))) {
		if (reason & uPD98402_INT_LOS)
			printk(KERN_NOTICE "%s(itf %d): signal lost\n",
			    dev->type,dev->number);
		if (reason & uPD98402_INT_PFM) stat_event(dev);
		if (reason & uPD98402_INT_PCO) {
			(void) GET(PCOCR); /* clear interrupt cause */
			atomic_add(GET(HECCT),
			    &PRIV(dev)->sonet_stats.uncorr_hcs);
		}
		if ((reason & uPD98402_INT_RFO) && 
		    (time_after(jiffies, silence) || silence == 0)) {
			printk(KERN_WARNING "%s(itf %d): uPD98402 receive "
			    "FIFO overflow\n",dev->type,dev->number);
			silence = (jiffies+HZ/2)|1;
		}
	}
}


static int uPD98402_start(struct atm_dev *dev)
{
	DPRINTK("phy_start\n");
	if (!(dev->dev_data = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL)))
		return -ENOMEM;
	spin_lock_init(&PRIV(dev)->lock);
	memset(&PRIV(dev)->sonet_stats,0,sizeof(struct k_sonet_stats));
	(void) GET(PCR); /* clear performance events */
	PUT(uPD98402_PFM_FJ,PCMR); /* ignore frequency adj */
	(void) GET(PCOCR); /* clear overflows */
	PUT(~uPD98402_PCO_HECC,PCOMR);
	(void) GET(PICR); /* clear interrupts */
	PUT(~(uPD98402_INT_PFM | uPD98402_INT_ALM | uPD98402_INT_RFO |
	  uPD98402_INT_LOS),PIMR); /* enable them */
	(void) fetch_stats(dev,NULL,1); /* clear kernel counters */
	atomic_set(&PRIV(dev)->sonet_stats.corr_hcs,-1);
	atomic_set(&PRIV(dev)->sonet_stats.tx_cells,-1);
	atomic_set(&PRIV(dev)->sonet_stats.rx_cells,-1);
	return 0;
}


static int uPD98402_stop(struct atm_dev *dev)
{
	/* let SAR driver worry about stopping interrupts */
	kfree(PRIV(dev));
	return 0;
}


static const struct atmphy_ops uPD98402_ops = {
	.start		= uPD98402_start,
	.ioctl		= uPD98402_ioctl,
	.interrupt	= uPD98402_int,
	.stop		= uPD98402_stop,
};


int uPD98402_init(struct atm_dev *dev)
{
DPRINTK("phy_init\n");
	dev->phy = &uPD98402_ops;
	return 0;
}


MODULE_LICENSE("GPL");

EXPORT_SYMBOL(uPD98402_init);

static __init int uPD98402_module_init(void)
{
	return 0;
}
module_init(uPD98402_module_init);
/* module_exit not defined so not unloadable */
