ac.h revision 1341:6d7c4f090a72
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 2006 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#ifndef	_SYS_AC_H
28#define	_SYS_AC_H
29
30#pragma ident	"%Z%%M%	%I%	%E% SMI"
31
32#ifdef	__cplusplus
33extern "C" {
34#endif
35
36/* useful debugging stuff */
37#define	AC_ATTACH_DEBUG		0x1
38#define	AC_REGISTERS_DEBUG	0x2
39
40/*
41 * OBP supplies us with two register sets for the AC nodes. They are:
42 *
43 *	0		miscellaneous regs
44 *	1		Cache tags
45 *
46 * We do not use the cache tags for anything in the kernel, so we
47 * do not map them in.
48 */
49
50/* Macros for physical acccess, fhc.h has to be present */
51#define	AC_OFFSET		0x00001000000ull
52#define	AC_CENTRAL		0x80000000
53#define	AC_ARB_FAST		0x00002000
54#define	AC_BCSR(board)		(FHC_BOARD_BASE(2*(board)) + FHC_OFFSET + \
55				AC_OFFSET + AC_OFF_BCSR)
56
57/* Register set 0 Offsets */
58#define	AC_OFF_BRCS		0x10
59#define	AC_OFF_BCSR		0x20
60#define	AC_OFF_ESR		0x30
61#define	AC_OFF_EMR		0x40
62#define	AC_OFF_MEMCTL		0x60
63#define	AC_OFF_MEMDEC0		0x70
64#define	AC_OFF_MEMDEC1		0x80
65#define	AC_OFF_UPA0		0x2000
66#define	AC_OFF_UPA1		0x4000
67#define	AC_OFF_CNTR		0x6000
68#define	AC_OFF_MCCR		0x6020
69
70/* Use predefined strings to name the kstats from this driver. */
71#define	AC_KSTAT_NAME		"address_controller"
72#define	MEMCTL_KSTAT_NAMED	"acmemctl"
73#define	MEMDECODE0_KSTAT_NAMED	"acmemdecode0"
74#define	MEMDECODE1_KSTAT_NAMED	"acmemdecode1"
75#define	CNTR_KSTAT_NAMED	"accounter"
76#define	MCCR_KSTAT_NAMED	"acmccr"
77#define	BANK_0_KSTAT_NAMED	"acbank0"
78#define	BANK_1_KSTAT_NAMED	"acbank1"
79
80/* used for the picN kstats */
81#define	AC_NUM_PICS	2
82#define	AC_COUNTER_TO_PIC0(CNTR)	((CNTR) & 0xFFFFFFFFULL)
83#define	AC_COUNTER_TO_PIC1(CNTR)	((CNTR) >> 32)
84
85/* used to clear/set the pcr */
86#define	AC_CLEAR_PCR(PCR)		((PCR) & ~(0x3F3F))
87#define	AC_SET_HOT_PLUG(PCR)		((PCR) | (0x3F3F))
88
89/* used for programming the pic */
90#define	AC_SET_PIC_BUS_PAUSE(BRD)	(0x80000000LL - 0x9ac4 - ((BRD) << 3))
91
92/* defines for AC Board Configuration and Status Register */
93#define	NO_CACHE	0
94#define	CACHE_512K	2
95#define	CACHE_1M	3
96#define	CACHE_2M	4
97#define	CACHE_4M	5
98#define	CACHE_8M	6
99#define	CACHE_16M	7
100
101#define	ARB_MASTER	0x8000
102#define	ARB_INIT	0x4000
103#define	ARB_FAST	0x2000
104#define	FTC_CPAR	0x0200
105
106#define	AC_CSR_REFEN		(1ULL << 27)
107
108/* defines for Memory decode registers */
109#define	AC_MEM_VALID		0x8000000000000000ULL
110
111/* size of a memory SIMM group */
112#define	RASIZE0(memctl)		(8 << ((((memctl) >> 8) & 0x7) << 1))
113#define	RASIZE1(memctl)		(8 << ((((memctl) >> 11) & 0x7) << 1))
114#define	RATBL0(memctl)		(((memctl) >> 8) & 0x7)
115#define	RATBL1(memctl)		(((memctl) >> 11) & 0x7)
116
117/*
118 * Interleave factor of a memory SIMM group.
119 * Possible values are 1, 2, 4, 8, and 16. 1 means not interleaved.
120 * Larger groups can be interleaved with smaller groups. Groups
121 * on the same board can be interleaved as well.
122 */
123#define	INTLV0(memctl)		(1 << ((memctl) & 0x7))
124#define	INTLV1(memctl)		(1 << (((memctl) >> 3) & 0x7))
125#define	INTVAL0(memctl)		((memctl) & 0x7)
126#define	INTVAL1(memctl)		(((memctl) >> 3) & 0x7)
127
128/*
129 * Physical base mask of a memory SIMM group. Note that this is
130 * not the real physical base, and is just used to match up the
131 * interleaving of groups. The mask bits (UK) are used to mask
132 * out the match (UM) field so that the bases can be compared.
133 */
134#define	GRP_UK(memdec)	(((memdec) >> 39) & 0xFFF)
135#define	GRP_UM(memdec)	(((memdec) >> 12) & 0x7FFF)
136#define	GRP_BASE(memdec) (GRP_UM(memdec) & ~(GRP_UK(memdec)))
137#define	GRP_LK(memdec)	(((memdec) >> 6) & 0xf)
138#define	GRP_LM(memdec)	((memdec) & 0xf)
139#define	GRP_LBASE(memdec) (GRP_LM(memdec) & ~(GRP_LK(memdec)))
140#define	GRP_REALBASE(m) ((GRP_BASE(m) << 26) | (GRP_LBASE(m) << 6))
141#define	GRP_UK2SPAN(memdec) ((GRP_UK(memdec) + 1) << 26)
142#define	GRP_SPANMB(memdec) (GRP_UK2SPAN(memdec) >> 20)
143
144/*
145 * memory states and conditions for sunfire memory system
146 */
147enum ac_bank_id { Bank0 = 0, Bank1 = 1 };
148enum ac_bank_status { StUnknown = 0, StNoMem, StBad, StActive, StSpare };
149enum ac_bank_condition { ConUnknown = 0, ConOK, ConFailing, ConFailed,
150			ConTest, ConBad };
151
152/*
153 * AC memory bank ioctl interface.
154 */
155
156/* 'G' (for gigabytes!) does not appear to be used elsewhere in the kernel */
157#define	AC_IOC		('G'<<8)
158
159/*
160 * For all AC_MEM_ ioctls the arg pointer points to a sysc_cfga_cmd_t
161 * except for AC_MEM_ADMIN_VER. The private pointer then points to a
162 * structure of the appropriate type, if required.
163 */
164#define	AC_MEM_ADMIN_VER	(AC_IOC|0)	/* arg is &ac_mem_version_t */
165#define	AC_MEM_CONFIGURE	(AC_IOC|1)	/* private == NULL */
166#define	AC_MEM_UNCONFIGURE	(AC_IOC|2)	/* private == NULL */
167#define	AC_MEM_STAT		(AC_IOC|3)	/* ac_stat_t */
168#define	AC_MEM_TEST_START	(AC_IOC|4)	/* ac_mem_test_start_t */
169#define	AC_MEM_TEST_STOP	(AC_IOC|5)	/* ac_mem_test_stop_t */
170#define	AC_MEM_TEST_READ	(AC_IOC|6)	/* ac_mem_test_read_t */
171#define	AC_MEM_TEST_WRITE	(AC_IOC|7)	/* ac_mem_test_write_t */
172#define	AC_MEM_EXERCISE		(AC_IOC|128)	/* various */
173
174#define	AC_OUTPUT_LEN		MAXPATHLEN		/* output str len */
175
176typedef enum {
177	AC_ERR_DEFAULT = 0,	/* generic errors */
178	AC_ERR_INTRANS,		/* hardware in transition */
179	AC_ERR_UTHREAD,		/* can't stop user thread */
180	AC_ERR_KTHREAD,		/* can't stop kernel thread */
181	AC_ERR_SUSPEND,		/* can't suspend a device */
182	AC_ERR_RESUME,		/* can't resume a device */
183	AC_ERR_POWER,		/* not enough power for slot */
184	AC_ERR_COOLING,		/* not enough cooling for slot */
185	AC_ERR_PRECHARGE,	/* not enough precharge for slot */
186	AC_ERR_HOTPLUG,		/* Hot Plug Unavailable */
187	AC_ERR_HW_COMPAT,	/* incompatible hardware found during dr */
188	AC_ERR_NON_DR_PROM,	/* prom not support Dynamic Reconfiguration */
189	AC_ERR_CORE_RESOURCE,	/* core resource cannot be removed */
190	AC_ERR_PROM,		/* error encountered in OBP/POST */
191	AC_ERR_DR_INIT,		/* error encountered in sysc_dr_init op */
192	AC_ERR_NDI_ATTACH,	/* error encountered in NDI attach operations */
193	AC_ERR_NDI_DETACH,	/* error encountered in NDI detach operations */
194	AC_ERR_RSTATE,		/* wrong receptacle state */
195	AC_ERR_OSTATE,		/* wrong occupant state */
196	AC_ERR_COND,		/* invalid condition */
197	AC_ERR_BD,		/* invalid board id */
198	AC_ERR_BD_TYPE,		/* invalid board type */
199	AC_ERR_BD_STATE,	/* invalid board state */
200	AC_ERR_MEM_PERM,	/* no write permission */
201	AC_ERR_MEM_BK,		/* invalid memory bank */
202	AC_ERR_MEM_TEST,	/* invalid memory test id */
203	AC_ERR_MEM_TEST_PAR,	/* invalid memory test parameter(s) */
204	AC_ERR_KPM_CANCELLED,	/* kphysm_del_cancel (for complete) */
205	AC_ERR_KPM_REFUSED,	/* kphysm_pre_del failed (for complete) */
206	AC_ERR_KPM_SPAN,	/* memory already in use (add) */
207	AC_ERR_KPM_DUP,		/* memory span duplicate (delete) */
208	AC_ERR_KPM_FAULT,	/* memory access test failed (add) */
209	AC_ERR_KPM_RESOURCE,	/* some resource was not available */
210	AC_ERR_KPM_NOTSUP,	/* operation not supported */
211	AC_ERR_KPM_NOHANDLES,	/* cannot allocate any more handles */
212	AC_ERR_KPM_NONRELOC,	/* non-relocatable pages in span */
213	AC_ERR_KPM_HANDLE,	/* bad handle supplied */
214	AC_ERR_KPM_BUSY,	/* memory in span is being deleted */
215	AC_ERR_KPM_NOTVIABLE,	/* vM viability test failed */
216	AC_ERR_KPM_SEQUENCE,	/* function called out of sequence */
217	AC_ERR_KPM_NOWORK,	/* no pages to delete */
218	AC_ERR_KPM_NOTFINISHED,	/* thread not finished */
219	AC_ERR_KPM_NOTRUNNING,	/* thread not running */
220	AC_ERR_VMEM,		/* insufficient virtual memory */
221	AC_ERR_INTR,		/* delete interrupt by user */
222	AC_ERR_TIMEOUT,		/* delete timed out */
223	AC_ERR_MEM_DEINTLV	/* could not de-interleave memory */
224} ac_err_t;
225
226/*
227 * Config admin command structure for AC_MEM ioctls.
228 */
229typedef struct ac_cfga_cmd {
230	uint_t		force:1;	/* force this state transition */
231	uint_t		test:1;		/* Need to test hardware */
232	int		arg;		/* generic data for test */
233	ac_err_t	errtype;	/* error code returned */
234	char		*outputstr;	/* output returned from ioctl */
235	void		*private;	/* command private data */
236} ac_cfga_cmd_t;
237
238typedef struct ac_cfga_cmd32 {
239	uint_t		force:1;	/* force this state transition */
240	uint_t		test:1;		/* Need to test hardware */
241	int		arg;		/* generic data for test */
242	ac_err_t	errtype;	/* error code returned */
243	caddr32_t	outputstr;	/* output returned from ioctl */
244	caddr32_t	private;	/* command private data */
245} ac_cfga_cmd32_t;
246
247typedef uint_t ac_mem_version_t;		/* platform interface rev */
248#define	AC_MEM_ADMIN_VERSION	1
249
250typedef uint_t mem_test_handle_t;
251
252typedef struct {
253	uint64_t		module_id;
254	uint64_t		afsr;
255	uint64_t		afar;
256	uint64_t		udbh_error_reg;
257	uint64_t		udbl_error_reg;
258} sunfire_processor_error_regs_t;
259
260/*
261 * page_size gives the requires size for the read or write buffer.
262 * A read can be restricted to one or more line_size units starting
263 * at a multiple of line_size units from the start of the page.
264 * afar_base is the physical base of the bank being tested so
265 * that the afar value can be translated to an offset into the bank.
266 */
267typedef struct {
268	mem_test_handle_t	handle;
269	pid_t			tester_pid;	/* PID of test starter */
270	sysc_cfga_cond_t	prev_condition;
271	u_longlong_t		bank_size;	/* bytes */
272	uint_t			page_size;	/* bytes */
273	uint_t			line_size;	/* bytes */
274	u_longlong_t		afar_base;
275} ac_mem_test_start_t;
276
277typedef struct {
278	mem_test_handle_t	handle;
279	sysc_cfga_cond_t	condition;
280} ac_mem_test_stop_t;
281
282/*
283 * line_offset is in the range 0 - (page_size/line_size)-1
284 * line_count is in the range 1 - (page_size/line_size)
285 */
286typedef struct {
287	u_longlong_t		page_num;
288	uint_t			line_offset;
289	uint_t			line_count;
290} ac_test_addr_t;
291
292/*
293 * Data will be transferred in/out of the buffer at:
294 * 		(page_buf + (line_offset*line_size))
295 */
296typedef struct {
297	mem_test_handle_t	handle;
298	void			*page_buf;
299	ac_test_addr_t		address;
300	sunfire_processor_error_regs_t	*error_buf;
301} ac_mem_test_read_t;
302
303typedef struct {
304	mem_test_handle_t	handle;
305	void			*page_buf;
306	ac_test_addr_t		address;
307} ac_mem_test_write_t;
308
309#ifdef _SYSCALL32
310
311/* Kernel's view of ILP32 structure version. */
312
313typedef struct {
314	mem_test_handle_t	handle;
315	caddr32_t		page_buf;		/* void * */
316	ac_test_addr_t		address;
317	caddr32_t		error_buf; /* sunfire_processor_error_regs_t */
318} ac_mem_test_read32_t;
319
320typedef struct {
321	mem_test_handle_t	handle;
322	caddr32_t		page_buf;		/* void * */
323	ac_test_addr_t		address;
324} ac_mem_test_write32_t;
325
326#endif /* _SYSCALL32 */
327
328/* structure returned from AC_MEM_STAT ioctl */
329typedef struct {
330	sysc_cfga_rstate_t	rstate;
331	sysc_cfga_ostate_t	ostate;
332	sysc_cfga_cond_t	condition;
333	time_t			status_time;
334	uint_t			board;
335	uint_t			real_size;
336	uint_t			use_size;
337	uint_t			busy;		/* add/delete in progress */
338	uint_t			page_size;	/* bytes */
339	uint64_t		phys_pages;
340	uint64_t		managed;
341	uint64_t		nonrelocatable;
342	/* to supply address, group, info */
343	uint64_t		ac_memctl;
344	uint64_t		ac_decode0;
345	uint64_t		ac_decode1;
346} ac_stat_t;
347
348#ifdef _SYSCALL32
349
350/* Kernel's view of ILP32 structure version. */
351
352typedef struct {
353	sysc_cfga_rstate_t	rstate;
354	sysc_cfga_ostate_t	ostate;
355	sysc_cfga_cond_t	condition;
356	time32_t		status_time;
357	uint_t			board;
358	uint_t			real_size;
359	uint_t			use_size;
360	uint_t			busy;		/* add/delete in progress */
361	uint_t			page_size;	/* bytes */
362	uint64_t		phys_pages;
363	uint64_t		managed;
364	uint64_t		nonrelocatable;
365	/* to supply address, group, info */
366	uint64_t		ac_memctl;
367	uint64_t		ac_decode0;
368	uint64_t		ac_decode1;
369} ac_stat32_t;
370
371#endif /* _SYSCALL32 */
372
373/* Command values in cmd_cfga.arg for the AC_MEM_EXERCISE ioctl. */
374#define	AC_MEMX_RELOCATE_ALL	0
375
376/* Stats structure for AC_MEMX_RELOCATE_ALL (cmd_cfga.private != NULL). */
377struct ac_memx_relocate_stats {
378	uint_t		base;
379	uint_t		npgs;
380	uint_t		nopaget;
381	uint_t		nolock;
382	uint_t		isfree;
383	uint_t		reloc;
384	uint_t		noreloc;
385};
386
387/* End of ioctl interface. */
388
389#if defined(_KERNEL)
390
391typedef struct {
392	ac_cfga_cmd_t	cmd_cfga;
393	char		*errbuf;	/* internal error buffer */
394	struct ac_soft_state *softsp;
395	uint_t		bank;		/* Decoded bank number. */
396} ac_cfga_pkt_t;
397
398#define	AC_ERR_SET(pkt, err)	(pkt)->cmd_cfga.errtype = (err)
399
400#define	MEM_BOARD_VISIBLE(BD) \
401		((BD)->sc.rstate == SYSC_CFGA_RSTATE_CONNECTED && \
402		(BD)->sc.ostate == SYSC_CFGA_OSTATE_CONFIGURED)
403
404#ifndef	TRUE
405#define	TRUE (1)
406#endif
407#ifndef	FALSE
408#define	FALSE (0)
409#endif
410
411#define	AC_BANK0_STATUS		"bank-0-status"
412#define	AC_BANK1_STATUS		"bank-1-status"
413#define	AC_BANK_NOMEM		"nomem"
414#define	AC_BANK_OK		"ok"
415#define	AC_BANK_SPARE		"spare"
416#define	AC_BANK_FAILED		"failed"
417
418/*
419 * Test for a valid size setting. The size must be set as
420 * a contiguous number of bits starting at the least significant bit.
421 * Adding one to such a number causes a carry to be propagated to
422 * the first zero bit, eg 00111 -> 01000. Thus for a correctly
423 * formed value, the AND of the two numbers is 0.
424 */
425#define	GRP_SIZE_IS_SET(memdec)	((GRP_UK(memdec) & (GRP_UK(memdec) + 1)) == 0)
426
427/* set the decode register bits according to the desired bank layout */
428#define	SETUP_DECODE(addr, mb, intlv, group) \
429	((((addr) >> 26) & 0x7fffULL) << 12) |			/* UM */ \
430	((((mb) >> 6) - 1ULL) << 39) |				/* UK */ \
431	((group) & 0xfULL) |					/* LM */ \
432	((0xfULL << (intlv) & 0xfULL) << 6)			/* LK */
433
434/*
435 * Driver minor number macros.
436 */
437#define	AC_GETINSTANCE(M)	((M) >> 1)
438#define	AC_GETBANK(M)		((M) & 1)
439#define	AC_PUTINSTANCE(I)	((I) << 1)
440
441/*
442 * Attachment point names.
443 */
444#define	NAME_BANK0	"bank0"
445#define	NAME_BANK1	"bank1"
446
447/*
448 * Memory Database
449 * This information is generally accessed through the bd_list so we will
450 * just protect it by that for now.
451 */
452struct ac_mem_info {
453	int busy;				/* A bank is in transition */
454	time_t status_change;			/* Time of last change */
455
456	sysc_cfga_rstate_t rstate;
457	sysc_cfga_ostate_t ostate;
458	sysc_cfga_cond_t condition;
459	uint_t real_size;			/* Real size in MB of bank */
460	uint_t use_size;			/* In use size in MB */
461};
462
463/* Structures used in the driver to manage the hardware */
464struct ac_soft_state {
465	dev_info_t *dip;	/* dev info of myself */
466	dev_info_t *pdip;	/* dev info of my parent */
467	int board;		/* Board number for this AC */
468
469	/* fields protected by bd_list lock */
470	struct ac_mem_info bank[2];	/* memory bank information */
471
472	/* Mapped addresses of registers */
473	void *ac_base;		/* Base address of Address Controller */
474	volatile uint32_t *ac_id;		/* ID register */
475	volatile uint64_t *ac_memctl;		/* Memory Control */
476	volatile uint64_t *ac_memdecode0;	/* Memory Decode 0 */
477	volatile uint64_t *ac_memdecode1;	/* Memory Decode 1 */
478	volatile uint64_t *ac_counter;		/* AC counter register */
479	volatile uint32_t *ac_mccr;		/* AC Counter control */
480	kstat_t *ac_ksp;
481	kstat_t	*ac_counters_ksp;		/* performance counter kstat */
482};
483
484extern void	ac_blkcopy(caddr_t, caddr_t, uint_t, uint_t);
485extern void	ac_mapin(uint64_t, caddr_t);
486extern void	ac_unmap(caddr_t);
487
488/* kstat structure used by ac to pass data to user programs. */
489struct ac_kstat {
490	struct kstat_named ac_memctl;		/* AC Memory control */
491	struct kstat_named ac_memdecode0;	/* AC Memory Decode Bank 0 */
492	struct kstat_named ac_memdecode1;	/* AC Memory Decode Bank 1 */
493	struct kstat_named ac_mccr;		/* AC Mem Counter Control */
494	struct kstat_named ac_counter;		/* AC Counter */
495	struct kstat_named ac_bank0_status;
496	struct kstat_named ac_bank1_status;
497};
498
499#endif	/* _KERNEL */
500
501#ifdef	__cplusplus
502}
503#endif
504
505#endif	/* _SYS_AC_H */
506