#if defined(MODVERSIONS)
#include <linux/modversions.h>
#endif
//#include <linux/config.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mii.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/version.h>
#include <asm/dma.h>

//#include "ip175d.h"

#define DRV_NAME	"ip175d"

static struct net_device* pNet_dev=NULL;


#define Write_Reg(phy,reg,val)	phy_write(phy,reg,val)	//modify this to MII interface
#define Read_Reg(phy,reg)	phy_read(phy,reg)			//modify this to MII interface
void phy_write(int phyaddr, int regaddr, int value)		//modify this to MII interface
{
}
u16 phy_read(int phyaddr, int regaddr)					//modify this to MII interface
{
	return 0;
}


void write_reg_bits(u16 phyaddr,u16 regaddr,u16 bitnum,u16 bitstart,u16 value)
{
	u16 reg_val=Read_Reg(phyaddr,regaddr);
	u16 bitmsk=0,i;
	for(i=0;i<bitnum;i++){
		bitmsk|=(u16)0x1<<(i);
	}
	reg_val &= ~(bitmsk<<bitstart);
	reg_val |= (value&bitmsk)<<bitstart;
	Write_Reg(phyaddr,regaddr,reg_val);
}

u16 read_reg_bits(u16 phyaddr,u16 regaddr,u16 bitnum,u16 bitstart)
{
	u16 reg_val=Read_Reg(phyaddr,regaddr);
	u16 bitmsk=0,i;
	for(i=0;i<bitnum;i++){
		bitmsk|=(u16)0x1<<(i);
	}
	return (reg_val>>bitstart)&bitmsk;
}


static int os_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
//	struct mii_ioctl_data *mii = (struct mii_ioctl_data*)&ifr->ifr_data;
//	printk(KERN_ERR "\n IP175d IOCTL called! (%08x)\n",cmd);
	switch(cmd)
	{
	case	SIOCSMIIREG:	//WriteMDC
		{
		struct mii_ioctl_data *mii = (struct mii_ioctl_data*)&ifr->ifr_data;
		printk(KERN_ERR"Phy:%d Reg:%d D:%04x",mii->phy_id,mii->reg_num,mii->val_in);
		Write_Reg(mii->phy_id,mii->reg_num,mii->val_in);
		}
		return 0;
		break;
	case	SIOCGMIIREG:	//ReadMDC
		{
		struct mii_ioctl_data *mii = (struct mii_ioctl_data*)&ifr->ifr_data;
		printk(KERN_ERR"Phy:%d Reg:%d",mii->phy_id,mii->reg_num);
		mii->val_out=Read_Reg(mii->phy_id,mii->reg_num);
		//printk(KERN_ERR"D:%04x",mii->val_out);
		}
		return 0;
		break;
	}
	return -EOPNOTSUPP;
}

static const struct net_device_ops ip_netdev_ops = {
        .ndo_do_ioctl = os_do_ioctl,
};



struct net_device * __init linux_probe(void)
{	
	u8 MACID[6]={0x00,0x00,0x00,0x00,0x17,0x5d};
	struct net_device* dev;
	u16 register_err;
	const struct net_device_ops *netdev_ops;



	dev= alloc_etherdev(sizeof(*dev));	//get device name eth0
	if(!dev) {
		printk("\ndriver allocation fail");
		return ERR_PTR(-ENOMEM);
	}
	pNet_dev=dev;
	strcpy(dev->name,DRV_NAME);

	dev->netdev_ops =  &ip_netdev_ops;
	memcpy(dev->dev_addr,MACID,sizeof(MACID));

	printk("\nModule load!");
	register_err=register_netdev(dev);
	if( register_err )	//register netdevice fail
	{	printk("\nregister netdev fail");
		//release_region(dev->base_addr,2);
		free_netdev(dev);
		return(ERR_PTR(register_err));
	}
	return dev;
}
int __init init_module(void)
{
	linux_probe();
	return 0;
}
void __exit cleanup_module(void)
{
	printk(KERN_ERR "\nModule");
//	printk("\nModule(%s)",pNet_dev->name);
	unregister_netdev(pNet_dev);
	free_netdev(pNet_dev);
	printk(KERN_ERR " removed!\n");
}



