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

歡迎訪問 生活随笔!

生活随笔

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

linux

Linux驱动——sdio type card(八)

發布時間:2024/1/18 linux 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux驱动——sdio type card(八) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Linux驅動——sdio type card(八)

備注:
??1. Kernel版本:5.4
??2. 使用工具:Source Insight 4.0

文章目錄

  • Linux驅動——sdio type card(八)
    • 概述
    • 數據結構
      • mmc_sdio_ops
    • 核心接口說明
      • sdio type card匹配相關
        • mmc_attach_sdio
        • mmc_sdio_init_card
      • sdio ops相關函數
        • mmc_send_io_op_cond
        • mmc_io_rw_direct
        • mmc_io_rw_extended
        • sdio_reset
      • sdio irq相關函數
        • 注冊sdio_irq——sdio_claim_irq
        • 釋放sdio_irq——sdio_release_irq
        • 創建sdio_irq_thread——sdio_card_irq_get
        • 實現sdio_irq_thread——sdio_irq_thread
      • sdio io相關函數
        • host相關
        • sdio func相關
        • 塊配置相關
        • IO讀寫相關

概述

??card相關模塊為對應card實現相應的操作,包括初始化操作、以及對應的總線操作集合。負責和對應card協議層相關的東西。
sdio type card相關代碼:

drivers/mmc/core/sdio.c(提供接口) drivers/mmc/core/sdio_ops.c(提供和sdio type card協議相關的操作) drivers/mmc/core/sdio_irq.c(提供sdio irq相關功能的操作) drivers/mmc/core/sdio_cis.c(提供sdio cis相關功能的操作) drivers/mmc/core/sdio_ops.h

數據結構

mmc_sdio_ops

static const struct mmc_bus_ops mmc_sdio_ops = {.remove = mmc_sdio_remove,.detect = mmc_sdio_detect,.pre_suspend = mmc_sdio_pre_suspend,.suspend = mmc_sdio_suspend,.resume = mmc_sdio_resume,.runtime_suspend = mmc_sdio_runtime_suspend,.runtime_resume = mmc_sdio_runtime_resume,.alive = mmc_sdio_alive,.hw_reset = mmc_sdio_hw_reset,.sw_reset = mmc_sdio_sw_reset, };

核心接口說明

sdio type card匹配相關

mmc_attach_sdio

/** Starting point for SDIO card init.*/ int mmc_attach_sdio(struct mmc_host *host) {int err, i, funcs;u32 ocr, rocr;struct mmc_card *card;WARN_ON(!host->claimed);/** * 以下部分,連同mmc_rescan_try_freq中的* mmc_go_idle和mmc_send_if_cond一起構成了* “嘗試獲取一個合適的工作電壓” 的任務 */// host發送參數為0的ACMD41命令,提取response中的VHS,// 得到card支持的工作電壓范圍err = mmc_send_io_op_cond(host, 0, &ocr);if (err)return err;//創建sd_ops,host->bus_ops指向mmc_sdio_opsmmc_attach_bus(host, &mmc_sdio_ops);if (host->ocr_avail_sdio)host->ocr_avail = host->ocr_avail_sdio;// host選擇一個card和host都支持的最低的工作電壓,// 并將host提供給card的工作電壓設置為這個值。// 后續就以host->ocr作為工作電壓對sd card進行初始化rocr = mmc_select_voltage(host, ocr);/** Can we support the voltage(s) of the card(s)?*/if (!rocr) {err = -EINVAL;goto err;}/** Detect and init the card.*//** 上述已經完成了card的識別操作,并且為card選擇了一個合適的工作電壓 **//** 后續調用mmc_sdio_init_card對sdio card進行初始化,也就是代碼核心 **/err = mmc_sdio_init_card(host, rocr, NULL);if (err)goto err;card = host->card;/** Enable runtime PM only if supported by host+card+board*/if (host->caps & MMC_CAP_POWER_OFF_CARD) {/** Do not allow runtime suspend until after SDIO function* devices are added.*/pm_runtime_get_noresume(&card->dev);/** Let runtime PM core know our card is active*/err = pm_runtime_set_active(&card->dev);if (err)goto remove;/** Enable runtime PM for this card*/pm_runtime_enable(&card->dev);}/** The number of functions on the card is encoded inside* the ocr.*/// 根據ocr寄存器獲取func數目funcs = (ocr & 0x70000000) >> 28;card->sdio_funcs = 0;/** Initialize (but don't add) all present functions.*/// 初始化sdio_funcfor (i = 0; i < funcs; i++, card->sdio_funcs++) {err = sdio_init_func(host->card, i + 1);if (err)goto remove;/** Enable Runtime PM for this func (if supported)*/if (host->caps & MMC_CAP_POWER_OFF_CARD)pm_runtime_enable(&card->sdio_func[i]->dev);}/** First add the card to the driver model...*/mmc_release_host(host);// 將sd card添加到device中err = mmc_add_card(host->card);if (err)goto remove_added;/** ...then the SDIO functions.*///注冊 sdio_func 到driver中for (i = 0;i < funcs;i++) {err = sdio_add_func(host->card->sdio_func[i]);if (err)goto remove_added;}if (host->caps & MMC_CAP_POWER_OFF_CARD)pm_runtime_put(&card->dev);mmc_claim_host(host);return 0;remove:mmc_release_host(host); remove_added:/** The devices are being deleted so it is not necessary to disable* runtime PM. Similarly we also don't pm_runtime_put() the SDIO card* because it needs to be active to remove any function devices that* were probed, and after that it gets deleted.*/mmc_sdio_remove(host);mmc_claim_host(host); err:mmc_detach_bus(host);pr_err("%s: error %d whilst initialising SDIO card\n",mmc_hostname(host), err);return err; }

mmc_sdio_init_card

/** Handle the detection and initialisation of a card.** In the case of a resume, "oldcard" will contain the card* we're trying to reinitialise.*/ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,struct mmc_card *oldcard) {struct mmc_card *card;int err;int retries = 10;u32 rocr = 0;u32 ocr_card = ocr;WARN_ON(!host->claimed);/* to query card if 1.8V signalling is supported */if (mmc_host_uhs(host))ocr |= R4_18V_PRESENT;try_again:/** 在mmc_sd_get_cid中完成如下工作::: **//** 重新復位,完成card的內部初始化 **//** 設置信號電壓,包括card和host的設置 **//** 獲取card的CID值 **/// 調用mmc_sd_get_cid進行復位、內部初始化,// 設置信號電壓,然后獲取CID值,// 最終card進入了identification state。if (!retries) {pr_warn("%s: Skipping voltage switch\n", mmc_hostname(host));ocr &= ~R4_18V_PRESENT;}/** Inform the card of the voltage*/err = mmc_send_io_op_cond(host, ocr, &rocr);if (err)return err;/** For SPI, enable CRC as appropriate.*/if (mmc_host_is_spi(host)) {err = mmc_spi_set_crc(host, use_spi_crc);if (err)return err;}/** Allocate card structure.*/card = mmc_alloc_card(host, NULL);if (IS_ERR(card))return PTR_ERR(card);if ((rocr & R4_MEMORY_PRESENT) &&mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) {card->type = MMC_TYPE_SD_COMBO;if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO ||memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) {err = -ENOENT;goto mismatch;}} else {card->type = MMC_TYPE_SDIO;if (oldcard && oldcard->type != MMC_TYPE_SDIO) {err = -ENOENT;goto mismatch;}}/** Call the optional HC's init_card function to handle quirks.*/if (host->ops->init_card)host->ops->init_card(host, card);/** If the host and card support UHS-I mode request the card* to switch to 1.8V signaling level. No 1.8v signalling if* UHS mode is not enabled to maintain compatibility and some* systems that claim 1.8v signalling in fact do not support* it. Per SDIO spec v3, section 3.1.2, if the voltage is already* 1.8v, the card sets S18A to 0 in the R4 response. So it will* fails to check rocr & R4_18V_PRESENT, but we still need to* try to init uhs card. sdio_read_cccr will take over this task* to make sure which speed mode should work.*/if (rocr & ocr & R4_18V_PRESENT) {err = mmc_set_uhs_voltage(host, ocr_card);if (err == -EAGAIN) {mmc_sdio_resend_if_cond(host, card);retries--;goto try_again;} else if (err) {ocr &= ~R4_18V_PRESENT;}}/** For native busses: set card RCA and quit open drain mode.*/if (!mmc_host_is_spi(host)) {err = mmc_send_relative_addr(host, &card->rca);if (err)goto remove;/** Update oldcard with the new RCA received from the SDIO* device -- we're doing this so that it's updated in the* "card" struct when oldcard overwrites that later.*/if (oldcard)oldcard->rca = card->rca;}/** Read CSD, before selecting the card*/if (!oldcard && card->type == MMC_TYPE_SD_COMBO) {err = mmc_sd_get_csd(host, card);if (err)goto remove;mmc_decode_cid(card);}/** Select card, as all following commands rely on that.*/if (!mmc_host_is_spi(host)) {err = mmc_select_card(card);if (err)goto remove;}if (card->quirks & MMC_QUIRK_NONSTD_SDIO) {/** This is non-standard SDIO device, meaning it doesn't* have any CIA (Common I/O area) registers present.* It's host's responsibility to fill cccr and cis* structures in init_card().*/mmc_set_clock(host, card->cis.max_dtr);if (card->cccr.high_speed) {mmc_set_timing(card->host, MMC_TIMING_SD_HS);}if (oldcard)mmc_remove_card(card);elsehost->card = card;return 0;}/** Read the common registers. Note that we should try to* validate whether UHS would work or not.*/err = sdio_read_cccr(card, ocr);if (err) {mmc_sdio_resend_if_cond(host, card);if (ocr & R4_18V_PRESENT) {/* Retry init sequence, but without R4_18V_PRESENT. */retries = 0;goto try_again;}return err;}/** Read the common CIS tuples.*/// 獲取card CIS 值err = sdio_read_common_cis(card);if (err)goto remove;if (oldcard) {if (card->cis.vendor == oldcard->cis.vendor &&card->cis.device == oldcard->cis.device) {mmc_remove_card(card);card = oldcard;} else {err = -ENOENT;goto mismatch;}}card->ocr = ocr_card;mmc_fixup_device(card, sdio_fixup_methods);/** 獲取sd card的配置寄存器和狀態寄存器 **//** 讀取card 的switch狀態,也就是其支持的function **/// host發送ACMD51命令,要求card回復其SCR寄存器(SD configuration register)的值// host發送ACMD13命令,要求card回復其SSR寄存器(SD status regiter)的值// host發送CMD6命令來讀取card switch status。// 通過card switch status可以得到card支持的總線速度模式以及驅動強度類型。if (card->type == MMC_TYPE_SD_COMBO) {err = mmc_sd_setup_card(host, card, oldcard != NULL);/* handle as SDIO-only card if memory init failed */if (err) {mmc_go_idle(host);if (mmc_host_is_spi(host))/* should not fail, as it worked previously */mmc_spi_set_crc(host, use_spi_crc);card->type = MMC_TYPE_SDIO;} elsecard->dev.type = &sd_type;}/** If needed, disconnect card detection pull-up resistor.*/// 關閉 card detection 功能err = sdio_disable_cd(card);if (err)goto remove;/* Initialization sequence for UHS-I cards *//* Only if card supports 1.8v and UHS signaling */// 切換到sdio highspeed 模式、配置時鐘速率、配置數據總線寬度if ((ocr & R4_18V_PRESENT) && card->sw_caps.sd3_bus_mode) {err = mmc_sdio_init_uhs_card(card);if (err)goto remove;} else {/** Switch to high-speed (if supported).*/err = sdio_enable_hs(card);if (err > 0)mmc_set_timing(card->host, MMC_TIMING_SD_HS);else if (err)goto remove;/** Change to the card's maximum speed.*/mmc_set_clock(host, mmc_sdio_get_max_clock(card));/** Switch to wider bus (if supported).*/err = sdio_enable_4bit_bus(card);if (err)goto remove;}if (host->caps2 & MMC_CAP2_AVOID_3_3V &&host->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330) {pr_err("%s: Host failed to negotiate down from 3.3V\n",mmc_hostname(host));err = -EINVAL;goto remove;}host->card = card;return 0;mismatch:pr_debug("%s: Perhaps the card was replaced\n", mmc_hostname(host)); remove:if (oldcard != card)mmc_remove_card(card);return err; }

sdio ops相關函數

mmc_send_io_op_cond

int mmc_send_io_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) {struct mmc_command cmd = {};int i, err = 0;cmd.opcode = SD_IO_SEND_OP_COND;cmd.arg = ocr;cmd.flags = MMC_RSP_SPI_R4 | MMC_RSP_R4 | MMC_CMD_BCR;for (i = 100; i; i--) {err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);if (err)break;/* if we're just probing, do a single pass */if (ocr == 0)break;/* otherwise wait until reset completes */if (mmc_host_is_spi(host)) {/** Both R1_SPI_IDLE and MMC_CARD_BUSY indicate* an initialized card under SPI, but some cards* (Marvell's) only behave when looking at this* one.*/if (cmd.resp[1] & MMC_CARD_BUSY)break;} else {if (cmd.resp[0] & MMC_CARD_BUSY)break;}err = -ETIMEDOUT;mmc_delay(10);}if (rocr)*rocr = cmd.resp[mmc_host_is_spi(host) ? 1 : 0];return err; }

mmc_io_rw_direct

int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn,unsigned addr, u8 in, u8 *out) {return mmc_io_rw_direct_host(card->host, write, fn, addr, in, out); } static int mmc_io_rw_direct_host(struct mmc_host *host, int write, unsigned fn,unsigned addr, u8 in, u8 *out) {struct mmc_command cmd = {};int err;if (fn > 7)return -EINVAL;/* sanity check */if (addr & ~0x1FFFF)return -EINVAL;cmd.opcode = SD_IO_RW_DIRECT;cmd.arg = write ? 0x80000000 : 0x00000000;cmd.arg |= fn << 28;cmd.arg |= (write && out) ? 0x08000000 : 0x00000000;cmd.arg |= addr << 9;cmd.arg |= in;cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC;err = mmc_wait_for_cmd(host, &cmd, 0);if (err)return err;if (mmc_host_is_spi(host)) {/* host driver already reported errors */} else {if (cmd.resp[0] & R5_ERROR)return -EIO;if (cmd.resp[0] & R5_FUNCTION_NUMBER)return -EINVAL;if (cmd.resp[0] & R5_OUT_OF_RANGE)return -ERANGE;}if (out) {if (mmc_host_is_spi(host))*out = (cmd.resp[0] >> 8) & 0xFF;else*out = cmd.resp[0] & 0xFF;}return 0; }

mmc_io_rw_extended

