日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux驱动向不同串口发数据,Linux串口(serial、uart)驱动程序设计

發布時間:2024/7/19 linux 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux驱动向不同串口发数据,Linux串口(serial、uart)驱动程序设计 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、核心數據結構

串口驅動有3個核心數據結構,它們都定義在

1、uart_driver

uart_driver包含了串口設備名、串口驅動名、主次設備號、串口控制臺(可選)等信息,還封裝了tty_driver(底層串口驅動無需關心tty_driver)。

struct uart_driver {

struct module???? *owner;???????????/* 擁有該uart_driver的模塊,一般為THIS_MODULE */

const char????????*driver_name;???? /*?串口驅動名,串口設備文件名以驅動名為基礎 */

const char????????*dev_name;????????/* 串口設備名 */

int??????????????? major;????????? ?/* 主設備號 */

int????????????????minor;???????? ??/* 次設備號 */

int????????????????nr;???????????? ?/* 該uart_driver支持的串口個數(最大) */

struct console????*cons;????????????/* 其對應的console.若該uart_driver支持serial console,否則為NULL *//*

* these are private; the low level driver should not

* touch these; they should be initialised to NULL

*/

struct uart_state?*state;

struct tty_driver?*tty_driver;

};

2、uart_port

uart_port用于描述串口端口的I/O端口或I/O內存地址、FIFO大小、端口類型、串口時鐘等信息。實際上,一個uart_port實例對應一個串口設備

struct uart_port {

spinlock_t???????????? lock;?????????? /* 串口端口鎖 */

unsigned int?????????? iobase;???????? /* IO端口基地址 */

unsigned char __iomem?*membase;????/* IO內存基地址,經映射(如ioremap)后的IO內存虛擬基地址 */

unsigned int?????????? irq;???????????/* 中斷號 */

unsigned int?????????? uartclk;????????/* 串口時鐘 */

unsigned int???????????fifosize;???????/* 串口FIFO緩沖大小 */

unsigned char????????? x_char;?????????/* xon/xoff字符 */

unsigned char????????? regshift;???????/* 寄存器位移 */

unsigned char????????? iotype;?????????/* IO訪問方式 */

unsigned char????????? unused1;

#define UPIO_PORT????????(0)?????????????? /* IO端口 */

#define UPIO_HUB6????????(1)

#define UPIO_MEM???????? (2)????????????? ?/* IO內存 */

#define UPIO_MEM32???????(3)

#define UPIO_AU??????????(4)?????????????? /* Au1x00 type IO */

#define UPIO_TSI???????? (5)?????????????? /* Tsi108/109 type IO */

#define UPIO_DWAPB???????(6)?????????????? /* DesignWare APB UART */

#define UPIO_RM9000??????(7)?????????????? /* RM9000 type IO */

unsigned int????????read_status_mask;??/* 關心的Rx error status */

unsigned int????????ignore_status_mask;/* 忽略的Rx error status */

struct uart_info????? *info;?????????? /* pointer to parent info */

struct uart_icount???? icount;??????? ?/* 計數器 */

struct console????????*cons;????????? ?/*?console結構體 */

#ifdef CONFIG_SERIAL_CORE_CONSOLE

unsigned long?????????sysrq;????????? ?/* sysrq timeout */

#endif

upf_t??????????????? ?flags;

#define UPF_FOURPORT???????? ((__force upf_t) (1 << 1))

#define UPF_SAK????????????? ((__force upf_t) (1 << 2))

#define UPF_SPD_MASK??????? ?((__force upf_t) (0x1030))

#define UPF_SPD_HI?????????? ((__force upf_t) (0x0010))

#define UPF_SPD_VHI????????? ((__force upf_t) (0x0020))

#define UPF_SPD_CUST???????? ((__force upf_t) (0x0030))

#define UPF_SPD_SHI????????? ((__force upf_t) (0x1000))

#define UPF_SPD_WARP???????? ((__force upf_t) (0x1010))

#define UPF_SKIP_TEST??????? ((__force upf_t) (1 << 6))

#define UPF_AUTO_IRQ???????? ((__force upf_t) (1 << 7))

#define UPF_HARDPPS_CD?????? ((__force upf_t) (1 << 11))

#define UPF_LOW_LATENCY????? ((__force upf_t) (1 << 13))

#define UPF_BUGGY_UART?????? ((__force upf_t) (1 << 14))

#define UPF_MAGIC_MULTIPLIER?((__force upf_t) (1 << 16))

#define UPF_CONS_FLOW????????((__force upf_t) (1 << 23))

#define UPF_SHARE_IRQ????????((__force upf_t) (1 << 24))

#define UPF_BOOT_AUTOCONF????((__force upf_t) (1 << 28))

#define UPF_FIXED_PORT???????((__force upf_t) (1 << 29))

#define UPF_DEAD???????????? ((__force upf_t) (1 << 30))

#define UPF_IOREMAP????????? ((__force upf_t) (1 << 31))

#define UPF_CHANGE_MASK??????((__force upf_t) (0x17fff))

#define UPF_USR_MASK???????? ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))

unsigned int???????????? mctrl;????????/* 當前的moden設置 */

unsigned int???????????? timeout;??????/* character-based timeout */

unsigned int???????????? type;?????????/* 端口類型 */

const struct uart_ops???*ops;????????? /* 串口端口操作函數集 */

unsigned int???????????? custom_divisor;

unsigned int???????????? line;?????????/* 端口索引 */

resource_size_t??????????mapbase;??????/* IO內存物理基地址,可用于ioremap */

struct device????????? ?*dev;??????????/* 父設備 */

unsigned char?????????? ?hub6;?????????/* this should be in the 8250 driver */

unsigned char??????????? suspended;

unsigned char??????????? unused[2];

void????????????????????*private_data;?/* 端口私有數據,一般為platform數據指針 */

};

uart_iconut為串口信息計數器,包含了發送字符計數、接收字符計數等。在串口的發送中斷處理函數和接收中斷處理函數中,我們需要管理這些計數。

struct uart_icount {

__u32????cts;

__u32????dsr;

__u32????rng;

__u32????dcd;

__u32????rx;/*?發送字符計數 */

__u32????tx;/*?接受字符計數 */

__u32????frame;/*?幀錯誤計數 */

__u32????overrun;/*?Rx FIFO溢出計數 */

__u32????parity;/*?幀校驗錯誤計數 */

__u32????brk;/*?break計數 */

__u32????buf_overrun;

};

uart_info有兩個成員在底層串口驅動會用到:xmit和tty。用戶空間程序通過串口發送數據時,上層驅動將用戶數據保存在xmit;而串口發送中斷處理函數就是通過xmit獲取到用戶數據并將它們發送出去。串口接收中斷處理函數需要通過tty將接收到的數據傳遞給行規則層。

/* uart_info實例僅在串口端口打開時有效,它可能在串口關閉時被串口核心層釋放。因此,在使用uart_port的uart_info成員時必須保證串口已打開。底層驅動和核心層驅動都可以修改uart_info實例。

* This is the state information which is only valid when the port

* is open; it may be freed by the core driver once the device has

* been closed. Either the low level driver or the core can modify

* stuff here.

*/

struct uart_info {

struct tty_struct?????*tty;

struct circ_buf????????xmit;

uif_t????????????????? flags;/*

* Definitions for info->flags. These are _private_ to serial_core, and

* are specific to this structure. They may be queried by low level drivers.

*/

#define UIF_CHECK_CD????????((__force uif_t) (1 << 25))

#define UIF_CTS_FLOW????????((__force uif_t) (1 << 26))

#define UIF_NORMAL_ACTIVE????((__force uif_t) (1 << 29))

#define UIF_INITIALIZED????????((__force uif_t) (1 << 31))

#define UIF_SUSPENDED????????((__force uif_t) (1 << 30))

int???????????????????? blocked_open;

struct tasklet_struct???tlet;

wait_queue_head_t?????? open_wait;

wait_queue_head_t?????? delta_msr_wait;

};

3、uart_ops

uart_ops涵蓋了串口驅動可對串口設備進行的所有操作。

/*

* This structure describes all the operations that can be

* done on the physical hardware.

*/

