source: trunk/src/os2ahci/ahci.h@ 80

Last change on this file since 80 was 80, checked in by chris, 14 years ago

Version 1.06
============

  • Finally came across a BIOS which accesses the ICH7/8 controller via SATA registers (i.e. not AHCI mode). This required a few changes to the code at boot time because it turned out that COMRESETs are required whenever switching to/from AHCI mode to allow the AHCI or SATA controller to re-discover the attached devices:
  • 'init_reset' will now be forced on when finding a controller in non-AHCI mode at boot time.
  • A COMRESET is initiated for each implemented port after turning off AHCI mode when restoring the BIOS configuration; this is done only for Intel controllers at this point because they map the AHCI port SCR MMIO registers even when not in AHCI mode.
  • apm_suspend() has been adjusted to restore the BIOS configuration to prevent needless timeouts when the BIOS takes over during suspend or power-off operations.
  • Small changes to the functions which save/restore BIOS/port settings to avoid pitfalls; among others, the port save/restore code now also saves and restores the port's engine status.
  • Improvements to debug logging around port resets.
  • Moved code to clear pending interrupts from ahci_reset_port() to ahci_stop_port() because both need it and resetting a port involves stopping it, first.
  • NCQ mode has found to cause problems on a Dell D630. This may be related to the hard disk used for the test but since I've never seen more than one queued command regardless of the I/O load (even during simulaneous xcopy operations), NCQ mode is now off by default and needs to be turned on via the /N switch (i.e. the the /N switch now has a reversed meaning).
  • Removed the code which attempts to establish another MMIO base address in case the one assigned by the BIOS can't be reserved via resource manager; if there's a conflict, it's extremely unlikely we would ever be able to restore the BIOS MMIO address at boot time without the BIOS clashing with whatever conflicts with the MMIO address, thus there's no point trying to do any of this.
  • Implemented a reset context hook watchdog; in the early boot phase, some components apparently don't yield the CPU so the context hook will never execute without the watchdog. Now we'll give the context hook 10 seconds to execute, otherwise the watchdog will expire and we'll call the context hook directly from the corresponding timer callback.
File size: 14.2 KB
Line 
1/******************************************************************************
2 * ahci.h - AHCI-specific constants for os2ahci.h
3 *
4 * Copyright (c) 2010 Christian Mueller. Parts copied from/inspired by the
5 * Linux AHCI driver; those parts are (c) Linux AHCI/ATA maintainers
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22/* ----------------------------- include files ----------------------------- */
23
24/* -------------------------- macros and constants ------------------------- */
25
26/******************************************************************************
27 * device prefix strings for Resource Manager
28 */
29#define RM_HD_PREFIX "HD_(%d,%d) "
30#define RM_HD_PREFIX_LEN (sizeof(RM_HD_PREFIX) - 1)
31#define RM_CD_PREFIX "CD_(%d,%d) "
32#define RM_CD_PREFIX_LEN (sizeof(RM_CD_PREFIX) - 1)
33#define RM_TAPE_PREFIX "TAPE_(%d,%d) "
34#define RM_TAPE_PREFIX_LEN (sizeof(RM_TAPE_PREFIX) - 1)
35#define RM_MAX_PREFIX_LEN RM_TAPE_PREFIX_LEN
36
37/******************************************************************************
38 * AHCI flags and constants; those were initially copied from the Linux AHCI
39 * driver but converted to macros because enums are 16 bits for OS/2 drivers
40 * (unless we use KEE and a 32-bit compiler, which we don't)
41 *
42 * Changes from the Linux source:
43 *
44 * - reduced AHCI_MAX_SG from 168 to 48 because the port-specific DMA scratch
45 * buffer needs to be less than 64K to allow mapping the whole DMA area to a
46 * 16-bit memory segment
47 *
48 * - added AHCI_MAX_SG_ELEMENT_LEN constant
49 *
50 * - replaced much of the top-level size/offset math with real structs and
51 * corresponding sizeof() directives.
52 */
53#define AHCI_PCI_BAR 5
54#define AHCI_MAX_PORTS 32
55#define AHCI_MAX_SG 48 /* hardware max is 64K */
56#define AHCI_MAX_SG_ELEMENT_LEN (1UL << 22)
57#define AHCI_MAX_CMDS 32
58#define AHCI_RX_FIS_SZ 256
59
60/* port-specific DMA scratch buffer aligned to 1024 bytes */
61#define AHCI_PORT_PRIV_DMA_SZ (((sizeof(AHCI_PORT_DMA) + 1023U) / 1024U) * 1024U)
62
63#define AHCI_IRQ_ON_SG (1UL << 31)
64#define AHCI_CMD_ATAPI (1UL << 5)
65#define AHCI_CMD_WRITE (1UL << 6)
66#define AHCI_CMD_PREFETCH (1UL << 7)
67#define AHCI_CMD_RESET (1UL << 8)
68#define AHCI_CMD_CLR_BUSY (1UL << 10)
69
70#define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */
71#define RX_FIS_SDB 0x58 /* offset of SDB FIS data */
72#define RX_FIS_UNK 0x60 /* offset of Unknown FIS data */
73
74#define board_ahci 0
75#define board_ahci_vt8251 1
76#define board_ahci_ign_iferr 2
77#define board_ahci_sb600 3
78#define board_ahci_mv 4
79#define board_ahci_sb700 5 /* for SB700 and SB800 */
80#define board_ahci_mcp65 6
81#define board_ahci_nopmp 7
82#define board_ahci_yesncq 8
83#define board_ahci_nosntf 9
84
85/* global controller registers */
86#define HOST_CAP 0x00 /* host capabilities */
87#define HOST_CTL 0x04 /* global host control */
88#define HOST_IRQ_STAT 0x08 /* interrupt status */
89#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */
90#define HOST_VERSION 0x10 /* AHCI spec. version compliancy */
91#define HOST_CCC 0x14 /* Command Completion Coalescing Control */
92#define HOST_CCC_PORTS 0x18 /* CCC ports */
93#define HOST_EM_LOC 0x1c /* Enclosure Management location */
94#define HOST_EM_CTL 0x20 /* Enclosure Management Control */
95#define HOST_CAP2 0x24 /* host capabilities, extended */
96#define HOST_BOHC 0x28 /* BIOS hand off control and status */
97
98/* HOST_CTL bits */
99#define HOST_RESET (1UL << 0) /* reset controller; self-clear */
100#define HOST_IRQ_EN (1UL << 1) /* global IRQ enable */
101#define HOST_AHCI_EN (1UL << 31) /* AHCI enabled */
102
103/* HOST_CAP bits */
104#define HOST_CAP_SXS (1UL << 5) /* Supports External SATA */
105#define HOST_CAP_EMS (1UL << 6) /* Enclosure Management support */
106#define HOST_CAP_CCC (1UL << 7) /* Command Completion Coalescing */
107#define HOST_CAP_PART (1UL << 13) /* Partial state capable */
108#define HOST_CAP_SSC (1UL << 14) /* Slumber state capable */
109#define HOST_CAP_PIO_MULTI (1UL << 15) /* PIO multiple DRQ support */
110#define HOST_CAP_FBS (1UL << 16) /* FIS-based switching support */
111#define HOST_CAP_PMP (1UL << 17) /* Port Multiplier support */
112#define HOST_CAP_ONLY (1UL << 18) /* Supports AHCI mode only */
113#define HOST_CAP_CLO (1UL << 24) /* Command List Override support */
114#define HOST_CAP_LED (1UL << 25) /* Supports activity LED */
115#define HOST_CAP_ALPM (1UL << 26) /* Aggressive Link PM support */
116#define HOST_CAP_SSS (1UL << 27) /* Staggered Spin-up */
117#define HOST_CAP_MPS (1UL << 28) /* Mechanical presence switch */
118#define HOST_CAP_SNTF (1UL << 29) /* SNotification register */
119#define HOST_CAP_NCQ (1UL << 30) /* Native Command Queueing */
120#define HOST_CAP_64 (1UL << 31) /* PCI DAC (64-bit DMA) support */
121
122/* HOST_CAP2 bits */
123#define HOST_CAP2_BOH (1UL << 0) /* BIOS/OS handoff supported */
124#define HOST_CAP2_NVMHCI (1UL << 1) /* NVMHCI supported */
125#define HOST_CAP2_APST (1UL << 2) /* Automatic partial to slumber */
126
127/* HOST_BOHC bits */
128#define HOST_BOHC_BOS (1UL << 0) /* BIOS owned (semaphore bit) */
129#define HOST_BOHC_OOS (1UL << 1) /* OS owned (semaphore bit) */
130#define HOST_BOHC_SOOE (1UL << 2) /* SMI on ownership change enable */
131#define HOST_BOHC_OOC (1UL << 3) /* OS ownership change */
132#define HOST_BOHC_BB (1UL << 4) /* BIOS is busy changing ownership */
133
134/* registers for each SATA port */
135#define PORT_LST_ADDR 0x00 /* command list DMA addr */
136#define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */
137#define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */
138#define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */
139#define PORT_IRQ_STAT 0x10 /* interrupt status */
140#define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */
141#define PORT_CMD 0x18 /* port command */
142#define PORT_TFDATA 0x20 /* taskfile data */
143#define PORT_SIG 0x24 /* device TF signature */
144#define PORT_CMD_ISSUE 0x38 /* command issue */
145#define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */
146#define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */
147#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */
148#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */
149#define PORT_SCR_NTF 0x3c /* SATA phy register: SNotification */
150
151/* PORT_IRQ_{STAT,MASK} bits */
152#define PORT_IRQ_COLD_PRES (1UL << 31) /* cold presence detect */
153#define PORT_IRQ_TF_ERR (1UL << 30) /* task file error */
154#define PORT_IRQ_HBUS_ERR (1UL << 29) /* host bus fatal error */
155#define PORT_IRQ_HBUS_DATA_ERR (1UL << 28) /* host bus data error */
156#define PORT_IRQ_IF_ERR (1UL << 27) /* interface fatal error */
157#define PORT_IRQ_IF_NONFATAL (1UL << 26) /* interface non-fatal error */
158#define PORT_IRQ_OVERFLOW (1UL << 24) /* xfer exhausted available S/G */
159#define PORT_IRQ_BAD_PMP (1UL << 23) /* incorrect port multiplier */
160#define PORT_IRQ_PHYRDY (1UL << 22) /* PhyRdy changed */
161#define PORT_IRQ_DEV_ILCK (1UL << 7) /* device interlock */
162#define PORT_IRQ_CONNECT (1UL << 6) /* port connect change status */
163#define PORT_IRQ_SG_DONE (1UL << 5) /* descriptor processed */
164#define PORT_IRQ_UNK_FIS (1UL << 4) /* unknown FIS rx'd */
165#define PORT_IRQ_SDB_FIS (1UL << 3) /* Set Device Bits FIS rx'd */
166#define PORT_IRQ_DMAS_FIS (1UL << 2) /* DMA Setup FIS rx'd */
167#define PORT_IRQ_PIOS_FIS (1UL << 1) /* PIO Setup FIS rx'd */
168#define PORT_IRQ_D2H_REG_FIS (1UL << 0) /* D2H Register FIS rx'd */
169#define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \
170 PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \
171 PORT_IRQ_UNK_FIS | PORT_IRQ_BAD_PMP)
172#define PORT_IRQ_ERROR (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | \
173 PORT_IRQ_HBUS_DATA_ERR)
174#define DEF_PORT_IRQ (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | \
175 PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | \
176 PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS)
177
178/* PORT_CMD bits */
179#define PORT_CMD_ASP (1UL << 27) /* Aggressive Slumber/Partial */
180#define PORT_CMD_ALPE (1UL << 26) /* Aggressive Link PM enable */
181#define PORT_CMD_ATAPI (1UL << 24) /* Device is ATAPI */
182#define PORT_CMD_PMP (1UL << 17) /* PMP attached */
183#define PORT_CMD_LIST_ON (1UL << 15) /* cmd list DMA engine running */
184#define PORT_CMD_FIS_ON (1UL << 14) /* FIS DMA engine running */
185#define PORT_CMD_FIS_RX (1UL << 4) /* Enable FIS receive DMA engine */
186#define PORT_CMD_CLO (1UL << 3) /* Command list override */
187#define PORT_CMD_POWER_ON (1UL << 2) /* Power up device */
188#define PORT_CMD_SPIN_UP (1UL << 1) /* Spin up device */
189#define PORT_CMD_START (1UL << 0) /* Enable port DMA engine */
190
191#define PORT_CMD_ICC_MASK (0xfUL << 28) /* i/f ICC state mask */
192#define PORT_CMD_ICC_ACTIVE (0x1UL << 28) /* Put i/f in active state */
193#define PORT_CMD_ICC_PARTIAL (0x2UL << 28) /* Put i/f in partial state */
194#define PORT_CMD_ICC_SLUMBER (0x6UL << 28) /* Put i/f in slumber state */
195
196/* driver status bits */
197#define AHCI_HFLAG_NO_NCQ (1UL << 0) /* no native cmd queuing */
198#define AHCI_HFLAG_IGN_IRQ_IF_ERR (1UL << 1) /* ignore IRQ_IF_ERR */
199#define AHCI_HFLAG_IGN_SERR_INTERNAL (1UL << 2) /* ignore SERR_INTERNAL */
200#define AHCI_HFLAG_32BIT_ONLY (1UL << 3) /* force 32bit */
201#define AHCI_HFLAG_MV_PATA (1UL << 4) /* PATA port */
202#define AHCI_HFLAG_NO_MSI (1UL << 5) /* no PCI MSI */
203#define AHCI_HFLAG_NO_PMP (1UL << 6) /* no PMP */
204#define AHCI_HFLAG_NO_HOTPLUG (1UL << 7) /* ignore PxSERR.DIAG.N */
205#define AHCI_HFLAG_SECT255 (1UL << 8) /* max 255 sectors */
206#define AHCI_HFLAG_YES_NCQ (1UL << 9) /* force NCQ cap on */
207#define AHCI_HFLAG_NO_SUSPEND (1UL << 10) /* don't suspend */
208#define AHCI_HFLAG_SRST_TOUT_IS_OFFLINE (1UL << 11) /* treat SRST timeout as
209 link offline */
210#define AHCI_HFLAG_NO_SNTF (1UL << 12) /* no sntf */
211
212#define ICH_MAP 0x90 /* ICH MAP register */
213
214/* em constants */
215#define EM_MAX_SLOTS 8
216#define EM_MAX_RETRY 5
217
218/* em_ctl bits */
219#define EM_CTL_RST (1UL << 9) /* Reset */
220#define EM_CTL_TM (1UL << 8) /* Transmit Message */
221#define EM_CTL_ALHD (1UL << 26) /* Activity LED */
222
223/* ------------------------ typedefs and structures ------------------------ */
224
225/* Primitive types
226 *
227 * Note: Since OS/2 is essentially an x86 OS and this driver, as well as the
228 * interface it's developed for, is based on x86 design patterns, we're
229 * not even going to start making a difference between little and big
230 * endian architectures. PCI is little endian, AHCI is little endian,
231 * x86 is little endian, and that's it.
232 */
233typedef unsigned char u8;
234typedef unsigned short u16;
235typedef unsigned long u32;
236
237/* AHCI S/G structure */
238typedef struct {
239 u32 addr; /* address of S/G element */
240 u32 addr_hi; /* address of S/G element (upper 32 bits) */
241 u32 reserved;
242 u32 size; /* size of S/G element - 1; the high 10 bits are flags:
243 * 31 : interrupt on completion of this S/G
244 * 30-22 : reserved */
245} AHCI_SG;
246
247/* AHCI command header */
248typedef struct {
249 u32 options; /* command options */
250 u32 status; /* command status */
251 u32 tbl_addr; /* command table address */
252 u32 tbl_addr_high; /* command table address (upper 32 bits) */
253 u32 reserved[4];
254} AHCI_CMD_HDR;
255
256/* AHCI command table */
257typedef struct {
258 u8 cmd_fis[64]; /* ATA command FIS */
259 u8 atapi_cmd[16]; /* ATAPI command */
260 u8 reserved[48];
261 AHCI_SG sg_list[AHCI_MAX_SG]; /* AHCI S/G list */
262} AHCI_CMD_TBL;
263
264/* AHCI port DMA scratch area */
265typedef struct {
266 AHCI_CMD_HDR cmd_hdr[AHCI_MAX_CMDS]; /* command headers */
267 u8 rx_fis[AHCI_RX_FIS_SZ]; /* FIS RX area */
268 AHCI_CMD_TBL cmd_tbl[AHCI_MAX_CMDS]; /* command table */
269} AHCI_PORT_DMA;
270
271/* AHCI port BIOS configuration save area */
272typedef struct {
273 u32 cmd_list; /* cmd list base address */
274 u32 cmd_list_h; /* cmd list base address high */
275 u32 fis_rx; /* FIS receive buffer */
276 u32 fis_rx_h; /* FIS receive bufffer high */
277 u32 irq_mask; /* IRQ mask */
278 u32 port_cmd; /* port engine status */
279} AHCI_PORT_CFG;
280
Note: See TracBrowser for help on using the repository browser.