int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz) {struct mmc_request mrq = {};struct mmc_command cmd = {};struct mmc_data data = {};struct scatterlist sg, *sg_ptr;struct sg_table sgtable;unsigned int nents, left_size, i;unsigned int seg_size = card->host->max_seg_size;int err;WARN_ON(blksz == 0);/* sanity check */if (addr & ~0x1FFFF)return -EINVAL;mrq.cmd = &cmd;mrq.data = &data;cmd.opcode = SD_IO_RW_EXTENDED; // cmd53cmd.arg = write ? 0x80000000 : 0x00000000; // 讀寫方向cmd.arg |= fn << 28; // func->numcmd.arg |= incr_addr ? 0x04000000 : 0x00000000;cmd.arg |= addr << 9; // 塊地址if (blocks == 0)cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */elsecmd.arg |= 0x08000000 | blocks; /* block mode */cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;data.blksz = blksz; // 配置塊大小/* Code in host drivers/fwk assumes that "blocks" always is >=1 */data.blocks = blocks ? blocks : 1; // 配置塊數量data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;left_size = data.blksz * data.blocks;nents = DIV_ROUND_UP(left_size, seg_size);if (nents > 1) {if (sg_alloc_table(&sgtable, nents, GFP_KERNEL))return -ENOMEM;data.sg = sgtable.sgl;data.sg_len = nents;for_each_sg(data.sg, sg_ptr, data.sg_len, i) {sg_set_buf(sg_ptr, buf + i * seg_size,min(seg_size, left_size));left_size -= seg_size;}} else {data.sg = &sg;data.sg_len = 1;//初始化sg,找到buf對應的物理頁地址,為DMA傳輸做準備sg_init_one(&sg, buf, left_size);}mmc_set_data_timeout(&data, card);mmc_pre_req(card->host, &mrq);//發送數據,并且等待返回mmc_wait_for_req(card->host, &mrq);if (cmd.error)err = cmd.error;else if (data.error)err = data.error;else if (mmc_host_is_spi(card->host))/* host driver already reported errors */err = 0;else if (cmd.resp[0] & R5_ERROR)//返回數據處理R5err = -EIO;else if (cmd.resp[0] & R5_FUNCTION_NUMBER)err = -EINVAL;else if (cmd.resp[0] & R5_OUT_OF_RANGE)err = -ERANGE;elseerr = 0;mmc_post_req(card->host, &mrq, err);if (nents > 1)sg_free_table(&sgtable);return err; }

sdio_reset

int sdio_reset(struct mmc_host *host) {int ret;u8 abort;/* SDIO Simplified Specification V2.0, 4.4 Reset for SDIO */ret = mmc_io_rw_direct_host(host, 0, 0, SDIO_CCCR_ABORT, 0, &abort);if (ret)abort = 0x08;elseabort |= 0x08;return mmc_io_rw_direct_host(host, 1, 0, SDIO_CCCR_ABORT, abort, NULL); }

sdio irq相關函數

注冊sdio_irq——sdio_claim_irq

/*** sdio_claim_irq - claim the IRQ for a SDIO function* @func: SDIO function* @handler: IRQ handler callback** Claim and activate the IRQ for the given SDIO function. The provided* handler will be called when that IRQ is asserted. The host is always* claimed already when the handler is called so the handler should not* call sdio_claim_host() or sdio_release_host().*/ int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler) {int ret;unsigned char reg;if (!func)return -EINVAL;pr_debug("SDIO: Enabling IRQ for %s...\n", sdio_func_id(func));// sdio_func已注冊中斷,則為異常if (func->irq_handler) { pr_debug("SDIO: IRQ for %s already in use.\n", sdio_func_id(func));return -EBUSY;}// 獲取中斷使能寄存器值ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, &reg);if (ret)return ret;reg |= 1 << func->num;reg |= 1; /* Master interrupt enable */// 使能中斷ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL);if (ret)return ret;func->irq_handler = handler;// 創建sdio_irq_thread內核線程ret = sdio_card_irq_get(func->card);if (ret)func->irq_handler = NULL;// 配置sdio_single_irqsdio_single_irq_set(func->card);return ret; } EXPORT_SYMBOL_GPL(sdio_claim_irq);

釋放sdio_irq——sdio_release_irq

/*** sdio_release_irq - release the IRQ for a SDIO function* @func: SDIO function** Disable and release the IRQ for the given SDIO function.*/ int sdio_release_irq(struct sdio_func *func) {int ret;unsigned char reg;if (!func)return -EINVAL;pr_debug("SDIO: Disabling IRQ for %s...\n", sdio_func_id(func));if (func->irq_handler) {func->irq_handler = NULL;sdio_card_irq_put(func->card);sdio_single_irq_set(func->card);}ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, &reg);if (ret)return ret;reg &= ~(1 << func->num);/* Disable master interrupt with the last function interrupt */if (!(reg & 0xFE))reg = 0;ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL);if (ret)return ret;return 0; } EXPORT_SYMBOL_GPL(sdio_release_irq);

創建sdio_irq_thread——sdio_card_irq_get

