色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > Davicom公司DM9000A和DM9010 ISA NIC 以太網(wǎng)驅(qū)動(dòng)分析

          Davicom公司DM9000A和DM9010 ISA NIC 以太網(wǎng)驅(qū)動(dòng)分析

          作者: 時(shí)間:2012-11-02 來(lái)源:網(wǎng)絡(luò) 收藏

          receive the packet to upper layer, free the transmitted packet

          */

          #if LINUX_VERSION_CODE KERNEL_VERSION(2,5,0)

          static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)

          #else

          static irqreturn_t dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)

          #endif

          {

          struct net_device *dev = dev_id;

          board_info_t *db;

          int int_status,i;

          u8 reg_save;

          DMFE_DBUG(0, dmfe_interrupt(), 0);

          /* A real interrupt coming */

          db = (board_info_t *)dev->priv;

          spin_lock(db->lock);

          /* Save previous register address */

          reg_save = inb(db->io_addr);

          /* Disable all interrupt */

          iow(db, DM9KS_IMR, DM9KS_DISINTR);

          /* Got / interrupt status */

          int_status = ior(db, DM9KS_ISR); /* Got ISR */

          iow(db, DM9KS_ISR, int_status); /* Clear ISR status */

          /* Link status change */

          if (int_status DM9KS_LINK_INTR)

          {

          netif_stop_queue(dev);

          for(i=0; i500; i++) /*wait link OK, waiting time =0.5s */

          {

          phy_read(db,0x1);

          if(phy_read(db,0x1) 0x4) /*Link OK*/

          {

          /* wait for detected Speed */

          for(i=0; i200;i++)

          udelay(1000);

          /* set media speed */

          if(phy_read(db,0)0x2000) db->Speed =100;

          else db->Speed =10;

          break;

          }

          udelay(1000);

          }

          netif_wake_queue(dev);

          //printk([INTR]i=%d speed=%dn,i, (int)(db->Speed));

          }

          /* Received the coming packet */

          if (int_status DM9KS_RX_INTR)

          dmfe_packet_receive(dev);

          /* Trnasmit Interrupt check */

          if (int_status DM9KS_TX_INTR)

          dmfe_tx_done(0);

          if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT)

          {

          iow(db, DM9KS_IMR, 0xa2);

          }

          else

          {

          /* Re-enable interrupt mask */

          iow(db, DM9KS_IMR, DM9KS_REGFF);

          }

          /* Restore previous register address */

          outb(reg_save, db->io_addr);

          spin_unlock(db->lock);

          #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)

          return IRQ_HANDLED;

          #endif

          }

          /*

          Get statistics from driver.

          */

          static struct net_device_stats * dmfe_get_stats(struct net_device *dev)

          {

          board_info_t *db = (board_info_t *)dev->priv;

          DMFE_DBUG(0, dmfe_get_stats, 0);

          return db->stats;

          }

          /*

          Process the upper socket ioctl command

          */

          static int dmfe_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)

          {

          DMFE_DBUG(0, dmfe_do_ioctl(), 0);

          return 0;

          }

          /* Our watchdog timed out. Called by the networking layer */

          static void

          dmfe_timeout(struct net_device *dev)

          {

          board_info_t *db = (board_info_t *)dev->priv;

          DMFE_DBUG(0, dmfe_TX_timeout(), 0);

          printk(TX time-out -- dmfe_timeout().n);

          db->reset_tx_timeout++;

          db->stats.tx_errors++;

          #if FALSE

          printk(TX packet count = %dn, db->tx_pkt_cnt);

          printk(TX timeout = %dn, db->reset_tx_timeout);

          printk(22H=0x%02x 23H=0x%02xn,ior(db,0x22),ior(db,0x23));

          printk(faH=0x%02x fbH=0x%02xn,ior(db,0xfa),ior(db,0xfb));

          #endif

          dmfe_reset(dev);

          }

          static void dmfe_reset(struct net_device * dev)

          {

          board_info_t *db = (board_info_t *)dev->priv;

          u8 reg_save;

          int i;

          /* Save previous register address */

          reg_save = inb(db->io_addr);

          netif_stop_queue(dev);

          db->reset_counter++;

          dmfe_init_dm9000(dev);

          db->Speed =10;

          for(i=0; i1000; i++) /*wait link OK, waiting time=1 second */

          {

          if(phy_read(db,0x1) 0x4) /*Link OK*/

          {

          if(phy_read(db,0)0x2000) db->Speed =100;

          else db->Speed =10;

          break;

          }

          udelay(1000);

          }

          netif_wake_queue(dev);

          /* Restore previous register address */

          outb(reg_save, db->io_addr);

          }

          /*

          A periodic timer routine

          */

          static void dmfe_timer(unsigned long data)

          {

          struct net_device * dev = (struct net_device *)data;

          board_info_t *db = (board_info_t *)dev->priv;

          DMFE_DBUG(0, dmfe_timer(), 0);

          if (db->cont_rx_pkt_cnt>=CONT_RX_PKT_CNT)

          {

          db->cont_rx_pkt_cnt=0;

          iow(db, DM9KS_IMR, DM9KS_REGFF);

          }

          /* Set timer again */

          db->timer.expires = DMFE_TIMER_WUT;

          add_timer(db->timer);

          return;

          }

          #if !defined(CHECKSUM)

          pid控制相關(guān)文章:pid控制原理




          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