跟着程序的流程我们来到
if (!mmc_card_present(card) && !mmc_card_dead(card)) {
if (mmc_register_card(card))
来看
/*
* Internal function. Register a new MMC card with the driver model.
*/
int mmc_register_card(struct mmc_card *card)
{
int ret;
snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
"%s:%04x", mmc_hostname(card->host), card->rca);
ret = device_add(&card->dev);
if (ret == 0) {
if (mmc_card_sd(card)) {
ret = device_create_file(&card->dev, &mmc_dev_attr_scr);
if (ret)
device_del(&card->dev);
}
}
return ret;
}
int device_add(struct device *dev)
{
……………………………………….
if ((error = device_add_attrs(dev)))
goto AttrsError;
if ((error = device_pm_add(dev)))
goto PMError;
if ((error = bus_add_device(dev)))//把设备加入到总线中
goto BusError;
kobject_uevent(&dev->kobj, KOBJ_ADD);
bus_attach_device(dev);在总线中去匹配自己的驱动(那一半)
…………………………………………..
}
void bus_attach_device(struct device * dev)
{
struct bus_type * bus = dev->bus;
if (bus) {
device_attach(dev);
klist_add_tail(&dev->knode_bus, &bus->klist_devices);
}
}
int device_attach(struct device * dev)
{
int ret = 0;
down(&dev->sem);
if (dev->driver) {
device_bind_driver(dev);
ret = 1;
} else
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
up(&dev->sem);
return ret;
}
static int __device_attach(struct device_driver * drv, void * data)
{
struct device * dev = data;
return driver_probe_device(drv, dev);
}
device_add(&card->dev)将到相应总线mmc_bus_type上去搜索相应驱动。找到驱动后就设置dev->driver=drv,并调用mmc_bus_type总线的probe函数被调用,即mmc_bus_probe函数;该函数在mmc_sysfs.c中:
static int mmc_bus_probe(struct device *dev)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = dev_to_mmc_card(dev);
return drv->probe(card);
}
然后会调用mmc_block.c中的probe函数,mmc_blk_probe()首先分配一个新的mmc_blk_data结构变量,然后调用mmc_init_queue,初始化blk队列。然后建立一个线程mmc_queue_thread()。
static int mmc_blk_probe(struct mmc_card *card)
{
struct mmc_blk_data *md;
int err;
/*
* Check that the card supports the command class(es) we need.
*/
if (!(card->csd.cmdclass & CCC_BLOCK_READ))
return -ENODEV;
md = mmc_blk_alloc(card);
if (IS_ERR(md))
return PTR_ERR(md);
err = mmc_blk_set_blksize(md, card);
if (err)
goto out;
//出入sd卡,驱动起来的时候会打印
printk(KERN_INFO "%s: %s %s %lluKiB %s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
(unsigned long long)(get_capacity(md->disk) >> 1),
md->read_only ? "(ro)" : "");
我的打印如下:
Enabling 1 bit mode
Enabling 1 bit mode
Enabling 1 bit mode
Enabling 1 bit mode
Enabling 1 bit mode
Enabling 1 bit mode
Enabling 1 bit mode
Enabling 1 bit mode
Enabling 4 bit mode
Enabling 4 bit mode
mmcblk0: mmc0:88e4 SU 16G 15558144KiB
mmcblk0:<7>mmc0: starting CMD7 arg 88e40000 flags 00000015
Enabling 4 bit mode
p1
……………………………………………………
mmc_set_drvdata(card, md);
add_disk(md->disk);
return 0;
out:
mmc_blk_put(md);
return err;
}
struct mmc_blk_data封装了struct gendisk 与 struct mmc_queue,而struct mmc_queue封装了struct mmc_card与struct request。
static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
{
struct mmc_blk_data *md;
int devidx, ret;
devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS);
if (devidx >= MMC_NUM_MINORS) //32
return ERR_PTR(-ENOSPC);
__set_bit(devidx, dev_use);
md = kmalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
if (!md) {
ret = -ENOMEM;
goto out;
}
memset(md, 0, sizeof(struct mmc_blk_data));
/*
* Set the read-only status based on the supported commands
* and the write protect switch.
*/
md->read_only = mmc_blk_readonly(card);
/*
* Both SD and MMC specifications state (although a bit
* unclearly in the MMC case) that a block size of 512
* bytes must always be supported by the card.
*/
md->block_bits = 9; // 2的9次方为512
md->disk = alloc_disk(1 << MMC_SHIFT);
if (md->disk == NULL) {
ret = -ENOMEM;
goto err_kfree;
}
spin_lock_init(&md->lock);
md->usage = 1;
ret = mmc_init_queue(&md->queue, card, &md->lock); //创建一个队列
if (ret)
goto err_putdisk;
md->queue.prep_fn = mmc_blk_prep_rq;
md->queue.issue_fn = mmc_blk_issue_rq;//请求传输函数
md->queue.data = md;
md->disk->major = major;
md->disk->first_minor = devidx << MMC_SHIFT;
md->disk->fops = &mmc_bdops;//块设备操作函数
md->disk->private_data = md;
md->disk->queue = md->queue.queue;
md->disk->driverfs_dev = &card->dev;
/*
* As discussed on lkml, GENHD_FL_REMOVABLE should:
*
* - be set for removable media with permanent block devices
* - be unset for removable block devices with permanent media
*
* Since MMC block devices clearly fall under the second
* case, we do not set GENHD_FL_REMOVABLE. Userspace
* should use the block device creation/destruction hotplug
* messages to tell when the card is present.
*/
sprintf(md->disk->disk_name, "mmcblk%d", devidx);
blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
/*
* The CSD capacity field is in units of read_blkbits.
* set_capacity takes units of 512 bytes.
*/
set_capacity(md->disk, card->csd.capacity << (card->csd.read_blkbits - 9));
return md;
err_putdisk:
put_disk(md->disk);
err_kfree:
kfree(md);
out:
return ERR_PTR(ret);
}
/**
* mmc_init_queue - initialise a queue structure.
* @mq: mmc queue
* @card: mmc card to attach this queue
* @lock: queue lock
*
* Initialise a MMC card request queue.
*/
int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock)
{
struct mmc_host *host = card->host;
u64 limit = BLK_BOUNCE_HIGH;
int ret;
if (host->dev->dma_mask && *host->dev->dma_mask)
limit = *host->dev->dma_mask;
mq->card = card;
mq->queue = blk_init_queue(mmc_request, lock);
if (!mq->queue)
return -ENOMEM;
blk_queue_prep_rq(mq->queue, mmc_prep_request);
blk_queue_bounce_limit(mq->queue, limit);
blk_queue_max_sectors(mq->queue, host->max_sectors);
blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
blk_queue_max_segment_size(mq->queue, host->max_seg_size);
mq->queue->queuedata = mq;
mq->req = NULL;
mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs,
GFP_KERNEL);
if (!mq->sg) {
ret = -ENOMEM;
goto cleanup_queue;
}
init_MUTEX(&mq->thread_sem);
//这里就是在读写sd卡时你所看到的内核线程mmcqd了
mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");
if (IS_ERR(mq->thread)) {
ret = PTR_ERR(mq->thread);
goto free_sg;
}
return 0;
free_sg:
kfree(mq->sg);
mq->sg = NULL;
cleanup_queue:
blk_cleanup_queue(mq->queue);
return ret;
}
至此,驱动向系统添加了一个块设备。
请求处理过程:
mmc_request--->mmc_queue_thread----->mmc_blk_issue_rq---->mmc_wait_for_req--->mmc_start_request----> mmc_davinci_ops里边的mmc_davinci_request就被调用了;