1 /// 引入Module 2 use crate::{ 3 driver::base::{ 4 device::{ 5 device_number::{DeviceNumber, Major}, 6 Device, DeviceError, IdTable, BLOCKDEVS, 7 }, 8 map::{ 9 DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START, 10 DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX, 11 }, 12 }, 13 kerror, 14 }; 15 16 use alloc::{sync::Arc, vec::Vec}; 17 use core::any::Any; 18 use system_error::SystemError; 19 20 use super::disk_info::Partition; 21 22 /// 该文件定义了 Device 和 BlockDevice 的接口 23 /// Notice 设备错误码使用 Posix 规定的 int32_t 的错误码表示,而不是自己定义错误enum 24 25 // 使用方法: 26 // 假设 blk_dev 是块设备 27 // <blk_dev as Device>::read_at() 调用的是Device的函数 28 // <blk_dev as BlockDevice>::read_at() 调用的是BlockDevice的函数 29 30 /// 定义类型 31 pub type BlockId = usize; 32 33 /// 定义常量 34 pub const BLK_SIZE_LOG2_LIMIT: u8 = 12; // 设定块设备的块大小不能超过 1 << 12. 35 /// 在DragonOS中,我们认为磁盘的每个LBA大小均为512字节。(注意,文件系统的1个扇区可能事实上是多个LBA) 36 pub const LBA_SIZE: usize = 512; 37 38 /// @brief 块设备的迭代器 39 /// @usage 某次操作读/写块设备的[L,R]范围内的字节, 40 /// 那么可以使用此结构体进行迭代遍历,每次调用next()返回一个BlockRange 41 pub struct BlockIter { 42 pub begin: usize, // 迭代器的起始位置 -> 块设备的地址 (单位是字节) 43 pub end: usize, 44 pub blk_size_log2: u8, 45 pub multiblock: bool, // 是否启用连续整块同时遍历 46 } 47 48 /// @brief Range搭配迭代器BlockIter使用,[L,R]区间被分割成多个小的Range 49 /// Range要么是整块,要么是一块的某一部分 50 /// 细节: range = [begin, end) 左闭右开 51 pub struct BlockRange { 52 pub lba_start: usize, // 起始块的lba_id 53 pub lba_end: usize, // 终止块的lba_id 54 pub begin: usize, // 起始位置在块内的偏移量, 如果BlockIter启用Multiblock,则是多个块的偏移量 55 pub end: usize, // 结束位置在块内的偏移量,单位是字节 56 pub blk_size_log2: u8, 57 } 58 59 impl BlockIter { 60 #[allow(dead_code)] 61 pub fn new(start_addr: usize, end_addr: usize, blk_size_log2: u8) -> BlockIter { 62 return BlockIter { 63 begin: start_addr, 64 end: end_addr, 65 blk_size_log2, 66 multiblock: false, 67 }; 68 } 69 pub fn new_multiblock(start_addr: usize, end_addr: usize, blk_size_log2: u8) -> BlockIter { 70 return BlockIter { 71 begin: start_addr, 72 end: end_addr, 73 74 blk_size_log2, 75 multiblock: true, 76 }; 77 } 78 79 /// 获取下一个整块或者不完整的块 80 pub fn next_block(&mut self) -> BlockRange { 81 let blk_size_log2 = self.blk_size_log2; 82 let blk_size = 1usize << self.blk_size_log2; 83 let lba_id = self.begin / blk_size; 84 let begin = self.begin % blk_size; 85 let end = if lba_id == self.end / blk_size { 86 self.end % blk_size 87 } else { 88 blk_size 89 }; 90 91 self.begin += end - begin; 92 93 return BlockRange { 94 lba_start: lba_id, 95 lba_end: lba_id + 1, 96 begin, 97 end, 98 blk_size_log2, 99 }; 100 } 101 102 /// 如果能返回多个连续的整块,则返回;否则调用next_block()返回不完整的块 103 pub fn next_multiblock(&mut self) -> BlockRange { 104 let blk_size_log2 = self.blk_size_log2; 105 let blk_size = 1usize << self.blk_size_log2; 106 let lba_start = self.begin / blk_size; 107 let lba_end = self.end / blk_size; 108 109 // 如果不是整块,先返回非整块的小部分 110 if __bytes_to_lba(self.begin, blk_size) 111 != __bytes_to_lba(self.begin + blk_size - 1, blk_size) 112 || lba_start == lba_end 113 { 114 return self.next_block(); 115 } 116 117 let begin = self.begin % blk_size; // 因为是多个整块,这里必然是0 118 let end = __lba_to_bytes(lba_end, blk_size) - self.begin; 119 120 self.begin += end - begin; 121 122 return BlockRange { 123 lba_start, 124 lba_end, 125 begin, 126 end, 127 blk_size_log2, 128 }; 129 } 130 } 131 132 /// BlockIter 函数实现 133 impl Iterator for BlockIter { 134 type Item = BlockRange; 135 136 fn next(&mut self) -> Option<<Self as Iterator>::Item> { 137 if self.begin >= self.end { 138 return None; 139 } 140 if self.multiblock { 141 return Some(self.next_multiblock()); 142 } else { 143 return Some(self.next_block()); 144 } 145 } 146 } 147 148 /// BlockRange 函数实现 149 impl BlockRange { 150 #[allow(dead_code)] 151 pub fn is_empty(&self) -> bool { 152 return self.end == self.begin; 153 } 154 pub fn len(&self) -> usize { 155 return self.end - self.begin; 156 } 157 /// 判断是不是整块 158 pub fn is_full(&self) -> bool { 159 return self.len() == (1usize << self.blk_size_log2); 160 } 161 /// 判断是不是多个整块连在一起 162 pub fn is_multi(&self) -> bool { 163 return self.len() >= (1usize << self.blk_size_log2) 164 && (self.len() % (1usize << self.blk_size_log2) == 0); 165 } 166 /// 获取 BlockRange 在块设备内部的起始位置 (单位是字节) 167 pub fn origin_begin(&self) -> usize { 168 return (self.lba_start << self.blk_size_log2) + self.begin; 169 } 170 /// 获取 BlockRange 在块设备内部的结尾位置 (单位是字节) 171 pub fn origin_end(&self) -> usize { 172 return (self.lba_start << self.blk_size_log2) + self.end; 173 } 174 } 175 176 /// 从字节地址转换到lba id 177 #[inline] 178 pub fn __bytes_to_lba(addr: usize, blk_size: usize) -> BlockId { 179 return addr / blk_size; 180 } 181 182 /// 从lba id转换到字节地址, 返回lba_id的最左侧字节 183 #[inline] 184 pub fn __lba_to_bytes(lba_id: usize, blk_size: usize) -> BlockId { 185 return lba_id * blk_size; 186 } 187 188 /// @brief 块设备应该实现的操作 189 pub trait BlockDevice: Device { 190 /// @brief: 在块设备中,从第lba_id_start个块开始,读取count个块数据,存放到buf中 191 /// 192 /// @parameter lba_id_start: 起始块 193 /// @parameter count: 读取块的数量 194 /// @parameter buf: 目标数组 195 /// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节; 196 /// 否则返回Err(错误码),其中错误码为负数; 197 /// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度) 198 fn read_at( 199 &self, 200 lba_id_start: BlockId, 201 count: usize, 202 buf: &mut [u8], 203 ) -> Result<usize, SystemError>; 204 205 /// @brief: 在块设备中,从第lba_id_start个块开始,把buf中的count个块数据,存放到设备中 206 /// @parameter lba_id_start: 起始块 207 /// @parameter count: 写入块的数量 208 /// @parameter buf: 目标数组 209 /// @return: 如果操作成功,返回 Ok(操作的长度) 其中单位是字节; 210 /// 否则返回Err(错误码),其中错误码为负数; 211 /// 如果操作异常,但是并没有检查出什么错误,将返回Err(已操作的长度) 212 fn write_at( 213 &self, 214 lba_id_start: BlockId, 215 count: usize, 216 buf: &[u8], 217 ) -> Result<usize, SystemError>; 218 219 /// @brief: 同步磁盘信息,把所有的dirty数据写回硬盘 - 待实现 220 fn sync(&self) -> Result<(), SystemError>; 221 222 /// @brief: 每个块设备都必须固定自己块大小,而且该块大小必须是2的幂次 223 /// @return: 返回一个固定量,硬编码(编程的时候固定的常量). 224 fn blk_size_log2(&self) -> u8; 225 226 // TODO: 待实现 open, close 227 228 /// @brief 本函数用于实现动态转换。 229 /// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self 230 fn as_any_ref(&self) -> &dyn Any; 231 232 /// @brief 本函数用于将BlockDevice转换为Device。 233 /// 由于实现了BlockDevice的结构体,本身也实现了Device Trait, 因此转换是可能的。 234 /// 思路:在BlockDevice的结构体中新增一个self_ref变量,返回self_ref.upgrade()即可。 235 fn device(&self) -> Arc<dyn Device>; 236 237 /// @brief 返回块设备的块大小(单位:字节) 238 fn block_size(&self) -> usize; 239 240 /// @brief 返回当前磁盘上的所有分区的Arc指针数组 241 fn partitions(&self) -> Vec<Arc<Partition>>; 242 243 fn write_at_bytes(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError> { 244 // assert!(len <= buf.len()); 245 if len > buf.len() { 246 return Err(SystemError::E2BIG); 247 } 248 249 let iter = BlockIter::new_multiblock(offset, offset + len, self.blk_size_log2()); 250 let multi = iter.multiblock; 251 252 for range in iter { 253 let buf_begin = range.origin_begin() - offset; // 本次读操作的起始位置/已经读了这么多字节 254 let buf_end = range.origin_end() - offset; 255 let buf_slice = &buf[buf_begin..buf_end]; 256 let count: usize = range.lba_end - range.lba_start; 257 let full = multi && range.is_multi() || !multi && range.is_full(); 258 259 if full { 260 self.write_at(range.lba_start, count, buf_slice)?; 261 } else { 262 if self.blk_size_log2() > BLK_SIZE_LOG2_LIMIT { 263 return Err(SystemError::E2BIG); 264 } 265 266 let mut temp = vec![0; 1usize << self.blk_size_log2()]; 267 // 由于块设备每次读写都是整块的,在不完整写入之前,必须把不完整的地方补全 268 self.read_at(range.lba_start, 1, &mut temp[..])?; 269 // 把数据从临时buffer复制到目标buffer 270 temp[range.begin..range.end].copy_from_slice(buf_slice); 271 self.write_at(range.lba_start, 1, &temp[..])?; 272 } 273 } 274 return Ok(len); 275 //self.0.lock().write_at(lba_id_start, count, buf) 276 } 277 278 fn read_at_bytes( 279 &self, 280 offset: usize, 281 len: usize, 282 buf: &mut [u8], 283 ) -> Result<usize, SystemError> { 284 if len > buf.len() { 285 return Err(SystemError::E2BIG); 286 } 287 288 let iter = BlockIter::new_multiblock(offset, offset + len, self.blk_size_log2()); 289 let multi = iter.multiblock; 290 291 // 枚举每一个range 292 for range in iter { 293 let buf_begin = range.origin_begin() - offset; // 本次读操作的起始位置/已经读了这么多字节 294 let buf_end = range.origin_end() - offset; 295 let buf_slice = &mut buf[buf_begin..buf_end]; 296 let count: usize = range.lba_end - range.lba_start; 297 let full = multi && range.is_multi() || !multi && range.is_full(); 298 299 // 读取整个block作为有效数据 300 if full { 301 // 调用 BlockDevice::read_at() 直接把引用传进去,不是把整个数组move进去 302 self.read_at(range.lba_start, count, buf_slice)?; 303 } else { 304 // 判断块的长度不能超过最大值 305 if self.blk_size_log2() > BLK_SIZE_LOG2_LIMIT { 306 return Err(SystemError::E2BIG); 307 } 308 309 let mut temp = vec![0; 1usize << self.blk_size_log2()]; 310 self.read_at(range.lba_start, 1, &mut temp[..])?; 311 312 // 把数据从临时buffer复制到目标buffer 313 buf_slice.copy_from_slice(&temp[range.begin..range.end]); 314 } 315 } 316 return Ok(len); 317 318 // kdebug!( 319 // "ahci read at {lba_id_start}, count={count}, lock={:?}", 320 // self.0 321 // ); 322 } 323 } 324 325 /// @brief 块设备框架函数集 326 pub struct BlockDeviceOps; 327 328 impl BlockDeviceOps { 329 /// @brief: 主设备号转下标 330 /// @parameter: major: 主设备号 331 /// @return: 返回下标 332 #[allow(dead_code)] 333 fn major_to_index(major: Major) -> usize { 334 return (major.data() % DEV_MAJOR_HASH_SIZE) as usize; 335 } 336 337 /// @brief: 动态获取主设备号 338 /// @parameter: None 339 /// @return: 如果成功,返回主设备号,否则,返回错误码 340 #[allow(dead_code)] 341 fn find_dynamic_major() -> Result<Major, SystemError> { 342 let blockdevs = BLOCKDEVS.lock(); 343 // 寻找主设备号为234~255的设备 344 for index in ((DEV_MAJOR_DYN_END.data())..DEV_MAJOR_HASH_SIZE).rev() { 345 if let Some(item) = blockdevs.get(index as usize) { 346 if item.is_empty() { 347 return Ok(Major::new(index)); // 返回可用的主设备号 348 } 349 } 350 } 351 // 寻找主设备号在384~511的设备 352 for index in 353 ((DEV_MAJOR_DYN_EXT_END.data() + 1)..(DEV_MAJOR_DYN_EXT_START.data() + 1)).rev() 354 { 355 if let Some(blockdevss) = blockdevs.get(Self::major_to_index(Major::new(index))) { 356 let mut flag = true; 357 for item in blockdevss { 358 if item.device_number().major() == Major::new(index) { 359 flag = false; 360 break; 361 } 362 } 363 if flag { 364 // 如果数组中不存在主设备号等于index的设备 365 return Ok(Major::new(index)); // 返回可用的主设备号 366 } 367 } 368 } 369 return Err(SystemError::EBUSY); 370 } 371 372 /// @brief: 注册设备号,该函数需要指定主设备号 373 /// @parameter: from: 主设备号 374 /// count: 次设备号数量 375 /// name: 字符设备名 376 /// @return: 如果注册成功,返回设备号,否则,返回错误码 377 #[allow(dead_code)] 378 pub fn register_blockdev_region( 379 from: DeviceNumber, 380 count: u32, 381 name: &'static str, 382 ) -> Result<DeviceNumber, SystemError> { 383 Self::__register_blockdev_region(from, count, name) 384 } 385 386 /// @brief: 注册设备号,该函数自动分配主设备号 387 /// @parameter: baseminor: 主设备号 388 /// count: 次设备号数量 389 /// name: 字符设备名 390 /// @return: 如果注册成功,返回,否则,返回false 391 #[allow(dead_code)] 392 pub fn alloc_blockdev_region( 393 baseminor: u32, 394 count: u32, 395 name: &'static str, 396 ) -> Result<DeviceNumber, SystemError> { 397 Self::__register_blockdev_region( 398 DeviceNumber::new(Major::UNNAMED_MAJOR, baseminor), 399 count, 400 name, 401 ) 402 } 403 404 /// @brief: 注册设备号 405 /// @parameter: device_number: 设备号,主设备号如果为0,则动态分配 406 /// minorct: 次设备号数量 407 /// name: 字符设备名 408 /// @return: 如果注册成功,返回设备号,否则,返回错误码 409 fn __register_blockdev_region( 410 device_number: DeviceNumber, 411 minorct: u32, 412 name: &'static str, 413 ) -> Result<DeviceNumber, SystemError> { 414 let mut major = device_number.major(); 415 let baseminor = device_number.minor(); 416 if major >= DEV_MAJOR_MAX { 417 kerror!( 418 "DEV {} major requested {:?} is greater than the maximum {}\n", 419 name, 420 major, 421 DEV_MAJOR_MAX.data() - 1 422 ); 423 } 424 if minorct > DeviceNumber::MINOR_MASK + 1 - baseminor { 425 kerror!("DEV {} minor range requested ({}-{}) is out of range of maximum range ({}-{}) for a single major\n", 426 name, baseminor, baseminor + minorct - 1, 0, DeviceNumber::MINOR_MASK); 427 } 428 let blockdev = DeviceStruct::new(DeviceNumber::new(major, baseminor), minorct, name); 429 if major == Major::UNNAMED_MAJOR { 430 // 如果主设备号为0,则自动分配主设备号 431 major = Self::find_dynamic_major().expect("Find synamic major error.\n"); 432 } 433 if let Some(items) = BLOCKDEVS.lock().get_mut(Self::major_to_index(major)) { 434 let mut insert_index: usize = 0; 435 for (index, item) in items.iter().enumerate() { 436 insert_index = index; 437 match item.device_number().major().cmp(&major) { 438 core::cmp::Ordering::Less => continue, 439 core::cmp::Ordering::Greater => { 440 break; // 大于则向后插入 441 } 442 core::cmp::Ordering::Equal => { 443 if item.device_number().minor() + item.minorct() <= baseminor { 444 continue; // 下一个主设备号大于或者次设备号大于被插入的次设备号最大值 445 } 446 if item.base_minor() >= baseminor + minorct { 447 break; // 在此处插入 448 } 449 return Err(SystemError::EBUSY); // 存在重合的次设备号 450 } 451 } 452 } 453 items.insert(insert_index, blockdev); 454 } 455 456 return Ok(DeviceNumber::new(major, baseminor)); 457 } 458 459 /// @brief: 注销设备号 460 /// @parameter: major: 主设备号,如果为0,动态分配 461 /// baseminor: 起始次设备号 462 /// minorct: 次设备号数量 463 /// @return: 如果注销成功,返回(),否则,返回错误码 464 fn __unregister_blockdev_region( 465 device_number: DeviceNumber, 466 minorct: u32, 467 ) -> Result<(), SystemError> { 468 if let Some(items) = BLOCKDEVS 469 .lock() 470 .get_mut(Self::major_to_index(device_number.major())) 471 { 472 for (index, item) in items.iter().enumerate() { 473 if item.device_number() == device_number && item.minorct() == minorct { 474 // 设备号和数量都相等 475 items.remove(index); 476 return Ok(()); 477 } 478 } 479 } 480 return Err(SystemError::EBUSY); 481 } 482 483 /// @brief: 块设备注册 484 /// @parameter: cdev: 字符设备实例 485 /// dev_t: 字符设备号 486 /// range: 次设备号范围 487 /// @return: none 488 #[allow(dead_code)] 489 pub fn bdev_add(_bdev: Arc<dyn BlockDevice>, id_table: IdTable) -> Result<(), DeviceError> { 490 if id_table.device_number().data() == 0 { 491 kerror!("Device number can't be 0!\n"); 492 } 493 todo!("bdev_add") 494 // return device_manager().add_device(bdev.id_table(), bdev.device()); 495 } 496 497 /// @brief: block设备注销 498 /// @parameter: dev_t: 字符设备号 499 /// range: 次设备号范围 500 /// @return: none 501 #[allow(dead_code)] 502 pub fn bdev_del(_devnum: DeviceNumber, _range: usize) { 503 unimplemented!(); 504 } 505 } 506