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