865 iow(db, DM9KS_RXCR, 0x00); /* Disable RX */
866
867 /* Dump Statistic counter */
868 #if FALSE
869 printk('nRX FIFO OVERFLOW %lxn', db->stats.rx_fifo_errors);
870 printk('RX CRC %lxn', db->stats.rx_crc_errors);
871 printk('RX LEN Err %lxn', db->stats.rx_length_errors);
872 printk('RESET %xn', db->reset_counter);
873 printk('RESET: TX Timeout %xn', db->reset_tx_timeout);
874 printk('g_TX_nsr %xn', g_TX_nsr);
875 #endif
876
877 return 0;
878 }
879
880 static void dmfe_tx_done(unsigned long unused)
881 {
882 struct net_device *dev = dmfe_dev;
883 board_info_t *db = (board_info_t *)dev->priv;
884 int nsr;
885
886 DMFE_DBUG(0, 'dmfe_tx_done()', 0);
887
888 nsr = ior(db, DM9KS_NSR);
889 if (nsr & 0x0c)
890 {
891 if(nsr & 0x04) db->tx_pkt_cnt--;
892 if(nsr & 0x08) db->tx_pkt_cnt--;
893 if(db->tx_pkt_cnt < 0)
894 {
895 printk(KERN_DEBUG 'DM9KS:tx_pkt_cnt ERROR!!n');
896 while(ior(db,DM9KS_TCR) & 0x1){}
897 db->tx_pkt_cnt = 0;
898 }
899
900 }else{
901 while(ior(db,DM9KS_TCR) & 0x1){}
902 db->tx_pkt_cnt = 0;
903 }
904
905 netif_wake_queue(dev);
906
907 return;
908 }
909
910 /*
911 DM9000 insterrupt handler
912 receive the packet to upper layer, free the transmitted packet
913 */
914 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
915 static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
916 #else
917 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
918 static irqreturn_t dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)
919 #else
920 static irqreturn_t dmfe_interrupt(int irq, void *dev_id) /* for kernel 2.6.20*/
921 #endif
922 #endif
923 {
924 struct net_device *dev = dev_id;
925 board_info_t *db;
926 int int_status,i;
927 u8 reg_save;
928
929 DMFE_DBUG(0, 'dmfe_interrupt()', 0);
930
931 /* A real interrupt coming */
932 db = (board_info_t *)dev->priv;
933 spin_lock(&db->lock);
934
935 /* Save previous register address */
936 reg_save = inb(db->io_addr);
937
938 /* Disable all interrupt */
939 iow(db, DM9KS_IMR, DM9KS_DISINTR);
940
941 /* Got DM9000/DM9010 interrupt status */
942 int_status = ior(db, DM9KS_ISR); /* Got ISR */
943 iow(db, DM9KS_ISR, int_status); /* Clear ISR status */
944
945 /* Link status change */
946 if (int_status & DM9KS_LINK_INTR)
947 {
948 netif_stop_queue(dev);
949 for(i=0; i<500; i++) /*wait link OK, waiting time =0.5s */
950 {
951 phy_read(db,0x1);
952 if(phy_read(db,0x1) & 0x4) /*Link OK*/
953 {
954 /* wait for detected Speed */
955 for(i=0; i<200;i++)
956 udelay(1000);
957 /* set media speed */
958 if(phy_read(db,0)&0x2000) db->Speed =100;
959 else db->Speed =10;
960 break;
961 }
962 udelay(1000);
963 }
964 netif_wake_queue(dev);
965 //printk('[INTR]i=%d speed=%dn',i, (int)(db->Speed));
966 }
967 /* Received the coming packet */
968 if (int_status & DM9KS_RX_INTR)
969 dmfe_packet_receive(dev);
970
971 /* Trnasmit Interrupt check */
972 if (int_status & DM9KS_TX_INTR)
973 dmfe_tx_done(0);
974
975 if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT)
976 {
977 iow(db, DM9KS_IMR, 0xa2);
978 }
979 else
980 {
981 /* Re-enable interrupt mask */
982 iow(db, DM9KS_IMR, DM9KS_REGFF);
983 }
984
985 /* Restore previous register address */
986 outb(reg_save, db->io_addr);
987
988 spin_unlock(&db->lock);
989 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
990 return IRQ_HANDLED;
991 #endif
992 }
993
994 /*
995 Get statistics from driver.
996 */
997 static struct net_device_stats * dmfe_get_stats(struct net_device *dev)
998 {
999 board_info_t *db = (board_info_t *)dev->priv;
1000 DMFE_DBUG(0, 'dmfe_get_stats', 0);
1001 return &db->stats;
1002 }
1003 /*
1004 * Process the ethtool ioctl command
1005 */
1006 static int dmfe_ethtool_ioctl(struct net_device *dev, void *useraddr)
1007 {
1008 //struct dmfe_board_info *db = dev->priv;
1009 struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
1010 u32 ethcmd;
1011
1012 if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd)))
1013 return -EFAULT;
1014
1015 switch (ethcmd)
1016 {
1017 case ETHTOOL_GDRVINFO:
1018 strcpy(info.driver, DRV_NAME);
1019 strcpy(info.version, DRV_VERSION);
1020
1021 sprintf(info.bus_info, 'ISA 0x%lx %d',dev->base_addr, dev->irq);
1022 if (copy_to_user(useraddr, &info, sizeof(info)))
1023 return -EFAULT;
1024 return 0;
1025 }
1026
1027 return -EOPNOTSUPP;
1028 }
1029 /*
1030 Process the upper socket ioctl command
1031 */
1032 static int dmfe_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1033 {
1034 board_info_t *db = (board_info_t *)dev->priv;
1035 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) /* for kernel 2.6.7 */
1036 struct mii_ioctl_data *data=(struct mii_ioctl_data *)&ifr->ifr_data;
1037 #endif
1038 int rc=0;
1039
1040 DMFE_DBUG(0, 'dmfe_do_ioctl()', 0);
1041
1042 if (!netif_running(dev))
1043 return -EINVAL;
1044
1045 if (cmd == SIOCETHTOOL)
1046 rc = dmfe_ethtool_ioctl(dev, (void *) ifr->ifr_data);
1047 else {
1048 spin_lock_irq(&db->lock);
1049 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) /* for kernel 2.6.7 */
1050 rc = generic_mii_ioctl(&db->mii, data, cmd, NULL);
1051 #else
1052 rc = generic_mii_ioctl(&db->mii, if_mii(ifr), cmd, NULL);
1053 #endif
上一篇:s3c2440的USB热插拔驱动问题
下一篇:S3C实现DMA驱动程序编写
推荐阅读最新更新时间:2024-11-10 01:21
设计资源 培训 开发板 精华推荐
- 【ART-Pi】基于POWERBUS的通讯主站
- LTC2908CTS8-B1、3.3V、2.5V、1.8V、1.2V四路电源监视器的典型应用电路
- LTC4055EUF 演示板、USB 电源控制器和锂离子充电器、适配器输入 = 4.5V 至 5.5V、USB 输入 = 4.35V 至 5.5V
- LM2595ADPBCKGEVB:降压开关稳压器评估板
- 0.96寸oled小电视TV
- 用于 Intel 486TM DX4TM Overdrive 微处理器的 LT1587CT-3.3 3.3V/3A 低压差稳压器的典型应用
- SC284P 双通道 2.5MHz、2.0A 同步降压的典型应用,具有自动省电功能
- ADZS-21479-EZLITE、ADSP-2147x EZ-KIT Lite 评估系统基于 SHARC 数字信号处理器 (DSP)
- LTC3567 的典型应用 - 具有 I2C 控制功能的高效 USB 电源管理器和 1A 降压-升压转换器
- WS2812b灯带 穿越机灯带