1. 程式人生 > >SD/MMC卡塊裝置驅動程式

SD/MMC卡塊裝置驅動程式

int mmc_blk_issue_rq( struct mmc_queue * mq, struct request * req)
{
struct mmc_blk_data * md = mq-> data;
struct mmc_card * card = md-> queue.card ;
int ret;
  //認領控制器,發命令到卡設定card為選中狀態
if ( mmc_card_claim_host( card) )
goto cmd_err;
 
do
{
struct mmc_blk_request brq;
struct mmc_command cmd;
    
    //初始化MMC塊請求結構
memset( & brq, 0 , sizeof ( struct mmc_blk_request) ) ;
brq.mrq .cmd = & brq.cmd ;
brq.mrq .data = & brq.data ;
 
brq.cmd .arg = req-> sector <<
9 ;
brq.cmd .flags = MMC_RSP_R1;
brq.data .timeout_ns = card-> csd.tacc_ns * 10 ;
brq.data .timeout_clks = card-> csd.tacc_clks * 10 ;
brq.data .blksz_bits = md-> block_bits;
brq.data .blocks = req-> nr_sectors >> (
md-> block_bits - 9 ) ;
brq.stop .opcode = MMC_STOP_TRANSMISSION;
brq.stop .arg = 0 ;
brq.stop .flags = MMC_RSP_R1B;
 
if ( rq_data_dir( req) == READ) { //讀請求
brq.cmd .opcode = brq.data .blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
brq.data .flags |= MMC_DATA_READ;
} else { //寫
brq.cmd .opcode = MMC_WRITE_BLOCK;
brq.cmd .flags = MMC_RSP_R1B;
brq.data .flags |= MMC_DATA_WRITE;
brq.data .blocks = 1 ;
}
brq.mrq .stop = brq.data .blocks > 1 ? & brq.stop : NULL;
 
brq.data .sg = mq-> sg;
brq.data .sg_len = blk_rq_map_sg( req-> q, req, brq.data .sg ) ;
    //等待請求完成
mmc_wait_for_req( card-> host, & brq.mrq ) ;
……
do {
int err;
 
cmd.opcode = MMC_SEND_STATUS;
cmd.arg = card-> rca << 16 ;
cmd.flags = MMC_RSP_R1;
err = mmc_wait_for_cmd( card-> host, & cmd, 5 ) ;
if ( err) {
printk( KERN_ERR "%s: error %d requesting status/n " ,
req-> rq_disk-> disk_name, err) ;
goto cmd_err;
}
} while ( ! ( cmd.resp [ 0 ] & R1_READY_FOR_DATA) ) ;
 
//一個塊被成功傳輸
spin_lock_irq( & md-> lock) ;
ret = end_that_request_chunk( req, 1 , brq.data .bytes_xfered ) ;
if ( ! ret) {
//整個請求完全成功完成
add_disk_randomness( req-> rq_disk) ;
blkdev_dequeue_request( req) ; //從佇列中刪除請求
end_that_request_last( req) ; //寫一些更新資訊
}
spin_unlock_irq( & md-> lock) ;
} while ( ret) ;
 
mmc_card_release_host( card) ;
 
return 1 ;
 
cmd_err:
mmc_card_release_host( card) ;
 
spin_lock_irq( & md-> lock) ;
do {
    //結束請求req上的I/O,操作成功時返回0
ret = end_that_request_chunk( req, 0 ,
    req-> current_nr_sectors << 9 ) ;
} while ( ret) ;
 
add_disk_randomness( req-> rq_disk) ;
blkdev_dequeue_request( req) ;
end_that_request_last( req) ;
spin_unlock_irq( & md-> lock) ;
 
return 0 ;
}