Add Erik Quanstrom's atazz
(needed to disable power management/head unload on 2.5" drive)
This commit is contained in:
parent
913afc39c9
commit
fa7fb8b66b
11 changed files with 6820 additions and 0 deletions
131
sys/src/cmd/atazz/atazz.h
Normal file
131
sys/src/cmd/atazz/atazz.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
enum {
|
||||
Cmdn = 1,
|
||||
Cmdf, /* cfa only */
|
||||
Cmdp, /* packet */
|
||||
Cmd5sc, /* 512-byte sector size, set sector count */
|
||||
};
|
||||
|
||||
typedef struct Dev Dev;
|
||||
struct Dev {
|
||||
Sfis;
|
||||
int fd;
|
||||
uint secsize;
|
||||
uvlong nsect;
|
||||
uvlong wwn;
|
||||
};
|
||||
|
||||
enum {
|
||||
Cmdsz = 18,
|
||||
Replysz = 18,
|
||||
};
|
||||
|
||||
typedef struct Rcmd Rcmd;
|
||||
struct Rcmd {
|
||||
uchar sdcmd; /* sd command; 0xff means ata passthrough */
|
||||
uchar ataproto; /* ata protocol. non-data, pio, reset, dd, etc. */
|
||||
uchar fis[Fissize];
|
||||
};
|
||||
|
||||
typedef struct Req Req;
|
||||
struct Req {
|
||||
int rfd;
|
||||
int wfd;
|
||||
uchar fmtrw;
|
||||
uvlong lba;
|
||||
uvlong count; /* bytes; allow long sectors to work */
|
||||
uint nsect;
|
||||
char haverfis;
|
||||
uint fisbits; /* bitmask of manually set fields */
|
||||
Rcmd cmd;
|
||||
Rcmd reply;
|
||||
uchar *data;
|
||||
uchar raw;
|
||||
};
|
||||
|
||||
void sigfmt(Req*);
|
||||
void idfmt(Req*);
|
||||
void iofmt(Req*);
|
||||
void sdfmt(Req*);
|
||||
void smfmt(Req*);
|
||||
void slfmt(Req*);
|
||||
void glfmt(Req*);
|
||||
|
||||
typedef struct Btab Btab;
|
||||
struct Btab {
|
||||
int bit;
|
||||
char *name;
|
||||
};
|
||||
char *sebtab(char*, char*, Btab*, int, uint);
|
||||
|
||||
typedef struct Txtab Txtab;
|
||||
typedef struct Fetab Fetab;
|
||||
|
||||
struct Txtab {
|
||||
int val;
|
||||
char *name;
|
||||
Fetab *fe;
|
||||
};
|
||||
|
||||
struct Fetab {
|
||||
int reg;
|
||||
Txtab *tab;
|
||||
int ntab;
|
||||
};
|
||||
|
||||
/* sct “registers” */
|
||||
enum {
|
||||
Sbase = 1<<5,
|
||||
Sbyte = 0<<6,
|
||||
Sw = 1<<6,
|
||||
Sdw = 2<<6,
|
||||
Sqw = 3<<6,
|
||||
Ssz = 3<<6,
|
||||
|
||||
Saction = 0 | Sbase | Sw,
|
||||
Sfn = 1 | Sbase | Sw,
|
||||
Slba = 2 | Sbase | Sqw,
|
||||
Scnt = 6 | Sbase | Sqw,
|
||||
Spat = 10 | Sbase | Sdw,
|
||||
Ssc = 2 | Sbase | Sw,
|
||||
Stimer = 3 | Sbase | Sw,
|
||||
Sfe = 2 | Sbase | Sw,
|
||||
Sstate = 3 | Sbase | Sw,
|
||||
Soptf = 4 | Sbase | Sw,
|
||||
Stabid = 2 | Sbase | Sw,
|
||||
|
||||
Pbase = 1<<6,
|
||||
};
|
||||
|
||||
void pw(uchar*, ushort);
|
||||
void pdw(uchar*, uint);
|
||||
void pqw(uchar*, uvlong);
|
||||
ushort w(uchar*);
|
||||
uint dw(uchar*);
|
||||
uvlong qw(uchar*);
|
||||
|
||||
/*
|
||||
* botch. integrate with fis.h?
|
||||
*/
|
||||
enum {
|
||||
Psct = 1<<6 + 8,
|
||||
};
|
||||
|
||||
typedef struct Atatab Atatab;
|
||||
struct Atatab {
|
||||
ushort cc;
|
||||
uchar flags;
|
||||
uchar pktflags;
|
||||
ushort protocol;
|
||||
Fetab *tab;
|
||||
void (*fmt)(Req*);
|
||||
char *name;
|
||||
};
|
||||
|
||||
int eprint(char *, ...);
|
||||
int opendev(char*, Dev*);
|
||||
int probe(void);
|
||||
|
||||
extern int squelch;
|
||||
|
||||
#pragma varargck argpos eprint 1
|
||||
#pragma varargck type "π" char**
|
573
sys/src/cmd/atazz/atazz.ms
Normal file
573
sys/src/cmd/atazz/atazz.ms
Normal file
|
@ -0,0 +1,573 @@
|
|||
.FP lucidasans
|
||||
.TL
|
||||
ATA au Naturel
|
||||
.AU
|
||||
Erik Quanstrom
|
||||
quanstro@quanstro.net
|
||||
.AB
|
||||
The Plan 9
|
||||
.I sd (3)
|
||||
interface allows raw commands to be sent. Traditionally,
|
||||
only SCSI CDBs could be sent in this manner. For devices
|
||||
that respond to ATA/ATAPI commands, a small set of SCSI CDBs
|
||||
have been translated into an ATA equivalent. This approach
|
||||
works very well. However, there are ATA commands such as
|
||||
SMART which do not have direct translations. I describe how
|
||||
ATA/ATAPI commands were supported without disturbing
|
||||
existing functionality.
|
||||
.AE
|
||||
.SH
|
||||
Introduction
|
||||
.PP
|
||||
In writing new
|
||||
.I sd (3)
|
||||
drivers for plan 9, it has been necessary to copy laundry
|
||||
list of special commands that were needed with previous
|
||||
drivers. The set of commands supported by each device
|
||||
driver varies, and they are typically executed by writing a
|
||||
magic string into the driver's
|
||||
.CW ctl
|
||||
file. This requires code duplicated for each driver, and
|
||||
covers few commands. Coverage depends on the driver. It is
|
||||
not possible for the control interface to return output,
|
||||
making some commands impossible to implement. While a
|
||||
work around has been to change the contents of the control
|
||||
file, this solution is extremely unwieldy even for simple
|
||||
commands such as
|
||||
.CW "IDENTIFY DEVICE" .
|
||||
.SH
|
||||
Considerations
|
||||
.PP
|
||||
Currently, all
|
||||
.I sd
|
||||
devices respond to a small subset of SCSI commands
|
||||
through the raw interface and the normal read/write interface uses
|
||||
SCSI command blocks. SCSI devices, of course, respond natively
|
||||
while ATA devices emulate these commands with the help
|
||||
.I sd .
|
||||
This means that
|
||||
.I scuzz (8)
|
||||
can get surprisingly far with ATA devices, and ATAPI
|
||||
.I \fP(\fPsic. )
|
||||
devices
|
||||
work quite well. Although a new implementation might not
|
||||
use this approach, replacing the interface did not appear
|
||||
cost effective and would lead to maximum incompatibilities,
|
||||
while this interface is experimental. This means that the raw interface will need
|
||||
a method of signaling an ATA command rather than a SCSI CDB.
|
||||
.PP
|
||||
An unattractive wart of the ATA command set is there are seven
|
||||
protocols and two command sizes. While each command has a
|
||||
specific size (either 28-bit LBA or 48-bit LLBA) and is
|
||||
associated with a particular protocol (PIO, DMA, PACKET,
|
||||
etc.), this information is available only by table lookup.
|
||||
While this information may not always be necessary for simple
|
||||
SATA-based controllers, for the IDE controllers, it is required.
|
||||
PIO commands are required and use a different set of registers
|
||||
than DMA commands. Queued DMA commands and ATAPI
|
||||
commands are submitted differently still. Finally,
|
||||
the data direction is implied by the command. Having these
|
||||
three extra pieces of information in addition to the command
|
||||
seems necessary.
|
||||
.PP
|
||||
A final bit of extra-command information that may be useful
|
||||
is a timeout. While
|
||||
.I alarm (2)
|
||||
timeouts work with many drivers, it would be an added
|
||||
convenience to be able to specify a timeout along with the
|
||||
command. This seems a good idea in principle, since some
|
||||
ATA commands should return within milli- or microseconds,
|
||||
others may take hours to complete. On the other hand, the
|
||||
existing SCSI interface does not support it and changing its
|
||||
kernel-to-user space format would be quite invasive. Timeouts
|
||||
were left for a later date.
|
||||
.SH
|
||||
Protocol and Data Format
|
||||
.PP
|
||||
The existing protocol for SCSI commands suits ATA as well.
|
||||
We simply write the command block to the raw device. Then
|
||||
we either write or read the data. Finally the status block
|
||||
is read. What remains is choosing a data format for ATA
|
||||
commands.
|
||||
.PP
|
||||
The T10 Committee has defined a SCSI-to-ATA translation
|
||||
scheme called SAT[4]. This provides a standard set of
|
||||
translations between common SCSI commands and ATA commands.
|
||||
It specifies the ATA protocol and some other sideband
|
||||
information. It is particularly useful for common commands
|
||||
such as
|
||||
.CW "READ\ (12)"
|
||||
or
|
||||
.CW "READ CAPACITY\ (12)" .
|
||||
Unfortunately, our purpose is to address the uncommon commands.
|
||||
For those, special commands
|
||||
.CW "ATA PASSTHROUGH\ (12)"
|
||||
and
|
||||
.CW "(16)"
|
||||
exist. Unfortunately several commands we are interested in,
|
||||
such as those that set transfer modes are not allowed by the
|
||||
standard. This is not a major obstacle. We could simply
|
||||
ignore the standard. But this goes against the general
|
||||
reasons for using an established standard: interoperability.
|
||||
Finally, it should be mentioned that SAT format adds yet
|
||||
another intermediate format of variable size which would
|
||||
require translation to a usable format for all the existing
|
||||
Plan 9 drivers. If we're not hewing to a standard, we should
|
||||
build or choose for convenience.
|
||||
.PP
|
||||
ATA-8 and ACS-2 also specify an abstract register layout.
|
||||
The size of the command block varies based on the “size”
|
||||
(either 28- or 48-bits) of the command and only context
|
||||
differentiates a command from a response. The SATA
|
||||
specification defines host-to-drive communications. The
|
||||
formats of transactions are called Frame Information
|
||||
Structures (FISes). Typically drivers fill out the command
|
||||
FISes directly and have direct access to the Device-to-Host
|
||||
Register (D2H) FISes that return the resulting ATA register
|
||||
settings. The command FISes are also called Host-to-Device
|
||||
(H2D) Register FISes. Using this structure has several advantages. It
|
||||
is directly usable by many of the existing SATA drivers.
|
||||
All SATA commands are the same size and are tagged as
|
||||
commands. Normal responses are also all of the same size
|
||||
and are tagged as responses. Unfortunately, the ATA
|
||||
protocol is not specified. Nevertheless, SATA FISes seem to
|
||||
handle most of our needs and are quite convenient; they can
|
||||
be used directly by two of the three current SATA drivers.
|
||||
.SH
|
||||
Implementation
|
||||
.PP
|
||||
Raw ATA commands are formatted as a ATA escape byte, an
|
||||
encoded ATA protocol
|
||||
.CW proto
|
||||
and the FIS. Typically this would be a
|
||||
H2D FIS, but this is not a requirement. The escape byte
|
||||
.R 0xff ,
|
||||
which is not and, according to the current specification,
|
||||
will never be a valid SCSI command, was chosen. The
|
||||
protocol encoding
|
||||
.CW proto
|
||||
and other FIS construction details are specified in
|
||||
.CW "/sys/include/fis.h" .
|
||||
The
|
||||
.CW proto
|
||||
encodes the ATA protocol, the command “size” and data
|
||||
direction. The “atazz” command format is pictured in \*(Fn.
|
||||
.F1
|
||||
.PS
|
||||
scale=10
|
||||
w=8
|
||||
h=2
|
||||
define hdr |
|
||||
[
|
||||
box $1 ht h wid w
|
||||
] |
|
||||
define fis |
|
||||
[
|
||||
box $1 ht h wid w
|
||||
] |
|
||||
|
||||
F: [
|
||||
A: hdr("0xff")
|
||||
hdr("proto")
|
||||
hdr("0x27")
|
||||
hdr("flags")
|
||||
|
||||
B: hdr("cmd") at A+(0, -h)
|
||||
hdr("feat")
|
||||
hdr("lba0")
|
||||
hdr("lba8")
|
||||
|
||||
C: hdr("lba16") at B+(0, -h)
|
||||
hdr("dev")
|
||||
hdr("lba24")
|
||||
hdr("lba32")
|
||||
|
||||
D: hdr("lba40") at C+(0, -h)
|
||||
hdr("feat8")
|
||||
hdr("cnt")
|
||||
hdr("cnt8")
|
||||
|
||||
E: hdr("rsvd") at D+(0, -h)
|
||||
hdr("ctl")
|
||||
]
|
||||
G: [
|
||||
fis("sdXX/raw")
|
||||
] at F.se +(w*2, -h)
|
||||
arrow from F.e to G.w
|
||||
H: [
|
||||
fis("data")
|
||||
] at G.sw +(-w*2, -h)
|
||||
HH: [
|
||||
fis("sdXX/raw")
|
||||
] at H.se +(w*2, -h)
|
||||
|
||||
arrow from H.e to HH.w
|
||||
|
||||
Q: [
|
||||
fis("sdXX/raw")
|
||||
] at HH +(0, -2*h)
|
||||
|
||||
I: [
|
||||
K: hdr("0xff")
|
||||
hdr("proto")
|
||||
hdr("0x34")
|
||||
hdr("port");
|
||||
|
||||
L: hdr("stat") at K+(0, -h)
|
||||
hdr("err")
|
||||
hdr("lba0")
|
||||
hdr("lba8")
|
||||
|
||||
M: hdr("lba16") at L+(0, -h)
|
||||
hdr("dev")
|
||||
hdr("lba24")
|
||||
hdr("lba32")
|
||||
|
||||
O: hdr("lba40") at M+(0, -h)
|
||||
hdr("feat8")
|
||||
hdr("cnt")
|
||||
hdr("cnt8")
|
||||
|
||||
P: hdr("rsvd") at O+(0, -h)
|
||||
hdr("ctl")
|
||||
] at Q.sw +(-w*3.5, -3*h)
|
||||
arrow from Q.w to I.e
|
||||
|
||||
.PE
|
||||
.F2
|
||||
.F3
|
||||
.PP
|
||||
Raw ATA replies are formatted as a one-byte
|
||||
.R sd
|
||||
status code followed by the reply FIS.
|
||||
The usual read/write register substitutions are
|
||||
applied; ioport replaces flags, status replaces cmd, error
|
||||
replaces feature.
|
||||
.PP
|
||||
Important commands such as
|
||||
.CW "SMART RETURN STATUS"
|
||||
return no data. In this case, the protocol is run as usual.
|
||||
The client performs a 0-byte read to fulfill data transfer
|
||||
step. The status is in the D2H FIS returned as the status.
|
||||
The vendor ATA command
|
||||
.R 0xf0
|
||||
is used to return the device signature FIS as there is no
|
||||
universal in-band way to do this without side effects.
|
||||
When talking only to ATA drives, it is possible to first
|
||||
issue a
|
||||
.CW "IDENTIFY PACKET DEVICE"
|
||||
and then a
|
||||
.CW "IDENTIFY DEVICE"
|
||||
command, inferring the device type from the successful
|
||||
command. However, it would not be possible to enumerate the
|
||||
devices behind a port multiplier using this technique.
|
||||
.SH
|
||||
Kernel changes and Libfis
|
||||
.PP
|
||||
Very few changes were made to devsd to accommodate ATA
|
||||
commands. the
|
||||
.CW SDreq
|
||||
structure adds
|
||||
.CW proto
|
||||
and
|
||||
.CW ataproto
|
||||
fields. To avoid disturbing existing SCSI functionality and
|
||||
to allow drivers which support SCSI and ATA commands in
|
||||
parallel, an additional
|
||||
.CW ataio
|
||||
callback was added to
|
||||
.CW SDifc
|
||||
with the same signature as
|
||||
the existing
|
||||
.CW rio
|
||||
callback. About twenty lines of code were
|
||||
added to
|
||||
.CW port/devsd.c
|
||||
to recognize raw ATA commands and call the
|
||||
driver's
|
||||
.CW ataio
|
||||
function.
|
||||
.PP
|
||||
To assist in generating the FISes to communicate with devices,
|
||||
.CW libfis
|
||||
was written. It contains functions to identify and
|
||||
enumerate the important features of a drive, to format
|
||||
H2D FISes And finally, functions for
|
||||
.I sd
|
||||
and
|
||||
.I sd
|
||||
-devices to build D2H FISes to
|
||||
capture the device signature.
|
||||
.PP
|
||||
All ATA device drivers for the 386 architecture have been
|
||||
modified to accept raw ATA commands. Due to consolidation
|
||||
of FIS handling, the AHCI driver lost
|
||||
175 lines of code, additional non-atazz-related functionality
|
||||
notwithstanding. The IDE driver remained exactly the same
|
||||
size. Quite a bit more code could be removed if the driver
|
||||
were reorganized. The mv50xx driver gained 153 lines of
|
||||
code. Development versions of the Marvell Orion driver
|
||||
lost over 500 lines while
|
||||
.CW libfis
|
||||
is only about the same line count.
|
||||
.PP
|
||||
Since FIS formats were used to convey
|
||||
commands from user space,
|
||||
.CW libfis
|
||||
has been equally useful for user space applications. This is
|
||||
because the
|
||||
.I atazz
|
||||
interface can be thought of as an idealized HBA. Conversely,
|
||||
the hardware driver does not need to know anything about
|
||||
the command it is issuing beyond the ATA protocol.
|
||||
.SH
|
||||
Atazz
|
||||
.PP
|
||||
As an example and debugging tool, the
|
||||
.I atazz (8)
|
||||
command was written.
|
||||
.I Atazz
|
||||
is an analog to
|
||||
.I scuzz (8);
|
||||
they can be thought of as a driver for a virtual interface provided
|
||||
by
|
||||
.I sd
|
||||
combined with a disk console.
|
||||
ATA commands are spelled out verbosely as in ACS-2. Arbitrary ATA
|
||||
commands may be submitted, but the controller or driver may
|
||||
not support all of them. Here is a sample transcript:
|
||||
.P1
|
||||
az> probe
|
||||
/dev/sda0 976773168; 512 50000f001b206489
|
||||
/dev/sdC1 0; 0 0
|
||||
/dev/sdD0 1023120; 512 0
|
||||
/dev/sdE0 976773168; 512 50014ee2014f5b5a
|
||||
/dev/sdF7 976773168; 512 5000cca214c3a6d3
|
||||
az> open /dev/sdF0
|
||||
az> smart enable operations
|
||||
az> smart return status
|
||||
normal
|
||||
az> rfis
|
||||
00
|
||||
34405000004fc2a00000000000000000
|
||||
.P2
|
||||
.PP
|
||||
In the example, the
|
||||
.CW probe
|
||||
command is a special command that uses
|
||||
.CW #S/sdctl
|
||||
to enumerate the controllers in the system.
|
||||
For each controller, the
|
||||
.CW sd
|
||||
vendor command
|
||||
.CW 0xf0
|
||||
.CW \fP(\fPGET
|
||||
.CW SIGNATURE )
|
||||
is issued. If this command is successful, the
|
||||
number of sectors, sector size and WWN are gathered
|
||||
and and listed. The
|
||||
.CW /dev/sdC1
|
||||
device reports 0 sectors and 0 sector size because it is
|
||||
a DVD-RW with no media. The
|
||||
.CW open
|
||||
command is another special command that issues the
|
||||
same commands a SATA driver would issue to gather
|
||||
the information about the drive. The final two commands
|
||||
enable SMART
|
||||
and return the SMART status. The smart status is
|
||||
returned in a D2H FIS. This result is parsed the result
|
||||
is printed as either “normal,” or “threshold exceeded”
|
||||
(the drive predicts imminent failure).
|
||||
.PP
|
||||
As a further real-world example, a drive from my file server
|
||||
failed after a power outage. The simple diagnostic
|
||||
.CW "SMART RETURN STATUS"
|
||||
returned an uninformative “threshold exceeded.”
|
||||
We can run some more in-depth tests. In this case we
|
||||
will need to make up for the fact that
|
||||
.I atazz
|
||||
does not know every option to every command. We
|
||||
will set the
|
||||
.CW lba0
|
||||
register by hand:
|
||||
.P1
|
||||
az> smart lba0 1 execute off-line immediate # short data collection
|
||||
az> smart read data
|
||||
col status: 00 never started
|
||||
exe status: 89 failed: shipping damage, 90% left
|
||||
time left: 10507s
|
||||
shrt poll: 176m
|
||||
ext poll: 19m
|
||||
az>
|
||||
.P2
|
||||
.PP
|
||||
Here we see that the drive claims that it was damaged in
|
||||
shipping and the damage occurred in the first 10% of the
|
||||
drive. Since we know the drive had been working before
|
||||
the power outage, and the original symptom was excessive
|
||||
UREs (Unrecoverable Read Errors) followed by write
|
||||
failures, and finally a threshold exceeded condition, it is
|
||||
reasonable to assume that the head may have crashed.
|
||||
.SH
|
||||
Stand Alone Applications
|
||||
.PP
|
||||
There are several obvious stand-alone applications for
|
||||
this functionality: a drive firmware upgrade utility,
|
||||
a drive scrubber that bypasses the drive cache and a
|
||||
SMART monitor.
|
||||
.PP
|
||||
Since SCSI also supports a basic SMART-like
|
||||
interface through the
|
||||
.CW "SEND DIAGNOSTIC"
|
||||
and
|
||||
.CW "RECEIVE DIAGNOSTIC RESULTS"
|
||||
commands,
|
||||
.I disk/smart (8)
|
||||
gives a chance to test both raw ATA and SCSI
|
||||
commands in the same application.
|
||||
.PP
|
||||
.I Disk/smart
|
||||
uses the usual techniques for gathering a list of
|
||||
devices or uses the devices given. Then it issues a raw ATA request for
|
||||
the device signature. If that fails, it is assumed
|
||||
that the drive is SCSI, and a raw SCSI request is issued.
|
||||
In both cases,
|
||||
.I disk/smart
|
||||
is able to reliably determine if SMART is supported
|
||||
and can be enabled.
|
||||
.PP
|
||||
If successful, each device is probed every 5 minutes
|
||||
and failures are logged. A one shot mode is also
|
||||
available:
|
||||
.P1
|
||||
chula# disk/smart -atv
|
||||
sda0: normal
|
||||
sda1: normal
|
||||
sda2: normal
|
||||
sda3: threshold exceeded
|
||||
sdE1: normal
|
||||
sdF7: normal
|
||||
.P2
|
||||
.PP
|
||||
Drives
|
||||
.CW sda0 ,
|
||||
.CW sda1
|
||||
are SCSI
|
||||
and the remainder are ATA. Note that other drives
|
||||
on the same controller are ATA.
|
||||
Recalling that
|
||||
.CW sdC0
|
||||
was previously listed, we can check to see why no
|
||||
results were reported by
|
||||
.CW sdC0 :
|
||||
.P1
|
||||
chula# for(i in a3 C0)
|
||||
echo identify device |
|
||||
atazz /dev/sd$i >[2]/dev/null |
|
||||
grep '^flags'
|
||||
flags lba llba smart power nop sct
|
||||
flags lba
|
||||
.P2
|
||||
So we see that
|
||||
.CW sdC0
|
||||
simply does not support the SMART feature set.
|
||||
.SH
|
||||
Further Work
|
||||
.PP
|
||||
While the raw ATA interface has been used extensively
|
||||
from user space and has allowed the removal of quirky
|
||||
functionality, device setup has not yet been addressed.
|
||||
For example, both the Orion and AHCI drivers have
|
||||
an initialization routine similar to the following
|
||||
.P1
|
||||
newdrive(Drive *d)
|
||||
{
|
||||
setfissig(d, getsig(d));
|
||||
if(identify(d) != 0)
|
||||
return SDeio;
|
||||
setpowermode(d);
|
||||
if(settxmode(d, d->udma) != 0)
|
||||
return SDeio;
|
||||
return SDok;
|
||||
}
|
||||
.P2
|
||||
However in preparing this document, it was discovered
|
||||
that one sets the power mode before setting the
|
||||
transfer mode and the other does the opposite. It is
|
||||
not clear that this particular difference is a problem,
|
||||
but over time, such differences will be the source of bugs.
|
||||
Neither the IDE nor the Marvell 50xx drivers sets the
|
||||
power mode at all. Worse,
|
||||
none is capable of properly addressing drives with
|
||||
features such as PUIS (Power Up In Standby) enabled.
|
||||
To addresses this problem all four of the ATA drivers would
|
||||
need to be changed.
|
||||
.PP
|
||||
Rather than maintaining a number of mutually out-of-date
|
||||
drivers, it would be advantageous to build an ATA analog
|
||||
of
|
||||
.CW pc/sdscsi.c
|
||||
using the raw ATA interface to submit ATA commands.
|
||||
There are some difficulties that make such a change a bit
|
||||
more than trivial. Since current model for hot-pluggable
|
||||
devices is not compatible with the top-down
|
||||
approach currently taken by
|
||||
.I sd
|
||||
this would need to be addressed. It does not seem that
|
||||
this would be difficult. Interface resets after failed commands
|
||||
should also be addressed.
|
||||
.SH
|
||||
Source
|
||||
.PP
|
||||
The current source including all the pc drivers and applications
|
||||
are available
|
||||
in the following
|
||||
.I contrib (1)
|
||||
packages on
|
||||
.I sources :
|
||||
.br
|
||||
.CW "quanstro/fis" ,
|
||||
.br
|
||||
.CW "quanstro/sd" ,
|
||||
.br
|
||||
.CW "quanstro/atazz" ,
|
||||
and
|
||||
.br
|
||||
.CW "quanstro/smart" .
|
||||
.PP
|
||||
The following manual pages are included:
|
||||
.br
|
||||
.I fis (2),
|
||||
.I sd (3),
|
||||
.I sdahci (3),
|
||||
.I sdaoe (3),
|
||||
.I sdloop (3),
|
||||
.I sdorion (3),
|
||||
.I atazz (8),
|
||||
and
|
||||
.I smart (8).
|
||||
.SH
|
||||
Abbreviated References
|
||||
.nr PI 5n
|
||||
.IP [1]
|
||||
.I sd (1),
|
||||
published online at
|
||||
.br
|
||||
.CW "http://plan9.bell-labs.com/magic/man2html/3/sd" .
|
||||
.IP [2]
|
||||
.I scuzz (8),
|
||||
published online at
|
||||
.br
|
||||
.CW "http://plan9.bell-labs.com/magic/man2html/8/scuzz" .
|
||||
.IP [3]
|
||||
T13
|
||||
.I "ATA/ATAPI Command Set\ \-\ 2" ,
|
||||
revision 1, January 21, 2009,
|
||||
formerly published online at
|
||||
.CW "http://www.t13.org" .
|
||||
.IP [4]
|
||||
T10
|
||||
.I "SCSI/ATA Translation\ \-\ 2 (SAT\-2)" ,
|
||||
revision 7, February 18, 2007,
|
||||
formerly published online at
|
||||
.CW "http://www.t10.org" .
|
3414
sys/src/cmd/atazz/atazz.ps
Normal file
3414
sys/src/cmd/atazz/atazz.ps
Normal file
File diff suppressed because it is too large
Load diff
71
sys/src/cmd/atazz/bit.c
Normal file
71
sys/src/cmd/atazz/bit.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <fis.h>
|
||||
#include "atazz.h"
|
||||
|
||||
char*
|
||||
sebtab(char *p, char *e, Btab *t, int nt, uint u)
|
||||
{
|
||||
char *p0;
|
||||
int i;
|
||||
|
||||
p0 = p;
|
||||
for(i = 0; i < nt; i++)
|
||||
if(u & 1<< t[i].bit)
|
||||
p = seprint(p, e, "%s ", t[i].name);
|
||||
if(p > p0)
|
||||
p--;
|
||||
*p = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
pw(uchar *p, ushort i)
|
||||
{
|
||||
p[0] = i >> 0;
|
||||
p[1] = i >> 8;
|
||||
}
|
||||
|
||||
void
|
||||
pdw(uchar *p, uint i)
|
||||
{
|
||||
p[0] = i >> 0;
|
||||
p[1] = i >> 8;
|
||||
p[2] = i >> 16;
|
||||
p[3] = i >> 24;
|
||||
}
|
||||
|
||||
void
|
||||
pqw(uchar *p, uvlong i)
|
||||
{
|
||||
pdw(p, i);
|
||||
pdw(p + 4, i >> 32);
|
||||
}
|
||||
|
||||
ushort
|
||||
w(uchar *u)
|
||||
{
|
||||
ushort r;
|
||||
|
||||
r = u[0] << 0;
|
||||
r |= u[1] << 8;
|
||||
return r;
|
||||
}
|
||||
|
||||
uint
|
||||
dw(uchar *u)
|
||||
{
|
||||
ulong r;
|
||||
|
||||
r = u[0] << 0;
|
||||
r |= u[1] << 8;
|
||||
r |= u[2] << 16;
|
||||
r |= u[3] << 24;
|
||||
return r;
|
||||
}
|
||||
|
||||
uvlong
|
||||
qw(uchar *u)
|
||||
{
|
||||
return dw(u) | (uvlong)dw(u + 4)<<32;
|
||||
}
|
92
sys/src/cmd/atazz/macros.ms
Normal file
92
sys/src/cmd/atazz/macros.ms
Normal file
|
@ -0,0 +1,92 @@
|
|||
.de F1
|
||||
.nr OI \\n(.iu
|
||||
.nr PW 1v
|
||||
.KF
|
||||
.sp 0.3v
|
||||
..
|
||||
.de T1
|
||||
.F1
|
||||
..
|
||||
.de F2
|
||||
.ds Fp Figure\ \\n(Fi
|
||||
.ds Fn Figure\ \\n+(Fi
|
||||
.ds Fq \\*(Fp
|
||||
.F0
|
||||
..
|
||||
.de T2
|
||||
.ds Tp Table\ \\n(Ti
|
||||
.ds Tn Table\ \\n+(Ti
|
||||
.ds Tq \\*(Tp
|
||||
.T0
|
||||
..
|
||||
.de F0
|
||||
.nr BD 1
|
||||
.if t .ps \\n(PS-1
|
||||
.ie \\n(VS>=41 .vs \\n(VSu-1p
|
||||
.el .vs \\n(VSp-1p
|
||||
.ft 1
|
||||
.di DD
|
||||
.ll \\n(.lu*3u/4u
|
||||
.in 0
|
||||
.fi
|
||||
.ad b
|
||||
.sp 0.5v
|
||||
\f3\\*(Fq\f1\ \ \c
|
||||
..
|
||||
.de T0
|
||||
.nr BD 1
|
||||
.if t .ps \\n(PS-1
|
||||
.ie \\n(VS>=41 .vs \\n(VSu-1p
|
||||
.el .vs \\n(VSp-1p
|
||||
.ft 1
|
||||
.di DD
|
||||
.ll \\n(.lu*3u/4u
|
||||
.in 0
|
||||
.fi
|
||||
.ad b
|
||||
.sp 0.5v
|
||||
\f3\\*(Tq\f1\ \ \c
|
||||
..
|
||||
.de F3
|
||||
.sp 0.5v
|
||||
.di
|
||||
.br
|
||||
.ll \\n(.lu*4u/3u
|
||||
.if \\n(dl>\\n(BD .nr BD \\n(dl
|
||||
.if \\n(BD<\\n(.l .in (\\n(.lu-\\n(BDu)/2u
|
||||
.nf
|
||||
.DD
|
||||
.in \\n(OIu
|
||||
.nr BD 0
|
||||
.fi
|
||||
.KE
|
||||
.ie \\n(VS>=41 .vs \\n(VSu
|
||||
.el .vs \\n(VSp
|
||||
..
|
||||
.de T3
|
||||
.F3
|
||||
..
|
||||
.de EX
|
||||
.P1
|
||||
\s-4
|
||||
..
|
||||
.de EE
|
||||
\s+4
|
||||
.P2
|
||||
..
|
||||
.nr Fi 1 +1
|
||||
.nr Ti 1 +1
|
||||
.ds Fn Figure\ \\n(Fi
|
||||
.ds Tn Table\ \\n(Ti
|
||||
.nr XP 2 \" delta point size for program
|
||||
.nr XV 2p \" delta vertical for programs
|
||||
.nr XT 4 \" delta tab stop for programs
|
||||
.nr DV .5v \" space before start of program
|
||||
.FP lucidasans
|
||||
.nr PS 11
|
||||
.nr VS 13
|
||||
.nr LL 6.6i
|
||||
.nr PI 0 \" paragraph indent
|
||||
.nr PD 4p \" extra space between paragraphs
|
||||
.pl 11i
|
||||
.rm CH
|
1928
sys/src/cmd/atazz/main.c
Normal file
1928
sys/src/cmd/atazz/main.c
Normal file
File diff suppressed because it is too large
Load diff
23
sys/src/cmd/atazz/mkfile
Normal file
23
sys/src/cmd/atazz/mkfile
Normal file
|
@ -0,0 +1,23 @@
|
|||
</$objtype/mkfile
|
||||
|
||||
TARG = atazz
|
||||
|
||||
HFILES = atazz.h tabs.h
|
||||
OFILES = bit.$O main.$O probe.$O
|
||||
|
||||
BIN=/$objtype/bin
|
||||
UPDATE=\
|
||||
mkfile\
|
||||
$HFILES\
|
||||
${OFILES:%.$O=%.c}\
|
||||
${TARG:%=/386/bin/%}\
|
||||
|
||||
%.ps:DQ: %.ms
|
||||
eval `{doctype macros.ms $stem.ms} | \
|
||||
lp -m.9 -dstdout >$target
|
||||
|
||||
%.pdf:DQ: %.ps
|
||||
cat /sys/doc/docfonts $stem.ps >_$stem.ps
|
||||
ps2pdf _$stem.ps $stem.pdf && rm -f _$stem.ps
|
||||
|
||||
</sys/src/cmd/mkone
|
75
sys/src/cmd/atazz/probe.c
Normal file
75
sys/src/cmd/atazz/probe.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <fis.h>
|
||||
#include "atazz.h"
|
||||
|
||||
static int
|
||||
ckprint(char *s)
|
||||
{
|
||||
char buf[ERRMAX];
|
||||
int st;
|
||||
Dev d;
|
||||
|
||||
squelch = 1;
|
||||
d.fd = -1;
|
||||
st = opendev(s, &d);
|
||||
squelch = 0;
|
||||
if(st == -1){
|
||||
rerrstr(buf, sizeof buf);
|
||||
if(strstr(buf, "ata command") != nil)
|
||||
return 0;
|
||||
return 0 /* -1 */;
|
||||
}
|
||||
close(d.fd);
|
||||
print("%s\t%llud; %ud\t%llux\n", s, d.nsect, d.secsize, d.wwn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
probe0(char *s, int l)
|
||||
{
|
||||
char *p, *f[3], buf[16];
|
||||
int i, r;
|
||||
|
||||
s[l] = 0;
|
||||
r = 0;
|
||||
for(; p = strchr(s, '\n'); s = p + 1){
|
||||
if(tokenize(s, f, nelem(f)) < 1)
|
||||
continue;
|
||||
for(i = 0; i < 10; i++){
|
||||
snprint(buf, sizeof buf, "/dev/%s%d", f[0], i);
|
||||
switch(ckprint(buf)){
|
||||
case -1:
|
||||
eprint("!device error %s: %r\n", buf);
|
||||
break;
|
||||
case 0:
|
||||
goto nextdev;
|
||||
case 1:
|
||||
r++;
|
||||
break;
|
||||
}
|
||||
nextdev:
|
||||
;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
probe(void)
|
||||
{
|
||||
char *s;
|
||||
int fd, l, r;
|
||||
|
||||
fd = open("/dev/sdctl", OREAD);
|
||||
if(fd == -1)
|
||||
return -1;
|
||||
r = -1;
|
||||
l = 1024; /* #S/sdctl has 0 size; guess */
|
||||
if(s = malloc(l + 1))
|
||||
if((l = read(fd, s, l)) > 0)
|
||||
r = probe0(s, l);
|
||||
free(s);
|
||||
close(fd);
|
||||
return r;
|
||||
}
|
25
sys/src/cmd/atazz/sctnotes
Normal file
25
sys/src/cmd/atazz/sctnotes
Normal file
|
@ -0,0 +1,25 @@
|
|||
read log ext page 17
|
||||
- phy error log
|
||||
read log ext sctstat
|
||||
- current temperature
|
||||
|
||||
sct read data table hda temperature history
|
||||
- temperature history
|
||||
sct feature control
|
||||
set state [preserve]
|
||||
write cache
|
||||
write cache reordering
|
||||
enable
|
||||
disable
|
||||
set features
|
||||
temperature logging interval
|
||||
minutes
|
||||
return state
|
||||
return feature option flags
|
||||
write cache
|
||||
write cache reordering
|
||||
temperature logging interval
|
||||
az> sct error recovery time set read timer = 5
|
||||
az> sct error recovery time return read timer
|
||||
|
||||
sct cmd: Invalid Function code in SCT Feature Control command
|
22
sys/src/cmd/atazz/smartnotes
Normal file
22
sys/src/cmd/atazz/smartnotes
Normal file
|
@ -0,0 +1,22 @@
|
|||
this currently needs some more work
|
||||
|
||||
az> smart lba0 1 execute off-line immediate # short data collection
|
||||
az> smart read data
|
||||
col status: 06 aborted by device with fatal error
|
||||
exe status: 89 failed: shipping damage, 90% left
|
||||
time left: 11924s
|
||||
shrt poll: 200m
|
||||
ext poll: 21m
|
||||
|
||||
options are:
|
||||
lba0
|
||||
0x00 normal
|
||||
0x01 short self-test
|
||||
0x02 extended self-test
|
||||
0x03 conveyance self-test
|
||||
0x04 selective self-test
|
||||
0x7f abort off-line mode self-test routine
|
||||
0x81 short self-test in captive mode
|
||||
0x82 extended "
|
||||
0x83 conveyance "
|
||||
0x85 selective "
|
466
sys/src/cmd/atazz/tabs.h
Normal file
466
sys/src/cmd/atazz/tabs.h
Normal file
|
@ -0,0 +1,466 @@
|
|||
Txtab regtx[] = {
|
||||
Ftype, "type", 0,
|
||||
Fflags, "flags", 0,
|
||||
Fcmd, "cmd", 0,
|
||||
Ffeat, "feat", 0,
|
||||
Flba0, "lba0", 0,
|
||||
Flba8, "lba8", 0,
|
||||
Flba16, "lba16", 0,
|
||||
Fdev, "dev", 0,
|
||||
Flba24, "lba24", 0,
|
||||
Flba32, "lba32", 0,
|
||||
Flba40, "lba40", 0,
|
||||
Ffeat8, "feat8", 0,
|
||||
Fsc, "sc", 0,
|
||||
Fsc8, "sc8", 0,
|
||||
Ficc, "icc", 0,
|
||||
Fcontrol,"control", 0,
|
||||
|
||||
/* aliases */
|
||||
Ffeat, "features", 0,
|
||||
Flba0, "sector", 0,
|
||||
Flba8, "cyl0", 0,
|
||||
Flba8, "byte0", 0,
|
||||
Flba16, "cyl8", 0,
|
||||
Flba24, "dh", 0,
|
||||
Flba24, "byte8", 0,
|
||||
Flba32, "cyl24", 0,
|
||||
Flba40, "cyl32", 0,
|
||||
};
|
||||
|
||||
Txtab smautosave[] = {
|
||||
0, "disable", 0,
|
||||
0xf1, "enable", 0,
|
||||
};
|
||||
|
||||
Fetab _b0d2[] = {
|
||||
Fsc, smautosave, nelem(smautosave),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab smlba8[] = {
|
||||
0x4f, "", 0,
|
||||
};
|
||||
Txtab smlba16[] = {
|
||||
0xc2, "", 0,
|
||||
};
|
||||
|
||||
Txtab smartfeat[] = {
|
||||
// 0xd0, "read data", 0,
|
||||
0xd2, "attribute autosave", _b0d2,
|
||||
0xd2, "aa", 0,
|
||||
0xd4, "execute off-line immediate", 0,
|
||||
// 0xd5, "read log", 0,
|
||||
// 0xd6, "write log", 0,
|
||||
0xd8, "enable operations", 0,
|
||||
0xd9, "disable operations", 0,
|
||||
0xda, "return status", 0,
|
||||
};
|
||||
|
||||
Fetab _b0[] = {
|
||||
Ffeat, smartfeat, nelem(smartfeat),
|
||||
Flba8, smlba8, 1,
|
||||
Flba16, smlba16, 1,
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab _b0d0feat[] = {
|
||||
0xd0, "", 0,
|
||||
};
|
||||
|
||||
Fetab _b0d0[] = {
|
||||
Ffeat, _b0d0feat, nelem(_b0d0feat),
|
||||
Flba8, smlba8, 1,
|
||||
Flba16, smlba16, 1,
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
|
||||
Txtab _b0d5feat[] = {
|
||||
0xd5, "", 0,
|
||||
};
|
||||
|
||||
Txtab _b0d5count[] = {
|
||||
0x01, "", 0,
|
||||
};
|
||||
|
||||
Txtab smpage[] = {
|
||||
0x00, "page 0", 0,
|
||||
0x01, "page 1", 0,
|
||||
0x02, "page 2", 0,
|
||||
0x03, "page 3", 0,
|
||||
0x04, "page 4", 0,
|
||||
0x05, "page 5", 0,
|
||||
0x06, "page 6", 0,
|
||||
0x07, "page 7", 0,
|
||||
0x08, "page 8", 0,
|
||||
0x09, "page 9", 0,
|
||||
0x11, "page 17", 0,
|
||||
0xe0, "sctstat", 0,
|
||||
0xe1, "sctdata", 0,
|
||||
};
|
||||
|
||||
Fetab _b0d5[] = {
|
||||
Ffeat, _b0d5feat, nelem(_b0d5feat),
|
||||
// Fsc, _b0d5count, nelem(_b0d5count),
|
||||
Flba0, smpage, nelem(smpage),
|
||||
Flba8, smlba8, 1,
|
||||
Flba16, smlba16, 1,
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Fetab _2f[] = {
|
||||
Flba0, smpage, nelem(smpage),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab nvfeat[] = {
|
||||
0x00, "set power mode", 0,
|
||||
0x01, "return from power mode", 0,
|
||||
0x10, "add lbas", 0,
|
||||
0x11, "remove lbas", 0,
|
||||
0x13, "query pinned set", 0,
|
||||
0x13, "query misses", 0,
|
||||
0x14, "flush", 0,
|
||||
0x15, "disable", 0,
|
||||
0x16, "disable", 0,
|
||||
};
|
||||
|
||||
Fetab _b6[] = {
|
||||
Ffeat, nvfeat, nelem(nvfeat),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab umodes[] = {
|
||||
0x40, "0", 0,
|
||||
0x41, "1", 0,
|
||||
0x42, "2", 0,
|
||||
0x43, "3", 0,
|
||||
0x44, "4", 0,
|
||||
0x45, "5", 0,
|
||||
0x46, "6", 0,
|
||||
};
|
||||
|
||||
Fetab _ef0340[] = {
|
||||
Fsc, umodes, nelem(umodes),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab txmode[] = {
|
||||
0x00, "pio", 0,
|
||||
0x01, "pio-iordy", 0,
|
||||
0x08, "piofc", 0,
|
||||
0x20, "mwdma", 0,
|
||||
0x40, "udma", _ef0340,
|
||||
};
|
||||
|
||||
Fetab _ef03[] = {
|
||||
Fsc, txmode, nelem(txmode),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab apmmode[] = {
|
||||
0xfe, "maximum", 0,
|
||||
0x80, "minimum without standby", 0,
|
||||
0x02, "intermediate", 0,
|
||||
0x01, "standby", 0,
|
||||
};
|
||||
|
||||
Fetab _ef05[] = {
|
||||
Fsc, apmmode, nelem(apmmode),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab scisone[] = {
|
||||
1, "", 0,
|
||||
};
|
||||
|
||||
Fetab _scis1[] = {
|
||||
Fsc, scisone, nelem(scisone),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab feat[] = {
|
||||
0x01, "enable 8-bit pio", 0,
|
||||
0x02, "enable write cache", 0,
|
||||
0x03, "set transfer mode", _ef03,
|
||||
0x05, "enable apm", _ef05,
|
||||
0x06, "enable power-up in standby", 0,
|
||||
0x07, "power-up in standby device spin-up", 0,
|
||||
0x10, "enable sata features", 0,
|
||||
0x0a, "enable cfa power mode 1", 0,
|
||||
0x31, "disable media status notification", 0,
|
||||
0x42, "enable aam", 0,
|
||||
0x43, "set maximum host interface sector times", 0,
|
||||
0x55, "disable read look-ahead", 0,
|
||||
0x5d, "enable release interrupt", 0,
|
||||
0x5e, "enable service interrupt", 0,
|
||||
0x66, "disable reverting to power-on defaults", 0,
|
||||
0x81, "disable 8-bit pio", 0,
|
||||
0x82, "disable write cache", 0,
|
||||
0x85, "disable apm", 0,
|
||||
0x86, "disable power-up in standby", 0,
|
||||
0x8a, "disable cfa power mode 1", 0,
|
||||
0x10, "disable sata features", 0,
|
||||
0x95, "enable media status notification", 0,
|
||||
0xaa, "enable read look-ahead", 0,
|
||||
0xc1, "disable free-fall control", 0,
|
||||
0xc2, "disable aam", 0,
|
||||
0xc3, "sense data", 0, /* incomplete; enable/disable */
|
||||
0xcc, "enable reverting to power-on defaults", 0,
|
||||
0xdd, "disable release interrupt", 0,
|
||||
0xde, "disable service interrupt", 0,
|
||||
};
|
||||
|
||||
Fetab _ef[] = {
|
||||
Ffeat, feat, nelem(feat),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
/* 0xffff — sct command executing in background */
|
||||
char *sctetab[] = {
|
||||
"Command complete without error",
|
||||
"Invalid Function Code",
|
||||
"Input LBA out of range"
|
||||
"Request 512-byte data block count overflow.", /* sic */
|
||||
"Invalid Function code in Error Recovery command",
|
||||
"Invalid Selection code in Error Recovery command",
|
||||
"Host read command timer is less than minimum value",
|
||||
"Host write command timer is less than minimum value",
|
||||
"Background SCT command was aborted because of an interrupting host command",
|
||||
"Background SCT command was terminated because of unrecoverable error",
|
||||
"Invalid Function code in SCT Read/Write Long command",
|
||||
"SCT data transfer command was issued without first issuing an SCT command",
|
||||
"Invalid Function code in SCT Feature Control command",
|
||||
"Invalid Feature code in SCT Feature Control command",
|
||||
"Invalid New State value in SCT Feature Control command",
|
||||
"Invalid Option Flags value in SCT Feature Control command",
|
||||
"Invalid SCT Action code",
|
||||
"Invalid Table ID (table not supported)",
|
||||
"Command wa saborted due to device security being locked",
|
||||
"Invalid revision code in SCT data",
|
||||
"Foreground SCT operation was terminated because of unrecoverable error",
|
||||
"Error Recovery Timer expired", /* sic */
|
||||
};
|
||||
|
||||
Txtab fcfewcrt[] = {
|
||||
1, "enable", 0,
|
||||
2, "disable", 0,
|
||||
};
|
||||
|
||||
Fetab fcfewcr[] = {
|
||||
Sstate, fcfewcrt, nelem(fcfewcrt),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab fcfewct[] = {
|
||||
1, "set features", 0,
|
||||
2, "enable", 0,
|
||||
3, "disable", 0,
|
||||
};
|
||||
|
||||
Fetab fcfewc[] = {
|
||||
Sstate, fcfewct, nelem(fcfewct),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab fcfn[] = {
|
||||
1, "set state", 0,
|
||||
2, "return state", 0,
|
||||
3, "return feature option flags", 0,
|
||||
};
|
||||
|
||||
Txtab fcfe[] = {
|
||||
2, "write cache reordering", fcfewcr,
|
||||
1, "write cache", fcfewc,
|
||||
3, "temperature logging interval", 0,
|
||||
};
|
||||
|
||||
Txtab fcoptf[] = {
|
||||
1, "preserve", 0,
|
||||
};
|
||||
|
||||
Txtab fcproto[] = {
|
||||
Pnd, "", 0,
|
||||
};
|
||||
|
||||
Fetab sctfc[] = {
|
||||
Sfn, fcfn, nelem(fcfn),
|
||||
Sfe, fcfe, nelem(fcfe),
|
||||
Soptf, fcoptf, nelem(fcoptf),
|
||||
Pbase, fcproto, nelem(fcproto),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab sctdt[] = {
|
||||
Stabid, "tableid", 0,
|
||||
};
|
||||
|
||||
Txtab tabnam[] = {
|
||||
2, "hda temperature history", 0,
|
||||
};
|
||||
|
||||
Txtab tablefc[] = {
|
||||
1, "", 0,
|
||||
};
|
||||
|
||||
Fetab tables[] = {
|
||||
Sfn, tablefc, nelem(tablefc),
|
||||
Stabid, tabnam, nelem(tabnam),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab ersc[] = {
|
||||
1, "read timer", 0,
|
||||
2, "write timer", 0,
|
||||
};
|
||||
|
||||
Txtab erfc[] = {
|
||||
1, "set", 0,
|
||||
2, "return", 0,
|
||||
};
|
||||
|
||||
Txtab erti[] = {
|
||||
-1, "=", 0,
|
||||
};
|
||||
|
||||
Fetab scter[] = {
|
||||
Sfn, erfc, nelem(erfc),
|
||||
Ssc, ersc, nelem(ersc),
|
||||
Stimer, erti, nelem(erti),
|
||||
Pbase, fcproto, nelem(fcproto),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Fetab patfe[] = {
|
||||
Pbase, fcproto, nelem(fcproto),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab wsfc[] = {
|
||||
1, "repeat write pattern", patfe,
|
||||
2, "repeat write data block", 0,
|
||||
0x101, "repeat write pattern foreground", patfe,
|
||||
0x102, "repeat write data block foreground", 0,
|
||||
};
|
||||
|
||||
Txtab wslba[] = {
|
||||
-1, "lba", 0,
|
||||
};
|
||||
|
||||
Txtab wscnt[] = {
|
||||
-1, "count", 0,
|
||||
};
|
||||
|
||||
Txtab wspat[] = {
|
||||
-1, "pattern", 0,
|
||||
};
|
||||
|
||||
Fetab wsame[] = {
|
||||
Sfn, wsfc, nelem(wsfc),
|
||||
Slba, wslba, nelem(wslba),
|
||||
Scnt, wscnt, nelem(wscnt),
|
||||
Spat, wspat, nelem(wspat),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Txtab action[] = {
|
||||
5, "read data table", tables,
|
||||
4, "feature control", sctfc,
|
||||
3, "error recovery time", scter,
|
||||
2, "write same", wsame,
|
||||
};
|
||||
|
||||
Fetab scta[] = {
|
||||
Saction, action, nelem(action),
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
Atatab atatab[] = {
|
||||
0x00, 0, 0, Pnd|P28, 0, 0, "nop",
|
||||
0x03, 0, Cmdn, Pnd|P28, 0, 0, "cfa request extended error",
|
||||
0x08, Cmdn, 0, Preset|P28, 0, 0, "device reset",
|
||||
0x0b, 0, Cmdp, Pnd|P48, 0, 0, "request sense data ext",
|
||||
0x20, 0, 0, Pin|Ppio|P28, 0, iofmt, "read sector",
|
||||
0x24, 0, Cmdn, Pin|Ppio|P48, 0, iofmt, "read sector ext",
|
||||
0x25, 0, Cmdn, Pin|Pdma|P48, 0, iofmt, "read dma ext",
|
||||
0x26, 0, Cmdn, Pin|Pdmq|P48, 0, iofmt, "read dma queued ext",
|
||||
0x27, 0, Cmdn, Pnd|P48, 0, 0, "read native max address ext",
|
||||
0x29, 0, Cmdn, Pin|Ppio|P48, 0, iofmt, "read multiple ext",
|
||||
0x2a, 0, Cmdn, Pin|Pdma|P48, 0, iofmt, "read stream dma ext",
|
||||
0x2b, 0, Cmdn, Pin|Ppio|P48, 0, iofmt, "read stream ext",
|
||||
0x2f, Cmd5sc, 0, Pin|Ppio|P48|P512, _2f, glfmt, "read log ext",
|
||||
0x2f, Cmd5sc, 0, Psct|Pin|Ppio|P48|P512, scta, 0, "sct",
|
||||
0x30, 0, Cmdn, Pout|Ppio|P28, 0, 0, "write sector",
|
||||
0x34, 0, Cmdn, Pout|Ppio|P48, 0, 0, "write sector ext",
|
||||
0x35, 0, Cmdn, Pout|Pdma|P48, 0, 0, "write dma ext",
|
||||
0x36, 0, Cmdn, Pout|Pdmq|P48, 0, 0, "write dma queued ext",
|
||||
0x37, 0, Cmdn, Pnd|P48, 0, 0, "set max address ext",
|
||||
0x38, 0, Cmdn, Pout|Ppio|P28, 0, 0, "cfa write sectors without erase",
|
||||
0x39, 0, Cmdn, Pout|Ppio|P48, 0, 0, "write multiple ext",
|
||||
0x3a, 0, Cmdn, Pout|Pdma|P48, 0, 0, "write stream dma ext",
|
||||
0x3b, 0, Cmdn, Pout|Ppio|P48, 0, 0, "write stream ext",
|
||||
0x3d, 0, Cmdn, Pout|Pdma|P48, 0, 0, "write dma fua ext",
|
||||
0x3e, 0, Cmdn, Pout|Pdmq|P48, 0, 0, "write dma queued fua ext",
|
||||
0x3f, 0, 0, Pout|Ppio|P48, 0, 0, "write log ext",
|
||||
0x40, 0, Cmdn, Pnd|P28, 0, 0, "read verify sector",
|
||||
0x42, 0, Cmdn, Pnd|P48, 0, 0, "read verify sector ext",
|
||||
0x45, 0, Cmdn, Pnd|P48, 0, 0, "write uncorrectable ext",
|
||||
0x47, Cmd5sc, 0, Pin|Pdma|P48|P512, _2f, glfmt, "read log dma ext",
|
||||
0x51, 0, 0, Pnd|P48, 0, 0, "configure stream",
|
||||
0x57, 0, 0, Pout|Pdma|P48, 0, 0, "write log dma ext",
|
||||
0x5b, 0, Cmdp, Pnd|P28, 0, 0, "trusted non-data",
|
||||
0x5c, 0, Cmdp, Pin|Ppio|P28, 0, iofmt, "trusted receive",
|
||||
0x5d, 0, Cmdp, Pin|Pdma|P28, 0, iofmt, "trusted receive dma",
|
||||
0x5e, 0, Cmdp, Pout|Ppio|P28, 0, 0, "trusted send",
|
||||
0x5f, 0, Cmdp, Pout|Pdma|P28, 0, 0, "trusted send dma",
|
||||
0x60, 0, Cmdn, Pin|Pdmq|P48, 0, iofmt, "read fpdma queued",
|
||||
0x61, 0, Cmdn, Pout|Pdmq|P48, 0, 0, "write fpdma queued",
|
||||
0x87, 0, Cmdn, Pin|Ppio|P28, 0, iofmt, "cfa translate sector",
|
||||
0x90, 0, 0, Pdiag|P28, 0, 0, "execute device diagnostic",
|
||||
0x92, 0, Cmdn, Pout|Ppio|P28, 0, 0, "download microcode",
|
||||
0x93, 0, Cmdn, Pout|Pdma|P28, 0, 0, "download microcode dma",
|
||||
0xa0, Cmdn, 0, Ppkt, 0, 0, "packet",
|
||||
0xa1, Cmdn, 0, Pin|Ppio|P28|P512, _scis1, idfmt, "identify packet device",
|
||||
0xb0, Cmd5sc, Cmdn, Pin|Ppio|P28|P512, _b0d0, sdfmt, "smart read data",
|
||||
0xb0, Cmd5sc, Cmdn, Pin|Ppio|P28|P512, _b0d5, slfmt, "smart read log",
|
||||
0xb0, 0, Cmdn, Pnd|P28, _b0, smfmt, "smart",
|
||||
0xb1, 0, 0, Pnd|P28, 0, 0, "device configuration overlay",
|
||||
0xb6, 0, Cmdn, Pnd|P48, 0, 0, "nv cache",
|
||||
0xc0, Cmdf, Cmdn, Pnd|P28, 0, 0, "cfa erase sectors",
|
||||
0xc4, 0, Cmdn, Pin|Ppio|P28, 0, iofmt, "read multiple",
|
||||
0xc5, 0, Cmdn, Pout|Ppio|P28, 0, 0, "write multiple",
|
||||
0xc6, 0, Cmdn, Pnd|P28, 0, 0, "set multiple mode",
|
||||
0xc7, 0, Cmdn, Pin|Pdmq|P28, 0, iofmt, "read dma queued",
|
||||
0xc8, 0, Cmdn, Pin|Pdma|P28, 0, iofmt, "read dma",
|
||||
0xca, 0, Cmdn, Pout|Pdma|P28, 0, 0, "write dma",
|
||||
0xcc, 0, Cmdn, Pout|Pdmq|P28, 0, 0, "write dma queued",
|
||||
0xcd, 0, Cmdn, Pout|Ppio|P28, 0, 0, "cfa write multiple without erase",
|
||||
0xce, 0, Cmdn, Pout|Ppio|P48, 0, 0, "write multiple fua ext",
|
||||
0xd1, 0, Cmdn, Pnd|P28, 0, 0, "check media card type",
|
||||
0xda, 0, Cmdn, Pnd|P28, 0, 0, "get media status",
|
||||
0xe0, 0, 0, Pnd|P28, 0, 0, "standby immediate",
|
||||
0xe1, 0, 0, Pnd|P28, 0, 0, "idle immediate",
|
||||
0xe2, 0, 0, Pnd|P28, 0, 0, "standby",
|
||||
0xe3, 0, 0, Pnd|P28, 0, 0, "idle",
|
||||
0xe4, 0, Cmdn, Pin|Ppio|P28, 0, iofmt, "read buffer",
|
||||
0xe5, 0, 0, Pnd|P28, 0, 0, "check power mode",
|
||||
0xe6, 0, 0, Pnd|P28, 0, 0, "sleep",
|
||||
0xe7, 0, 0, Pnd|P28, 0, 0, "flush cache",
|
||||
0xe8, 0, Cmdn, Pout|Ppio|P28, 0, 0, "write buffer",
|
||||
0xe9, 0, Cmdn, Pin|Pdma|P28, 0, iofmt, "read buffer dma",
|
||||
0xea, 0, Cmdn, Pnd|P28, 0, 0, "flush cache ext",
|
||||
0xeb, 0, Cmdn, Pdma|P28, 0, 0, "write buffer dma",
|
||||
0xec, 0, 0, Pin|Ppio|P28|P512, _scis1, idfmt, "identify device",
|
||||
0xef, 0, 0, Pnd|P28, _ef, 0, "set features",
|
||||
0xf1, 0, 0, Pout|Ppio|P28, 0, 0, "security set password",
|
||||
0xf2, 0, 0, Pout|Ppio|P28, 0, 0, "security unlock",
|
||||
0xf3, 0, 0, Pnd|P28, 0, 0, "security erase prepare",
|
||||
0xf4, 0, 0, Pout|Ppio|P28, 0, 0, "security erase unit",
|
||||
0xf5, 0, 0, Pnd|P28, 0, 0, "security freeze lock",
|
||||
0xf6, 0, 0, Pout|Ppio|P28, 0, 0, "security disable password",
|
||||
0xf8, 0, 0, Pnd|P28, 0, 0, "read native max address",
|
||||
0xf9, 0, 0, Pnd|P28, 0, 0, "set max address",
|
||||
0xf000, 0, 0, Pnd|P28, 0, sigfmt, "signature",
|
||||
0xf100, 0, 0, Pnd|P28, 0, 0, "oobreset",
|
||||
};
|
Loading…
Reference in a new issue