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