原标题:ARM-Linux驱动--DM9000网卡驱动分析(四)

硬件平台:FL2440 (S3C2440)

内核版本:2.6.35

主机平台:Ubuntu 11.04

内核版本:2.6.39

交叉编译器: -linux-gcc 4.3.2

原创作品,转载请标明出处

本文接上文

- -- 分析(一)

ARM-Linux驱动--DM9000网卡驱动分析(二)

ARM-Linux驱动--DM9000网卡驱动分析(三)

1、接下来接着分析DM9000网卡驱动的数据接收函数

view plainprint?

static void

dm9000_rx(struct net_device *dev)

{

board_info_t *db = netdev_priv(dev);

struct dm9000_rxhdr rxhdr;

struct sk_buff *skb;

u8 rxbyte, *rdptr;

bool GoodPacket;

int RxLen;

do {

ior(db, DM9000_MRCMDX);

rxbyte = readb(db->io_data);

if (rxbyte & DM9000_PKT_ERR) {

dev_warn(db->dev, "status check fail: %d\n", rxbyte);

iow(db, DM9000_RCR, 0x00);

iow(db, DM9000_ISR, IMR_PAR);

return;

}

if (!(rxbyte & DM9000_PKT_RDY))

return;

GoodPacket = true;

writeb(DM9000_MRCMD, db->io_addr);

(db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));

RxLen = le16_to_cpu(rxhdr.RxLen);

if (netif_msg_rx_status(db))

dev_dbg(db->dev, "RX: status x, length x\n",

rxhdr.RxStatus, RxLen);

if (RxLen < 0x40) {

GoodPacket = false;

if (netif_msg_rx_err(db))

dev_dbg(db->dev, "RX: Bad Packet (runt)\n");

}

if (RxLen > DM9000_PKT_MAX) {

dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);

}

if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |

RSR_PLE | RSR_RWTO |

RSR_LCS | RSR_RF)) {

GoodPacket = false;

if (rxhdr.RxStatus & RSR_FOE) {

if (netif_msg_rx_err(db))

dev_dbg(db->dev, "fifo error\n");

dev->stats.rx_fifo_errors++;

}

if (rxhdr.RxStatus & RSR_CE) {

if (netif_msg_rx_err(db))

dev_dbg(db->dev, "crc error\n");

dev->stats.rx_crc_errors++;

}

if (rxhdr.RxStatus & RSR_RF) {

if (netif_msg_rx_err(db))

dev_dbg(db->dev, "length error\n");

dev->stats.rx_length_errors++;

}

}

if (GoodPacket &&

((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {

skb_reserve(skb, 2);

rdptr = (u8 *) skb_put(skb, RxLen - 4);

(db->inblk)(db->io_data, rdptr, RxLen);

dev->stats.rx_bytes += RxLen;

skb->protocol = eth_type_trans(skb, dev);

if (db->rx_csum) {

if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0)

skb->ip_summed = CHECKSUM_UNNECESSARY;

else

skb->ip_summed = CHECKSUM_NONE;

}

netif_rx(skb);

dev->stats.rx_packets++;

} else {

(db->dumpblk)(db->io_data, RxLen);

}

} while (rxbyte & DM9000_PKT_RDY);

}

2、下面是完整的DM9000驱动代码,可以完整的查看

view plainprint?

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "dm9000.h"

#include

#include

#include

#define DM9000_PHY 0x40

#define CARDNAME "dm9000"

#define DRV_VERSION "1.31"

static int watchdog = 5000;

module_param(watchdog, int, 0400);

MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");

enum dm9000_type {

TYPE_DM9000E,

TYPE_DM9000A,

TYPE_DM9000B

};

typedef struct board_info {

void __iomem *io_addr;

void __iomem *io_data;

u16 irq;

u16 tx_pkt_cnt;

u16 queue_pkt_len;

u16 queue_start_addr;

u16 queue_ip_summed;

u16 dbug_cnt;

u8 io_mode;

u8 phy_addr;

u8 imr_all;

unsigned int flags;

unsigned int in_suspend :1;

unsigned int wake_supported :1;

int debug_level;

enum dm9000_type type;

void (*inblk)(void __iomem *port, void *data, int length);

void (*outblk)(void __iomem *port, void *data, int length);

void (*dumpblk)(void __iomem *port, int length);

struct device *dev;

struct resource *addr_res;

struct resource *data_res;

struct resource *addr_req;

struct resource *data_req;

struct resource *irq_res;

int irq_wake;

struct mutex addr_lock;

struct delayed_work phy_poll;

struct net_device *ndev;

spinlock_t lock;

struct mii_if_info mii;

u32 msg_enable;

u32 wake_state;

int rx_csum;

int can_csum;

int ip_summed;

} board_info_t;

