| /* |
| * This file is part of the UCB release of Plan 9. It is subject to the license |
| * terms in the LICENSE file found in the top-level directory of this |
| * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No |
| * part of the UCB release of Plan 9, including this file, may be copied, |
| * modified, propagated, or distributed except according to the terms contained |
| * in the LICENSE file. |
| */ |
| |
| /* |
| * advanced host controller interface (sata) |
| * © 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, command specific */ |
| ASdrdy = 1 << 6, /* ready, command specific */ |
| 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 |
| */ |
| |
| /* Capability bits: supported features */ |
| enum { |
| Hs64a = 1 << 31, /* 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, /* aggressive 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, /* multiple-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 */ |
| }; |
| |
| #define HBA_CAP 0x00 // Host Capabilities |
| #define HBA_GHC 0x04 // Global Host Control |
| #define HBA_ISR 0x08 // Interrupt Status Register |
| #define HBA_PI 0x0C // Ports Implemented |
| #define HBA_VS 0x10 // Version |
| #define HBA_CCC_CTL 0x14 // Command Completion Coalescing Control |
| #define HBA_CCC_PORTS 0x18 // Command Completion Coalescing Ports |
| #define HBA_EM_LOC 0x1C // Enclosure Management Location |
| #define HBA_EM_CTL 0x20 // Enclosure Management Control |
| #define HBA_CAP2 0x24 // Host Capabilities Extended |
| #define HBA_BOHC 0x28 // BIOS/OS Hand-Off Control and Status |
| |
| /* Interrupt Status bits */ |
| 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 w/ 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, |
| }; |
| |
| /* Command/Status register bits */ |
| enum { |
| Aicc = 1 << 28, /* interface communcations control. 4 bits */ |
| Aasp = 1 << 27, /* aggressive slumber & partial sleep */ |
| Aalpe = 1 << 26, /* aggressive 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 dev (requires cold-pres. detect) */ |
| Asud = 1 << 1, /* spin-up device; requires ss capability */ |
| Ast = 1 << 0, /* start */ |
| |
| Arun = Ast | Acr | Afre | Afr, |
| }; |
| |
| /* SControl register bits */ |
| enum { |
| Aipm = 1 << 8, /* interface power mgmt. 3=off */ |
| Aspd = 1 << 4, |
| Adis = 1 << 2, // Disable SATA interface and put Phy in offline mode |
| Adet = 1 << 0, /* device detection */ |
| }; |
| |
| #define PORT_CLB 0x00 // Port Command List Base address |
| #define PORT_CLBU 0x04 // Port Command List Base address Upper 32-bits |
| #define PORT_FB 0x08 // Port FIS Base address |
| #define PORT_FBU 0x0C // Port FIS Base address Upper 32-bits |
| #define PORT_IS 0x10 // Port Interrupt Status |
| #define PORT_IE 0x14 // Port Interrupt Enable |
| #define PORT_CMD 0x18 // Port Command and status |
| #define PORT_RES1 0x1C // Reserved |
| #define PORT_TFD 0x20 // Port Task File Data |
| #define PORT_SIG 0x24 // Port Signature |
| #define PORT_SSTS 0x28 // Port Serial ATA Status (SCR0: SStatus) |
| #define PORT_SCTL 0x2C // Port Serial ATA Control (SCR2: SControl) |
| #define PORT_SERR 0x30 // Port Serial ATA Error (SCR1: SError) |
| #define PORT_SACT 0x34 // Port Serial ATA Active (SCR3: SActive) |
| #define PORT_CI 0x38 // Port Command Issue |
| #define PORT_SNTF 0x3C // Port Serial ATA Notification (SCR4: SNotification) |
| #define PORT_FBS 0x40 // Port FIS-Based Switching control |
| #define PORT_DEVSLP 0x44 // Port Device Sleep |
| #define PORT_RES2 0x48 // Reserved |
| #define PORT_VS 0x70 // Vendor Specific |
| |
| enum { |
| /* |
| * Aport sstatus bits (actually states): |
| * 11-8 interface power management |
| * 7-4 current interface speed (generation #) |
| * 3-0 device detection |
| */ |
| Intslumber = 0x600, |
| Intpartpwr = 0x200, |
| Intactive = 0x100, |
| Intpm = 0xf00, |
| |
| Devphyoffline = 4, |
| Devphycomm = 2, /* phy communication established */ |
| Devpresent = 1, |
| Devdet = Devpresent | Devphycomm | Devphyoffline, |
| }; |
| |
| /* in host's memory; not memory mapped */ |
| struct afis { |
| unsigned char *base; |
| unsigned char *d; |
| unsigned char *p; |
| unsigned char *r; |
| unsigned char *u; |
| uint32_t *devicebits; |
| }; |
| |
| // Command header flags |
| 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 */ |
| }; |
| |
| // AHCI Command List Command Header |
| // Each header is an element in the list which is up to 32 elements long |
| #define ALIST_SIZE 0x20 // Size of the struct in memory, not for access |
| #define ALIST_FLAGS 0x00 // Flags and PRDTL (PRDT Length) |
| #define ALIST_LEN 0x04 // PRD byte count transferred |
| #define ALIST_CTAB 0x08 // Physical address of 128-bit aligned Command Table |
| #define ALIST_CTABHI 0x0C // CTAB physical address upper 32 bits |
| #define ALIST_RES 0x10 // Reserved |
| |
| // AHCI Physical Region Descriptor Table Element |
| // Each of these elements is part of a table with up to 65,535 entries |
| #define APRDT_SIZE 0x10 // Size of the struct in memory, not for access |
| #define APRDT_DBA 0x00 // Data Base Address (physical) |
| #define APRDT_DBAHI 0x04 // Data Base Address upper 32 bits |
| #define APRDT_RES 0x08 // Reserved |
| #define APRDT_COUNT 0x0C // 31=Intr on Completion, 30:22=Reserved, 21:0=DBC |
| |
| // AHCI Command Table |
| // Note that there is no fixed size specified - there are 1 to 65,535 PRDT's |
| // Size = ACTAB_PRDT + APRDT*N_APRDT |
| #define ACTAB_CFIS 0x00 // Command Frame Information Struct (up to 64 bytes) |
| #define ACTAB_ATAPI 0x40 // ATAPI Command (12 or 16 bytes) |
| #define ACTAB_RES 0x50 // Reserved |
| #define ACTAB_PRDT 0x80 // PRDT (up to 65,535 entries in spec, this has one) |
| |
| // Portm flags (status flags?) |
| enum { |
| Ferror = 1, |
| Fdone = 2, |
| }; |
| |
| // Portm feature flags |
| enum { |
| Dllba = 1, |
| Dsmart = 1 << 1, |
| Dpower = 1 << 2, |
| Dnop = 1 << 3, |
| Datapi = 1 << 4, |
| Datapi16 = 1 << 5, |
| }; |
| |
| struct aportm { |
| qlock_t ql; |
| struct rendez Rendez; |
| unsigned char flag; |
| unsigned char feat; |
| unsigned char smart; |
| struct afis fis; |
| void *list; |
| void *ctab; |
| }; |
| |
| struct aportc { |
| void *p; |
| struct aportm *pm; |
| }; |