struct uart_ops {

unsigned int?(*tx_empty)(struct uart_port *);?/*?串口的Tx FIFO緩存是否為空?*/

void???????? (*set_mctrl)(struct uart_port *, unsigned int mctrl);/*?設置串口modem控制?*/

unsigned int?(*get_mctrl)(struct uart_port *);/*?獲取串口modem控制?*/

void???????? (*stop_tx)(struct uart_port *);/*?禁止串口發送數據?*/

void???????? (*start_tx)(struct uart_port *);/*?使能串口發送數據?*/

void???????? (*send_xchar)(struct uart_port *, char ch);/*?發送xChar?*/

void???????? (*stop_rx)(struct uart_port *);/*?禁止串口接收數據?*/

void???????? (*enable_ms)(struct uart_port *);/*?使能modem的狀態信號?*/

void???????? (*break_ctl)(struct uart_port *, int ctl);/*?設置break信號?*/

int????????? (*startup)(struct uart_port *);/*?啟動串口,應用程序打開串口設備文件時,該函數會被調用?*/

void???????? (*shutdown)(struct uart_port *);/*?關閉串口,應用程序關閉串口設備文件時,該函數會被調用?*/

void???????? (*set_termios)(struct uart_port *, struct ktermios *new,?struct ktermios *old);/*?設置串口參數?*/

void???????? (*pm)(struct uart_port *, unsigned int state,

unsigned int oldstate);/*?串口電源管理?*/

int????????? (*set_wake)(struct uart_port *, unsigned int state);/*??*/

const char? *(*type)(struct uart_port *);/*?返回一描述串口類型的字符串?*/

void???????? (*release_port)(struct uart_port *);/*?釋放串口已申請的IO端口/IO內存資源,必要時還需iounmap?*/

int????????? (*request_port)(struct uart_port *);/*?申請必要的IO端口/IO內存資源,必要時還可以重新映射串口端口?*/

void???????? (*config_port)(struct uart_port *, int);/*?執行串口所需的自動配置?*/

int????????? (*verify_port)(struct uart_port *, struct serial_struct *);/*?核實新串口的信息?*/

int????????? (*ioctl)(struct uart_port *, unsigned int, unsigned long);/*?IO控制?*/

};

二、串口驅動API

1、uart_register_driver

/* 功能:??? uart_register_driver用于將串口驅動uart_driver注冊到內核(串口核心層)中,通常在模塊初始化函數調用該函數。

* 參數 drv:要注冊的uart_driver

*?返回值:? 成功,返回0;否則返回錯誤碼

*/

int uart_register_driver(struct uart_driver *drv)

2、uart_unregister_driver

/* 功能:??? uart_unregister_driver用于注銷我們已注冊的uart_driver,通常在模塊卸載函數調用該函數

*參數 drv:要注銷的uart_driver

*?返回值:? 成功,返回0;否則返回錯誤碼

*/

void uart_unregister_driver(struct uart_driver *drv)

3、uart_add_one_port

/* 功能:??? uart_add_one_port用于為串口驅動添加一個串口端口,通常在探測到設備后(驅動的設備probe方法)調用該函數

* 參數?drv:串口驅動

*????? port:要添加的串口端口

* 返回值:成功,返回0;否則返回錯誤碼

*/

int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)

4、uart_remove_one_port

/* 功能:?????uart_remove_one_port用于刪除一個已添加到串口驅動中的串口端口,通常在驅動卸載時調用該函數

* 參數?drv: 串口驅動

*????? port: 要刪除的串口端口

* 返回值:?? 成功,返回0;否則返回錯誤碼

*/

int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)

5、uart_write_wakeup

/* 功能:???? uart_write_wakeup喚醒上層因向串口端口寫數據而阻塞的進程,通常在串口發送中斷處理函數中調用該函數

* 參數 port:需要喚醒寫阻塞進程的串口端口

*/

void uart_write_wakeup(struct uart_port *port)

6、uart_suspend_port

/* 功能:???? uart_suspend_port用于掛起特定的串口端口

*?參數drv: 要掛起的串口端口所屬的串口驅動

*??????port:要掛起的串口端口

* 返回值:?? 成功返回0;否則返回錯誤碼

*/

int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)

7、uart_resume_port

/* 功能:???? uart_resume_port用于恢復某一已掛起的串口

*?參數drv: 要恢復的串口端口所屬的串口驅動

*??????port:要恢復的串口端口

* 返回值:?? 成功返回0;否則返回錯誤碼

*/

int uart_resume_port(struct uart_driver *drv, struct uart_port *port)

8、uart_get_baud_rate

/* 功能:??????? uart_get_baud_rate通過解碼termios結構體來獲取指定串口的波特率

* 參數 port:? 要獲取波特率的串口端口

*???? termios:當前期望的termios配置(包含串口波特率)

*???? old:??? 以前的termios配置,可以為NULL

*???? min:??? 可接受的最小波特率

*???? max:????可接受的最大波特率

* 返回值:???? 串口的波特率

*/

unsigned int

uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,

struct ktermios *old, unsigned int min, unsigned int max)

9、uart_get_divisor

/* 功能:???? uart_get_divisor用于計算某一波特率的串口時鐘分頻數(串口波特率除數)

* 參數 port:要計算時鐘分頻數的串口端口

*????? baud:期望的波特率

*返回值:??? 串口時鐘分頻數

*/

unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud)

10、uart_update_timeout

/* 功能:????? uart_update_timeout用于更新(設置)串口FIFO超時時間

* 參數 port: 要更新超時時間的串口端口

*???? cflag:termios結構體的cflag值

*???? baud: 串口的波特率*/

void uart_update_timeout(struct uart_port *port, unsigned intcflag,?unsigned int baud)

11、uart_match_port

/* 功能:uart_match_port用于判斷兩串口端口是否為同一端口

* 參數 port1、port2:要判斷的串口端口

* 返回值:不同返回0;否則返回非0

*/

int uart_match_port(struct uart_port *port1, struct uart_port *port2)

12、uart_console_write

/* 功能:??????? uart_console_write用于向串口端口寫一控制臺信息

*?參數 port:??? 要寫信息的串口端口

*???? s:???????要寫的信息

*???? count:?? 信息的大小

*???? putchar: 用于向串口端口寫字符的函數,該函數函數有兩個參數:串口端口和要寫的字符

*/

void uart_console_write(struct uart_port *port, const char *s,

unsigned int count,

void (*putchar)(struct uart_port *, int))

三、串口驅動例子

該串口驅動例子是我針對s3c2410處理器的串口2(uart2)獨立開發的。因為我通過博創2410s開發板的GRPS擴展板來測試該驅動(已通過測試),所以我叫該串口為gprs_uart。

