// ahci generic
// © 2007 coraid, inc
// ata errors
enum{
Emed = 1<<0, // media error
Enm = 1<<1, // no media
Eabrt = 1<<2, // abort
Emcr = 1<<3, // media change request
Eidnf = 1<<4, // no user-accessible address
Emc = 1<<5, // media change
Eunc = 1<<6, // data error
Ewp = 1<<6, // write protect
Eicrc = 1<<7, // interface crc error
Efatal = Eidnf|Eicrc, // must sw reset.
};
// ata status
enum{
ASerr = 1<<0, // error
ASdrq = 1<<3, // request
ASdf = 1<<5, // fault
ASdrdy = 1<<6, // ready
ASbsy = 1<<7, // busy
ASobs = 1<<1|1<<2|1<<4,
};
// pci configuration
enum{
Abar = 5,
};
/* ahci memory configuration
0000-0023 generic host control
0024-009f reserved
00a0-00ff vendor specific.
0100-017f port 0
...
1080-1100 port 31
*/
// cap bits
enum{
Hs64a = 1<<31, // supports 64-bit addressing
Hsncq = 1<<30, // " ncq
Hssntf = 1<<29, // " snotification reg.
Hsmps = 1<<28, // " mech pres switch
Hsss = 1<<27, // " staggered spinup
Hsalp = 1<<26, // " agressive link pm
Hsal = 1<<25, // " activity led
Hsclo = 1<<24, // " command-list override
Hiss = 1<<20, // " for interface speed.
// Hsnzo = 1<<19,
Hsam = 1<<18, // " ahci-mode only
Hspm = 1<<17, // " port multiplier
// Hfbss = 1<<16,
Hpmb = 1<<15, // " mutiple-block pio
Hssc = 1<<14, // " slumber state
Hpsc = 1<<13, // " partial-slumber state
Hncs = 1<<8, // " n command slots
Hcccs = 1<<7, // " coal
Hems = 1<<6, // " enclosure mgmt.
Hsxs = 1<<5, // " external sata.
Hnp = 1<<0, // " n ports
};
// ghc bits
enum{
Hae = 1<<31, // enable ahci
Hie = 1<<1, // " interrupts
Hhr = 1<<0, // hba reset
};
typedef struct{
u32int cap;
u32int ghc;
u32int isr;
u32int pi; // ports implemented
u32int ver;
u32int ccc; // coaleasing control
u32int cccports;
u32int emloc;
u32int emctl;
} Ahba;
enum{
Acpds = 1<<31, // cold port detect status
Atfes = 1<<30, // task file error status
Ahbfs = 1<<29, // hba fatal
Ahbds = 1<<28, // hba error (parity error)
Aifs = 1<<27, // interface fatal §6.1.2
Ainfs = 1<<26, // interface error (recovered)
Aofs = 1<<24, // too many bytes from disk.
Aipms = 1<<23, // incorrect prt mul status
Aprcs = 1<<22, // PhyRdy change status Pxserr.diag.n
Adpms = 1<<7, // mechanical presence status
Apcs = 1<<6, // port connect diag.x
Adps = 1<<5, // descriptor processed
Aufs = 1<<4, // unknown fis diag.f
Asdbs = 1<<3, // set device bits fis received with i bit set.
Adss = 1<<2, // dma setup
Apio = 1<<1, // pio setup fis
Adhrs = 1<<0, // device to host register fis.
IEM = Acpds|Atfes|Ahbds|Ahbfs|Ahbds|Aifs|Ainfs|Aprcs|Apcs|Adps|Aufs|Asdbs|Adss|Adhrs,
Ifatal = Atfes|Ahbfs|Ahbds|Aifs,
};
// serror bits.
enum{
SerrX = 1<<26, // exchanged
SerrF = 1<<25, // unknown fis
SerrT = 1<<24, // transition error
SerrS = 1<<23, // link sequence
SerrH = 1<<22, // handshake
SerrC = 1<<21, // crc
SerrD = 1<<20, // not used by ahci
SerrB = 1<<19, // 10-tp-8 decode
SerrW = 1<<18, // comm wake
SerrI = 1<<17, // phy internal
SerrN = 1<<16, // phyrdy change
ErrE = 1<<11, // internal
ErrP = 1<<10, // ata protocol violation
ErrC = 1<<9, // communication
ErrT = 1<<8, // transient
ErrM = 1<<1, // recoverd comm
ErrI = 1<<0, // recovered data integrety
ErrAll = ErrE|ErrP|ErrC|ErrT|ErrM|ErrI,
SerrAll = SerrX|SerrF|SerrT|SerrS|SerrH|SerrC|SerrD|SerrB|SerrW|SerrI|SerrN|ErrAll,
SerrBad = 0x7f<<19,
};
// cmd register bits
enum{
Aicc = 1<<28, // interface communcations control. 4 bits
Aasp = 1<<27, // agressive slumber & partial sleep
Aalpe = 1<<26, // agressive link pm enable
Adlae = 1<<25, // drive led on atapi
Aatapi = 1<<24, // device is atapi
Aesp = 1<<21, // external sata port
Acpd = 1<<20, // cold presence detect
Ampsp = 1<<19, // mechanical pres.
Ahpcp = 1<<18, // hot plug capable
Apma = 1<<17, // pm attached
Acps = 1<<16, // cold presence state
Acr = 1<<15, // cmdlist running
Afr = 1<<14, // fis running
Ampss = 1<<13, // mechanical presence switch state
Accs = 1<<8, // current command slot 12:08
Afre = 1<<4, // fis enable receive.
Aclo = 1<<3, // command list override
Apod = 1<<2, // power on device (requires cold-pres. detect)
Asud = 1<<1, // spin-up device; requires ss capability.
Ast = 1<<0, // start
Arun = Ast|Acr|Afre|Afr,
};
// ctl register bits
enum{
Aipm = 1<<8, // interface power mgmt. 3=off
Aspd = 1<<4,
Adet = 1<<0, // device detcection.
};
#define sstatus scr0
#define sctl scr2
#define serror scr1
#define sactive scr3
typedef struct{
u32int list; // PxCLB must be 1kb aligned.
u32int listhi;
u32int fis; // 256-byte aligned.
u32int fishi;
u32int isr;
u32int ie; // interrupt enable
u32int cmd;
u32int res1;
u32int task;
u32int sig;
u32int scr0;
u32int scr2;
u32int scr1;
u32int scr3;
u32int ci; // command issue
u32int ntf;
uchar res2[8];
u32int vendor;
}Aport;
// in hosts memory; not memory mapped
typedef struct{
uchar *base;
uchar *d;
uchar *p;
uchar *r;
uchar *u;
u32int *devicebits;
}Afis;
enum{
Lprdtl = 1<<16, // physical region descriptor table len
Lpmp = 1<<12, // port multiplier port
Lclear = 1<<10, // clear busy on R_OK
Lbist = 1<<9,
Lreset = 1<<8,
Lpref = 1<<7, // prefetchable
Lwrite = 1<<6,
Latapi = 1<<5,
Lcfl = 1<<0, // command fis length in double words
};
// in hosts memory; memory mapped
typedef struct{
u32int flags;
u32int len;
u32int ctab;
u32int ctabhi;
uchar reserved[16];
}Alist;
typedef struct{
u32int dba;
u32int dbahi;
u32int pad;
u32int count;
}Aprdt;
typedef struct{
uchar cfis[0x40];
uchar atapi[0x10];
uchar pad[0x30];
Aprdt prdt;
}Actab;
enum{
Ferror = 1,
Fdone = 2,
};
enum{
Dllba = 1,
Dsmart = 1<<1,
Dpower = 1<<2,
Dnop = 1<<3,
Datapi = 1<<4,
Datapi16= 1<<5,
};
typedef struct{
// QLock;
// Rendez;
uchar flag;
uchar feat;
uchar smart;
Afis fis;
Alist *list;
Actab *ctab;
}Aportm;
typedef struct{
Aport *p;
Aportm *m;
}Aportc;
|