⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtl_rtl8139_drv.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
  	struct pci_dev *dev = rtl8139dev;  	int boguscnt = rt_rtl8139_max_interrupt_work;   	void *ioaddr = rtl_8139_tp.mmio_addr;  	int status = 0, link_changed = 0; /* avoid bogus "uninit" warning */  	rt_rtl8139_inside_the_interrupt_handler = 1;   	rt_rtl8139_interrupted++;   	do {                status = RTL_R16 (IntrStatus);                 /* h/w no longer present (hotplug?) or major error, bail */                if (status == 0xFFFF)                        break;                /* Acknowledge all of the current interrupt sources ASAP, but                   an first get an additional status bit from CSCR. */                if (status & RxUnderrun)                        link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit;                RTL_W16_F (IntrStatus, (status & RxFIFOOver) ? (status | RxOverflow) : status);                 if ((status &                     (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |                      RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0) {                        break;			}                 if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver))  {   /* Rx interrupt */                        rt_rtl8139_rx_interrupt (dev);  		}                 if (status & (TxOK | TxErr)) {                        rt_rtl8139_tx_interrupt (dev);                   }                 boguscnt--;        } while (boguscnt > 0);          if (boguscnt <= 0) {                rtl_printf ( "%s: Too much work at interrupt, "                        "IntrStatus=0x%4.4x.\n", dev->name,                        status);                 /* Clear all interrupt sources. */                RTL_W16 (IntrStatus, 0xffff);        }  	if(!rt_rtl8139_trying_to_close){  		rtl_hard_enable_irq(rtl_8139_tp.pci_dev->irq);	}      	rt_rtl8139_interrupted--;     	return (rt_rtl8139_inside_the_interrupt_handler = 0);}/* Syncronize the MII management interface by shifting 32 one bits out. */                                    static void rt_rtl8139_mdio_sync (void *mdio_addr){        int i;          for (i = 32; i >= 0; i--) {                writeb (MDIO_WRITE1, mdio_addr);                rt_rtl8139_mdio_delay (mdio_addr);                writeb (MDIO_WRITE1 | MDIO_CLK, mdio_addr);                rt_rtl8139_mdio_delay (mdio_addr);        } }static int rt_rtl8139_mdio_read (struct pci_dev *dev, int phy_id, int location){        void *mdio_addr = rtl_8139_tp.mmio_addr + Config4;        int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;        int retval = 0;        int i;          if (phy_id > 31) {      /* Really a 8139.  Use internal registers. */                return location < 8 && mii_2_8139_map[location] ?                    readw (rtl_8139_tp.mmio_addr + mii_2_8139_map[location]) : 0;        }        rt_rtl8139_mdio_sync (mdio_addr);        /* Shift the read command bits out. */        for (i = 15; i >= 0; i--) {                int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;                 writeb (MDIO_DIR | dataval, mdio_addr);                rt_rtl8139_mdio_delay (mdio_addr);                writeb (MDIO_DIR | dataval | MDIO_CLK, mdio_addr);                rt_rtl8139_mdio_delay (mdio_addr);        }         /* Read the two transition, 16 data, and wire-idle bits. */        for (i = 19; i > 0; i--) {                writeb (0, mdio_addr);                rt_rtl8139_mdio_delay (mdio_addr);                retval = (retval << 1) | ((readb (mdio_addr) & MDIO_DATA_IN) ? 1 : 0);                writeb (MDIO_CLK, mdio_addr);                rt_rtl8139_mdio_delay (mdio_addr);        }         return (retval >> 1) & 0xffff;}static void rt_rtl8139_mdio_write (struct pci_dev *dev, int phy_id, int location,                        int value){        void *mdio_addr = rtl_8139_tp.mmio_addr + Config4;        int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;        int i;          if (phy_id > 31) {      /* Really a 8139.  Use internal registers. */                void *ioaddr = rtl_8139_tp.mmio_addr;                if (location == 0) {                        RTL_W8_F (Cfg9346, Cfg9346_Unlock);                        //////////////////////////////////////////////////////////////                        switch(rtl_8139_tp.AutoNegoAbility){                        case 1: RTL_W16 (NWayAdvert, AutoNegoAbility10half); break;                        case 2: RTL_W16 (NWayAdvert, AutoNegoAbility10full); break;                        case 4: RTL_W16 (NWayAdvert, AutoNegoAbility100half); break;                        case 8: RTL_W16 (NWayAdvert, AutoNegoAbility100full); break;                        default: break;                        }                        RTL_W16_F (BasicModeCtrl, AutoNegotiationEnable|AutoNegotiationRestart);                        //////////////////////////////////////////////////////////////                        RTL_W8_F (Cfg9346, Cfg9346_Lock);                } else if (location < 8 && mii_2_8139_map[location])                        RTL_W16_F (mii_2_8139_map[location], value);                 return;        }        rt_rtl8139_mdio_sync (mdio_addr);        /* Shift the command bits out. */        for (i = 31; i >= 0; i--) {                int dataval =                    (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;                writeb (dataval, mdio_addr);                rt_rtl8139_mdio_delay (mdio_addr);                writeb (dataval | MDIO_CLK, mdio_addr);                rt_rtl8139_mdio_delay (mdio_addr);        }        /* Clear out extra bits. */        for (i = 2; i > 0; i--) {                writeb (0, mdio_addr);                rt_rtl8139_mdio_delay (mdio_addr);                writeb (MDIO_CLK, mdio_addr);                rt_rtl8139_mdio_delay (mdio_addr);        }        return;}/* Serial EEPROM section. */ /*  EEPROM_Ctrl bits. */#define EE_SHIFT_CLK    0x04    /* EEPROM shift clock. */#define EE_CS                   0x08    /* EEPROM chip select. */#define EE_DATA_WRITE   0x02    /* EEPROM chip data in. */#define EE_WRITE_0              0x00#define EE_WRITE_1              0x02#define EE_DATA_READ    0x01    /* EEPROM chip data out. */#define EE_ENB                  (0x80 | EE_CS) /* Delay between EEPROM clock transitions.   No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. */ #define rt_rtl8139_eeprom_delay()  readl(ee_addr) /* The EEPROM commands include the alway-set leading bit. */#define EE_WRITE_CMD    (5)#define EE_READ_CMD             (6)#define EE_ERASE_CMD    (7)static int __devinit rt_rtl8139_read_eeprom (void *ioaddr, int location, int addr_len){        int i;        unsigned retval = 0;        void *ee_addr = ioaddr + Cfg9346;        int read_cmd = location | (EE_READ_CMD << addr_len);          writeb (EE_ENB & ~EE_CS, ee_addr);        writeb (EE_ENB, ee_addr);        rt_rtl8139_eeprom_delay ();         /* Shift the read command bits out. */        for (i = 4 + addr_len; i >= 0; i--) {                int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;                writeb (EE_ENB | dataval, ee_addr);                rt_rtl8139_eeprom_delay ();                writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);                rt_rtl8139_eeprom_delay ();        }        writeb (EE_ENB, ee_addr);        rt_rtl8139_eeprom_delay ();         for (i = 16; i > 0; i--) {                writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);                rt_rtl8139_eeprom_delay ();                retval =                    (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 :                                     0);                writeb (EE_ENB, ee_addr);                rt_rtl8139_eeprom_delay ();        }         /* Terminate the EEPROM access. */        writeb (~EE_CS, ee_addr);        rt_rtl8139_eeprom_delay ();         return retval;}/* Set or clear the multicast filter for this adaptor.   This routine is not state sensitive and need not be SMP locked. */ static unsigned const ethernet_polynomial = 0x04c11db7U;static inline u32 rt_rtl8139_ether_crc (int length, unsigned char *data){        int crc = -1;          while (--length >= 0) {                unsigned char current_octet = *data++;                int bit;                for (bit = 0; bit < 8; bit++, current_octet >>= 1)                        crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ?                             ethernet_polynomial : 0);        }         return crc;} static void rt_rtl8139_set_rx_mode (struct pci_dev *dev){        void *ioaddr = rtl_8139_tp.mmio_addr;        int rx_mode;        u32 tmp;         /* Note: do not reorder, GCC is clever about common statements. */	rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptAllPhys;         /* We can safely update without stopping the chip. */        tmp = rtl8139_rx_config | rx_mode |                (RTL_R32 (RxConfig) & rtl_chip_info[rtl_8139_tp.chipset].RxConfigMask);        RTL_W32_F (RxConfig, tmp);         rtl_printf ("%s:   rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n",                        dev->name, rtl_8139_tp.drv_flags, RTL_R32 (RxConfig)); }/* Start the hardware at open or resume. */static void rt_rtl8139_hw_start (struct pci_dev *dev){        void *ioaddr = rtl_8139_tp.mmio_addr;        u32 i;        u8 tmp;          /* Soft reset the chip. */        RTL_W8 (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) | CmdReset);        rtl_delay (100);         /* Check that the chip has finished the reset. */        for (i = 1000; i > 0; i--)                if ((RTL_R8 (ChipCmd) & CmdReset) == 0)                        break;        /* unlock Config[01234] and BMCR register writes */        RTL_W8_F (Cfg9346, Cfg9346_Unlock);        /* Restore our idea of the MAC address. */        RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (rtl_8139_tp.dev_addr + 0)));        RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (rtl_8139_tp.dev_addr + 4)));         /* Must enable Tx/Rx before setting transfer thresholds! */        RTL_W8_F (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) |                           CmdRxEnb | CmdTxEnb);         i = rtl8139_rx_config |            (RTL_R32 (RxConfig) & rtl_chip_info[rtl_8139_tp.chipset].RxConfigMask);        RTL_W32_F (RxConfig, i);         /* Check this value: the documentation for IFG contradicts ifself. */        RTL_W32 (TxConfig, (TX_DMA_BURST << TxDMAShift));         rtl_8139_tp.cur_rx = 0;         /* This is check_duplex() */        if (rtl_8139_tp.phys[0] >= 0  ||  (rtl_8139_tp.drv_flags & HAS_MII_XCVR)) {                u16 mii_reg5 = rt_rtl8139_mdio_read(dev, rtl_8139_tp.phys[0], 5);                if (mii_reg5 == 0xffff)                        ;                                       /* Not there */                else if ((mii_reg5 & 0x0100) == 0x0100                                 || (mii_reg5 & 0x00C0) == 0x0040)                        rtl_8139_tp.full_duplex = 1;                rtl_printf("%s: Setting %s%s-duplex based on"                           " auto-negotiated partner ability %4.4x.\n", dev->name,                           mii_reg5 == 0 ? "" :                           (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",                           rtl_8139_tp.full_duplex ? "full" : "half", mii_reg5);        }        if (rtl_8139_tp.chipset >= CH_8139A) {                tmp = RTL_R8 (Config1) & Config1Clear;                tmp |= Cfg1_Driver_Load;                tmp |= (rtl_8139_tp.chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */                RTL_W8_F (Config1, tmp);        } else {                u8 foo = RTL_R8 (Config1) & Config1Clear;                RTL_W8 (Config1, rtl_8139_tp.full_duplex ? (foo|0x60) : (foo|0x20));        }         if (rtl_8139_tp.chipset >= CH_8139B) {                tmp = RTL_R8 (Config4) & ~(1<<2);                /* chip will clear Rx FIFO overflow automatically */                tmp |= (1<<7);                RTL_W8 (Config4, tmp);                 /* disable magic packet scanning, which is enabled                 * when PM is enabled above (Config1) */                RTL_W8 (Config3, RTL_R8 (Config3) & ~(1<<5));        }        /* Lock Config[01234] and BMCR register writes */        RTL_W8_F (Cfg9346, Cfg9346_Lock);        rtl_delay (10);         /* init Rx ring buffer DMA address */        RTL_W32_F (RxBuf, rtl_8139_tp.rx_ring_dma);         /* init Tx buffer DMA addresses */        for (i = 0; i < NUM_TX_DESC; i++)                RTL_W32_F (TxAddr0 + (i * 4), rtl_8139_tp.tx_bufs_dma + (rtl_8139_tp.tx_buf[i] - rtl_8139_tp.tx_bufs));         RTL_W32_F (RxMissed, 0);         rt_rtl8139_set_rx_mode (dev);            /* no early-rx interrupts */        RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear);         /* make sure RxTx has started */        RTL_W8_F (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear) |                           CmdRxEnb | CmdTxEnb);         /* Enable all known interrupts by setting the interrupt mask. */        RTL_W16_F (IntrMask, rtl8139_intr_mask);  }/* Initialize the Rx and Tx rings, along with various 'dev' bits. */static void rt_rtl8139_init_ring (struct pci_dev *dev){        int i;          rtl_8139_tp.cur_rx = 0;        rtl_8139_tp.cur_tx = 0;        rtl_8139_tp.dirty_tx = 0;         for (i = 0; i < NUM_TX_DESC; i++) {                rtl_8139_tp.tx_info[i].skb = NULL;                rtl_8139_tp.tx_info[i].mapping = 0;                rtl_8139_tp.tx_buf[i] = &rtl_8139_tp.tx_bufs[i * TX_BUF_SIZE];        } }static int dev_rtl8139_open (struct pci_dev *dev){        int retval;        long ioaddr;	ioaddr = (long)rtl_8139_tp.mmio_addr;          retval = rtl_request_irq (dev->irq, &rt_rtl8139_interrupt);        if (retval) {                rtl_printf ("rtl_request_irq : EXIT, returning %d\n", retval);                return retval;        } else rtl_8139_tp.must_free_irq = 1;        rtl_8139_tp.tx_bufs = pci_alloc_consistent(rtl_8139_tp.pci_dev, TX_BUF_TOT_LEN,                                           &rtl_8139_tp.tx_bufs_dma);        rtl_8139_tp.rx_ring = pci_alloc_consistent(rtl_8139_tp.pci_dev, RX_BUF_TOT_LEN,                                           &rtl_8139_tp.rx_ring_dma);        if (rtl_8139_tp.tx_bufs == NULL || rtl_8139_tp.rx_ring == NULL) {                rtl_free_irq(dev->irq);                 if (rtl_8139_tp.tx_bufs)                        pci_free_consistent(rtl_8139_tp.pci_dev, TX_BUF_TOT_LEN,                                            rtl_8139_tp.tx_bufs, rtl_8139_tp.tx_bufs_dma);                if (rtl_8139_tp.rx_ring)                        pci_free_consistent(rtl_8139_tp.pci_dev, RX_BUF_TOT_LEN,                                            rtl_8139_tp.rx_ring, rtl_8139_tp.rx_ring_dma);                 rtl_printf ("EXIT, returning -ENOMEM\n");                return -ENOMEM;         }        rtl_8139_tp.full_duplex = rtl_8139_tp.duplex_lock;        rtl_8139_tp.tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;        rtl_8139_tp.twistie = 1;         rt_rtl8139_init_ring (dev);        rt_rtl8139_hw_start (dev);              rtl_printf ("%s: dev_8139_open() ioaddr %#lx IRQ %d"                        " GP Pins %2.2x %s-duplex.\n",                        dev->name, pci_resource_start (rtl_8139_tp.pci_dev, 1),                        dev->irq, RTL_R8 (MediaStatus),                        rtl_8139_tp.full_duplex ? "full" : "half");         if (rtl_8139_tp.thr_pid < 0)                rtl_printf ( "%s: unable to start kernel thread\n",                        dev->name);         return 0;}/***************************************************************************************/int start_up_rtl8139_device(struct pci_dev *dev){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -