色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux SPI-NAND 驅動開發指南

嵌入式Linux那些事 ? 來源:嵌入式Linux那些事 ? 作者:嵌入式Linux那些事 ? 2023-03-06 10:11 ? 次閱讀

Linux SPI-NAND 驅動開發指南1 概述1.1 編寫目的1.2 適用范圍1.3 相關人員3 流程設計3.1 體系結構3.2 源碼結構3.3 關鍵數據定義3.3.1 flash 設備信息數據結構3.3.2 flash chip 數據結構3.3.3 aw_spinand_chip_request3.3.4 ubi_ec_hdr3.3.5 ubi_vid_hdr3.4 關鍵接口說明3.4.1 MTD 層接口3.4.1.1 aw_rawnand_mtd_erase3.4.1.2 aw_rawnand_mtd_read3.4.1.3 aw_rawnand_mtd_read_oob3.4.1.4 aw_rawnand_mtd_write3.4.1.5 aw_rawnand_mtd_write_oob3.4.1.6 aw_rawnand_mtd_block_isbad3.4.1.7 aw_rawnand_mtd_block_markbad3.4.2 物理層接口3.4.2.1 aw_spinand_chip_read_single_page3.4.2.3 aw_spinand_chip_erase_single_block3.4.2.4 aw_spinand_chip_isbad_single_block3.4.2.5 aw_spinand_chip_markbad_single_block4 模塊配置4.1 uboot 模塊配置4.2 kernel 模塊配置4.3 env.cfg

Linux SPI-NAND 驅動開發指南

1 概述

1.1 編寫目的

介紹 Sunxi SPINand mtd/ubi 驅動設計, 方便相關驅動和應用開發人員

1.2 適用范圍

本設計適用于所有 sunxi 平臺

1.3 相關人員

Nand 模塊開發人員,及應用開發人員等

2 術語、縮略語及概念

MTD:(Memory Technology device)是用于訪問存儲設備的 linux 子系統。本模塊是MTD 子系統的 flash 驅動部分

UBI:UBI 子系統是基于 MTD 子系統的,在 MTD 上實現 nand 特性的管理邏輯,向上屏蔽nand 的特性

壞塊 (Bad Block):制作工藝和 nand 本身的物理性質導致在出廠和正常使用過程中都會產生壞塊

3 流程設計

3.1 體系結構

NAND MTD/UBI 驅動主要包括 5 大組件,如下圖:

pYYBAGQFS9uAOr4ZAAGc7l0cECY377.png

圖 3-1: UBI 架構

說明:

MTD standard interface: 對接 MTD 層通用讀寫接口

FLASH bad block manager: 驅動層對 flash 壞塊的管理

FLASH SPL: 主要是實現讀寫 boot0、boot1,可用于 ioctl 對boot0、boot1 的升級

SECURESTORAGE:主要是給上層提供私有數據的管理 SPI:HOST端控制器層的實現。

3.2 源碼結構

kernel 源碼目錄:linux-5.4/drivers/mtd/awnand/spinand

.

├── Kconfig

├── Makefile

├── physic

│ ├── bbt.c

│ ├── cache.c

│ ├── core.c

│ ├── ecc.c

│ ├── id.c

│ ├── Makefile

│ ├── ops.c

│ └── physic.h

├── secure-storage.c

├── sunxi-common.c

├── sunxi-core.c

├── sunxi-debug.c

├── sunxi-nftl-core.c

└── sunxi-spinand.h

內核目錄下

`-- include

`-- linux

`-- mtd

|-- aw-spinand.h

3.3 關鍵數據定義

3.3.1 flash 設備信息數據結構

struct aw_spinand_phy_info {

const char *Model;

unsigned char NandID[MAX_ID_LEN];

unsigned int DieCntPerChip;

unsigned int BlkCntPerDie;

unsigned int PageCntPerBlk;

unsigned int SectCntPerPage;

unsigned int OobSizePerPage;

#define BAD_BLK_FLAG_MARK 0x03

#define BAD_BLK_FLAG_FRIST_1_PAGE 0x00

#define BAD_BLK_FLAG_FIRST_2_PAGE 0x01

#define BAD_BLK_FLAG_LAST_1_PAGE 0x02

#define BAD_BLK_FLAG_LAST_2_PAGE 0x03

int BadBlockFlag;

#define SPINAND_DUAL_READ BIT(0)

#define SPINAND_QUAD_READ BIT(1)

#define SPINAND_QUAD_PROGRAM BIT(2)

#define SPINAND_QUAD_NO_NEED_ENABLE BIT(3)

#define SPINAND_ONEDUMMY_AFTER_RANDOMREAD BIT(8)

int OperationOpt;

int MaxEraseTimes;

#define HAS_EXT_ECC_SE01 BIT(0)

#define HAS_EXT_ECC_STATUS BIT(1)

enum ecc_status_shift ecc_status_shift;

int EccFlag;

enum ecc_limit_err EccType;

enum ecc_oob_protected EccProtectedType;

};

說明:

? Model:flash 的 model 名字

? NandID:flash 的 id 碼

? DieCntPerChip:每 chip 的 die 個數

? BlkCntPerDie:每 die 有多少個 block

? PageCntPerBlk:每 block 有多少個 page

? SectCntPerPage:每 page 有多少個扇區

? OobSizePerPage:每 page 的 obb 大小

? BadBlockFlag:壞塊標志存放在每個 block 的那個 page 中

BAD_BLK_FLAG_FRIST_1_PAGE

BAD_BLK_FLAG_FIRST_2_PAGE

BAD_BLK_FLAG_LAST_1_PAGE

BAD_BLK_FLAG_LAST_2_PAGE

? OperationOpt:支持的操作

SPINAND_DUAL_READ

SPINAND_QUAD_READ

SPINAND_QUAD_PROGRAM

SPINAND_QUAD_NO_NEED_ENABLE

SPINAND_ONEDUMMY_AFTER_RANDOMREAD

? MaxEraseTimes:最大擦除數據

? EccFlag:特性物料讀 ecc status 說需目錄不同

? GD5F1GQ4UCYIG 通過 0Fh + C0h 獲取 ecc status,則無需配置 EccFlag

? MX35LF1GE4AB 通過 7Ch + one dummy byte 獲取 ecc status,則配置 EccFlag = HAS_EXT_ECC_STATUS

? EccType:設置 ecc 值對應的狀態關系

? EccProtectedType:在 spare 去選擇收 ecc 保護的 16byte 作為 oob 區

例(MX35LF2GE4AD):

{

.Model = "MX35LF2GE4AD",

.NandID = {0xc2, 0x26, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff},

.DieCntPerChip = 1,

.SectCntPerPage = 4,

.PageCntPerBlk = 64,

.BlkCntPerDie = 2048,

.OobSizePerPage = 64,

.OperationOpt = SPINAND_QUAD_READ | SPINAND_QUAD_PROGRAM | SPINAND_DUAL_READ,

.MaxEraseTimes = 65000,

.EccFlag = HAS_EXT_ECC_STATUS,

.EccType = BIT4_LIMIT5_TO_8_ERR9_TO_15,

.EccProtectedType = SIZE16_OFF4_LEN4_OFF8,

.BadBlockFlag = BAD_BLK_FLAG_FIRST_2_PAGE,

},

?

?

3.3.2 flash chip 數據結構

struct aw_spinand_chip {

struct aw_spinand_chip_ops *ops;

struct aw_spinand_ecc *ecc;

struct aw_spinand_cache *cache;

struct aw_spinand_info *info;

struct aw_spinand_bbt *bbt;

struct spi_device *spi;

unsigned int rx_bit;

unsigned int tx_bit;

unsigned int freq;

void *priv;

};

此結構定義了 flash chip 層的物理模型數據結構以及 chip 層對 flash 的操作接口。

? aw_spinand_chip_ops:flash 讀、寫、擦等操作接口

? aw_spinand_ecc:flash ecc 讀、寫和校驗操作接口

? aw_spinand_cache:對緩存 page 的管理,提高讀寫效率

? aw_spinand_info:flash ID、page size 等信息及獲取信息的操作接口

? aw_spinand_bbt:flash 壞塊表及管理等操作接口

? spi_device:spi 父設備的操作結構體

? rx_bit:讀狀態操作標志

? tx_bit:寫狀態操作標志

3.3.3 aw_spinand_chip_request

struct aw_spinand_chip_request {

unsigned int block;

unsigned int page;

unsigned int pageoff;

unsigned int ooblen;

unsigned int datalen;

void *databuf;

void *oobbuf;

unsigned int oobleft;

unsigned int dataleft;

};

操作目標結構體,改結構體填充我們待操作的 block 的那個 page 的多少偏移的數據

databuf/oobbuf

? block:待操作塊

? page:待操作頁

? pageoff:操作偏移

? ooblen:操作 oob 長度

? datalen:操作數據長度

? databuf:操作目標數據

? oobbuf:操作目標 oob

3.3.4 ubi_ec_hdr

struct ubi_ec_hdr {

__be32 magic;

__u8 version;

__u8 padding1[3];

__be64 ec; /* Warning: the current limit is 31-bit anyway! */

__be32 vid_hdr_offset;

__be32 data_offset;

__be32 image_seq;

__u8 padding2[32];

__be32 hdr_crc;

} __packed;

@magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)

@version: version of UBI implementation which is supposed to accept this UBI image

@padding1: reserved for future, zeroes

@ec: the erase counter

@vid_hdr_offset: where the VID header starts

@data_offset: where the user data start

@image_seq: image sequence number

@padding2: reserved for future, zeroes

@hdr_crc: erase counter header CRC checksum

EC: Erase Count,記錄塊的擦除次數,在 ubiattach 的時候指定一個 mtd,如果 PEB 上沒有

EC,則用平均的 EC 值,寫入 EC 值只有在擦除的時候才會增加 1

3.3.5 ubi_vid_hdr

struct ubi_vid_hdr {

__be32 magic;

__u8 version;

__u8 vol_type;

__u8 copy_flag;

__u8 compat;

__be32 vol_id;

__be32 lnum;

__u8 padding1[4];

__be32 data_size;

__be32 used_ebs;

__be32 data_pad;

__be32 data_crc;

__u8 padding2[4];

__be64 sqnum;

__u8 padding3[12];

__be32 hdr_crc;

} __packed;

@magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)

@version: UBI implementation version which is supposed to accept this UBI image(%UBI_VERSION)

@vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)

@copy_flag: if this logical eraseblock was copied from another physical eraseblock(for wear-leveling reasons)

@compat: compatibility of this volume(%0, %UBI_COMPAT_DELETE, %UBI_COMPAT_IGNORE,%UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)

@vol_id: ID of this volume

@lnum: logical eraseblock number

@padding1: reserved for future, zeroes

@data_size: how many bytes of data this logical eraseblock contains

@used_ebs: total number of used logical eraseblocks in this volume

@data_pad: how many bytes at the end of this physical eraseblock are not used

@data_crc: CRC checksum of the data stored in this logical eraseblock

@padding2: reserved for future, zeroes

@sqnum: sequence number

@padding3: reserved for future, zeroes

@hdr_crc: volume identifier header CRC checksum

參數說明

@sqnum 是創建此 VID 頭時的全局序列計數器的值。每次 UBI 寫一個新的 VID 頭到 flash 時,全局序列計數器都會增加,比如當它將一個邏輯的 eraseblock 映射到一個新的物理的 erase-block 時。全局序列計數器是一個無符號 64 位整數,我們假設它永遠不會溢出。@sqnum(序列號) 用于區分新舊版本的邏輯擦除塊。

有兩種情況,可能有多個物理 eraseblock 對應同一個邏輯 eraseblock,即在卷標識頭中有相同的 @vol_id@lnum 值。假設我們有一個邏輯的擦除塊 L,它被映射到物理的擦除塊 P。

因為 UBI 可以異步擦除物理上的擦除塊,所以可能出現以下情況:L 被異步擦除,所以 P 被安排擦除,然后 L 被寫入,即。映射到另一個物理的擦除塊 P1,所以 P1 被寫入,然后不干凈的重啟發生。結果-有兩個物理的 eraseblock P 和 P1 對應同一個邏輯的 eraseblock L。但是 P1 的序列號更大,所以 UBI 在連接 flash 時選擇 P1。

UBI 不時地將邏輯擦除塊移動到其他物理擦除塊,以達到損耗均衡的目的。例如,如果 UBI將 L 從 P 移動到 P1,在 P 被物理擦除之前會發生不干凈的重啟,有兩個物理擦除塊 P 和 P1 對應于 L, UBI 必須在 flash 連接時選擇其中一個。@sqnum 字段表示哪個 PEB 是原始的 (顯然 P 的 @sqnum 更低) 和副本。但是選擇具有更高序列號的物理擦除塊是不夠的,因為不干凈的重新引導可能發生在復制過程的中間,因此 P 中的數據被損壞(P->P1 沒復制完)。僅僅選擇序號較低的物理擦除塊是不夠的,因為那里的數據可能很舊 (考慮在復制之后向 P1 添加更多數據的情況)。此外,不干凈的重啟可能發生在擦除 P 剛剛開始的時候,所以它會導致不穩定的 P,“大部分” 是 OK 的,但仍然有不穩定的情況。

UBI 使用 @copy_flag 字段表示這個邏輯擦除塊是一個副本。UBI 還計算數據的 CRC,當數據被移動時,并將其存儲在副本 (P1) 的 @data_crc 字段。因此,當 UBI 需要從兩個 (P 或 P1)中選擇一個物理擦除塊時,會檢查新塊 (P1) 的 @copy_flag。如果它被清除,情況就簡單了,新的就會被選中。如果設置了該值,則檢查副本 (P1) 的數據 CRC。如果 CRC 校驗和是正確的,這個物理擦除塊被選中 (P1)。否則,將選擇較老的 P。如果是靜態卷,@data_crc 字段包含邏輯擦除塊內容的 CRC 校驗和。對于動態卷,它不包含 CRC 校驗和規則。唯一的例外情況是,當物理擦除塊的數據被磨損均衡子系統移動時,磨損均衡子系統計算數據 CRC,并將其存儲在 @data_crc 字段中。

@used_ebs 字段僅用于靜態卷,它表示該卷的數據需要多少個擦除塊。對于動態卷,這個字段不被使用并且總是包含 0。

@data_pad 在創建卷時使用對齊參數計算。因此,@data_pad 字段有效地減少了該卷的邏輯擦除塊的大小。當一個人在 UBI 卷上使用面向塊的軟件 (比如,cramfs) 時,這是非常方便的。

LEB PEB

poYBAGQFS9yANjNKAADUhxhfkK0422.png

圖 3-2: PEB-LEB

3.4 關鍵接口說明

3.4.1 MTD 層接口

3.4.1.1 aw_rawnand_mtd_erase

static int aw_rawnand_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)

description:mtd erase interface

@mtd:MTD device structure

@instr:erase operation descrition structure

return:success return 0,fail return fail code

3.4.1.2 aw_rawnand_mtd_read

static int aw_rawnand_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,size_t *retlen, u_char *buf)

description:mtd read interface

@mtd:MTD device structure

@from:offset to read from MTD device

@len: data len

@retlen:had read data len

@buf:data buffer

return:success return max_bitflips,fail return fail code

3.4.1.3 aw_rawnand_mtd_read_oob

static int aw_rawnand_mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)

description:mtd read data with oob

@mtd:MTD device structure

@ops:oob eperation descrition structure

return:success return max_bitflips,fail return fail code

3.4.1.4 aw_rawnand_mtd_write

static int aw_rawnand_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)

description:mtd write data interface

@to:offset to MTD device

@len:want write data len

@retlen:return the writen len

@buf:data buffer

return:success return 0, fail return code fail

3.4.1.5 aw_rawnand_mtd_write_oob

static int aw_rawnand_mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops * ops)

description:write data with oob

@mtd:MTD device structure

@to:offset to MTD device

@ops:oob operation descrition structure

return:success return 0, fail return code fail

3.4.1.6 aw_rawnand_mtd_block_isbad

static int aw_rawnand_mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)

description:check block is badblock or not

@mtd:MTD device structure

@ofs: offset the mtd device start (align to simu block size)

return:true if the block is bad, or false if the block is good

3.4.1.7 aw_rawnand_mtd_block_markbad

static int aw_rawnand_mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)

description:mark block at the given offset as bad block

@mtd:MTD device structure

@ofs:offset the mtd device start

return:success to mark return 0, or fail return fail code.

3.4.2 物理層接口

3.4.2.1 aw_spinand_chip_read_single_page

static int aw_spinand_chip_read_single_page(struct aw_spinand_chip *chip, struct aw_spinand_chip_request *req)

description:Read physics on a page

@chip:See 3.3.2

@req:See 3.3.3

return:zero on success, else a negative error code.

3.4.2.2 aw_spinand_chip_write_single_page

static int aw_spinand_chip_write_single_page(struct aw_spinand_chip *chip, struct aw_spinand_chip_request *req)

description:Write physics on a page

@chip:See 3.3.2

@req:See 3.3.3

return:zero on success, else a negative error code.

3.4.2.3 aw_spinand_chip_erase_single_block

static int aw_spinand_chip_erase_single_block(struct aw_spinand_chip *chip, struct aw_spinand_chip_request *req)

description:Erase physics on a block

@chip:See 3.3.2

@req: See 3.3.3

return:zero on success, else a negative error code.

3.4.2.4 aw_spinand_chip_isbad_single_block

static int aw_spinand_chip_isbad_single_block(struct aw_spinand_chip *chip, struct aw_spinand_chip_request *req)

description:Set to bad block

@chip:See 3.3.2

@req:See 3.3.3

return:zero on success, else a negative error code.

3.4.2.5 aw_spinand_chip_markbad_single_block

static int aw_spinand_chip_markbad_single_block(struct aw_spinand_chip *chip, struct aw_spinand_chip_request *req)

description:Set to bad block

@chip:See 3.3.2

@req:See 3.3.3

return:zero on success, else a negative error code.

4 模塊配置

4.1 uboot 模塊配置

Device Drivers-->Sunxi flash support--> [*]Support sunxi nand devices [*]Support sunxi nand ubifs devices [*]Support COMM NAND V1 interface

如下圖:

pYYBAGQFS9yAXDhCAAAz_JZAlXU846.png

圖 4-1: u-boot-spinand-menuconfig

4.2 kernel 模塊配置

Device Drivers->Memory Technology Device(MTD) support-->sunxi-nand

poYBAGQFS92ANQg5AAEZ9Ed3Q_g916.png

圖 4-2: UBI

pYYBAGQFS92AKrvyAAED-96owBU300.png

圖 4-3: ker_nand-cfg

poYBAGQFS96AMABLAAElogNJBT4742.png

圖 4-4: ker_spinand

Device Drivers->SPI support

pYYBAGQFS9-AVnVcAACzeLD7fio718.png

圖 4-5: spi-1

poYBAGQFS9-AZKCdAAE1nlU7xPI939.png

圖 4-6: spi-2

Device Drivers->DMA Engine support

pYYBAGQFS-CAKE0qAADhS4Lzrhk584.png

圖 4-7: DMA-1

poYBAGQFS-CAWGIFAAEo8Mauq04553.png

圖 4-8: DMA-2

Device Drivers->SOC(System On Chip)

pYYBAGQFS-KAWdEoAAEtqaXKh1g056.png

圖 4-9: SID

File systems-->Miscellaneous filesystems-->

poYBAGQFS-OAPidRAAH5yMnW5lQ768.png

圖 4-10: menuconfig_spinand_ubifs

4.3 env.cfg

在 env.cfg 中添加修改下值,setargs_nand_ubi 先 copy 一份 setargs_nand 再添加對應變量

pYYBAGQFS-OAXPXcAAB34Z9RiTo882.png

圖 4-11: build-mkcmd


審核編輯黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • NAND
    +關注

    關注

    16

    文章

    1683

    瀏覽量

    136197
  • 驅動
    +關注

    關注

    12

    文章

    1841

    瀏覽量

    85328
  • Linux
    +關注

    關注

    87

    文章

    11312

    瀏覽量

    209702
  • SPI
    SPI
    +關注

    關注

    17

    文章

    1707

    瀏覽量

    91675
收藏 人收藏

    評論

    相關推薦

    linux驅動開發指南基于arm9處理器

    linux驅動開發指南基于arm9處理器
    發表于 08-13 20:28

    【圖書分享】《Linux驅動開發指南——基于ARM9處理器》

    《嵌入式設計及Linux驅動開發指南——基于ARM9處理器》附件:
    發表于 03-18 17:21

    EAC0945 linux開發指南

    EAC0945 linux開發指南
    發表于 09-28 12:40

    EAC0945 linux開發指南

    `EAC0945 linux開發指南`
    發表于 10-31 12:18

    沒有SPI-Nand, NAND無法啟動怎么解決?

    沒有SPI-Nand, NAND 無法啟動
    發表于 09-06 06:24

    Tiny6410 Linux開發指南詳解

    Tiny6410 Linux 開發指南
    發表于 07-08 17:12 ?210次下載
    Tiny6410 <b class='flag-5'>Linux</b><b class='flag-5'>開發指南</b>詳解

    A64開發板LCD開發指南

    A64開發板LCD開發指南驅動開發指南
    發表于 06-21 17:02 ?0次下載

    S5P4418開發板GPS模塊驅動移植開發指南

    S5P4418開發板GPS模塊驅動移植開發指南
    發表于 06-21 17:02 ?0次下載

    Linux的平臺下Mini210S裸機程序開發指南

    Linux的平臺下Mini210S裸機程序開發指南
    發表于 10-29 10:52 ?59次下載
    <b class='flag-5'>Linux</b>的平臺下Mini210S裸機程序<b class='flag-5'>開發指南</b>

    Rockchip Linux SDK的開發指南的詳細資料說明

    本文檔的主要內容詳細介紹的是Rockchip Linux SDK的開發指南的詳細資料說明。
    發表于 01-10 17:17 ?74次下載
    Rockchip <b class='flag-5'>Linux</b> SDK的<b class='flag-5'>開發指南</b>的詳細資料說明

    Tina_Linux_系統軟件開發指南

    Tina_Linux_系統軟件開發指南
    的頭像 發表于 03-02 15:25 ?1839次閱讀
    Tina_<b class='flag-5'>Linux</b>_系統軟件<b class='flag-5'>開發指南</b>

    Tina Linux配置開發指南

    Tina Linux配置開發指南
    的頭像 發表于 03-02 15:28 ?1.6w次閱讀
    Tina <b class='flag-5'>Linux</b>配置<b class='flag-5'>開發指南</b>

    Linux NOR開發指南

    Linux NOR開發指南
    的頭像 發表于 03-06 09:55 ?975次閱讀
    <b class='flag-5'>Linux</b> NOR<b class='flag-5'>開發指南</b>

    Linux SPI開發指南

    介紹 SPI 模塊的使用方法,方便開發人員使用。
    的頭像 發表于 03-06 10:23 ?1577次閱讀
    <b class='flag-5'>Linux</b> <b class='flag-5'>SPI</b><b class='flag-5'>開發指南</b>

    迅為RK3568開發驅動開發指南-輸入子系統

    迅為RK3568開發驅動開發指南-輸入子系統
    的頭像 發表于 02-23 15:11 ?902次閱讀
    迅為RK3568<b class='flag-5'>開發</b>板<b class='flag-5'>驅動</b><b class='flag-5'>開發指南</b>-輸入子系統
    主站蜘蛛池模板: 色情内射少妇兽交| 一受多攻高h| freevideoshd| 色橹橹欧美在线观看视频高清 | 970女主播电台歌曲| 免费人成视频19674不收费| 扒开老师大腿猛进AAA片软件| 色迷迷电影| 国精产品一区二区三区| 综合久久伊人| 日本一本免费线观看视频| 国产免费阿v精品视频网址| 印度12 13free| 肉多的小说腐小说| 国产亚洲欧美ai在线看片| 777米奇影院第七色色| 人妻 中文无码 中出| 狠狠国产欧美在线视频| 99国内精品| 性按摩AAAAAAA片| 毛片在线网址| 国产福利视频一区二区| 一本色道久久88加勒比—综合| 琪琪婷婷五月色综合久久| 狠狠色狠狠色88综合日日91 | jlzzzjizzzjlzzz亚洲| 无码AV毛片色欲欧洲美洲| 两个女人互添下身高潮自视频| babesvideos欧美最新| 性色欲情网站IWWW| 欧美重口绿帽video| 狠狠色色综合站| 仓井空torrent| 亚洲一区二区免费看| 日韩精品无码久久一区二区三| 久久精品小视频| 国产高清免费观看| 99久久综合精品免费| 亚洲人成色777777老人头| 十大禁止安装的黄台有风险| 久久香蕉国产免费天天|