1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #ifndef _SI3124REG_H
27 #define	_SI3124REG_H
28 
29 #ifdef	__cplusplus
30 extern "C" {
31 #endif
32 
33 #pragma pack(1)
34 
35 typedef struct si_sge {
36 	/* offset 0x00 */
37 	union {
38 		uint64_t _sge_addr_ll;
39 		uint32_t _sge_addr_la[2];
40 	} _sge_addr_un;
41 
42 #define	sge_addr_low	_sge_addr_un._sge_addr_la[0]
43 #define	sge_addr_high	_sge_addr_un._sge_addr_la[1]
44 #define	sge_addr	_sge_addr_un._sge_addr_ll
45 
46 	/* offset 0x08 */
47 	uint32_t sge_data_count;
48 
49 	/* offset 0x0c */
50 	uint32_t sge_trm_lnk_drd_xcf_rsvd;
51 
52 #define	SET_SGE_LNK(sge)	(sge.sge_trm_lnk_drd_xcf_rsvd = 0x40000000)
53 #define	SET_SGE_TRM(sge)	(sge.sge_trm_lnk_drd_xcf_rsvd = 0x80000000)
54 #define	IS_SGE_TRM_SET(sge)	(sge.sge_trm_lnk_drd_xcf_rsvd & 0x80000000)
55 
56 } si_sge_t;
57 
58 /* Scatter Gather Table consists of four SGE entries */
59 typedef struct si_sgt {
60 	si_sge_t sgt_sge[4];
61 } si_sgt_t;
62 
63 
64 /* Register - Host to Device FIS (from SATA spec) */
65 typedef struct fis_reg_h2d {
66 	/* offset 0x00 */
67 	uint32_t fish_type_pmp_rsvd_cmddevctl_cmd_features;
68 
69 #define	SET_FIS_TYPE(fis, type)	\
70 	((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features |= (type & 0xff))
71 
72 #define	SET_FIS_PMP(fis, pmp)	\
73 	((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features |= \
74 	    ((pmp & 0xf) << 8))
75 
76 #define	SET_FIS_CDMDEVCTL(fis, cmddevctl)	\
77 	((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features |=	\
78 		((cmddevctl & 0x1) << 15))
79 
80 #define	SET_FIS_COMMAND(fis, command)	\
81 	((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features |=	\
82 		((command & 0xff) << 16))
83 
84 #define	GET_FIS_COMMAND(fis)	\
85 	(((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features >> 16) & 0xff)
86 
87 #define	SET_FIS_FEATURES(fis, features)	\
88 	((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features |=	\
89 		((features & 0xff) << 24))
90 
91 #define	GET_FIS_FEATURES(fis)	\
92 	(((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features >> 24) & 0xff)
93 
94 	/* offset 0x04 */
95 	uint32_t fish_sector_cyllow_cylhi_devhead;
96 
97 #define	SET_FIS_SECTOR(fis, sector)	\
98 	((&fis)->fish_sector_cyllow_cylhi_devhead |= ((sector & 0xff)))
99 
100 #define	GET_FIS_SECTOR(fis)	\
101 	((&fis)->fish_sector_cyllow_cylhi_devhead & 0xff)
102 
103 #define	SET_FIS_CYL_LOW(fis, cyl_low)	\
104 	((&fis)->fish_sector_cyllow_cylhi_devhead |= ((cyl_low & 0xff) << 8))
105 
106 #define	GET_FIS_CYL_LOW(fis)	\
107 	(((&fis)->fish_sector_cyllow_cylhi_devhead >> 8) & 0xff)
108 
109 #define	SET_FIS_CYL_HI(fis, cyl_hi)	\
110 	((&fis)->fish_sector_cyllow_cylhi_devhead |= ((cyl_hi & 0xff) << 16))
111 
112 #define	GET_FIS_CYL_HI(fis)	\
113 	(((&fis)->fish_sector_cyllow_cylhi_devhead >> 16) & 0xff)
114 
115 #define	SET_FIS_DEV_HEAD(fis, dev_head)	\
116 	((&fis)->fish_sector_cyllow_cylhi_devhead |= ((dev_head & 0xff) << 24))
117 
118 #define	GET_FIS_DEV_HEAD(fis)	\
119 	(((&fis)->fish_sector_cyllow_cylhi_devhead >> 24) & 0xff)
120 
121 
122 	/* offset 0x08 */
123 	uint32_t fish_sectexp_cyllowexp_cylhiexp_featuresexp;
124 
125 #define	SET_FIS_SECTOR_EXP(fis, sectorexp)	\
126 	((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp |=	\
127 		((sectorexp & 0xff)))
128 
129 #define	GET_FIS_SECTOR_EXP(fis)	\
130 	((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp  & 0xff)
131 
132 #define	SET_FIS_CYL_LOW_EXP(fis, cyllowexp)			\
133 	((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp |= 	\
134 		((cyllowexp & 0xff) << 8))
135 
136 #define	GET_FIS_CYL_LOW_EXP(fis)			\
137 	(((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp >> 8) & 0xff)
138 
139 #define	SET_FIS_CYL_HI_EXP(fis, cylhiexp)			\
140 	((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp |= 	\
141 		((cylhiexp & 0xff) << 16))
142 
143 #define	GET_FIS_CYL_HI_EXP(fis)			\
144 	(((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp >> 16) & 0xff)
145 
146 #define	SET_FIS_FEATURES_EXP(fis, features_exp)		\
147 	((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp |= 	\
148 		((features_exp & 0xff) << 24))
149 
150 	/* offset 0x0c */
151 	uint32_t fish_sectcount_sectcountexp_rsvd_devctl;
152 
153 #define	SET_FIS_SECTOR_COUNT(fis, sector_count)	\
154 	((&fis)->fish_sectcount_sectcountexp_rsvd_devctl |= \
155 	    ((sector_count & 0xff)))
156 
157 #define	GET_FIS_SECTOR_COUNT(fis)	\
158 	((&fis)->fish_sectcount_sectcountexp_rsvd_devctl & 0xff)
159 
160 #define	SET_FIS_SECTOR_COUNT_EXP(fis, sector_count_exp)	\
161 	((&fis)->fish_sectcount_sectcountexp_rsvd_devctl |= \
162 		((sector_count_exp & 0xff) << 8))
163 
164 #define	GET_FIS_SECTOR_COUNT_EXP(fis)	\
165 	(((&fis)->fish_sectcount_sectcountexp_rsvd_devctl >> 8) & 0xff)
166 
167 #define	SET_FIS_SECTOR_DEVCTL(fis, devctl)	\
168 	((&fis)->fish_sectcount_sectcountexp_rsvd_devctl |= \
169 	    ((devctl & 0xff) << 24))
170 
171 	/* offset 0x10 */
172 	uint32_t fish_rsvd3;		/* should be zero */
173 } fis_reg_h2d_t;
174 
175 
176 
177 
178 /*
179  * Port Request Block
180  */
181 typedef struct si_prb {
182 	/* offset 0x00 */
183 	uint32_t prb_control_override;
184 
185 #define	SET_PRB_CONTROL_PKT_READ(prb)	\
186 	(prb->prb_control_override |= (0x1 << 4))
187 
188 #define	SET_PRB_CONTROL_PKT_WRITE(prb)	\
189 	(prb->prb_control_override |= (0x1 << 5))
190 
191 #define	SET_PRB_CONTROL_SOFT_RESET(prb)	\
192 	(prb->prb_control_override |= (0x1 << 7))
193 
194 	/* offset 0x04 */
195 	uint32_t prb_received_count;
196 
197 	/* offset 0x08 */
198 	fis_reg_h2d_t prb_fis; 			/* this is of 0x14 bytes size */
199 
200 	/* offset 0x1c */
201 	uint32_t prb_rsvd3;
202 
203 	/* offset 0x20 */
204 	si_sge_t prb_sge0;
205 
206 	/* offset 0x30 */
207 	si_sge_t prb_sge1;
208 
209 } si_prb_t;
210 
211 #pragma pack()
212 
213 
214 /* Various interrupt bits */
215 #define	INTR_COMMAND_COMPLETE		(0x1 << 0)
216 #define	INTR_COMMAND_ERROR		(0x1 << 1)
217 #define	INTR_PORT_READY			(0x1 << 2)
218 #define	INTR_POWER_CHANGE		(0x1 << 3)
219 #define	INTR_PHYRDY_CHANGE		(0x1 << 4)
220 #define	INTR_COMWAKE_RECEIVED		(0x1 << 5)
221 #define	INTR_UNRECOG_FIS		(0x1 << 6)
222 #define	INTR_DEV_XCHANGED		(0x1 << 7)
223 #define	INTR_8B10B_DECODE_ERROR		(0x1 << 8)
224 #define	INTR_CRC_ERROR			(0x1 << 9)
225 #define	INTR_HANDSHAKE_ERROR		(0x1 << 10)
226 #define	INTR_SETDEVBITS_NOTIFY		(0x1 << 11)
227 #define	INTR_MASK			(0xfff)
228 
229 /* Device signatures */
230 #define	SI_SIGNATURE_PORT_MULTIPLIER	0x96690101
231 #define	SI_SIGNATURE_ATAPI		0xeb140101
232 #define	SI_SIGNATURE_DISK		0x00000101
233 
234 
235 /* Global definitions */
236 #define	GLOBAL_OFFSET(si_ctlp)		(si_ctlp->sictl_global_addr)
237 #define	GLOBAL_CONTROL_REG(si_ctlp)	(GLOBAL_OFFSET(si_ctlp)+0x40)
238 #define	GLOBAL_INTERRUPT_STATUS(si_ctlp)	(GLOBAL_OFFSET(si_ctlp)+0x44)
239 
240 /* Per port definitions */
241 #define	PORT_OFFSET(si_ctlp, port)	(si_ctlp->sictl_port_addr + port*0x2000)
242 #define	PORT_LRAM(si_ctlp, port, slot)		\
243 			(PORT_OFFSET(si_ctlp, port) + 0x0 + slot*0x80)
244 #define	PORT_CONTROL_SET(si_ctlp, port)		\
245 			(PORT_OFFSET(si_ctlp, port) + 0x1000)
246 #define	PORT_STATUS(si_ctlp, port)		\
247 			(PORT_OFFSET(si_ctlp, port) + 0x1000)
248 #define	PORT_CONTROL_CLEAR(si_ctlp, port)		\
249 			(PORT_OFFSET(si_ctlp, port) + 0x1004)
250 #define	PORT_INTERRUPT_STATUS(si_ctlp, port)	\
251 			(PORT_OFFSET(si_ctlp, port) + 0x1008)
252 #define	PORT_INTERRUPT_ENABLE_SET(si_ctlp, port)	\
253 			(PORT_OFFSET(si_ctlp, port) + 0x1010)
254 #define	PORT_INTERRUPT_ENABLE_CLEAR(si_ctlp, port) \
255 			(PORT_OFFSET(si_ctlp, port) + 0x1014)
256 #define	PORT_COMMAND_ERROR(si_ctlp, port) 	\
257 			(PORT_OFFSET(si_ctlp, port) + 0x1024)
258 #define	PORT_SLOT_STATUS(si_ctlp, port)	(PORT_OFFSET(si_ctlp, port) + 0x1800)
259 
260 #define	PORT_SCONTROL(si_ctlp, port)	(PORT_OFFSET(si_ctlp, port) + 0x1f00)
261 #define	PORT_SSTATUS(si_ctlp, port)	(PORT_OFFSET(si_ctlp, port) + 0x1f04)
262 #define	PORT_SERROR(si_ctlp, port)	(PORT_OFFSET(si_ctlp, port) + 0x1f08)
263 #define	PORT_SACTIVE(si_ctlp, port)	(PORT_OFFSET(si_ctlp, port) + 0x1f0c)
264 
265 #define	PORT_COMMAND_ACTIVATION(si_ctlp, port, slot)	\
266 			(PORT_OFFSET(si_ctlp, port) + 0x1c00 + slot*0x8)
267 
268 #define	PORT_SIGNATURE_MSB(si_ctlp, port, slot)		\
269 			(PORT_OFFSET(si_ctlp, port) + slot*0x80 + 0x0c)
270 #define	PORT_SIGNATURE_LSB(si_ctlp, port, slot)		\
271 			(PORT_OFFSET(si_ctlp, port) + slot*0x80 + 0x14)
272 
273 /* Interesting bits of Port Control Set register */
274 #define	PORT_CONTROL_SET_BITS_PORT_RESET		0x1
275 #define	PORT_CONTROL_SET_BITS_DEV_RESET			0x2
276 #define	PORT_CONTROL_SET_BITS_PORT_INITIALIZE		0x4
277 #define	PORT_CONTROL_SET_BITS_PACKET_LEN		0x20
278 #define	PORT_CONTROL_SET_BITS_RESUME			0x40
279 #define	PORT_CONTROL_SET_BITS_PM_ENABLE			0x2000
280 
281 /* Interesting bits of Port Control Clear register */
282 #define	PORT_CONTROL_CLEAR_BITS_PORT_RESET		0x1
283 #define	PORT_CONTROL_CLEAR_BITS_INTR_NCoR		0x8
284 #define	PORT_CONTROL_CLEAR_BITS_PACKET_LEN		0x20
285 #define	PORT_CONTROL_CLEAR_BITS_RESUME			0x40
286 
287 /* Interesting bits of Port Status register */
288 #define	PORT_STATUS_BITS_PORT_READY		0x80000000
289 
290 /* Interesting bits of Global Control register */
291 #define	GLOBAL_CONTROL_REG_BITS_CLEAR		0x00000000
292 
293 #define	POST_PRB_ADDR(si_ctlp, si_portp, port, slot)			  \
294 	(void) ddi_dma_sync(si_portp->siport_prbpool_dma_handle,	  \
295 			slot * sizeof (si_prb_t),			  \
296 			sizeof (si_prb_t),				  \
297 			DDI_DMA_SYNC_FORDEV);				  \
298 									  \
299 	(void) ddi_dma_sync(si_portp->siport_sgbpool_dma_handle,	  \
300 			slot * sizeof (si_sgblock_t) * si_dma_sg_number,  \
301 			sizeof (si_sgblock_t) * si_dma_sg_number,	  \
302 			DDI_DMA_SYNC_FORDEV);				  \
303 									  \
304 	ddi_put64(si_ctlp->sictl_port_acc_handle, 			  \
305 		(uint64_t *)PORT_COMMAND_ACTIVATION(si_ctlp, port, slot), \
306 		(uint64_t)(si_portp->siport_prbpool_physaddr + 		  \
307 		slot*sizeof (si_prb_t)));
308 
309 #define	SI_SLOT_MASK	0x7fffffff
310 #define	SI_NUM_SLOTS	0x1f		/* 31 */
311 
312 #define	ATTENTION_BIT	0x80000000
313 #define	IS_ATTENTION_RAISED(slot_status)	(slot_status & ATTENTION_BIT)
314 
315 #define	SI3124_DEV_ID	0x3124
316 #define	SI3132_DEV_ID	0x3132
317 #define	SI3531_DEV_ID	0x3531
318 
319 #define	PM_CSR(devid)	 ((devid == SI3124_DEV_ID) ? 0x68 : 0x58)
320 
321 #define	REGISTER_FIS_H2D	0x27
322 
323 #define	SI31xx_INTR_PORT_MASK	0xf
324 
325 /* PCI BAR registers */
326 #define	PCI_BAR0	1	/* Contains global register set */
327 #define	PCI_BAR1	2	/* Contains port register set */
328 
329 /* Port Status and Control Registers (from port multiplier spec) */
330 #define	PSCR_REG0	0
331 #define	PSCR_REG1	1
332 #define	PSCR_REG2	2
333 #define	PSCR_REG3	3
334 
335 /* SStatus bit fields */
336 #define	SSTATUS_DET_MASK	0x0000000f
337 #define	SSTATUS_SPD_MASK	0x000000f0
338 #define	SSTATUS_SPD_SHIFT	4
339 #define	SSTATUS_IPM_MASK	0x00000f00
340 #define	SSTATUS_IPM_SHIFT	8
341 
342 
343 #define	SSTATUS_DET_NODEV_NOPHY		 0x0 /* No device, no PHY */
344 #define	SSTATUS_DET_DEVPRESENT_NOPHY	 0x1 /* Dev present, no PHY */
345 #define	SSTATUS_DET_DEVPRESENT_PHYONLINE 0x3 /* Dev present, PHY online */
346 
347 #define	SSTATUS_IPM_NODEV_NOPHY			0x0 /* No dev, no PHY */
348 #define	SSTATUS_IPM_INTERFACE_ACTIVE		0x1 /* Interface active */
349 #define	SSTATUS_IPM_INTERFACE_POWERPARTIAL	0x2 /* partial power mgmnt */
350 #define	SSTATUS_IPM_INTERFACE_POWERSLUMBER	0x6 /* slumber power mgmt */
351 
352 /* SControl bit fields */
353 #define	SCONTROL_DET_MASK	0x0000000f
354 
355 
356 
357 
358 /* Command Error codes */
359 #define	CMD_ERR_DEVICEERRROR		1
360 #define	CMD_ERR_SDBERROR		2
361 #define	CMD_ERR_DATAFISERROR		3
362 #define	CMD_ERR_SENDFISERROR		4
363 #define	CMD_ERR_INCONSISTENTSTATE	5
364 #define	CMD_ERR_DIRECTIONERROR		6
365 #define	CMD_ERR_UNDERRUNERROR		7
366 #define	CMD_ERR_OVERRUNERROR		8
367 #define	CMD_ERR_PACKETPROTOCOLERROR	11
368 #define	CMD_ERR_PLDSGTERRORBOUNDARY	16
369 #define	CMD_ERR_PLDSGTERRORTARETABORT	17
370 #define	CMD_ERR_PLDSGTERRORMASTERABORT	18
371 #define	CMD_ERR_PLDSGTERRORPCIERR	19
372 #define	CMD_ERR_PLDCMDERRORBOUNDARY	24
373 #define	CMD_ERR_PLDCMDERRORTARGETABORT	25
374 #define	CMD_ERR_PLDCMDERRORMASTERABORT	26
375 #define	CMD_ERR_PLDCMDERORPCIERR	27
376 #define	CMD_ERR_PSDERRORTARGETABORT	33
377 #define	CMD_ERR_PSDERRORMASTERABORT	34
378 #define	CMD_ERR_PSDERRORPCIERR		35
379 #define	CMD_ERR_SENDSERVICEERROR	36
380 
381 #ifdef	__cplusplus
382 }
383 #endif
384 
385 #endif /* _SI3124REG_H */
386