1204行,由structmmc_host得到struct s3cmci_host。
1205行,從host->mrq取出mmc_request以便使用。
1206行,因為host->cmd_is_stop被設(shè)置為0,所以cmd被設(shè)置為mrq->cmd。
1214-1216行,清空SDICmdSta寄存器、SDIDatSta寄存器和SDIFSTA寄存器。
1216-1245行,如果cmd->data不為0,即當(dāng)前command帶有要處理的數(shù)據(jù),則執(zhí)行這個if語句塊,進(jìn)行數(shù)據(jù)處理的準(zhǔn)備工作。
1219行,調(diào)用s3cmci_setup_data(host,cmd->data),該函數(shù)定義在drivers/mmc/host/s3cmci.c文件中:
1054-1057行,如果命令數(shù)據(jù)為空,則清零SDIDatCon寄存器。
1059-1067行,根據(jù)Datasheet的描述,如果在多模塊下必須分配字大小,即BlkSize[1:0]=00,所以這里“與”3來判斷是不是單模塊。如果在單模塊處理的情況下,模塊數(shù)大于1,則出錯退出。
1069-1082行,循環(huán)判斷是否有數(shù)據(jù)正在發(fā)送或接收,如果有,則停止傳輸,并復(fù)位時鐘。最多循環(huán)3次。
1086-1087行,如果使用DMA傳輸,則使能SDIDatCon寄存器的第15位DMA功能。
1089-1090行,如果數(shù)據(jù)總線寬度為4線,則使能SDIDatCon寄存器的第16位寬總線WideBus功能。
1092-1093行,配置SDIDatCon寄存器的第17位,數(shù)據(jù)傳輸模式為塊傳輸模式。
1095-1098行,如果是寫數(shù)據(jù),配置SDIDatCon寄存器的第20位,收到回應(yīng)后開始寫數(shù)據(jù)。然后配置SDIDatCon寄存器的第12、13位,設(shè)置為寫模式。
1100-1103行,如果是讀數(shù)據(jù),配置SDIDatCon寄存器的第19位,命令發(fā)送后開始讀數(shù)據(jù)。
然后配置SDIDatCon寄存器的第12、13位,設(shè)置為讀模式。
1105-1108行,如果是S3C2440,配置SDIDatCon寄存器的第22、23位為10,即傳輸單位為word。然后配置SDIDatCon寄存器的第14位,開始數(shù)據(jù)傳輸。
1110行,將dcon寫入SDIDatCon寄存器。
1114行,將data->blksz寫入SDIBSize寄存器。
1117-1118行,設(shè)置出現(xiàn)FIFO失敗SDI中斷使能;數(shù)據(jù)接收CRC錯誤SDI中斷使能;數(shù)據(jù)接收超時SDI中斷使能;數(shù)據(jù)計時為0SDI中斷使能。
1120行,調(diào)用enable_imask使能設(shè)置的中斷。
1124-1132行,設(shè)置SDIDTimer寄存器。
回到s3cmci_send_request函數(shù):
1223-1230行,如果s3cmci_setup_data出錯,則打印信息并退出。
1232-1233行,如果使用DMA,則調(diào)用s3cmci_prepare_dma函數(shù),該函數(shù)定義在drivers/mmc/host/s3cmci.c文件中,關(guān)于DMA相關(guān)的函數(shù),我們不再詳細(xì)跟蹤了。
1235行,如果沒有使用DMA數(shù)據(jù)傳輸方式,則調(diào)用s3cmci_prepare_pio函數(shù),即使用FIFO數(shù)據(jù)傳輸方式,具體來說,就是調(diào)用 do_pio_write向FIFO中填充數(shù)據(jù),當(dāng)64字節(jié)的FIFO少于33字節(jié)時就會產(chǎn)生中斷;或者從SD讀數(shù)據(jù),則先使能中斷,當(dāng)FIFO多于31 字節(jié)時,則會調(diào)用中斷服務(wù)程序,中斷服務(wù)程序會調(diào)用do_pio_read讀出FIFO的數(shù)據(jù)。
s3cmci_prepare_pio函數(shù)定義在drivers/mmc/host/s3cmci.c文件中:
1141行,根據(jù)data->flags確定是讀還是寫。
1151行,如果是寫,則調(diào)用do_pio_write函數(shù)。do_pio_write函數(shù)定義在drivers/mmc/host/s3cmci.c文件中:
527行,取得SDIDAT寄存器的物理地址保存在to_ptr變量中。
529行,調(diào)用fifo_free(host)函數(shù)取得FIFO的剩余可用空間的字節(jié)數(shù)保存在fifo變量中,這里,fifo變量代表這次while循環(huán)最多可寫的字節(jié)個數(shù)。如果剩余空間大于3個字節(jié),即最小寫一個字,則循環(huán)條件成立。
530-532行,如果host->pio_bytes為0,則調(diào)用get_data_buffer從分散聚集列表中取得保存要寫的數(shù)據(jù)的緩 沖區(qū),緩沖區(qū)的長度和起始地址分別保存在get_data_buffer的2個參數(shù)host->pio_bytes和第3個參數(shù) host->pio_ptr中。
533-539行,如果get_data_buffer出錯,打印信息退出。
551-552行,如果fifo大于等于host->pio_bytes,即FIFO的可用空間大于等于保存要寫數(shù)據(jù)的緩沖區(qū)長度,則將fifo設(shè)置為host->pio_bytes。
554行,如果fifo小于host->pio_bytes,即FIFO的可用空間小于要寫數(shù)據(jù)的緩沖區(qū)長度,則將fifo設(shè)置為fifo – (fifo & 3)。從注釋可以看到,這是為了保證以字為單位進(jìn)行寫操作。
556行,host->pio_bytes-= fifo,保存這次寫操作后,剩余的要寫的字節(jié)數(shù)。
557行,host->pio_count+= fifo,保存已經(jīng)寫了多少個字節(jié)。
559行,將字節(jié)數(shù)轉(zhuǎn)化為字?jǐn)?shù)。
561-562行,寫數(shù)據(jù)到SDIDAT寄存器。
563行,host->pio_ptr= ptr,保存當(dāng)前還剩余要寫數(shù)據(jù)的位置。
564行,結(jié)束這次while循環(huán),回到529行重新執(zhí)行上述過程。
566行,使能SDIIntMsk第4位,如果Tx FIFO填充滿一半,就產(chǎn)生中斷。
回到s3cmci_prepare_pio函數(shù)中:
1152行,使能SDIIntMsk第4位,如果Tx FIFO填充滿一半,就產(chǎn)生中斷。
1154行,使能SDIIntMsk第0位,如果Rx FIFO填充滿一半,就生產(chǎn)中斷。
1155行,使能SDIIntMsk第2位,如果Rx FIFO讀取了最后的數(shù)據(jù),就產(chǎn)生中斷。
回到s3cmci_send_request函數(shù):
1248行,調(diào)用s3cmci_send_command(host,cmd)發(fā)送命令。
該函數(shù)定義在drivers/mmc/host/s3cmci.c文件中: