static struct s3c_ts_mach_info s3c_ts_platform __initdata = {.delay             = 10000,       /*转化延迟*/.presc          = 49,          /*转化时钟分频*/.oversampling_shift   = 2,       /*转化次数 1<<2 == 4次*/.resol_bit       = 12,          /*转化进度*/.s3c_adc_con        = ADC_TYPE_2,
};/*s3c_ts所列的资源*/
static struct resource s3c_ts_resource[] = {[0] = {.start = SAMSUNG_PA_ADC,.end   = SAMSUNG_PA_ADC + SZ_256 - 1,.flags = IORESOURCE_MEM,},[1] = {.start = IRQ_PENDN,.end   = IRQ_PENDN,.flags = IORESOURCE_IRQ,},[2] = {.start = IRQ_ADC,.end   = IRQ_ADC,.flags = IORESOURCE_IRQ,}
};/*platform设备定义*/
struct platform_device s3c_device_ts = {.name        = "s3c-ts",.id       = -1,.num_resources    = ARRAY_SIZE(s3c_ts_resource),.resource    = s3c_ts_resource,
};void __init s3c_ts_set_platdata(struct s3c_ts_mach_info *pd)
{struct s3c_ts_mach_info *npd;if (!pd) {printk(KERN_ERR "%s: no platform data\n", __func__);return;}npd = kmemdup(pd, sizeof(struct s3c_ts_mach_info), GFP_KERNEL);if (!npd)printk(KERN_ERR "%s: no memory for platform data\n", __func__);s3c_device_ts.dev.platform_data = npd;
}/* linux/drivers/input/touchscreen/s3c-ts.c** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA** Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>* iPAQ H1940 touchscreen support** ChangeLog** 2004-09-05: Herbert Potzl <herbert@13thfloor.at>* - added clock (de-)allocation code** 2005-03-06: Arnaud Patard <arnaud.patard@rtp-net.org>*      - h1940_ -> s3c24xx (this driver is now also used on the n30*        machines :P)*      - Debug messages are now enabled with the config option*        TOUCHSCREEN_S3C_DEBUG*      - Changed the way the value are read*      - Input subsystem should now work*      - Use ioremap and readl/writel** 2005-03-23: Arnaud Patard <arnaud.patard@rtp-net.org>*      - Make use of some undocumented features of the touchscreen*        controller** 2006-09-05: Ryu Euiyoul <ryu.real@gmail.com>*      - added power management suspend and resume code**/#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>#include <asm/io.h>
#include <asm/irq.h>
#include <mach/hardware.h>#include <plat/regs-adc.h>
#include <mach/ts.h>
#include <mach/irqs.h>#define CONFIG_TOUCHSCREEN_S3C_DEBUG
#undef CONFIG_TOUCHSCREEN_S3C_DEBUG/* For ts->dev.id.version */
#define S3C_TSVERSION   0x0101/*x等于0, 为等待按下中断, x等于1, 为等待松开中断**/
#define WAIT4INT(x)  (((x)<<8) | \S3C_ADCTSC_YM_SEN | S3C_ADCTSC_YP_SEN | S3C_ADCTSC_XP_SEN | \S3C_ADCTSC_XY_PST(3))/*自动测量x,y坐标*/
#define AUTOPST      (S3C_ADCTSC_YM_SEN | S3C_ADCTSC_YP_SEN | S3C_ADCTSC_XP_SEN | \S3C_ADCTSC_AUTO_PST | S3C_ADCTSC_XY_PST(0))#define DEBUG_LVL    KERN_DEBUG/* Touchscreen default configuration */
struct s3c_ts_mach_info s3c_ts_default_cfg __initdata = {.delay =         5000,//10000,.presc =      49,.oversampling_shift =   4,//2,.resol_bit =         10
};/** Definitions & global arrays.*/
static char *s3c_ts_name = "S3C TouchScreen";
static void __iomem         *ts_base;
static struct resource      *ts_mem;
static struct resource      *ts_irq;
static struct clk       *ts_clock;
static struct s3c_ts_info   *ts;static int downflag=0;#ifdef  CONFIG_FORLINX6410_ADCDEFINE_SEMAPHORE(ADC_LOCK);
/* Indicate who is using the ADC controller */
#define LOCK_FREE       0
#define LOCK_TS         1
#define LOCK_ADC        2
static int adc_lock_id = LOCK_FREE;#define ADC_free()      (adc_lock_id == LOCK_FREE)
#define ADC_locked4TS() (adc_lock_id == LOCK_TS)static inline int s3c_ts_adc_lock(int id) {int ret;ret = down_trylock(&ADC_LOCK);if (!ret) {adc_lock_id = id;}return ret;
}static inline void s3c_ts_adc_unlock(void) {adc_lock_id = 0;up(&ADC_LOCK);
}static unsigned int _adccon, _adctsc, _adcdly;int X6410_adc_acquire_io(void) {int ret;ret = s3c_ts_adc_lock(LOCK_ADC);if (!ret) {_adccon = readl(ts_base + S3C_ADCCON);_adctsc = readl(ts_base + S3C_ADCTSC);_adcdly = readl(ts_base + S3C_ADCDLY);printk("forlinx debug****X6410_adc_acquire_io();.\n");}return ret;
}
EXPORT_SYMBOL(X6410_adc_acquire_io);void X6410_adc_release_io(void) {writel(_adccon, ts_base + S3C_ADCCON);writel(_adctsc, ts_base + S3C_ADCTSC);writel(_adcdly, ts_base + S3C_ADCDLY);writel(WAIT4INT(0), ts_base + S3C_ADCTSC);s3c_ts_adc_unlock();printk("forlinx debug*****X6410_adc_release_io();.\n");}EXPORT_SYMBOL(X6410_adc_release_io);#endif/* 当定时器到了后,就会调用touch_timer_fire函数**  * */static void touch_timer_fire(unsigned long data)
{unsigned long data0;unsigned long data1;int pendown;#ifdef CONFIG_FORLINX6410_ADCif (!ADC_locked4TS()) {/* Note: pen UP interrupt detected and handled, the lock is released,* so do nothing in the timer which started by ADC ISR. */return;}
#endif/*读取ADCDATA0 和 ADCDAT1寄存器*/data0 = readl(ts_base+S3C_ADCDAT0);data1 = readl(ts_base+S3C_ADCDAT1);/*判断是否按下*/pendown = (!(data0 & S3C_ADCDAT0_UPDOWN)) && (!(data1 & S3C_ADCDAT1_UPDOWN));if (pendown) {//down//printk("pendown=1.\n");if (ts->count) {#ifdef CONFIG_TOUCHSCREEN_S3C_DEBUG{struct timeval tv;do_gettimeofday(&tv);printk(KERN_INFO "T: %06d, X: %03ld, Y: %03ld\n", (int)tv.tv_usec, ts->xp, ts->yp);}
#endif/*上报事件*/if(downflag==0){input_report_abs(ts->dev, ABS_X, ts->xp);input_report_abs(ts->dev, ABS_Y, ts->yp);input_report_key(ts->dev, BTN_TOUCH, 1);input_report_abs(ts->dev, ABS_PRESSURE, 1);input_sync(ts->dev);}else{// printk("downflag=1.ignore this data.\n");downflag=0;}}/*如果count=0, 也就是刚进来的时候,开启ADC中断。 接着就会调用ADC中断的处理函数*/ts->xp = 0;ts->yp = 0;ts->count = 0;writel(S3C_ADCTSC_PULL_UP_DISABLE | AUTOPST, ts_base+S3C_ADCTSC);writel(readl(ts_base+S3C_ADCCON) | S3C_ADCCON_ENABLE_START, ts_base+S3C_ADCCON);}else {//upts->count = 0;input_report_key(ts->dev, BTN_TOUCH, 0);input_report_abs(ts->dev, ABS_PRESSURE, 0);input_sync(ts->dev);writel(WAIT4INT(0), ts_base+S3C_ADCTSC);#ifdef CONFIG_FORLINX6410_ADCif (ADC_locked4TS()) {s3c_ts_adc_unlock();printk("forlinx debug*****s3c_ts_adc_unlock();.\n");}
#endif}}static struct timer_list touch_timer =TIMER_INITIALIZER(touch_timer_fire, 0, 0);/* 当触摸屏按下后,会触发tc中断*  * tc中断触发后,会调用touch_timer_fire函数* */
static irqreturn_t stylus_updown(int irqno, void *param)
{unsigned long data0;unsigned long data1;#ifdef CONFIG_FORLINX6410_ADC/*检测是否上锁ADC_LOCK*/if (!ADC_locked4TS()) {if (s3c_ts_adc_lock(LOCK_TS)) {/* Locking ADC controller failed */printk("Lock ADC failed, %d\n", adc_lock_id);return IRQ_HANDLED;}printk("forlinx debug***** s3c_ts_adc_lock(LOCK_TS);.\n");}
#endifdata0 = readl(ts_base+S3C_ADCDAT0);data1 = readl(ts_base+S3C_ADCDAT1);/* TODO we should never get an interrupt with updown set while* the timer is running, but maybe we ought to verify that the* timer isn't running anyways. */touch_timer_fire(0);if(ts->s3c_adc_con==ADC_TYPE_2) {__raw_writel(0x0, ts_base+S3C_ADCCLRWK);__raw_writel(0x0, ts_base+S3C_ADCCLRINT);}return IRQ_HANDLED;
}/* 当ADC中断触发时,就会调用ADC中断处理函数** */static irqreturn_t stylus_action(int irqno, void *param)
{unsigned long data0;unsigned long data1;#ifdef CONFIG_FORLINX6410_ADCif (!ADC_locked4TS()) {if (ADC_free()) {printk("Unexpected\n");/* Clear ADC interrupt */__raw_writel(0x0, ts_base + S3C_ADCCLRINT);}return IRQ_HANDLED;}
#endif//printk("stylus_action.\n");data0 = readl(ts_base+S3C_ADCDAT0);data1 = readl(ts_base+S3C_ADCDAT1);/*可以看见每次进来都是ts->xp++  ts->yp++ */if(ts->resol_bit==12) {
#if defined(CONFIG_TOUCHSCREEN_NEW)ts->yp += S3C_ADCDAT0_XPDATA_MASK_12BIT - (data0 & S3C_ADCDAT0_XPDATA_MASK_12BIT);ts->xp += S3C_ADCDAT1_YPDATA_MASK_12BIT - (data1 & S3C_ADCDAT1_YPDATA_MASK_12BIT);
#else ts->xp += data0 & S3C_ADCDAT0_XPDATA_MASK_12BIT;ts->yp += data1 & S3C_ADCDAT1_YPDATA_MASK_12BIT;
#endif}else {
#if defined(CONFIG_TOUCHSCREEN_NEW)ts->yp += S3C_ADCDAT0_XPDATA_MASK - (data0 & S3C_ADCDAT0_XPDATA_MASK);ts->xp += S3C_ADCDAT1_YPDATA_MASK - (data1 & S3C_ADCDAT1_YPDATA_MASK);
#elsets->xp += data0 & S3C_ADCDAT0_XPDATA_MASK;ts->yp += data1 & S3C_ADCDAT1_YPDATA_MASK;
#endif  }/*每次中断发生,count++*/ts->count++;/* 判断count小于4。 再次触发ADC中断* 当count等于4时,就启动定时器。然后跳到定时器处理函数中去* */if (ts->count < (1<<ts->shift)) {writel(S3C_ADCTSC_PULL_UP_DISABLE | AUTOPST, ts_base+S3C_ADCTSC);writel(readl(ts_base+S3C_ADCCON) | S3C_ADCCON_ENABLE_START, ts_base+S3C_ADCCON);} else {mod_timer(&touch_timer, jiffies+1);writel(WAIT4INT(1), ts_base+S3C_ADCTSC);}if(ts->s3c_adc_con==ADC_TYPE_2) {__raw_writel(0x0, ts_base+S3C_ADCCLRWK);__raw_writel(0x0, ts_base+S3C_ADCCLRINT);}return IRQ_HANDLED;
}static struct s3c_ts_mach_info *s3c_ts_get_platdata (struct device *dev)
{if (dev->platform_data != NULL)return (struct s3c_ts_mach_info *)dev->platform_data;return &s3c_ts_default_cfg;
}/* * s3c_ts_probe函数的主要作用是:初始化硬件相关的资源。* 比如: 内存ioremap, 中断资源获取, 配置ADCCCON等寄存器** 当中断注册好后,当我们按下触摸屏后,就会触发tc中断*/
static int __init s3c_ts_probe(struct platform_device *pdev)
{struct resource *res;struct device *dev;struct input_dev *input_dev;struct s3c_ts_mach_info * s3c_ts_cfg;int ret, size;dev = &pdev->dev;/* 得到s3c_ts_resource*/res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (res == NULL) {dev_err(dev,"no memory resource specified\n");return -ENOENT;}size = (res->end - res->start) + 1;ts_mem = request_mem_region(res->start, size, pdev->name);if (ts_mem == NULL) {dev_err(dev, "failed to get memory region\n");ret = -ENOENT;goto err_req;}ts_base = ioremap(res->start, size);if (ts_base == NULL) {dev_err(dev, "failed to ioremap() region\n");ret = -EINVAL;goto err_map;}ts_clock = clk_get(&pdev->dev, "adc");if (IS_ERR(ts_clock)) {dev_err(dev, "failed to find watchdog clock source\n");ret = PTR_ERR(ts_clock);goto err_clk;}clk_enable(ts_clock);/*得到s3c_ts_cfg配置文件*/s3c_ts_cfg = s3c_ts_get_platdata(&pdev->dev);/*设置ADC分频分频系数*/if ((s3c_ts_cfg->presc&0xff) > 0)writel(S3C_ADCCON_PRSCEN | S3C_ADCCON_PRSCVL(s3c_ts_cfg->presc&0xff),ts_base+S3C_ADCCON);elsewritel(0, ts_base+S3C_ADCCON);/* Initialise registers *//*设置ADC转化延迟*/if ((s3c_ts_cfg->delay&0xffff) > 0)writel(s3c_ts_cfg->delay & 0xffff, ts_base+S3C_ADCDLY);/*设置AD:2-bit A/D conversion*/if (s3c_ts_cfg->resol_bit==12) {switch(s3c_ts_cfg->s3c_adc_con) {case ADC_TYPE_2:writel(readl(ts_base+S3C_ADCCON)|S3C_ADCCON_RESSEL_12BIT, ts_base+S3C_ADCCON);break;case ADC_TYPE_1:writel(readl(ts_base+S3C_ADCCON)|S3C_ADCCON_RESSEL_12BIT_1, ts_base+S3C_ADCCON);break;default:dev_err(dev, "Touchscreen over this type of AP isn't supported !\n");break;}}/*等待按下中断*/writel(WAIT4INT(0), ts_base+S3C_ADCTSC);ts = kzalloc(sizeof(struct s3c_ts_info), GFP_KERNEL);input_dev = input_allocate_device();if (!input_dev) {ret = -ENOMEM;goto err_alloc;}ts->dev = input_dev;/*设置输入设备的事件类型: 按键事件, 同步事件, 绝对位移事件*/ts->dev->evbit[0] = ts->dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);ts->dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);/*设置触摸屏的x,y坐标以及压力*/if (s3c_ts_cfg->resol_bit==12) {input_set_abs_params(ts->dev, ABS_X, 0, 0xFFF, 0, 0);input_set_abs_params(ts->dev, ABS_Y, 0, 0xFFF, 0, 0);}else {input_set_abs_params(ts->dev, ABS_X, 0, 0x3FF, 0, 0);input_set_abs_params(ts->dev, ABS_Y, 0, 0x3FF, 0, 0);}input_set_abs_params(ts->dev, ABS_PRESSURE, 0, 1, 0, 0);sprintf(ts->phys, "input(ts)");/*输入设备的初始化* 比如: name, 总线类型, 版本号等* */ts->dev->name = s3c_ts_name;ts->dev->phys = ts->phys;ts->dev->id.bustype = BUS_RS232;ts->dev->id.vendor = 0xDEAD;ts->dev->id.product = 0xBEEF;ts->dev->id.version = S3C_TSVERSION;ts->shift = s3c_ts_cfg->oversampling_shift;ts->resol_bit = s3c_ts_cfg->resol_bit;ts->s3c_adc_con = s3c_ts_cfg->s3c_adc_con;/* For IRQ_PENDUP *//*请求中断资源0, 注册tc中断*/ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);if (ts_irq == NULL) {dev_err(dev, "no irq resource specified\n");ret = -ENOENT;goto err_irq;}ret = request_irq(ts_irq->start, stylus_updown, IRQF_SAMPLE_RANDOM, "s3c_updown", ts);if (ret != 0) {dev_err(dev,"s3c_ts.c: Could not allocate ts IRQ_PENDN !\n");ret = -EIO;goto err_irq;}/* For IRQ_ADC *//*请求中断资源1, 注册ADC中断*/ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 1);if (ts_irq == NULL) {dev_err(dev, "no irq resource specified\n");ret = -ENOENT;goto err_irq;}ret = request_irq(ts_irq->start, stylus_action, IRQF_SAMPLE_RANDOM | IRQF_SHARED,"s3c_action", ts);if (ret != 0) {dev_err(dev, "s3c_ts.c: Could not allocate ts IRQ_ADC !\n");ret =  -EIO;goto err_irq;}printk(KERN_INFO "%s got loaded successfully : %d bits\n", s3c_ts_name, s3c_ts_cfg->resol_bit);/* All went ok, so register to the input system *//*注册输入型设备*/ret = input_register_device(ts->dev);if(ret) {dev_err(dev, "s3c_ts.c: Could not register input device(touchscreen)!\n");ret = -EIO;goto fail;}return 0;fail:free_irq(ts_irq->start, ts->dev);free_irq(ts_irq->end, ts->dev);err_irq:input_free_device(input_dev);kfree(ts);err_alloc:clk_disable(ts_clock);clk_put(ts_clock);err_clk:iounmap(ts_base);err_map:release_resource(ts_mem);kfree(ts_mem);err_req:return ret;
}static int s3c_ts_remove(struct platform_device *dev)
{printk(KERN_INFO "s3c_ts_remove() of TS called !\n");disable_irq(IRQ_ADC);disable_irq(IRQ_PENDN);free_irq(IRQ_PENDN, ts->dev);free_irq(IRQ_ADC, ts->dev);if (ts_clock) {clk_disable(ts_clock);clk_put(ts_clock);ts_clock = NULL;}input_unregister_device(ts->dev);iounmap(ts_base);return 0;
}#ifdef CONFIG_PM
static unsigned int adccon, adctsc, adcdly;static int s3c_ts_suspend(struct platform_device *dev, pm_message_t state)
{adccon = readl(ts_base+S3C_ADCCON);adctsc = readl(ts_base+S3C_ADCTSC);adcdly = readl(ts_base+S3C_ADCDLY);disable_irq(IRQ_ADC);disable_irq(IRQ_PENDN);clk_disable(ts_clock);return 0;
}static int s3c_ts_resume(struct platform_device *pdev)
{clk_enable(ts_clock);writel(adccon, ts_base+S3C_ADCCON);writel(adctsc, ts_base+S3C_ADCTSC);writel(adcdly, ts_base+S3C_ADCDLY);writel(WAIT4INT(0), ts_base+S3C_ADCTSC);enable_irq(IRQ_ADC);enable_irq(IRQ_PENDN);return 0;
}
#else
#define s3c_ts_suspend NULL
#define s3c_ts_resume  NULL
#endifstatic struct platform_driver s3c_ts_driver = {.probe          = s3c_ts_probe,.remove         = s3c_ts_remove,.suspend        = s3c_ts_suspend,.resume         = s3c_ts_resume,.driver       = {.owner  = THIS_MODULE,.name    = "s3c-ts",},
};static char banner[] __initdata = KERN_INFO "S3C Touchscreen driver, (c) 2008 Samsung Electronics\n";
/* 首先: 我们注册是platform驱动,当然有platform驱动就会有platform设备了。* 当platform驱动注册到系统中时,就会和platform设备去匹配。** 那问题来了? platform是如何匹配设备与驱动的?* platform_match()函数中strcmp(pdev->name, drv->name)这句就会告诉你, 是通过设备的name与驱动的name匹配的。** 而我们的s3c_ts_driver的name = "s3c-ts",那么我们的设备的名字应该也会是"s3c-ts"** 我们搜索系统发现:Dev-ts.c文件中存在s3c_device_ts的name为"s3c-ts"。很明显这就是platform驱动对应的platform的设备了。** 当设备与驱动的名称匹配了,就会调用s3c_ts_probe函数。* * */
static int __init s3c_ts_init(void)
{printk(banner);return platform_driver_register(&s3c_ts_driver);
}static void __exit s3c_ts_exit(void)
{platform_driver_unregister(&s3c_ts_driver);
}

