xref: /DragonOS/kernel/src/driver/scsi/mod.rs (revision 9fa0e95eeed8630a8a69c874090af2f10e8eee02)
1*9fa0e95eSLoGin use bitmap::traits::BitMapOps;
2*9fa0e95eSLoGin use system_error::SystemError;
3*9fa0e95eSLoGin use unified_init::macros::unified_init;
4*9fa0e95eSLoGin 
5*9fa0e95eSLoGin use crate::{
6*9fa0e95eSLoGin     init::initcall::INITCALL_POSTCORE,
7*9fa0e95eSLoGin     libs::spinlock::{SpinLock, SpinLockGuard},
8*9fa0e95eSLoGin };
9*9fa0e95eSLoGin 
10*9fa0e95eSLoGin use super::base::block::block_device::BlockDevName;
11*9fa0e95eSLoGin 
12*9fa0e95eSLoGin static mut SCSI_MANAGER: Option<ScsiManager> = None;
13*9fa0e95eSLoGin 
14*9fa0e95eSLoGin #[inline]
scsi_manager() -> &'static ScsiManager15*9fa0e95eSLoGin pub fn scsi_manager() -> &'static ScsiManager {
16*9fa0e95eSLoGin     unsafe { SCSI_MANAGER.as_ref().unwrap() }
17*9fa0e95eSLoGin }
18*9fa0e95eSLoGin 
19*9fa0e95eSLoGin #[unified_init(INITCALL_POSTCORE)]
scsi_manager_init() -> Result<(), SystemError>20*9fa0e95eSLoGin fn scsi_manager_init() -> Result<(), SystemError> {
21*9fa0e95eSLoGin     unsafe {
22*9fa0e95eSLoGin         SCSI_MANAGER = Some(ScsiManager::new());
23*9fa0e95eSLoGin     }
24*9fa0e95eSLoGin     Ok(())
25*9fa0e95eSLoGin }
26*9fa0e95eSLoGin 
27*9fa0e95eSLoGin pub struct ScsiManager {
28*9fa0e95eSLoGin     inner: SpinLock<InnerScsiManager>,
29*9fa0e95eSLoGin }
30*9fa0e95eSLoGin 
31*9fa0e95eSLoGin struct InnerScsiManager {
32*9fa0e95eSLoGin     id_bmp: bitmap::StaticBitmap<{ ScsiManager::MAX_DEVICES }>,
33*9fa0e95eSLoGin     devname: [Option<BlockDevName>; ScsiManager::MAX_DEVICES],
34*9fa0e95eSLoGin }
35*9fa0e95eSLoGin 
36*9fa0e95eSLoGin impl ScsiManager {
37*9fa0e95eSLoGin     pub const MAX_DEVICES: usize = 25;
38*9fa0e95eSLoGin 
new() -> Self39*9fa0e95eSLoGin     pub fn new() -> Self {
40*9fa0e95eSLoGin         Self {
41*9fa0e95eSLoGin             inner: SpinLock::new(InnerScsiManager {
42*9fa0e95eSLoGin                 id_bmp: bitmap::StaticBitmap::new(),
43*9fa0e95eSLoGin                 devname: [const { None }; Self::MAX_DEVICES],
44*9fa0e95eSLoGin             }),
45*9fa0e95eSLoGin         }
46*9fa0e95eSLoGin     }
47*9fa0e95eSLoGin 
inner(&self) -> SpinLockGuard<InnerScsiManager>48*9fa0e95eSLoGin     fn inner(&self) -> SpinLockGuard<InnerScsiManager> {
49*9fa0e95eSLoGin         self.inner.lock()
50*9fa0e95eSLoGin     }
51*9fa0e95eSLoGin 
alloc_id(&self) -> Option<BlockDevName>52*9fa0e95eSLoGin     pub fn alloc_id(&self) -> Option<BlockDevName> {
53*9fa0e95eSLoGin         let mut inner = self.inner();
54*9fa0e95eSLoGin         let idx = inner.id_bmp.first_false_index()?;
55*9fa0e95eSLoGin         inner.id_bmp.set(idx, true);
56*9fa0e95eSLoGin         let name = Self::format_name(idx);
57*9fa0e95eSLoGin         inner.devname[idx] = Some(name.clone());
58*9fa0e95eSLoGin         Some(name)
59*9fa0e95eSLoGin     }
60*9fa0e95eSLoGin 
61*9fa0e95eSLoGin     /// Generate a new block device name like 'sda', 'sdb', etc.
format_name(id: usize) -> BlockDevName62*9fa0e95eSLoGin     fn format_name(id: usize) -> BlockDevName {
63*9fa0e95eSLoGin         let x = (b'a' + id as u8) as char;
64*9fa0e95eSLoGin         BlockDevName::new(format!("sd{}", x), id)
65*9fa0e95eSLoGin     }
66*9fa0e95eSLoGin 
free_id(&self, id: usize)67*9fa0e95eSLoGin     pub fn free_id(&self, id: usize) {
68*9fa0e95eSLoGin         if id >= Self::MAX_DEVICES {
69*9fa0e95eSLoGin             return;
70*9fa0e95eSLoGin         }
71*9fa0e95eSLoGin         self.inner().id_bmp.set(id, false);
72*9fa0e95eSLoGin         self.inner().devname[id] = None;
73*9fa0e95eSLoGin     }
74*9fa0e95eSLoGin }
75