Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
x393_sata
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
x393_sata
Commits
a432d1a7
Commit
a432d1a7
authored
Apr 11, 2017
by
Mikhail Karpenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Set/get disk power management features from x393sata.py
parent
b37e83be
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
156 additions
and
0 deletions
+156
-0
x393sata.py
py393sata/x393sata.py
+156
-0
No files found.
py393sata/x393sata.py
View file @
a432d1a7
...
@@ -150,6 +150,11 @@ ATA_RDMA_EXT = 0x25 # Read DMA devices that support 48-bit Addressing
...
@@ -150,6 +150,11 @@ ATA_RDMA_EXT = 0x25 # Read DMA devices that support 48-bit Addressing
ATA_RBUF_PIO
=
0xe4
# Read 512 bytes from device buffer in PIO mode
ATA_RBUF_PIO
=
0xe4
# Read 512 bytes from device buffer in PIO mode
ATA_RBUF_DMA
=
0xe9
# Read 512 bytes from device buffer in DMA mode
ATA_RBUF_DMA
=
0xe9
# Read 512 bytes from device buffer in DMA mode
ATA_READ_LOG_EXT
=
0x2f
ATA_READ_LOG_EXT
=
0x2f
ATA_SET_FEATURES
=
0xef
# Set features command
# SET FEATURES command subcommand codes
APM_ENABLE
=
0x05
APM_DISABLE
=
0x85
class
x393sata
(
object
):
class
x393sata
(
object
):
DRY_MODE
=
True
# True
DRY_MODE
=
True
# True
...
@@ -1465,6 +1470,157 @@ class x393sata(object):
...
@@ -1465,6 +1470,157 @@ class x393sata(object):
else
:
else
:
return
'10389B'
return
'10389B'
# raise Exception ("Unknown camera MAC address used to get 10389 revision. Only *:01 (10389) and *:02 (10389B) are currently defined")
# raise Exception ("Unknown camera MAC address used to get 10389 revision. Only *:01 (10389) and *:02 (10389B) are currently defined")
def
set_features
(
self
,
feature
,
param
=
0
,
do_not_start
=
False
,
prd_irqs
=
None
):
"""
Send SET FEATURES command
@param feature - subcommand to be processed (see ATA/ATAPI command set 7.45 for the list of subcommands);
supported commands: 0x05 (enable APM feature set), 0x85 (disable APM feature set)
@param param - parameter for the feature
@param do_not_start - do not actually launch the command by writing 1 to command_issue (CI) bit in PxCI register
@param prd_irqs - None or a tuple/list with per-PRD interrupts
"""
supported_subcmd
=
[
APM_ENABLE
,
APM_DISABLE
]
if
not
feature
in
supported_subcmd
:
raise
Exception
(
"Subcommand 0x
%
x is not supported"
%
(
feature
))
# Clear interrupt register
self
.
x393_mem
.
write_mem
(
self
.
get_reg_address
(
'HBA_PORT__PxIS'
),
0xffffffff
)
self
.
sync_for_cpu
(
'H2D'
,
COMMAND_ADDRESS
,
256
)
# command and PRD table
# clear system memory for the command
for
a
in
range
(
64
):
self
.
x393_mem
.
write_mem
(
COMMAND_ADDRESS
+
4
*
a
,
0
)
#Setup command table in system memory
self
.
x393_mem
.
write_mem
(
COMMAND_ADDRESS
+
0
,
FIS_H2DR
|
# FIS type - H2D register (0x27)
(
0x80
<<
8
)
|
# set C = 1
(
ATA_SET_FEATURES
<<
16
)
|
# Command = 0xEF
(
feature
<<
24
))
# features = subcommand, see ATA/ATAPI command set 7.45 table 104
# other DWORDs are subcommand scpecific
if
feature
==
APM_ENABLE
:
count
=
param
&
0xff
self
.
x393_mem
.
write_mem
(
COMMAND_ADDRESS
+
12
,
count
|
# count field is subcommand specific
(
0x08
<<
24
))
# control field as set by hdparm
# Setup command header
self
.
x393_mem
.
write_mem
(
MAXI1_ADDR
+
COMMAND_HEADER0_OFFS
+
(
0
<<
2
),
(
5
<<
0
)
|
# 'CFL' - number of DWORDs in this CFIS
(
0
<<
5
)
|
# 'A' Not ATAPI
(
0
<<
6
)
|
# 'W' Not write to device
# (1 << 7) | # 'P' Prefetchable = 1
(
0
<<
7
)
|
# 'P' Prefetchable = 0
(
0
<<
8
)
|
# 'R' Not a Reset
(
0
<<
9
)
|
# 'B' Not a BIST
# (1 << 10) | # 'C' Do clear BSY/CI after transmitting this command
(
0
<<
10
)
|
# 'C' Do clear BSY/CI after transmitting this command
(
0
<<
16
))
# 'PRDTL' - number of PRDT entries (no data required)
self
.
x393_mem
.
write_mem
(
MAXI1_ADDR
+
COMMAND_HEADER0_OFFS
+
(
2
<<
2
),
(
COMMAND_ADDRESS
))
# 'CTBA' - Command table base address
self
.
sync_for_device
(
'H2D'
,
COMMAND_ADDRESS
,
256
)
# command and PRD table
self
.
sync_for_device
(
'D2H'
,
DATAIN_ADDRESS
,
512
)
# Set PxCMD.ST bit (it may already be set)
self
.
x393_mem
.
write_mem
(
self
.
get_reg_address
(
'HBA_PORT__PxCMD'
),
0x11
)
# .ST and .FRE bits (FRE is readonly 1 anyway)
# Set Command Issued
if
do_not_start
:
print
(
'Run the following command to start the comand:'
)
print
(
"mem.write_mem(sata.get_reg_address('HBA_PORT__PxCI'), 1)"
)
else
:
self
.
x393_mem
.
write_mem
(
self
.
get_reg_address
(
'HBA_PORT__PxCI'
),
1
)
print
(
"Command table data:"
)
print
(
"_=mem.mem_dump (0x
%
x, 0x10,4)"
%
(
COMMAND_ADDRESS
))
self
.
x393_mem
.
mem_dump
(
COMMAND_ADDRESS
,
0x20
,
4
)
#Wait interrupt
for
_
in
range
(
10
):
istat
=
self
.
x393_mem
.
read_mem
(
self
.
get_reg_address
(
'HBA_PORT__PxIS'
))
if
istat
:
self
.
parse_register
(
group_range
=
[
'HBA_PORT__PxIS'
],
skip0
=
True
,
dword
=
None
)
if
istat
!=
1
:
#DHRS interrupt (for PIO - 2)
print
(
"
\n
======================Got wrong interrupt ============================"
)
self
.
reg_status
()
print
(
"_=mem.mem_dump (0x
%
x, 0x4,4)"
%
(
MAXI1_ADDR
+
DBG_OFFS
))
self
.
x393_mem
.
mem_dump
(
MAXI1_ADDR
+
DBG_OFFS
,
0x4
,
4
)
print
(
"Datascope (debug) data:"
)
print
(
"_=mem.mem_dump (0x
%
x, 0x20,4)"
%
(
DATASCOPE_ADDR
))
self
.
x393_mem
.
mem_dump
(
DATASCOPE_ADDR
,
0xa0
,
4
)
dd
=
0
for
a
in
range
(
0x80001000
,
0x80001014
,
4
):
dd
|=
self
.
x393_mem
.
read_mem
(
a
)
if
dd
==
0
:
print
(
"*** Probably got cache/write buffer problem, continuing ***"
)
break
raise
Exception
(
"Failed to get interrupt"
)
break
sleep
(
0.1
)
else
:
print
(
"
\n
====================== Failed to get interrupt ============================"
)
self
.
reg_status
()
print
(
"_=mem.mem_dump (0x
%
x, 0x4,4)"
%
(
MAXI1_ADDR
+
DBG_OFFS
))
self
.
x393_mem
.
mem_dump
(
MAXI1_ADDR
+
DBG_OFFS
,
0x4
,
4
)
print
(
"Datascope (debug) data:"
)
print
(
"_=mem.mem_dump (0x
%
x, 0x100,4)"
%
(
DATASCOPE_ADDR
))
self
.
x393_mem
.
mem_dump
(
DATASCOPE_ADDR
,
0x200
,
4
)
raise
Exception
(
"Failed to get interrupt"
)
print
(
"Datascope (debug) data:"
)
print
(
"_=mem.mem_dump (0x
%
x, 0x200,4)"
%
(
DATASCOPE_ADDR
))
self
.
x393_mem
.
mem_dump
(
DATASCOPE_ADDR
,
0x200
,
4
)
def
get_features
(
self
):
"""
Send IDENTIFY DEVICE command and (partially) parse its output
"""
self
.
setup_pio_read_identify_command
()
# get power management features, see ATA/ATAPI command set 7.45.9
# all offsets here are in WORDS as given in IDENTIFY DEVICE data table and should be doubled
print
(
"Power management features:"
)
id_word
=
self
.
x393_mem
.
read_mem
(
DATAIN_ADDRESS
+
IDENTIFY_BUF
+
2
*
82
)
if
id_word
&
0x08
:
print
(
"Power management feature set is supported (see ATA/ATAPI command set 4.15 for the full list of supported commands)"
)
id_word
=
self
.
x393_mem
.
read_mem
(
DATAIN_ADDRESS
+
IDENTIFY_BUF
+
2
*
83
)
if
id_word
&
0x08
:
id_word
=
self
.
x393_mem
.
read_mem
(
DATAIN_ADDRESS
+
IDENTIFY_BUF
+
2
*
86
)
if
(
id_word
&
0x08
):
is_enabled
=
"enabled"
else
:
is_enabled
=
"disabled"
print
(
"
\t
APM feature set is supported and
%
s"
%
(
is_enabled
))
else
:
print
(
"
\t
APM feature set is NOT supported"
)
id_word
=
self
.
x393_mem
.
read_mem
(
DATAIN_ADDRESS
+
IDENTIFY_BUF
+
2
*
91
)
&
0xff
if
id_word
==
0x0
:
level
=
"reserved"
elif
id_word
==
0x1
:
level
=
"minimum pwr with standby mode"
elif
id_word
>
0x1
and
id_word
<=
0x7f
:
level
=
"intermediate pwr with standby mode"
elif
id_word
==
0x80
:
level
=
"minimum pwr without standby mode"
elif
id_word
>=
0x81
and
id_word
<=
0xfd
:
level
=
"intermediate pwr without standby mode"
elif
id_word
==
0xfe
:
level
=
"maximun performance"
elif
id_word
==
0xff
:
level
=
"reserved"
print
(
"
\t
Current APM level: 0x
%
x [
%
s]"
%
(
id_word
,
level
))
# get SATA features related to power management, see ATA/ATAPI command set 7.45.17
id_word
=
self
.
x393_mem
.
read_mem
(
DATAIN_ADDRESS
+
IDENTIFY_BUF
+
2
*
78
)
if
id_word
&
0x08
:
id_word
=
self
.
x393_mem
.
read_mem
(
DATAIN_ADDRESS
+
IDENTIFY_BUF
+
2
*
79
)
if
id_word
&
0x08
:
state
=
"device initiated power management enabled"
else
:
state
=
"device initiated power management disabled"
print
(
"
\t
Device supports initiating power management,
%
s"
%
(
state
))
id_word
=
self
.
x393_mem
.
read_mem
(
DATAIN_ADDRESS
+
IDENTIFY_BUF
+
2
*
76
)
if
id_word
&
0x4000
:
print
(
"
\t
Supports Device Automatic Partial to Slumber transition"
)
if
id_word
&
0x2000
:
print
(
"
\t
Supports Host Automatic Partial to Slumber transition"
)
if
id_word
&
0x200
:
print
(
"
\t
Supports receipt of host initiated power management requests"
)
def
init_sata
():
def
init_sata
():
...
...
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