Linux触摸屏驱动分析(6410) -- s3c-ts相关推荐

  1. linux 触摸屏驱动分析

    mini2440驱动分析系列之 ---------------------------------------Mini2440触摸屏程序分析 By JeefJiang July,8th,2009 这是 ...

  2. linux 触摸结构体,xboot-x4412ibox项目实战54-Linux触摸屏驱动之I2C驱动实验 - Powered by Discuz!...

    前面我们分析了linux触摸屏驱动的input子系统机制,本章节分析linux触摸屏驱动的i2c机制. 驱动源码路径: kernel/drivers/input/touchscreen/ft5x06_ ...

  3. Linux程序之触摸,linux 触摸屏驱动编写

    早在诺基亚手机还比较流行的时候,那时候触摸屏用的还不多.但是随着触摸屏手机.即智能手机的流行,触摸屏基本成了手机的标配.所以,今天可以看看触摸屏驱动在linux上是如何进行的. 1.驱动目录 driv ...

  4. Linux触屏驱动Windows,linux 触摸屏驱动编写

    这篇文章主要介绍了linux 触摸屏驱动编写,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 早在诺基亚手机还比较流行的时候,那时候触摸屏用的还不多.但是随着触摸屏手机.即 ...

  5. linux串口驱动分析

    linux串口驱动分析 硬件资源及描写叙述 s3c2440A 通用异步接收器和发送器(UART)提供了三个独立的异步串行 I/O(SIO)port,每一个port都能够在中断模式或 DMA 模式下操作 ...

  6. Linux spi驱动分析(四)----SPI设备驱动(W25Q32BV)

    一.W25Q32BV芯片简介 W25X是一系列SPI接口Flash芯片的简称,它采用SPI接口和CPU通信,本文使用的W25Q32BV容量为32M,具体特性如下: 1.1.基本特性 该芯片最大支持10 ...

  7. Linux spi驱动分析----SPI设备驱动(W25Q32BV)

    转载地址:http://blog.chinaunix.net/uid-25445243-id-4026974.html 一.W25Q32BV芯片简介 W25X是一系列SPI接口Flash芯片的简称,它 ...

  8. Wince6.0 s3c6410触摸屏驱动分析

    http://blog.sina.com.cn/s/blog_4b4b54da01012gbz.html Wince6.0 s3c6410触摸屏驱动分析     一.wince 触摸屏驱动概述... ...

  9. 触摸屏linux系统时间,关于Linux触摸屏驱动

    操作系统对于经常应用电脑的用户非常的重要,一个好的操作系统,能更好的节省学习的时间.本文讲解Linux触摸屏驱动开发,在Linux触摸屏驱动中,最好的范例莫过于mc68328digi.c的实现.本文把 ...

  10. Linux网卡驱动分析之RTL8139(五)

    Linux网卡驱动分析之RTL8139(五) deliver_skb(dev.c) // 该函数就是调用个协议的接收函数处理该skb 包,进入第三层网络层处理 static __inline__ in ...

