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