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