diff options
author | google <google@daverabbitz.ath.cx> | 2012-09-20 22:39:48 +1200 |
---|---|---|
committer | google <google@daverabbitz.ath.cx> | 2012-09-20 22:39:48 +1200 |
commit | fa7fb8b66b9ff50029532d09315f03896f2ac4c4 (patch) | |
tree | 262cfe8966f3c07a5ad6ed61fda028f6fa928a36 /sys | |
parent | 913afc39c9b4750e630c7f4ff3161a37602b006b (diff) |
Add Erik Quanstrom's atazz
(needed to disable power management/head unload on 2.5" drive)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/src/cmd/atazz/atazz.h | 131 | ||||
-rw-r--r-- | sys/src/cmd/atazz/atazz.ms | 573 | ||||
-rw-r--r-- | sys/src/cmd/atazz/atazz.ps | 3414 | ||||
-rw-r--r-- | sys/src/cmd/atazz/bit.c | 71 | ||||
-rw-r--r-- | sys/src/cmd/atazz/macros.ms | 92 | ||||
-rw-r--r-- | sys/src/cmd/atazz/main.c | 1928 | ||||
-rw-r--r-- | sys/src/cmd/atazz/mkfile | 23 | ||||
-rw-r--r-- | sys/src/cmd/atazz/probe.c | 75 | ||||
-rw-r--r-- | sys/src/cmd/atazz/sctnotes | 25 | ||||
-rw-r--r-- | sys/src/cmd/atazz/smartnotes | 22 | ||||
-rw-r--r-- | sys/src/cmd/atazz/tabs.h | 466 |
11 files changed, 6820 insertions, 0 deletions
diff --git a/sys/src/cmd/atazz/atazz.h b/sys/src/cmd/atazz/atazz.h new file mode 100644 index 000000000..16c21f1f5 --- /dev/null +++ b/sys/src/cmd/atazz/atazz.h @@ -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** diff --git a/sys/src/cmd/atazz/atazz.ms b/sys/src/cmd/atazz/atazz.ms new file mode 100644 index 000000000..7048327c5 --- /dev/null +++ b/sys/src/cmd/atazz/atazz.ms @@ -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" . diff --git a/sys/src/cmd/atazz/atazz.ps b/sys/src/cmd/atazz/atazz.ps new file mode 100644 index 000000000..e20824c82 --- /dev/null +++ b/sys/src/cmd/atazz/atazz.ps @@ -0,0 +1,3414 @@ +%!PS-Adobe-2.0 +%%Version: 0.1 +%%Creator: troff, Plan 9 edition +%%DocumentFonts: (atend) +%%Pages: (atend) +%%EndComments +% +% Version 3.3.2 prologue for troff files. +% + +/#copies 1 store +/aspectratio 1 def +/formsperpage 1 def +/landscape false def +/linewidth .3 def +/magnification 1 def +/margin 0 def +/orientation 0 def +/resolution 720 def +/rotation 1 def +/xoffset 0 def +/yoffset 0 def + +/roundpage true def +/useclippath true def +/pagebbox [0 0 612 792] def + +/R /Times-Roman def +/I /Times-Italic def +/B /Times-Bold def +/BI /Times-BoldItalic def +/H /Helvetica def +/HI /Helvetica-Oblique def +/HB /Helvetica-Bold def +/HX /Helvetica-BoldOblique def +/CW /Courier def +/CO /Courier def +/CI /Courier-Oblique def +/CB /Courier-Bold def +/CX /Courier-BoldOblique def +/PA /Palatino-Roman def +/PI /Palatino-Italic def +/PB /Palatino-Bold def +/PX /Palatino-BoldItalic def +/Hr /Helvetica-Narrow def +/Hi /Helvetica-Narrow-Oblique def +/Hb /Helvetica-Narrow-Bold def +/Hx /Helvetica-Narrow-BoldOblique def +/KR /Bookman-Light def +/KI /Bookman-LightItalic def +/KB /Bookman-Demi def +/KX /Bookman-DemiItalic def +/AR /AvantGarde-Book def +/AI /AvantGarde-BookOblique def +/AB /AvantGarde-Demi def +/AX /AvantGarde-DemiOblique def +/NR /NewCenturySchlbk-Roman def +/NI /NewCenturySchlbk-Italic def +/NB /NewCenturySchlbk-Bold def +/NX /NewCenturySchlbk-BoldItalic def +/ZD /ZapfDingbats def +/ZI /ZapfChancery-MediumItalic def +/S /S def +/S1 /S1 def +/GR /Symbol def + +/inch {72 mul} bind def +/min {2 copy gt {exch} if pop} bind def + +/setup { + counttomark 2 idiv {def} repeat pop + + landscape {/orientation 90 orientation add def} if + /scaling 72 resolution div def + linewidth setlinewidth + 1 setlinecap + + pagedimensions + xcenter ycenter translate + orientation rotation mul rotate + width 2 div neg height 2 div translate + xoffset inch yoffset inch neg translate + margin 2 div dup neg translate + magnification dup aspectratio mul scale + scaling scaling scale + + addmetrics + 0 0 moveto +} def + +/pagedimensions { + useclippath userdict /gotpagebbox known not and { + /pagebbox [clippath pathbbox newpath] def + roundpage currentdict /roundpagebbox known and {roundpagebbox} if + } if + pagebbox aload pop + 4 -1 roll exch 4 1 roll 4 copy + landscape {4 2 roll} if + sub /width exch def + sub /height exch def + add 2 div /xcenter exch def + add 2 div /ycenter exch def + userdict /gotpagebbox true put +} def + +/addmetrics { + /Symbol /S null Sdefs cf + /Times-Roman /S1 StandardEncoding dup length array copy S1defs cf +} def + +/pagesetup { + /page exch def + currentdict /pagedict known currentdict page known and { + page load pagedict exch get cvx exec + } if +} def + +/decodingdefs [ + {counttomark 2 idiv {y moveto show} repeat} + {neg /y exch def counttomark 2 idiv {y moveto show} repeat} + {neg moveto {2 index stringwidth pop sub exch div 0 32 4 -1 roll widthshow} repeat} + {neg moveto {spacewidth sub 0.0 32 4 -1 roll widthshow} repeat} + {counttomark 2 idiv {y moveto show} repeat} + {neg setfunnytext} +] def + +/setdecoding {/t decodingdefs 3 -1 roll get bind def} bind def + +/w {neg moveto show} bind def +/m {neg dup /y exch def moveto} bind def +/done {/lastpage where {pop lastpage} if} def + +/f { + dup /font exch def findfont exch + dup /ptsize exch def scaling div dup /size exch def scalefont setfont + linewidth ptsize mul scaling 10 mul div setlinewidth + /spacewidth ( ) stringwidth pop def +} bind def + +/changefont { + /fontheight exch def + /fontslant exch def + currentfont [ + 1 0 + fontheight ptsize div fontslant sin mul fontslant cos div + fontheight ptsize div + 0 0 + ] makefont setfont +} bind def + +/sf {f} bind def + +/cf { + dup length 2 idiv + /entries exch def + /chtab exch def + /newencoding exch def + /newfont exch def + + findfont dup length 1 add dict + /newdict exch def + {1 index /FID ne {newdict 3 1 roll put}{pop pop} ifelse} forall + + newencoding type /arraytype eq {newdict /Encoding newencoding put} if + + newdict /Metrics entries dict put + newdict /Metrics get + begin + chtab aload pop + 1 1 entries {pop def} for + newfont newdict definefont pop + end +} bind def + +% +% A few arrays used to adjust reference points and character widths in some +% of the printer resident fonts. If square roots are too high try changing +% the lines describing /radical and /radicalex to, +% +% /radical [0 -75 550 0] +% /radicalex [-50 -75 500 0] +% +% Move braceleftbt a bit - default PostScript character is off a bit. +% + +/Sdefs [ + /bracketlefttp [201 500] + /bracketleftbt [201 500] + /bracketrighttp [-81 380] + /bracketrightbt [-83 380] + /braceleftbt [203 490] + /bracketrightex [220 -125 500 0] + /radical [0 0 550 0] + /radicalex [-50 0 500 0] + /parenleftex [-20 -170 0 0] + /integral [100 -50 500 0] + /infinity [10 -75 730 0] +] def + +/S1defs [ + /underscore [0 80 500 0] + /endash [7 90 650 0] +] def +% +% Version 3.3.2 drawing procedures for dpost. Automatically pulled in when +% needed. +% + +/inpath false def +/savematrix matrix def + +/Dl { + inpath + {neg lineto pop pop} + {newpath neg moveto neg lineto stroke} + ifelse +} bind def + +/De { + /y1 exch 2 div def + /x1 exch 2 div def + /savematrix savematrix currentmatrix def + neg exch x1 add exch translate + x1 y1 scale + 0 0 1 0 360 + inpath + {1 0 moveto arc savematrix setmatrix} + {newpath arc savematrix setmatrix stroke} + ifelse +} bind def + +/Da { + /dy2 exch def + /dx2 exch def + /dy1 exch def + /dx1 exch def + dy1 add neg exch dx1 add exch + dx1 dx1 mul dy1 dy1 mul add sqrt + dy1 dx1 neg atan + dy2 neg dx2 atan + inpath + {arc} + {newpath arc stroke} + ifelse +} bind def + +/DA { + /dy2 exch def + /dx2 exch def + /dy1 exch def + /dx1 exch def + dy1 add neg exch dx1 add exch + dx1 dx1 mul dy1 dy1 mul add sqrt + dy1 dx1 neg atan + dy2 neg dx2 atan + inpath + {arcn} + {newpath arcn stroke} + ifelse +} bind def + +/Ds { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + /y0 exch def + /x0 exch def + x0 5 x1 mul add 6 div + y0 5 y1 mul add -6 div + x2 5 x1 mul add 6 div + y2 5 y1 mul add -6 div + x1 x2 add 2 div + y1 y2 add -2 div + inpath + {curveto} + {newpath x0 x1 add 2 div y0 y1 add -2 div moveto curveto stroke} + ifelse +} bind def +% +% Tries to round clipping path dimensions, as stored in array pagebbox, so they +% match one of the known sizes in the papersizes array. Lower left coordinates +% are always set to 0. +% + +/roundpagebbox { + 7 dict begin + /papersizes [8.5 inch 11 inch 14 inch 17 inch] def + + /mappapersize { + /val exch def + /slop .5 inch def + /diff slop def + /j 0 def + 0 1 papersizes length 1 sub { + /i exch def + papersizes i get val sub abs + dup diff le {/diff exch def /j i def} {pop} ifelse + } for + diff slop lt {papersizes j get} {val} ifelse + } def + + pagebbox 0 0 put + pagebbox 1 0 put + pagebbox dup 2 get mappapersize 2 exch put + pagebbox dup 3 get mappapersize 3 exch put + end +} bind def + +%%EndProlog +%%BeginSetup +mark +/magnification .9 def +% +% Encoding vector and redefinition of findfont for the ISO Latin1 standard. +% The 18 characters missing from ROM based fonts on older printers are noted +% below. +% + +/ISOLatin1Encoding [ + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /space + /exclam + /quotedbl + /numbersign + /dollar + /percent + /ampersand + /quoteright + /parenleft + /parenright + /asterisk + /plus + /comma + /minus + /period + /slash + /zero + /one + /two + /three + /four + /five + /six + /seven + /eight + /nine + /colon + /semicolon + /less + /equal + /greater + /question + /at + /A + /B + /C + /D + /E + /F + /G + /H + /I + /J + /K + /L + /M + /N + /O + /P + /Q + /R + /S + /T + /U + /V + /W + /X + /Y + /Z + /bracketleft + /backslash + /bracketright + /asciicircum + /underscore + /quoteleft + /a + /b + /c + /d + /e + /f + /g + /h + /i + /j + /k + /l + /m + /n + /o + /p + /q + /r + /s + /t + /u + /v + /w + /x + /y + /z + /braceleft + /bar + /braceright + /asciitilde + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /.notdef + /dotlessi + /grave + /acute + /circumflex + /tilde + /macron + /breve + /dotaccent + /dieresis + /.notdef + /ring + /cedilla + /.notdef + /hungarumlaut + /ogonek + /caron + /space + /exclamdown + /cent + /sterling + /currency + /yen + /brokenbar % missing + /section + /dieresis + /copyright + /ordfeminine + /guillemotleft + /logicalnot + /hyphen + /registered + /macron + /degree % missing + /plusminus % missing + /twosuperior % missing + /threesuperior % missing + /acute + /mu % missing + /paragraph + /periodcentered + /cedilla + /onesuperior % missing + /ordmasculine + /guillemotright + /onequarter % missing + /onehalf % missing + /threequarters % missing + /questiondown + /Agrave + /Aacute + /Acircumflex + /Atilde + /Adieresis + /Aring + /AE + /Ccedilla + /Egrave + /Eacute + /Ecircumflex + /Edieresis + /Igrave + /Iacute + /Icircumflex + /Idieresis + /Eth % missing + /Ntilde + /Ograve + /Oacute + /Ocircumflex + /Otilde + /Odieresis + /multiply % missing + /Oslash + /Ugrave + /Uacute + /Ucircumflex + /Udieresis + /Yacute % missing + /Thorn % missing + /germandbls + /agrave + /aacute + /acircumflex + /atilde + /adieresis + /aring + /ae + /ccedilla + /egrave + /eacute + /ecircumflex + /edieresis + /igrave + /iacute + /icircumflex + /idieresis + /eth % missing + /ntilde + /ograve + /oacute + /ocircumflex + /otilde + /odieresis + /divide % missing + /oslash + /ugrave + /uacute + /ucircumflex + /udieresis + /yacute % missing + /thorn % missing + /ydieresis +] def + +/NewFontDirectory FontDirectory maxlength dict def + +% +% Apparently no guarantee findfont is defined in systemdict so the obvious +% +% systemdict /findfont get exec +% +% can generate an error. So far the only exception is a VT600 (version 48.0). +% + +userdict /@RealFindfont known not { + userdict begin + /@RealFindfont systemdict begin /findfont load end def + end +} if + +/findfont { + dup NewFontDirectory exch known not { + dup + %dup systemdict /findfont get exec % not always in systemdict + dup userdict /@RealFindfont get exec + dup /Encoding get StandardEncoding eq { + dup length dict begin + {1 index /FID ne {def}{pop pop} ifelse} forall + /Encoding ISOLatin1Encoding def + currentdict + end + /DummyFontName exch definefont + } if + NewFontDirectory 3 1 roll put + } if + NewFontDirectory exch get +} bind def + +%%Patch from lp +%%EndPatch from lp + +setup +%%EndSetup +%%Page: 1 1 +/saveobj save def +mark +1 pagesetup +13 /LucidaSans-Demi f +(ATA) 2584 1230 w +(au) 2908 1230 w +(Naturel) 3113 1230 w +11 /LucidaSans-Italic f +(Erik) 2672 1490 w +(Quanstrom) 2917 1490 w +(quanstro@quanstro.net) 2465 1620 w +(ABSTRACT) 2817 2095 w +11 /LucidaSansUnicode00 f +(The) 1116 2375 w +(Plan) 1351 2375 w +(9) 1609 2375 w +11 /LucidaSans-Italic f +(sd) 1714 2375 w +11 /LucidaSansUnicode00 f +(\(3\)) 1835 2375 w +(interface) 2012 2375 w +(allows) 2516 2375 w +(raw) 2885 2375 w +(commands) 3112 2375 w +(to) 3729 2375 w +(be) 3873 2375 w +(sent.) 4041 2375 w +(Traditionally,) 4375 2375 w +(only) 1116 2505 w +(SCSI) 1378 2505 w +(CDBs) 1642 2505 w +(could) 1959 2505 w +(be) 2289 2505 w +(sent) 2458 2505 w +(in) 2723 2505 w +(this) 2861 2505 w +(manner.) 3095 2505 w +(For) 3608 2505 w +(devices) 3816 2505 w +(that) 4247 2505 w +(respond) 4495 2505 w +(to) 4968 2505 w +(ATA/ATAPI) 1116 2635 w +(commands,) 1768 2635 w +(a) 2443 2635 w +(small) 2563 2635 w +(set) 2905 2635 w +(of) 3123 2635 w +(SCSI) 3290 2635 w +(CDBs) 3575 2635 w +(have) 3913 2635 w +(been) 4220 2635 w +(translated) 4540 2635 w +(into) 1116 2765 w +(an) 1371 2765 w +(ATA) 1547 2765 w +(equivalent.) 1815 2765 w +(This) 2484 2765 w +(approach) 2756 2765 w +(works) 3299 2765 w +(very) 3663 2765 w +(well.) 3931 2765 w +(However,) 4258 2765 w +(there) 4798 2765 w +(are) 1116 2895 w +(ATA) 1322 2895 w +(commands) 1581 2895 w +(such) 2200 2895 w +(as) 2486 2895 w +(SMART) 2641 2895 w +(which) 3047 2895 w +(do) 3394 2895 w +(not) 3568 2895 w +(have) 3782 2895 w +(direct) 4069 2895 w +(translations.) 4413 2895 w +(I) 1116 3025 w +(describe) 1190 3025 w +(how) 1683 3025 w +(ATA/ATAPI) 1945 3025 w +(commands) 2580 3025 w +(were) 3203 3025 w +(supported) 3498 3025 w +(without) 4085 3025 w +(disturbing) 4528 3025 w +(existing functionality.) 1116 3155 w +11 /LucidaSans-Demi f +(Introduction) 720 3545 w +11 /LucidaSansUnicode00 f +(In) 720 3715 w +(writing) 858 3715 w +(new) 1267 3715 w +11 /LucidaSans-Italic f +(sd) 1520 3715 w +11 /LucidaSansUnicode00 f +(\(3\)) 1641 3715 w +(drivers) 1821 3715 w +(for) 2226 3715 w +(plan) 2418 3715 w +(9,) 2687 3715 w +(it) 2830 3715 w +(has) 2942 3715 w +(been) 3166 3715 w +(necessary) 3466 3715 w +(to) 4028 3715 w +(copy) 4175 3715 w +(laundry) 4463 3715 w +(list) 4902 3715 w +(of) 5102 3715 w +(spe\255) 5249 3715 w +(cial) 720 3845 w +(commands) 937 3845 w +(that) 1554 3845 w +(were) 1800 3845 w +(needed with previous drivers.) 2089 3845 w +(The) 3739 3845 w +(set) 3973 3845 w +(of) 4167 3845 w +(commands supported) 4310 3845 w +(by) 720 3975 w +(each) 894 3975 w +(device) 1189 3975 w +(driver) 1575 3975 w +(varies,) 1933 3975 w +(and) 2329 3975 w +(they) 2575 3975 w +(are) 2851 3975 w +(typically) 3067 3975 w +(executed) 3553 3975 w +(by) 4089 3975 w +(writing) 4264 3975 w +(a) 4684 3975 w +(magic) 4794 3975 w +(string) 5162 3975 w +(into) 720 4105 w +(the) 968 4105 w +(driver) 1178 4105 w +11 /LucidaSansUnicode20 f +(\031) 1488 4105 w +11 /LucidaSansUnicode00 f +(s) 1523 4105 w +11 /LucidaTypewriter f +(ctl) 1618 4105 w +11 /LucidaSansUnicode00 f +(file.) 1894 4105 w +(This) 2170 4105 w +(requires) 2434 4105 w +(code) 2912 4105 w +(duplicated) 3205 4105 w +(for) 3803 4105 w +(each) 3995 4105 w +(driver,) 4281 4105 w +(and) 4665 4105 w +(covers) 4902 4105 w +(few) 5284 4105 w +(commands.) 720 4235 w +(Coverage) 1410 4235 w +(depends) 1947 4235 w +(on) 2441 4235 w +(the) 2615 4235 w +(driver.) 2825 4235 w +(It) 3244 4235 w +(is) 3357 4235 w +(not) 3485 4235 w +(possible) 3701 4235 w +(for) 4184 4235 w +(the) 4377 4235 w +(control) 4588 4235 w +(interface) 5004 4235 w +(to) 720 4365 w +(return) 895 4365 w +(output,) 1290 4365 w +(making) 1745 4365 w +(some) 2206 4365 w +(commands) 2559 4365 w +(impossible) 3206 4365 w +(to) 3849 4365 w +(implement.) 4023 4365 w +(While) 4729 4365 w +(a) 5084 4365 w +(work) 5211 4365 w +(around) 720 4495 w +(has) 1148 4495 w +(been) 1383 4495 w +(to) 1694 4495 w +(change) 1852 4495 w +(the) 2285 4495 w +(contents) 2506 4495 w +(of) 3015 4495 w +(the) 3173 4495 w +(control) 3394 4495 w +(file,) 3820 4495 w +(this) 4073 4495 w +(solution) 4321 4495 w +(is) 4803 4495 w +(extremely) 4942 4495 w +(unwieldy even for simple) 720 4625 w +(commands such as) 2088 4625 w +11 /LucidaTypewriter f +(IDENTIFY DEVICE) 3139 4625 w +11 /LucidaSansUnicode00 f +(.) 4324 4625 w +11 /LucidaSans-Demi f +(Considerations) 720 4885 w +11 /LucidaSansUnicode00 f +(Currently,) 720 5055 w +(all) 1294 5055 w +11 /LucidaSans-Italic f +(sd) 1464 5055 w +11 /LucidaSansUnicode00 f +(devices) 1630 5055 w +(respond) 2070 5055 w +(to) 2552 5055 w +(a) 2706 5055 w +(small) 2813 5055 w +(subset) 3142 5055 w +(of) 3540 5055 w +(SCSI) 3694 5055 w +(commands) 3966 5055 w +(through) 4593 5055 w +(the) 5064 5055 w +(raw) 5281 5055 w +(interface) 720 5185 w +(and) 1229 5185 w +(the) 1468 5185 w +(normal) 1680 5185 w +(read/write) 2096 5185 w +(interface) 2697 5185 w +(uses) 3206 5185 w +(SCSI) 3489 5185 w +(command) 3756 5185 w +(blocks.) 4322 5185 w +(SCSI) 4777 5185 w +(devices,) 5043 5185 w +(of) 720 5315 w +(course,) 877 5315 w +(respond) 1315 5315 w +(natively) 1800 5315 w +(while) 2259 5315 w +(ATA) 2587 5315 w +(devices) 2857 5315 w +(emulate) 3300 5315 w +(these) 3777 5315 w +(commands) 4115 5315 w +(with) 4745 5315 w +(the) 5020 5315 w +(help) 5241 5315 w +11 /LucidaSans-Italic f +(sd) 720 5445 w +11 /LucidaSansUnicode00 f +(.) 841 5445 w +(This) 952 5445 w +(means) 1218 5445 w +(that) 1608 5445 w +11 /LucidaSans-Italic f +(scuzz) 1860 5445 w +11 /LucidaSansUnicode00 f +(\(8\)) 2155 5445 w +(can) 2337 5445 w +(get) 2563 5445 w +(surprisingly) 2775 5445 w +(far) 3444 5445 w +(with) 3632 5445 w +(ATA) 3899 5445 w +(devices,) 4161 5445 w +(and) 4631 5445 w +(ATAPI) 4870 5445 w +(\() 5224 5445 w +11 /LucidaSans-Italic f +(sic.) 5260 5445 w +11 /LucidaSansUnicode00 f +(\)) 5436 5445 w +(devices) 720 5575 w +(work) 1159 5575 w +(quite) 1465 5575 w +(well.) 1782 5575 w +(Although) 2108 5575 w +(a) 2641 5575 w +(new) 2747 5575 w +(implementation) 3007 5575 w +(might) 3891 5575 w +(not) 4247 5575 w +(use) 4468 5575 w +(this) 4699 5575 w +(approach,) 4941 5575 w +(replacing) 720 5705 w +(the) 1251 5705 w +(interface) 1460 5705 w +(did) 1966 5705 w +(not) 2174 5705 w +(appear) 2388 5705 w +(cost) 2793 5705 w +(effective) 3050 5705 w +(and) 3541 5705 w +(would) 3776 5705 w +(lead) 4134 5705 w +(to) 4395 5705 w +(maximum) 4540 5705 w +(incom\255) 5111 5705 w +(patibilities,) 720 5835 w +(while) 1360 5835 w +(this) 1685 5835 w +(interface) 1928 5835 w +(is) 2442 5835 w +(experimental.) 2576 5835 w +(This) 3395 5835 w +(means) 3666 5835 w +(that) 4062 5835 w +(the) 4320 5835 w +(raw) 4538 5835 w +(interface) 4776 5835 w +(will) 5291 5835 w +(need a) 720 5965 w +(method of) 1112 5965 w +(signaling an ATA) 1699 5965 w +(command rather than a) 2639 5965 w +(SCSI) 3925 5965 w +(CDB.) 4186 5965 w +(An) 720 6135 w +(unattractive) 901 6135 w +(wart) 1571 6135 w +(of) 1841 6135 w +(the) 1987 6135 w +(ATA) 2196 6135 w +(command) 2455 6135 w +(set) 3018 6135 w +(is) 3215 6135 w +(there) 3341 6135 w +(are) 3657 6135 w +(seven) 3863 6135 w +(protocols) 4206 6135 w +(and) 4744 6135 w +(two) 4980 6135 w +(com\255) 5211 6135 w +(mand) 720 6265 w +(sizes.) 1060 6265 w +(While) 1439 6265 w +(each) 1768 6265 w +(command) 2055 6265 w +(has) 2620 6265 w +(a) 2845 6265 w +(specific) 2946 6265 w +(size) 3389 6265 w +(\(either) 3641 6265 w +(28-bit) 4026 6265 w +(LBA) 4409 6265 w +(or) 4646 6265 w +(48-bit) 4797 6265 w +(LLBA\)) 5180 6265 w +(and) 720 6395 w +(is) 956 6395 w +(associated) 1082 6395 w +(with) 1681 6395 w +(a) 1945 6395 w +(particular) 2045 6395 w +(protocol) 2594 6395 w +(\(PIO,) 3077 6395 w +(DMA,) 3366 6395 w +(PACKET,) 3694 6395 w +(etc.\),) 4181 6395 w +(this) 4485 6395 w +(information) 4721 6395 w +(is) 5384 6395 w +(available) 720 6525 w +(only) 1231 6525 w +(by) 1499 6525 w +(table) 1669 6525 w +(lookup.) 1978 6525 w +(While) 2459 6525 w +(this) 2792 6525 w +(information) 3033 6525 w +(may) 3701 6525 w +(not) 3965 6525 w +(always) 4184 6525 w +(be) 4579 6525 w +(necessary) 4753 6525 w +(for) 5319 6525 w +(simple) 720 6655 w +(SATA-based) 1126 6655 w +(controllers,) 1840 6655 w +(for) 2499 6655 w +(the) 2705 6655 w +(IDE) 2929 6655 w +(controllers,) 3156 6655 w +(it) 3815 6655 w +(is) 3941 6655 w +(required.) 4082 6655 w +(PIO) 4658 6655 w +(commands) 4891 6655 w +(are) 720 6785 w +(required) 941 6785 w +(and) 1446 6785 w +(use) 1697 6785 w +(a) 1936 6785 w +(different) 2049 6785 w +(set) 2562 6785 w +(of) 2773 6785 w +(registers) 2933 6785 w +(than) 3452 6785 w +(DMA) 3742 6785 w +(commands.) 4048 6785 w +(Queued) 4751 6785 w +(DMA) 5218 6785 w +(commands) 720 6915 w +(and) 1344 6915 w +(ATAPI) 1585 6915 w +(commands) 1942 6915 w +(are) 2566 6915 w +(submitted) 2777 6915 w +(differently) 3360 6915 w +(still.) 3954 6915 w +(Finally,) 4261 6915 w +(the) 4681 6915 w +(data) 4896 6915 w +(direc\255) 5172 6915 w +(tion) 720 7045 w +(is) 966 7045 w +(implied) 1092 7045 w +(by) 1527 7045 w +(the) 1690 7045 w +(command.) 1898 7045 w +(Having) 2530 7045 w +(these) 2934 7045 w +(three) 3260 7045 w +(extra) 3575 7045 w +(pieces) 3888 7045 w +(of) 4262 7045 w +(information) 4407 7045 w +(in) 5068 7045 w +(addi\255) 5205 7045 w +(tion to the) 720 7175 w +(command seems necessary.) 1312 7175 w +cleartomark +showpage +saveobj restore +%%EndPage: 1 1 +%%Page: 2 2 +/saveobj save def +mark +2 pagesetup +11 /LucidaSansUnicode00 f +(A) 720 850 w +(final) 864 850 w +(bit) 1166 850 w +(of) 1376 850 w +(extra-command) 1552 850 w +(information) 2486 850 w +(that) 3179 850 w +(may) 3459 850 w +(be) 3748 850 w +(useful) 3948 850 w +(is) 4344 850 w +(a) 4501 850 w +(timeout.) 4631 850 w +(While) 5183 850 w +11 /LucidaSans-Italic f +(alarm) 720 980 w +11 /LucidaSansUnicode00 f +(\(2\)) 1041 980 w +(timeouts) 1221 980 w +(work) 1729 980 w +(with) 2029 980 w +(many) 2294 980 w +(drivers,) 2621 980 w +(it) 3061 980 w +(would) 3173 980 w +(be) 3533 980 w +(an) 3702 980 w +(added) 3869 980 w +(convenience) 4237 980 w +(to) 4933 980 w +(be) 5079 980 w +(able) 5248 980 w +(to) 720 1110 w +(specify) 884 1110 w +(a) 1313 1110 w +(timeout) 1430 1110 w +(along) 1899 1110 w +(with) 2251 1110 w +(the) 2533 1110 w +(command.) 2760 1110 w +(This) 3411 1110 w +(seems) 3693 1110 w +(a) 4088 1110 w +(good) 4206 1110 w +(idea) 4534 1110 w +(in) 4815 1110 w +(principle,) 4972 1110 w +(since) 720 1240 w +(some) 1052 1240 w +(ATA) 1397 1240 w +(commands) 1676 1240 w +(should) 2315 1240 w +(return) 2733 1240 w +(within) 3120 1240 w +(milli-) 3504 1240 w +(or) 3856 1240 w +(microseconds,) 4026 1240 w +(others) 4855 1240 w +(may) 5252 1240 w +(take) 720 1370 w +(hours) 984 1370 w +(to) 1324 1370 w +(complete.) 1468 1370 w +(On) 2065 1370 w +(the) 2255 1370 w +(other) 2462 1370 w +(hand,) 2781 1370 w +(the) 3118 1370 w +(existing) 3325 1370 w +(SCSI) 3787 1370 w +(interface) 4049 1370 w +(does) 4553 1370 w +(not) 4844 1370 w +(support) 5057 1370 w +(it) 720 1500 w +(and) 829 1500 w +(changing) 1063 1500 w +(its) 1588 1500 w +(kernel-to-user) 1753 1500 w +(space) 2589 1500 w +(format) 2929 1500 w +(would) 3322 1500 w +(be) 3679 1500 w +(quite) 3846 1500 w +(invasive.) 4154 1500 w +(Timeouts) 4685 1500 w +(were) 5218 1500 w +(left) 720 1630 w +(for a) 931 1630 w +(later date.) 1215 1630 w +11 /LucidaSans-Demi f +(Protocol and) 720 1890 w +(Data) 1467 1890 w +(Format) 1764 1890 w +11 /LucidaSansUnicode00 f +(The) 720 2060 w +(existing) 965 2060 w +(protocol) 1437 2060 w +(for) 1927 2060 w +(SCSI) 2126 2060 w +(commands) 2398 2060 w +(suits) 3025 2060 w +(ATA) 3324 2060 w +(as) 3591 2060 w +(well.) 3754 2060 w +(We) 4082 2060 w +(simply) 4286 2060 w +(write) 4681 2060 w +(the) 4993 2060 w +(com\255) 5211 2060 w +(mand) 720 2190 w +(block) 1060 2190 w +(to) 1388 2190 w +(the) 1536 2190 w +(raw) 1747 2190 w +(device.) 1978 2190 w +(Then) 2426 2190 w +(we) 2733 2190 w +(either) 2920 2190 w +(write) 3270 2190 w +(or) 3575 2190 w +(read) 3727 2190 w +(the) 4004 2190 w +(data.) 4215 2190 w +(Finally) 4557 2190 w +(the) 4938 2190 w +(status) 5149 2190 w +(block) 720 2320 w +(is read.) 1043 2320 w +(What) 1508 2320 w +(remains is choosing a) 1808 2320 w +(data) 3005 2320 w +(format) 3272 2320 w +(for ATA) 3664 2320 w +(commands.) 4108 2320 w +(The) 720 2490 w +(T10) 964 2490 w +(Committee) 1216 2490 w +(has) 1846 2490 w +(defined) 2076 2490 w +(a) 2524 2490 w +(SCSI-to-ATA) 2630 2490 w +(translation) 3358 2490 w +(scheme) 3976 2490 w +(called) 4428 2490 w +(SAT[4].) 4786 2490 w +(This) 5247 2490 w +(provides) 720 2620 w +(a) 1217 2620 w +(standard) 1318 2620 w +(set) 1828 2620 w +(of) 2026 2620 w +(translations) 2173 2620 w +(between) 2840 2620 w +(common) 3328 2620 w +(SCSI) 3829 2620 w +(commands) 4094 2620 w +(and) 4714 2620 w +(ATA) 4951 2620 w +(com\255) 5211 2620 w +(mands.) 720 2750 w +(It) 1184 2750 w +(specifies) 1295 2750 w +(the) 1799 2750 w +(ATA) 2008 2750 w +(protocol) 2267 2750 w +(and) 2750 2750 w +(some) 2987 2750 w +(other) 3313 2750 w +(sideband) 3635 2750 w +(information.) 4160 2750 w +(It) 4893 2750 w +(is) 5005 2750 w +(partic\255) 5132 2750 w +(ularly) 720 2880 w +(useful) 1107 2880 w +(for) 1526 2880 w +(common) 1770 2880 w +(commands) 2323 2880 w +(such) 2995 2880 w +(as) 3334 2880 w +11 /LucidaTypewriter f +(READ \(12\)) 3542 2880 w +11 /LucidaSansUnicode00 f +(or) 4344 2880 w +11 /LucidaTypewriter f +(READ) 4547 2880 w +(CAPAC\255) 4998 2880 w +(ITY \(12\)) 720 3010 w +11 /LucidaSansUnicode00 f +(.) 1352 3010 w +(Unfortunately,) 1468 3010 w +(our) 2276 3010 w +(purpose) 2502 3010 w +(is) 2985 3010 w +(to) 3120 3010 w +(address) 3275 3010 w +(the) 3740 3010 w +(uncommon) 3958 3010 w +(commands.) 4603 3010 w +(For) 5301 3010 w +(those,) 720 3140 w +(special) 1094 3140 w +(commands) 1507 3140 w +11 /LucidaTypewriter f +(ATA) 2133 3140 w +(PASSTHROUGH \(12\)) 2459 3140 w +11 /LucidaSansUnicode00 f +(and) 3768 3140 w +11 /LucidaTypewriter f +(\(16\)) 4011 3140 w +11 /LucidaSansUnicode00 f +(exist.) 4372 3140 w +(Unfortunately) 4745 3140 w +(several) 720 3270 w +(commands) 1142 3270 w +(we) 1770 3270 w +(are) 1964 3270 w +(interested) 2179 3270 w +(in,) 2764 3270 w +(such) 2946 3270 w +(as) 3241 3270 w +(those) 3405 3270 w +(that) 3746 3270 w +(set) 4004 3270 w +(transfer) 4210 3270 w +(modes) 4676 3270 w +(are) 5080 3270 w +(not) 5296 3270 w +(allowed) 720 3400 w +(by) 1166 3400 w +(the) 1330 3400 w +(standard.) 1539 3400 w +(This) 2117 3400 w +(is) 2380 3400 w +(not) 2506 3400 w +(a) 2720 3400 w +(major) 2819 3400 w +(obstacle.) 3164 3400 w +(We) 3715 3400 w +(could) 3909 3400 w +(simply) 4238 3400 w +(ignore) 4623 3400 w +(the) 5002 3400 w +(stan\255) 5210 3400 w +(dard.) 720 3530 w +(But) 1070 3530 w +(this) 1279 3530 w +(goes) 1512 3530 w +(against) 1801 3530 w +(the) 2224 3530 w +(general) 2431 3530 w +(reasons) 2865 3530 w +(for) 3316 3530 w +(using) 3506 3530 w +(an) 3835 3530 w +(established) 4001 3530 w +(standard:) 4646 3530 w +(inter\255) 5188 3530 w +(operability.) 720 3660 w +(Finally,) 1395 3660 w +(it) 1809 3660 w +(should) 1920 3660 w +(be) 2318 3660 w +(mentioned) 2487 3660 w +(that) 3096 3660 w +(SAT) 3345 3660 w +(format) 3587 3660 w +(adds) 3982 3660 w +(yet) 4275 3660 w +(another) 4473 3660 w +(intermedi\255) 4923 3660 w +(ate) 720 3790 w +(format) 922 3790 w +(of) 1317 3790 w +(variable) 1464 3790 w +(size) 1922 3790 w +(which) 2174 3790 w +(would) 2522 3790 w +(require) 2882 3790 w +(translation) 3304 3790 w +(to) 3915 3790 w +(a) 4062 3790 w +(usable) 4162 3790 w +(format) 4549 3790 w +(for) 4945 3790 w +(all) 5137 3790 w +(the) 5301 3790 w +(existing) 720 3920 w +(Plan) 1183 3920 w +(9) 1442 3920 w +(drivers.) 1548 3920 w +(If) 2021 3920 w +(we) 2131 3920 w +11 /LucidaSansUnicode20 f +(\031) 2278 3920 w +11 /LucidaSansUnicode00 f +(re) 2313 3920 w +(not) 2457 3920 w +(hewing) 2670 3920 w +(to) 3090 3920 w +(a) 3235 3920 w +(standard,) 3333 3920 w +(we) 3874 3920 w +(should) 4057 3920 w +(build) 4453 3920 w +(or) 4759 3920 w +(choose) 4907 3920 w +(for) 5319 3920 w +(convenience.) 720 4050 w +(ATA-8) 720 4220 w +(and) 1126 4220 w +(ACS-2) 1376 4220 w +(also) 1772 4220 w +(specify) 2040 4220 w +(an) 2466 4220 w +(abstract) 2648 4220 w +(register) 3131 4220 w +(layout.) 3595 4220 w +(The) 4044 4220 w +(size) 4296 4220 w +(of) 4562 4220 w +(the) 4723 4220 w +(command) 4947 4220 w +(block) 720 4350 w +(varies) 1054 4350 w +(based) 1413 4350 w +(on) 1776 4350 w +(the) 1957 4350 w +11 /LucidaSansUnicode20 f +(\034) 2174 4350 w +11 /LucidaSansUnicode00 f +(size) 2215 4350 w +11 /LucidaSansUnicode20 f +(\035) 2428 4350 w +11 /LucidaSansUnicode00 f +(\(either) 2515 4350 w +(28-) 2907 4350 w +(or) 3155 4350 w +(48-bits\)) 3313 4350 w +(of) 3794 4350 w +(the) 3947 4350 w +(command) 4163 4350 w +(and) 4733 4350 w +(only) 4976 4350 w +(con\255) 5245 4350 w +(text) 720 4480 w +(differentiates) 979 4480 w +(a) 1740 4480 w +(command) 1849 4480 w +(from) 2422 4480 w +(a) 2725 4480 w +(response.) 2834 4480 w +(The) 3438 4480 w +(SATA) 3686 4480 w +(specification) 4015 4480 w +(defines) 4737 4480 w +(host-) 5176 4480 w +(to-drive) 720 4610 w +(communications.) 1220 4610 w +(The) 2229 4610 w +(formats) 2491 4610 w +(of) 2967 4610 w +(transactions) 3138 4610 w +(are) 3853 4610 w +(called) 4083 4610 w +(Frame) 4457 4610 w +(Information) 4848 4610 w +(Structures) 720 4740 w +(\(FISes\).) 1306 4740 w +(Typically) 1761 4740 w +(drivers) 2271 4740 w +(fill) 2682 4740 w +(out) 2865 4740 w +(the) 3087 4740 w +(command) 3304 4740 w +(FISes) 3875 4740 w +(directly) 4189 4740 w +(and) 4629 4740 w +(have) 4873 4740 w +(direct) 5167 4740 w +(access) 720 4870 w +(to) 1107 4870 w +(the) 1255 4870 w +(Device-to-Host) 1465 4870 w +(Register) 2337 4870 w +(\(D2H\)) 2811 4870 w +(FISes) 3155 4870 w +(that) 3462 4870 w +(return) 3712 4870 w +(the) 4080 4870 w +(resulting) 4290 4870 w +(ATA) 4801 4870 w +(register) 5061 4870 w +(settings.) 720 5000 w +(The) 1283 5000 w +(command) 1551 5000 w +(FISes) 2145 5000 w +(are) 2482 5000 w +(also) 2719 5000 w +(called) 3004 5000 w +(Host-to-Device) 3386 5000 w +(\(H2D\)) 4289 5000 w +(Register) 4664 5000 w +(FISes.) 5169 5000 w +(Using) 720 5130 w +(this) 1057 5130 w +(structure) 1291 5130 w +(has) 1810 5130 w +(several) 2032 5130 w +(advantages.) 2444 5130 w +(It) 3155 5130 w +(is) 3265 5130 w +(directly) 3390 5130 w +(usable) 3821 5130 w +(by) 4206 5130 w +(many) 4369 5130 w +(of) 4694 5130 w +(the) 4839 5130 w +(existing) 5046 5130 w +(SATA) 720 5260 w +(drivers.) 1056 5260 w +(All) 1548 5260 w +(SATA) 1744 5260 w +(commands) 2080 5260 w +(are) 2717 5260 w +(the) 2941 5260 w +(same) 3168 5260 w +(size) 3506 5260 w +(and) 3776 5260 w +(are) 4031 5260 w +(tagged) 4256 5260 w +(as) 4682 5260 w +(commands.) 4856 5260 w +(Normal) 720 5390 w +(responses) 1154 5390 w +(are) 1741 5390 w +(also) 1955 5390 w +(all) 2217 5390 w +(of) 2388 5390 w +(the) 2542 5390 w +(same) 2758 5390 w +(size) 3084 5390 w +(and) 3342 5390 w +(are) 3585 5390 w +(tagged) 3798 5390 w +(as) 4212 5390 w +(responses.) 4374 5390 w +(Unfortu\255) 5030 5390 w +(nately, the) 720 5520 w +(ATA) 1317 5520 w +(protocol) 1573 5520 w +(is) 2052 5520 w +(not) 2176 5520 w +(specified.) 2388 5520 w +(Nevertheless,) 2973 5520 w +(SATA) 3728 5520 w +(FISes) 4044 5520 w +(seem) 4348 5520 w +(to) 4666 5520 w +(handle) 4810 5520 w +(most) 5206 5520 w +(of) 720 5650 w +(our) 865 5650 w +(needs) 1082 5650 w +(and) 1436 5650 w +(are) 1671 5650 w +(quite) 1876 5650 w +(convenient;) 2185 5650 w +(they) 2838 5650 w +(can) 3102 5650 w +(be) 3323 5650 w +(used) 3490 5650 w +(directly) 3781 5650 w +(by) 4211 5650 w +(two) 4373 5650 w +(of) 4602 5650 w +(the) 4746 5650 w +(three) 4953 5650 w +(cur\255) 5267 5650 w +(rent) 720 5780 w +(SATA) 971 5780 w +(drivers.) 1286 5780 w +11 /LucidaSans-Demi f +(Implementation) 720 6040 w +11 /LucidaSansUnicode00 f +(Raw) 720 6210 w +(ATA) 993 6210 w +(commands) 1272 6210 w +(are) 1911 6210 w +(formatted) 2137 6210 w +(as) 2724 6210 w +(a) 2900 6210 w +(ATA) 3020 6210 w +(escape) 3300 6210 w +(byte,) 3725 6210 w +(an) 4048 6210 w +(encoded) 4236 6210 w +(ATA) 4748 6210 w +(protocol) 5028 6210 w +11 /LucidaTypewriter f +(proto) 720 6340 w +11 /LucidaSansUnicode00 f +(and) 1164 6340 w +(the) 1411 6340 w +(FIS.) 1631 6340 w +(Typically) 1900 6340 w +(this) 2414 6340 w +(would) 2660 6340 w +(be) 3030 6340 w +(a) 3210 6340 w +(H2D) 3320 6340 w +(FIS,) 3602 6340 w +(but) 3836 6340 w +(this) 4063 6340 w +(is) 4309 6340 w +(not) 4446 6340 w +(a) 4671 6340 w +(requirement.) 4781 6340 w +(The) 720 6470 w +(escape) 956 6470 w +(byte) 1359 6470 w +(0xff,) 1626 6470 w +(which) 1917 6470 w +(is) 2264 6470 w +(not) 2390 6470 w +(and,) 2604 6470 w +(according) 2875 6470 w +(to) 3435 6470 w +(the) 3581 6470 w +(current) 3790 6470 w +(specification,) 4213 6470 w +(will) 4959 6470 w +(never) 5178 6470 w +(be) 720 6600 w +(a) 906 6600 w +(valid) 1022 6600 w +(SCSI) 1328 6600 w +(command,) 1609 6600 w +(was) 2224 6600 w +(chosen.) 2481 6600 w +(The) 2983 6600 w +(protocol) 3237 6600 w +(encoding) 3736 6600 w +11 /LucidaTypewriter f +(proto) 4281 6600 w +11 /LucidaSansUnicode00 f +(and) 4731 6600 w +(other) 4984 6600 w +(FIS) 5322 6600 w +(construction) 720 6730 w +(details) 1442 6730 w +(are) 1852 6730 w +(specified) 2077 6730 w +(in) 2614 6730 w +11 /LucidaTypewriter f +(/sys/include/fis.h) 2772 6730 w +11 /LucidaSansUnicode00 f +(.) 4194 6730 w +(The) 4322 6730 w +11 /LucidaTypewriter f +(proto) 4579 6730 w +11 /LucidaSansUnicode00 f +(encodes) 5032 6730 w +(the) 720 6860 w +(ATA) 930 6860 w +(protocol,) 1190 6860 w +(the) 1708 6860 w +(command) 1918 6860 w +11 /LucidaSansUnicode20 f +(\034) 2482 6860 w +11 /LucidaSansUnicode00 f +(size) 2523 6860 w +11 /LucidaSansUnicode20 f +(\035) 2736 6860 w +11 /LucidaSansUnicode00 f +(and) 2816 6860 w +(data) 3053 6860 w +(direction.) 3324 6860 w +(The) 3905 6860 w +11 /LucidaSansUnicode20 f +(\034) 4143 6860 w +11 /LucidaSansUnicode00 f +(atazz) 4184 6860 w +11 /LucidaSansUnicode20 f +(\035) 4473 6860 w +11 /LucidaSansUnicode00 f +(command) 4552 6860 w +(format) 5115 6860 w +(is pictured in Figure 1.) 720 6990 w +cleartomark +showpage +saveobj restore +%%EndPage: 2 2 +%%Page: 3 3 +/saveobj save def +mark +3 pagesetup +1224 1078 1224 934 Dl +1224 934 1800 934 Dl +1800 934 1800 1078 Dl +1800 1078 1224 1078 Dl +11 /LucidaSansUnicode00 f +(0xff) 1403 1028 w +1800 1078 1800 934 Dl +1800 934 2376 934 Dl +2376 934 2376 1078 Dl +2376 1078 1800 1078 Dl +(proto) 1944 1028 w +2376 1078 2376 934 Dl +2376 934 2952 934 Dl +2952 934 2952 1078 Dl +2952 1078 2376 1078 Dl +(0x27) 2527 1028 w +2952 1078 2952 934 Dl +2952 934 3528 934 Dl +3528 934 3528 1078 Dl +3528 1078 2952 1078 Dl +(flags) 3111 1028 w +1224 1222 1224 1078 Dl +1224 1078 1800 1078 Dl +1800 1078 1800 1222 Dl +1800 1222 1224 1222 Dl +(cmd) 1399 1172 w +1800 1222 1800 1078 Dl +1800 1078 2376 1078 Dl +2376 1078 2376 1222 Dl +2376 1222 1800 1222 Dl +(feat) 1986 1172 w +2376 1222 2376 1078 Dl +2376 1078 2952 1078 Dl +2952 1078 2952 1222 Dl +2952 1222 2376 1222 Dl +(lba0) 2549 1172 w +2952 1222 2952 1078 Dl +2952 1078 3528 1078 Dl +3528 1078 3528 1222 Dl +3528 1222 2952 1222 Dl +(lba8) 3125 1172 w +1224 1366 1224 1222 Dl +1224 1222 1800 1222 Dl +1800 1222 1800 1366 Dl +1800 1366 1224 1366 Dl +(lba16) 1362 1316 w +1800 1366 1800 1222 Dl +1800 1222 2376 1222 Dl +2376 1222 2376 1366 Dl +2376 1366 1800 1366 Dl +(dev) 1994 1316 w +2376 1366 2376 1222 Dl +2376 1222 2952 1222 Dl +2952 1222 2952 1366 Dl +2952 1366 2376 1366 Dl +(lba24) 2514 1316 w +2952 1366 2952 1222 Dl +2952 1222 3528 1222 Dl +3528 1222 3528 1366 Dl +3528 1366 2952 1366 Dl +(lba32) 3090 1316 w +1224 1510 1224 1366 Dl +1224 1366 1800 1366 Dl +1800 1366 1800 1510 Dl +1800 1510 1224 1510 Dl +(lba40) 1362 1460 w +1800 1510 1800 1366 Dl +1800 1366 2376 1366 Dl +2376 1366 2376 1510 Dl +2376 1510 1800 1510 Dl +(feat8) 1951 1460 w +2376 1510 2376 1366 Dl +2376 1366 2952 1366 Dl +2952 1366 2952 1510 Dl +2952 1510 2376 1510 Dl +(cnt) 2582 1460 w +2952 1510 2952 1366 Dl +2952 1366 3528 1366 Dl +3528 1366 3528 1510 Dl +3528 1510 2952 1510 Dl +(cnt8) 3123 1460 w +1224 1654 1224 1510 Dl +1224 1510 1800 1510 Dl +1800 1510 1800 1654 Dl +1800 1654 1224 1654 Dl +(rsvd) 1399 1604 w +1800 1654 1800 1510 Dl +1800 1510 2376 1510 Dl +2376 1510 2376 1654 Dl +2376 1654 1800 1654 Dl +(ctl) 2024 1604 w +4392 1870 4392 1726 Dl +4392 1726 4968 1726 Dl +4968 1726 4968 1870 Dl +4968 1870 4392 1870 Dl +(sdXX/raw) 4424 1820 w +3528 1294 4392 1798 Dl +4320 1777 4391 1797 Dl +4338 1746 4391 1797 Dl +2952 2086 2952 1942 Dl +2952 1942 3528 1942 Dl +3528 1942 3528 2086 Dl +3528 2086 2952 2086 Dl +(data) 3124 2036 w +4392 2302 4392 2158 Dl +4392 2158 4968 2158 Dl +4968 2158 4968 2302 Dl +4968 2302 4392 2302 Dl +(sdXX/raw) 4424 2252 w +3528 2014 4392 2230 Dl +4317 2230 4391 2230 Dl +4326 2194 4391 2229 Dl +4392 2590 4392 2446 Dl +4392 2446 4968 2446 Dl +4968 2446 4968 2590 Dl +4968 2590 4392 2590 Dl +(sdXX/raw) 4424 2540 w +1224 2806 1224 2662 Dl +1224 2662 1800 2662 Dl +1800 2662 1800 2806 Dl +1800 2806 1224 2806 Dl +(0xff) 1403 2756 w +1800 2806 1800 2662 Dl +1800 2662 2376 2662 Dl +2376 2662 2376 2806 Dl +2376 2806 1800 2806 Dl +(proto) 1944 2756 w +2376 2806 2376 2662 Dl +2376 2662 2952 2662 Dl +2952 2662 2952 2806 Dl +2952 2806 2376 2806 Dl +(0x34) 2527 2756 w +2952 2806 2952 2662 Dl +2952 2662 3528 2662 Dl +3528 2662 3528 2806 Dl +3528 2806 2952 2806 Dl +(port) 3129 2756 w +1224 2950 1224 2806 Dl +1224 2806 1800 2806 Dl +1800 2806 1800 2950 Dl +1800 2950 1224 2950 Dl +(stat) 1413 2900 w +1800 2950 1800 2806 Dl +1800 2806 2376 2806 Dl +2376 2806 2376 2950 Dl +2376 2950 1800 2950 Dl +(err) 2012 2900 w +2376 2950 2376 2806 Dl +2376 2806 2952 2806 Dl +2952 2806 2952 2950 Dl +2952 2950 2376 2950 Dl +(lba0) 2549 2900 w +2952 2950 2952 2806 Dl +2952 2806 3528 2806 Dl +3528 2806 3528 2950 Dl +3528 2950 2952 2950 Dl +(lba8) 3125 2900 w +1224 3094 1224 2950 Dl +1224 2950 1800 2950 Dl +1800 2950 1800 3094 Dl +1800 3094 1224 3094 Dl +(lba16) 1362 3044 w +1800 3094 1800 2950 Dl +1800 2950 2376 2950 Dl +2376 2950 2376 3094 Dl +2376 3094 1800 3094 Dl +(dev) 1994 3044 w +2376 3094 2376 2950 Dl +2376 2950 2952 2950 Dl +2952 2950 2952 3094 Dl +2952 3094 2376 3094 Dl +(lba24) 2514 3044 w +2952 3094 2952 2950 Dl +2952 2950 3528 2950 Dl +3528 2950 3528 3094 Dl +3528 3094 2952 3094 Dl +(lba32) 3090 3044 w +1224 3238 1224 3094 Dl +1224 3094 1800 3094 Dl +1800 3094 1800 3238 Dl +1800 3238 1224 3238 Dl +(lba40) 1362 3188 w +1800 3238 1800 3094 Dl +1800 3094 2376 3094 Dl +2376 3094 2376 3238 Dl +2376 3238 1800 3238 Dl +(feat8) 1951 3188 w +2376 3238 2376 3094 Dl +2376 3094 2952 3094 Dl +2952 3094 2952 3238 Dl +2952 3238 2376 3238 Dl +(cnt) 2582 3188 w +2952 3238 2952 3094 Dl +2952 3094 3528 3094 Dl +3528 3094 3528 3238 Dl +3528 3238 2952 3238 Dl +(cnt8) 3123 3188 w +1224 3382 1224 3238 Dl +1224 3238 1800 3238 Dl +1800 3238 1800 3382 Dl +1800 3382 1224 3382 Dl +(rsvd) 1399 3332 w +1800 3382 1800 3238 Dl +1800 3238 2376 3238 Dl +2376 3238 2376 3382 Dl +2376 3382 1800 3382 Dl +(ctl) 2024 3332 w +4392 2518 3528 3022 Dl +3581 2970 3528 3021 Dl +3599 3001 3528 3021 Dl +10 /LucidaSans-Demi f +(Figure 1) 2853 3646 w +11 /LucidaSansUnicode00 f +(Raw) 720 3836 w +(ATA) 980 3836 w +(replies) 1247 3836 w +(are) 1651 3836 w +(formatted) 1865 3836 w +(as) 2440 3836 w +(a) 2603 3836 w +(one-byte) 2710 3836 w +(sd) 3246 3836 w +(status) 3417 3836 w +(code) 3786 3836 w +(followed) 4086 3836 w +(by) 4587 3836 w +(the) 4759 3836 w +(reply) 4976 3836 w +(FIS.) 5287 3836 w +(The) 720 3966 w +(usual) 982 3966 w +(read/write) 1330 3966 w +(register) 1953 3966 w +(substitutions) 2427 3966 w +(are) 3185 3966 w +(applied;) 3415 3966 w +(ioport) 3906 3966 w +(replaces) 4289 3966 w +(flags,) 4794 3966 w +(status) 5149 3966 w +(replaces cmd, error replaces feature.) 720 4096 w +(Important) 720 4266 w +(commands) 1289 4266 w +(such) 1913 4266 w +(as) 2204 4266 w +11 /LucidaTypewriter f +(SMART) 2364 4266 w +(RETURN) 2846 4266 w +(STATUS) 3407 4266 w +11 /LucidaSansUnicode00 f +(return) 3924 4266 w +(no) 4296 4266 w +(data.) 4474 4266 w +(In) 4819 4266 w +(this) 4962 4266 w +(case,) 5202 4266 w +(the) 720 4396 w +(protocol) 940 4396 w +(is) 1433 4396 w +(run) 1569 4396 w +(as) 1798 4396 w +(usual.) 1963 4396 w +(The) 2366 4396 w +(client) 2613 4396 w +(performs) 2952 4396 w +(a) 3487 4396 w +(0-byte) 3596 4396 w +(read) 4006 4396 w +(to) 4291 4396 w +(fulfill) 4447 4396 w +(data) 4773 4396 w +(transfer) 5053 4396 w +(step.) 720 4526 w +(The) 1067 4526 w +(status) 1315 4526 w +(is) 1687 4526 w +(in) 1824 4526 w +(the) 1973 4526 w +(D2H) 2193 4526 w +(FIS) 2475 4526 w +(returned) 2674 4526 w +(as) 3183 4526 w +(the) 3349 4526 w +(status.) 3569 4526 w +(The) 4011 4526 w +(vendor) 4259 4526 w +(ATA) 4676 4526 w +(command) 4947 4526 w +(0xf0) 720 4656 w +(is) 1012 4656 w +(used) 1146 4656 w +(to) 1447 4656 w +(return) 1601 4656 w +(the) 1976 4656 w +(device) 2192 4656 w +(signature) 2575 4656 w +(FIS) 3121 4656 w +(as) 3316 4656 w +(there) 3478 4656 w +(is) 3801 4656 w +(no) 3934 4656 w +(universal) 4114 4656 w +(in-band) 4640 4656 w +(way) 5116 4656 w +(to) 5364 4656 w +(do) 720 4786 w +(this) 893 4786 w +(without) 1127 4786 w +(side) 1566 4786 w +(effects.) 1822 4786 w +(When) 2288 4786 w +(talking) 2618 4786 w +(only) 3021 4786 w +(to) 3282 4786 w +(ATA) 3428 4786 w +(drives,) 3687 4786 w +(it) 4081 4786 w +(is) 4192 4786 w +(possible) 4318 4786 w +(to) 4799 4786 w +(first) 4945 4786 w +(issue) 5198 4786 w +(a) 720 4916 w +11 /LucidaTypewriter f +(IDENTIFY) 817 4916 w +(PACKET) 1529 4916 w +(DEVICE) 2083 4916 w +11 /LucidaSansUnicode00 f +(and then a) 2593 4916 w +11 /LucidaTypewriter f +(IDENTIFY DEVICE) 3196 4916 w +11 /LucidaSansUnicode00 f +(command, inferring) 4416 4916 w +(the) 720 5046 w +(device) 944 5046 w +(type) 1335 5046 w +(from) 1617 5046 w +(the) 1925 5046 w +(successful) 2149 5046 w +(command.) 2753 5046 w +(However,) 3402 5046 w +(it) 3950 5046 w +(would) 4077 5046 w +(not) 4452 5046 w +(be) 4682 5046 w +(possible) 4867 5046 w +(to) 5364 5046 w +(enumerate) 720 5176 w +(the) 1326 5176 w +(devices behind a) 1532 5176 w +(port) 2460 5176 w +(multiplier using this technique.) 2717 5176 w +11 /LucidaSans-Demi f +(Kernel changes) 720 5436 w +(and) 1627 5436 w +(Libfis) 1873 5436 w +11 /LucidaSansUnicode00 f +(Very) 720 5606 w +(few) 1008 5606 w +(changes) 1248 5606 w +(were) 1739 5606 w +(made) 2045 5606 w +(to) 2391 5606 w +(devsd) 2551 5606 w +(to) 2917 5606 w +(accommodate) 3078 5606 w +(ATA) 3875 5606 w +(commands.) 4149 5606 w +(the) 4853 5606 w +11 /LucidaTypewriter f +(SDreq) 5077 5606 w +11 /LucidaSansUnicode00 f +(structure) 720 5736 w +(adds) 1251 5736 w +11 /LucidaTypewriter f +(proto) 1555 5736 w +11 /LucidaSansUnicode00 f +(and) 1999 5736 w +11 /LucidaTypewriter f +(ataproto) 2246 5736 w +11 /LucidaSansUnicode00 f +(fields.) 2927 5736 w +(To) 3338 5736 w +(avoid) 3523 5736 w +(disturbing) 3858 5736 w +(existing) 4455 5736 w +(SCSI) 4929 5736 w +(func\255) 5203 5736 w +(tionality and to allow) 720 5866 w +(drivers which support) 1874 5866 w +(SCSI) 3069 5866 w +(and) 3331 5866 w +(ATA) 3565 5866 w +(commands) 3822 5866 w +(in) 4439 5866 w +(parallel,) 4575 5866 w +(an) 5040 5866 w +(addi\255) 5205 5866 w +(tional) 720 5996 w +11 /LucidaTypewriter f +(ataio) 1075 5996 w +11 /LucidaSansUnicode00 f +(callback) 1524 5996 w +(was) 2009 5996 w +(added) 2265 5996 w +(to) 2649 5996 w +11 /LucidaTypewriter f +(SDifc) 2811 5996 w +11 /LucidaSansUnicode00 f +(with) 3260 5996 w +(the) 3540 5996 w +(same) 3764 5996 w +(signature) 4098 5996 w +(as) 4652 5996 w +(the) 4822 5996 w +(existing) 5046 5996 w +11 /LucidaTypewriter f +(rio) 720 6126 w +11 /LucidaSansUnicode00 f +(callback.) 995 6126 w +(About) 1534 6126 w +(twenty) 1893 6126 w +(lines) 2285 6126 w +(of) 2573 6126 w +(code) 2719 6126 w +(were) 3011 6126 w +(added) 3303 6126 w +(to) 3671 6126 w +11 /LucidaTypewriter f +(port/devsd.c) 3817 6126 w +11 /LucidaSansUnicode00 f +(to) 4803 6126 w +(recognize) 4949 6126 w +(raw) 720 6256 w +(ATA) 946 6256 w +(commands and call) 1202 6256 w +(the) 2267 6256 w +(driver) 2473 6256 w +11 /LucidaSansUnicode20 f +(\031) 2783 6256 w +11 /LucidaSansUnicode00 f +(s) 2818 6256 w +11 /LucidaTypewriter f +(ataio) 2909 6256 w +11 /LucidaSansUnicode00 f +(function.) 3339 6256 w +(To) 720 6426 w +(assist) 896 6426 w +(in) 1238 6426 w +(generating) 1378 6426 w +(the) 1993 6426 w +(FISes) 2205 6426 w +(to) 2514 6426 w +(communicate) 2663 6426 w +(with) 3419 6426 w +(devices,) 3686 6426 w +11 /LucidaTypewriter f +(libfis) 4156 6426 w +11 /LucidaSansUnicode00 f +(was) 4671 6426 w +(written.) 4914 6426 w +(It) 5399 6426 w +(contains) 720 6556 w +(functions) 1205 6556 w +(to) 1738 6556 w +(identify) 1882 6556 w +(and) 2320 6556 w +(enumerate) 2554 6556 w +(the) 3160 6556 w +(important) 3366 6556 w +(features of) 3927 6556 w +(a) 4541 6556 w +(drive, to format) 4637 6556 w +(H2D) 720 6686 w +(FISes And finally, functions) 988 6686 w +(for) 2465 6686 w +11 /LucidaSans-Italic f +(sd) 2654 6686 w +11 /LucidaSansUnicode00 f +(and) 2811 6686 w +11 /LucidaSans-Italic f +(sd) 3045 6686 w +11 /LucidaSansUnicode00 f +(-devices) 3202 6686 w +(to) 3696 6686 w +(build) 3840 6686 w +(D2H) 4146 6686 w +(FISes) 4415 6686 w +(to) 4719 6686 w +(capture) 4863 6686 w +(the) 5301 6686 w +(device) 720 6816 w +(signature.) 1093 6816 w +(All) 720 6986 w +(ATA) 907 6986 w +(device) 1176 6986 w +(drivers) 1562 6986 w +(for) 1976 6986 w +(the) 2177 6986 w +(386) 2396 6986 w +(architecture) 2651 6986 w +(have) 3336 6986 w +(been) 3632 6986 w +(modified) 3941 6986 w +(to) 4463 6986 w +(accept) 4619 6986 w +(raw) 5012 6986 w +(ATA) 5251 6986 w +(commands.) 720 7116 w +(Due) 1408 7116 w +(to) 1658 7116 w +(consolidation) 1803 7116 w +(of) 2556 7116 w +(FIS) 2701 7116 w +(handling,) 2887 7116 w +(the) 3424 7116 w +(AHCI) 3631 7116 w +(driver) 3932 7116 w +(lost) 4278 7116 w +(175) 4510 7116 w +(lines) 4753 7116 w +(of) 5039 7116 w +(code,) 5183 7116 w +(additional) 720 7246 w +(non-atazz-related) 1315 7246 w +(functionality) 2370 7246 w +(notwithstanding.) 3097 7246 w +(The) 4096 7246 w +(IDE) 4359 7246 w +(driver) 4597 7246 w +(remained) 4971 7246 w +cleartomark +showpage +saveobj restore +%%EndPage: 3 3 +%%Page: 4 4 +/saveobj save def +mark +4 pagesetup +11 /LucidaSansUnicode00 f +(exactly) 720 850 w +(the) 1138 850 w +(same) 1351 850 w +(size.) 1674 850 w +(Quite) 1999 850 w +(a) 2330 850 w +(bit) 2433 850 w +(more) 2617 850 w +(code) 2935 850 w +(could) 3231 850 w +(be) 3565 850 w +(removed) 3738 850 w +(if) 4244 850 w +(the) 4359 850 w +(driver) 4571 850 w +(were) 4922 850 w +(reor\255) 5217 850 w +(ganized.) 720 980 w +(The) 1266 980 w +(mv50xx) 1518 980 w +(driver) 2002 980 w +(gained) 2365 980 w +(153) 2778 980 w +(lines) 3039 980 w +(of) 3343 980 w +(code.) 3505 980 w +(Development) 3883 980 w +(versions) 4642 980 w +(of) 5139 980 w +(the) 5301 980 w +(Marvell) 720 1110 w +(Orion) 1166 1110 w +(driver) 1526 1110 w +(lost) 1898 1110 w +(over) 2156 1110 w +(500) 2449 1110 w +(lines) 2717 1110 w +(while) 3028 1110 w +11 /LucidaTypewriter f +(libfis) 3368 1110 w +11 /LucidaSansUnicode00 f +(is) 3903 1110 w +(only) 4052 1110 w +(about) 4337 1110 w +(the) 4704 1110 w +(same) 4936 1110 w +(line) 5278 1110 w +(count.) 720 1240 w +(Since) 720 1410 w +(FIS) 1043 1410 w +(formats) 1239 1410 w +(were) 1698 1410 w +(used) 1998 1410 w +(to) 2299 1410 w +(convey) 2453 1410 w +(commands) 2866 1410 w +(from) 3493 1410 w +(user) 3794 1410 w +(space,) 4072 1410 w +11 /LucidaTypewriter f +(libfis) 4458 1410 w +11 /LucidaSansUnicode00 f +(has) 4979 1410 w +(been) 5211 1410 w +(equally) 720 1540 w +(useful) 1151 1540 w +(for) 1528 1540 w +(user) 1731 1540 w +(space) 2012 1540 w +(applications.) 2366 1540 w +(This) 3130 1540 w +(is) 3405 1540 w +(because) 3543 1540 w +(the) 4027 1540 w +11 /LucidaSans-Italic f +(atazz) 4247 1540 w +11 /LucidaSansUnicode00 f +(interface) 4590 1540 w +(can) 5107 1540 w +(be) 5341 1540 w +(thought) 720 1670 w +(of) 1178 1670 w +(as) 1323 1670 w +(an) 1477 1670 w +(idealized) 1643 1670 w +(HBA.) 2162 1670 w +(Conversely,) 2491 1670 w +(the) 3146 1670 w +(hardware) 3355 1670 w +(driver) 3889 1670 w +(does) 4237 1670 w +(not) 4529 1670 w +(need) 4743 1670 w +(to) 5042 1670 w +(know) 5188 1670 w +(anything about) 720 1800 w +(the) 1559 1800 w +(command it) 1765 1800 w +(is issuing beyond the) 2433 1800 w +(ATA) 3604 1800 w +(protocol.) 3860 1800 w +11 /LucidaSans-Demi f +(Atazz) 720 2060 w +11 /LucidaSansUnicode00 f +(As an example) 720 2230 w +(and) 1541 2230 w +(debugging) 1775 2230 w +(tool,) 2383 2230 w +(the) 2661 2230 w +11 /LucidaSans-Italic f +(atazz) 2868 2230 w +11 /LucidaSansUnicode00 f +(\(8\)) 3162 2230 w +(command) 3339 2230 w +(was) 3900 2230 w +(written.) 4138 2230 w +11 /LucidaSans-Italic f +(Atazz) 4618 2230 w +11 /LucidaSansUnicode00 f +(is) 4957 2230 w +(an) 5081 2230 w +(ana\255) 5246 2230 w +(log) 720 2360 w +(to) 929 2360 w +11 /LucidaSans-Italic f +(scuzz) 1079 2360 w +11 /LucidaSansUnicode00 f +(\(8\);) 1374 2360 w +(they) 1592 2360 w +(can) 1862 2360 w +(be) 2089 2360 w +(thought) 2262 2360 w +(of) 2725 2360 w +(as) 2875 2360 w +(a) 3034 2360 w +(driver) 3137 2360 w +(for) 3489 2360 w +(a) 3684 2360 w +(virtual) 3787 2360 w +(interface) 4164 2360 w +(provided) 4673 2360 w +(by) 5184 2360 w +11 /LucidaSans-Italic f +(sd) 5351 2360 w +11 /LucidaSansUnicode00 f +(combined) 720 2490 w +(with) 1291 2490 w +(a) 1564 2490 w +(disk) 1672 2490 w +(console.) 1940 2490 w +(ATA) 2465 2490 w +(commands) 2733 2490 w +(are) 3361 2490 w +(spelled) 3576 2490 w +(out) 4005 2490 w +(verbosely) 4228 2490 w +(as) 4782 2490 w +(in) 4946 2490 w +(ACS-2.) 5093 2490 w +(Arbitrary) 720 2620 w +(ATA) 1227 2620 w +(commands may be) 1483 2620 w +(submitted, but) 2520 2620 w +(the) 3343 2620 w +(controller or driver may not) 3549 2620 w +(support) 5057 2620 w +(all) 720 2750 w +(of) 880 2750 w +(them.) 1023 2750 w +(Here) 1401 2750 w +(is a) 1686 2750 w +(sample) 1905 2750 w +(transcript:) 2322 2750 w +9 /LucidaTypewriter f +(az>) 940 2920 w +(probe) 1200 2920 w +(/dev/sda0) 940 3030 w +(976773168;) 1720 3030 w +(512) 2435 3030 w +(50000f001b206489) 2760 3030 w +(/dev/sdC1) 940 3140 w +(0;) 1720 3140 w +(0) 1915 3140 w +(0) 2240 3140 w +(/dev/sdD0) 940 3250 w +(1023120;) 1720 3250 w +(512) 2305 3250 w +(0) 2760 3250 w +(/dev/sdE0) 940 3360 w +(976773168;) 1720 3360 w +(512) 2435 3360 w +(50014ee2014f5b5a) 2760 3360 w +(/dev/sdF7) 940 3470 w +(976773168;) 1720 3470 w +(512) 2435 3470 w +(5000cca214c3a6d3) 2760 3470 w +(az>) 940 3580 w +(open) 1200 3580 w +(/dev/sdF0) 1525 3580 w +(az>) 940 3690 w +(smart) 1200 3690 w +(enable) 1590 3690 w +(operations) 2045 3690 w +(az>) 940 3800 w +(smart) 1200 3800 w +(return) 1590 3800 w +(status) 2045 3800 w +(normal) 940 3910 w +(az>) 940 4020 w +(rfis) 1200 4020 w +(00) 940 4130 w +(34405000004fc2a00000000000000000) 940 4240 w +11 /LucidaSansUnicode00 f +(In) 720 4470 w +(the) 871 4470 w +(example,) 1093 4470 w +(the) 1634 4470 w +11 /LucidaTypewriter f +(probe) 1856 4470 w +11 /LucidaSansUnicode00 f +(command) 2302 4470 w +(is) 2878 4470 w +(a) 3017 4470 w +(special) 3129 4470 w +(command) 3548 4470 w +(that) 4124 4470 w +(uses) 4386 4470 w +11 /LucidaTypewriter f +(#S/sdctl) 4680 4470 w +11 /LucidaSansUnicode00 f +(to) 5364 4470 w +(enumerate) 720 4600 w +(the) 1336 4600 w +(controllers) 1552 4600 w +(in) 2168 4600 w +(the) 2313 4600 w +(system.) 2529 4600 w +(For) 3018 4600 w +(each) 3233 4600 w +(controller,) 3524 4600 w +(the) 4118 4600 w +11 /LucidaTypewriter f +(sd) 4333 4600 w +11 /LucidaSansUnicode00 f +(vendor) 4535 4600 w +(command) 4947 4600 w +11 /LucidaTypewriter f +(0xf0) 720 4730 w +11 /LucidaSansUnicode00 f +(\() 1077 4730 w +11 /LucidaTypewriter f +(GET) 1113 4730 w +(SIGNATURE) 1391 4730 w +11 /LucidaSansUnicode00 f +(\)) 2102 4730 w +(is) 2179 4730 w +(issued.) 2309 4730 w +(If) 2764 4730 w +(this) 2879 4730 w +(command) 3118 4730 w +(is) 3685 4730 w +(successful,) 3815 4730 w +(the) 4443 4730 w +(number) 4656 4730 w +(of) 5112 4730 w +(sec\255) 5262 4730 w +(tors,) 720 4860 w +(sector) 1000 4860 w +(size) 1363 4860 w +(and) 1612 4860 w +(WWN) 1846 4860 w +(are) 2153 4860 w +(gathered) 2357 4860 w +(and) 2869 4860 w +(and) 3103 4860 w +(listed.) 3337 4860 w +(The) 3734 4860 w +11 /LucidaTypewriter f +(/dev/sdC1) 3968 4860 w +11 /LucidaSansUnicode00 f +(device) 4714 4860 w +(reports) 5087 4860 w +(0 sectors and) 720 4990 w +(0) 1476 4990 w +(sector) 1581 4990 w +(size) 1944 4990 w +(because) 2193 4990 w +(it) 2663 4990 w +(is) 2772 4990 w +(a) 2896 4990 w +(DVD-RW) 2993 4990 w +(with) 3495 4990 w +(no) 3757 4990 w +(media.) 3928 4990 w +(The) 4360 4990 w +11 /LucidaTypewriter f +(open) 4595 4990 w +11 /LucidaSansUnicode00 f +(command) 4947 4990 w +(is) 720 5120 w +(another) 850 5120 w +(special) 1304 5120 w +(command) 1714 5120 w +(that) 2281 5120 w +(issues) 2534 5120 w +(the) 2906 5120 w +(same) 3118 5120 w +(commands) 3440 5120 w +(a) 4062 5120 w +(SATA) 4164 5120 w +(driver) 4485 5120 w +(would) 4836 5120 w +(issue) 5198 5120 w +(to) 720 5250 w +(gather) 871 5250 w +(the) 1259 5250 w +(information) 1473 5250 w +(about) 2140 5250 w +(the) 2489 5250 w +(drive.) 2703 5250 w +(The) 3081 5250 w +(final) 3324 5250 w +(two) 3602 5250 w +(commands) 3839 5250 w +(enable) 4464 5250 w +(SMART) 4862 5250 w +(and) 5274 5250 w +(return) 720 5380 w +(the) 1108 5380 w +(SMART) 1338 5380 w +(status.) 1765 5380 w +(The) 2217 5380 w +(smart) 2475 5380 w +(status) 2839 5380 w +(is) 3221 5380 w +(returned) 3368 5380 w +(in) 3887 5380 w +(a) 4046 5380 w +(D2H) 4166 5380 w +(FIS.) 4458 5380 w +(This) 4737 5380 w +(result) 5021 5380 w +(is) 5384 5380 w +(parsed) 720 5510 w +(the) 1130 5510 w +(result) 1349 5510 w +(is) 1701 5510 w +(printed) 1837 5510 w +(as) 2271 5510 w +(either) 2436 5510 w +11 /LucidaSansUnicode20 f +(\034) 2794 5510 w +11 /LucidaSansUnicode00 f +(normal,) 2835 5510 w +11 /LucidaSansUnicode20 f +(\035) 3245 5510 w +11 /LucidaSansUnicode00 f +(or) 3334 5510 w +11 /LucidaSansUnicode20 f +(\034) 3494 5510 w +11 /LucidaSansUnicode00 f +(threshold) 3535 5510 w +(exceeded) 4091 5510 w +11 /LucidaSansUnicode20 f +(\035) 4600 5510 w +11 /LucidaSansUnicode00 f +(\(the) 4690 5510 w +(drive) 4946 5510 w +(pre\255) 5260 5510 w +(dicts imminent) 720 5640 w +(failure\).) 1551 5640 w +(As) 720 5810 w +(a) 889 5810 w +(further) 987 5810 w +(real-world) 1394 5810 w +(example,) 1993 5810 w +(a) 2520 5810 w +(drive) 2619 5810 w +(from) 2922 5810 w +(my) 3215 5810 w +(file) 3412 5810 w +(server) 3617 5810 w +(failed) 3982 5810 w +(after) 4317 5810 w +(a) 4605 5810 w +(power) 4704 5810 w +(outage.) 5070 5810 w +(The) 720 5940 w +(simple) 957 5940 w +(diagnostic) 1348 5940 w +11 /LucidaTypewriter f +(SMART) 1936 5940 w +(RETURN) 2413 5940 w +(STATUS) 2968 5940 w +11 /LucidaSansUnicode00 f +(returned) 3479 5940 w +(an) 3976 5940 w +(uninformative) 4142 5940 w +11 /LucidaSansUnicode20 f +(\034) 4923 5940 w +11 /LucidaSansUnicode00 f +(threshold) 4964 5940 w +(exceeded.) 720 6070 w +11 /LucidaSansUnicode20 f +(\035) 1264 6070 w +11 /LucidaSansUnicode00 f +(We) 1344 6070 w +(can) 1540 6070 w +(run) 1764 6070 w +(some) 1984 6070 w +(more) 2310 6070 w +(in-depth) 2625 6070 w +(tests.) 3137 6070 w +(In) 3502 6070 w +(this) 3641 6070 w +(case) 3877 6070 w +(we) 4151 6070 w +(will) 4337 6070 w +(need) 4557 6070 w +(to) 4858 6070 w +(make) 5006 6070 w +(up) 5335 6070 w +(for) 720 6200 w +(the) 919 6200 w +(fact) 1136 6200 w +(that) 1381 6200 w +11 /LucidaSans-Italic f +(atazz) 1638 6200 w +11 /LucidaSansUnicode00 f +(does) 1978 6200 w +(not) 2278 6200 w +(know) 2500 6200 w +(every) 2830 6200 w +(option) 3159 6200 w +(to) 3548 6200 w +(every) 3701 6200 w +(command.) 4029 6200 w +(We) 4669 6200 w +(will) 4871 6200 w +(set) 5097 6200 w +(the) 5301 6200 w +11 /LucidaTypewriter f +(lba0) 720 6330 w +11 /LucidaSansUnicode00 f +(register by hand:) 1071 6330 w +cleartomark +showpage +saveobj restore +%%EndPage: 4 4 +%%Page: 5 5 +/saveobj save def +mark +5 pagesetup +9 /LucidaTypewriter f +(az>) 940 830 w +(smart) 1200 830 w +(lba0) 1590 830 w +(1) 1915 830 w +(execute) 2045 830 w +(off-line) 2565 830 w +(immediate) 3150 830 w +(#) 3800 830 w +(short) 3930 830 w +(data) 4320 830 w +(collection) 4645 830 w +(az>) 940 940 w +(smart) 1200 940 w +(read) 1590 940 w +(data) 1915 940 w +(col) 940 1050 w +(status:) 1200 1050 w +(00) 1720 1050 w +(never) 1915 1050 w +(started) 2305 1050 w +(exe) 940 1160 w +(status:) 1200 1160 w +(89) 1720 1160 w +(failed:) 1915 1160 w +(shipping) 2435 1160 w +(damage,) 3020 1160 w +(90%) 3540 1160 w +(left) 3800 1160 w +(time) 940 1270 w +(left:) 1265 1270 w +(10507s) 1655 1270 w +(shrt) 940 1380 w +(poll:) 1265 1380 w +(176m) 1655 1380 w +(ext) 940 1490 w +(poll:) 1200 1490 w +(19m) 1590 1490 w +(az>) 940 1600 w +11 /LucidaSansUnicode00 f +(Here) 720 1830 w +(we) 1027 1830 w +(see) 1231 1830 w +(that) 1468 1830 w +(the) 1736 1830 w +(drive) 1964 1830 w +(claims) 2286 1830 w +(that) 2682 1830 w +(it) 2950 1830 w +(was) 3080 1830 w +(damaged) 3339 1830 w +(in) 3888 1830 w +(shipping) 4045 1830 w +(and) 4564 1830 w +(the) 4820 1830 w +(damage) 5049 1830 w +(occurred) 720 1960 w +(in) 1226 1960 w +(the) 1364 1960 w +(first) 1572 1960 w +(10%) 1824 1960 w +(of) 2073 1960 w +(the) 2218 1960 w +(drive.) 2426 1960 w +(Since) 2798 1960 w +(we) 3112 1960 w +(know) 3296 1960 w +(the) 3617 1960 w +(drive) 3825 1960 w +(had) 4127 1960 w +(been) 4362 1960 w +(working) 4660 1960 w +(before) 5126 1960 w +(the) 720 2090 w +(power) 941 2090 w +(outage,) 1319 2090 w +(and) 1771 2090 w +(the) 2019 2090 w +(original) 2240 2090 w +(symptom) 2695 2090 w +(was) 3239 2090 w +(excessive) 3491 2090 w +(UREs) 4051 2090 w +(\(Unrecoverable) 4362 2090 w +(Read) 5211 2090 w +(Errors\)) 720 2220 w +(followed) 1121 2220 w +(by) 1624 2220 w +(write) 1798 2220 w +(failures,) 2111 2220 w +(and) 2591 2220 w +(finally) 2837 2220 w +(a) 3208 2220 w +(threshold) 3317 2220 w +(exceeded) 3873 2220 w +(condition,) 4430 2220 w +(it) 5013 2220 w +(is) 5133 2220 w +(rea\255) 5268 2220 w +(sonable) 720 2350 w +(to assume) 1170 2350 w +(that) 1753 2350 w +(the) 1999 2350 w +(head may have) 2205 2350 w +(crashed.) 3038 2350 w +11 /LucidaSans-Demi f +(Stand) 720 2610 w +(Alone) 1074 2610 w +(Applications) 1434 2610 w +11 /LucidaSansUnicode00 f +(There) 720 2780 w +(are) 1107 2780 w +(several) 1357 2780 w +(obvious) 1814 2780 w +(stand-alone) 2312 2780 w +(applications) 3043 2780 w +(for) 3769 2780 w +(this) 4004 2780 w +(functionality:) 4283 2780 w +(a) 5064 2780 w +(drive) 5207 2780 w +(firmware) 720 2910 w +(upgrade) 1243 2910 w +(utility,) 1735 2910 w +(a) 2123 2910 w +(drive) 2233 2910 w +(scrubber) 2547 2910 w +(that) 3066 2910 w +(bypasses) 3326 2910 w +(the) 3861 2910 w +(drive) 4081 2910 w +(cache) 4395 2910 w +(and) 4747 2910 w +(a) 4994 2910 w +(SMART) 5104 2910 w +(monitor.) 720 3040 w +(Since) 720 3210 w +(SCSI) 1032 3210 w +(also supports a) 1293 3210 w +(basic) 2146 3210 w +(SMART-like) 2456 3210 w +(interface) 3114 3210 w +(through) 3618 3210 w +(the) 4079 3210 w +11 /LucidaTypewriter f +(SEND) 4286 3210 w +(DIAGNOSTIC) 4682 3210 w +11 /LucidaSansUnicode00 f +(and) 720 3340 w +11 /LucidaTypewriter f +(RECEIVE) 964 3340 w +(DIAGNOSTIC) 1607 3340 w +(RESULTS) 2487 3340 w +11 /LucidaSansUnicode00 f +(commands,) 3086 3340 w +11 /LucidaSans-Italic f +(disk/smart) 3748 3340 w +11 /LucidaSansUnicode00 f +(\(8\)) 4336 3340 w +(gives) 4522 3340 w +(a) 4842 3340 w +(chance) 4948 3340 w +(to) 5364 3340 w +(test) 720 3470 w +(both raw) 955 3470 w +(ATA) 1461 3470 w +(and SCSI) 1717 3470 w +(commands in the) 2211 3470 w +(same) 3168 3470 w +(application.) 3484 3470 w +11 /LucidaSans-Italic f +(Disk/smart) 720 3640 w +11 /LucidaSansUnicode00 f +(uses) 1362 3640 w +(the) 1644 3640 w +(usual) 1855 3640 w +(techniques) 2180 3640 w +(for) 2802 3640 w +(gathering) 2995 3640 w +(a) 3548 3640 w +(list) 3649 3640 w +(of) 3850 3640 w +(devices) 3998 3640 w +(or) 4432 3640 w +(uses) 4584 3640 w +(the) 4866 3640 w +(devices) 5078 3640 w +(given.) 720 3770 w +(Then) 1135 3770 w +(it) 1460 3770 w +(issues) 1590 3770 w +(a) 1977 3770 w +(raw) 2095 3770 w +(ATA) 2343 3770 w +(request) 2621 3770 w +(for) 3081 3770 w +(the) 3291 3770 w +(device) 3519 3770 w +(signature.) 3914 3770 w +(If) 4542 3770 w +(that) 4672 3770 w +(fails,) 4940 3770 w +(it) 5254 3770 w +(is) 5384 3770 w +(assumed) 720 3900 w +(that) 1262 3900 w +(the) 1541 3900 w +(drive) 1780 3900 w +(is) 2113 3900 w +(SCSI,) 2270 3900 w +(and) 2600 3900 w +(a) 2867 3900 w +(raw) 2997 3900 w +(SCSI) 3257 3900 w +(request) 3552 3900 w +(is) 4024 3900 w +(issued.) 4181 3900 w +(In) 4663 3900 w +(both) 4832 3900 w +(cases,) 5146 3900 w +11 /LucidaSans-Italic f +(disk/smart) 720 4030 w +11 /LucidaSansUnicode00 f +(is able) 1343 4030 w +(to reliably determine) 1725 4030 w +(if) 2871 4030 w +(SMART is supported and can be) 2979 4030 w +(enabled.) 4705 4030 w +(If) 720 4200 w +(successful,) 829 4200 w +(each) 1452 4200 w +(device) 1736 4200 w +(is) 2111 4200 w +(probed) 2236 4200 w +(every) 2654 4200 w +(5) 2974 4200 w +(minutes) 3080 4200 w +(and) 3546 4200 w +(failures) 3781 4200 w +(are) 4215 4200 w +(logged.) 4420 4200 w +(A) 4893 4200 w +(one) 5006 4200 w +(shot) 5240 4200 w +(mode) 720 4330 w +(is also available:) 1055 4330 w +9 /LucidaTypewriter f +(chula#) 940 4500 w +(disk/smart) 1395 4500 w +(-atv) 2110 4500 w +(sda0:) 940 4610 w +(normal) 1330 4610 w +(sda1:) 940 4720 w +(normal) 1330 4720 w +(sda2:) 940 4830 w +(normal) 1330 4830 w +(sda3:) 940 4940 w +(threshold) 1330 4940 w +(exceeded) 1980 4940 w +(sdE1:) 940 5050 w +(normal) 1330 5050 w +(sdF7:) 940 5160 w +(normal) 1330 5160 w +11 /LucidaSansUnicode00 f +(Drives) 720 5390 w +11 /LucidaTypewriter f +(sda0) 1095 5390 w +11 /LucidaSansUnicode00 f +(,) 1411 5390 w +11 /LucidaTypewriter f +(sda1) 1486 5390 w +11 /LucidaSansUnicode00 f +(are) 1842 5390 w +(SCSI) 2050 5390 w +(and) 2316 5390 w +(the) 2555 5390 w +(remainder) 2767 5390 w +(are) 3354 5390 w +(ATA.) 3563 5390 w +(Note) 3895 5390 w +(that) 4187 5390 w +(other) 4439 5390 w +(drives) 4763 5390 w +(on) 5125 5390 w +(the) 5301 5390 w +(same) 720 5520 w +(controller are) 1036 5520 w +(ATA.) 1789 5520 w +(Recalling that) 2115 5520 w +11 /LucidaTypewriter f +(sdC0) 2876 5520 w +11 /LucidaSansUnicode00 f +(was previously listed, we) 3227 5520 w +(can check) 4588 5520 w +(to see) 5149 5520 w +(why no results were) 720 5650 w +(reported by) 1819 5650 w +11 /LucidaTypewriter f +(sdC0) 2475 5650 w +11 /LucidaSansUnicode00 f +(:) 2791 5650 w +9 /LucidaTypewriter f +(chula#) 940 5820 w +(for\(i) 1395 5820 w +(in) 1785 5820 w +(a3) 1980 5820 w +(C0\)) 2175 5820 w +(echo) 1200 5930 w +(identify) 1525 5930 w +(device) 2110 5930 w +(|) 2565 5930 w +(atazz) 1460 6040 w +(/dev/sd$i) 1850 6040 w +(>[2]/dev/null) 2500 6040 w +(|) 3410 6040 w +(grep) 1460 6150 w +('^flags') 1785 6150 w +(flags) 940 6260 w +(lba) 1460 6260 w +(llba) 1720 6260 w +(smart) 2045 6260 w +(power) 2435 6260 w +(nop) 2825 6260 w +(sct) 3085 6260 w +(flags) 940 6370 w +(lba) 1460 6370 w +11 /LucidaSansUnicode00 f +(So we) 720 6560 w +(see) 1063 6560 w +(that) 1278 6560 w +11 /LucidaTypewriter f +(sdC0) 1524 6560 w +11 /LucidaSansUnicode00 f +(simply does not) 1875 6560 w +(support) 2758 6560 w +(the) 3208 6560 w +(SMART feature) 3414 6560 w +(set.) 4232 6560 w +cleartomark +showpage +saveobj restore +%%EndPage: 5 5 +%%Page: 6 6 +/saveobj save def +mark +6 pagesetup +11 /LucidaSans-Demi f +(Further) 720 850 w +(Work) 1174 850 w +11 /LucidaSansUnicode00 f +(While) 720 1020 w +(the) 1047 1020 w +(raw) 1256 1020 w +(ATA) 1485 1020 w +(interface) 1744 1020 w +(has) 2250 1020 w +(been) 2473 1020 w +(used) 2772 1020 w +(extensively) 3065 1020 w +(from) 3699 1020 w +(user) 3992 1020 w +(space) 4261 1020 w +(and) 4603 1020 w +(has) 4840 1020 w +(allowed) 5064 1020 w +(the) 720 1150 w +(removal) 928 1150 w +(of) 1391 1150 w +(quirky) 1536 1150 w +(functionality,) 1908 1150 w +(device) 2644 1150 w +(setup) 3019 1150 w +(has) 3352 1150 w +(not) 3574 1150 w +(yet) 3787 1150 w +(been) 3984 1150 w +(addressed.) 4282 1150 w +(For) 4937 1150 w +(exam\255) 5144 1150 w +(ple,) 720 1280 w +(both) 960 1280 w +(the) 1247 1280 w +(Orion) 1460 1280 w +(and) 1800 1280 w +(AHCI) 2040 1280 w +(drivers) 2347 1280 w +(have) 2755 1280 w +(an) 3045 1280 w +(initialization) 3216 1280 w +(routine) 3920 1280 w +(similar) 4345 1280 w +(to) 4747 1280 w +(the) 4898 1280 w +(follow\255) 5112 1280 w +(ing) 720 1410 w +9 /LucidaTypewriter f +(newdrive\(Drive) 940 1580 w +(*d\)) 1915 1580 w +({) 940 1690 w +(setfissig\(d,) 1200 1800 w +(getsig\(d\)\);) 2045 1800 w +(if\(identify\(d\)) 1200 1910 w +(!=) 2175 1910 w +(0\)) 2370 1910 w +(return) 1460 2020 w +(SDeio;) 1915 2020 w +(setpowermode\(d\);) 1200 2130 w +(if\(settxmode\(d,) 1200 2240 w +(d->udma\)) 2240 2240 w +(!=) 2825 2240 w +(0\)) 3020 2240 w +(return) 1460 2350 w +(SDeio;) 1915 2350 w +(return) 1200 2460 w +(SDok;) 1655 2460 w +(}) 940 2570 w +11 /LucidaSansUnicode00 f +(However) 720 2760 w +(in) 1228 2760 w +(preparing) 1377 2760 w +(this) 1945 2760 w +(document,) 2191 2760 w +(it) 2808 2760 w +(was) 2930 2760 w +(discovered) 3181 2760 w +(that) 3805 2760 w +(one) 4065 2760 w +(sets) 4311 2760 w +(the) 4575 2760 w +(power) 4795 2760 w +(mode) 5172 2760 w +(before) 720 2890 w +(setting) 1115 2890 w +(the) 1532 2890 w +(transfer) 1752 2890 w +(mode) 2220 2890 w +(and) 2569 2890 w +(the) 2816 2890 w +(other) 3036 2890 w +(does) 3368 2890 w +(the) 3671 2890 w +(opposite.) 3891 2890 w +(It) 4473 2890 w +(is) 4595 2890 w +(not) 4732 2890 w +(clear) 4957 2890 w +(that) 5261 2890 w +(this) 720 3020 w +(particular) 953 3020 w +(difference) 1500 3020 w +(is) 2075 3020 w +(a) 2200 3020 w +(problem,) 2298 3020 w +(but) 2816 3020 w +(over) 3031 3020 w +(time,) 3299 3020 w +(such) 3608 3020 w +(differences) 3893 3020 w +(will) 4524 3020 w +(be) 4742 3020 w +(the) 4910 3020 w +(source) 5118 3020 w +(of) 720 3150 w +(bugs.) 890 3150 w +(Neither) 1283 3150 w +(the) 1736 3150 w +(IDE) 1969 3150 w +(nor) 2205 3150 w +(the) 2447 3150 w +(Marvell) 2680 3150 w +(50xx) 3126 3150 w +(drivers) 3460 3150 w +(sets) 3888 3150 w +(the) 4165 3150 w +(power) 4398 3150 w +(mode) 4788 3150 w +(at) 5149 3150 w +(all.) 5312 3150 w +(Worse,) 720 3280 w +(none) 1122 3280 w +(is) 1429 3280 w +(capable) 1560 3280 w +(of) 2013 3280 w +(properly) 2164 3280 w +(addressing) 2653 3280 w +(drives) 3282 3280 w +(with) 3646 3280 w +(features) 3915 3280 w +(such) 4394 3280 w +(as) 4685 3280 w +(PUIS) 4845 3280 w +(\(Power) 5116 3280 w +(Up) 720 3410 w +(In) 916 3410 w +(Standby\)) 1067 3410 w +(enabled.) 1578 3410 w +(To) 2122 3410 w +(addresses) 2309 3410 w +(this) 2896 3410 w +(problem) 3143 3410 w +(all) 3639 3410 w +(four) 3814 3410 w +(of) 4085 3410 w +(the) 4243 3410 w +(ATA) 4464 3410 w +(drivers) 4735 3410 w +(would) 5151 3410 w +(need to be) 720 3540 w +(changed.) 1325 3540 w +(Rather) 720 3710 w +(than) 1104 3710 w +(maintaining) 1380 3710 w +(a) 2052 3710 w +(number) 2152 3710 w +(of) 2605 3710 w +(mutually) 2752 3710 w +(out-of-date) 3252 3710 w +(drivers,) 3936 3710 w +(it) 4376 3710 w +(would) 4488 3710 w +(be) 4848 3710 w +(advanta\255) 5018 3710 w +(geous) 720 3840 w +(to) 1081 3840 w +(build) 1229 3840 w +(an) 1539 3840 w +(ATA) 1708 3840 w +(analog) 1968 3840 w +(of) 2364 3840 w +11 /LucidaTypewriter f +(pc/sdscsi.c) 2511 3840 w +11 /LucidaSansUnicode00 f +(using) 3419 3840 w +(the) 3750 3840 w +(raw) 3960 3840 w +(ATA) 4190 3840 w +(interface) 4450 3840 w +(to) 4957 3840 w +(submit) 5104 3840 w +(ATA) 720 3970 w +(commands.) 987 3970 w +(There) 1684 3970 w +(are) 2036 3970 w +(some) 2250 3970 w +(difficulties) 2583 3970 w +(that) 3191 3970 w +(make) 3448 3970 w +(such) 3783 3970 w +(a) 4077 3970 w +(change) 4184 3970 w +(a) 4614 3970 w +(bit) 4722 3970 w +(more) 4911 3970 w +(than) 5234 3970 w +(trivial.) 720 4100 w +(Since) 1139 4100 w +(current) 1465 4100 w +(model) 1899 4100 w +(for) 2279 4100 w +(hot-pluggable) 2480 4100 w +(devices) 3297 4100 w +(is) 3739 4100 w +(not) 3875 4100 w +(compatible) 4099 4100 w +(with) 4738 4100 w +(the) 5012 4100 w +(top-) 5231 4100 w +(down approach currently taken by) 720 4230 w +11 /LucidaSans-Italic f +(sd) 2576 4230 w +11 /LucidaSansUnicode00 f +(this would need to be) 2732 4230 w +(addressed.) 3925 4230 w +(It) 4579 4230 w +(does) 4688 4230 w +(not) 4978 4230 w +(seem) 5190 4230 w +(that) 720 4360 w +(this) 997 4360 w +(would) 1260 4360 w +(be) 1647 4360 w +(difficult.) 1844 4360 w +(Interface) 2392 4360 w +(resets) 2925 4360 w +(after) 3312 4360 w +(failed) 3627 4360 w +(commands) 3989 4360 w +(should) 4635 4360 w +(also) 5060 4360 w +(be) 5341 4360 w +(addressed.) 720 4490 w +11 /LucidaSans-Demi f +(Source) 720 4750 w +11 /LucidaSansUnicode00 f +(The) 720 4920 w +(current) 962 4920 w +(source) 1390 4920 w +(including) 1787 4920 w +(all) 2323 4920 w +(the) 2491 4920 w +(pc) 2705 4920 w +(drivers) 2874 4920 w +(and) 3284 4920 w +(applications) 3526 4920 w +(are) 4214 4920 w +(available) 4426 4920 w +(in) 4937 4920 w +(the) 5081 4920 w +(fol\255) 5296 4920 w +(lowing) 720 5050 w +11 /LucidaSans-Italic f +(contrib) 1107 5050 w +11 /LucidaSansUnicode00 f +(\(1\) packages on) 1487 5050 w +11 /LucidaSans-Italic f +(sources) 2365 5050 w +11 /LucidaSansUnicode00 f +(:) 2770 5050 w +11 /LucidaTypewriter f +(quanstro/fis) 720 5180 w +11 /LucidaSansUnicode00 f +(,) 1668 5180 w +11 /LucidaTypewriter f +(quanstro/sd) 720 5310 w +11 /LucidaSansUnicode00 f +(,) 1589 5310 w +11 /LucidaTypewriter f +(quanstro/atazz) 720 5440 w +11 /LucidaSansUnicode00 f +(, and) 1826 5440 w +11 /LucidaTypewriter f +(quanstro/smart) 720 5570 w +11 /LucidaSansUnicode00 f +(.) 1826 5570 w +(The) 720 5740 w +(following manual) 954 5740 w +(pages are) 1908 5740 w +(included:) 2462 5740 w +11 /LucidaSans-Italic f +(fis) 720 5870 w +11 /LucidaSansUnicode00 f +(\(2\),) 848 5870 w +11 /LucidaSans-Italic f +(sd) 1059 5870 w +11 /LucidaSansUnicode00 f +(\(3\),) 1180 5870 w +11 /LucidaSans-Italic f +(sdahci) 1391 5870 w +11 /LucidaSansUnicode00 f +(\(3\),) 1734 5870 w +11 /LucidaSans-Italic f +(sdaoe) 1945 5870 w +11 /LucidaSansUnicode00 f +(\(3\),) 2254 5870 w +11 /LucidaSans-Italic f +(sdloop) 2465 5870 w +11 /LucidaSansUnicode00 f +(\(3\),) 2811 5870 w +11 /LucidaSans-Italic f +(sdorion) 3022 5870 w +11 /LucidaSansUnicode00 f +(\(3\),) 3422 5870 w +11 /LucidaSans-Italic f +(atazz) 3633 5870 w +11 /LucidaSansUnicode00 f +(\(8\), and) 3927 5870 w +11 /LucidaSans-Italic f +(smart) 4371 5870 w +11 /LucidaSansUnicode00 f +(\(8\).) 4689 5870 w +11 /LucidaSans-Demi f +(Abbreviated) 720 6130 w +(References) 1446 6130 w +11 /LucidaSansUnicode00 f +([1]) 720 6300 w +11 /LucidaSans-Italic f +(sd) 995 6300 w +11 /LucidaSansUnicode00 f +(\(1\), published online) 1116 6300 w +(at) 2251 6300 w +11 /LucidaTypewriter f +(http://plan9.bell-labs.com/magic/man2html/3/sd) 995 6430 w +11 /LucidaSansUnicode00 f +(.) 4629 6430 w +([2]) 720 6600 w +11 /LucidaSans-Italic f +(scuzz) 995 6600 w +11 /LucidaSansUnicode00 f +(\(8\), published online) 1290 6600 w +(at) 2425 6600 w +11 /LucidaTypewriter f +(http://plan9.bell-labs.com/magic/man2html/8/scuzz) 995 6730 w +11 /LucidaSansUnicode00 f +(.) 4866 6730 w +([3]) 720 6900 w +(T13) 995 6900 w +11 /LucidaSans-Italic f +(ATA/ATAPI) 1239 6900 w +(Command) 1865 6900 w +(Set ) 2446 6900 w +11 /LucidaSansUnicode20 f +(\023) 2642 6900 w +11 /LucidaSans-Italic f +(2) 2732 6900 w +11 /LucidaSansUnicode00 f +(,) 2801 6900 w +(revision) 2873 6900 w +(1,) 3329 6900 w +(January) 3470 6900 w +(21,) 3901 6900 w +(2009,) 4111 6900 w +(formerly) 4459 6900 w +(published) 4947 6900 w +(online) 995 7030 w +(at) 1359 7030 w +11 /LucidaTypewriter f +(http://www.t13.org) 1496 7030 w +11 /LucidaSansUnicode00 f +(.) 2918 7030 w +([4]) 720 7200 w +(T10) 995 7200 w +11 /LucidaSans-Italic f +(SCSI/ATA) 1268 7200 w +(Translation ) 1836 7200 w +11 /LucidaSansUnicode20 f +(\023) 2485 7200 w +11 /LucidaSans-Italic f +(2) 2575 7200 w +(\(SAT) 2710 7200 w +11 /LucidaSansUnicode20 f +(\023) 2951 7200 w +11 /LucidaSans-Italic f +(2\)) 3006 7200 w +11 /LucidaSansUnicode00 f +(,) 3111 7200 w +(revision) 3213 7200 w +(7,) 3699 7200 w +(February) 3870 7200 w +(18,) 4403 7200 w +(2007,) 4643 7200 w +(formerly) 5021 7200 w +cleartomark +showpage +saveobj restore +%%EndPage: 6 6 +%%Page: 7 7 +/saveobj save def +mark +7 pagesetup +11 /LucidaSansUnicode00 f +(published online) 995 850 w +(at) 1919 850 w +11 /LucidaTypewriter f +(http://www.t10.org) 2056 850 w +11 /LucidaSansUnicode00 f +(.) 3478 850 w +cleartomark +showpage +saveobj restore +%%EndPage: 7 7 +%%Trailer +done +%%DocumentFonts: LucidaSansUnicode20 LucidaSansUnicode00 LucidaSans-Demi LucidaSans-Italic LucidaTypewriter +%%Pages: 7 diff --git a/sys/src/cmd/atazz/bit.c b/sys/src/cmd/atazz/bit.c new file mode 100644 index 000000000..9e1f39352 --- /dev/null +++ b/sys/src/cmd/atazz/bit.c @@ -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; +} diff --git a/sys/src/cmd/atazz/macros.ms b/sys/src/cmd/atazz/macros.ms new file mode 100644 index 000000000..330626da3 --- /dev/null +++ b/sys/src/cmd/atazz/macros.ms @@ -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 diff --git a/sys/src/cmd/atazz/main.c b/sys/src/cmd/atazz/main.c new file mode 100644 index 000000000..0d0565eaf --- /dev/null +++ b/sys/src/cmd/atazz/main.c @@ -0,0 +1,1928 @@ +#include <u.h> +#include <libc.h> +#include <fis.h> +#include "atazz.h" +#include "tabs.h" + +#pragma varargck argpos eprint 1 +#pragma varargck type "π" char** + +enum { + Dontread = -2, +}; + +int interrupted; +int rflag; +int squelch; +int scttrace; +uchar issuetr[0x100]; + +Atatab *idcmd; +Atatab *idpktcmd; +Atatab *sigcmd; +Atatab *sctread; +Atatab *sctissue; + +int +πfmt(Fmt *f) +{ + char **p; + + p = va_arg(f->args, char**); + if(p == nil) + return fmtstrcpy(f, "<nil**>"); + for(; *p; p++){ + fmtstrcpy(f, *p); + if(p[1] != nil) + fmtstrcpy(f, " "); + } + return 0; +} + +int +eprint(char *fmt, ...) +{ + int n; + va_list args; + + if(squelch) + return 0; +// Bflush(&out); + + va_start(args, fmt); + n = vfprint(2, fmt, args); + va_end(args); + return n; +} + +void +fisset(Req *r, uint i, uint v) +{ + if(r->fisbits & 1<<i) + return; + r->fisbits |= 1<<i; + r->cmd.fis[i] = v; +} + +void +prreq(Req *r) +{ + uchar *u; + + print("%.2ux %.2ux\n", r->cmd.sdcmd, r->cmd.ataproto); + u = r->cmd.fis; + print("%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux ", + u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7]); + u += 8; + print("%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux\n", + u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7]); +} + +char* +protostr(char *p, char *e, int pr) +{ + char *s; + + *p = 0; + if(pr & P28) + p = seprint(p, e, "28:"); + else + p = seprint(p, e, "28:"); + switch(pr & Pprotom){ + default: + s = "unk"; + break; + case Ppkt: + s = "pkt"; + break; + case Pdiag: + s = "dig"; + break; + case Preset: + s = "rst"; + break; + case Pdmq: + s = "dmq"; + break; + case Pdma: + s = "dma"; + break; + case Ppio: + s = "pio"; + break; + } + p = seprint(p, e, "%s:", s); + switch(pr & Pdatam){ + default: + s = "nd"; + break; + case Pin: + s = "in"; + break; + case Pout: + s = "out"; + break; + } + p = seprint(p, e, "%s", s); + return p; +} + +void +displaycmd(Req *r, Atatab *a) +{ + char buf[32]; + int i; + + if(a->cc > nelem(issuetr) || !issuetr[a->cc]) + return; + protostr(buf, buf + sizeof buf, a->protocol); + fprint(2, "cmd %s:%2ux ", buf, a->cc); + for(i = 0; i < 16; i++) + fprint(2, "%.2ux", r->cmd.fis[i]); + fprint(2, "\n"); +} + +int +issueata(Req *r, Atatab *a, Dev *d) +{ + uchar u; + int n, ok, pr, rv; + + r->haverfis = 0; + pr = a->protocol & Pdatam; + r->data = realloc(r->data, r->count); + if(r->data == nil && r->count > 0) + sysfatal("realloc: %r"); + if(r->data == nil && pr != Pnd) + sysfatal("no data for cmd %.2ux", a->cc); + if(0 && r->fisbits) + print("fisbits %.16b\n", r->fisbits); + r->cmd.sdcmd = 0xff; + r->cmd.ataproto = a->protocol; + if(a->cc & 0xff00) + fisset(r, 0, a->cc >> 8); + else + fisset(r, 0, H2dev); + fisset(r, 1, Fiscmd); + fisset(r, 2, a->cc); + switch(pr){ + case Pout: + if(r->rfd != Dontread){ + n = readn(r->rfd, r->data, r->count); + if(n != r->count){ + if(n == -1) + eprint("!short src read %r\n"); + else + eprint("!short src read %d wanted %lld\n", n, r->count); + return -1; + } + } + case Pnd: + case Pin: + if(0 && (d->feat & Dlba) == 0 && (d->c | d->h | d->s)){ + int c, h, s; + c = r->lba / (d->s * d->h); + h = (r->lba / d->s) % d->h; + s = (r->lba % d->s) + 1; +print("%d %d %d\n", c, h, s); + fisset(r, 4, s); + fisset(r, 5, c); + fisset(r, 6, c >> 8); + fisset(r, 7, Ataobs | h); + }else{ + fisset(r, 4, r->lba); + fisset(r, 5, r->lba >> 8); + fisset(r, 6, r->lba >> 16); + u = Ataobs; + if(pr == Pin || pr == Pout) + u |= Atalba; + if((d->feat & Dllba) == 0) + u |= (r->lba >> 24) & 7; + fisset(r, 7, u); + fisset(r, 8, r->lba >> 24); + fisset(r, 9, r->lba >> 32); + fisset(r, 10, r->lba >> 48); + } + fisset(r, 12, r->nsect); + fisset(r, 13, r->nsect >> 8); + break; + } + fisset(r, 7, Ataobs); + displaycmd(r, a); + if(write(d->fd, &r->cmd, Cmdsz) != Cmdsz){ + eprint("fis write error: %r\n"); + return -1; + } + + werrstr(""); + switch(pr){ + default: + ok = read(d->fd, "", 0) == 0; + break; + case Pin: + ok = read(d->fd, r->data, r->count) == r->count; + r->lba += r->nsect; + break; + case Pout: + ok = write(d->fd, r->data, r->count) == r->count; + r->lba += r->nsect; + break; + } + rv = 0; + if(ok == 0){ + eprint("xfer error: %.2ux %r\n", a->cc); + rv = -1; + } + switch(n = read(d->fd, &r->reply, Replysz)){ + case Replysz: + r->haverfis = 1; + return rv; + case -1: + eprint("status fis read error: %r\n"); + return -1; + default: + eprint("status fis read error: short read: %d of %d\n", n, Replysz); + return -1; + } +} + +/* + * cheezy code; just issue a inquiry. use scuzz + * for real work with atapi devices + */ +int +issuepkt(Req *r, Atatab *a, Dev *d) +{ + char *p; + uchar *u; + int n, rv; + + r->haverfis = 0; + r->count = 128; + r->data = realloc(r->data, r->count); + if(r->data == nil && r->count > 0) + sysfatal("realloc: %r"); + r->cmd.sdcmd = 0xff; + r->cmd.ataproto = a->protocol; + memset(r->cmd.fis, 0, Fissize); + + u = r->cmd.fis; + u[0] = 0x12; + u[4] = 128-1; + displaycmd(r, a); + + if(write(d->fd, &r->cmd, 6 + 2) != 6 + 2){ + eprint("fis write error: %r\n"); + return -1; + } + n = read(d->fd, r->data, r->count); + rv = 0; + if(n == -1){ + eprint("xfer error: %.2ux %r\n", a->cc); + rv = -1; + } + + print("n is %d (%lld)\n", n, r->count); + if(n > 32){ + p = (char*)r->data; + print("%.8s %.16s\n", p + 8, p + 16); + } + + u = (uchar*)&r->reply; + n = read(d->fd, u, Replysz); + if(n < 0){ + eprint("status fis read error (%d): %r\n", n); + return -1; + } + + if(n < Replysz) + memset(u + n, 0, Replysz - n); + r->haverfis = 1; + return rv; +} + +/* + * silly protocol: + * 1. use write log ext 0xe0 to fill out the command + * 2. use write log ext 0xe1 to write or data (if any) + * 3. use read log ext 0xe0 to nab status. polled + */ +void +sctreq(Req *r) +{ + memset(r, 0, sizeof *r); + r->rfd = Dontread; +} + +char* +sctrsp(Req *r) +{ + uint i; + static char buf[32]; + + if(!r->haverfis) + return "no rfis"; + if((r->reply.fis[Frerror] & (Eidnf | Eabrt)) == 0) + return nil; + i = r->reply.fis[Fsc] | r->reply.fis[Flba0]<<8; + if(i == 0xffff) + return "in progress"; + else if(i == 0){ + snprint(buf, sizeof buf, "unknown %.2ux", r->reply.fis[Frerror]); + return buf; + }else if(i < nelem(sctetab)) + return sctetab[i]; + else + return "<bad>"; +} + +char* +sctready(Dev *d, int sec) +{ + char *s; + int i; + Req r; + static char e[ERRMAX]; + + for(;;){ + if(interrupted){ + s = "interrupted"; + break; + } + sctreq(&r); + fisset(&r, Fsc, 1); + fisset(&r, Flba0, 0xe0); + r.count = 512; + i = issueata(&r, sctread, d); + free(r.data); + if(i == -1){ + rerrstr(e, ERRMAX); + s = e; + break; + } + if((r.cmd.fis[Fsc] | r.cmd.fis[Fsc8]<<8) != 0xffff){ + s = sctrsp(&r); + break; + } + if(sec == 0){ + s = "timeout"; + break; + } + sleep(1000); + sec--; + } + return s; +} + +typedef struct Sttab Sttab; +struct Sttab { + int o; + int sz; + char *name; +}; + +Sttab sctt[] = { + 0, 2, "version", + 2, 2, "period", + 4, 2, "intval", + 6, 1, "max op", + 7, 1, "max", + 8, 1, "min op", + 9, 1, "min", +}; + +void +sctttab(Req *r) +{ + char c, buf[10]; + int i, n, l, d; + uchar *u; + + u = r->data; + for(i = 0; i < nelem(sctt); i++){ + switch(sctt[i].sz){ + case 1: + c = u[sctt[i].o]; + print("%s\t%d\n", sctt[i].name, c); + break; + case 2: + d = w(u + sctt[i].o); + print("%s\t%ud\n", sctt[i].name, d); + break; + } + } + n = w(u + 30); + l = w(u + 32); + for(i = 0; i < n; i++){ + c = u[34 + (l + i) % n]; + if((uchar)c == 0x80) + snprint(buf, sizeof buf, "xx"); + else + snprint(buf, sizeof buf, "%d", c); + d = i%10; + if(d == 0) + print("\nt%d\t%d", i, c); + else + print("% .2d", c); + } + if(i%10) + print("\n"); +} + +static struct { + uint code; + char *s; + char *ms; +} fxtab[] = { + 0x00010001, "set features", 0, + 0x00010002, "enabled", 0, + 0x00010003, "disabled", 0, + + 0x00020001, "enabled", 0, + 0x00020002, "disabled", 0, + + 0x0003ffff, "minute", "minutes", +}; + +void +sctfcout(ushort *u, Req *r) +{ + uchar *f; + ushort v; + uint c, m, i; + + f = r->reply.fis; + switch(u[1]){ + case 1: + case 2: + v = f[Fsc] | f[Flba0]<<8; + c = u[2]<<16 | v; + m = u[2]<<16 | 0xffff; + for(i = 0; i < nelem(fxtab); i++) + if(fxtab[i].code == c) + print("%s\n", fxtab[i].s); + else if(fxtab[i].code == m) + print("%d %s\n", v, v>1? fxtab[i].ms: fxtab[i].s); + break; + case 3: + v = f[Fsc] | f[Flba0]<<8; + if(v & 1) + print("preserve\n"); + else + print("volatile\n"); + break; + } +} + +void +scterout(ushort *u, Req *r) +{ + uchar *f; + uint v; + + f = r->reply.fis; + switch(u[1]){ + case 2: + v = f[Fsc] | f[Flba0]<<8; + v *= 100; + print("%dms\n", v); + } +} + +void +sctout(ushort *u, Req *r) +{ + switch(u[0]){ + case 5: + sctttab(r); + break; + case 4: + sctfcout(u, r); + break; + case 3: + scterout(u, r); + break; + } +} + +int +issuesct0(Req *r0, Atatab *a, Dev *d) +{ + char *s; + uchar proto; + Atatab *txa; + Req r; + + if((d->feat & Dsct) == 0){ + eprint("sct not supported\n"); + return -1; + } + + /* 1. issue command */ + sctreq(&r); + r.data = malloc(r0->count); + memcpy(r.data, r0->data, r0->count); + r.count = r0->count; + fisset(&r, Fsc, 1); + fisset(&r, Flba0, 0xe0); + if(issueata(&r, sctissue, d) == -1) + return -1; + if(s = sctrsp(&r)){ + eprint("sct error: %s\n", s); + return -1; + } + + /* 1a. check response */ + if((s = sctready(d, 1)) != nil){ + eprint("sct cmd: %s\n", s); + return -1; + } + /* 2. transfer data */ + + proto = a->protocol; + if(r0->fisbits & 1 << 16){ + proto &= ~Pdatam; + proto |= r0->cmd.ataproto; + } + switch(proto & Pdatam){ + default: + txa = nil; + break; + case Pin: + txa = sctread; + break; +/* case Pout: + txa = sctout; + break; +*/ + } + + if(txa != nil){ + sctreq(&r); + r.count = 512; + fisset(&r, Fsc, 1); + fisset(&r, Flba0, 0xe1); + if(issueata(&r, txa, d) == -1) + return -1; + + /* 2a. check response */ + if((s = sctready(d, 1)) != nil){ + eprint("sct cmd: %s\n", s); + return -1; + } + } + + sctout((ushort*)r0->data, &r); + free(r.data); + return 0; +} + +static void* +pushtrace(int i) +{ + void *tr0; + + tr0 = malloc(sizeof issuetr); + if(tr0 == 0) + return 0; + memcpy(tr0, issuetr, sizeof issuetr); + memset(issuetr, i, sizeof issuetr); + return tr0; +} + +static void +poptrace(void *tr0) +{ + if(tr0 == nil) + return; + memcpy(issuetr, tr0, sizeof issuetr); + free(tr0); +} + +int +issuesct(Req *r0, Atatab *a, Dev *d) +{ + int r; + void *t; + + t = nil; + if(scttrace) + t = pushtrace(1); + r = issuesct0(r0, a, d); + if(scttrace) + poptrace(t); + return r; +} + +int +issue(Req *r, Atatab *a, Dev *d) +{ + int rv; + int (*f)(Req*, Atatab*, Dev*); + + if(a->protocol & Psct) + f = issuesct; + else if((a->protocol & Pprotom) == Ppkt) + f = issuepkt; + else + f = issueata; + rv = f(r, a, d); + if(r->haverfis) + if(r->reply.fis[Fstatus] & ASerr){ + werrstr("ata error"); + rv = -1; + } + return rv; +} + +void +sigfmt(Req *r) +{ + print("%.8ux\n", fistosig(r->reply.fis)); +} + +int +opendev(char *dev, Dev *d) +{ + char buf[128]; + int rv; + ushort *u; + Req r; + + if(d->fd != -1) + close(d->fd); + memset(d, 0, sizeof *d); + snprint(buf, sizeof buf, "%s/raw", dev); + d->fd = open(buf, ORDWR); + if(d->fd == -1) + return -1; + memset(&r, 0, sizeof r); + if(issue(&r, sigcmd, d) == -1){ +lose: + close(d->fd); + return -1; + } + setfissig(d, fistosig(r.reply.fis)); + memset(&r, 0, sizeof r); + r.count = 512; + r.nsect = 1; + if(d->sig>>16 == 0xeb14) + rv = issue(&r, idpktcmd, d); + else + rv = issue(&r, idcmd, d); + if(rv == -1) + goto lose; + u = (ushort*)r.data; + d->nsect = idfeat(d, u); + d->secsize = idss(d, u); + d->wwn = idwwn(d, u); + return 0; +} + +void +rawout(Req *r) +{ + int n; + + n = write(r->wfd, r->data, r->count); + if(n != r->count) + eprint("!short write %ud wanted %lld\n", n, r->count); +} + +static ushort +gbit16(void *a) +{ + ushort j; + uchar *i; + + i = a; + j = i[1] << 8; + j |= i[0]; + return j; +} + +static Btab extra[] = { + 12, "ncqpri", + 11, "ncqunload", + 10, "phyevent", + 9, "hpwrctl", + 3, "6.0gbit", + 2, "3.0gbit", + 1, "1.5gbit", +}; + +static Btab suptab[] = { + 8, "wwn", + 5, "mediaserial", + 1, "smartst", + 0, "smartlog" +}; + +char* +pextraid(char *p, char *e, ushort *id, uint *medserial) +{ + char *p0; + ushort u; + + *p = 0; + *medserial = 0; + p0 = p; + p = sebtab(p, e, extra, nelem(extra), gbit16(id + 76)); + if(p != p0) + p = seprint(p, e, " "); + u = gbit16(id + 83); + if(u & 1<<5) + p = seprint(p, e, "gpl "); + p0 = p; + p = sebtab(p, e, suptab, nelem(suptab), gbit16(id + 84)); + if(p != p0) + p = seprint(p, e, " "); + u = gbit16(id + 120); + if(u & 1<<2) + p = seprint(p, e, "wunc "); + return p; +} + +static char *patatab[] = { + "ata8-apt", + "ata/atapi-7", +}; + +static char *satatab[] = { + "ata8-ast", + "sata1.0a", + "sataiiext", + "sata2.5", + "sata2.6", + "sata3.0", +}; + +char* +ptransport(char *p, char *e, ushort *id) +{ + char *s; + ushort u, i; + + u = gbit16(id + 222); + if(u == 0 || u == 0xffff) + return seprint(p, e, "unreported "); + i = (u>>5) & 0x7f; + switch(u & 7<<12){ + default: + s = "unktransport"; + break; + case 0: + s = "unkparallel"; + if(i < nelem(patatab)) + s = patatab[i]; + break; + case 1<<12: + s = "unkserial"; + if(i < nelem(satatab)) + s = satatab[i]; + break; + } + return seprint(p, e, "%s ", s); +} + +Btab entab[] = { + 10, "hpa", + 9, "reset", + 8, "service", + 7, "release", + 6, "rdlookahd", + 5, "vwc", + 4, "packet", + 3, "pm", + 2, "security", + 1, "smart", +}; + +Btab addlen[] = { + 15, "cfast", +// 14, "trim", /* check 169 */ + 13, "lpsalignerr", + 12, "iddma", + 11, "rbufdma", + 10, "wbufdma", + 9, "pwddma", + 8, "dlmcdma", +}; + +char* +penabled(char *p, char *e, ushort *id) +{ + char *p0; + ushort u; + + p0 = p; + p = sebtab(p, e, addlen, nelem(addlen), gbit16(id + 69)); + u = gbit16(id + 87); + if(u>>14 == 1){ + if(p != p0) + p = seprint(p, e, " "); + p = sebtab(p, e, entab, nelem(entab), gbit16(id + 85)); + } + return p; +} + +static char *fftab[] = { + nil, + "5¼", + "3½", + "2½", + "1.8", + "<1.8", +}; + +char* +pff(char *p, char *e, ushort *id) +{ + char *p0; + ushort u; + + p0 = p; + u = gbit16(id + 168); + if(u < nelem(fftab) && fftab[u] != nil) + p = seprint(p, e, "%s ", fftab[u]); + u = gbit16(id + 217); + if(u == 1) + p = seprint(p, e, "solid-state "); + else if(u != 0 && u != 0xfffe) + p = seprint(p, e, "%udrpm ", u); + if(p != p0) + p--; + *p = 0; + return p; +} + +Btab scttab[] = { + 5, "tables", + 4, "feactl", + 3, "errctl", + 2, "wsame", + 1, "rwlong", + 0, "sct", +}; + +char* +psct(char *p, char *e, ushort *id) +{ + return sebtab(p, e, scttab, nelem(scttab), gbit16(id + 206)); +} + +void +idfmt(Req *r) +{ + char buf[100]; + uint ss, i; + ushort *id; + uvlong nsect; + Sfis f; + + if(r->fmtrw == 0){ + rawout(r); + return; + } + id = (ushort*)r->data; + nsect = idfeat(&f, id); + ss = idss(&f, id); + + idmove(buf, id+10, 20); + print("serial\t%s\n", buf); + idmove(buf, id+23, 8); + print("firm\t%s\n", buf); + idmove(buf, id+27, 40); + print("model\t%s\n", buf); + print("wwn\t%ullx\n", idwwn(&f, id)); + pflag(buf, buf + sizeof buf, &f); + print("flags\t%s", buf); + print("geometry %llud %ud", nsect, ss); + if(f.c | f.h | f.s) + print(" %ud %ud %ud", f.c, f.h, f.s); + print("\n"); + penabled(buf, buf + sizeof buf, id); + print("enabled\t%s\n", buf); + pextraid(buf, buf + sizeof buf, id, &i); + print("extra\t%s\n", buf); + if(i){ + idmove(buf, id + 176, 60); + if(buf[0] != 0) + print("medias\t%s\n", buf); + } + psct(buf, buf + sizeof buf, id); + if(buf[0]) + print("sct\t%s\n", buf); + ptransport(buf, buf + sizeof buf, id); + print("trans\t%s\n", buf); + pff(buf, buf + sizeof buf, id); + if(buf[0]) + print("ff\t%s\n", buf); +} + +void +smfmt(Req *r) +{ + uchar *fis; + + if(r->cmd.fis[Ffeat] == 0xda){ + fis = r->reply.fis; + if(fis[5] == 0x4f && + fis[6] == 0xc2) + eprint("normal\n"); + else + eprint("threshold exceeded\n"); + return; + } +} + +void +iofmt(Req *r) +{ + uchar *u; + int i; + + if(r->fmtrw == 0){ + rawout(r); + return; + } + u = r->data; + for(i = 0; i < r->count; i += 16) + fprint(2, "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux" + "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux\n", + u[i + 0], u[i + 1], u[i + 2], u[i + 3], u[i + 4], u[i + 5], u[i + 6], u[i + 7], + u[i + 8], u[i + 9], u[i +10], u[i +11], u[i +12], u[i +13], u[i +14], u[i +15]); +} + +static char *csbyte[] = { + "never started", + nil, + "competed without error", + "in progress", + "suspended by cmd from host", + "aborted by cmd from host", + "aborted by device with fatal error", +}; + +static char *exe[] = { + "no error or never run", + "aborted by host", + "interrupted by host", + "fatal error; unable to complete", + "failed", + "failed: electricial", + "failed: servo", + "failed: read", + "failed: shipping damage", +[0xf] "in progress", +}; + +char* +tabtr(uint u, char **tab, int ntab) +{ + char *s; + + if(u >= ntab || (s = tab[u]) == nil) + s = "reserved"; + return s; +} + +void +sdfmt(Req *r) +{ + char *s; + uchar *b; + ushort u; + + if(r->fmtrw == 0){ + rawout(r); + return; + } + b = r->data; + u = b[362]; + if((u & 0xf0) == 0x80 && u != 0x81 && u != 0x83) + u &= 0xf; + s = tabtr(u, csbyte, nelem(csbyte)); + print("col status: %.2ux %s\n", b[362], s); + u = b[363]; + s = tabtr(u>>4, exe, nelem(exe)); + if(u & 0xf) + print("exe status: %.2ux %s, %d0%% left\n", u, s, u & 0xf); + else + print("exe status: %.2ux %s\n", u, s); + u = b[364] | b[365]<<8; + print("time left: %uds\n", u); + print("shrt poll: %udm\n", b[373]); + u = b[374]; + if(u == 0xff) + u = b[375] | b[376]<<8; + print("ext poll: %udm\n", u); +} + +void +pagemapfmt(Req *r) +{ + int i; + ushort *u; + + u = (ushort*)r->data; + if(u[0] != 1){ + print("unsupported\n"); + return; + } + for(i = 1; i < 128; i++) + if(u[i] > 0) + print("page %d: %d\n", i, u[i]); +} + +void +slfmt(Req *r) +{ + switch(r->cmd.fis[Flba0]){ + default: + iofmt(r); + break; + case 0: + pagemapfmt(r); + break; + } +} + +enum{ + Physz = 7<<12, +}; + +static char *phyec[] = { + "no event", + "icrc", + "err data", + "err d2h data", + "err h2d data", +[0x05] "err nd", + "err d2h nd", + "err h2d nd", + "retry d2h nd", + "nready", +[0x0a] "comreset", + "h2d crc", + nil, + "bad h2d", + nil, + "err h2d data crc", +[0x10] "err h2d data", + nil, + "err h2d nd crc", + "err h2d nd", +}; + +void +phyfmt(Req *r) +{ + char *ec; + uchar *p; + ushort *u, *e, id, sz; + + u = (ushort*)r->data; + e = u + 510/sizeof *u; + for(u += 2; u < e; u += sz){ + id = w((uchar*)u); + sz = (id & Physz) >> 12; + id &= ~Physz; + if(sz == 0) + break; + ec = "unk"; + if(id < nelem(phyec) && phyec[id] != nil) + ec = phyec[id]; + print("%.4ux\t%-15s\t", id, ec); + p = (uchar*)u + 2; + switch(sz<<1){ + default: + print("\n"); + break; + case 2: + print("%.4ux\n", w(p)); + break; + case 4: + print("%.8ux\n", dw(p)); + break; + case 8: + print("%.16llux\n", qw(p)); + break; + } + sz += 1; + } +} + +typedef struct Gltab Gltab; +struct Gltab{ + int offset; + char *name; +}; + +Gltab page3[] = { + 8, "power-on hrs", + 16, "head flying hrs", + 24, "head loads", + 32, "realloc'd sec", + 40, "read recovery att", + 48, "start failures" +}; + +void +qpfmt(Req *r, Gltab *t, int ntab) +{ + uchar *u; + int i; + uvlong v; + + u = r->data; + for(i = 0; i < ntab; i++){ + v = qw(u + t[i].offset); + if((v & 3ll<<63) != 3ll<<63) + continue; + print("%lud\t%s\n", (ulong)v, t[i].name); + } +} + +static char *sctsttab[] = { + "active waiting", + "standby", + "sleep", + "dst bgnd", + "smart bgnd", + "sct bgnd", +}; + +void +sctstatfmt(Req *r) +{ + char *s; + uchar *id, c; + + id = r->data; + print("version\t%d\n", gbit16(id + 0)); + print("vnd ver\t%2ux\n", gbit16(id + 2)); + print("flags\t%.8ux\n", dw(id + 6)); + c = id[10]; + s = "unk"; + if(c < nelem(sctsttab)) + s = sctsttab[c]; + print("state\t%s\n", s); + print("ext stat\t%.4ux\n", gbit16(id + 14)); + print("act code\t%.4ux\n", gbit16(id + 16)); + print("fn code\t%.4ux\n", gbit16(id + 18)); + print("lba\t%llud\n", qw(id + 40)); + print("temp\t%d\n", id[200]); + print("min t\t%d %d\n", id[201], id[203]); + print("max t\t%d %d\n", id[202], id[204]); + print("ot\t%d\n", dw(id + 206)); + print("ut\t%d\n", dw(id + 210)); +} + + +void +glfmt(Req *r) +{ + switch(r->cmd.fis[Flba0]){ + case 0: + pagemapfmt(r); + break; + case 3: + qpfmt(r, page3, nelem(page3)); + break; + case 17: + phyfmt(r); + break; + case 0xe0: + sctstatfmt(r); + break; + default: + iofmt(r); + break; + } +} + +char* +readline(char *prompt, char *line, int len) +{ + char *p, *e, *q; + int n, dump; + + e = line + len; +retry: + dump = 0; + if(interrupted) + eprint("\n%s", prompt); + else + eprint("%s", prompt); + interrupted = 0; + for(p = line;; p += n){ + if(p == e){ + dump = 1; + p = line; + } + n = read(0, p, e - p); + if(n < 0){ + if(interrupted) + goto retry; + return nil; + } + if(n == 0) + return nil; + if(q = memchr(p, '\n', n)){ + if(dump){ + eprint("!line too long\n"); + goto retry; + } + p = q; + break; + } + } + *p = 0; + return line; +} + +void +suggesttab(char *cmd, Atatab *a, int n) +{ + int i, l; + + l = strlen(cmd); + for(i = 0; i < n; i++) + if(cistrncmp(cmd, a[i].name, l) == 0) + eprint("%s\n", a[i].name); +} + +Atatab* +findtab(char **cmd, Atatab *a, int n) +{ + char *p, *c; + int i, cc, max, l; + + cc = strtoul(*cmd, &p, 0); + if(p != *cmd && (*p == 0 || *p == ' ')){ + for(i = 0; i < n; i++) + if(a[i].cc == cc){ + *cmd = p + 1; + return a + cc; + } + return 0; + } + max = 0; + cc = 0; + c = *cmd; + for(i = 0; i < n; i++){ + l = strlen(a[i].name); + if(l > max && cistrncmp(*cmd, a[i].name, l) == 0) + if(c[l] == ' ' || c[l] == 0){ + max = l + (c[l] == ' '); + cc = i; + } + } + if(max > 0){ + *cmd = *cmd + max; + return a + cc; + } + return 0; +} + +int +catch(void*, char *note) +{ + if(strstr(note, "interrupt") != nil) + return interrupted = 1; + return 0; +} + +char** +ndargs(Atatab*, Req *, char **p) +{ + return p; +} + +char** +ioargs(Atatab *, Req *r, char **p) +{ + if(r->nsect == 0) + r->nsect = 1; + if(p[0] == 0) + return p; + r->lba = strtoull(p[0], 0, 0); + p++; + if(p[0] == 0) + return p; + r->nsect = strtoul(p[0], 0, 0); + return p + 1; +} + +char** +stdargs(Atatab *, Req *r, char **p) +{ + char *s; + Rune x; + + for(; p[0] && p[0][0] == '-' && p[0][1]; p++){ + s = p[0] + 1; + if(*s == '-'){ + p++; + break; + } + while(*s && (s += chartorune(&x, s))) + switch(x){ + case 'r': + r->raw = 1; + break; + default: + return p; + } + } + return p; +} + +static void +chopoff(char *s, char *extra) +{ + char *p; + int l, ls; + + l = strlen(extra); + ls = strlen(s); + if(l >= ls) + return; + p = s + ls - l; + if(strcmp(p, extra) == 0) + *p = 0; +} + +char* +trim(char *s) +{ + char *p; + + while(*s && (*s == ' ' || *s == '\t')) + s++; + if(*s == 0) + return nil; + p = s + strlen(s) - 1; + while(*p == ' ' || *p == '\t') + p--; + p[1] = 0; + return s; +} + +int +doredir(Req *r, char **f, int nf, int mode, int *fd1, int *fd2) +{ + int fd; + + if(nf != 1 && nf != 2){ + eprint("!args\n"); + return -1; + } + fd = -1; + if(nf == 2){ + fd = open(f[1], mode); + if(mode != OREAD){ + if(fd == -1) + fd = create(f[1], mode, 0660); + else + seek(fd, 0, 2); + } + } + if(fd1){ + close(*fd1); + *fd1 = fd; + } + if(fd2){ + r->fmtrw = fd == -1; + close(*fd2); + *fd2 = fd; + } + return fd; +} + +int +special(char *s, Dev *d, Req *r) +{ + char buf[512], path[128], *f[20], sbuf[512], s2[512], *p, *e, *t; + uchar *u; + int i, j, nf; + Atatab *a; + + p = buf; + e = buf + sizeof buf; + if(!strcmp(s, "close")){ + r->haverfis = 0; + close(d->fd); + d->fd = -1; + return 0; + } + if(!strcmp(s, "scttrace")){ + scttrace = 1; + return 0; + } + if(!strcmp(s, "dev")){ + if(d->fd == -1){ + eprint("!bad cmd (device closed)\n"); + return 0; + } + if(fd2path(d->fd, path, sizeof path) == -1) + sysfatal("fd2path: %r"); + chopoff(path, "/raw"); + p = seprint(p, e, "dev\t%s\n", path); + p = seprint(p, e, "flags\t"); + p = pflag(p, e, d); + p = seprint(p, e, "lsectsz\t" "%ud ptol %ud\n", d->lsectsz, 1<<d->physshift); + p = seprint(p, e, "geometry %llud %ud\n", d->nsect, d->secsize); + if(d->c | d->h | d->s) + seprint(p, e, "chs\t%d %d %d\n", d->c, d->h, d->s); + print("%s", buf); + return 0; + } + if(!strcmp(s, "help")){ + suggesttab(buf, atatab, nelem(atatab)); + return 0; + } + if(!strcmp(s, "probe")){ + probe(); + return 0; + } + if(!strcmp(s, "rfis")){ + if(r->haverfis == 0){ + eprint("!no rfis\n"); + return 0; + } + p = seprint(p, e, "%.2x\n", r->reply.sdcmd); + u = r->reply.fis; + for(i = 0; i < 16; i++) + p = seprint(p, e, "%.2ux", u[i]); + seprint(p, e, "\n"); + print("%s", buf); + return 0; + } + for(t = s; *t == '<' || *t == '>'; t++) + ; + if(t != s) + snprint(sbuf, sizeof buf, "%.*s %s", (int)(t - s), s, t); + else + snprint(sbuf, sizeof sbuf, "%s", s); + nf = tokenize(sbuf, f, nelem(f)); + if(!strcmp(f[0], "issuetr")){ + if(nf == 1) + for(i = 0; i < nelem(issuetr); i++) + issuetr[i] ^= 1; + else{ + p = s2; + e = s2 + sizeof s2; + for(i = 1; i < nf - 1; i++) + p = seprint(p, e, "%s ", f[i]); + p = seprint(p, e, "%s", f[i]); + e = s2; + for(i = 1; i < nf; i++){ + j = strtoul(f[i], &p, 0); + if(*p == 0 && j < nelem(issuetr)) + issuetr[i] ^= 1; + else if(a = findtab(&e, atatab, nelem(atatab))) + issuetr[a->cc & 0xff] ^= 1; + } + } + return 0; + } + if(!strcmp(f[0], "open")){ + r->lba = 0; + if(nf == 2) + opendev(f[1], d); + else + eprint("!bad args to open\n"); + return 0; + } + if(!strcmp(f[0], ">")){ + doredir(r, f, nf, OWRITE, 0, &r->wfd); + return 0; + } + if(!strcmp(f[0], "<")){ + doredir(r, f, nf, OREAD, &r->rfd, 0); + return 0; + } + if(!strcmp(f[0], "<>")){ + doredir(r, f, nf, OWRITE, &r->rfd, &r->wfd); + return 0; + } + return -1; +} + +static char *regtab[] = { + "Ftype", + "Fflags", + "Fcmd", + "Ffeat", + "Flba0", + "Flba8", + "Flba16", + "Fdev", + "Flba24", + "Flba32", + "Flba40", + "Ffeat8", + "Fsc", + "Fsc8", + "Fr", + "Fcontrol", +}; + +void +setreg(Req *r, uint reg, uvlong v) +{ + uchar *o; + int x; + + switch(reg & (Sbase | Pbase)){ + case 0: + r->fisbits |= 1 << reg; + r->cmd.fis[reg] = v; +// print("%s: %.2ux\n", regtab[reg], (uchar)v); + break; + case Sbase: + case Sbase | Pbase: + x = reg & ~(Sbase | Ssz); + o = r->data + x*2; + assert(x < r->count); + switch(reg & Ssz){ + default: + print("reg & Ssz %ux\n", reg & Ssz); + _assert("bad table"); + case Sw: + pw(o, v); + break; + case Sdw: + pdw(o, v); + break; + case Sqw: + pqw(o, v); + break; + } + break; + case Pbase: + /* fix me please: this is teh suck */ + r->fisbits |= 1 << 16; + r->cmd.ataproto = v; + break; + } +} + +int +setfis0(Req *r, Txtab *t, char *p) +{ + char *e; + uvlong v; + + v = strtoull(p, &e, 0); + setreg(r, t->val, v); + return *e != 0; +} + +char** +setfis(Atatab*, Req *r, char **p) +{ + char *s; + int i; + +loop: + if((s = p[0]) == 0) + return p; + for(i = 0; i < nelem(regtx); i++) + if(strcmp(s, regtx[i].name) == 0 && p[1] != nil){ +// print("setfis0 %s %s\n", p[0], p[1]); + setfis0(r, regtx + i, p[1]); + p += 2; + goto loop; + } + return p; +} + +char* +rname(char *buf, int n, int r) +{ + int i; + + for(i = 0; i < nelem(regtx); i++) + if(regtx[i].val == r){ + snprint(buf, n, "%s", regtx[i].name); + return buf; + } + snprint(buf, n, "%.2ux", r); + return buf; +} + +int +mwcmp(char *a, char ***l) +{ + char buf[128], *f[20], **p; + int nf, i; + + if(*a == 0) + return 0; + p = *l; + if(p[0] == 0) + return -1; + snprint(buf, sizeof buf, "%s", a); + nf = tokenize(buf, f, nelem(f)); + for(i = 0; i < nf; i++) + if(p[i] == nil || cistrcmp(p[i], f[i]) != 0) + return -1; + *l = p + i - 1; + return 0; +} + +char **dofetab(Fetab*, Req*, char**); + +static char hexdig[] = "ABCDEFabcdef0123456789"; +static char hexonly[] = "ABCDEFabcdef"; +static char Enum[] = "expecting number"; + +int +fenum(Fetab *, int v, char ***p) +{ + char *e, *s, *r; + int base; + + if(v >= 0) + return v; + s = *(*p + 1); + e = nil; + if(s == nil || *s == 0) + e = Enum; + else{ + base = 0; + if(strspn(s, hexdig) == strlen(s) && + strpbrk(s, hexonly) != nil) + base = 0x10; + v = strtoul(s, &r, base); + if(*r) + e = Enum; + } + if(e == nil) + (*p)++; + else + print("error: %s [%s]\n", e, s); + return v; +} + +char** +dofetab0(Fetab *t, Req *r, char **p) +{ + int i, v; + Txtab *tab; + + if(t == nil) + return p; + tab = t->tab; +loop: + for(i = 0; i < t->ntab; i++) + if(mwcmp(tab[i].name, &p) == 0){ + v = fenum(t, tab[i].val, &p); + setreg(r, t->reg, v); + if(tab[i].name[0] != 0){ + p = dofetab(tab[i].fe, r, p + 1); + goto loop; + } + } + return p; + +} + +char** +dofetab(Fetab *t, Req *r, char **p) +{ + for(; t != nil && t->ntab > 0; t++) + p = dofetab0(t, r, p); + return p; +} + +char** +dotab(Atatab *a, Req *r, char **p) +{ + if(a->tab == nil) + return p; + return dofetab(a->tab, r, p); +} + +void +initreq(Req *r) +{ + memset(r, 0, sizeof *r); +// r->wfd = open("/dev/null", OWRITE); + r->wfd = dup(1, -1); + if(rflag == 0) + r->fmtrw = 1; + r->rfd = open("/dev/zero", OREAD); +} + +void +setup(void) +{ + int i; + + for(i = 0; i < nelem(atatab); i++) + if(atatab[i].cc == 0x2f){ + sctread = atatab + i; + break; + } + for(; i < nelem(atatab); i++) + if(atatab[i].cc == 0x3f){ + sctissue = atatab + i; + break; + } + for(; i < nelem(atatab); i++) + if(atatab[i].cc == 0xa1){ + idpktcmd = atatab + i; + break; + } + for(; i < nelem(atatab); i++) + if(atatab[i].cc == 0xec){ + idcmd = atatab + i; + break; + } + for(; i < nelem(atatab); i++) + if(atatab[i].cc == 0xf000){ + sigcmd = atatab + i; + break; + } +} + +typedef struct Htab Htab; +struct Htab { + ulong bit; + char *name; +}; + +Htab ertab[] = { + Eicrc, "icrc", + Ewp, "wp", + Emc, "mc", + Eidnf, "idnf", + Emcr, "mcr", + Eabrt, "abrt", + Enm, "nm", + Emed, "med", + Eunc, "unc", +}; + +Htab sttab[] = { + ASbsy, "bsy", + ASdrdy, "drdy", + ASdf, "df", + ASdrq, "drq", + ASerr, "err", +}; + +static char* +htabfmt(char *p, char *e, Htab *t, int n, ulong u) +{ + char *p0; + uint i; + + p0 = p; + for(i = 0; i < n; i++) + if(u & t[i].bit) + p = seprint(p, e, "%s | ", t[i].name); + if(p - 3 >= p0) + p -= 3; + if(p < e) + p[0] = 0; + return p; +} + +void +prerror(Req *r) +{ + char st[64], er[64]; + uchar *u; + + u = r->reply.fis; + if(r->haverfis == 0 || (u[Fstatus] & ASerr) == 0) + return; + htabfmt(er, er + sizeof er, ertab, nelem(ertab), u[Frerror]); + htabfmt(st, st + sizeof st, sttab, nelem(sttab), u[Fstatus] & ~ASobs); + fprint(2, "err %.2ux %.2ux (%s, %s)\n", u[Frerror], u[Fstatus], er, st); +} + +void +usage(void) +{ + eprint("usage: atazz dev\n"); + eprint(" or -c cmd\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char buf[1024], *p, *f[20], **fp; + int nf, cflag, i; + Atatab *a; + Req r; + Dev d; + + cflag = 0; + ARGBEGIN{ + case 'c': + cflag = atoi(EARGF(usage())); + break; + case 'r': + rflag = 1; + break; + default: + usage(); + }ARGEND + + if(cflag){ + for(i = 0; i < nelem(atatab); i++) + if(atatab[i].cc == cflag) + print("%s\n", atatab[i].name); + exits(""); + } + + setup(); + fmtinstall(L'π', πfmt); + if(argc > 1) + usage(); + initreq(&r); + d.fd = -1; + if(argc == 1 && opendev(*argv, &d) == -1) + sysfatal("opendev: %r"); + atnotify(catch, 1); + for(;;){ + memset(&r.cmd, 0, sizeof r.cmd); + r.fisbits = 0; + if(readline("az> ", buf, sizeof buf-1) == nil) + break; + if((p = trim(buf)) == nil) + continue; + if(special(buf, &d, &r) == 0) + continue; + if(d.fd == -1){ + eprint("!bad cmd (device closed)\n"); + continue; + } + a = findtab(&p, atatab, nelem(atatab)); + if(!a){ + suggesttab(buf, atatab, nelem(atatab)); + eprint("!unknown cmd\n"); + continue; + } + nf = tokenize(p, f, nelem(f) - 1); + f[nf] = 0; + fp = stdargs(a, &r, f); + fp = setfis(a, &r, fp); + if(a->protocol & Psct){ + r.count = 1 * 512; + r.data = realloc(r.data, r.count); + memset(r.data, 0, r.count); + } + fp = dotab(a, &r, fp); + switch(a->protocol & Pprotom){ + default: + eprint("!bad proto1 %.2ux\n", a->protocol & Pprotom); + continue; + case Pnd: + fp = ndargs(a, &r, fp); + case Preset: + case Pdiag: + r.count = 0; + r.lba = 0; + r.nsect = 0; + break; + case Ppio: + case Pdma: + case Pdmq: + case Ppkt: + if(a->flags & Cmd5sc){ + r.nsect = r.cmd.fis[Fsc]; + if(r.nsect == 0) + r.nsect = 1; + r.cmd.fis[Fsc] = r.nsect; + r.count = r.nsect * 0x200; + }else if((a->protocol & Pssm) == P512){ + r.lba = 0; + r.nsect = 0; + r.count = 512; + }else{ + fp = ioargs(a, &r, fp); + r.count = d.secsize * r.nsect; + } + break; + } + if(fp[0]){ + eprint("!extra args %π\n", fp); + continue; + } + if(issue(&r, a, &d) == -1){ + prerror(&r); + continue; + } + if(a->fmt) + a->fmt(&r); + } + exits(""); +} diff --git a/sys/src/cmd/atazz/mkfile b/sys/src/cmd/atazz/mkfile new file mode 100644 index 000000000..9dc7214b4 --- /dev/null +++ b/sys/src/cmd/atazz/mkfile @@ -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 diff --git a/sys/src/cmd/atazz/probe.c b/sys/src/cmd/atazz/probe.c new file mode 100644 index 000000000..7963364be --- /dev/null +++ b/sys/src/cmd/atazz/probe.c @@ -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; +} diff --git a/sys/src/cmd/atazz/sctnotes b/sys/src/cmd/atazz/sctnotes new file mode 100644 index 000000000..294b4edf1 --- /dev/null +++ b/sys/src/cmd/atazz/sctnotes @@ -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 diff --git a/sys/src/cmd/atazz/smartnotes b/sys/src/cmd/atazz/smartnotes new file mode 100644 index 000000000..0f169b6ab --- /dev/null +++ b/sys/src/cmd/atazz/smartnotes @@ -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 " diff --git a/sys/src/cmd/atazz/tabs.h b/sys/src/cmd/atazz/tabs.h new file mode 100644 index 000000000..3854199c2 --- /dev/null +++ b/sys/src/cmd/atazz/tabs.h @@ -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", +}; |