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
redox-os
drivers
Commits
74ed054d
Unverified
Commit
74ed054d
authored
Jan 07, 2018
by
Jeremy Soller
Committed by
GitHub
Jan 07, 2018
Browse files
Merge pull request #23 from ids1024/dma
ahci: refactor duplicated ATA command code into a method
parents
6394b1b5
c8154e76
Changes
2
Hide whitespace changes
Inline
Side-by-side
ahcid/src/ahci/disk_ata.rs
View file @
74ed054d
...
...
@@ -62,14 +62,14 @@ impl Disk for DiskATA {
let
mut
sector
:
usize
=
0
;
while
sectors
-
sector
>=
255
{
self
.port
.
ata_dma
(
block
+
sector
as
u64
,
255
,
false
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
?
;
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
);
}
sector
+=
255
;
}
if
sector
<
sectors
{
self
.port
.
ata_dma
(
block
+
sector
as
u64
,
sectors
-
sector
,
false
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
?
;
self
.port
.
dma_read_write
(
block
+
sector
as
u64
,
sectors
-
sector
,
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
),
(
sectors
-
sector
)
*
512
);
}
...
...
@@ -86,7 +86,7 @@ impl Disk for DiskATA {
while
sectors
-
sector
>=
255
{
unsafe
{
ptr
::
copy
(
buffer
.as_ptr
()
.offset
(
sector
as
isize
*
512
),
self
.buf
.as_mut_ptr
(),
255
*
512
);
}
if
let
Err
(
err
)
=
self
.port
.
ata_dma
(
block
+
sector
as
u64
,
255
,
true
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
{
if
let
Err
(
err
)
=
self
.port
.
dma_read_write
(
block
+
sector
as
u64
,
255
,
true
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
{
return
Err
(
err
);
}
...
...
@@ -95,7 +95,7 @@ impl Disk for DiskATA {
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
.
ata_dma
(
block
+
sector
as
u64
,
sectors
-
sector
,
true
,
&
mut
self
.clb
,
&
mut
self
.ctbas
,
&
mut
self
.buf
)
{
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
);
}
...
...
ahcid/src/ahci/hba.rs
View file @
74ed054d
...
...
@@ -140,54 +140,24 @@ impl HbaPort {
// Shared between identify() and identify_packet()
unsafe
fn
identify_inner
(
&
mut
self
,
cmd
:
u8
,
clb
:
&
mut
Dma
<
[
HbaCmdHeader
;
32
]
>
,
ctbas
:
&
mut
[
Dma
<
HbaCmdTable
>
;
32
])
->
Option
<
u64
>
{
self
.is
.write
(
u32
::
MAX
);
let
dest
:
Dma
<
[
u16
;
256
]
>
=
Dma
::
new
([
0
;
256
])
.unwrap
();
if
let
Some
(
slot
)
=
self
.slot
()
{
let
cmdheader
=
&
mut
clb
[
slot
as
usize
];
cmdheader
.cfl
.write
(((
size_of
::
<
FisRegH2D
>
()
/
size_of
::
<
u32
>
())
as
u8
));
let
res
=
self
.ata_dma
(
clb
,
ctbas
,
|
cmdheader
,
cmdfis
,
prdt_entries
,
_acmd
|
{
cmdheader
.prdtl
.write
(
1
);
{
let
cmdtbl
=
&
mut
ctbas
[
slot
as
usize
];
ptr
::
write_bytes
(
cmdtbl
.deref_mut
()
as
*
mut
HbaCmdTable
as
*
mut
u8
,
0
,
size_of
::
<
HbaCmdTable
>
());
let
prdt_entry
=
&
mut
cmdtbl
.prdt_entry
[
0
];
prdt_entry
.dba
.write
(
dest
.physical
()
as
u64
);
prdt_entry
.dbc
.write
(
512
|
1
);
}
{
let
cmdfis
=
&
mut
*
(
ctbas
[
slot
as
usize
]
.cfis
.as_mut_ptr
()
as
*
mut
FisRegH2D
);
cmdfis
.fis_type
.write
(
FisType
::
RegH2D
as
u8
);
cmdfis
.pm
.write
(
1
<<
7
);
cmdfis
.command
.write
(
cmd
);
cmdfis
.device
.write
(
0
);
cmdfis
.countl
.write
(
1
);
cmdfis
.counth
.write
(
0
);
}
while
self
.tfd
.readf
((
ATA_DEV_BUSY
|
ATA_DEV_DRQ
)
as
u32
)
{
thread
::
yield_now
();
}
self
.ci
.writef
(
1
<<
slot
,
true
);
self
.start
();
while
(
self
.ci
.readf
(
1
<<
slot
)
||
self
.tfd
.readf
(
0x80
))
&&
self
.is
.read
()
&
HBA_PORT_IS_ERR
==
0
{
thread
::
yield_now
();
}
self
.stop
();
let
prdt_entry
=
&
mut
prdt_entries
[
0
];
prdt_entry
.dba
.write
(
dest
.physical
()
as
u64
);
prdt_entry
.dbc
.write
(
512
|
1
);
if
self
.is
.read
()
&
HBA_PORT_IS_ERR
!=
0
{
print!
(
"{}"
,
format!
(
"ERROR IS {:X} TFD {:X} SERR {:X}
\n
"
,
self
.is
.read
(),
self
.tfd
.read
(),
self
.serr
.read
()));
return
None
;
}
cmdfis
.pm
.write
(
1
<<
7
);
cmdfis
.command
.write
(
cmd
);
cmdfis
.device
.write
(
0
);
cmdfis
.countl
.write
(
1
);
cmdfis
.counth
.write
(
0
);
});
if
res
.is_ok
()
{
let
mut
serial
=
String
::
new
();
for
word
in
10
..
20
{
let
d
=
dest
[
word
];
...
...
@@ -248,139 +218,95 @@ impl HbaPort {
}
}
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
]
>
)
->
Result
<
usize
>
{
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));
}
assert
!
(
sectors
>
0
&&
sectors
<
256
);
self
.is
.write
(
u32
::
MAX
);
if
let
Some
(
slot
)
=
self
.slot
()
{
let
res
=
self
.ata_dma
(
clb
,
ctbas
,
|
cmdheader
,
cmdfis
,
prdt_entries
,
_acmd
|
{
if
write
{
//print!("{}", format!("SLOT {}\n", slot));
let
cfl
=
cmdheader
.cfl
.read
();
cmdheader
.cfl
.write
(
cfl
|
1
<<
7
|
1
<<
6
)
}
let
cmdheader
=
&
mut
clb
[
slot
as
usize
];
cmdheader
.cfl
.write
(((
size_of
::
<
FisRegH2D
>
()
/
size_of
::
<
u32
>
())
as
u8
)
|
if
write
{
1
<<
7
|
1
<<
6
}
else
{
0
});
cmdheader
.prdtl
.write
(
1
);
{
let
cmdtbl
=
&
mut
ctbas
[
slot
as
usize
]
;
unsafe
{
ptr
::
write_bytes
(
cmdtbl
.deref_mut
()
as
*
mut
HbaCmdTable
as
*
mut
u8
,
0
,
size_of
::
<
HbaCmdTable
>
())
}
;
let
prdt_entry
=
&
mut
prdt_entries
[
0
];
prdt_entry
.dba
.write
(
buf
.physical
()
as
u64
)
;
prdt_entry
.dbc
.write
(((
sectors
*
512
)
as
u32
)
|
1
)
;
let
prdt_entry
=
&
mut
cmdtbl
.prdt_entry
[
0
];
prdt_entry
.dba
.write
(
buf
.physical
()
as
u64
);
prdt_entry
.dbc
.write
(((
sectors
*
512
)
as
u32
)
|
1
);
cmdfis
.pm
.write
(
1
<<
7
);
if
write
{
cmdfis
.command
.write
(
ATA_CMD_WRITE_DMA_EXT
);
}
else
{
cmdfis
.command
.write
(
ATA_CMD_READ_DMA_EXT
);
}
{
let
cmdfis
=
unsafe
{
&
mut
*
(
ctbas
[
slot
as
usize
]
.cfis
.as_mut_ptr
()
as
*
mut
FisRegH2D
)
};
cmdfis
.fis_type
.write
(
FisType
::
RegH2D
as
u8
);
cmdfis
.pm
.write
(
1
<<
7
);
if
write
{
cmdfis
.command
.write
(
ATA_CMD_WRITE_DMA_EXT
);
}
else
{
cmdfis
.command
.write
(
ATA_CMD_READ_DMA_EXT
);
}
cmdfis
.lba0
.write
(
block
as
u8
);
cmdfis
.lba1
.write
((
block
>>
8
)
as
u8
);
cmdfis
.lba2
.write
((
block
>>
16
)
as
u8
);
cmdfis
.device
.write
(
1
<<
6
);
cmdfis
.lba0
.write
(
block
as
u8
);
cmdfis
.lba1
.write
((
block
>>
8
)
as
u8
);
cmdfis
.lba2
.write
((
block
>>
16
)
as
u8
);
cmdfis
.lba3
.write
((
block
>>
24
)
as
u8
);
cmdfis
.lba4
.write
((
block
>>
32
)
as
u8
);
cmdfis
.lba5
.write
((
block
>>
40
)
as
u8
);
cmdfis
.device
.write
(
1
<<
6
);
cmdfis
.
countl
.write
(
sectors
as
u8
);
cmdfis
.
counth
.write
((
sectors
>>
8
)
as
u8
);
}
cmdfis
.
lba3
.write
(
(
block
>>
24
)
as
u8
);
cmdfis
.
lba4
.write
((
block
>>
32
)
as
u8
);
cmdfis
.lba5
.write
((
block
>>
40
)
as
u8
);
if
write
{
//print!("WAIT ATA_DEV_BUSY | ATA_DEV_DRQ\n");
}
while
self
.tfd
.readf
((
ATA_DEV_BUSY
|
ATA_DEV_DRQ
)
as
u32
)
{
thread
::
yield_now
();
}
cmdfis
.countl
.write
(
sectors
as
u8
);
cmdfis
.counth
.write
((
sectors
>>
8
)
as
u8
);
});
if
write
{
//print!("{}", format!("WRITE CI {:X} in {:X}\n", 1 << slot, self.ci.read()));
}
self
.ci
.writef
(
1
<<
slot
,
true
);
res
.and
(
Ok
(
sectors
*
512
))
}
self
.start
();
/// 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
|
{
let
cfl
=
cmdheader
.cfl
.read
();
cmdheader
.cfl
.write
(
cfl
|
1
<<
5
);
if
write
{
//print!("{}", format!("WAIT CI {:X} in {:X}\n", 1 << slot, self.ci.read()));
}
while
(
self
.ci
.readf
(
1
<<
slot
)
||
self
.tfd
.readf
(
0x80
))
&&
self
.is
.read
()
&
HBA_PORT_IS_ERR
==
0
{
thread
::
yield_now
();
if
write
{
//print!("{}", format!("WAIT CI {:X} TFD {:X} IS {:X} CMD {:X} SERR {:X}\n", self.ci.read(), self.tfd.read(), self.is.read(), self.cmd.read(), self.serr.read()));
}
}
cmdheader
.prdtl
.write
(
1
);
self
.stop
();
let
prdt_entry
=
&
mut
prdt_entries
[
0
];
prdt_entry
.dba
.write
(
buf
.physical
()
as
u64
);
prdt_entry
.dbc
.write
(
size
-
1
);
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
);
return
Err
(
Error
::
new
(
EIO
));
}
cmdfis
.pm
.write
(
1
<<
7
);
cmdfis
.command
.write
(
ATA_CMD_PACKET
);
cmdfis
.device
.write
(
0
);
cmdfis
.lba1
.write
(
0
);
cmdfis
.lba2
.write
(
0
);
cmdfis
.featurel
.write
(
1
);
cmdfis
.featureh
.write
(
0
);
if
write
{
//print!("{}", format!("SUCCESS {}\n", sectors));
}
Ok
(
sectors
*
512
)
}
else
{
print!
(
"No Command Slots
\n
"
);
Err
(
Error
::
new
(
EIO
))
}
unsafe
{
ptr
::
write_volatile
(
acmd
.as_mut_ptr
()
as
*
mut
[
u8
;
16
],
*
cmd
)
};
})
}
/// 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
<
()
>
{
fn
ata_dma
<
F
>
(
&
mut
self
,
clb
:
&
mut
Dma
<
[
HbaCmdHeader
;
32
]
>
,
ctbas
:
&
mut
[
Dma
<
HbaCmdTable
>
;
32
],
callback
:
F
)
->
Result
<
()
>
where
F
:
FnOnce
(
&
mut
HbaCmdHeader
,
&
mut
FisRegH2D
,
&
mut
[
HbaPrdtEntry
;
65536
],
&
mut
[
Mmio
<
u8
>
;
16
])
{
self
.is
.write
(
u32
::
MAX
);
if
let
Some
(
slot
)
=
self
.slot
()
{
let
cmdheader
=
&
mut
clb
[
slot
as
usize
];
cmdheader
.cfl
.write
(((
size_of
::
<
FisRegH2D
>
()
/
size_of
::
<
u32
>
())
as
u8
)
|
(
1
<<
5
));
cmdheader
.prdtl
.write
(
1
);
{
let
cmdheader
=
&
mut
clb
[
slot
as
usize
];
cmdheader
.cfl
.write
(((
size_of
::
<
FisRegH2D
>
()
/
size_of
::
<
u32
>
())
as
u8
));
let
cmdtbl
=
&
mut
ctbas
[
slot
as
usize
];
unsafe
{
ptr
::
write_bytes
(
cmdtbl
.deref_mut
()
as
*
mut
HbaCmdTable
as
*
mut
u8
,
0
,
size_of
::
<
HbaCmdTable
>
())
}
;
unsafe
{
ptr
::
write_bytes
(
cmdtbl
.deref_mut
()
as
*
mut
HbaCmdTable
as
*
mut
u8
,
0
,
size_of
::
<
HbaCmdTable
>
())
;
}
let
prdt_entry
=
&
mut
cmdtbl
.prdt_entry
[
0
];
prdt_entry
.dba
.write
(
buf
.physical
()
as
u64
);
prdt_entry
.dbc
.write
(
size
-
1
);
}
let
cmdfis
=
unsafe
{
&
mut
*
(
cmdtbl
.cfis
.as_mut_ptr
()
as
*
mut
FisRegH2D
)
};
cmdfis
.fis_type
.write
(
FisType
::
RegH2D
as
u8
);
{
let
cmd
fis
=
unsafe
{
&
mut
*
(
ctbas
[
slot
as
usize
]
.cfis
.as_mut_ptr
()
as
*
mut
FisRegH2D
)
};
let
prdt_entry
=
unsafe
{
&
mut
*
(
&
mut
cmdtbl
.prdt_entry
as
*
mut
_
)
};
let
a
cmd
=
unsafe
{
&
mut
*
(
&
mut
cmdtbl
.acmd
as
*
mut
_
)
};
cmdfis
.fis_type
.write
(
FisType
::
RegH2D
as
u8
);
cmdfis
.pm
.write
(
1
<<
7
);
cmdfis
.command
.write
(
ATA_CMD_PACKET
);
cmdfis
.device
.write
(
0
);
cmdfis
.lba1
.write
(
0
);
cmdfis
.lba2
.write
(
0
);
cmdfis
.featurel
.write
(
1
);
cmdfis
.featureh
.write
(
0
);
callback
(
cmdheader
,
cmdfis
,
prdt_entry
,
acmd
)
}
let
acmd
=
unsafe
{
&
mut
*
(
ctbas
[
slot
as
usize
]
.acmd
.as_mut_ptr
()
as
*
mut
[
u8
;
16
])
};
*
acmd
=
*
cmd
;
while
self
.tfd
.readf
((
ATA_DEV_BUSY
|
ATA_DEV_DRQ
)
as
u32
)
{
thread
::
yield_now
();
}
...
...
@@ -396,12 +322,15 @@ impl HbaPort {
self
.stop
();
if
self
.is
.read
()
&
HBA_PORT_IS_ERR
!=
0
{
print!
(
"{}"
,
format!
(
"ERROR IS {:X} TFD {:X} SERR {:X}
\n
"
,
self
.is
.read
(),
self
.tfd
.read
(),
self
.serr
.read
()));
return
Err
(
Error
::
new
(
EIO
));
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
(())
}
Ok
(())
}
else
{
print!
(
"No Command Slots
\n
"
);
Err
(
Error
::
new
(
EIO
))
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment