日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

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

linux

Linux platform总线(1):总体框架

發布時間:2025/3/21 linux 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux platform总线(1):总体框架 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • PlatForm設備驅動:??
  • 一、platform總線、設備與驅動??
  • 1.一個現實的Linux設備和驅動通常都需要掛接在一種總線上,對于本身依附于PCI、USB、I2?C、SPI等的設備而言,這自然不是問題,??
  • 但是在嵌入式系統里面,SoC系統中集成的獨立的外設控制器、掛接在SoC內存空間的外設等確不依附于此類總線。??
  • 基于這一背景,Linux發明了一種虛擬的總線,稱為platform總線,相應的設備稱為platform_device,而驅動成為?platform_driver。??
  • 2.注意,所謂的platform_device并不是與字符設備、塊設備和網絡設備并列的概念,而是Linux系統提供的一種附加手段,??
  • 例如,在?S3C6410處理器中,把內部集成的I2C、RTC、SPI、LCD、看門狗等控制器都歸納為platform_device,而它們本身就是字符設備。??
  • 3.基于Platform總線的驅動開發流程如下:??
  • (1)定義初始化platform?bus??
  • (2)定義各種platform?devices??
  • (3)注冊各種platform?devices??
  • (4)定義相關platform?driver??
  • (5)注冊相關platform?driver??
  • (6)操作相關設備??
  • 4.平臺相關結構??
  • //platform_device結構體??
  • struct?platform_device?{??
  • ?const?char?*?name;/*?設備名?*/??
  • ?u32?id;//設備id,用于給插入給該總線并且具有相同name的設備編號,如果只有一個設備的話填-1。??
  • ?struct?device?dev;//結構體中內嵌的device結構體。??
  • ?u32?num_resources;/*?設備所使用各類資源數量?*/??
  • ??struct?resource?*?resource;/*?//定義平臺設備的資源*/??
  • };??
  • //平臺資源結構??
  • struct?resource?{??
  • ?resource_size_t?start;?//定義資源的起始地址??
  • ?resource_size_t?end;?//定義資源的結束地址??
  • ?const?char?*name;?//定義資源的名稱??
  • ?unsigned?long?flags;?//定義資源的類型,比如MEM,IO,IRQ,DMA類型??
  • ?struct?resource?*parent,?*sibling,?*child;??
  • };??
  • //設備的驅動:platform_driver這個結構體中包含probe()、remove()、shutdown()、suspend()、?resume()函數,通常也需要由驅動實現。??
  • 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?pm_ext_ops?*pm;??
  • ?struct?device_driver?driver;??
  • };??
  • ???
  • //系統中為platform總線定義了一個bus_type的實例platform_bus_type,??
  • struct?bus_type?platform_bus_type?=?{??
  • ?.name?=?“platform”,??
  • ?.dev_attrs?=?platform_dev_attrs,??
  • ?.match?=?platform_match,??
  • ?.uevent?=?platform_uevent,??
  • ?.pm?=?PLATFORM_PM_OPS_PTR,??
  • };??
  • EXPORT_SYMBOL_GPL(platform_bus_type);??
  • ???
  • //這里要重點關注其match()成員函數,正是此成員表明了platform_device和platform_driver之間如何匹配。??
  • static?int?platform_match(struct?device?*dev,?struct?device_driver?*drv)??
  • {??
  • ?struct?platform_device?*pdev;??
  • ?pdev?=?container_of(dev,?struct?platform_device,?dev);??
  • ?return?(strncmp(pdev->name,?drv->name,?BUS_ID_SIZE)?==?0);??
  • }??
  • //匹配platform_device和platform_driver主要看二者的name字段是否相同。??
  • //對platform_device的定義通常在BSP的板文件中實現,在板文件中,將platform_device歸納為一個數組,最終通過platform_add_devices()函數統一注冊。??
  • //platform_add_devices()函數可以將平臺設備添加到系統中,這個函數的?原型為:??
  • int?platform_add_devices(struct?platform_device?**devs,?int?num);??
  • //該函數的第一個參數為平臺設備數組的指針,第二個參數為平臺設備的數量,它內部調用了platform_device_register()函?數用于注冊單個的平臺設備。??
  • 1.?platform?bus總線先被kenrel注冊。??
  • 2.?系統初始化過程中調用platform_add_devices或者platform_device_register,將平臺設備(platform?devices)注冊到平臺總線中(platform?bus)??
  • 3.?平臺驅動(platform?driver)與平臺設備(platform?device)的關聯是在platform_driver_register或者driver_register中實現,一般這個函數在驅動的初始化過程調用。??
  • 通過這三步,就將平臺總線,設備,驅動關聯起來。??
  • 二.Platform初始化??
  • 系統啟動時初始化時創建了platform_bus總線設備和platform_bus_type總線,platform總線是在內核初始化的時候就注冊進了內核。??
  • 內核初始化函數kernel_init()中調用了do_basic_setup()?,該函數中調用driver_init(),該函數中調用platform_bus_init(),我們看看platform_bus_init()函數:????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
  • int?__init?platform_bus_init(void)??
  • {??
  • ???????int?error;??
  • ???????early_platform_cleanup();?//清除platform設備鏈表??
  • ???????//該函數把設備名為platform?的設備platform_bus注冊到系統中,其他的platform的設備都會以它為parent。它在sysfs中目錄下.即?/sys/devices/platform。??
  • ???????//platform_bus總線也是設備,所以也要進行設備的注冊??
  • ???????//struct?device?platform_bus?=?{??
  • ???????//.init_name???????=?"platform",??
  • ????????//};??
  • ???????error?=?device_register(&platform_bus);//將平臺bus作為一個設備注冊,出現在device目錄???
  • ???????if?(error)??
  • ??????????????return?error;??
  • ???????//接著bus_register(&platform_bus_type)注冊了platform_bus_type總線.??
  • ???????/*?
  • ???????struct?bus_type?platform_bus_type?=?{?
  • ?????.name?=?“platform”,?
  • ?????.dev_attrs?=?platform_dev_attrs,?
  • ?????.match?=?platform_match,?
  • ?????.uevent?=?platform_uevent,?
  • ?????.pm?=?PLATFORM_PM_OPS_PTR,?
  • ????};?
  • ???????*/??
  • ???????//默認platform_bus_type中沒有定義probe函數。??
  • ???????error?=??bus_register(&platform_bus_type);//注冊平臺類型的bus,將出現在bus目錄下??
  • ???????if?(error)??
  • ??????????????device_unregister(&platform_bus);??
  • ???????return?error;??
  • }??
  • //總線類型match函數是在設備匹配驅動時調用,uevent函數在產生事件時調用。??
  • //platform_match函數在當屬于platform的設備或者驅動注冊到內核時就會調用,完成設備與驅動的匹配工作。??
  • static?int?platform_match(struct?device?*dev,?struct?device_driver?*drv)??
  • {??
  • ???????struct?platform_device?*pdev?=?to_platform_device(dev);??
  • ???????struct?platform_driver?*pdrv?=?to_platform_driver(drv);??
  • ???????/*?match?against?the?id?table?first?*/??
  • ???????if?(pdrv->id_table)??
  • ??????????????return?platform_match_id(pdrv->id_table,?pdev)?!=?NULL;??
  • ???????/*?fall-back?to?driver?name?match?*/??
  • ???????return?(strcmp(pdev->name,?drv->name)?==?0);//比較設備和驅動的名稱是否一樣??
  • }??
  • static?const?struct?platform_device_id?*platform_match_id(struct?platform_device_id?*id,struct?platform_device?*pdev)??
  • {??
  • ???????while?(id->name[0])?{??
  • ??????????????if?(strcmp(pdev->name,?id->name)?==?0)?{??
  • ?????????????????????pdev->id_entry?=?id;??
  • ?????????????????????return?id;??
  • ??????????????}??
  • ??????????????id++;??
  • ???????}??
  • ???????return?NULL;??
  • }??
  • //不難看出,如果pdrv的id_table數組中包含了pdev->name,或者drv->name和pdev->name名字相同,都會認為是匹配成功。??
  • //id_table數組是為了應對那些對應設備和驅動的drv->name和pdev->name名字不同的情況。??
  • //再看看platform_uevent()函數:platform_uevent?熱插拔操作函數??
  • static?int?platform_uevent(struct?device?*dev,?struct?kobj_uevent_env?*env)??
  • {??
  • ???????struct?platform_device???*pdev?=?to_platform_device(dev);??
  • ???????add_uevent_var(env,?"MODALIAS=%s%s",?PLATFORM_MODULE_PREFIX,?(pdev->id_entry)???pdev->id_entry->name?:?pdev->name);??
  • ???????return?0;??
  • }??
  • //添加了MODALIAS環境變量,我們回顧一下:platform_bus.?parent->kobj->kset->uevent_ops為device_uevent_ops,bus_uevent_ops的定義如下:??
  • static?struct?kset_uevent_ops?device_uevent_ops?=?{??
  • ???????.filter?=????dev_uevent_filter,??
  • ???????.name?=??????????dev_uevent_name,??
  • ???????.uevent?=?dev_uevent,??
  • };??
  • //當調用device_add()時會調用kobject_uevent(&dev->kobj,?KOBJ_ADD)產生一個事件,這個函數中會調用相應的kset_uevent_ops的uevent函數,??
  • 三.Platform設備的注冊??
  • 我們在設備模型的分析中知道了把設備添加到系統要調用device_initialize()和platform_device_add(pdev)函數。??
  • Platform設備的注冊分兩種方式:??
  • 1.對于platform設備的初注冊,內核源碼提供了platform_device_add()函數,輸入參數platform_device可以是靜態的全局設備,它是進行一系列的操作后調用device_add()將設備注冊到相應的總線(platform總線)上,??
  • 內核代碼中platform設備的其他注冊函數都是基于這個函數,如platform_device_register()、platform_device_register_simple()、platform_device_register_data()等。??
  • 2.另外一種機制就是動態申請platform_device_alloc()一個platform_device設備,然后通過platform_device_add_resources及platform_device_add_data等添加相關資源和屬性。??
  • 無論哪一種platform_device,最終都將通過platform_device_add這冊到platform總線上。??
  • 區別在于第二步:其實platform_device_add()包括device_add(),不過要先注冊resources,然后將設備掛接到特定的platform總線。??
  • 3.第一種平臺設備注冊方式??
  • //platform_device是靜態的全局設備,即platform_device結構的成員已經初始化完成??
  • //直接將平臺設備注冊到platform總線上??
  • /*platform_device_register和device_register的區別:?
  • (1).主要是有沒有resource的區別,前者的結構體包含后面,并且增加了struct?resource結構體成員,后者沒有。?
  • ??platform_device_register在device_register的基礎上增加了struct?resource部分的注冊。?
  • ??由此。可以看出,platform_device---paltform_driver_register機制與device-driver的主要區別就在于resource。?
  • ??前者適合于具有獨立資源設備的描述,后者則不是。?
  • (2).其實linux的各種其他驅動機制的基礎都是device_driver。只不過是增加了部分功能,適合于不同的應用場合.?
  • */??
  • int?platform_device_register(struct?platform_device?*pdev)??
  • {??
  • ?device_initialize(&pdev->dev);//初始化platform_device內嵌的device??
  • ?return?platform_device_add(pdev);//把它注冊到platform_bus_type上??
  • }??
  • int?platform_device_add(struct?platform_device?*pdev)??
  • {??
  • ??int?i,?ret?=?0;??
  • ??if?(!pdev)??
  • ????????return?-EINVAL;??
  • ??if?(!pdev->dev.parent)??
  • ???pdev->dev.parent?=?&platform_bus;//設置父節點,即platform_bus作為總線設備的父節點,其余的platform設備都是它的子設備??
  • ?????
  • ??//platform_bus是一個設備,platform_bus_type才是真正的總線???
  • ??pdev->dev.bus?=?&platform_bus_type;//設置platform總線,//指定bus類型為platform_bus_type???
  • ????
  • ??//設置pdev->dev內嵌的kobj的name字段,將platform下的名字傳到內部device,最終會//傳到kobj????
  • ??if?(pdev->id?!=?-1)??
  • ????????dev_set_name(&pdev->dev,?"%s.%d",?pdev->name,??pdev->id);??
  • ??else??
  • ????????dev_set_name(&pdev->dev,?"%s",?pdev->name);??
  • ????
  • ????
  • ??//初始化資源并將資源分配給它,每個資源的它的parent不存在則根據flags域設置parent,flags為IORESOURCE_MEM,??
  • ??//則所表示的資源為I/O映射內存,flags為IORESOURCE_IO,則所表示的資源為I/O端口。??
  • ??for?(i?=?0;?i?<?pdev->num_resources;?i++)?{??
  • ??????struct?resource?*p,?*r?=?&pdev->resource[i];??
  • ??????if?(r->name?==?NULL)//資源名稱為NULL則把設備名稱設置給它??
  • ????????r->name?=?dev_name(&pdev->dev);??
  • ???????????????
  • ??????p?=?r->parent;//取得資源的父節點,資源在內核中也是層次安排的??
  • ??????if?(!p)?{??
  • ?????????if?(resource_type(r)?==?IORESOURCE_MEM)?//如果父節點為NULL,并且資源類型為IORESOURCE_MEM,則把父節點設置為iomem_resource???
  • ???????????p?=?&iomem_resource;??
  • ?????????else?if?(resource_type(r)?==?IORESOURCE_IO)//否則如果類型為IORESOURCE_IO,則把父節點設置為ioport_resource??
  • ????????????p?=?&ioport_resource;??
  • ??????}??
  • ????????
  • ???????//將資源插入父節點,也就是出現在父節點目錄層次下???
  • ??????if?(p?&&?insert_resource(p,?r))?{??
  • ?????????printk(KERN_ERR?"%s:?failed?to?claim?resource?%d\n",dev_name(&pdev->dev),?i);ret?=?-EBUSY;??
  • ?????????goto?failed;??
  • ??????}??
  • ??}??
  • ????
  • ??pr_debug("Registering?platform?device?'%s'.?Parent?at?%s\n",dev_name(&pdev->dev),?dev_name(pdev->dev.parent));??
  • ??ret?=?device_add(&pdev->dev);//就在這里把設備注冊到總線設備上,標準設備注冊??
  • ??if?(ret?==?0)??
  • ????????return?ret;??
  • ????
  • ??failed:??
  • ??while?(--i?>=?0)?{??
  • ????????struct?resource?*r?=?&pdev->resource[i];??
  • ????????unsigned?long?type?=?resource_type(r);??
  • ????????if?(type?==?IORESOURCE_MEM?||?type?==?IORESOURCE_IO)??
  • ???????????????release_resource(r);??
  • ??}??
  • ??return?ret;??
  • }??
  • 4.第二種平臺設備注冊方式??
  • //先分配一個platform_device結構,對其進行資源等的初始化??
  • //之后再對其進行注冊,再調用platform_device_register()函數??
  • struct?platform_device?*?platform_device_alloc(const?char?*name,?int?id)??
  • {??
  • ?struct?platform_object?*pa;??
  • ?/*?
  • ?struct?platform_object?{?
  • ???????struct?platform_device?pdev;?
  • ???????char?name[1];?
  • ?};?
  • ?*/??
  • ?pa?=?kzalloc(sizeof(struct?platform_object)?+?strlen(name),?GFP_KERNEL);//該函數首先為platform設備分配內存空間??
  • ?if?(pa)?{??
  • ??strcpy(pa->name,?name);??
  • ??pa->pdev.name?=?pa->name;//初始化platform_device設備的名稱??
  • ??pa->pdev.id?=?id;//初始化platform_device設備的id??
  • ??device_initialize(&pa->pdev.dev);//初始化platform_device內嵌的device??
  • ??pa->pdev.dev.release?=?platform_device_release;??
  • ?}??
  • ?return?pa???&pa->pdev?:?NULL;??
  • }??
  • //一個更好的方法是,通過下面的函數platform_device_register_simple()動態創建一個設備,并把這個設備注冊到系統中:??
  • struct?platform_device?*platform_device_register_simple(const?char?*name,int?id,struct?resource?*res,unsigned?int?num)??
  • {??
  • ???????struct?platform_device?*pdev;??
  • ???????int?retval;??
  • ???????pdev?=?platform_device_alloc(name,?id);??
  • ???????if?(!pdev)?{??
  • ??????????????retval?=?-ENOMEM;??
  • ??????????????goto?error;??
  • ???????}??
  • ???????if?(num)?{??
  • ??????????????retval?=?platform_device_add_resources(pdev,?res,?num);??
  • ??????????????if?(retval)??
  • ?????????????????????goto?error;??
  • ???????}??
  • ???????retval?=?platform_device_add(pdev);??
  • ???????if?(retval)??
  • ??????????????goto?error;??
  • ????????????????
  • ???????return?pdev;??
  • error:??
  • ???????platform_device_put(pdev);??
  • ???????return?ERR_PTR(retval);??
  • }??
  • //該函數就是調用了platform_device_alloc()和platform_device_add()函數來創建的注冊platform?device,函數也根據res參數分配資源,看看platform_device_add_resources()函數:??
  • int?platform_device_add_resources(struct?platform_device?*pdev,struct?resource?*res,?unsigned?int?num)??
  • {??
  • ???????struct?resource?*r;??
  • ???????r?=?kmalloc(sizeof(struct?resource)?*?num,?GFP_KERNEL);//為資源分配內存空間??
  • ???????if?(r)?{??
  • ??????????????memcpy(r,?res,?sizeof(struct?resource)?*?num);??
  • ??????????????pdev->resource?=?r;????????//并拷貝參數res中的內容,鏈接到device并設置其num_resources??
  • ??????????????pdev->?num_resources?=?num;??
  • ???????}??
  • ???????return?r???0?:?-ENOMEM;??
  • }??
  • ??
  • 四.Platform設備驅動的注冊??
  • 我們在設備驅動模型的分析中已經知道驅動在注冊要調用driver_register(),??
  • platform?driver的注冊函數platform_driver_register()同樣也是進行其它的一些初始化后調用driver_register()將驅動注冊到platform_bus_type總線上.??
  • int?platform_driver_register(struct?platform_driver?*drv)??
  • {??
  • ???????drv->driver.bus?=?&platform_bus_type;//它將要注冊到的總線??
  • ???/*設置成platform_bus_type這個很重要,因為driver和device是通過bus聯系在一起的,?
  • ???具體在本例中是通過?platform_bus_type中注冊的回調例程和屬性來是實現的,?
  • ???driver與device的匹配就是通過?platform_bus_type注冊的回調例程platform_match?()來完成的。?
  • ???*/??
  • ???????if?(drv->probe)??
  • ??????????????drv->?driver.probe?=?platform_drv_probe;??
  • ???????if?(drv->remove)??
  • ??????????????drv->driver.remove?=?platform_drv_remove;??
  • ???????if?(drv->shutdown)??
  • ??????????????drv->driver.shutdown?=?platform_drv_shutdown;??
  • ???????return?driver_register(&drv->driver);//注冊驅動??
  • }??
  • //然后設定了platform_driver內嵌的driver的probe、remove、shutdown函數。??
  • static?int?platform_drv_probe(struct?device?*_dev)??
  • {??
  • ???????struct?platform_driver?*drv?=?to_platform_driver(_dev->driver);??
  • ???????struct?platform_device?*dev?=?to_platform_device(_dev);??
  • ???????return?drv->probe(dev);//調用platform_driver的probe()函數,這個函數一般由用戶自己實現??
  • ???????????????????//例如下邊結構,回調的是serial8250_probe()函數??
  • ????????/*?
  • ????static?struct?platform_driver?serial8250_isa_driver?=?{?
  • ?????.probe??=?serial8250_probe,?
  • ?????.remove??=?__devexit_p(serial8250_remove),?
  • ?????.suspend?=?serial8250_suspend,?
  • ?????.resume??=?serial8250_resume,?
  • ?????.driver??=?{?
  • ??????.name?=?"serial8250",?
  • ??????.owner?=?THIS_MODULE,?
  • ?????},?
  • ????};?
  • ????*/??
  • }??
  • static?int?platform_drv_remove(struct?device?*_dev)??
  • {??
  • ???????struct?platform_driver?*drv?=?to_platform_driver(_dev->driver);??
  • ???????struct?platform_device?*dev?=?to_platform_device(_dev);??
  • ???????return?drv->remove(dev);??
  • }??
  • static?void?platform_drv_shutdown(struct?device?*_dev)??
  • {??
  • ???????struct?platform_driver?*drv?=?to_platform_driver(_dev->driver);??
  • ???????struct?platform_device?*dev?=?to_platform_device(_dev);??
  • ???????drv->shutdown(dev);??
  • }??
  • //總結:??
  • 1.從這三個函數的代碼可以看到,又找到了相應的platform_driver和platform_device,然后調用platform_driver的probe、remove、shutdown函數。這是一種高明的做法:??
  • 在不針對某個驅動具體的probe、remove、shutdown指向的函數,而通過上三個過度函數來找到platform_driver,然后調用probe、remove、shutdown接口。??
  • 如果設備和驅動都注冊了,就可以通過bus?->match、bus->probe或driver->probe進行設備驅動匹配了。??
  • 2.驅動注冊的時候platform_driver_register()->driver_register()->bus_add_driver()->driver_attach()->bus_for_each_dev(),??
  • 對每個掛在虛擬的platform?bus的設備作__driver_attach()->driver_probe_device()->drv->bus->match()==platform_match()->比較strncmp(pdev->name,?drv->name,?BUS_ID_SIZE),??
  • 如果相符就調用platform_drv_probe()->driver->probe(),如果probe成功則綁定該設備到該驅動。 ?
  • 總結

    以上是生活随笔為你收集整理的Linux platform总线(1):总体框架的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 好看的黄色录像 | 亚洲色图欧美在线 | 在线观看的免费 | 在线播放少妇奶水过盛 | 国产资源久久 | a级黄视频| 国产欧美日韩亚洲 | 国产一区二区三区乱码 | 动漫一区二区三区 | 欧美成人另类 | 依依成人在线 | 少妇又色又紧又大爽又刺激 | 狠狠爱天天干 | 欧美特黄aaaaaa| 久色视频在线观看 | www.国产在线观看 | 在线视频激情小说 | 亚洲大胆人体 | 网友自拍视频 | 综合伊人久久 | 全部免费毛片在线播放一个 | 少妇精品久久久一区二区三区 | 一区一区三区产品乱码 | 波多野结衣一区 | 色94色欧美sute亚洲线路二 | 日本不卡一二三 | 久99精品 | 欧美1页 | 成人动漫免费在线观看 | av成人免费 | 人人艹视频 | 久久九九免费视频 | 一本综合久久 | 性xx紧缚网站 | 依人综合 | 日韩免费观看 | 中文字幕久久综合 | 手机在线一区 | 国产第一页在线 | 成人做爰66片免费看网站 | 亚洲精品免费在线观看 | 国产日产精品一区二区 | 性一交一乱一乱一视频 | 日本大奶少妇 | 国产18精品乱码免费看 | 欧美劲爆第一页 | mm131丰满少妇人体欣赏图 | 韩日视频一区 | 激情图片网站 | 精品动漫一区二区三区 | japanese强行粗暴 | 精品一二区 | 亚洲 欧美 国产 另类 | 最近中文字幕mv免费高清在线 | 潘金莲激情呻吟欲求不满视频 | 麻豆av在线免费观看 | 国产精品麻豆入口 | 97超级碰碰| 男人的天堂一区二区 | 成年人性生活视频 | 五月视频 | 亚洲精品福利视频 | 日本在线加勒比 | 97看片吧| 91超碰在线观看 | 国产区亚洲区 | 黄a大片 | 国产在线观看一区二区三区 | xxx老太太 | 亚洲精品免费视频 | 亚洲综合性 | 强辱丰满人妻hd中文字幕 | 四虎成人精品永久免费av九九 | 日韩综合久久 | 天堂а√在线最新版中文在线 | 五月激情小说网 | 成人高潮片免费网站 | 91丨porny丨| 欧美激情视频在线观看 | 大尺度在线观看 | 国产精品视频在线播放 | 浪漫樱花动漫在线观看免费 | 久久综合av | 国产特级片 | 黄大色黄大片女爽一次 | 免费一级一片 | 国产日韩欧美在线 | 黄色av网站免费看 | 伊人网av在线 | 国产精品宾馆在线 | 福利综合网 | 日韩 欧美 亚洲 国产 | 中文字幕一区二区三区久久久 | 亚洲品质自拍 | 蜜臀av性久久久久蜜臀aⅴ流畅 | 日韩精品字幕 | 欧美激情在线观看一区 | 色婷婷网| 99视频国产精品 |