Miscellaneous devices, which are special in the character device, it's main device number, is 10, different miscellaneous devices, which are differentiated by the secondary device number.
1. Registration and cancellation
int misc_register (struct miscdevice * misc)
Complete the registration of miscellaneous equipment,
int misc_deregister (struct miscdevice *misc)
Visible, device registration and logoff, are set to struct miscdevice struct
2. struct Miscdevice structural body
structMiscdevice {intMinor; Const Char*name;//name Const structFile_operations *fops;//file operation structure Body structList_head list; structDevice *parent; structDevice *This_device; Const Char*nodename; mode_t mode; };
struct, name is the name registered, will be in the/dev directory, the name of the display, the most important is the struct file_operations, when registering miscellaneous devices, the structure of the character device and miscellaneous devices to bind,
When the minor is Misc_dynamic_minor, the Miscdevice core layer automatically looks for a spare secondary device number,
3. Miscellaneous devices and character device drivers
Miscellaneous devices, which are essentially character device drivers, are just a special point. The main device number of the miscellaneous device, which is fixed at 10, distinguishes the device by the secondary device number. After registering the miscellaneous device, there is a name device node under the/dev/directory, and the class information is automatically generated under/sys/clas/misc, so that, to a certain extent, it is simpler than a standard character device driver to lose.
4. Process
struct ConstFile_operations Xxxx_fops ={. Unlock_ioctl=xxx_ioctl, XXXX}; structMiscdevice Xxx_dev ={. Minor=Misc_dynamic_minor,. Name="xxx",. FoPs=Xxxx_fops};Static int__init Xxx_init () {returnMisc_register (&xxx_dev);}void__exit Xxx_exit () {returnMisc_deregister (&xxx_dev);}
When calling Misc_register (&xxx_dev); , with the help of Misc_open, the implementation will Xxx_dev become file Private_data, that is, the system will help us achieve file->private_data = Xxx_dev.
Second, the bus flat, equipment, drive
In the actual programming, the most hope is that a set of support, can support a class of all devices, such as the same set of DM9000 drive, it is best to meet on different boards running, so in order to achieve the goal, the proposed bus, equipment, driver software architecture.
Driver writing code, there is some information about the device information, such as IO address, memory resource address, the rest of the operation of these devices, so, the information of these corresponding devices are extracted to a file, a device file, it only do the resources of different devices to define, Different platforms set different device files separately.
The drive is the operation of the device.
Bus, the main is to complete the equipment and the driver of the cooperation. Bus, device, drive software architecture, you can make the drive a universal.
When the system registers the device, the bus will match the corresponding device according to the information of the device, similarly, when the driver registers, the bus will run the matching device according to the information of the drive, and when the corresponding driver or device is found, the probe function of the driver file will be called.
2.1, Platform_device and Platform_driver
Because of the proposed bus, equipment, drive This software architecture, Linux fictitious virtual bus, called platform bus, equipment called Platform_device, Drive becomes platform_driver.
The platform_device has a corresponding structure,
structPlatform_device {Const Char* NAME;//Device Name intID; structDevice Dev;//Equipmentu32 num_resources; structResource * resource;//Resources Const structPLATFORM_DEVICE_ID *Id_entry; /*MFD Cell Pointer*/ structMfd_cell *Mfd_cell; /*Arch Specific Additions*/ structpdev_archdata Archdata;};
Platform_driver structure, we only need to pay attention to the name of the device, as well as the resources of the device.
structPlatform_driver {int(*probe) (structPlatform_device *);//Probe int(*remove) (structPlatform_device *);//Delete void(*shutdown) (structPlatform_device *); int(*suspend) (structPlatform_device *, pm_message_t State); int(*resume) (structPlatform_device *); structDevice_driver driver; Const structPLATFORM_DEVICE_ID *id_table;//ID of the platform device,};
The status of Platform_driver structure is equal to I2c_driver, Spi_driver, Usb_driver and Pci_driver. So, in the implementation of the I²c drive, you can use I2c_driver, of course, it can be platform_driver.
Device-to-driver matching is mainly achieved by means of the device name:
struct Platform_device Registers a name that specifies the name of the device, and the const struct platform_device_id inside the struct platform_driver *id_tabl e table, is the name of the different devices registered with the driver support, it is the match two names, after the successful match, will call the driver end of the probe function. Usually inside is probe inside, complete new character device drive operation.
2.2. Device Registration
When you create a new platform_device struct (or you can create a new pointer and then implement it via the Platform_device_alloc interface), you need to register the device with the kernel after you have finished setting the resource and name.
Device registration into the kernel:
Platform_device_add (struct platform_device *pdev)
Device canceled from kernel:
Platform_device_unregister (struct platform_device * pdev)
2.3, Driver's registration
struct Platform_driver inside the id_table specified the name of the device, when the bus to complete the name of the match, it will call the driver-side probe function, generally in the probe function to complete the registration, registration of the implementation, is generally registered as a character device drive or miscellaneous equipment.
3., device resources, driver access to resources
struct Resource { resource_size_t start; resource_size_t end; Const Char *name; Long flags; struct resource *parent, *sibling, * child;};
The resource structure inside the device structure realizes the description of the equipment resource. In general, you only need to care about start, end, flags.
Start: The starting value of the device resource
End: The ending value of the device resource
Flags: Flags for device resource types. Ioresource_io Ioresource_mem IORESOURCE_IRQ IORESOURCE_DMA
When flag is Ioresource_mem, start is the beginning of the memory address, and end is the end address of the memory resource.
When flag is IORESOURCE_IRQ, start and end are the starting and ending values of the interrupt number. If it's just a break, then the start and end values are the same.
Device has a hardware-related board-level resource, so the driver side, should need to obtain board-level resources, to obtain the relevant device resources, driver is through this interface to achieve matching device-side resources:
Platform_get_resource (structintint num)
Go to device to get the resource specified by type.
If it is a resource that gets an IRQ, you can also use the directly encapsulated interface:
PLATFORM_GET_IRQ (structint
4. Code
Drive development-Detailed code with Song Baohua Linux devices,
4.1. Device
Static structPlatform_device *globalfifo_pdev;//PointersStatic int__init Globalfifodev_init (void) { intret; Globalfifo_pdev= Platform_device_alloc ("Globalfifo", -1);//assign a device, specify a name if(!Globalfifo_pdev)return-Enomem; RET= Platform_device_add (Globalfifo_pdev);//registering device into the bus if(ret) {platform_device_put (Globalfifo_pdev); returnret; } return 0;} Module_init (globalfifodev_init);Static void__exit Globalfifodev_exit (void) {platform_device_unregister (Globalfifo_pdev); //To unregister a device from the bus} module_exit (globalfifodev_exit);
4.3, driver
Static intGlobalfifo_probe (structPlatform_device *Pdev) {ret= Misc_register (Miscdev);//Registration of miscellaneous devices if(Ret <0) Gotoerr;}Static intGlobalfifo_remove (structPlatform_device *Pdev) {Misc_deregister (Miscdev); //Logout return 0; }Static structPlatform_driver Globalfifo_driver ={. Driver={. Name="Globalfifo",//name. Owner =This_module,},. Probe= Globalfifo_probe,//if the name match succeeds, call the probe function. remove =Globalfifo_remove,};module_platform_driver (globalfifo_driver); //platform Equipment driver entrance
9, Linux-driven miscellaneous devices