#define dm9000_dbg(db, lev, msg...) do { \

if ((lev) < CONFIG_DM9000_DEBUGLEVEL && \

(lev) < db->debug_level) { \

dev_dbg(db->dev, msg); \

} \

} while (0)

static inline board_info_t *to_dm9000_board(struct net_device *dev)

{

return netdev_priv(dev);

}

static void

dm9000_reset(board_info_t * db)

{

dev_dbg(db->dev, "resetting device\n");

writeb(DM9000_NCR, db->io_addr);

udelay(200);

writeb(NCR_RST, db->io_data);

udelay(200);

}

static u8

ior(board_info_t * db, int reg)

{

writeb(reg, db->io_addr);

return readb(db->io_data);

}

static void

iow(board_info_t * db, int reg, int value)

{

writeb(reg, db->io_addr);

writeb(value, db->io_data);

}

static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count)

{

writesb(reg, data, count);

}

static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count)

{

writesw(reg, data, (count+1) >> 1);

}

static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count)

{

writesl(reg, data, (count+3) >> 2);

}

static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count)

{

readsb(reg, data, count);

}

static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count)

{

readsw(reg, data, (count+1) >> 1);

}

static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count)

{

readsl(reg, data, (count+3) >> 2);

}

static void dm9000_dumpblk_8bit(void __iomem *reg, int count)

{

int i;

int tmp;

for (i = 0; i < count; i++)

tmp = readb(reg);

}

static void dm9000_dumpblk_16bit(void __iomem *reg, int count)

{

int i;

int tmp;

count = (count + 1) >> 1;

for (i = 0; i < count; i++)

tmp = readw(reg);

}

static void dm9000_dumpblk_32bit(void __iomem *reg, int count)

{

int i;

int tmp;

count = (count + 3) >> 2;

for (i = 0; i < count; i++)

tmp = readl(reg);

}

static void dm9000_set_io(struct board_info *db, int byte_width)

{

switch (byte_width) {

case 1:

db->dumpblk = dm9000_dumpblk_8bit;

db->outblk = dm9000_outblk_8bit;

db->inblk = dm9000_inblk_8bit;

break;

case 3:

dev_dbg(db->dev, ": 3 byte IO, falling back to 16bit\n");

case 2:

db->dumpblk = dm9000_dumpblk_16bit;

db->outblk = dm9000_outblk_16bit;

db->inblk = dm9000_inblk_16bit;

break;

case 4:

default:

db->dumpblk = dm9000_dumpblk_32bit;

db->outblk = dm9000_outblk_32bit;

db->inblk = dm9000_inblk_32bit;

break;

}

}

static void dm9000_schedule_poll(board_info_t *db)

{

if (db->type == TYPE_DM9000E)

schedule_delayed_work(&db->phy_poll, HZ * 2);

}

static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)

{

board_info_t *dm = to_dm9000_board(dev);

if (!netif_running(dev))

return -EINVAL;

return generic_mii_ioctl(&dm->mii, if_mii(req), cmd, NULL);

}

static unsigned int

dm9000_read_locked(board_info_t *db, int reg)

{

unsigned long flags;

unsigned int ret;

spin_lock_irqsave(&db->lock, flags);

ret = ior(db, reg);

spin_unlock_irqrestore(&db->lock, flags);

return ret;

}

static int dm9000_wait_eeprom(board_info_t *db)

{

unsigned int status;

int timeout = 8;

while (1) {

status = dm9000_read_locked(db, DM9000_EPCR);

if ((status & EPCR_ERRE) == 0)

break;

msleep(1);

if (timeout-- < 0) {

dev_dbg(db->dev, "timeout waiting EEPROM\n");

break;

}

}

return 0;

}

static void

dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)

