1
- use crate :: syscall :: SystemError ;
1
+ use alloc :: sync :: Arc ;
2
2
3
- use super :: device:: Device ;
3
+ use crate :: { kerror, syscall:: SystemError } ;
4
+
5
+ use super :: {
6
+ device:: { mkdev, Device , DeviceNumber , IdTable , CHARDEVS , DEVICE_MANAGER , DEVMAP } ,
7
+ map:: {
8
+ kobj_map, kobj_unmap, DeviceStruct , DEV_MAJOR_DYN_END , DEV_MAJOR_DYN_EXT_END ,
9
+ DEV_MAJOR_DYN_EXT_START , DEV_MAJOR_HASH_SIZE , DEV_MAJOR_MAX , MINOR_MASK ,
10
+ } ,
11
+ } ;
4
12
5
13
pub trait CharDevice : Device {
6
14
/// Notice buffer对应设备按字节划分,使用u8类型
@@ -23,3 +31,184 @@ pub trait CharDevice: Device {
23
31
/// @brief: 同步信息,把所有的dirty数据写回设备 - 待实现
24
32
fn sync ( & self ) -> Result < ( ) , SystemError > ;
25
33
}
34
+
35
+ /// @brief 字符设备框架函数集
36
+ pub struct CharDevOps ;
37
+
38
+ impl CharDevOps {
39
+ /// @brief: 主设备号转下标
40
+ /// @parameter: major: 主设备号
41
+ /// @return: 返回下标
42
+ #[ allow( dead_code) ]
43
+ fn major_to_index ( major : usize ) -> usize {
44
+ return major % DEV_MAJOR_HASH_SIZE ;
45
+ }
46
+
47
+ /// @brief: 动态获取主设备号
48
+ /// @parameter: None
49
+ /// @return: 如果成功,返回主设备号,否则,返回错误码
50
+ #[ allow( dead_code) ]
51
+ fn find_dynamic_major ( ) -> Result < usize , SystemError > {
52
+ let chardevs = CHARDEVS . lock ( ) ;
53
+ // 寻找主设备号为234~255的设备
54
+ for index in ( DEV_MAJOR_DYN_END ..DEV_MAJOR_HASH_SIZE ) . rev ( ) {
55
+ if let Some ( item) = chardevs. get ( index) {
56
+ if item. is_empty ( ) {
57
+ return Ok ( index) ; // 返回可用的主设备号
58
+ }
59
+ }
60
+ }
61
+ // 寻找主设备号在384~511的设备
62
+ for index in ( DEV_MAJOR_DYN_EXT_END + 1 ..DEV_MAJOR_DYN_EXT_START + 1 ) . rev ( ) {
63
+ if let Some ( chardevss) = chardevs. get ( Self :: major_to_index ( index) ) {
64
+ let mut flag = true ;
65
+ for item in chardevss {
66
+ if item. device_number ( ) . major ( ) == index {
67
+ flag = false ;
68
+ break ;
69
+ }
70
+ }
71
+ if flag {
72
+ // 如果数组中不存在主设备号等于index的设备
73
+ return Ok ( index) ; // 返回可用的主设备号
74
+ }
75
+ }
76
+ }
77
+ return Err ( SystemError :: EBUSY ) ;
78
+ }
79
+
80
+ /// @brief: 注册设备号,该函数需要指定主设备号
81
+ /// @parameter: from: 主设备号
82
+ /// count: 次设备号数量
83
+ /// name: 字符设备名
84
+ /// @return: 如果注册成功,返回设备号,否则,返回错误码
85
+ #[ allow( dead_code) ]
86
+ pub fn register_chardev_region (
87
+ from : DeviceNumber ,
88
+ count : usize ,
89
+ name : & ' static str ,
90
+ ) -> Result < DeviceNumber , SystemError > {
91
+ Self :: __register_chardev_region ( from, count, name)
92
+ }
93
+
94
+ /// @brief: 注册设备号,该函数自动分配主设备号
95
+ /// @parameter: baseminor: 次设备号
96
+ /// count: 次设备号数量
97
+ /// name: 字符设备名
98
+ /// @return: 如果注册成功,返回,否则,返回false
99
+ #[ allow( dead_code) ]
100
+ pub fn alloc_chardev_region (
101
+ baseminor : usize ,
102
+ count : usize ,
103
+ name : & ' static str ,
104
+ ) -> Result < DeviceNumber , SystemError > {
105
+ Self :: __register_chardev_region ( mkdev ( 0 , baseminor) , count, name)
106
+ }
107
+
108
+ /// @brief: 注册设备号
109
+ /// @parameter: device_number: 设备号,主设备号如果为0,则动态分配
110
+ /// minorct: 次设备号数量
111
+ /// name: 字符设备名
112
+ /// @return: 如果注册成功,返回设备号,否则,返回错误码
113
+ fn __register_chardev_region (
114
+ device_number : DeviceNumber ,
115
+ minorct : usize ,
116
+ name : & ' static str ,
117
+ ) -> Result < DeviceNumber , SystemError > {
118
+ let mut major = device_number. major ( ) ;
119
+ let baseminor = device_number. minor ( ) ;
120
+ if major >= DEV_MAJOR_MAX {
121
+ kerror ! (
122
+ "DEV {} major requested {} is greater than the maximum {}\n " ,
123
+ name,
124
+ major,
125
+ DEV_MAJOR_MAX - 1
126
+ ) ;
127
+ }
128
+ if minorct > MINOR_MASK + 1 - baseminor {
129
+ kerror ! ( "DEV {} minor range requested ({}-{}) is out of range of maximum range ({}-{}) for a single major\n " ,
130
+ name, baseminor, baseminor + minorct - 1 , 0 , MINOR_MASK ) ;
131
+ }
132
+ let chardev = DeviceStruct :: new ( mkdev ( major, baseminor) , minorct, name) ;
133
+ if major == 0 {
134
+ // 如果主设备号为0,则自动分配主设备号
135
+ major = Self :: find_dynamic_major ( ) . expect ( "Find synamic major error.\n " ) ;
136
+ }
137
+ if let Some ( items) = CHARDEVS . lock ( ) . get_mut ( Self :: major_to_index ( major) ) {
138
+ let mut insert_index: usize = 0 ;
139
+ for ( index, item) in items. iter ( ) . enumerate ( ) {
140
+ insert_index = index;
141
+ match item. device_number ( ) . major ( ) . cmp ( & major) {
142
+ core:: cmp:: Ordering :: Less => continue ,
143
+ core:: cmp:: Ordering :: Greater => {
144
+ break ; // 大于则向后插入
145
+ }
146
+ core:: cmp:: Ordering :: Equal => {
147
+ if item. device_number ( ) . minor ( ) + item. minorct ( ) <= baseminor {
148
+ continue ; // 下一个主设备号大于或者次设备号大于被插入的次设备号最大值
149
+ }
150
+ if item. base_minor ( ) >= baseminor + minorct {
151
+ break ; // 在此处插入
152
+ }
153
+ return Err ( SystemError :: EBUSY ) ; // 存在重合的次设备号
154
+ }
155
+ }
156
+ }
157
+ items. insert ( insert_index, chardev) ;
158
+ }
159
+ return Ok ( mkdev ( major, baseminor) ) ;
160
+ }
161
+
162
+ /// @brief: 注销设备号
163
+ /// @parameter: major: 主设备号,如果为0,动态分配
164
+ /// baseminor: 起始次设备号
165
+ /// minorct: 次设备号数量
166
+ /// @return: 如果注销成功,返回(),否则,返回错误码
167
+ fn __unregister_chardev_region (
168
+ device_number : DeviceNumber ,
169
+ minorct : usize ,
170
+ ) -> Result < ( ) , SystemError > {
171
+ if let Some ( items) = CHARDEVS
172
+ . lock ( )
173
+ . get_mut ( Self :: major_to_index ( device_number. major ( ) ) )
174
+ {
175
+ for ( index, item) in items. iter ( ) . enumerate ( ) {
176
+ if item. device_number ( ) == device_number && item. minorct ( ) == minorct {
177
+ // 设备号和数量都相等
178
+ items. remove ( index) ;
179
+ return Ok ( ( ) ) ;
180
+ }
181
+ }
182
+ }
183
+ return Err ( SystemError :: EBUSY ) ;
184
+ }
185
+
186
+ /// @brief: 字符设备注册
187
+ /// @parameter: cdev: 字符设备实例
188
+ /// dev_t: 字符设备号
189
+ /// range: 次设备号范围
190
+ /// @return: none
191
+ #[ allow( dead_code) ]
192
+ pub fn cdev_add ( cdev : Arc < dyn CharDevice > , id_table : IdTable , range : usize ) {
193
+ if Into :: < usize > :: into ( id_table. device_number ( ) ) == 0 {
194
+ kerror ! ( "Device number can't be 0!\n " ) ;
195
+ }
196
+ DEVICE_MANAGER . add_device ( id_table. clone ( ) , cdev. clone ( ) ) ;
197
+ kobj_map (
198
+ DEVMAP . clone ( ) ,
199
+ id_table. device_number ( ) ,
200
+ range,
201
+ cdev. clone ( ) ,
202
+ )
203
+ }
204
+
205
+ /// @brief: 字符设备注销
206
+ /// @parameter: dev_t: 字符设备号
207
+ /// range: 次设备号范围
208
+ /// @return: none
209
+ #[ allow( dead_code) ]
210
+ pub fn cdev_del ( id_table : IdTable , range : usize ) {
211
+ DEVICE_MANAGER . remove_device ( & id_table) ;
212
+ kobj_unmap ( DEVMAP . clone ( ) , id_table. device_number ( ) , range) ;
213
+ }
214
+ }
0 commit comments