miscdevice混雜裝置驅動
原文地址:http://blog.csdn.net/tong646591/article/details/8301925
定義:字元裝置的一種,它們共享一個主裝置號(10),但次裝置號不同,所有的混雜裝置形成一個連結串列,對裝置訪問時核心根據次裝置號查詢到相應的miscdevice裝置。
例如:觸控式螢幕,LED,按鍵,串列埠。
即:為了節約主裝置號,將某些裝置用連結串列的形式連線在一起,最後通過查詢次裝置區分。這裡用主裝置無法匹配出裝置驅動,只能找到連結串列,再通過次裝置號,才能找到裝置驅動。而之前所學的,一般字元裝置,通過主裝置號,就能找到裝置驅動了。
混雜裝置驅動內建有自動建立裝置節點的程式碼,所以編譯好之後,能自動建立裝置節點。
相關的巨集,定義在 kernel/include/linux/miscdevice.h
[cpp] view plaincopy
#ifndef _LINUX_MISCDEVICE_H
#define _LINUX_MISCDEVICE_H
#include <linux/module.h>
#include <linux/major.h>
/*
* These allocations are managed by
* entry that is not in assigned your entry may well be moved and
* reassigned, or set dynamic if a fixed value is not justified.
*/
#define PSMOUSE_MINOR 1
#define MS_BUSMOUSE_MINOR 2
#define ATIXL_BUSMOUSE_MINOR 3
/*#define AMIGAMOUSE_MINOR 4 FIXME OBSOLETE */
#define ATARIMOUSE_MINOR 5
#define SUN_MOUSE_MINOR 6
#define APOLLO_MOUSE_MINOR 7
#define PC110PAD_MINOR 9
/*#define ADB_MOUSE_MINOR 10 FIXME OBSOLETE */
#define WATCHDOG_MINOR 130 /* Watchdog timer */
#define TEMP_MINOR 131 /* Temperature Sensor */
#define RTC_MINOR 135
#define EFI_RTC_MINOR 136 /* EFI Time services */
#define SUN_OPENPROM_MINOR 139
#define DMAPI_MINOR 140 /* DMAPI */
#define NVRAM_MINOR 144
#define SGI_MMTIMER 153
#define STORE_QUEUE_MINOR 155
#define I2O_MINOR 166
#define MICROCODE_MINOR 184
#define TUN_MINOR 200
#define MWAVE_MINOR 219 /* ACP/Mwave Modem */
#define MPT_MINOR 220
#define MPT2SAS_MINOR 221
#define HPET_MINOR 228
#define FUSE_MINOR 229
#define KVM_MINOR 232
#define BTRFS_MINOR 234
#define AUTOFS_MINOR 235
#define MISC_DYNAMIC_MINOR 255
struct device;
struct miscdevice {
int minor; //次裝置號
const char *name; //裝置名
const struct file_operations *fops;//檔案操作
struct list_head list; //形成連結串列
struct device *parent;
struct device *this_device;
const char *nodename;
mode_t mode;
};
extern int misc_register(struct miscdevice * misc); //混雜設備註冊
extern int misc_deregister(struct miscdevice *misc); //混雜設備註銷
#define MODULE_ALIAS_MISCDEV(minor) \
MODULE_ALIAS("char-major-" __stringify(MISC_MAJOR) \
"-" __stringify(minor))
#endif
雜項裝置的核心函式的定義位於:kernel/drivers/char/misc.c
/**
* misc_register - register a miscellaneous device
* @misc: device structure
*
* Register a miscellaneous device with the kernel. If the minor
* number is set to %MISC_DYNAMIC_MINOR a minor number is assigned
* and placed in the minor field of the structure. For other cases
* the minor number requested is used.
*
* The structure passed is linked into the kernel and may not be
* destroyed until it has been unregistered.
*
* A zero is returned on success and a negative errno code for
* failure.
*/
int misc_register(struct miscdevice * misc)
{
struct miscdevice *c;
dev_t dev;
int err = 0;
INIT_LIST_HEAD(&misc->list);
mutex_lock(&misc_mtx);
list_for_each_entry(c, &misc_list, list) {
if (c->minor == misc->minor) {
mutex_unlock(&misc_mtx);
return -EBUSY;
}
}
if (misc->minor == MISC_DYNAMIC_MINOR) { //#define MISC_DYNAMIC_MINOR 255
int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS); //#define DYNAMIC_MINORS 64 /* like dynamic majors */
if (i >= DYNAMIC_MINORS) {
mutex_unlock(&misc_mtx);
return -EBUSY;
}
misc->minor = DYNAMIC_MINORS - i - 1;
set_bit(i, misc_minors);
}
//獲得裝置號
dev = MKDEV(MISC_MAJOR, misc->minor); //#define MISC_MAJOR 10 // 在 kernel/include/linux/major.h 中定義。
misc->this_device = device_create(misc_class, misc->parent, dev, misc, "%s", misc->name);//說明了混雜裝置驅動內部有自動裝置驅動,可自動
//建立裝置節點
if (IS_ERR(misc->this_device)) {
int i = DYNAMIC_MINORS - misc->minor - 1;
if (i < DYNAMIC_MINORS && i >= 0)
clear_bit(i, misc_minors);
err = PTR_ERR(misc->this_device);
goto out;
}
/*
* Add it to the front, so that later devices can "override"
* earlier defaults
*/
list_add(&misc->list, &misc_list);
out:
mutex_unlock(&misc_mtx);
return err;
}
/**
* misc_deregister - unregister a miscellaneous device
* @misc: device to unregister
*
* Unregister a miscellaneous device that was previously
* successfully registered with misc_register(). Success
* is indicated by a zero return, a negative errno code
* indicates an error.
*/
int misc_deregister(struct miscdevice *misc)
{
int i = DYNAMIC_MINORS - misc->minor - 1;
if (list_empty(&misc->list))
return -EINVAL;
mutex_lock(&misc_mtx);
list_del(&misc->list);
device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
if (i < DYNAMIC_MINORS && i >= 0)
clear_bit(i, misc_minors);
EXPORT_SYMBOL(misc_register);
EXPORT_SYMBOL(misc_deregister);
static char *misc_devnode(struct device *dev, mode_t *mode)
{
struct miscdevice *c = dev_get_drvdata(dev);
if (mode && c->mode)
*mode = c->mode;
if (c->nodename)
return kstrdup(c->nodename, GFP_KERNEL);
return NULL;
}
static int __init misc_init(void)
{
int err;
#ifdef CONFIG_PROC_FS
proc_create("misc", 0, NULL, &misc_proc_fops);
#endif
misc_class = class_create(THIS_MODULE, "misc");
err = PTR_ERR(misc_class);
if (IS_ERR(misc_class))
goto fail_remove;
err = -EIO;
if (register_chrdev(MISC_MAJOR,"misc",&misc_fops))
goto fail_printk;
misc_class->devnode = misc_devnode;
return 0;
fail_printk:
printk("unable to get major %d for misc devices\n", MISC_MAJOR);
class_destroy(misc_class);
fail_remove:
remove_proc_entry("misc", NULL);
return err;
}
subsys_initcall(misc_init);
以下是建立自動裝置節點相關程式碼
"kernel/drivers/base/core.c"
struct device *device_create(struct class *class, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...)
{
va_list vargs;
struct device *dev;
va_start(vargs, fmt);
dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
va_end(vargs);
return dev;
}
EXPORT_SYMBOL_GPL(device_create);
static int __match_devt(struct device *dev, void *data)
{
dev_t *devt = data;
return dev->devt == *devt;
}
/**
* device_destroy - removes a device that was created with device_create()
* @class: pointer to the struct class that this device was registered with
* @devt: the dev_t of the device that was previously registered
*
* This call unregisters and cleans up a device that was created with a
* call to device_create().
*/
void device_destroy(struct class *class, dev_t devt)
{
struct device *dev;
dev = class_find_device(class, NULL, &devt, __match_devt);
if (dev) {
put_device(dev);
device_unregister(dev);
}
}
EXPORT_SYMBOL_GPL(device_destroy);
相關推薦
miscdevice混雜裝置驅動
原文地址:http://blog.csdn.net/tong646591/article/details/8301925 定義:字元裝置的一種,它們共享一個主裝置號(10),但次裝置號不同,所有的混雜裝置形成一個連結串列,對裝置訪問時核心根據次裝置號查詢到相應的miscd
平臺裝置驅動和混雜裝置驅動
1. 平臺裝置驅動 在linux2.6以後的裝置驅動模型中,只關心裝置、驅動和匯流排這三個實體,匯流排將裝置驅動繫結。在向系統註冊一個裝置時會由匯流排匹配對應的驅動,相反當向系統註冊一個驅動時由匯流排匹配出對應的裝置。 在linux裝置和驅動通常要掛接在某條總線上,對於II
Linux核心混雜裝置驅動
1.linux核心混雜裝置驅動 1.1混雜裝置驅動特點: 本質上還是一類字元裝置,在驅動軟體上,混雜裝置的主裝置號已經由核心指定主裝置號為10; 各個混雜裝置個體通過次裝置號來區分;1.2linux核心描述混雜裝置的資料結構 struct miscdevice { int
linux misc混雜裝置驅動 .
一. misc結構體 struct miscdevice { int minor; //次裝置號 const char *name; //裝置名 const struct file_operations *fops; //操作函式集 struct list_head list; //連結串列
linux驅動修煉之道-混雜裝置
Linux驅動中把無法歸類的五花八門的裝置定義為混雜裝置(用miscdevice結構體表述)。miscdevice共享一個主裝置號MISC_MAJOR(即10),但次裝置號不同。 所有的miscdevice裝置形成了一個連結串列,對裝置訪問時核心根據次裝置號查詢對應的mi
linux裝置驅動開發學習--記憶體和IO訪問
一 I/O 埠 1. 讀寫位元組埠(8 位寬) unsigned inb(unsigned port); void outb(unsigned char byte, unsigned port); 2. 讀寫字埠(16 位寬) unsigned inw(unsigne
字元裝置驅動程式的三種寫法
驅動工程師如何去寫驅動程式? 要看原理圖。確定如何去操作硬體。 對於點亮led燈來說,確定引腳,檢視晶片手冊,確定如何去操作引腳,要設定哪些暫存器,如何設定這些暫存器才可以讓這個引腳輸出高電平或者低電平。 寫驅動程式 驅動程式起封裝作用,如何封裝。應用程式要操作硬體需要o
linux裝置驅動模型 - regmap
1. regmap介紹 regmap主要是為了方便操作暫存器而設計的,它將所有模組的暫存器(包括soc上模組的暫存器和外圍裝置的暫存器等) 抽象出來,用一套統一介面來操作暫存器 比如,如果要操作i2c裝置的暫存器,那麼就要呼叫i2c_transfer介面,要操作spi裝置的暫存
linux裝置驅動模型 - device/bus/driver
在linux驅動模型中,為了便於管理各種裝置,我們把不同裝置分別掛在他們對應的總線上,裝置對應的驅動程式也在總線上找,這樣就提出了deivce-bus-driver的模型,硬體上有許多裝置匯流排,那麼我們就在裝置模型上抽象出bus概念,相應的device就代表裝置,driver表示驅動,
linux裝置驅動模型 - sys/kobject
1. sysfs 1.1 sysfs檔案系統註冊 在系統啟動時會註冊sysfs檔案系統 (fs/sysfs/mount.c) int __init sysfs_init(void) { int err; sysfs_root = kernfs_creat
linux裝置驅動模型 - 驅動框架
linux驅動模型框架如圖所示: 1. kernfs 驅動最終是提供給使用者層使用,那麼其中的介面就是通過kernfs檔案系統來註冊,kernfs是一個通用的核心虛擬檔案系統 2. sysfs/kobject sysfs是裝置驅動檔案系統,裝置之間的各種關係會在在/
linux裝置驅動(3)I2C驅動
i2c驅動程式的核心是建立i2c_driver結構體 /* This is the driver that will be inserted */ static struct i2c_driver at24cxx_driver = { .driver = { .name
塊裝置驅動之二
一、將塊裝置新增到系統 register_blkdev並沒有真正將裝置新增到系統中,想要將裝置新增到系統中,需要使用如下API: void blk_register_region(dev_t devt, unsigned long range, struct module *module,
塊裝置驅動程式之一
一、塊裝置概述 linux支援的兩種重要的裝置型別分別是字元裝置和塊裝置,塊裝置可以隨機地以固定大小的塊傳送資料。與字元裝置相比,塊裝置有以下幾個特殊之處: 塊裝置可以從資料的任何位置進行訪問 塊資料總是以固定長度進行傳輸,即便請求的這是一個位元組 對塊裝置的訪問有大量的快
《linux裝置驅動開發》,基於最新的linux 4.0核心-----筆記
第二章 Linux 的核心結構及構建 ---->這一章是自己總結的 1、核心結構(主要是下面這幾個部分) 系統呼叫介面<–>System call interface 程序管理<------>Process manag
《裝置驅動程式》--Jonathan corbet,Alessandro rubini & Greg kroah-hartman
第二章 構造和執行模組 2.1核心模組與應用程式的對比 1、應用程式可以是C的庫函式,而驅動程式只能使用linux核心原始碼中的函式,而不能使用C的庫函式。 2、應用程式是有main函式的;而驅動程式沒有main函式 3、驅動程式有自己的入口和出口;而應用程式
linux裝置驅動 按鍵幾種寫法總結
對於基礎按鍵的驅動,有如下幾種寫法: (1)查詢 所謂查詢方法,主要描述應用程式會在while(1)裡面一直read,如果沒有資料會導致阻塞,佔用CPU;這種方法是最差的。 (2)中斷 中斷配合休眠會避免查詢法佔用CPU的缺點。 應用程式和查詢法沒有什麼區別, 但是驅動裡面的read
光碟安裝win7系統顯示缺少所需的cd dvd驅動器裝置驅動程式
注意:必須用內建光碟機才會好使。 這樣的問題是由於安裝版映象中不帶USB3.0驅動,安裝介質插到USB3.0介面導致。可以換到USB2.0的介面或是把USB3.0介面的裝置拔掉。 如果上面方法不行,則用下面方法: 1、首先進入BIOS,在BIOS中-Config-USB-USB3.0
WDF開發USB裝置驅動教程(1)
PDF下載地址(1.2版):連結地址 CY001開發板討論帖:連結地址 注:本文件新版本已出,請在部落格中查詢,或下載PDF全文文件。 連結地址WDF開發USB裝置驅動教程 by 張佩 文件說明 &
linux 裝置驅動 nand驅動框架
nand 裝置驅動(一)架構 使用mini2440 - nand 1. nand硬體 1.1 資源 LDATD0~7資料線和地址線是複用的,都是8位 既可以傳輸資料(命令或者資料), 也可以傳送地址訊號 訊號說明: CLE: 命令鎖存, 高表示cmd ALE: 地址鎖存, 高表示地址