{

unsigned long flags;

if (db->flags & DM9000_PLATF_NO_EEPROM) {

to[0] = 0xff;

to[1] = 0xff;

return;

}

mutex_lock(&db->addr_lock);

spin_lock_irqsave(&db->lock, flags);

iow(db, DM9000_EPAR, offset);

iow(db, DM9000_EPCR, EPCR_ERPRR);

spin_unlock_irqrestore(&db->lock, flags);

dm9000_wait_eeprom(db);

msleep(1);

spin_lock_irqsave(&db->lock, flags);

iow(db, DM9000_EPCR, 0x0);

to[0] = ior(db, DM9000_EPDRL);

to[1] = ior(db, DM9000_EPDRH);

spin_unlock_irqrestore(&db->lock, flags);

mutex_unlock(&db->addr_lock);

}

static void

dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)

{

unsigned long flags;

if (db->flags & DM9000_PLATF_NO_EEPROM)

return;

mutex_lock(&db->addr_lock);

spin_lock_irqsave(&db->lock, flags);

iow(db, DM9000_EPAR, offset);

iow(db, DM9000_EPDRH, data[1]);

iow(db, DM9000_EPDRL, data[0]);

iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);

spin_unlock_irqrestore(&db->lock, flags);

dm9000_wait_eeprom(db);

mdelay(1);

spin_lock_irqsave(&db->lock, flags);

iow(db, DM9000_EPCR, 0);

spin_unlock_irqrestore(&db->lock, flags);

mutex_unlock(&db->addr_lock);

}

static void dm9000_get_drvinfo(struct net_device *dev,

struct ethtool_drvinfo *info)

{

board_info_t *dm = to_dm9000_board(dev);

strcpy(info->driver, CARDNAME);

strcpy(info->version, DRV_VERSION);

strcpy(info->bus_info, to_platform_device(dm->dev)->name);

}

static u32 dm9000_get_msglevel(struct net_device *dev)

{

board_info_t *dm = to_dm9000_board(dev);

return dm->msg_enable;

}

static void dm9000_set_msglevel(struct net_device *dev, u32 value)

{

board_info_t *dm = to_dm9000_board(dev);

dm->msg_enable = value;

}

static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)

{

board_info_t *dm = to_dm9000_board(dev);

mii_ethtool_gset(&dm->mii, cmd);

return 0;

}

static int dm9000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)

{

board_info_t *dm = to_dm9000_board(dev);

return mii_ethtool_sset(&dm->mii, cmd);

}

static int dm9000_nway_reset(struct net_device *dev)

{

board_info_t *dm = to_dm9000_board(dev);

return mii_nway_restart(&dm->mii);

}

static uint32_t dm9000_get_rx_csum(struct net_device *dev)

{

board_info_t *dm = to_dm9000_board(dev);

return dm->rx_csum;

}

static int dm9000_set_rx_csum_unlocked(struct net_device *dev, uint32_t data)

{

board_info_t *dm = to_dm9000_board(dev);

if (dm->can_csum) {

dm->rx_csum = data;

iow(dm, DM9000_RCSR, dm->rx_csum ? RCSR_CSUM : 0);

return 0;

}

return -EOPNOTSUPP;

}

static int dm9000_set_rx_csum(struct net_device *dev, uint32_t data)

{

board_info_t *dm = to_dm9000_board(dev);

unsigned long flags;

int ret;

spin_lock_irqsave(&dm->lock, flags);

ret = dm9000_set_rx_csum_unlocked(dev, data);

spin_unlock_irqrestore(&dm->lock, flags);

return ret;

}

static int dm9000_set_tx_csum(struct net_device *dev, uint32_t data)

{

board_info_t *dm = to_dm9000_board(dev);

int ret = -EOPNOTSUPP;

if (dm->can_csum)

ret = ethtool_op_set_tx_csum(dev, data);

return ret;

}

static u32 dm9000_get_link(struct net_device *dev)

{

board_info_t *dm = to_dm9000_board(dev);

u32 ret;

if (dm->flags & DM9000_PLATF_EXT_PHY)

ret = mii_link_ok(&dm->mii);

else

ret = dm9000_read_locked(dm, DM9000_NSR) & NSR_LINKST ? 1 : 0;

return ret;

}

#define DM_EEPROM_MAGIC (0x444D394B)

static int dm9000_get_eeprom_len(struct net_device *dev)