static int sdio_card_irq_get(struct mmc_card *card) {struct mmc_host *host = card->host;WARN_ON(!host->claimed);if (!host->sdio_irqs++) {if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {atomic_set(&host->sdio_irq_thread_abort, 0);//創建sdio irq thread 內核線程host->sdio_irq_thread =kthread_run(sdio_irq_thread, host,"ksdioirqd/%s", mmc_hostname(host));if (IS_ERR(host->sdio_irq_thread)) {int err = PTR_ERR(host->sdio_irq_thread);host->sdio_irqs--;return err;}} else if (host->caps & MMC_CAP_SDIO_IRQ) {host->ops->enable_sdio_irq(host, 1);}}return 0; }

實現sdio_irq_thread——sdio_irq_thread

static int sdio_irq_thread(void *_host) {struct mmc_host *host = _host;struct sched_param param = { .sched_priority = 1 };unsigned long period, idle_period;int ret;// 將sdio irq thread線程為實時線程FIFO,優先級為1sched_setscheduler(current, SCHED_FIFO, &param);/** We want to allow for SDIO cards to work even on non SDIO* aware hosts. One thing that non SDIO host cannot do is* asynchronous notification of pending SDIO card interrupts* hence we poll for them in that case.*/// 輪詢運行時間為10msidle_period = msecs_to_jiffies(10);// 若host支持硬件sdio_irq,則為中斷模式,否則為輪詢模式,10ms調度一次period = (host->caps & MMC_CAP_SDIO_IRQ) ?MAX_SCHEDULE_TIMEOUT : idle_period;pr_debug("%s: IRQ thread started (poll period = %lu jiffies)\n",mmc_hostname(host), period);do {/** We claim the host here on drivers behalf for a couple* reasons:** 1) it is already needed to retrieve the CCCR_INTx;* 2) we want the driver(s) to clear the IRQ condition ASAP;* 3) we need to control the abort condition locally.** Just like traditional hard IRQ handlers, we expect SDIO* IRQ handlers to be quick and to the point, so that the* holding of the host lock does not cover too much work* that doesn't require that lock to be held.*/// 獲取host的使用權ret = __mmc_claim_host(host, NULL,&host->sdio_irq_thread_abort);if (ret)break;// 調用sdio_fun irq_handler函數或獲取sdio card status再調用sdio_funcret = process_sdio_pending_irqs(host);// 釋放host的使用權mmc_release_host(host);/** Give other threads a chance to run in the presence of* errors.*/if (ret < 0) {set_current_state(TASK_INTERRUPTIBLE);if (!kthread_should_stop())schedule_timeout(HZ);set_current_state(TASK_RUNNING);}/** Adaptive polling frequency based on the assumption* that an interrupt will be closely followed by more.* This has a substantial benefit for network devices.*/if (!(host->caps & MMC_CAP_SDIO_IRQ)) {if (ret > 0)period /= 2;else {period++;if (period > idle_period)period = idle_period;}}set_current_state(TASK_INTERRUPTIBLE);// 處理完sdio card中的數據,若支持sdio_irq,則使能sdio_irqif (host->caps & MMC_CAP_SDIO_IRQ)host->ops->enable_sdio_irq(host, 1);if (!kthread_should_stop())schedule_timeout(period);set_current_state(TASK_RUNNING);} while (!kthread_should_stop());// 支持sdio_irq,則關閉sdio_irqif (host->caps & MMC_CAP_SDIO_IRQ)host->ops->enable_sdio_irq(host, 0);pr_debug("%s: IRQ thread exiting with code %d\n",mmc_hostname(host), ret);return ret; }

process_sdio_pending_irqs:

static int process_sdio_pending_irqs(struct mmc_host *host) {struct mmc_card *card = host->card;int i, ret, count;bool sdio_irq_pending = host->sdio_irq_pending;unsigned char pending;struct sdio_func *func;/* Don't process SDIO IRQs if the card is suspended. */if (mmc_card_suspended(card))return 0;/* Clear the flag to indicate that we have processed the IRQ. */host->sdio_irq_pending = false;/** Optimization, if there is only 1 function interrupt registered* and we know an IRQ was signaled then call irq handler directly.* Otherwise do the full probe.*/// sdio_single_irq已注冊,則直接調用func->irq_handler處理本次中斷func = card->sdio_single_irq;if (func && sdio_irq_pending) {func->irq_handler(func);return 1;}// 發送cmd5 查詢irq_pending???ret = sdio_get_pending_irqs(host, &pending);if (ret)return ret;// 根據pending,調用所對應的funccount = 0;for (i = 1; i <= 7; i++) {if (pending & (1 << i)) {func = card->sdio_func[i - 1];if (!func) {pr_warn("%s: pending IRQ for non-existent function\n",mmc_card_id(card));ret = -EINVAL;} else if (func->irq_handler) {func->irq_handler(func);count++;} else {pr_warn("%s: pending IRQ with no handler\n",sdio_func_id(func));ret = -EINVAL;}}}if (count)return count;return ret; }

sdio_get_pending_irqs:

static int sdio_get_pending_irqs(struct mmc_host *host, u8 *pending) {struct mmc_card *card = host->card;int ret;WARN_ON(!host->claimed);ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, pending);if (ret) {pr_debug("%s: error %d reading SDIO_CCCR_INTx\n",mmc_card_id(card), ret);return ret;}if (*pending && mmc_card_broken_irq_polling(card) &&!(host->caps & MMC_CAP_SDIO_IRQ)) {unsigned char dummy;/* A fake interrupt could be created when we poll SDIO_CCCR_INTx* register with a Marvell SD8797 card. A dummy CMD52 read to* function 0 register 0xff can avoid this.*/mmc_io_rw_direct(card, 0, 0, 0xff, 0, &dummy);}return 0; }

sdio io相關函數

host相關

sdio_claim_host:

void sdio_claim_host(struct sdio_func *func) {if (WARN_ON(!func))return;mmc_claim_host(func->card->host); } EXPORT_SYMBOL_GPL(sdio_claim_host);

sdio_release_host:

void sdio_release_host(struct sdio_func *func) {if (WARN_ON(!func))return;mmc_release_host(func->card->host); } EXPORT_SYMBOL_GPL(sdio_release_host);

sdio func相關

int sdio_enable_func(struct sdio_func *func); int sdio_disable_func(struct sdio_func *func);

塊配置相關

int sdio_set_block_size(struct sdio_func *func, unsigned blksz); unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz);

IO讀寫相關

// 讀寫1byte u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret); void sdio_writeb(struct sdio_func *func, u8 b, unsigned int addr, int *err_ret); u8 sdio_writeb_readb(struct sdio_func *func, u8 write_byte, unsigned int addr, int *err_ret);// 讀寫塊數據 int sdio_memcpy_fromio(struct sdio_func *func, void *dst, unsigned int addr, int count); int sdio_memcpy_toio(struct sdio_func *func, unsigned int addr, void *src, int count);// 讀寫FIFO 1byte int sdio_readsb(struct sdio_func *func, void *dst, unsigned int addr, int count); int sdio_writesb(struct sdio_func *func, unsigned int addr, void *src, int count);// 讀寫16bit(2byte) u16 sdio_readw(struct sdio_func *func, unsigned int addr, int *err_ret); void sdio_writew(struct sdio_func *func, u16 b, unsigned int addr, int *err_ret);// 讀寫32bit(4byte) u32 sdio_readl(struct sdio_func *func, unsigned int addr, int *err_ret); void sdio_writel(struct sdio_func *func, u32 b, unsigned int addr, int *err_ret);// sdio func0 讀取1byte unsigned char sdio_f0_readb(struct sdio_func *func, unsigned int addr, int *err_ret); void sdio_f0_writeb(struct sdio_func *func, unsigned char b, unsigned int addr, int *err_ret);

??
sdio_io_rw_ext_helper:
??以上IO相關的函數,最終都是調用本函數來實現相關的功能,具體實現方式如下:

/* Split an arbitrarily sized data transfer into several* IO_RW_EXTENDED commands. */ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write,unsigned addr, int incr_addr, u8 *buf, unsigned size) {unsigned remainder = size;unsigned max_blocks;int ret;if (!func || (func->num > 7))return -EINVAL;/* Do the bulk of the transfer using block mode (if supported). */// 支持多塊傳輸,且當前傳輸數據大于一塊大小if (func->card->cccr.multi_block && (size > sdio_max_byte_size(func))) {/* Blocks per command is limited by host count, host transfer* size and the maximum for IO_RW_EXTENDED of 511 blocks. */max_blocks = min(func->card->host->max_blk_count, 511u);// 快對齊收發數據while (remainder >= func->cur_blksize) {unsigned blocks;blocks = remainder / func->cur_blksize;if (blocks > max_blocks)blocks = max_blocks;size = blocks * func->cur_blksize;ret = mmc_io_rw_extended(func->card, write,func->num, addr, incr_addr, buf,blocks, func->cur_blksize);if (ret)return ret;remainder -= size;buf += size;if (incr_addr)addr += size;}}/* Write the remainder using byte mode. */// 收發剩余數據while (remainder > 0) {size = min(remainder, sdio_max_byte_size(func));/* Indicate byte mode by setting "blocks" = 0 */ret = mmc_io_rw_extended(func->card, write, func->num, addr,incr_addr, buf, 0, size);if (ret)return ret;remainder -= size;buf += size;if (incr_addr)addr += size;}return 0; }

總結

以上是生活随笔為你收集整理的Linux驱动——sdio type card(八)的全部內容,希望文章能夠幫你解決所遇到的問題。

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

国产99久久久精品 | 狠狠色伊人亚洲综合网站野外 | 天天碰天天操视频 | 日日夜日日干 | 精品99999 | 丁香花中文字幕 | 99爱精品在线 | 一级一片免费视频 | 久久福利 | 91久久精品日日躁夜夜躁国产 | 欧美激情综合五月色丁香 | 久草在线免费看视频 | 亚洲 av网站 | 天天天天天天干 | 高清不卡毛片 | 日韩高清毛片 | 国产成人精品一区在线 | 成人午夜片av在线看 | 丁香视频 | 中文字幕在线观看网站 | 天天操比| 97碰视频 | 久久综合婷婷国产二区高清 | 欧美一区二区在线看 | 久久久91精品国产一区二区精品 | 久久999久久 | 免费看国产黄色 | 成人一区二区在线 | 国产成人精品一区二区三区福利 | 免费在线观看成年人视频 | 久久无码精品一区二区三区 | 久久欧洲视频 | 精品视频9999 | 国产精选在线观看 | 国产黄色一级片 | 国产日产精品久久久久快鸭 | 欧美成人理伦片 | 免费欧美高清视频 | .国产精品成人自产拍在线观看6 | 欧美性生活小视频 | 美女视频久久 | 99久久电影 | 午夜精品成人一区二区三区 | 久久久首页| 在线观看成人国产 | 视频国产区 | 欧美成人精品欧美一级乱 | 日韩一区二区三区观看 | 久久精品a| 日本爱爱免费 | 人人网av | 色天天天 | 中文字幕一区二区三区在线观看 | 观看免费av | 精品欧美一区二区在线观看 | 综合精品在线 | 日本不卡视频 | 国产精品白浆视频 | 欧美亚洲免费在线一区 | 国产香蕉视频在线播放 | 成人毛片一区 | 激情综合站 | 97超碰人人干 | se视频网址 | 日韩国产在线观看 | 国产一区视频免费在线观看 | 精品999国产 | 97电影网站 | 成人av一区二区在线观看 | 久久麻豆精品 | 久久亚洲日本 | 国产精品一级在线 | 国内精品久久久久久久久 | 国模精品一区二区三区 | 国产成人一区二区在线观看 | 亚洲国产精品电影在线观看 | 亚洲成人免费观看 | 在线视频 91 | 亚洲精品资源在线观看 | 99久精品| 国产一区二区三区四区大秀 | 欧美日韩在线观看不卡 | 激情五月在线观看 | 国产精品美女久久久 | 在线观看av网 | 天天干,天天射,天天操,天天摸 | 亚洲视频专区在线 | 日韩精品久久久久久久电影竹菊 | 国产精品2019 | 国产精品系列在线 | 亚洲国产片色 | 在线看片中文字幕 | 日日干综合 | 成人禁用看黄a在线 | 亚洲欧美国产日韩在线观看 | 成人性生交大片免费看中文网站 | 亚洲视频在线免费看 | 色吧久久 | 国产亚洲精品久久久久动 | 亚洲欧美怡红院 | 亚洲国产美女精品久久久久∴ | 麻豆传媒视频观看 | 天天操天天操天天操天天操 | 欧美资源在线观看 | 亚洲欧美日韩在线看 | 丁香综合网| 99久久精品国产毛片 | 国产亚洲精品久久久久久移动网络 | 国产成人一二三 | 男女视频久久久 | 久久久久9999亚洲精品 | 亚洲精品在线视频网站 | 欧美日韩另类在线 | 久久少妇 | 久久精品这里都是精品 | 亚洲日本黄色 | 成人av在线直播 | 最新高清无码专区 | 成人污视频在线观看 | 97视频在线观看免费 | 99热这里有| 亚洲电影影音先锋 | 国产精品淫片 | 国产精品久久久久久久久费观看 | 怡红院av久久久久久久 | 激情综合五月天 | 麻花豆传媒mv在线观看 | 国产精品一区二区三区视频免费 | 精品亚洲国产视频 | 国产亚洲婷婷 | 日韩理论在线 | 国产精品女 | 四虎国产精品成人免费4hu | 久久久精品久久日韩一区综合 | 欧美日本一区 | 国产精品v欧美精品v日韩 | www.色爱| 国产精品小视频网站 | 六月丁香婷婷久久 | 999视频在线播放 | 日韩精品免费一区 | 日日夜夜免费精品 | 中文字幕中文字幕在线中文字幕三区 | 久久国产美女视频 | 精品一区二区久久久久久久网站 | 豆豆色资源网xfplay | 日韩亚洲在线 | 99精品久久只有精品 | 国产视频在线观看一区 | 久久久久久久久久久网 | 天天躁日日躁狠狠躁av中文 | 91人人澡人人爽人人精品 | 国产高清一级 | 在线播放一区二区三区 | 综合伊人av | 亚洲精品视频在线免费 | 成人av在线网 | 久久激情视频 久久 | 日韩午夜电影网 | 西西人体www444 | 婷婷网站天天婷婷网站 | 在线免费色 | 国产色女人 | 韩日av一区二区 | 久久精品国产精品亚洲 | 亚洲精品中文字幕视频 | 日韩久久片 | 91麻豆国产| 欧美激情综合色 | 久草在线一免费新视频 | 色狠狠综合 | 国精产品一二三线999 | 九九视频网站 | 懂色av一区二区三区蜜臀 | 91在线最新 | 国产精品久久久久久久久蜜臀 | 六月婷色| 国产欧美精品一区aⅴ影院 99视频国产精品免费观看 | 免费看网站在线 | 日韩免费av网址 | 男女视频91| 国产手机在线 | 夜色资源站国产www在线视频 | 99热这里只有精品久久 | 韩国av一区 | 午夜影视一区 | 欧美日韩免费一区 | 日本资源中文字幕在线 | 天天干,夜夜爽 | 三级a毛片 | 国产91成人 | 亚洲人天堂 | 区一区二在线 | 91桃色视频 | 国产韩国日本高清视频 | aa一级片| 99久久久久久| 免费看一及片 | 西西444www大胆高清视频 | 毛片播放网站 | 精品99视频| 在线观看视频中文字幕 | 久久深爱网 | 99爱这里只有精品 | 国产精品你懂的在线观看 | 亚洲精品一区二区18漫画 | 在线免费观看视频 | 91久久久久久国产精品 | 午夜精品久久 | 日产乱码一二三区别在线 | 九九视频这里只有精品 | 色欧美88888久久久久久影院 | 久久久99精品免费观看 | 久久国产区| 最新国产精品久久精品 | 视频在线日韩 | 99久久爱 | 99久久婷婷国产综合亚洲 | 五月婷婷久久丁香 | 欧美人体xx | 中文字幕在线观看日本 | 亚洲精品国久久99热 | 亚洲综合欧美精品电影 | 中文字幕一二三区 | 亚洲精品三级 | 久久国产精品99国产精 | 国内精品久久久久影院优 | 久久人人爽人人 | 久爱精品在线 | 一区中文字幕电影 | 亚洲免费黄色 | 久久午夜精品视频 | 毛片永久新网址首页 | 波多野结衣资源 | 色视频在线免费观看 | 精品国产电影一区二区 | 蜜臀av性久久久久av蜜臀三区 | 国产精品女人网站 | 中文字幕视频免费观看 | 黄色毛片一级片 | 亚洲国产97在线精品一区 | 成年人天堂com | 高清国产午夜精品久久久久久 | 99久久网站 | 天天干 夜夜操 | 婷婷色在线视频 | 久久精品男人的天堂 | 欧美国产视频在线 | 久久国产精品免费看 | 在线观看你懂的网址 | 精品一区二区日韩 | 青青久草在线视频 | 91久久久久久国产精品 | 在线播放日韩 | 欧美极品少妇xbxb性爽爽视频 | 久久国产免费 | 狠色狠色综合久久 | 久久久久免费看 | 国产网红在线观看 | 伊甸园av在线| 在线观看视频中文字幕 | 天天艹| 欧美综合干| 国产精品久久在线观看 | 国产精品久久99综合免费观看尤物 | 丝袜一区在线 | 色婷婷av在线 | 五月天六月丁香 | 欧美亚洲国产日韩 | 日韩精品一区二区在线视频 | 手机在线小视频 | 亚洲色影爱久久精品 | 日韩a在线看 | 欧美精品在线一区二区 | 亚洲欧洲成人 | 久久国产精品久久久久 | 国产流白浆高潮在线观看 | av在线永久免费观看 | 国产视频日本 | 91精品对白一区国产伦 | 99c视频在线| 久久久高清免费视频 | 国产精品久久久久亚洲影视 | 欧美在线一二 | 欧美一级黄色片 | 日韩一区二区三区免费电影 | 久草精品在线播放 | 99精品视频免费 | 日本视频网 | 91香蕉视频好色先生 | 色999视频 | 91香蕉视频黄色 | a在线播放 | 日韩免费看 | 超碰个人在线 | 亚洲一级久久 | 在线黄色免费 | 久久香蕉电影 | 亚洲高清精品在线 | 久久不见久久见免费影院 | 久久免费av电影 | 亚洲综合导航 | 日本精品在线视频 | 五月激情av | 国产一级做a | 欧美精品久久人人躁人人爽 | av片在线观看 | 久久综合国产伦精品免费 | 精品久久一二三区 | 国际精品久久久 | 国际精品久久久久 | 美女网站视频免费都是黄 | 天堂网一区 | 婷婷亚洲五月色综合 | 亚洲美女免费精品视频在线观看 | 国产手机在线播放 | 国产成人三级在线观看 | 色婷婷综合久久久中文字幕 | 久久免费公开视频 | 五月婷婷六月综合 | 97偷拍视频 | 日韩国产精品一区 | 九色91在线视频 | 啪啪小视频网站 | 精品国产一区二区三区久久久蜜月 | 91精品久久久久 | 成人avav | 一区二区三区在线免费 | 91传媒在线播放 | 国产一区国产精品 | 亚洲精品国产自产拍在线观看 | av三级在线免费观看 | 日韩二区三区在线 | 97超视频免费观看 | 涩涩在线 | 国产精品尤物 | 免费在线色 | 成人资源站 | 91精品国自产在线偷拍蜜桃 | 国产黄影院色大全免费 | 久久成人国产精品一区二区 | 国产精品国产亚洲精品看不卡15 | 亚洲国产精品va在线 | 国产少妇在线观看 | 亚洲精品视频网 | 久久国产精品免费 | 中文字幕在线观看免费高清电影 | 久久美女高清视频 | 日韩免费一区二区在线观看 | 黄色网址中文字幕 | 就操操久久 | 国产短视频在线播放 | 中文字幕二区三区 | 国产伦精品一区二区三区四区视频 | 亚洲成av人片在线观看www | 狠狠的日 | 日韩视频在线不卡 | 在线免费观看羞羞视频 | 成人免费网站视频 | 久草在线这里只有精品 | 久久天堂网站 | 深爱激情综合 | 日韩免费视频一区二区 | 最新国产在线视频 | 精品久久久久久久 | 欧美色图狠狠干 | 久久精品韩国 | 国产美女免费观看 | 中文字幕在线观看网 | 伊人资源视频在线 | 中文字幕日本在线观看 | av在线免费观看不卡 | 婷婷精品国产欧美精品亚洲人人爽 | 91中文字幕网 | 国产精品日韩高清 | 欧美91成人网 | 99久久久久久久久久 | 久久久久久国产精品久久 | 欧美午夜性生活 | 97电影网手机版 | 亚洲影音先锋 | 中文在线√天堂 | 五月天精品视频 | 久久在线电影 | 99免费在线播放99久久免费 | 中文字幕免费播放 | 久久人人添人人爽添人人88v | 国产精品99精品 | 亚洲精品2区 | 91成人区| www日韩精品 | 亚洲免费小视频 | 中文字幕 在线 一 二 | 久久精品伊人 | 亚洲国产成人精品电影在线观看 | 97视频中文字幕 | 青青射| 国产精品爽爽爽 | 国产欧美日韩视频 | 日韩啪啪小视频 | 久久精品视频99 | 免费一级片视频 | 国产无遮挡又黄又爽在线观看 | 一区三区视频 | 久久免费黄色大片 | av大片免费 | 色综合久久久久网 | 国产视频二区三区 | 97av在线视频 | 日本99热| 亚洲精品欧美精品 | 999久久精品 | 国产精品情侣视频 | 国产999精品久久久久久麻豆 | 午夜影院三级 | 国产成人免费高清 | 久久躁日日躁aaaaxxxx | 97超碰在线视 | 国产粉嫩在线 | 黄色网址国产 | 日日夜夜综合 | 99在线观看视频网站 | 免费在线观看av网址 | 欧美一区二区三区在线观看 | 日韩av在线免费看 | 国产精品私人影院 | 成年人在线免费看视频 | 91福利在线导航 | 亚洲va在线va天堂 | 国产免费视频一区二区裸体 | 日韩欧美视频在线观看免费 | 欧美日韩一区二区三区在线观看视频 | 国产精品成人久久久久 | 天天操天天舔天天干 | 久久精品电影网 | 在线观看v片 | 最近中文字幕免费大全 | 亚洲电影图片小说 | 97精品国产97久久久久久免费 | 永久黄网站色视频免费观看w | 日韩三级av| 国产小视频免费观看 | 日韩在线观看一区二区 | 国产高清免费av | 成片免费观看视频999 | 久久成人毛片 | 国产精品免费久久久 | 热久久电影 | 91成人在线观看高潮 | 亚洲综合激情网 | 黄色avwww| 日韩在线欧美在线 | 在线视频a | 91视频啊啊啊 | 中文字幕日韩无 | 欧美在线观看视频一区二区三区 | 天天拍天天色 | 久久久精品免费看 | 婷婷色网址 | 91精品色 | 国产又粗又硬又爽视频 | 美女网站黄在线观看 | 欧洲精品二区 | 国产成人精品一区二区三区福利 | 亚洲五月综合 | 黄色av一区二区三区 | 日韩中文字幕在线观看 | 天天躁天天躁天天躁婷 | 麻豆91在线观看 | 在线天堂中文www视软件 | av午夜电影 | 在线中文字幕电影 | 久久avav | 国产精品久久久久久一区二区三区 | 天天射天天做 | 97av免费视频 | 国产一区二区三区免费视频 | 亚欧日韩成人h片 | 日日夜夜骑| 91视视频在线直接观看在线看网页在线看 | 国产精华国产精品 | 国产在线视频一区二区三区 | 五月天婷婷综合 | 超薄丝袜一二三区 | 黄色大片入口 | 粉嫩av一区二区三区四区五区 | 成人aaa毛片 | 日本aaa在线观看 | 在线观看岛国 | 成人免费一级 | 欧美性猛片 | 91禁在线看 | 国产永久免费高清在线观看视频 | 亚洲精品国产麻豆 | avsex| 91片黄在线观看动漫 | 91精品国产91热久久久做人人 | 久久影院午夜论 | 在线日本看片免费人成视久网 | 一区二区三区国产欧美 | 久久99国产精品 | 久草| 欧美a影视 | 天堂av在线7 | 亚洲精品国偷拍自产在线观看蜜桃 | 中文字幕在线播放一区二区 | 久久精品99久久久久久 | 97色狠狠| 91精品系列 | 亚洲久草在线视频 | 精品免费久久久久 | 精品人人人| 人人玩人人添人人 | 最近中文字幕高清字幕在线视频 | 永久中文字幕 | 久操伊人| 91九色视频网站 | 精品久久福利 | 中文字幕资源站 | 99r精品视频在线观看 | 五月婷婷综合激情网 | 美女免费视频一区 | 少妇bbw搡bbbb搡bbbb | 狠狠干美女| 天天操天天摸天天干 | 99久久久成人国产精品 | 91精品啪在线观看国产 | 九九免费在线观看视频 | 亚洲 欧美 日韩 综合 | 天天插天天色 | 精品国偷自产在线 | 日韩免费看视频 | free. 性欧美.com | 日韩精品中文字幕久久臀 | 久久久午夜精品福利内容 | 日韩精品免费一区二区三区 | 久久特级毛片 | 狠狠色丁香久久婷婷综合五月 | 亚洲精品乱码久久久久v最新版 | www.夜色.com| 婷婷丁香自拍 | 欧美日韩p片 | 女人18片毛片90分钟 | 亚洲91网站 | 亚洲欧洲精品久久 | 亚洲精品在线观看中文字幕 | 丁香六月久久综合狠狠色 | 亚洲毛片在线观看. | 亚洲精品视频在线 | 9ⅰ精品久久久久久久久中文字幕 | 亚洲精品mv在线观看 | 日本中文字幕电影在线免费观看 | 中文字幕乱码亚洲精品一区 | 91色吧| 欧美精品少妇xxxxx喷水 | 色丁香久久 | 992tv人人网tv亚洲精品 | 亚洲一区二区三区四区在线视频 | 东方av在线免费观看 | 久久一区二区免费视频 | 免费网站观看www在线观看 | 五月婷婷在线视频观看 | 字幕网在线观看 | 国产精品去看片 | 国产成人一区二 | 97视频免费在线看 | 黄色三级视频片 | 人人射| 深夜免费小视频 | 久久午夜色播影院免费高清 | 久久高清 | 久久这里精品视频 | 日韩特黄一级欧美毛片特黄 | 久久第四色 | 久久字幕网 | 91精品免费在线观看 | 人人澡视频 | 亚洲精品乱码久久久久久9色 | 国产精品岛国久久久久久久久红粉 | 国产精品麻豆一区二区三区 | 国产精品久久久久婷婷 | 精品一区电影国产 | 最近2019好看的中文字幕免费 | 中文字幕亚洲在线观看 | 国产免费中文字幕 | 欧美激情视频一二区 | 欧美aaa级片 | 91精品国| 五月婷婷中文网 | 久久久久在线观看 | 亚洲视频久久 | 91尤物国产尤物福利在线播放 | 九九色在线观看 | 激情久久小说 | 久久激情视频 久久 | 国产在线不卡一区 | 人人爽人人做 | 日韩欧美在线观看一区 | 久久字幕网 | 中文有码在线视频 | 国产精品久久久免费看 | 四虎www.| 午夜久操| 亚洲 欧美日韩 国产 中文 | 国产中文字幕国产 | 成人在线免费观看网站 | 9ⅰ精品久久久久久久久中文字幕 | 91桃花视频 | av资源免费观看 | 日韩精品一区二区三区不卡 | 国产成人精品免费在线观看 | 久久看毛片 | 涩涩网站在线播放 | 综合视频在线 | 日韩精品视频在线观看免费 | 日日精品 | 伊人网综合在线观看 | 欧美精品久久久久久久久老牛影院 | 黄色免费在线看 | 欧美a性 | 国产 av 日韩 | 中文字幕亚洲精品在线观看 | 黄色avwww | 国产剧情一区在线 | 亚洲伊人av | 亚洲精品免费观看 | 亚洲欧美日韩国产 | 香蕉视频免费看 | 国产亚洲在线观看 | 天天干夜夜干 | 色婷婷狠狠18 | 夜夜看av | 免费午夜网站 | 中文字幕在线一区观看 | 91色一区二区三区 | 91精品国产一区二区三区 | 国产成人精品亚洲a | 欧美激情精品久久 | 成年人视频免费在线 | 国产91学生粉嫩喷水 | 日韩欧美aaa | 亚洲视频大全 | 国产美女永久免费 | www.久久久久 | 亚洲va男人天堂 | 精品国产乱码一区二 | 婷婷综合视频 | 国产91精品看黄网站 | 99精品免费久久久久久久久日本 | 国产精品毛片一区视频播不卡 | 九九热精品视频在线播放 | 亚洲91中文字幕无线码三区 | 亚洲国产久 | 日韩综合一区二区三区 | 国产精品高清免费在线观看 | 狠狠干我 | 在线中文字幕播放 | 在线日韩中文 | 天天操夜夜操国产精品 | 狠狠撸电影 | 久久99精品国产99久久6尤 | 欧美疯狂性受xxxxx另类 | 亚洲精品男人天堂 | 久久av网 | 久久久久久久久黄色 | 久99久在线视频 | 久久精品视频免费播放 | 精品国内自产拍在线观看视频 | 天天操天天添 | 天天色天天色天天色 | 色福利网 | 国产麻豆果冻传媒在线观看 | 福利一区二区 | 噜噜色官网 | 日韩美女久久 | 91精品国产网站 | 国产一级黄| 色婷婷视频在线 | 天天操天天摸天天爽 | 狠狠操精品 | 国产黄色资源 | 十八岁免进欧美 | 欧美福利片在线观看 | 国内视频一区二区 | 成人午夜久久 | 欧美精品久久久久久久久久白贞 | 黄色成人影院 | 天天射天天射 | 亚洲九九九在线观看 | 久久成电影| 亚洲黄色小说网址 | 国产欧美精品xxxx另类 | 在线观看亚洲精品 | 久久久久久毛片 | 国产首页 | 久久人91精品久久久久久不卡 | 亚洲精品高清在线 | 国产999精品久久久久久绿帽 | 欧美性网站 | 成人久久毛片 | 国产视频精品在线 | www.夜夜爽| 国产精品美女久久久久久久 | 在线观看视频黄 | 婷婷免费在线视频 | 精品国产乱码一区二 | 国产露脸91国语对白 | 日韩av一区二区三区在线观看 | 亚洲精品 在线视频 | 日韩簧片在线观看 | 亚洲国产影院 | 国际精品网 | 香蕉视频18 | 久久久999免费视频 日韩网站在线 | 亚洲区精品 | 在线亚洲小视频 | 国产成人久久77777精品 | 亚洲精品乱码久久久久久写真 | 天天综合网~永久入口 | 久草精品视频在线播放 | 欧美精品在线一区 | 1000部国产精品成人观看 | 欧美精品久久久久a | 国产手机视频精品 | 中文字幕在线一二 | 国产精品不卡av | 亚洲精品午夜国产va久久成人 | 一级黄色大片 | 亚洲精品伦理在线 | 丁香 久久 综合 | 91日韩在线播放 | 国产精品女人久久久 | 国产在线久久久 | 成人免费在线视频观看 | 久香蕉 | 久色 网| 日韩精品久久久久久久电影竹菊 | 久久一区二区三区超碰国产精品 | 日本韩国精品一区二区在线观看 | 美女在线观看网站 | 国产一区视频免费在线观看 | 69视频永久免费观看 | 成人网色 | 一区二区视 | 色婷婷av在线 | 国产成人91 | 久久人人看 | 最新日韩视频 | 成人一区不卡 | 黄色免费网站大全 | 超碰97在线资源 | 欧美 日韩精品 | 免费能看的av | www.狠狠操.com | 亚洲精品成人av在线 | 国产福利91精品一区二区三区 | 波多野结衣在线中文字幕 | 中文字幕国产亚洲 | 日日精品| 手机在线免费av | 2019中文 | 国产小视频在线看 | 992tv在线观看 | 国产一区在线视频观看 | 中文字幕亚洲在线观看 | 久久久久区| 国产精品免费一区二区 | 精品久久精品久久 | 欧美日韩精品网站 | 国产美女免费观看 | 国产精品第二十页 | 综合久久久久久 | 国产在线看一区 | 日本中文字幕视频 | 久久午夜视频 | 天天精品视频 | 亚洲激情| 亚洲国产伊人 | 日韩伦理一区二区三区av在线 | 免费观看久久 | 亚州精品在线视频 | 丁香五香天综合情 | 国产亚洲婷婷 | 免费又黄又爽的视频 | 久久精彩免费视频 | 久久综合久久久 | 毛片888| 婷婷综合网 | 91麻豆精品国产91久久久无限制版 | 免费国产亚洲视频 | 毛片网免费 | 超碰97中文| 五月综合在线观看 | 91传媒免费在线观看 | 久草爱| 国产精品久久久久免费观看 | 少妇性aaaaaaaaa视频 | 国产成人免费高清 | 亚洲三级在线 | 婷五月天激情 | 啪啪免费观看网站 | 99av在线视频| 五月天激情在线 | 婷婷激情欧美 | 久久久久久久久毛片精品 | 日韩一区二区免费在线观看 | 毛片永久免费 | 久久精品国产第一区二区三区 | 在线不卡的av| 一本一本久久a久久精品综合小说 | 91亚洲欧美| 国内精品久久久久影院优 | 免费在线一区二区 | 国产精品视频久久久 | 91视频 - x99av| 一区 二区电影免费在线观看 | 精品国产成人av在线免 | 国产精品高潮呻吟久久久久 | 麻豆传媒视频观看 | 亚洲专区在线播放 | 国产在线视频一区二区三区 | av不卡网站| 私人av| 色婷婷一 | 久久成人视屏 | 亚洲国产日韩av | 国产精品一区二区久久精品爱微奶 | 亚洲精品乱码久久久久久蜜桃91 | 香蕉日日 | 日韩免费不卡av | 天天天干天天天操 | 99热九九这里只有精品10 | 久久在现| 日本特黄一级 | 丁香综合网| 国产视频在线免费观看 | 亚洲国产美女久久久久 | 一区二区三区视频网站 | 麻豆视频在线观看免费 | 亚洲专区 国产精品 | 91精品视频免费看 | 日日操网站 | 91成人网页版 | 成人一级视频在线观看 | 国产精品第二十页 | 精品一区二区三区香蕉蜜桃 | 999电影免费在线观看 | 狠狠色狠狠色终合网 | 日本免费久久高清视频 | 免费在线成人 | 久久理论视频 | 视频91在线| 在线有码中文 | 亚洲欧美va | 亚洲女同videos| 日韩精品一区二区三区中文字幕 | 日b视频在线观看网址 | 911久久香蕉国产线看观看 | 午夜视频在线观看一区二区三区 | 九色视频网站 | www.久久精品视频 | 亚州日韩中文字幕 | 国产黄色精品 | 欧美日韩三级在线观看 | 国产精品一区二区美女视频免费看 | 91人人澡人人爽人人精品 | 少妇激情久久 | 成人黄大片视频在线观看 | 国产黄在线播放 | 国产中文字幕视频 | 久久免费在线观看视频 | 日韩精品一区二区免费视频 | 搡bbbb搡bbb视频 | 欧美精品做受xxx性少妇 | 在线不卡的av | 久久精品这里精品 | 超碰在线人人草 | 久久国产精品一区二区三区 | 亚洲高清在线精品 | 国产xxxxx在线观看 | 国产精品av在线 | 久久黄视频 | 国产精品精品久久久 | 欧美成人69av | 色国产精品一区在线观看 | 国产高清小视频 | 91理论片午午伦夜理片久久 | 蜜臀av.com| 激情在线网址 | 天天色天天操综合 | 免费观看黄色12片一级视频 | 久久伊人八月婷婷综合激情 | 日韩电影在线视频 | 天天操夜夜想 | 69绿帽绿奴3pvideos| 亚洲欧美日韩国产精品一区午夜 | 亚洲h在线播放在线观看h | 久久深夜 | 精品夜夜嗨av一区二区三区 | 国产毛片在线 | 国产亚洲精品v | 最近高清中文字幕 | 日韩城人在线 | 九色自拍视频 | 欧美日bb| 欧美日韩不卡一区二区 | 久久久久草 | 久久婷婷国产色一区二区三区 | 正在播放 久久 | 91一区二区三区久久久久国产乱 | 国产高清在线看 | 日韩电影中文字幕在线观看 | 日韩综合在线观看 | 欧美爽爽爽 | 国产亚洲精品久久久久久久久久 | 久久久久国产精品免费网站 | 久久婷婷丁香 | 成人av在线直播 | 91av视频| 日韩色综合 | 天天狠狠干| 久久精选视频 | 五月天综合在线 | 亚洲人成人99网站 | 免费网站污 | 波多野结衣电影久久 | 在线观看免费版高清版 | 丁香在线观看完整电影视频 | 天天操夜夜操国产精品 | 亚洲视频免费在线观看 | 五月天中文字幕mv在线 | 337p日本欧洲亚洲大胆裸体艺术 | 99久久夜色精品国产亚洲 | 亚洲国产av精品毛片鲁大师 | 久草电影在线观看 | 综合色综合 | 亚洲精品在线二区 | 国产视频一二三 | 国产系列 在线观看 | av福利超碰网站 | 国产一区二区在线影院 | 欧美一级在线看 | 国产九色91 | 国产三级视频在线 | 狠狠躁天天躁 | 国产在线高清视频 | 亚洲涩综合 | 中文字幕一区在线 | 亚洲国产精品推荐 | 美女国产精品 | 欧美在线日韩在线 | 日韩美视频 | 国产精品永久 | 国产在线精品视频 | 欧美成人久久 | 成人一级电影在线观看 | 911香蕉视频| www.超碰| 蜜臀aⅴ国产精品久久久国产 | 国产在线观看污片 | 亚洲干| 欧美日韩国产一区二区在线观看 | 国产一区在线视频 | 国产伦理精品一区二区 | 国产一级视屏 | 精品在线视频一区 | 欧美日韩亚洲精品在线 | 国产精品自产拍在线观看网站 | 久久无码精品一区二区三区 | 五月婷亚洲| 91av福利视频 | 夜色.com| 91干干干 | 一区二区三区 中文字幕 | 四虎成人网 | av东方在线| 久久久片 | 精品一区二区电影 | 日韩影视大全 | 97色狠狠 | 成人黄色小视频 | 亚洲japanese制服美女 | 免费高清在线观看成人 | 99精品在线免费观看 | www夜夜| 日韩高清av | 欧美激情另类文学 | 免费黄色一区 | 成人久久久久久久久 | 丝袜美女在线 | 97国产情侣爱久久免费观看 | 久久综合久色欧美综合狠狠 | 成人黄色国产 | 欧美日韩国产精品一区 | 亚洲精品一区二区在线观看 | 干天天 | а天堂中文最新一区二区三区 | 亚洲乱码国产乱码精品天美传媒 |