該驅動將串口看作平臺(platform)設備。platform可以看作一偽總線,用于將集成于片上系統的輕量級設備與Linux設備驅動模型聯系到一起,它包含以下兩部分(有關platform的聲明都在#include ,具體實現在drivers/base/platform.c):

1、platform設備。我們需要為每個設備定義一個platform_device實例

struct platform_device {

const char????? *name;/*?設備名 */

int????????????? id;/*?設備的id號 */

struct device??? dev;/*?其對應的device */

u32??????????????num_resources;/*?該設備用有的資源數 */

struct resource?*resource;/*?資源數組 */

};

為我們的設備創建platform_device實例有兩種方法:填充一個platform_device結構體后用platform_device_register(一次注冊一個)或platform_add_devices(一次可以注冊多個platform設備)將platform_device注冊到內核;更簡單的是使用platform_device_register_simple來建立并注冊我們的platform_device。

2、platform驅動。platform設備由platform驅動進行管理。當設備加入到系統中時,platform_driver的probe方法會被調用來見對應的設備添加或者注冊到內核;當設備從系統中移除時,platform_driver的remove方法會被調用來做一些清理工作,如移除該設備的一些實例、注銷一些已注冊到系統中去的東西。

struct platform_driver {

int? (*probe)(struct platform_device *);

int? (*remove)(struct platform_device *);

void (*shutdown)(struct platform_device *);

int? (*suspend)(struct platform_device *, pm_message_t state);

int? (*suspend_late)(struct platform_device *, pm_message_t state);

int? (*resume_early)(struct platform_device *);

int? (*resume)(struct platform_device *);

struct device_driver driver;

};

更詳細platform資料可參考網上相關文章。

例子驅動中申請和釋放IO內存區的整個過程如下:

insmod?gprs_uart.ko→gprs_init_module()→uart_register_driver()→gprs_uart_probe()→uart_add_one_port()→gprs_uart_config_port()→gprs_uart_request_port()→request_mem_region()

rmmod?gprs_uart.ko→gprs_exit_module()→uart_unregister_driver()→gprs_uart_remove()→uart_remove_one_port()→gprs_uart_release_port()→release_mem_region()

例子驅動中申請和釋放IRQ資源的整個過程如下:

open?/dev/gprs_uart→gprs_uart_startup()→request_irq()

close?/dev/gprs_uart→gprs_uart_shutdown()→free_irq()

想了解更詳細的調用過程可以在驅動模塊各函數頭插入printk(KERN_DEBUG "%s\n", __FUNCTION__);并在函數尾插入printk(KERN_DEBUG "%s done\n", __FUNCTION__);

下面是串口驅動例子和其GPRS測試程序源碼下載地址:

#include

#include

#include ???????/* printk() */

#include ?????????/* kmalloc() */

#include ???????????/* everything... */

#include ????????/* error codes */

#include ????????/* size_t */

#include ????????/* O_ACCMODE */

#include ?????????/* cli(), *_flags */

#include ????????/* copy_*_user */

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define DEV_NAME????????????"gprs_uart"???? /* 設備名 */

/* 這里將串口的主設備號設為0,則串口設備編號由內核動態分配;你也可指定串口的設備編號 */

#define GPRS_UART_MAJOR????????0????????????/* 主設備號 */

#define GPRS_UART_MINOR????????0????????????/* 次設備號 */

#define GPRS_UART_FIFO_SIZE????16???????????/* 串口FIFO的大小 */

#define RXSTAT_DUMMY_READ????(0x10000000)

#define MAP_SIZE ????????????(0x100)????????/* 要映射的串口IO內存區大小 */

/* 串口發送中斷號 */

#define TX_IRQ(port) ((port)->irq + 1)

/* 串口接收中斷號 */

#define RX_IRQ(port) ((port)->irq)

/* 允許串口接收字符的標志 */

#define tx_enabled(port) ((port)->unused[0])

/* 允許串口發送字符的標志 */

#define rx_enabled(port) ((port)->unused[1])

/* 獲取寄存器地址 */

#define portaddr(port, reg) ((port)->membase + (reg))

/* 讀8位寬的寄存器 */

#define rd_regb(port, reg) (ioread8(portaddr(port, reg)))

/* 讀32位寬的寄存器 */

#define rd_regl(port, reg) (ioread32(portaddr(port, reg)))

/* 寫8位寬的寄存器 */

#define wr_regb(port, reg, val) \

do { iowrite8(val, portaddr(port, reg)); } while(0)

/* 寫32位寬的寄存器 */

#define wr_regl(port, reg, val) \

do { iowrite32(val, portaddr(port, reg)); } while(0)

/* 禁止串口發送數據 */

static void gprs_uart_stop_tx(struct uart_port *port)

{

if (tx_enabled(port))????????????/* 若串口已啟動發送 */

{

disable_irq(TX_IRQ(port));???/* 禁止發送中斷 */

tx_enabled(port) = 0;????????/* 設置串口為未啟動發送 */

}

}

/* 使能串口發送數據 */

static void gprs_uart_start_tx(struct uart_port *port)

{

if (!tx_enabled(port))???????????/* 若串口未啟動發送 */

{

enable_irq(TX_IRQ(port));????/* 使能發送中斷 */

tx_enabled(port) = 1;????????/* 設置串口為已啟動發送 */

}

}

/* 禁止串口接收數據 */

static void gprs_uart_stop_rx(struct uart_port *port)

{

if (rx_enabled(port))????????????/* 若串口已啟動接收 */

{

disable_irq(RX_IRQ(port));???/* 禁止接收中斷 */

rx_enabled(port) = 0;????????/* 設置串口為未啟動接收 */

}

}

/* 使能modem的狀態信號 */

static void gprs_uart_enable_ms(struct uart_port *port)

{

}

/* 串口的Tx FIFO緩存是否為空 */

static unsigned int gprs_uart_tx_empty(struct uart_port *port)

{

int ret = 1;

unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT);

unsigned long ufcon = rd_regl(port, S3C2410_UFCON);

if (ufcon & S3C2410_UFCON_FIFOMODE)????/* 若使能了FIFO */

{

if ((ufstat & S3C2410_UFSTAT_TXMASK) != 0 ||????/* 0 (ufstat & S3C2410_UFSTAT_TXFULL))???????/* FIFO滿 */

ret = 0;

}

else????/* 若未使能了FIFO,則判斷發送緩存和發送移位寄存器是否均為空 */

{

ret = rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE;

}

return ret;

}

/* 獲取串口modem控制,因為uart2無modem控制,所以CTS、DSR直接返回有效 */

static unsigned int gprs_uart_get_mctrl(struct uart_port *port)

{

return (TIOCM_CTS | TIOCM_DSR | TIOCM_CAR);

}

/* 設置串口modem控制 */

static void gprs_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)

{

}

/* 設置break信號 */

static void gprs_uart_break_ctl(struct uart_port *port, int break_state)

{

unsigned long flags;

unsigned int ucon;

spin_lock_irqsave(&port->lock, flags);

ucon = rd_regl(port, S3C2410_UCON);

if (break_state)

ucon |= S3C2410_UCON_SBREAK;

else

ucon &= ~S3C2410_UCON_SBREAK;

wr_regl(port, S3C2410_UCON, ucon);

spin_unlock_irqrestore(&port->lock, flags);

}

/* 返回Rx FIFO已存多少數據 */

static int gprs_uart_rx_fifocnt(unsigned long ufstat)

{

/* 若Rx FIFO已滿,返回FIFO的大小 */

if (ufstat & S3C2410_UFSTAT_RXFULL)

return GPRS_UART_FIFO_SIZE;

/* 若FIFO未滿,返回Rx FIFO已存了多少字節數據 */

return (ufstat & S3C2410_UFSTAT_RXMASK) >> S3C2410_UFSTAT_RXSHIFT;

}

#define S3C2410_UERSTAT_PARITY (0x1000)

/* 串口接收中斷處理函數,獲取串口接收到的數據,并將這些數據遞交給行規則層 */

static irqreturn_t gprs_uart_rx_chars(int irq, void *dev_id)

{

struct uart_port *port = dev_id;

struct tty_struct *tty = port->info->tty;

unsigned int ufcon, ch, flag, ufstat, uerstat;

int max_count = 64;

/* 循環接收數據,最多一次中斷接收64字節數據 */

while (max_count-- > 0)

{

ufcon = rd_regl(port, S3C2410_UFCON);

ufstat = rd_regl(port, S3C2410_UFSTAT);

/* 若Rx FIFO無數據了,跳出循環 */

if (gprs_uart_rx_fifocnt(ufstat) == 0)

break;

/* 讀取Rx error狀態寄存器 */

uerstat = rd_regl(port, S3C2410_UERSTAT);

/* 讀取已接受到的數據 */

ch = rd_regb(port, S3C2410_URXH);

/* insert the character into the buffer */

/* 先將tty標志設為正常 */

flag = TTY_NORMAL;

/* 遞增接收字符計數器 */

port->icount.rx++;

/* 判斷是否存在Rx error

* if (unlikely(uerstat & S3C2410_UERSTAT_ANY))等同于

* if (uerstat & S3C2410_UERSTAT_ANY)

* 只是unlikely表示uerstat & S3C2410_UERSTAT_ANY的值為假的可能性大一些

* 另外還有一個likely(value)表示value的值為真的可能性更大一些

*/

if (unlikely(uerstat & S3C2410_UERSTAT_ANY))

{

/* 若break錯誤,遞增icount.brk計算器 */

if (uerstat & S3C2410_UERSTAT_BREAK)

{

port->icount.brk++;

if (uart_handle_break(port))

goto ignore_char;

}

/* 若frame錯誤,遞增icount.frame計算器 */

if (uerstat & S3C2410_UERSTAT_FRAME)

port->icount.frame++;

/* 若overrun錯誤,遞增icount.overrun計算器 */

if (uerstat & S3C2410_UERSTAT_OVERRUN)

port->icount.overrun++;

/* 查看我們是否關心該Rx error

* port->read_status_mask保存著我們感興趣的Rx error status

*/

uerstat &= port->read_status_mask;

/* 若我們關心該Rx error,則將flag設置為對應的error flag */

if (uerstat & S3C2410_UERSTAT_BREAK)

flag = TTY_BREAK;

else if (uerstat & S3C2410_UERSTAT_PARITY)

flag = TTY_PARITY;

else if (uerstat & ( S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_OVERRUN))

flag = TTY_FRAME;

}

/* 處理sys字符 */

if (uart_handle_sysrq_char(port, ch))

goto ignore_char;

/* 將接收到的字符插入到tty設備的flip緩沖 */

uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, flag);

ignore_char:

continue;

}

/* 刷新tty設備的flip緩沖,將接受到的數據傳給行規則層 */

tty_flip_buffer_push(tty);

return IRQ_HANDLED;

}

/* 串口發送中斷處理函數,將用戶空間的數據(保存在環形緩沖xmit里)發送出去 */

static irqreturn_t gprs_uart_tx_chars(int irq, void *dev_id)

{

struct uart_port *port = dev_id;

struct circ_buf *xmit = &port->info->xmit;????????/* 獲取環線緩沖 */

int count = 256;

/* 若設置了xChar字符 */

if (port->x_char)

{

/* 將該xChar發送出去 */

wr_regb(port, S3C2410_UTXH, port->x_char);

/* 遞增發送計數 */

port->icount.tx++;

/* 清除xChar */

port->x_char = 0;

/* 退出中斷處理 */

goto out;

}

/* 如果沒有更多的字符需要發送(環形緩沖為空),

* 或者uart Tx已停止,

* 則停止uart并退出中斷處理函數

*/

if (uart_circ_empty(xmit) || uart_tx_stopped(port))

{

gprs_uart_stop_tx(port);

goto out;

}

/* 循環發送數據,直到環形緩沖為空,最多一次中斷發送256字節數據 */

while (!uart_circ_empty(xmit) && count-- > 0)

{

/* 若Tx FIFO已滿,退出循環 */

if (rd_regl(port, S3C2410_UFSTAT) & S3C2410_UFSTAT_TXFULL)

break;

/* 將要發送的數據寫入Tx FIFO */

wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);

/* 移向循環緩沖中下一要發送的數據 */

xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);

