FIS(2)                                                     FIS(2)

     NAME
          setfissig, txmodefis, atapirwfis, featfis, flushcachefis,
          identifyfis, nopfis, rwfis, skelfis, sigtofis, fiswr, fisrw,
          id16, id32, id64, idmove, idfeat, idwwn, idss, idpuis,
          pflag, fistosig, sasbhash, sashash - SATA/SAS FIS and drive
          feature functions

     SYNOPSIS
          #include <u.h>
          #include <libc.h>
          #include <fis.h>

          enum {
                 Fissize  = 0x20,    /* nominal (fits all) fis size */

                 Dlba     = 1<<0,
                 Dllba    = 1<<1,
                 Dsmart   = 1<<2,
                 Dpower   = 1<<3,
                 Dnop     = 1<<4,
                 Datapi   = 1<<5,
                 Datapi16 = 1<<6,
                 Data8    = 1<<7,
                 Dsct     = 1<<8,
          };

          enum {
                 Pspinup  = 1<<0,
                 Pidready = 1<<1,
          };

          struct Sfis {
                 ushort   feat;      /* features supportd */
                 uchar    udma;      /* modes supported */
                 uchar    speeds;    /* sata: allowed speeds */
                 uint     sectsz;    /* sector size */
                 uint     phystol;   /* log2(logical/physical) */
                 uint     sig;       /* signature */
                 uint     c;         /* cylinder */
                 uint     h;         /* head */
                 uint     s;         /* sector */
          };

          void   setfissig(Sfis *sfis, uint sig)

          int    txmodefis(Sfis *sfis, uchar *fis, uchar mode)

          int    featfis(Sfis *sfis, uchar *fis, uchar feat)

          int    flushcachefis(Sfis *sfis, uchar *fis)

     Page 1                       Plan 9            (printed 12/22/24)

     FIS(2)                                                     FIS(2)

          int    identifyfis(Sfis *sfis, uchar *fis)

          int    nopfis(Sfis *sfis, uchar *fis, int srst)

          int    fisrw(Sfis *f, uchar *fis, int *count)

          int    rwfis(Sfis *sfis, uchar *fis, int rw, int nsect, uvlong lba)

          int    atapirwfis(Sfis *sfis, uchar *fis, uchar *cdb, int cdblen, int ndata)

          void   skelfis(uchar *fis)

          void   sigtofis(Sfis *sfis, uchar *d2hfis)

          uvlong fisrw(Sfis *sfis, uchar *fis, int *nsect)

          ushort id16(ushort *id, int idx)

          uint   id32(ushort *id, int idx)

          uvlong id64(ushort *id, int idx)

          void   idmove(char *buf, ushort *ididx, int n)

          vlong  idfeat(Sfis *sfis, ushort *id)

          uvlong idwwn(Sfis*, ushort *id)

          int    idss(Sfis *sfis, ushort *id)

          int    idpuis(ushort *id)

          char   *pflag(char *p, char *e, Sfis *sbis)

          uint   fistosig(uchar *fis)

          uint   sashash(uvlong u)

          uchar* sasbhash(uchar *t, uchar *s)

     DESCRIPTION
          The Sfis type describes the connection between an ATA drive
          and a Host Bus Adaptor (HBA).  The details of this connec-
          tion, such as DMA and LBA support, and the logcal sectors
          per physical sector are used to construct the proper SATA
          FISes.

          Since ATA uses a seperate sector size for addressing (the
          logical sector size) and for ECC calculations (the physical
          sector size), the library returns values based on the physi-
          cal sector size.  This allows clients to make intelligent
          decisions about IO size without worrying about this

     Page 2                       Plan 9            (printed 12/22/24)

     FIS(2)                                                     FIS(2)

          implementation botch.

          feat      selected features supported by the drive.  Set by
                    idfeat.

          udma      the UDMA modes supported by the drive.  Set by
                    idfeat.

          speeds    bitmaped signaling speeds supported by the device.
                    SATA drives may support 1.5gbit/s, 3.0gbit/s and
                    6.0gbit/s signaling.

          sig       this field contains the drive's “signature.”
                    Drives that support the packet command set have a
                    signature of 0xeb140000, while conventional drives
                    have a signature of 0x0101.  The signature is set
                    by setfissig.  See sd(3) for more information.

          c, h, s   the number of physical or logical cylinders, heads
                    and sectors claimed by the drive.  CHS addressing
                    is not allowed by SATA drivers.  Set by idfeat.

          Typically, a client starts by filling out sfis->sig.  Device
          drivers typically have an ideosyncratic method of obtaining
          a signature.  Clients of sd(3) can use special commands to
          obtain a signature.  Given a signature the client can use
          identifyfis to identify the device and finally idfeat, idss
          and idwwn to fill out the structure and extract the maximum
          LBA+1 and the sector size.

          The xtofis functions create FISes to be sent from the host
          to the device.  These are called H2D or Host to Device Reg-
          ister FISes.  All require a fis buffer of at least Fislen
          bytes.  The return value is the ATA protocol of the returned
          command.  For example, identifyfis returns
          Pin|Ppio|P28|P512.

          setfissig(sfis, sig)
               sets the device's ATA signature.

          identifyfis(sfis, fis)
               builds an ATA IDENTIFY DEVICE or IDENTIFY PACKET DEVICE
               FIS, based on sfis->sig.

          id16(id, idx), id32, id64
               return id word, double-world or quad-word at position
               idx.

          idss(sfis, id)
               return the physical sector size of the disk.  The phys-
               ical sector size is the quanta protected by ECC and is
               never smaller than the logical sector size, which is

     Page 3                       Plan 9            (printed 12/22/24)

     FIS(2)                                                     FIS(2)

               used in LBA calcuations.

          idpuis(id)
               checks for PUIS (power up in standby) modes.  Invalid
               id blocks return -1.  Otherwise Pspinup is set if the
               drive needs SET FEATURES subcommand 7 to return com-
               plete data and Pidready bit set if the id block is com-
               plete.  Both or neither bits may be set.

          idfeat(sfis, id)
               parses the 512-byte data block returned by the identify
               commands.  On success, the last LBA+1 is returned.
               Unparseable or unsupportable data blocks return -1.
               Flags may be converted to a descriptive string with
               pflag.  Idss and idwwn return the sector size and World
               Wide Name from the same data.

          idmove(buf, ididx, n)
               converts an ATA string of length n into a null-
               terminated string.  Trailing spaces are deleted.

          fistosig(fis)
               converts a D2H FIS into a device signature.

          txmodefis(sfis, fis, mode)
               builds a SET TRANSFER MODE FIS.

          featfis(sfis, fis, feat)
               builds a SET FEATURES FIS.

          flushcachefis(sfis, fis)
               builds a FLUSH CACHE FIS.

          nopfis(sfis, fis, srst)
               builds a NOP FIS.  If srst is set, then out-of-band
               signaling is used to request a soft reset.  It is not
               expected that srst will be useful outside of device
               drivers.

          rwfis(sfis, fis, rw, nsect, lba)
               generates a FIS requesting an nsect i/o at lba. If rw
               is non-zero, then a write is requested otherwise a read
               is requested.  The correct command to issue is deter-
               mined by sfis . DMA and 48-bit (LLBA) commands are pre-
               ferred.  The inverse is fisrw which returns the lba and
               nsect given a FIS generated by rwfis.

          atapirwfis(sfis, fis, cdb, cdlen, ndata)
               generates an ATAPI read or write FIS.  The cdb contains
               a cdblen-byte SCSI Command Data Block describing an
               nbyte-byte i/o operation.

     Page 4                       Plan 9            (printed 12/22/24)

     FIS(2)                                                     FIS(2)

          skelfis(fis)
               builds a skeleton Host-to-Device (H2D) Register FIS.
               Fis must be a buffer of at least Fislen bytes.

          The fistox functions create FISes to be sent from the device
          to the host.  These are called D2H or Device to Host Regis-
          ter FISes and are used to generate faux responses where
          actual communication with a device would be desirable.  All
          require a fis buffer of at least Fislen bytes.

          sigtofis(sfis, d2hfis)
               builds a device signature fis from based on a device's
               sfis.

          sashash(sasaddr)
               generates a 4-byte hashed SAS address from an 8 byte
               WWN.

          sasbhash(sasaddr, wwn)
               fills the buffer sasaddr with the hashed SAS addresse
               from the 8 byte buffer wwn.

          sigtofis(sfis, d2hfis)

     SOURCE
          /sys/src/libfis

     SEE ALSO
          atazz(8), sd(3), sdide(3), sdahci(3), sdodin(3), smart(8)

     BUGS
          Support for CHS-style addressing is somewhat weak.  In par-
          ticular, rwfis does not do the usual LBA-to-CHS transations.
          This is done by drivers that support CHS addressing.  Cur-
          rently this is only the IDE driver.

          The Sfis structure arguably could contain the LBA size, it
          is required for the correct construction of FISes.

     Page 5                       Plan 9            (printed 12/22/24)