I would like to commemorate the past
Taking sdio as an example, mmc_attach_sdio is used to match the driver and device. In essence, sdio_bus matching rules are used to match the driver and device. In mmc_attach_sdio, the first is MMC matching a bus, that is, the bus used for MMC bus to process the host. In sdio, the SD card memory MMC is a physical device, while in non-SD card memory, such as the sdio interface, MMC is characterized as bus, this is important. In addition to MMC bus, sdio_bus exists.
Int mmc_attach_sdio (struct mmc_host * Host, u32 OCR)
{
Interr;
Inti, funcs;
Structmmc_card * card;
Mmc_attach_bus (host, & mmc_sdio_ops); -- host matches an MMC Bus
Card = mmc_alloc_card (host, null); -- apply for a card entity, similar to a bus device.
Card-> type = mmc_type_sdio;
Card-> sdio_funcs = funcs;
Host-> card = card;
For (I = 0; I <funcs; I ++ ){
Sdio_init_func (host-> card, I + 1 );
}
Mmc_release_host (host );
Mmc_add_card (host-> card );
For (I = 0; I <funcs; I ++ ){
Sdio_add_func (host-> card-> sdio_func [I]);
}
Return0;
}
What is hard to understand is func, which is actually the encapsulation of a physical device and can be considered as a device.
Struct sdio_func * sdio_alloc_func (structmmc_card * card)
{
Structsdio_func * func;
Func = kzarloc (sizeof (struct sdio_func), gfp_kernel );
Func-> card = card;
Device_initialize (& func-> Dev );
Func-> Dev. Parent = & Card-> dev; -- obviously, the card device is the parent device of the sdio device.
Func-> Dev. Bus = & sdio_bus_type;
Func-> Dev. Release = sdio_release_func;
Returnfunc;
}
The above code is clear at a glance. It is the encapsulation of a specific device entity. Its bus type is sdio_bus. sdio_init_func, which only initializes a device without register. The register of the device is implemented in sdio_add_func. Similarly, the card object is not registered before mmc_add_card. The registration of the device is realized only in the mmc_add_card function.
Now the device registration is complete. In fact, the sdio bus is similar to the USB bus. Why? Children's shoes who have compiled USB drivers should know that writing USB drivers is only writing driver loading, and there is no specific device loading entity, which leads to a lot of confusion about children's shoes. Why is there no device loading, in fact, when a USB device is inserted, a USB device entity is dynamically created. After the USB device entity is created, a matching driver is called based on different device IDs. The same is true for sdio devices. The code above is confusing, so it is impossible to see the loading of specific devices. In fact, the above Code includes the MMC host driver.
3. Driver Loading
Take the sdio driver as an example. registering an sdio driver will call the following function.
Int sdio_register_driver (struct sdio_driver * DRV)
{
DRV-> DRV. Name = DRV-> name;
DRV-> DRV. Bus = & sdio_bus_type;
Returndriver_register (& DRV-> DRV );
}
In fact, it is easy to understand that sdio_driver is actually a driver encapsulation, and the driver's bus is sdio_bus_type. The driver of this device is very simple. Let's look at the sdio_driver structure.
Struct sdio_driver {
Char * Name; -- driver name
Conststruct sdio_device_id * id_table; -- driver device ID
INT (* probe) (struct sdio_func *, const struct sdio_device_id *);
Void (* remove) (struct sdio_func *);
Structdevice_driver DRV;
};
I'm familiar with id_table. In the USB driver, it depends on how the device matches the driver. In sdio, the device and driver are matched based on the id_table.
4. Matching between drivers and devices
After introducing device registration and driver registration, let's see how these two match. Remember that the sdio driver has two buses, one is MMC bus and the other is sdio bus.
First, let's look at the match of MMC bus.
Static int mmc_bus_match (struct device * Dev, struct device_driver * DRV)
{
Return1;
}
This is very easy, just 1.
Check the match of sdio bus.
Static int sdio_bus_match (struct device * Dev, struct device_driver * DRV)
{
Structsdio_func * func = dev_to_sdio_func (Dev );
Structsdio_driver * sdrv = to_sdio_driver (DRV );
If (sdio_match_device (func, sdrv ))
Return1;
Return0;
}
By viewing the implementation of the above Code, you will find that the matching between the device and the driver is achieved based on id_table.
5. Probe
If a corresponding device or driver is found during device registration or driver registration, the corresponding driver is called. But remember that the probe of MMC bus will be called first, followed by the probe of sdio bus. The implementation process is similar to that of platfrom.
Vi. Summary
To put it bluntly, sdio is still a bus. Its nature is still inseparable from drivers and devices. If you have experience with USB drivers, you will have a good understanding of the drivers of sdio bus. In the Linux kernel, you can bypass the class.