port->icount.tx++;

}

/* 如果環形緩沖區中剩余的字符少于WAKEUP_CHARS,喚醒上層 */

if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)

uart_write_wakeup(port);

/* 如果環形緩沖為空,則停止發送 */

if (uart_circ_empty(xmit))

gprs_uart_stop_tx(port);

out:

return IRQ_HANDLED;

}

/* 啟動串口端口,在打開該驅動的設備文件時會調用該函數來申請串口中斷,并設置串口為可接受,也可發送 */

static int gprs_uart_startup(struct uart_port *port)

{

unsigned long flags;

int ret;

const char *portname = to_platform_device(port->dev)->name;

/* 設置串口為不可接受,也不可發送 */

rx_enabled(port) = 0;

tx_enabled(port) = 0;

spin_lock_irqsave(&port->lock, flags);

/* 申請接收中斷 */

ret = request_irq(RX_IRQ(port), gprs_uart_rx_chars, 0, portname, port);

if (ret != 0)

{

printk(KERN_ERR "cannot get irq %d\n", RX_IRQ(port));

return ret;

}

/* 設置串口為允許接收 */

rx_enabled(port) = 1;

/* 申請發送中斷 */

ret = request_irq(TX_IRQ(port), gprs_uart_tx_chars, 0, portname, port);

if (ret)

{

printk(KERN_ERR "cannot get irq %d\n", TX_IRQ(port));

rx_enabled(port) = 0;

free_irq(RX_IRQ(port), port);

goto err;

}

/* 設置串口為允許發送 */

tx_enabled(port) = 1;

err:

spin_unlock_irqrestore(&port->lock, flags);

return ret;

}

/* 關閉串口,在關閉驅動的設備文件時會調用該函數,釋放串口中斷 */

static void gprs_uart_shutdown(struct uart_port *port)

{

rx_enabled(port) = 0;????????????????/* 設置串口為不允許接收????*/

free_irq(RX_IRQ(port), port);????????/* 釋放接收中斷????*/

tx_enabled(port) = 0;????????????????/* 設置串口為不允許發送????*/

free_irq(TX_IRQ(port), port);????????/* 釋放發送中斷????*/

}

/* 設置串口參數 */

static void gprs_uart_set_termios(struct uart_port *port,

struct ktermios *termios,

struct ktermios *old)

{

unsigned long flags;

unsigned int baud, quot;

unsigned int ulcon, ufcon = 0;

/* 不支持moden控制信號線

* HUPCL:????關閉時掛斷moden

* CMSPAR:????mark or space (stick) parity

* CLOCAL:????忽略任何moden控制線

*/

termios->c_cflag &= ~(HUPCL | CMSPAR);

termios->c_cflag |= CLOCAL;

/* 獲取用戶設置的串口波特率,并計算分頻數(串口波特率除數quot) */

baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);

if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)

quot = port->custom_divisor;

else

quot = port->uartclk / baud / 16 - 1;

/* 設置數據字長 */

switch (termios->c_cflag & CSIZE)

{

case CS5:

ulcon = S3C2410_LCON_CS5;

break;

case CS6:

ulcon = S3C2410_LCON_CS6;

break;

case CS7:

ulcon = S3C2410_LCON_CS7;

break;

case CS8:

default:

ulcon = S3C2410_LCON_CS8;

break;

}

/* 是否要求設置兩個停止位(CSTOPB) */

if (termios->c_cflag & CSTOPB)

ulcon |= S3C2410_LCON_STOPB;

/* 是否使用奇偶檢驗 */

if (termios->c_cflag & PARENB)

{

if (termios->c_cflag & PARODD)??/* 奇校驗 */

ulcon |= S3C2410_LCON_PODD;

else????????????????????????????/* 偶校驗 */

ulcon |= S3C2410_LCON_PEVEN;

}

else????????????????????????????????/* 無校驗 */

{

ulcon |= S3C2410_LCON_PNONE;

}

if (port->fifosize > 1)

ufcon |= S3C2410_UFCON_FIFOMODE | S3C2410_UFCON_RXTRIG8;

spin_lock_irqsave(&port->lock, flags);

/* 設置FIFO控制寄存器、線控制寄存器和波特率除數寄存器 */

wr_regl(port, S3C2410_UFCON, ufcon);

wr_regl(port, S3C2410_ULCON, ulcon);

wr_regl(port, S3C2410_UBRDIV, quot);

/* 更新串口FIFO的超時時限 */

uart_update_timeout(port, termios->c_cflag, baud);

/* 設置我們感興趣的Rx error */

port->read_status_mask = S3C2410_UERSTAT_OVERRUN;

if (termios->c_iflag & INPCK)

port->read_status_mask |= S3C2410_UERSTAT_FRAME | S3C2410_UERSTAT_PARITY;

/* 設置我們忽略的Rx error */

port->ignore_status_mask = 0;

if (termios->c_iflag & IGNPAR)

port->ignore_status_mask |= S3C2410_UERSTAT_OVERRUN;

if (termios->c_iflag & IGNBRK && termios->c_iflag & IGNPAR)

port->ignore_status_mask |= S3C2410_UERSTAT_FRAME;

/* 若未設置CREAD(使用接收器),則忽略所有Rx error*/

if ((termios->c_cflag & CREAD) == 0)

port->ignore_status_mask |= RXSTAT_DUMMY_READ;

spin_unlock_irqrestore(&port->lock, flags);

}

/* 獲取串口類型 */

static const char *gprs_uart_type(struct uart_port *port)

{/* 返回描述串口類型的字符串指針 */

return port->type == PORT_S3C2410 ? "gprs_uart:s3c2410_uart2" : NULL;

}

/* 申請串口一些必要的資源,如IO端口/IO內存資源,必要時還可以重新映射串口端口 */

static int gprs_uart_request_port(struct uart_port *port)

{

struct resource *res;

const char *name = to_platform_device(port->dev)->name;

/* request_mem_region請求分配IO內存,從開始port->mapbase,大小MAP_SIZE

* port->mapbase保存當前串口的寄存器基地址(物理)

* uart2: 0x50008000

*/

res = request_mem_region(port->mapbase, MAP_SIZE, name);

if (res == NULL)

{

printk(KERN_ERR"request_mem_region error: %p\n", res);

return -EBUSY;

}

return 0;

}

/* 釋放串口已申請的IO端口/IO內存資源,必要時還需iounmap */

static void gprs_uart_release_port(struct uart_port *port)

{

/* 釋放已分配IO內存 */

release_mem_region(port->mapbase, MAP_SIZE);

}

/* 執行串口所需的自動配置 */

static void gprs_uart_config_port(struct uart_port *port, int flags)

{

int retval;

/* 請求串口 */

retval = gprs_uart_request_port(port);

/* 設置串口類型 */

if (flags & UART_CONFIG_TYPE && retval == 0)

port->type = PORT_S3C2410;

}

/* The UART operations structure */

static struct uart_ops gprs_uart_ops = {

.start_tx????????= gprs_uart_start_tx,??????/* Start transmitting */

.stop_tx????????= gprs_uart_stop_tx,????????/* Stop transmission */

.stop_rx????????= gprs_uart_stop_rx,????????/* Stop reception */

.enable_ms????????= gprs_uart_enable_ms,????/* Enable modem status signals */

.tx_empty????????= gprs_uart_tx_empty,??????/* Transmitter busy? */

.get_mctrl????????= gprs_uart_get_mctrl,????/* Get modem control */

.set_mctrl????????= gprs_uart_set_mctrl,????/* Set modem control */

.break_ctl????????= gprs_uart_break_ctl,????/* Set break signal */

.startup????????= gprs_uart_startup,????????/* App opens GPRS_UART */

.shutdown????????= gprs_uart_shutdown,??????/* App closes GPRS_UART */

.set_termios????= gprs_uart_set_termios,????/* Set termios */

.type????????????= gprs_uart_type,??????????/* Get UART type */

.request_port????= gprs_uart_request_port,??/* Claim resources associated with a GPRS_UART port */

.release_port????= gprs_uart_release_port,??/* Release resources associated with a GPRS_UART port */

.config_port????= gprs_uart_config_port,????/* Configure when driver adds a GPRS_UART port */

};

/* Uart driver for GPRS_UART */

static struct uart_driver gprs_uart_driver = {

.owner = THIS_MODULE,????????????????/* Owner */

.driver_name = DEV_NAME,?????????????/* Driver name */

.dev_name = DEV_NAME,????????????????/* Device node name */

.major = GPRS_UART_MAJOR,????????????/* Major number */

.minor = GPRS_UART_MINOR,????????????/* Minor number start */

.nr = 1,???????????????????????????? /* Number of UART ports */

};

/* Uart port for GPRS_UART port */

static struct uart_port gprs_uart_port = {

.irq????????= IRQ_S3CUART_RX2,???????????/* IRQ */

.fifosize????= GPRS_UART_FIFO_SIZE,??????/* Size of the FIFO */

.iotype????????= UPIO_MEM,???????????????/* IO memory */

.flags????????= UPF_BOOT_AUTOCONF,???????/* UART port flag */

.ops????????= &gprs_uart_ops,????????????/* UART operations */

.line????????= 0,????????????????????????/* UART port number */

.lock????????= __SPIN_LOCK_UNLOCKED(gprs_uart_port.lock),

};

/* 初始化指定串口端口 */

static int gprs_uart_init_port(struct uart_port *port, struct platform_device *platdev)

{

unsigned long flags;

unsigned int gphcon;

if (platdev == NULL)

return -ENODEV;

port->dev????????= &platdev->dev;

/* 設置串口波特率時鐘頻率 */

port->uartclk????= clk_get_rate(clk_get(&platdev->dev, "pclk"));

/* 設置串口的寄存器基地址(物理): 0x50008000 */

port->mapbase????= S3C2410_PA_UART2;

/* 設置當前串口的寄存器基地址(虛擬): 0xF5008000 */

port->membase????= S3C24XX_VA_UART + (S3C2410_PA_UART2 - S3C24XX_PA_UART);

spin_lock_irqsave(&port->lock, flags);

wr_regl(port, S3C2410_UCON, S3C2410_UCON_DEFAULT);

wr_regl(port, S3C2410_ULCON, S3C2410_LCON_CS8 | S3C2410_LCON_PNONE);

wr_regl(port, S3C2410_UFCON, S3C2410_UFCON_FIFOMODE

| S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_RESETBOTH);

/* 將I/O port H的gph6和gph7設置為TXD2和RXD2 */

gphcon = readl(S3C2410_GPHCON);

gphcon &= ~((0x5) << 12);

writel(gphcon, S3C2410_GPHCON);

spin_unlock_irqrestore(&port->lock, flags);

return 0;

}

/* Platform driver probe */

static int __init gprs_uart_probe(struct platform_device *dev)

{

int ret;

/* 初始化串口 */

ret = gprs_uart_init_port(&gprs_uart_port, dev);

if (ret < 0)

{

printk(KERN_ERR"gprs_uart_probe: gprs_uart_init_port error: %d\n", ret);

return ret;

}

/* 添加串口 */

ret = uart_add_one_port(&gprs_uart_driver, &gprs_uart_port);

if (ret < 0)

{

printk(KERN_ERR"gprs_uart_probe: uart_add_one_port error: %d\n", ret);

return ret;

}

/* 將串口uart_port結構體保存在platform_device->dev->driver_data中 */

platform_set_drvdata(dev, &gprs_uart_port);

return 0;

}

/* Called when the platform driver is unregistered */

static int gprs_uart_remove(struct platform_device *dev)

{

platform_set_drvdata(dev, NULL);

/* 移除串口 */

uart_remove_one_port(&gprs_uart_driver, &gprs_uart_port);

return 0;

}

/* Suspend power management event */

static int gprs_uart_suspend(struct platform_device *dev, pm_message_t state)

{

uart_suspend_port(&gprs_uart_driver, &gprs_uart_port);

return 0;

}

/* Resume after a previous suspend */

static int gprs_uart_resume(struct platform_device *dev)

{

uart_resume_port(&gprs_uart_driver, &gprs_uart_port);

return 0;

}

/* Platform driver for GPRS_UART */

static struct platform_driver gprs_plat_driver = {

.probe = gprs_uart_probe,????????????????/* Probe method */

.remove = __exit_p(gprs_uart_remove),????/* Detach method */

.suspend = gprs_uart_suspend,????????????/* Power suspend */

.resume = gprs_uart_resume,????????????? /* Resume after a suspend */

.driver = {

.owner????= THIS_MODULE,

.name = DEV_NAME,????????????????????/* Driver name */

},

};

/* Platform device for GPRS_UART */

struct platform_device *gprs_plat_device;

static int __init gprs_init_module(void)

{

int retval;

/* Register uart_driver for GPRS_UART */

retval = uart_register_driver(&gprs_uart_driver);

if (0 != retval)

{

printk(KERN_ERR "gprs_init_module: can't register the GPRS_UART driver %d\n", retval);

return retval;

}

/* Register platform device for GPRS_UART. Usually called

during architecture-specific setup */

gprs_plat_device = platform_device_register_simple(DEV_NAME, 0, NULL, 0);

if (IS_ERR(gprs_plat_device))

{

retval = PTR_ERR(gprs_plat_device);

printk(KERN_ERR "gprs_init_module: can't register platform device %d\n", retval);

goto fail_reg_plat_dev;

}

/* Announce a matching driver for the platform

devices registered above */

retval = platform_driver_register(&gprs_plat_driver);

if (0 != retval)

{

printk(KERN_ERR "gprs_init_module: can't register platform driver %d\n", retval);

goto fail_reg_plat_drv;

}

return 0; /* succeed */

fail_reg_plat_drv:

platform_device_unregister(gprs_plat_device);

fail_reg_plat_dev:

uart_unregister_driver(&gprs_uart_driver);

return retval;

}

static void __exit gprs_exit_module(void)

{

/* The order of unregistration is important. Unregistering the

UART driver before the platform driver will crash the system */

/* Unregister the platform driver */

platform_driver_unregister(&gprs_plat_driver);

/* Unregister the platform devices */

platform_device_unregister(gprs_plat_device);

/* Unregister the GPRS_UART driver */

uart_unregister_driver(&gprs_uart_driver);

}

module_init(gprs_init_module);

module_exit(gprs_exit_module);

MODULE_AUTHOR("lingd");

MODULE_LICENSE("Dual BSD/GPL");

總結

以上是生活随笔為你收集整理的linux驱动向不同串口发数据,Linux串口(serial、uart)驱动程序设计的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

