Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
drivers
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Liam Naddell
drivers
Commits
c8154e76
Unverified
Commit
c8154e76
authored
Jan 06, 2018
by
Ian Douglas Scott
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ahci: refactor duplicated ATA command code into a method
parent
6394b1b5
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
77 additions
and
148 deletions
+77
-148
ahcid/src/ahci/disk_ata.rs
ahcid/src/ahci/disk_ata.rs
+4
-4
ahcid/src/ahci/hba.rs
ahcid/src/ahci/hba.rs
+73
-144
No files found.
ahcid/src/ahci/disk_ata.rs
View file @
c8154e76
...
...
@@ -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 @
c8154e76
...
...
@@ -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
cmdfis
=
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
acmd
=
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
Markdown
is supported
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