Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Nagy Tibor
drivers
Commits
a38dfb32
Verified
Commit
a38dfb32
authored
Jan 12, 2019
by
Jeremy Soller
Browse files
Use IRQs to prevent spin loops in ahcid
parent
ca748c99
Changes
8
Hide whitespace changes
Inline
Side-by-side
Cargo.lock
View file @
a38dfb32
...
...
@@ -5,7 +5,6 @@ dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.45 (registry+https://github.com/rust-lang/crates.io-index)",
"spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
...
...
ahcid/Cargo.toml
View file @
a38dfb32
...
...
@@ -4,6 +4,5 @@ version = "0.1.0"
[dependencies]
bitflags
=
"0.7"
spin
=
"0.4"
redox_syscall
=
"0.1"
byteorder
=
"1.2"
ahcid/src/ahci/disk_ata.rs
View file @
a38dfb32
...
...
@@ -6,10 +6,23 @@ use syscall::error::Result;
use
super
::
hba
::{
HbaPort
,
HbaCmdTable
,
HbaCmdHeader
};
use
super
::
Disk
;
enum
BufferKind
<
'a
>
{
Read
(
&
'a
mut
[
u8
]),
Write
(
&
'a
[
u8
]),
}
struct
Request
{
address
:
usize
,
total_sectors
:
usize
,
sector
:
usize
,
running_opt
:
Option
<
(
u32
,
usize
)
>
,
}
pub
struct
DiskATA
{
id
:
usize
,
port
:
&
'static
mut
HbaPort
,
size
:
u64
,
request_opt
:
Option
<
Request
>
,
clb
:
Dma
<
[
HbaCmdHeader
;
32
]
>
,
ctbas
:
[
Dma
<
HbaCmdTable
>
;
32
],
_fb
:
Dma
<
[
u8
;
256
]
>
,
...
...
@@ -40,69 +53,92 @@ impl DiskATA {
id
:
id
,
port
:
port
,
size
:
size
,
request_opt
:
None
,
clb
:
clb
,
ctbas
:
ctbas
,
_fb
:
fb
,
buf
:
buf
})
}
}
impl
Disk
for
DiskATA
{
fn
id
(
&
self
)
->
usize
{
self
.id
}
fn
size
(
&
mut
self
)
->
u64
{
self
.size
}
fn
read
(
&
mut
self
,
block
:
u64
,
buffer
:
&
mut
[
u8
])
->
Result
<
usize
>
{
let
sectors
=
buffer
.len
()
/
512
;
let
mut
sector
:
usize
=
0
;
while
sectors
-
sector
>=
255
{
self
.port
.dma_read_write
(
block
+
sector
as
u64
,
255
,
false
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
?
;
unsafe
{
ptr
::
copy
(
self
.buf
.as_ptr
(),
buffer
.as_mut_ptr
()
.offset
(
sector
as
isize
*
512
),
255
*
512
);
}
fn
request
(
&
mut
self
,
block
:
u64
,
mut
buffer_kind
:
BufferKind
)
->
Result
<
Option
<
usize
>>
{
let
(
write
,
address
,
total_sectors
)
=
match
buffer_kind
{
BufferKind
::
Read
(
ref
buffer
)
=>
(
false
,
buffer
.as_ptr
()
as
usize
,
buffer
.len
()
/
512
),
BufferKind
::
Write
(
ref
buffer
)
=>
(
true
,
buffer
.as_ptr
()
as
usize
,
buffer
.len
()
/
512
),
};
let
mut
request
=
match
self
.request_opt
.take
()
{
Some
(
request
)
=>
if
address
==
request
.address
&&
total_sectors
==
request
.total_sectors
{
// Keep servicing current request
request
}
else
{
// Have to wait for another request to finish
self
.request_opt
=
Some
(
request
);
return
Ok
(
None
);
},
None
=>
{
// Create new request
Request
{
address
,
total_sectors
,
sector
:
0
,
running_opt
:
None
,
}
}
};
sector
+=
255
;
}
if
sector
<
sectors
{
self
.port
.dma_read_write
(
block
+
sector
as
u64
,
sectors
-
sector
,
false
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
?
;
// Finish a previously running request
if
let
Some
(
running
)
=
request
.running_opt
.take
()
{
self
.port
.ata_stop
(
running
.0
)
?
;
unsafe
{
ptr
::
copy
(
self
.buf
.as_ptr
(),
buffer
.as_mut_ptr
()
.offset
(
sector
as
isize
*
512
),
(
sectors
-
sector
)
*
512
);
}
if
let
BufferKind
::
Read
(
ref
mut
buffer
)
=
buffer_kind
{
unsafe
{
ptr
::
copy
(
self
.buf
.as_ptr
(),
buffer
.as_mut_ptr
()
.add
(
request
.sector
*
512
),
running
.1
*
512
);
}
}
sector
+=
sectors
-
sector
;
request
.
sector
+=
running
.1
;
}
Ok
(
sector
*
512
)
}
fn
write
(
&
mut
self
,
block
:
u64
,
buffer
:
&
[
u8
])
->
Result
<
usize
>
{
let
sectors
=
buffer
.len
()
/
512
;
if
request
.sector
<
request
.total_sectors
{
// Start a new request
let
sectors
=
if
request
.total_sectors
-
request
.sector
>=
255
{
255
}
else
{
request
.total_sectors
-
request
.sector
};
let
mut
sector
:
usize
=
0
;
while
sectors
-
sector
>=
255
{
unsafe
{
ptr
::
copy
(
buffer
.as_ptr
()
.offset
(
sector
as
isize
*
512
),
self
.buf
.as_mut_ptr
(),
255
*
512
);
}
if
let
BufferKind
::
Write
(
ref
buffer
)
=
buffer_kind
{
unsafe
{
ptr
::
copy
(
buffer
.as_ptr
()
.add
(
request
.sector
*
512
),
self
.buf
.as_mut_ptr
(),
sectors
*
512
);
}
}
if
let
Err
(
err
)
=
self
.port
.
dma_read_write
(
block
+
sector
as
u64
,
255
,
tru
e
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
{
re
turn
Err
(
err
);
if
let
Some
(
slot
)
=
self
.port
.
ata_dma
(
block
+
request
.
sector
as
u64
,
sectors
,
writ
e
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
{
re
quest
.running_opt
=
Some
((
slot
,
sectors
)
);
}
sector
+=
255
;
self
.request_opt
=
Some
(
request
);
Ok
(
None
)
}
else
{
// Done
Ok
(
Some
(
request
.sector
*
512
))
}
if
sector
<
sectors
{
unsafe
{
ptr
::
copy
(
buffer
.as_ptr
()
.offset
(
sector
as
isize
*
512
),
self
.buf
.as_mut_ptr
(),
(
sectors
-
sector
)
*
512
);
}
}
}
if
let
Err
(
err
)
=
self
.port
.dma_read_write
(
block
+
sector
as
u64
,
sectors
-
sector
,
true
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
{
return
Err
(
err
);
}
impl
Disk
for
DiskATA
{
fn
id
(
&
self
)
->
usize
{
self
.id
}
sector
+=
sectors
-
sector
;
}
fn
size
(
&
mut
self
)
->
u64
{
self
.size
}
fn
read
(
&
mut
self
,
block
:
u64
,
buffer
:
&
mut
[
u8
])
->
Result
<
Option
<
usize
>>
{
self
.request
(
block
,
BufferKind
::
Read
(
buffer
))
}
Ok
(
sector
*
512
)
fn
write
(
&
mut
self
,
block
:
u64
,
buffer
:
&
[
u8
])
->
Result
<
Option
<
usize
>>
{
self
.request
(
block
,
BufferKind
::
Write
(
buffer
))
}
fn
block_length
(
&
mut
self
)
->
Result
<
u32
>
{
...
...
ahcid/src/ahci/disk_atapi.rs
View file @
a38dfb32
...
...
@@ -5,7 +5,7 @@ use std::ptr;
use
byteorder
::{
ByteOrder
,
BigEndian
};
use
syscall
::
io
::
Dma
;
use
syscall
::
error
::{
Result
,
E
NOSYS
,
Error
};
use
syscall
::
error
::{
Result
,
E
BADF
,
Error
};
use
super
::
hba
::{
HbaPort
,
HbaCmdTable
,
HbaCmdHeader
};
use
super
::
Disk
;
...
...
@@ -61,7 +61,7 @@ impl DiskATAPI {
let
mut
cmd
=
[
0
;
16
];
cmd
[
0
]
=
SCSI_READ_CAPACITY
;
self
.port
.
packet
(
&
cmd
,
8
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
?
;
self
.port
.
atapi_dma
(
&
cmd
,
8
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
?
;
// Instead of a count, contains number of last LBA, so add 1
let
blk_count
=
BigEndian
::
read_u32
(
&
self
.buf
[
0
..
4
])
+
1
;
...
...
@@ -83,9 +83,9 @@ impl Disk for DiskATAPI {
}
}
fn
read
(
&
mut
self
,
block
:
u64
,
buffer
:
&
mut
[
u8
])
->
Result
<
usize
>
{
fn
read
(
&
mut
self
,
block
:
u64
,
buffer
:
&
mut
[
u8
])
->
Result
<
Option
<
usize
>
>
{
// TODO: Handle audio CDs, which use special READ CD command
let
blk_len
=
self
.block_length
()
?
;
let
sectors
=
buffer
.len
()
as
u32
/
blk_len
;
...
...
@@ -102,7 +102,7 @@ impl Disk for DiskATAPI {
let
buf_size
=
buf_len
*
blk_len
;
while
sectors
-
sector
>=
buf_len
{
let
cmd
=
read10_cmd
(
block
as
u32
+
sector
,
buf_len
as
u16
);
self
.port
.
packet
(
&
cmd
,
buf_size
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
?
;
self
.port
.
atapi_dma
(
&
cmd
,
buf_size
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
?
;
unsafe
{
ptr
::
copy
(
self
.buf
.as_ptr
(),
buffer
.as_mut_ptr
()
.offset
(
sector
as
isize
*
blk_len
as
isize
),
buf_size
as
usize
);
}
...
...
@@ -110,20 +110,20 @@ impl Disk for DiskATAPI {
}
if
sector
<
sectors
{
let
cmd
=
read10_cmd
(
block
as
u32
+
sector
,
(
sectors
-
sector
)
as
u16
);
self
.port
.
packet
(
&
cmd
,
buf_size
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
?
;
self
.port
.
atapi_dma
(
&
cmd
,
buf_size
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
?
;
unsafe
{
ptr
::
copy
(
self
.buf
.as_ptr
(),
buffer
.as_mut_ptr
()
.offset
(
sector
as
isize
*
blk_len
as
isize
),
((
sectors
-
sector
)
*
blk_len
)
as
usize
);
}
sector
+=
sectors
-
sector
;
}
Ok
((
sector
*
blk_len
)
as
usize
)
Ok
(
Some
(
(
sector
*
blk_len
)
as
usize
)
)
}
fn
write
(
&
mut
self
,
_block
:
u64
,
_buffer
:
&
[
u8
])
->
Result
<
usize
>
{
Err
(
Error
::
new
(
E
NOSYS
))
// TODO: Implement writ
t
ing
fn
write
(
&
mut
self
,
_block
:
u64
,
_buffer
:
&
[
u8
])
->
Result
<
Option
<
usize
>
>
{
Err
(
Error
::
new
(
E
BADF
))
// TODO: Implement writing
}
fn
block_length
(
&
mut
self
)
->
Result
<
u32
>
{
Ok
(
self
.read_capacity
()
?
.1
)
}
...
...
ahcid/src/ahci/hba.rs
View file @
a38dfb32
...
...
@@ -116,7 +116,7 @@ impl HbaPort {
self
.fb
[
1
]
.write
((
fb
.physical
()
>>
32
)
as
u32
);
let
is
=
self
.is
.read
();
self
.is
.write
(
is
);
self
.ie
.write
(
0
);
self
.ie
.write
(
0
b10111
);
let
serr
=
self
.serr
.read
();
self
.serr
.write
(
serr
);
...
...
@@ -142,7 +142,7 @@ impl HbaPort {
unsafe
fn
identify_inner
(
&
mut
self
,
cmd
:
u8
,
clb
:
&
mut
Dma
<
[
HbaCmdHeader
;
32
]
>
,
ctbas
:
&
mut
[
Dma
<
HbaCmdTable
>
;
32
])
->
Option
<
u64
>
{
let
dest
:
Dma
<
[
u16
;
256
]
>
=
Dma
::
new
([
0
;
256
])
.unwrap
();
let
res
=
self
.ata_
dma
(
clb
,
ctbas
,
|
cmdheader
,
cmdfis
,
prdt_entries
,
_acmd
|
{
let
slot
=
self
.ata_
start
(
clb
,
ctbas
,
|
cmdheader
,
cmdfis
,
prdt_entries
,
_acmd
|
{
cmdheader
.prdtl
.write
(
1
);
let
prdt_entry
=
&
mut
prdt_entries
[
0
];
...
...
@@ -154,9 +154,9 @@ impl HbaPort {
cmdfis
.device
.write
(
0
);
cmdfis
.countl
.write
(
1
);
cmdfis
.counth
.write
(
0
);
});
})
?
;
if
res
.is_ok
()
{
if
self
.ata_stop
(
slot
)
.is_ok
()
{
let
mut
serial
=
String
::
new
();
for
word
in
10
..
20
{
let
d
=
dest
[
word
];
...
...
@@ -217,14 +217,12 @@ impl HbaPort {
}
}
pub
fn
dma_read_write
(
&
mut
self
,
block
:
u64
,
sectors
:
usize
,
write
:
bool
,
clb
:
&
mut
Dma
<
[
HbaCmdHeader
;
32
]
>
,
ctbas
:
&
mut
[
Dma
<
HbaCmdTable
>
;
32
],
buf
:
&
mut
Dma
<
[
u8
;
256
*
512
]
>
)
->
Result
<
usize
>
{
if
write
{
//print!("{}", format!("AHCI {:X} DMA BLOCK: {:X} SECTORS: {} WRITE: {}\n", (self as *mut HbaPort) as usize, block, sectors, write));
}
pub
fn
ata_dma
(
&
mut
self
,
block
:
u64
,
sectors
:
usize
,
write
:
bool
,
clb
:
&
mut
Dma
<
[
HbaCmdHeader
;
32
]
>
,
ctbas
:
&
mut
[
Dma
<
HbaCmdTable
>
;
32
],
buf
:
&
mut
Dma
<
[
u8
;
256
*
512
]
>
)
->
Option
<
u32
>
{
// print!("{}", format!("AHCI {:X} DMA BLOCK: {:X} SECTORS: {} WRITE: {}\n", (self as *mut HbaPort) as usize, block, sectors, write));
assert
!
(
sectors
>
0
&&
sectors
<
256
);
let
res
=
self
.ata_
dma
(
clb
,
ctbas
,
|
cmdheader
,
cmdfis
,
prdt_entries
,
_acmd
|
{
self
.ata_
start
(
clb
,
ctbas
,
|
cmdheader
,
cmdfis
,
prdt_entries
,
_acmd
|
{
if
write
{
let
cfl
=
cmdheader
.cfl
.read
();
cmdheader
.cfl
.write
(
cfl
|
1
<<
7
|
1
<<
6
)
...
...
@@ -255,14 +253,12 @@ impl HbaPort {
cmdfis
.countl
.write
(
sectors
as
u8
);
cmdfis
.counth
.write
((
sectors
>>
8
)
as
u8
);
});
res
.and
(
Ok
(
sectors
*
512
))
})
}
/// Send ATAPI packet
pub
fn
packet
(
&
mut
self
,
cmd
:
&
[
u8
;
16
],
size
:
u32
,
clb
:
&
mut
Dma
<
[
HbaCmdHeader
;
32
]
>
,
ctbas
:
&
mut
[
Dma
<
HbaCmdTable
>
;
32
],
buf
:
&
mut
Dma
<
[
u8
;
256
*
512
]
>
)
->
Result
<
()
>
{
self
.ata_
dma
(
clb
,
ctbas
,
|
cmdheader
,
cmdfis
,
prdt_entries
,
acmd
|
{
pub
fn
atapi_dma
(
&
mut
self
,
cmd
:
&
[
u8
;
16
],
size
:
u32
,
clb
:
&
mut
Dma
<
[
HbaCmdHeader
;
32
]
>
,
ctbas
:
&
mut
[
Dma
<
HbaCmdTable
>
;
32
],
buf
:
&
mut
Dma
<
[
u8
;
256
*
512
]
>
)
->
Result
<
()
>
{
let
slot
=
self
.ata_
start
(
clb
,
ctbas
,
|
cmdheader
,
cmdfis
,
prdt_entries
,
acmd
|
{
let
cfl
=
cmdheader
.cfl
.read
();
cmdheader
.cfl
.write
(
cfl
|
1
<<
5
);
...
...
@@ -281,12 +277,14 @@ impl HbaPort {
cmdfis
.featureh
.write
(
0
);
unsafe
{
ptr
::
write_volatile
(
acmd
.as_mut_ptr
()
as
*
mut
[
u8
;
16
],
*
cmd
)
};
})
})
.ok_or
(
Error
::
new
(
EIO
))
?
;
self
.ata_stop
(
slot
)
}
fn
ata_
dma
<
F
>
(
&
mut
self
,
clb
:
&
mut
Dma
<
[
HbaCmdHeader
;
32
]
>
,
ctbas
:
&
mut
[
Dma
<
HbaCmdTable
>
;
32
],
callback
:
F
)
->
Result
<
()
>
pub
fn
ata_
start
<
F
>
(
&
mut
self
,
clb
:
&
mut
Dma
<
[
HbaCmdHeader
;
32
]
>
,
ctbas
:
&
mut
[
Dma
<
HbaCmdTable
>
;
32
],
callback
:
F
)
->
Option
<
u32
>
where
F
:
FnOnce
(
&
mut
HbaCmdHeader
,
&
mut
FisRegH2D
,
&
mut
[
HbaPrdtEntry
;
65536
],
&
mut
[
Mmio
<
u8
>
;
16
])
{
//TODO: Should probably remove
self
.is
.write
(
u32
::
MAX
);
if
let
Some
(
slot
)
=
self
.slot
()
{
...
...
@@ -312,27 +310,31 @@ impl HbaPort {
self
.ci
.writef
(
1
<<
slot
,
true
);
//TODO: Should probably remove
self
.start
();
while
(
self
.ci
.readf
(
1
<<
slot
)
||
self
.tfd
.readf
(
0x80
))
&&
self
.is
.read
()
&
HBA_PORT_IS_ERR
==
0
{
thread
::
yield_now
();
}
Some
(
slot
)
}
else
{
None
}
}
self
.stop
();
pub
fn
ata_stop
(
&
mut
self
,
slot
:
u32
)
->
Result
<
()
>
{
while
(
self
.ci
.readf
(
1
<<
slot
)
||
self
.tfd
.readf
(
0x80
))
&&
self
.is
.read
()
&
HBA_PORT_IS_ERR
==
0
{
thread
::
yield_now
();
}
if
self
.is
.read
()
&
HBA_PORT_IS_ERR
!=
0
{
print!
(
"{}"
,
format!
(
"ERROR IS {:X} IE {:X} CMD {:X} TFD {:X}
\n
SSTS {:X} SCTL {:X} SERR {:X} SACT {:X}
\n
CI {:X} SNTF {:X} FBS {:X}
\n
"
,
self
.is
.read
(),
self
.ie
.read
(),
self
.cmd
.read
(),
self
.tfd
.read
(),
self
.ssts
.read
(),
self
.sctl
.read
(),
self
.serr
.read
(),
self
.sact
.read
(),
self
.ci
.read
(),
self
.sntf
.read
(),
self
.fbs
.read
()));
self
.is
.write
(
u32
::
MAX
);
Err
(
Error
::
new
(
EIO
))
}
else
{
Ok
(())
}
}
else
{
print!
(
"No Command Slots
\n
"
);
self
.stop
();
if
self
.is
.read
()
&
HBA_PORT_IS_ERR
!=
0
{
print!
(
"{}"
,
format!
(
"ERROR IS {:X} IE {:X} CMD {:X} TFD {:X}
\n
SSTS {:X} SCTL {:X} SERR {:X} SACT {:X}
\n
CI {:X} SNTF {:X} FBS {:X}
\n
"
,
self
.is
.read
(),
self
.ie
.read
(),
self
.cmd
.read
(),
self
.tfd
.read
(),
self
.ssts
.read
(),
self
.sctl
.read
(),
self
.serr
.read
(),
self
.sact
.read
(),
self
.ci
.read
(),
self
.sntf
.read
(),
self
.fbs
.read
()));
self
.is
.write
(
u32
::
MAX
);
Err
(
Error
::
new
(
EIO
))
}
else
{
Ok
(())
}
}
}
...
...
ahcid/src/ahci/mod.rs
View file @
a38dfb32
...
...
@@ -13,18 +13,19 @@ pub mod hba;
pub
trait
Disk
{
fn
id
(
&
self
)
->
usize
;
fn
size
(
&
mut
self
)
->
u64
;
fn
read
(
&
mut
self
,
block
:
u64
,
buffer
:
&
mut
[
u8
])
->
Result
<
usize
>
;
fn
write
(
&
mut
self
,
block
:
u64
,
buffer
:
&
[
u8
])
->
Result
<
usize
>
;
fn
read
(
&
mut
self
,
block
:
u64
,
buffer
:
&
mut
[
u8
])
->
Result
<
Option
<
usize
>
>
;
fn
write
(
&
mut
self
,
block
:
u64
,
buffer
:
&
[
u8
])
->
Result
<
Option
<
usize
>
>
;
fn
block_length
(
&
mut
self
)
->
Result
<
u32
>
;
}
pub
fn
disks
(
base
:
usize
,
name
:
&
str
)
->
Vec
<
Box
<
Disk
>>
{
unsafe
{
&
mut
*
(
base
as
*
mut
HbaMem
)
}
.init
();
let
pi
=
unsafe
{
&
mut
*
(
base
as
*
mut
HbaMem
)
}
.pi
.read
();
let
ret
:
Vec
<
Box
<
Disk
>>
=
(
0
..
32
)
pub
fn
disks
(
base
:
usize
,
name
:
&
str
)
->
(
&
'static
mut
HbaMem
,
Vec
<
Box
<
Disk
>>
)
{
let
hba_mem
=
unsafe
{
&
mut
*
(
base
as
*
mut
HbaMem
)
};
hba_mem
.init
();
let
pi
=
hba_mem
.pi
.read
();
let
disks
:
Vec
<
Box
<
Disk
>>
=
(
0
..
hba_mem
.ports
.len
())
.filter
(|
&
i
|
pi
&
1
<<
i
as
i32
==
1
<<
i
as
i32
)
.filter_map
(|
i
|
{
let
port
=
&
mut
unsafe
{
&
mut
*
(
ba
se
as
*
mut
HbaMem
)
}
.ports
[
i
]
;
let
port
=
unsafe
{
&
mut
*
h
ba
_mem
.ports
.as_mut_ptr
()
.add
(
i
)
}
;
let
port_type
=
port
.probe
();
print!
(
"{}"
,
format!
(
"{}-{}: {:?}
\n
"
,
name
,
i
,
port_type
));
...
...
@@ -54,5 +55,5 @@ pub fn disks(base: usize, name: &str) -> Vec<Box<Disk>> {
})
.collect
();
ret
(
hba_mem
,
disks
)
}
ahcid/src/main.rs
View file @
a38dfb32
#![deny(warnings)]
#![feature(asm)]
//#![deny(warnings)]
extern
crate
spin
;
extern
crate
syscall
;
extern
crate
byteorder
;
...
...
@@ -9,7 +7,7 @@ use std::{env, usize};
use
std
::
fs
::
File
;
use
std
::
io
::{
Read
,
Write
};
use
std
::
os
::
unix
::
io
::
FromRawFd
;
use
syscall
::{
EVENT_READ
,
PHYSMAP_WRITE
,
Event
,
Packet
,
Scheme
};
use
syscall
::{
EVENT_READ
,
PHYSMAP_WRITE
,
Event
,
Packet
,
Scheme
BlockMut
};
use
scheme
::
DiskScheme
;
...
...
@@ -49,6 +47,8 @@ fn main() {
let
mut
event_file
=
File
::
open
(
"event:"
)
.expect
(
"ahcid: failed to open event file"
);
syscall
::
setrens
(
0
,
0
)
.expect
(
"ahcid: failed to enter null namespace"
);
event_file
.write
(
&
Event
{
id
:
socket_fd
,
flags
:
EVENT_READ
,
...
...
@@ -61,10 +61,10 @@ fn main() {
data
:
0
})
.expect
(
"ahcid: failed to event irq scheme"
);
let
scheme
=
DiskScheme
::
new
(
scheme_name
,
ahci
::
disks
(
address
,
&
name
));
syscall
::
setrens
(
0
,
0
)
.expect
(
"ahcid: failed to enter null namespace"
);
let
(
hba_mem
,
disks
)
=
ahci
::
disks
(
address
,
&
name
);
let
mut
scheme
=
DiskScheme
::
new
(
scheme_name
,
hba_mem
,
disks
);
let
mut
todo
=
Vec
::
new
();
loop
{
let
mut
event
=
Event
::
default
();
if
event_file
.read
(
&
mut
event
)
.expect
(
"ahcid: failed to read event file"
)
==
0
{
...
...
@@ -76,14 +76,42 @@ fn main() {
if
socket
.read
(
&
mut
packet
)
.expect
(
"ahcid: failed to read disk scheme"
)
==
0
{
break
;
}
scheme
.handle
(
&
mut
packet
);
socket
.write
(
&
mut
packet
)
.expect
(
"ahcid: failed to write disk scheme"
);
if
let
Some
(
a
)
=
scheme
.handle
(
&
packet
)
{
packet
.a
=
a
;
socket
.write
(
&
mut
packet
)
.expect
(
"ahcid: failed to write disk scheme"
);
}
else
{
todo
.push
(
packet
);
}
}
// let mut i = 0;
// while i < todo.len() {
// if let Some(a) = scheme.handle(&todo[i]) {
// let mut packet = todo.remove(i);
// packet.a = a;
// socket.write(&mut packet).expect("ahcid: failed to write disk scheme");
// } else {
// i += 1;
// }
// }
}
else
if
event
.id
==
irq_fd
{
let
mut
irq
=
[
0
;
8
];
if
irq_file
.read
(
&
mut
irq
)
.expect
(
"ahcid: failed to read irq file"
)
>=
irq
.len
()
{
//TODO : Test for IRQ
//irq_file.write(&irq).expect("ahcid: failed to write irq file");
if
scheme
.irq
()
{
irq_file
.write
(
&
irq
)
.expect
(
"ahcid: failed to write irq file"
);
let
mut
i
=
0
;
while
i
<
todo
.len
()
{
if
let
Some
(
a
)
=
scheme
.handle
(
&
todo
[
i
])
{
let
mut
packet
=
todo
.remove
(
i
);
packet
.a
=
a
;
socket
.write
(
&
mut
packet
)
.expect
(
"ahcid: failed to write disk scheme"
);
}
else
{
i
+=
1
;
}
}
}
}
}
else
{
println!
(
"Unknown event {}"
,
event
.id
);
...
...
ahcid/src/scheme.rs
View file @
a38dfb32
...
...
@@ -2,44 +2,63 @@ use std::collections::BTreeMap;
use
std
::{
cmp
,
str
};
use
std
::
fmt
::
Write
;
use
std
::
io
::
Read
;
use
s
td
::
sync
::
Arc
;
use
std
::
sync
::
atomic
::{
AtomicUsize
,
Ordering
};
use
spin
::
Mutex
;
use
syscall
::{
Error
,
EACCES
,
EBADF
,
EINVAL
,
EISDIR
,
ENOENT
,
Result
,
Scheme
,
Stat
,
MODE_DIR
,
MODE_FILE
,
O_DIRECTORY
,
O_STAT
,
SEEK_CUR
,
SEEK_END
,
SEEK_SET
};
use
s
yscall
::{
Error
,
EACCES
,
EBADF
,
EINVAL
,
EISDIR
,
ENOENT
,
Result
,
Io
,
SchemeBlockMut
,
Stat
,
MODE_DIR
,
MODE_FILE
,
O_DIRECTORY
,
O_STAT
,
SEEK_CUR
,
SEEK_END
,
SEEK_SET
};
use
ahci
::
Disk
;
use
ahci
::
hba
::
HbaMem
;
#[derive(Clone)]
enum
Handle
{
List
(
Vec
<
u8
>
,
usize
),
Disk
(
Arc
<
Mutex
<
Box
<
Disk
>>>
,
usize
,
usize
)
Disk
(
usize
,
usize
)
}
pub
struct
DiskScheme
{
scheme_name
:
String
,
disks
:
Box
<
[
Arc
<
Mutex
<
Box
<
Disk
>>>
]
>
,
handles
:
Mutex
<
BTreeMap
<
usize
,
Handle
>>
,
next_id
:
AtomicUsize
hba_mem
:
&
'static
mut
HbaMem
,
disks
:
Box
<
[
Box
<
Disk
>
]
>
,
handles
:
BTreeMap
<
usize
,
Handle
>
,
next_id
:
usize
}
impl
DiskScheme
{
pub
fn
new
(
scheme_name
:
String
,
disks
:
Vec
<
Box
<
Disk
>>
)
->
DiskScheme
{
let
mut
disk_arcs
=
vec!
[];
for
disk
in
disks
{
disk_arcs
.push
(
Arc
::
new
(
Mutex
::
new
(
disk
)));
}
pub
fn
new
(
scheme_name
:
String
,
hba_mem
:
&
'static
mut
HbaMem
,
disks
:
Vec
<
Box
<
Disk
>>
)
->
DiskScheme
{
DiskScheme
{
scheme_name
:
scheme_name
,
disks
:
disk_arcs
.into_boxed_slice
(),
handles
:
Mutex
::
new
(
BTreeMap
::
new
()),
next_id
:
AtomicUsize
::
new
(
0
)
hba_mem
:
hba_mem
,
disks
:
disks
.into_boxed_slice
(),
handles
:
BTreeMap
::
new
(),
next_id
:
0
}
}
}
impl
Scheme
for
DiskScheme
{
fn
open
(
&
self
,
path
:
&
[
u8
],
flags
:
usize
,
uid
:
u32
,
_gid
:
u32
)
->
Result
<
usize
>
{
impl
DiskScheme
{
pub
fn
irq
(
&
mut
self
)
->
bool
{
let
pi
=
self
.hba_mem.pi
.read
();
let
is
=
self
.hba_mem.is
.read
();
let
pi_is
=
pi
&
is
;
for
i
in
0
..
self
.hba_mem.ports
.len
()
{
if
pi_is
&
1
<<
i
>
0
{
let
port
=
&
mut
self
.hba_mem.ports
[
i
];
let
is
=
port
.is
.read
();
//println!("IRQ Port {}: {:#>08x}", i, is);
//TODO: Handle requests for only this port here
port
.is
.write
(
is
);
}
}
self
.hba_mem.is
.write
(
is
);
is
!=
0
}
}
impl
SchemeBlockMut
for
DiskScheme
{
fn
open
(
&
mut
self
,
path
:
&
[
u8
],
flags
:
usize
,
uid
:
u32
,
_gid
:
u32
)
->
Result
<
Option
<
usize
>>
{
if
uid
==
0
{
let
path_str
=
str
::
from_utf8
(
path
)
.or
(
Err
(
Error
::
new
(
ENOENT
)))
?
.trim_matches
(
'/'
);
if
path_str
.is_empty
()
{
...
...
@@ -50,19 +69,21 @@ impl Scheme for DiskScheme {
write!
(
list
,
"{}
\n
"
,
i
)
.unwrap
();
}
let
id
=
self
.next_id
.fetch_add
(
1
,
Ordering
::
SeqCst
);
self
.handles
.lock
()
.insert
(
id
,
Handle
::
List
(
list
.into_bytes
(),
0
));
Ok
(
id
)
let
id
=
self
.next_id
;
self
.next_id
+=
1
;
self
.handles
.insert
(
id
,
Handle
::
List
(
list
.into_bytes
(),
0
));
Ok
(
Some
(
id
))
}
else
{
Err
(
Error
::
new
(
EISDIR
))