{

return 128;

}

static int dm9000_get_eeprom(struct net_device *dev,

struct ethtool_eeprom *ee, u8 *data)

{

board_info_t *dm = to_dm9000_board(dev);

int offset = ee->offset;

int len = ee->len;

int i;

if ((len & 1) != 0 || (offset & 1) != 0)

return -EINVAL;

if (dm->flags & DM9000_PLATF_NO_EEPROM)

return -ENOENT;

ee->magic = DM_EEPROM_MAGIC;

for (i = 0; i < len; i += 2)

dm9000_read_eeprom(dm, (offset + i) / 2, data + i);

return 0;

}

static int dm9000_set_eeprom(struct net_device *dev,

struct ethtool_eeprom *ee, u8 *data)

{

board_info_t *dm = to_dm9000_board(dev);

int offset = ee->offset;

int len = ee->len;

int i;

if ((len & 1) != 0 || (offset & 1) != 0)

return -EINVAL;

if (dm->flags & DM9000_PLATF_NO_EEPROM)

return -ENOENT;

if (ee->magic != DM_EEPROM_MAGIC)

return -EINVAL;

for (i = 0; i < len; i += 2)

dm9000_write_eeprom(dm, (offset + i) / 2, data + i);

return 0;

}

static void dm9000_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)

{

board_info_t *dm = to_dm9000_board(dev);

memset(w, 0, sizeof(struct ethtool_wolinfo));

w->supported = dm->wake_supported ? WAKE_MAGIC : 0;

w->wolopts = dm->wake_state;

}

static int dm9000_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)

{

board_info_t *dm = to_dm9000_board(dev);

unsigned long flags;

u32 opts = w->wolopts;

u32 wcr = 0;

if (!dm->wake_supported)

return -EOPNOTSUPP;

if (opts & ~WAKE_MAGIC)

return -EINVAL;

if (opts & WAKE_MAGIC)

wcr |= WCR_MAGICEN;

mutex_lock(&dm->addr_lock);

spin_lock_irqsave(&dm->lock, flags);

iow(dm, DM9000_WCR, wcr);

spin_unlock_irqrestore(&dm->lock, flags);

mutex_unlock(&dm->addr_lock);

if (dm->wake_state != opts) {

if (!dm->wake_state)

set_irq_wake(dm->irq_wake, 1);

else if (dm->wake_state & !opts)

set_irq_wake(dm->irq_wake, 0);

}

dm->wake_state = opts;

return 0;

}

static const struct ethtool_ops dm9000_ethtool_ops = {

.get_drvinfo = dm9000_get_drvinfo,

.get_settings = dm9000_get_settings,

.set_settings = dm9000_set_settings,

.get_msglevel = dm9000_get_msglevel,

.set_msglevel = dm9000_set_msglevel,

.nway_reset = dm9000_nway_reset,

.get_link = dm9000_get_link,

.get_wol = dm9000_get_wol,

.set_wol = dm9000_set_wol,

.get_eeprom_len = dm9000_get_eeprom_len,

.get_eeprom = dm9000_get_eeprom,

.set_eeprom = dm9000_set_eeprom,

.get_rx_csum = dm9000_get_rx_csum,

.set_rx_csum = dm9000_set_rx_csum,

.get_tx_csum = ethtool_op_get_tx_csum,

.set_tx_csum = dm9000_set_tx_csum,

};

static void dm9000_show_carrier(board_info_t *db,

unsigned carrier, unsigned nsr)

{

struct net_device *ndev = db->ndev;

unsigned ncr = dm9000_read_locked(db, DM9000_NCR);

if (carrier)

dev_info(db->dev, "%s: link up, %dMbps, %s-duplex, no LPA\n",

ndev->name, (nsr & NSR_SPEED) ? 10 : 100,

(ncr & NCR_FDX) ? "full" : "half");

else

dev_info(db->dev, "%s: link down\n", ndev->name);

}

static void

dm9000_poll_work(struct work_struct *w)