最新文章

  1. 【读书笔记《Bootstrap 实战》】3.优化站点资源、完成响应式图片、让传送带支持手势...
  2. 关于element-ui 中使用Notice组件(Message、MessageBox、Notification)所遇到的坑
  3. 6.分布式数据库HBase第2部分
  4. java 注解使用_Java 注解用法
  5. ### C++总结-[类成员函数]
  6. PostgreSQL11.7逻辑复制压测
  7. CentOS Linux解决Device eth0 does not seem to be present【转】
  8. Teamcenter 入门开发系列问答(3)
  9. self-sizing cell的一个问题
  10. Atitit.iso格式蓝光 BDMV 结构说明
  11. java日期字符串排序_java字符串日期排序比较问题
  12. 睿智的目标检测26——Pytorch搭建yolo3目标检测平台
  13. 【田间连着车间、佘太酒业这十年!
  14. 转型只争朝夕!又一火电企业成立新能源公司
  15. C语言 分解质因数。例如:输入90,打印出90=2*3*3*5。
  16. SEO文章优化,内容SEO优化,SEO文章内容优化
  17. 基于PHP的酒店住宿管理系统 毕业设计源码261455
  18. P106双N卡 自动调用方案
  19. 2022 年七大前沿科技:每一项都能改变世界
  20. 确定电气间隙和爬电距离

热门文章

  1. java并发编程(四) 线程池 任务执行、终止源码分析
  2. android优化 清除无效代码 UCDetector
  3. 【mysql】关于IO/内存方面的一些优化
  4. Python破解协议密码
  5. [转+]C语言复杂声明
  6. js实现php中图片轮播,两种js实现轮播图的方式
  7. MongoDB lsm降低 disk lantency
  8. vue组件挂载到全局方法
  9. 黑客的克星或叫“白客”
  10. [jQuery] 按比例缩小图片