视频三区| 日日夜夜中文字幕 | 中文永久免费观看 | 五月天色婷婷丁香 | 高潮久久久久久久久 | 日韩免费视频 | 日本99久久 | 久草在线播放视频 | 97电院网手机版 | 国产精品一区二区在线播放 | 色福利网 | 天天插天天干天天操 | 国产手机在线精品 | 五月花丁香婷婷 | 9久久精品 | 在线天堂中文在线资源网 | 激情自拍av| 日日草视频 | 日韩精品黄 | 久久少妇av | 91亚洲精品久久久蜜桃借种 | 国产91精品一区二区麻豆亚洲 | 丝袜美腿av| 国产精品毛片久久久久久久久久99999999 | 国产91精品久久久久 | 韩国精品视频在线观看 | 美女在线观看av | 亚洲成人999 | 国产黄色片久久久 | www.激情五月.com| 久久成人精品视频 | 午夜三级理论 | 国产 精品 资源 | 中文字幕久久网 | 探花视频免费观看 | 精品国产中文字幕 | 99久久精品国产欧美主题曲 | 黄色在线小网站 | 99久久精品国产一区二区成人 | 深夜国产在线 | 久久人人插 | 成人午夜电影免费在线观看 | 欧美性色综合网 | a在线免费 | 丁香婷婷综合激情五月色 | 中国一级片在线观看 | 免费看黄色小说的网站 | 国产中文字幕国产 | 成人国产一区二区 | 青春草免费在线视频 | 国内久久视频 | 91尤物国产尤物福利在线播放 | 免费一级特黄毛大片 | 久久99爱视频 | 日本一区二区三区视频在线播放 | 四虎最新域名 | 97涩涩视频 | 在线播放视频一区 | 天天做天天爱天天爽综合网 | 在线不卡中文字幕播放 | 在线免费观看黄网站 | 国产一级做a爱片久久毛片a | 久青草电影 | 日韩高清 一区 | av在线亚洲天堂 | 黄在线免费看 | 国产精品毛片 | 精品久久免费 | 99精品久久只有精品 | bbbbb女女女女女bbbbb国产 | 最近更新好看的中文字幕 | 激情综合网五月婷婷 | 天堂网av在线 | 在线有码中文 | 国产97免费 | 欧美亚洲国产精品久久高清浪潮 | 久久综合网色—综合色88 | 九色最新网址 | 黄色三级网站 | 日韩亚洲在线 | 中文字幕韩在线第一页 | 99久久婷婷国产一区二区三区 | 亚洲综合视频在线 | 国产精品免费一区二区 | 日韩电影在线观看一区二区 | 精品美女在线视频 | 国产在线不卡精品 | 在线黄av | 在线免费视频一区 | 国产精品久久精品国产 | 97色在线观看 | 在线之家官网 | 国产一区精品在线 | 亚洲三级国产 | 麻豆91小视频 | 肉色欧美久久久久久久免费看 | 久久免费黄色 | 久久精品国产免费看久久精品 | 国产精品女人网站 | 国产一区二区在线免费观看 | 婷婷丁香视频 | 欧美 日韩 性 | 国产一区二区在线播放 | 欧美少妇18p | 美女av免费 | 亚洲精品国产欧美在线观看 | 国产黄a三级 | 欧美做受高潮电影o | 999在线观看视频 | 国产精品涩涩屋www在线观看 | 亚洲黄色一级视频 | 亚洲国产高清视频 | 97超碰人人干 | 亚洲日本色 | 中文字幕日韩国产 | 麻豆成人在线观看 | 成人av在线直播 | 91av在线视频播放 | 成人国产一区 | 日韩中文久久 | 中文字幕传媒 | 天天爽天天射 | 狠狠插狠狠干 | 久久国产片 | 二区视频在线观看 | www.看片网站 | 久久99精品久久只有精品 | 51久久夜色精品国产麻豆 | 精品久久久免费视频 | 狠狠色噜噜狠狠狠 | 91免费观看国产 | av电影在线播放 | 欧美色图一区 | 成人午夜剧场在线观看 | 99国产在线观看 | 国产精品视频久久 | 色94色欧美 | 国产一级片观看 | 91视频亚洲 | 亚洲精品1区2区3区 超碰成人网 | 91色综合 | 久久首页 | 91中文字幕| 狠狠的干狠狠的操 | 国产日韩中文字幕 | 韩国av电影在线观看 | 丁香高清视频在线看看 | 久久久久免费精品视频 | 亚洲精品在线观看av | 日本中文字幕电影在线免费观看 | 国产99爱 | 岛国一区在线 | 国产成人一二片 | 日本中文字幕在线视频 | 久久优 | 国产男女免费完整视频 | 狠狠色伊人亚洲综合网站色 | 欧美日韩另类在线观看 | 人人爽爽人人 | 成人亚洲综合 | 天天色综合三 | 91看毛片 | 欧美一级专区免费大片 | 欧美动漫一区二区三区 | 久久九九精品 | 成人动漫视频在线 | 国产精品第二页 | 国内精品久久久久久 | 青青河边草手机免费 | 天天干天天做天天爱 | 成人免费在线电影 | 99久久99久久精品免费 | 久久久久国产视频 | 麻豆精品视频 | 天天干,天天射,天天操,天天摸 | 一区免费视频 | 日本精品视频免费 | 在线免费av网站 | 97超碰福利久久精品 | 国产精品一区专区欧美日韩 | 色播五月婷婷 | 日韩精品1区2区 | 免费看国产一级片 | 欧美日韩在线视频一区二区 | 国产精品嫩草影院99网站 | 一区二区三区手机在线观看 | 国产精品97| 免费在线黄色av | 国产亚洲精品久久久久久无几年桃 | 久久手机精品视频 | 欧美日韩性 | www国产亚洲 | 日韩一级成人av | 中文在线www| 精品国产诱惑 | 国产精品欧美久久久久无广告 | 精品国产网址 | 欧美日韩国产免费视频 | 日本午夜在线观看 | 午夜丰满寂寞少妇精品 | 欧美一二三视频 | 91精品黄色 | 三级视频日韩 | 99热这里只有精品1 av中文字幕日韩 | 91在线麻豆 | 国产精品成人一区二区三区吃奶 | 色婷婷福利| 成人国产精品av | 日本黄色免费观看 | 国产成人精品一区二 | 久久毛片视频 | 91免费版在线观看 | 亚洲精品中文字幕视频 | 国产探花视频在线播放 | www.天天综合 | 亚洲精品久久久久999中文字幕 | 亚洲精品456在线播放第一页 | 国产午夜精品视频 | 婷婷在线视频 | 在线免费观看国产 | 国产高清区 | 最近最新mv字幕免费观看 | 亚洲激情综合 | 91九色视频观看 | 国产va饥渴难耐女保洁员在线观看 | 91在线最新| 日韩精品久久一区二区三区 | 制服丝袜欧美 | 久久精品一二区 | 五月激情亚洲 | 99中文字幕 | 亚洲国产成人精品电影在线观看 | 久久免费播放 | 在线免费性生活片 | 国产一区久久 | 日韩在线大片 | 国产高清免费在线观看 | 久久久在线视频 | 丁香色天天 | 麻豆系列在线观看 | 一区二区三区免费在线观看视频 | 2018亚洲男人天堂 | 香蕉精品视频在线观看 | 久久精品一二区 | 在线观看av网 | 日韩美一区二区三区 | 丁香花在线视频观看免费 | 91精品伦理 | 久久高清av | 亚洲黄色av| 午夜精品久久久久99热app | 日韩av影片在线观看 | 亚洲第一区在线观看 | 日日夜夜狠狠干 | 中文在线8资源库 | 在线观看精品视频 | 久久9精品 | 麻豆94tv免费版 | 成人在线中文字幕 | www国产精品com | 中文字幕丝袜美腿 | 人人爽人人| 99麻豆久久久国产精品免费 | 久久精品成人热国产成 | 韩日精品在线观看 | 国产在线第三页 | 一区二区三区四区在线免费观看 | 国产字幕在线观看 | 久久人人爽av | 中文字幕亚洲情99在线 | 久久久久亚洲精品男人的天堂 | 欧美一区二区伦理片 | 国产中文a | 婷婷午夜 | 国内精品久久久久影院一蜜桃 | 91最新中文字幕 | 欧美最猛性xxxxx免费 | 九九热只有这里有精品 | 97超碰在线播放 | 91视频 - x99av | 日韩视频欧美视频 | 美女网站久久 | 精品久久久精品 | 久久中文字幕视频 | 亚洲第一香蕉视频 | 成人全视频免费观看在线看 | 另类老妇性bbwbbw高清 | 中文字幕亚洲欧美日韩 | 激情久久综合网 | 97成人在线观看视频 | 日本久草电影 | 久久一级电影 | 91香蕉亚洲精品 | 狠狠gao| 国产手机视频在线 | 四虎永久免费在线观看 | 欧洲亚洲精品 | 91在线www | 国产精品久久久久久久久久了 | 欧美精品v国产精品 | 国产视频一区精品 | 免费视频一二三区 | 免费av网站在线看 | 91在线精品视频 | 女人高潮一级片 | 色婷婷视频在线 | 狠狠五月婷婷 | 久久精品爱爱视频 | 日韩国产欧美在线视频 | av资源在线观看 | 国产大尺度视频 | 国产精品福利午夜在线观看 | 免费看毛片网站 | 97久久久免费福利网址 | 亚洲黄色大片 | 久久超碰97 | 99 国产精品 | 天天操夜夜操天天射 | 久久久久国产成人精品亚洲午夜 | 曰本三级在线 | 天天狠狠 | 国产日韩中文字幕 | 97人人爽| 久久9999久久| 最近2019中文免费高清视频观看www99 | 一级片视频在线 | 精品视频久久久 | 国产丝袜制服在线 | 亚洲另类视频在线观看 | av中文天堂在线 | 亚州人成在线播放 | 欧洲成人免费 | 黄色毛片在线观看 | 欧美激情精品久久 | 日本精品视频在线观看 | 国产一二三区在线观看 | 亚洲最大激情中文字幕 | 在线视频观看91 | 日日夜夜添 | av线上看 | 国产高清视频在线播放一区 | 久久福利小视频 | 久久视奸| 中文字幕中文字幕在线中文字幕三区 | 欧美性另类 | 日韩成人免费在线观看 | 日本精品视频在线播放 | 天天操天天操天天操天天操天天操天天操 | 色视频网站免费观看 | 夜夜躁日日躁狠狠久久av | av在线免费在线观看 | 狠狠干 狠狠操 | 天天摸日日摸人人看 | www.com在线观看 | 狠狠躁夜夜躁人人爽视频 | 狠狠色丁香九九婷婷综合五月 | 国产亚洲精品久久19p | 婷婷丁香在线视频 | 在线亚洲成人 | 五月天中文字幕mv在线 | 免费在线观看国产精品 | 久草在线免费在线观看 | 亚洲精品综合一区二区 | 天天射天天舔天天干 | 视频在线在亚洲 | 成人a视频| 久久天堂精品视频 | 婷婷四房综合激情五月 | 国产精品一区二区免费视频 | 久久免费毛片视频 | 亚洲精品国产精品国自产观看浪潮 | 久久免费看 | 久久久久久免费视频 | 成人在线观看影院 | 美女黄久久| 激情婷婷丁香 | 精品国产一二区 | 亚洲高清免费在线 | 日韩午夜剧场 | 91国内产香蕉 | 成人久久18免费网站 | 午夜视频免费播放 | 亚洲精品88欧美一区二区 | 精品福利国产 | 久久中文欧美 | 精品国产乱码一区二区三区在线 | 成年人视频在线免费 | 国产手机在线观看视频 | 中文字幕中文字幕在线一区 | 国产精品嫩草影院123 | 国产在线污 | 国产一级做a | 国产精品成 | 91精品国产欧美一区二区成人 | 久热免费 | 成人影片在线播放 | 国产精品 中文字幕 亚洲 欧美 | 欧美精品一区二区在线播放 | 欧美乱码精品一区二区 | 成人三级视频 | 麻豆视频免费在线播放 | 日韩一二三在线 | 在线 高清 中文字幕 | 成人av一区二区兰花在线播放 | 久久成人福利 | 欧美色888| 96国产在线 | 成人黄色大片在线免费观看 | 午夜久久成人 | 国产黄色大片 | 免费在线观看成人av | 成人资源在线播放 | 日日骑 | 精品国产欧美一区二区三区不卡 | 日本黄色一级电影 | 夜夜嗨av色一区二区不卡 | 在线 成人 | 五月天丁香亚洲 | 超碰97在线资源 | 天天射天天色天天干 | 免费色视频 | 久久综合射 | 中国一级片在线播放 | 欧美日韩一区三区 | 国产亚洲精品中文字幕 | 国产精品黄色在线观看 | 狠狠躁日日躁 | 久久国产亚洲精品 | 亚洲一区天堂 | 天天操天天色天天 | 天天操夜夜叫 | 视频精品一区二区三区 | 婷婷视频在线观看 | 97韩国电影| 国内精品久久久精品电影院 | 国产成人久久精品77777 | 激情综合色播五月 | 综合色中色 | 色资源网在线观看 | 日韩在线视频免费观看 | 91探花在线视频 | 中文字幕制服丝袜av久久 | 狠狠色丁香久久婷婷综 | 色资源在线 | 在线观看亚洲a | 96超碰在线 | 免费观看一级特黄欧美大片 | 国产不卡av在线播放 | 国产精品欧美久久久久无广告 | 成人黄色大片在线免费观看 | 亚洲欧美视频网站 | 日韩午夜一级片 | 日韩精品免费 | 黄色小说免费在线观看 | 久久这里精品视频 | 欧美-第1页-屁屁影院 | 免费看在线看www777 | 黄色av三级在线 | 亚州中文av | 国产破处精品 | 久久视频一区 | av三级在线播放 | 久久综合给合久久狠狠色 | 久久99精品国产91久久来源 | 国产精品99精品久久免费 | 国内丰满少妇猛烈精品播 | 一区二区影视 | 美女视频黄是免费的 | 国产精品一区二区三区99 | 日韩欧美一区二区在线播放 | 五月婷婷在线播放 | 成人黄色小说网 | 91视频高清 | a在线视频v视频 | 在线欧美a | 日韩成人高清在线 | 国产精品一区二区三区久久 | 啪啪免费观看网站 | 欧美亚洲专区 | 黄色成人在线 | 精品国产一区二区三区四区vr | 国产999精品久久久久久 | 亚洲精品视频一 | 91传媒在线播放 | 久久久亚洲麻豆日韩精品一区三区 | 一区二区三区四区在线免费观看 | 奇米777777| 亚洲精选国产 | 在线观看中文字幕av | 久久久久婷 | 91色偷偷 | 亚洲精品免费在线视频 | 99精品免费视频 | 一区二区三区视频 | 久久久久这里只有精品 | 成人黄色中文字幕 | 激情综合网五月激情 | 国产一卡久久电影永久 | 日韩a级免费视频 | 天天干视频在线 | 久久 国产一区 | 中文字幕888 | 91欧美日韩国产 | 国产爽妇网 | 国产精品午夜在线观看 | 成人在线一区二区三区 | 中文字幕九九 | 黄色www免费 | 天天天天天天操 | 国产精品大片在线观看 | 2023亚洲精品国偷拍自产在线 | 视频 国产区 | 亚洲天天在线日亚洲洲精 | 婷婷丁香色综合狠狠色 | 久久视频 | 黄色小说免费在线观看 | 天天干天天干天天干天天干天天干天天干 | 在线观看国产一区二区 | 亚洲无在线 | av综合在线观看 | 免费黄色网址大全 | 最近日本mv字幕免费观看 | 97在线影院 | 在线a人v观看视频 | 精品欧美一区二区精品久久 | 狠狠久久婷婷 | 免费高清在线一区 | 激情丁香久久 | 日韩精品欧美一区 | 成人免费观看网站 | 久久一线 | 91激情小视频 | 五月婷婷中文字幕 | 99视频免费 | 黄色毛片在线 | 亚洲一级电影 | 亚洲激情p | 国产在线a | 久久精品电影网 | 日本护士三级少妇三级999 | www免费在线观看 | 国产精品自拍在线 | 中文字幕在线观看一区二区三区 | 国产美女免费视频 | 在线观看久 | 天堂av影院 | 久草久草久草久草 | 天天干,天天插 | 精品国产三级a∨在线欧美 免费一级片在线观看 | av日韩av| 日黄网站 | a视频在线 | 国产香蕉视频 | 国产色视频123区 | 日韩精品一区二区三区高清免费 | 97网站| 免费人成网 | 伊人婷婷久久 | 中文字幕 第二区 | 亚洲国产片 | 91人人澡人人爽人人精品 | 国产精品视频区 | 黄色一二级片 | 免费看片网址 | 免费在线观看av网站 | 国产精品都在这里 | 色播激情五月 | 手机av在线不卡 | 亚洲狠狠丁香婷婷综合久久久 | 免费国产一区二区视频 | 久久精品国产久精国产 | 日韩免费 | 中文字幕久久精品亚洲乱码 | 91资源在线视频 | 国产成人亚洲在线电影 | 日韩视频欧美视频 | 高清国产午夜精品久久久久久 | 欧美另类z0zx | 五月天婷婷综合 | 国产色爽 | 九色视频网址 | 亚洲播放一区 | 九九九热精品免费视频观看 | 丁香在线观看完整电影视频 | 久久国产一区二区三区 | 天天做天天看 | 在线不卡中文字幕播放 | 超碰在线cao | 欧美日韩在线视频观看 | 一区二区三高清 | 国产高清一 | 综合网中文字幕 | 人人爱人人舔 | 亚洲视频h| 天操夜夜操 | 涩av在线| 亚洲激情 欧美激情 | 在线免费观看一区二区三区 | 美女国内精品自产拍在线播放 | 国产理论一区二区三区 | 国产精品午夜8888 | 日韩欧美一区二区三区免费观看 | 久久久免费观看完整版 | 欧美日韩中文在线视频 | 天天综合视频在线观看 | 69av久久| 亚洲在线免费视频 | 综合精品久久久 | 成年人app网址 | 91视频免费看网站 | 开心色激情网 | 免费色黄 | 欧美a在线免费观看 | 免费色av| 永久黄网站色视频免费观看w | 久久伦理 | 亚洲免费资源 | 免费观看国产成人 | av中文在线 | 成人欧美一区二区三区黑人麻豆 | 久久国产麻豆 | 九九天堂 | 97人人艹 | 国产黄色免费在线观看 | 久久久免费在线观看 | 在线观看黄 | 欧美黄网站 | 中文字幕亚洲精品日韩 | 午夜久久福利视频 | 亚洲春色综合另类校园电影 | avwww在线观看| 日韩av成人免费看 | www.天天操| 97电影在线看视频 | 九月婷婷人人澡人人添人人爽 | 国产97在线视频 | 手机在线小视频 | 中文字幕一区在线 | 中文一区二区三区在线观看 | 亚洲天天综合网 | 极品嫩模被强到高潮呻吟91 | 性色大片在线观看 | 午夜久久久影院 | 99久久日韩精品视频免费在线观看 | 亚洲.www | 免费黄在线看 | 天天爽天天射 | 日韩美女高潮 | 91 在线视频播放 | 中文字幕高清在线 | 黄色一级大片在线免费看产 | 99福利片| 欧美激情在线网站 | av福利电影| www.777奇米 | 黄色一区二区在线观看 | 午夜色大片在线观看 | 玖玖视频在线 | 91桃色视频 | 波多野结衣在线观看一区二区三区 | 欧美日韩精品二区第二页 | 久草视频免费播放 | 91丨九色丨国产在线观看 | 在线观看免费成人 | 三级黄色三级 | 午夜精品导航 | 国产精品一区二区三区在线免费观看 | 在线天堂中文www视软件 | 欧美一级在线观看视频 | 国产精品完整版 | 亚洲精品女 | 人人澡视频| 99福利影院| 国产黄色片一级三级 | 中文字幕在线免费观看 | 国产在线一卡 | 日韩精品电影在线播放 | 国产成人精品一区二区三区网站观看 | 久久一区精品 | 久久久久久黄色 | 亚洲激色 | 久久99精品久久久久婷婷 | 狠狠操狠狠插 | 国产999在线 | 99免在线观看免费视频高清 | 亚洲人xxx | 激情图片区 | 激情婷婷综合网 | 亚洲国产免费 | 久青草视频在线观看 | 久久精品79国产精品 | 天天在线操 | 丁香综合av | 欧美一二三四在线 | 日韩精品一区二区三区中文字幕 | 狠狠狠狠狠狠操 | 六月丁香婷 | 91看片看淫黄大片 | 最新中文字幕视频 | 在线亚洲欧美日韩 | 福利视频导航网址 | 青青草久草在线 | 精品视频久久久 | 日韩成人欧美 | 伊人午夜 | 亚洲人久久 | 欧美精品免费在线 | 精品国产一区二区三区久久 | 狠狠狠狠狠狠狠干 | 欧美精品一区二区三区四区在线 | 蜜臀av性久久久久av蜜臀妖精 | 婷婷电影在线观看 | 欧美精品免费一区二区 | 久久久人 | 亚洲一区二区视频在线 | 美女在线免费观看视频 | 亚洲精品乱码久久 | 十八岁以下禁止观看的1000个网站 | 免费在线国产黄色 | 精品一区电影 | 亚洲国产影院av久久久久 | 午夜视频色| 免费看污黄网站 | 日本久久视频 | 中文字幕大全 | 天天射狠狠干 | 国产一性一爱一乱一交 | 波多野结衣视频一区二区三区 | 国产中文字幕网 | 成人免费在线视频观看 | 中文国产字幕 | av日韩在线网站 | 日韩av中文 | 日韩大片在线免费观看 | 免费欧美 | 国产不卡精品视频 | 97在线视频网站 | 亚洲视频 视频在线 | 99精品视频在线观看播放 | 五月天电影免费在线观看一区 | 国产精品美女在线 | 亚洲欧美日韩一级 | 午夜av免费观看 | 亚洲情感电影大片 | 91麻豆精品久久久久久 | 日韩xxxx视频 | 色狠狠一区二区 | 超薄丝袜一二三区 | 波多野结衣资源 | 天天曰视频| 免费福利在线播放 | 欧美午夜视频在线 | 日本中文字幕在线免费观看 | 伊人永久在线 | 精品久久一区 | 成人在线网站观看 | 激情视频在线高清看 | 一区二区三区免费看 | 探花视频免费在线观看 | 欧美成人在线免费观看 | 狠狠网| 17婷婷久久www | 精品国产美女 | 911国产| 在线观看国产www | 国产手机在线播放 | 青春草免费在线视频 | 精品在线二区 | 操操操日日日干干干 | 久草热久草视频 | 欧美亚洲国产日韩 | 久久久国产精品一区二区三区 | 中文字幕第一页在线 | av成人免费在线看 | 国产裸体无遮挡 | 丁香电影小说免费视频观看 | 永久免费的啪啪网站免费观看浪潮 | 色婷婷啪啪免费在线电影观看 | 狠狠操电影网 | 丁香六月婷婷开心婷婷网 | 婷婷在线免费 | 天天射网站 | www.久久久com | 婷婷激情在线 | 五月婷婷激情综合网 | 国产精品久久久久久高潮 | 亚洲在线视频免费观看 | 狠狠干夜夜操天天爽 | 国产精品伦一区二区三区视频 | 激情视频二区 | 久久久在线 | 午夜av免费在线观看 | 日韩免费三级 | 亚洲免费婷婷 | 国产视频二区三区 | 97av影院 | 伊色综合久久之综合久久 | 免费视频在线观看网站 | 日本一区二区三区视频在线播放 | 狠狠色综合欧美激情 | 9999国产精品 | 日韩三级中文字幕 | 蜜臀av夜夜澡人人爽人人桃色 | 美女视频久久久 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 夜夜爽夜夜操 | 免费视频久久久久久久 | 九九免费在线视频 | 免费视频色 | 黄色的视频网站 | 久久香蕉电影网 | 人人要人人澡人人爽人人dvd | 97国产在线播放 | 四虎影视成人永久免费观看视频 | 亚洲精品久久久久久久蜜桃 | 日躁夜躁狠狠躁2001 | 亚洲欧美日韩在线看 | 狠狠色丁香婷婷综合欧美 | 国产999免费视频 | mm1313亚洲精品国产 | 久久国产网站 | 国产精品福利无圣光在线一区 | 日韩欧美一区二区三区免费观看 | 国产精品久久久久久av | 国产成人精品一区二区 | 天天艹天天干天天 | 亚洲精品国产日韩 | 成人毛片在线视频 | 国产中文视频 | 成人av网站在线 | 丁香在线观看完整电影视频 | 成人激情开心网 | 中文字幕在线观看不卡 | 欧美最猛性xxxxx亚洲精品 | 香蕉视频亚洲 | 亚洲激情久久 | 免费黄色网址大全 | 黄色软件网站在线观看 | 国产在线精品视频 | 99精品福利视频 | 2021国产精品视频 | 天天曰夜夜爽 | 九九免费在线观看 | 天天干天天看 | 中文字幕一二三区 | 日韩欧美国产视频 | 日韩欧美视频二区 | 天天射综合网站 | 国产免费精彩视频 | 免费视频成人 | 黄色软件在线观看视频 | 伊人激情综合 | 久久精品国产精品 | 探花视频免费在线观看 | 亚洲人成免费网站 | 中文日韩在线视频 | av黄色免费在线观看 | 国产一级片免费观看 | 夜夜操天天干, | 久久国产精品一区二区三区四区 | 天天做综合网 | 四虎在线免费观看 | 日本女人b | 天天狠狠干 | 99视频| 1区2区3区在线观看 三级动图 | 在线免费观看麻豆视频 | 国产专区一 | 麻豆91网站| 国产伦精品一区二区三区无广告 | 日本论理电影 | 三级动态视频在线观看 | 91麻豆精品91久久久久同性 | 免费电影一区二区三区 | 日韩精品一区二区三区电影 | 婷婷成人亚洲综合国产xv88 | av在线收看| 91完整版| 涩涩资源网 | 不卡在线一区 | 91在线国内视频 | 深爱激情五月婷婷 | 99热99| 黄色三级在线看 | 欧美另类高清 | 中文在线亚洲 | 麻豆成人网 | 999免费视频 | 亚洲黄网址 | 97视频免费在线 | 久久精品艹 | av福利电影 | av片在线看 | 狠狠色丁香婷婷综合 | 免费看精品久久片 | 91色在线观看 | 久久久国产精品一区二区三区 | 日韩久久久久久久久 | 日本黄色大片免费看 | 天天操天天能 | 久久毛片高清国产 | 久久久久久久国产精品视频 | 亚洲国产影院av久久久久 | 日韩激情视频在线 | 综合五月婷婷 | www.色婷婷 | 国产精品com| 国产视频精选在线 | 超碰在线亚洲 | 91桃花视频 | 中文在线字幕免费观看 | 久草精品视频 | 国产综合久久 | 黄网站色 | 永久免费的av电影 | 国产精品久久久久久影院 | 国产精品麻豆91 | 99av国产精品欲麻豆 | 欧美a影视| 国产亚洲高清视频 | 亚洲国产中文字幕在线观看 | 婷婷伊人综合亚洲综合网 | 国产伦精品一区二区三区四区视频 | 天天做日日做天天爽视频免费 | 五月婷婷久 | 国产91精品高清一区二区三区 | 久草久草久草久草 | 亚洲精品在 | 日韩激情第一页 | 日韩伦理一区二区三区av在线 | 色婷婷狠狠五月综合天色拍 | 国产裸体视频网站 | 国产成人性色生活片 | 999久久久欧美日韩黑人 | 欧美精品久久久久久久亚洲调教 | 一二三久久久 | 毛片3 | 免费观看视频黄 | 国产91精品看黄网站 | 亚洲精选视频免费看 | 午夜男人影院 | 国产日韩视频在线 | 91视频观看免费 | 国产小视频在线免费观看 | 草免费视频 | 国产黄色精品视频 | 日本黄色免费大片 | 日韩天天干 | 国产精品成人一区二区 | 日韩av成人 | 一区二区激情 | 激情综合婷婷 | 99久久精品国 | 久草精品网 | 亚洲精品乱码久久久久久按摩 | 在线色资源| 国产人成看黄久久久久久久久 | 天天操天天怕 | 国产精品99久久久久久武松影视 | 草久久精品 | 日韩欧美高清免费 | 六月激情久久 | 日日日天天天 | 91精品国产九九九久久久亚洲 | 亚洲欧洲中文日韩久久av乱码 | 欧美日韩在线免费视频 | av永久网址 | 久久久夜色 | 日韩精选在线 | 国产在线第三页 | 色国产在线 | 久久99亚洲网美利坚合众国 | 极品久久久久 | 69国产盗摄一区二区三区五区 | 日韩va欧美va亚洲va久久 | 欧美成a人片在线观看久 | 99精彩视频在线观看免费 | 国产精品久久久久国产a级 激情综合中文娱乐网 | 亚洲无吗视频在线 | 天天爱天天干天天爽 | 一区二区不卡视频在线观看 | av先锋影音少妇 | 国产亚洲视频在线观看 | 亚洲精品玖玖玖av在线看 | 中文字幕一区二区三 | 天天综合导航 | 久久999精品 | 成年人在线观看网站 | 丁香六月国产 | 在线观看成人毛片 | 日韩三级视频在线看 | 丁香一区二区 | 97爱| 国语精品久久 | 有码中文字幕在线观看 | 一区 二区电影免费在线观看 | 国产精成人品免费观看 | 伊人官网|