{

struct delayed_work *dw = to_delayed_work(w);

board_info_t *db = container_of(dw, board_info_t, phy_poll);

struct net_device *ndev = db->ndev;

if (db->flags & DM9000_PLATF_SIMPLE_PHY &&

!(db->flags & DM9000_PLATF_EXT_PHY)) {

unsigned nsr = dm9000_read_locked(db, DM9000_NSR);

unsigned old_carrier = netif_carrier_ok(ndev) ? 1 : 0;

unsigned new_carrier;

new_carrier = (nsr & NSR_LINKST) ? 1 : 0;

if (old_carrier != new_carrier) {

if (netif_msg_link(db))

dm9000_show_carrier(db, new_carrier, nsr);

if (!new_carrier)

netif_carrier_off(ndev);

else

netif_carrier_on(ndev);

}

} else

mii_check_media(&db->mii, netif_msg_link(db), 0);

if (netif_running(ndev))

dm9000_schedule_poll(db);

}

static void

dm9000_release_board(struct platform_device *pdev, struct board_info *db)

{

iounmap(db->io_addr);

iounmap(db->io_data);

release_resource(db->data_req);

kfree(db->data_req);

release_resource(db->addr_req);

kfree(db->addr_req);

}

static unsigned char dm9000_type_to_char(enum dm9000_type type)

{

switch (type) {

case TYPE_DM9000E: return 'e';

case TYPE_DM9000A: return 'a';

case TYPE_DM9000B: return 'b';

}

return '?';

}

static void

dm9000_hash_table_unlocked(struct net_device *dev)

{

board_info_t *db = netdev_priv(dev);

struct netdev_hw_addr *ha;

int i, oft;

u32 hash_val;

u16 hash_table[4];

u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;

dm9000_dbg(db, 1, "entering %s\n", __func__);

for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)

iow(db, oft, dev->dev_addr[i]);

for (i = 0; i < 4; i++)

hash_table[i] = 0x0;

hash_table[3] = 0x8000;

if (dev->flags & IFF_PROMISC)

rcr |= RCR_PRMSC;

if (dev->flags & IFF_ALLMULTI)

rcr |= RCR_ALL;

netdev_for_each_mc_addr(ha, dev) {

hash_val = ether_crc_le(6, ha->addr) & 0x3f;

hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);

}

for (i = 0, oft = DM9000_MAR; i < 4; i++) {

iow(db, oft++, hash_table[i]);

iow(db, oft++, hash_table[i] >> 8);

}

iow(db, DM9000_RCR, rcr);

}

static void

dm9000_hash_table(struct net_device *dev)

{

board_info_t *db = netdev_priv(dev);

unsigned long flags;

spin_lock_irqsave(&db->lock, flags);

dm9000_hash_table_unlocked(dev);

spin_unlock_irqrestore(&db->lock, flags);

}

static void

dm9000_init_dm9000(struct net_device *dev)

{

board_info_t *db = netdev_priv(dev);

unsigned int imr;

unsigned int ncr;

dm9000_dbg(db, 1, "entering %s\n", __func__);

db->io_mode = ior(db, DM9000_ISR) >> 6;

dm9000_set_rx_csum_unlocked(dev, db->rx_csum);

iow(db, DM9000_GPR, 0);

iow(db, DM9000_GPCR, GPCR_GEP_CNTL);

iow(db, DM9000_GPR, 0);

ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;

if (db->wake_supported)

ncr |= NCR_WAKEEN;

iow(db, DM9000_NCR, ncr);

iow(db, DM9000_TCR, 0);

iow(db, DM9000_BPTR, 0x3f);

iow(db, DM9000_FCR, 0xff);

责任编辑:

arm平台linux的ethtool配置,ARM-Linux驱动--DM9000网卡驱动分析(四)相关推荐

  1. ARM平台下无线网卡的配置

    ARM平台下无线网卡的配置 前言 看了下上次博客时间,大概是毕业后到目前两个多月了没有更新博客,突然发现自己正在变得越来越懒,这可不是一个好的征兆.除过找工作一个礼拜的时间,算起来已经工作了快2个月了 ...

  2. linux 内核 网卡驱动 移植,Linux内核移植步骤_添加DM9000网卡驱动(设备树).docx

    Linux内核移植步骤_添加DM9000网卡驱动(设备树) Linux内核移植步骤2015年05月13日星期三上午 11:05往设备树中添加网卡驱动:1.选平台,指定交叉编译工具链:(1).在Make ...

  3. linux 内核 网卡驱动 移植,linux内核移植步骤添加dm9000网卡驱动(设备树).docx

    linux内核移植步骤添加dm9000网卡驱动(设备树).docx LINUX内核移植步骤2015年05月13日星期三上午1105往设备树中添加网卡驱动1.选平台,指定交叉编译工具链1.在MAKEFI ...

  4. 以太网卡驱动程序移植linux,基于S3C2440的DM9000网卡驱动的移植

    摘  要: 主要研究了基于Linux内核的网卡驱动的移植.Linux网络设备驱动程序的体系结构可以分为4层,首先分析了各层的具体功能实现,并在此基础上充分利用S3C2440开发板完成DM9000网卡驱 ...

  5. VMware linux 虚拟机(ubuntu18.04) 安装TL-WDN5200H 2.0网卡驱动 完美使用(适用于vmware无法桥接网络使用此方法)

    VMware linux 虚拟机(ubuntu18.04) 安装TL-WDN5200H 2.0网卡驱动 完美使用(适用于vmware无法桥接网络使用此方法) # 以下操作均已root用户操作 # 安装 ...

  6. zynq7000系列移植—JRE移植到嵌入式ARM平台(java运行在嵌入式linux)

    转载:https://blog.csdn.net/weixin_39827918/article/details/78806642 前言 因公司项目需求,需要在zynq 7000平台下运行 java ...

  7. linux内核的配置过程,linux内核的配置机制及其编译过程

    linux内核的配置机制及其编译过程. 一.配置系统的基本结构 Linux内核的配置系统由三个部分组成,分别是: 1.Makefile:分布在 Linux 内核源代码根目录及各层目录中,定义 Linu ...

  8. linux 2440网卡驱动,Linux-2.6.30平台下移植DM9000网卡驱动到TQ2440

    平台:虚拟机Ubuntu 12.04  内核:linux-2.6.30 开发板:TQ2440 包括编译内核.制作文件系统,到目前可以在虚拟机上可以通过交叉网线可以和开发板互通,用了弄了差不多快两天时间 ...

  9. linux下怎么配置显卡,Linux系统如何配置双显卡?

    Linux系统如何配置双显卡?相信很多Linux用户都苦于Linux系统没有Optimus支持吧?这就意味着Linux系统不能进行显卡智能切换,只能一直使用核心显卡或独立显卡,这样对操作是非常不友好的 ...

最新文章

  1. 嵌入式开发板加载U盘,U盘测试
  2. C#下把txt文件数据读进sql server中存储所遇到的乱码问题
  3. [日常工作]WorkStation 使用端口转发的方式使用宿主机IP地址提供服务
  4. java jdk 1.8 配置_jdk1.8安装及java环境变量配置(内含一键配置工具)
  5. Linux网络编程——黑马程序员笔记
  6. linux添加三权,基于SELinux的三权分离技术的研究
  7. Loadrunner 接口测试的两种方法
  8. 年薪30W的软件测试“老司机”工作经验
  9. Python中装入包pandas和matplotlib
  10. 夯实基础开新局--全国乡镇党委换届工作进展顺利
  11. 掰碎了讲换行符和回车符
  12. STL容器-queue队列
  13. python源码中的pass
  14. matlab中的uigetfile函数和setappdata函数
  15. 双目三维重建:双目摄像头实现双目测距(Python)
  16. 微软为什么总招人黑?
  17. 七阶拉丁方阵_关于拉丁方阵教学的思考
  18. 非常全面的前端协作规范
  19. G1垃圾回收日志分析
  20. 膨胀卷积(空洞卷积)

热门文章

  1. rpc协议微服务器,go微服务之rpc:hprose服务端
  2. 一款带ai基因的向导般生成ppt的神奇网站
  3. 机器学习:何为PR曲线与ROC曲线
  4. STM32CubeMX——循迹传感器TCRT5000的使用
  5. 微信小程序——服务通知,发送订阅消息
  6. 树莓派交叉编译(PS交叉编译链下载安装、配置永久环境变量、带WiringPi库交叉编译、软链接)
  7. 利用循环解决矩阵nan值(错误解决)
  8. mysql5.7 pxc方案_mysql5.7 pxc
  9. 2款2.4G蓝牙PCB天线尺寸(来自TI)
  10. 电子设计教程50:16*16LED点阵屏驱动-LED点阵屏工作原理