summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4u/sys/sbdpriv.h
blob: ddcd9d7ca30b8f33ac5ba0b0837ec31ab8d4a695 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_SBDPRIV_H
#define	_SYS_SBDPRIV_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/processor.h>
#include <sys/obpdefs.h>
#include <sys/memlist.h>
#include <sys/sbd_ioctl.h>
#include <sys/mem_config.h>
#include <sys/sbd.h>
#ifdef DEBUG
#include <sys/promif.h>
#endif


/*
 * This structure passes the information when the caller requests to
 * reserve a portion of unconfigured memory. It is also used to release
 * previously reserved memory
 */
struct sbd_mres {
	uint64_t	new_base_pa;	/* new base addr for physintalled */
	uint64_t	reserved_pa;	/* addr of the reserved mem */
	uint64_t	size;		/* size of the reserved chunk. */
};

int sbd_memory_reserve(dev_info_t *, uint64_t, struct sbd_mres *);
int sbd_memory_release(dev_info_t *, uint64_t, struct sbd_mres *);

/*	This error type is used inside sbd only */
typedef struct {
	int	e_errno;
	int	e_code;
	char	e_rsc[MAXPATHLEN];
} sbderror_t;

#include <sys/sbd.h>
#include <sys/sbd_error.h>

typedef enum {
	SBD_STATE_EMPTY = 0,
	SBD_STATE_OCCUPIED,
	SBD_STATE_CONNECTED,
	SBD_STATE_UNCONFIGURED,
	SBD_STATE_PARTIAL,
	SBD_STATE_CONFIGURED,
	SBD_STATE_RELEASE,
	SBD_STATE_UNREFERENCED,
	SBD_STATE_FATAL,
	SBD_STATE_MAX
} sbd_istate_t;

typedef struct {
	sbderror_t	*errp;
	sbd_flags_t	flags;
} sbd_treeinfo_t;

/*
 * generic flags (sbd_handle.h_flags)
 */
#define	SBD_FLAG_DEVI_FORCE	0x00000001

/* mirror of SBD_FLAG_FORCE from sbd_ioctl.h */
#define	SBD_IOCTL_FLAG_FORCE	0x00000004

#define	SBD_USER_FLAG_MASK	0x0000ffff

#define	SBD_KERN_FLAG_MASK	0xffff0000	/* no flags in use */

/*
 * Translation macros for sbd->sbdp flags
 */
#define	SBD_2_SBDP_FLAGS(f) (((f) & SBD_IOCTL_FLAG_FORCE) ? \
				SBDP_IOCTL_FLAG_FORCE : 0)

typedef struct sbd_handle {
	void		*h_sbd;
	sbderror_t	*h_err;
	dev_t		h_dev;		/* dev_t of opened device */
	int		h_cmd;		/* ioctl argument */
	int		h_mode;		/* device open mode */
	sbd_flags_t	h_flags;
	sbd_ioctl_arg_t	*h_iap;		/* points to kernel copy of ioargs */
	sbdp_opts_t	h_opts;		/* points to the platform options */
} sbd_handle_t;

#define	SBD_HD2ERR(hd)		((hd)->h_err)
#define	SBD_GET_ERR(ep)		((ep)->e_code)
#define	SBD_SET_ERR(ep, ec)	((ep)->e_code = (ec))
#define	SBD_GET_ERRNO(ep)	((ep)->e_errno)
#define	SBD_SET_ERRNO(ep, en)	((ep)->e_errno = (en))
#define	SBD_GET_ERRSTR(ep)	((ep)->e_rsc)

#define	SBD_SET_ERRSTR(ep, es)	\
{ \
	if ((es) && (*(es) != '\0')) \
		(void) strncpy((ep)->e_rsc, (es), MAXPATHLEN); \
}

#define	SBD_SET_IOCTL_ERR(ierr, code, rsc) \
{ \
	(ierr)->e_code = (int)(code); \
	if ((rsc) && (*(rsc) != '\0')) \
		bcopy((caddr_t)(rsc), \
			(caddr_t)(ierr)->e_rsc, \
			sizeof ((ierr)->e_rsc)); \
}

#define	SBD_FREE_ERR(ep) \
	((ep)->e_rsc[0] = '\0')

#define	SBD_GET_PERR(spe, ep) \
{ \
	(ep)->e_errno = EIO; \
	(ep)->e_code = (spe)->e_code; \
	if (*((spe)->e_rsc) != '\0') \
		bcopy((caddr_t)((spe)->e_rsc), \
			(caddr_t)((ep))->e_rsc, \
			sizeof (((ep))->e_rsc)); \
}

/*
 * dev_t is shared by PIM and PSM layers.
 *
 * Format = 31......16,15.......0
 *	    |   PIM   |   PSM   |
 */
#define	_SBD_DEVPIM_SHIFT	16
#define	_SBD_DEVPIM_MASK		0xffff
#define	_SBD_DEVPSM_MASK		0xffff

#define	SBD_GET_MINOR2INST(d)	(((d) >> _SBD_DEVPIM_SHIFT) & _SBD_DEVPIM_MASK)
#define	SBD_MAKE_MINOR(i, m) \
			((((i) & _SBD_DEVPIM_MASK) << _SBD_DEVPIM_SHIFT) | \
			((m) & _SBD_DEVPSM_MASK))

#define	GETSTRUCT(t, n) \
		((t *)kmem_zalloc((size_t)(n) * sizeof (t), KM_SLEEP))
#define	FREESTRUCT(p, t, n) \
		(kmem_free((caddr_t)(p), sizeof (t) * (size_t)(n)))

#define	GET_SOFTC(i)		ddi_get_soft_state(sbd_g.softsp, (i))
#define	ALLOC_SOFTC(i)		ddi_soft_state_zalloc(sbd_g.softsp, (i))
#define	FREE_SOFTC(i)		ddi_soft_state_free(sbd_g.softsp, (i))

/*
 * Per instance soft-state structure.
 */
typedef struct sbd_softstate {
	void		*sbd_boardlist;
	int		max_boards;
	int		wnode;
} sbd_softstate_t;

/*
 * dr Global data elements
 */
typedef struct {
	sbd_softstate_t	*softsp;	/* pointer to initialize soft state */
} sbd_global;

typedef struct {
	sbderror_t	dv_error;
	dev_info_t	*dv_dip;
} sbd_devlist_t;

extern int	plat_max_io_units_per_board();
extern int	plat_max_cmp_units_per_board();
extern int	plat_max_cpu_units_per_board();
extern int	plat_max_mem_units_per_board();
#define	MAX_IO_UNITS_PER_BOARD		plat_max_io_units_per_board()
#define	MAX_CMP_UNITS_PER_BOARD		plat_max_cmp_units_per_board()
#define	MAX_CPU_UNITS_PER_BOARD		plat_max_cpu_units_per_board()
#define	MAX_MEM_UNITS_PER_BOARD		plat_max_mem_units_per_board()
#define	SBD_MAX_UNITS_PER_BOARD		8
/* If any of the max units exceeds 5, this must be adjusted	*/

#define	SBD_MAX_INSTANCES		16

#define	SBD_NUM_STATES		((int)SBD_STATE_MAX)

#ifdef DEBUG
#define	SBD_DEVICE_TRANSITION(sb, nt, un, st) \
{ \
	int	_ostate, _nstate; \
	_ostate = (int)((sb)->sb_dev[NIX(nt)][un].u_common.sbdev_state); \
	_nstate = (int)(st); \
	PR_STATE("BOARD %d (%s.%d) STATE: %s(%d) -> %s(%d)\n", \
		(sb)->sb_num, \
		sbd_ct_str[nt], (un), \
		sbd_state_str[_ostate], _ostate, \
		sbd_state_str[_nstate], _nstate); \
	(void) drv_getparm(TIME, \
	(void *)&(sb)->sb_dev[NIX(nt)][un].u_common.sbdev_time); \
	(sb)->sb_dev[NIX(nt)][un].u_common.sbdev_state = (st); \
	(sb)->sb_dev[NIX(nt)][un].u_common.sbdev_ostate = ostate_cvt(st); \
	send_event = 1; \
}
#define	SBD_BOARD_TRANSITION(sb, st) \
{ \
	PR_STATE("BOARD %d STATE: %s(%d) -> %s(%d)\n", \
		(sb)->sb_num, \
		sbd_state_str[(int)(sb)->sb_state], (int)(sb)->sb_state, \
		sbd_state_str[(int)(st)], (int)(st)); \
	(sb)->sb_pstate = (sb)->sb_state; \
	(sb)->sb_state = (st); \
	send_event = 1; \
}
#else /* DEBUG */
#define	SBD_DEVICE_TRANSITION(sb, nt, un, st) \
{ \
	(sb)->sb_dev[NIX(nt)][un].u_common.sbdev_state = (st); \
	(sb)->sb_dev[NIX(nt)][un].u_common.sbdev_ostate = ostate_cvt(st); \
	(void) drv_getparm(TIME, \
		(void *)&(sb)->sb_dev[NIX(nt)][un].u_common.sbdev_time); \
	send_event = 1; \
}
#define	SBD_BOARD_TRANSITION(sb, st) \
		((sb)->sb_pstate = (sb)->sb_state, (sb)->sb_state = (st),  \
		send_event = 1)
#endif /* DEBUG */

#define	SBD_DEVICE_STATE(sb, nt, un) \
		((sb)->sb_dev[NIX(nt)][un].u_common.sbdev_state)
#define	SBD_BOARD_STATE(sb) \
		((sb)->sb_state)
#define	SBD_BOARD_PSTATE(sb) \
		((sb)->sb_pstate)

typedef uint32_t sbd_devset_t;

/*
 * sbd_priv_handle_t MUST appear first.
 */
typedef struct sbd_priv_handle {
	sbd_handle_t		sh_handle;
	void			*sh_arg;	/* raw ioctl arg */
	sbd_devset_t		sh_devset;	/* based on h_dev */
	sbd_devset_t		sh_orig_devset;	/* what client requested */
	sbderror_t		sh_err;
	struct sbd_priv_handle	*sh_next;
} sbd_priv_handle_t;

#define	SBD_MAXNUM_NT		3
#define	NIX(t)			(((t) == SBD_COMP_CPU) ? 0 : \
				((t) == SBD_COMP_MEM) ? 1 : \
				((t) == SBD_COMP_IO) ? 2 : \
				((t) == SBD_COMP_CMP) ? 0 : SBD_MAXNUM_NT)

#define	SBD_NUM_MC_PER_BOARD	4


typedef struct sbd_common_unit {
	sbd_istate_t		sbdev_state;
	sbd_cond_t		sbdev_cond;
	sbd_state_t		sbdev_ostate;
	time_t			sbdev_time;
	int			sbdev_busy;
	void			*sbdev_sbp;
	int			sbdev_unum;
	sbd_comp_type_t		sbdev_type;
	dev_info_t		*sbdev_dip;
} sbd_common_unit_t;

typedef struct sbd_mem_unit {
	sbd_common_unit_t	sbm_cm;
	sbd_istate_t		sbm_state;	/* mem-unit state */
	uint_t			sbm_flags;
	pfn_t			sbm_basepfn;
	pgcnt_t			sbm_npages;
	pgcnt_t			sbm_pageslost;
	/*
	 * The following fields are used during
	 * the memory detach process only. sbm_mlist
	 * will be used to store the board memlist
	 * following a detach. The memlist will be
	 * used to re-attach the board when configuring
	 * the unit directly after an unconfigure.
	 */
	struct sbd_mem_unit	*sbm_peer;
	struct memlist		*sbm_mlist;
	struct memlist		*sbm_del_mlist;
	memhandle_t		sbm_memhandle;
	pfn_t			sbm_alignment_mask;
	pfn_t			sbm_slice_offset;
	/*
	 * The following field is used to support the
	 * representation of all memory controllers on
	 * a board with one sbd_mem_unit_t.
	 */
	dev_info_t		*sbm_dip[SBD_NUM_MC_PER_BOARD];
	/*
	 * The following field determines if the memory on this board
	 * is part of an interleave across boards
	 */
	int			sbm_interleave;
} sbd_mem_unit_t;

/*
 * Currently only maintain state information for individual
 * components.
 */
typedef struct sbd_cpu_unit {
	sbd_common_unit_t	sbc_cm;		/* cpu-unit state */
	processorid_t		sbc_cpu_id;
	cpu_flag_t		sbc_cpu_flags;
	ushort_t		sbc_pad1;
	int			sbc_cpu_impl;
	int			sbc_speed;
	int			sbc_ecache;
} sbd_cpu_unit_t;

typedef struct sbd_io_unit {
	sbd_common_unit_t	sbi_cm;		/* io-unit state */
} sbd_io_unit_t;

typedef union {
	sbd_common_unit_t	u_common;
	sbd_mem_unit_t		_mu;
	sbd_cpu_unit_t		_cu;
	sbd_io_unit_t		_iu;
} sbd_dev_unit_t;

typedef struct {
	sbd_priv_handle_t	*sb_handle;
	int			sb_ref;		/* # of handle references */
	int			sb_num;		/* board number */
	void			*sb_softsp;	/* pointer to soft state */
	dev_info_t		*sb_topdip;	/* top devinfo of instance */
	sbd_istate_t		sb_state;	/* (current) board state */
	sbd_istate_t		sb_pstate;	/* previous board state */
	sbd_cond_t		sb_cond;	/* condition		*/
	sbd_state_t		sb_rstate;	/* receptacle state	*/
	sbd_state_t		sb_ostate;	/* occupant state	*/
		/*
		 * 0=CPU, 1=MEM, 2=IO, 3=NULL
		 */
	dev_info_t		**sb_devlist[SBD_MAXNUM_NT + 1];

	sbd_devset_t	sb_dev_present;		/* present mask */
	sbd_devset_t	sb_dev_attached;	/* attached mask */
	sbd_devset_t	sb_dev_released;	/* released mask */
	sbd_devset_t	sb_dev_unreferenced;	/* unreferenced mask */
	sbd_dev_unit_t	*sb_dev[SBD_MAXNUM_NT];

	char		*sb_cpupath[SBD_MAX_UNITS_PER_BOARD];
	char		*sb_mempath[SBD_MAX_UNITS_PER_BOARD];
	char		*sb_iopath[SBD_MAX_UNITS_PER_BOARD];

	int		sb_ndev;		/* number of devs */
	int		sb_errno;		/* store errno */
	int		sb_busy;		/* drain in progress */
	int		sb_assigned;
	int		sb_flags;
	kmutex_t	sb_flags_mutex;		/* mutex to protect flags */
	int		sb_wnode;
	int		sb_memaccess_ok;
	sbd_stat_t	sb_stat;		/* cached board status */
	processorid_t	sb_cpuid;		/* for starfire connect */
	time_t		sb_time;		/* time of last board op */
	kmutex_t	sb_mutex;
	kmutex_t	sb_slock;		/* status - unconfig, discon */
} sbd_board_t;

/* definitions for sb_flags */
#define	SBD_BOARD_STATUS_CACHED	1

#define	SBD_GET_BOARD_MEMUNIT(sb, un) \
			(&((sb)->sb_dev[NIX(SBD_COMP_MEM)][un]._mu))
#define	SBD_GET_BOARD_CPUUNIT(sb, un) \
			(&((sb)->sb_dev[NIX(SBD_COMP_CPU)][un]._cu))
#define	SBD_GET_BOARD_IOUNIT(sb, un) \
			(&((sb)->sb_dev[NIX(SBD_COMP_IO)][un]._iu))

typedef ushort_t	boardset_t;	/* assumes 16 boards max */

#define	BOARDSET(b)		((boardset_t)(1 << (b)))
#define	BOARD_IN_SET(bs, b)	(((bs) & BOARDSET(b)) != 0)
#define	BOARD_ADD(bs, b)	((bs) |= BOARDSET(b))
#define	BOARD_DEL(bs, b)	((bs) &= ~BOARDSET(b))

/*
 * Format of sbd_devset_t bit masks:
 *
 *	32		   16        8    4    0
 *	|....|....|...I|IIII|....|...M|CCCC|CCCC|
 * 1 = indicates respective component present/attached.
 * I = I/O, M = Memory, C = CPU.
 */
#define	DEVSET_ANYUNIT		(-1)
#define	_NT2DEVPOS(t, u)	((NIX(t) << 3) + (u))
#define	_DEVSET_MASK		0x001f01ff
#define	_CMP_DEVSET_MASK	0x11
#define	DEVSET(t, u) \
	(((u) == DEVSET_ANYUNIT) ? \
	    (sbd_devset_t)((0xff << _NT2DEVPOS((t), 0)) & _DEVSET_MASK) : \
	(((t) == SBD_COMP_CMP) ? \
	    (sbd_devset_t)(_CMP_DEVSET_MASK << _NT2DEVPOS((t), (u))) : \
	(sbd_devset_t)(1 << _NT2DEVPOS((t), (u)))))

#define	DEVSET_IN_SET(ds, t, u)	(((ds) & DEVSET((t), (u))) != 0)
#define	DEVSET_ADD(ds, t, u)	((ds) |= DEVSET((t), (u)))
#define	DEVSET_DEL(ds, t, u)	((ds) &= ~DEVSET((t), (u)))
#define	DEVSET_GET_UNITSET(ds, t) \
	(((ds) & DEVSET((t), DEVSET_ANYUNIT)) >> _NT2DEVPOS((t), 0))
/*
 * Ops for sbd_board_t.sb_dev_present
 */
#define	SBD_DEV_IS_PRESENT(bp, nt, un) \
			DEVSET_IN_SET((bp)->sb_dev_present, (nt), (un))
#define	SBD_DEV_SET_PRESENT(bp, nt, un) \
			DEVSET_ADD((bp)->sb_dev_present, (nt), (un))
#define	SBD_DEV_CLR_PRESENT(bp, nt, un) \
			DEVSET_DEL((bp)->sb_dev_present, (nt), (un))
/*
 * Ops for sbd_board_t.sb_dev_attached
 */
#define	SBD_DEV_IS_ATTACHED(bp, nt, un) \
			DEVSET_IN_SET((bp)->sb_dev_attached, (nt), (un))
#define	SBD_DEV_SET_ATTACHED(bp, nt, un) \
			DEVSET_ADD((bp)->sb_dev_attached, (nt), (un))
#define	SBD_DEV_CLR_ATTACHED(bp, nt, un) \
			DEVSET_DEL((bp)->sb_dev_attached, (nt), (un))
/*
 * Ops for sbd_board_t.sb_dev_released
 */
#define	SBD_DEV_IS_RELEASED(bp, nt, un) \
			DEVSET_IN_SET((bp)->sb_dev_released, (nt), (un))
#define	SBD_DEV_SET_RELEASED(bp, nt, un) \
			DEVSET_ADD((bp)->sb_dev_released, (nt), (un))
#define	SBD_DEV_CLR_RELEASED(bp, nt, un) \
			DEVSET_DEL((bp)->sb_dev_released, (nt), (un))
/*
 * Ops for sbd_board_t.sb_dev_unreferenced
 */
#define	SBD_DEV_IS_UNREFERENCED(bp, nt, un) \
			DEVSET_IN_SET((bp)->sb_dev_unreferenced, (nt), (un))
#define	SBD_DEV_SET_UNREFERENCED(bp, nt, un) \
			DEVSET_ADD((bp)->sb_dev_unreferenced, (nt), (un))
#define	SBD_DEV_CLR_UNREFERENCED(bp, nt, un) \
			DEVSET_DEL((bp)->sb_dev_unreferenced, (nt), (un))

#define	SBD_DEVS_PRESENT(bp) \
			((bp)->sb_dev_present)
#define	SBD_DEVS_ATTACHED(bp) \
			((bp)->sb_dev_attached)
#define	SBD_DEVS_RELEASED(bp) \
			((bp)->sb_dev_released)
#define	SBD_DEVS_UNREFERENCED(bp) \
			((bp)->sb_dev_unreferenced)
#define	SBD_DEVS_UNATTACHED(bp) \
			((bp)->sb_dev_present & ~(bp)->sb_dev_attached)
#define	SBD_DEVS_CONFIGURE(bp, devs) \
			((bp)->sb_dev_attached = (devs))
#define	SBD_DEVS_DISCONNECT(bp, devs) \
			((bp)->sb_dev_present &= ~(devs))
#define	SBD_DEVS_CANCEL(bp, devs) \
			((bp)->sb_dev_released &= ~(devs), \
			(bp)->sb_dev_unreferenced &= ~(devs))

/*
 * return values from sbd_cancel_cpu
 */
#define	SBD_CPUERR_NONE		0
#define	SBD_CPUERR_RECOVERABLE	-1
#define	SBD_CPUERR_FATAL	-2

/*
 * sbd_board_t.sbmem[].sbm_flags
 */
#define	SBD_MFLAG_RESERVED	0x01	/* mem unit reserved for delete */
#define	SBD_MFLAG_SOURCE	0x02	/* source brd of copy/rename op */
#define	SBD_MFLAG_TARGET	0x04	/* board selected as target */
#define	SBD_MFLAG_MEMUPSIZE	0x08	/* move from big to small board */
#define	SBD_MFLAG_MEMDOWNSIZE	0x10	/* move from small to big board */
#define	SBD_MFLAG_MEMRESIZE	0x18	/* move to different size board */
#define	SBD_MFLAG_RELOWNER	0x20	/* memory release (delete) owner */
#define	SBD_MFLAG_RELDONE	0x40

typedef struct {
	int	sfio_cmd;
	void	*sfio_arg;
} sbd_ioctl_t;

/*
 * 32bit support for sbd_ioctl_t.
 */
typedef struct {
	int32_t		sfio_cmd;
	uint32_t	sfio_arg;
} sbd_ioctl32_t;

/*
 * PSM-DR layers are only allowed to use lower 16 bits of dev_t.
 * B    - bottom 4 bits are for the slot number.
 * D    - device type chosen (0 = indicates all devices in slot).
 * U	- unit number if specific device type chosen.
 * X    - not used.
 *
 * Upper      Lower
 * XXXXUUUUDDDDBBBB
 *
 * Note that this format only allows attachment points to
 * either represent all the units on a board or one particular
 * unit.  A more general specification would permit any combination
 * of specific units and types to be represented by individual
 * attachment points.
 */
#define	SBD_DEV_SLOTMASK	0x000f
/*
 * These device level definitions are primarily for unit testing.
 */
#define	SBD_DEV_UNITMASK	0x0f00
#define	SBD_DEV_UNITSHIFT	8
#define	SBD_DEV_CPU		0x0010
#define	SBD_DEV_MEM		0x0020
#define	SBD_DEV_IO		0x0040
#define	SBD_DEV_TYPEMASK	(SBD_DEV_CPU | SBD_DEV_MEM | SBD_DEV_IO)
#define	SBD_DEV_TYPESHIFT	4

/*
 * Slot, Instance, and Minor number Macro definitions
 */
#define	SLOT2DEV(s)		((s) & SBD_DEV_SLOTMASK)
#define	SBDGETSLOT(unit)	((unit) & SBD_DEV_SLOTMASK)
/*
 * The following is primarily for unit testing.
 */
#define	ALLCPU2DEV(s)		(SBD_DEV_CPU | SLOT2DEV(s))
#define	ALLMEM2DEV(s)		(SBD_DEV_MEM | SLOT2DEV(s))
#define	ALLIO2DEV(s)		(SBD_DEV_IO | SLOT2DEV(s))
#define	_UNIT2DEV(u)		(((u) << SBD_DEV_UNITSHIFT) & \
					SBD_DEV_UNITMASK)
#define	CPUUNIT2DEV(s, c)	(_UNIT2DEV(c) | ALLCPU2DEV(s))
#define	MEMUNIT2DEV(s, m)	(_UNIT2DEV(m) | ALLMEM2DEV(s))
#define	IOUNIT2DEV(s, i)	(_UNIT2DEV(i) | ALLIO2DEV(s))

#define	DEV_IS_ALLUNIT(d)	(((d) & SBD_DEV_UNITMASK) == 0)
#define	_DEV_IS_ALLTYPE(d)	(((d) & SBD_DEV_TYPEMASK) == 0)
#define	DEV_IS_ALLBOARD(d)	(DEV_IS_ALLUNIT(d) && _DEV_IS_ALLTYPE(d))
#define	DEV_IS_CPU(d)		((d) & SBD_DEV_CPU)
#define	DEV_IS_MEM(d)		((d) & SBD_DEV_MEM)
#define	DEV_IS_IO(d)		((d) & SBD_DEV_IO)
#define	DEV_IS_ALLCPU(d)	(DEV_IS_ALLUNIT(d) && DEV_IS_CPU(d))
#define	DEV_IS_ALLMEM(d)	(DEV_IS_ALLUNIT(d) && DEV_IS_MEM(d))
#define	DEV_IS_ALLIO(d)		(DEV_IS_ALLUNIT(d) && DEV_IS_IO(d))
#define	DEV2UNIT(d) \
		((((d) & SBD_DEV_UNITMASK) >> SBD_DEV_UNITSHIFT) - 1)
#define	DEV2NT(d) \
		(DEV_IS_MEM(d) ? SBD_COMP_MEM : \
		DEV_IS_CPU(d) ? SBD_COMP_CPU : \
		DEV_IS_IO(d) ? SBD_COMP_IO : SBD_COMP_UNKNOWN)

/*
 * Macros to cast between PIM and PSM layers of the following
 * structures:
 *	board_t		<-> sbd_board_t
 *	sbd_handle_t	<-> sbd_priv_handle_t
 *	sbderror_t	<-> sbderror_t
 *	slot		-> board_t
 *	slot		-> sbd_board_t
 *	sbd_board_t	-> sbd_handle_t
 *	sbd_handle	-> sbderror_t
 */
#define	SBDH2BD(bd)		((sbd_board_t *)(bd))

#define	HD2MACHHD(hd)		((sbd_priv_handle_t *)(hd))
#define	MACHHD2HD(mhd)		((sbd_handle_t *)&((mhd)->sh_handle))

#define	ERR2MACHERR(err)	((sbderror_t *)(err))
#define	MACHERR2ERR(merr)	((sbderror_t *)(merr))

#define	BSLOT2MACHBD(b)		(&(sbd_boardlist[b]))
#define	BSLOT2BD(slot)		MACHBD2BD(BSLOT2MACHBD(slot))

#define	MACHBD2HD(sbp)		MACHHD2HD((sbp)->sb_handle)

#define	HD2MACHERR(hd)		ERR2MACHERR(SBD_HD2ERR(hd))

#define	MACHSRHD2HD(srh)	((srh)->sr_dr_handlep)

/*
 * CMP Specific Helpers
 */
#define	MAX_CORES_PER_CMP		2
#define	SBD_CMP_CORE_UNUM(cmp, core)	((cmp + (core * 512))
#define	SBD_CMP_NUM(unum)		(unum & 0x3)

/*
 * Some stuff to assist in debug.
 */
#ifdef DEBUG
#define	SBD_DBG_STATE	0x00000001
#define	SBD_DBG_QR	0x00000002
#define	SBD_DBG_CPU	0x00000004
#define	SBD_DBG_MEM	0x00000008
#define	SBD_DBG_IO	0x00000010
#define	SBD_DBG_HW	0x00000020
#define	SBD_DBG_BYP	0x00000040

#define	PR_ALL		if (sbd_debug)			printf
#define	PR_STATE	if (sbd_debug & SBD_DBG_STATE)	printf
#define	PR_QR		if (sbd_debug & SBD_DBG_QR)	prom_printf
#define	PR_CPU		if (sbd_debug & SBD_DBG_CPU)	printf
#define	PR_MEM		if (sbd_debug & SBD_DBG_MEM)	printf
#define	PR_IO		if (sbd_debug & SBD_DBG_IO)	printf
#define	PR_HW		if (sbd_debug & SBD_DBG_HW)	printf
#define	PR_BYP		if (sbd_debug & SBD_DBG_BYP)	prom_printf

#define	SBD_MEMLIST_DUMP(ml)	memlist_dump(ml)

extern uint_t	sbd_debug;
#else /* DEBUG */
#define	PR_ALL		if (0) printf
#define	PR_STATE	PR_ALL
#define	PR_QR		PR_ALL
#define	PR_CPU		PR_ALL
#define	PR_MEM		PR_ALL
#define	PR_IO		PR_ALL
#define	PR_HW		PR_ALL
#define	PR_BYP		PR_ALL

#define	SBD_MEMLIST_DUMP(ml)
#endif /* DEBUG */
extern char	*sbd_state_str[];
extern char	*sbd_ct_str[];

/*
 * event flag
 */
extern char send_event;

/*
 * IMPORTANT:
 * The following two defines are also coded into OBP, so if they
 * need to change here, don't forget to change OBP also.
 */
#define	SBD_OBP_PROBE_GOOD	0
#define	SBD_OBP_PROBE_BAD	1

extern int		sbd_setup_instance(int, dev_info_t *, int, int,
				caddr_t);
extern int		sbd_teardown_instance(int, caddr_t);
extern int		sbd_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
				char *event);

extern sbd_comp_type_t	sbd_cm_type(char *name);
extern sbd_state_t	ostate_cvt(sbd_istate_t state);
extern void		sbd_cpu_set_prop(sbd_cpu_unit_t *cp, dev_info_t *dip);
extern int		sbd_cpu_flags(sbd_handle_t *hp, sbd_devset_t devset,
				sbd_dev_stat_t *dsp);
extern int		sbd_disconnect_cpu(sbd_handle_t *hp, int unit);
extern int		sbd_connect_cpu(sbd_board_t *sbp, int unit);
extern int		sbd_disconnect_mem(sbd_handle_t *hp, int unit);

extern int		sbd_pre_detach_mem(sbd_handle_t *hp,
				sbd_devlist_t *devlist, int devnum);
extern int		sbd_post_attach_mem(sbd_handle_t *,
				sbd_devlist_t *, int);
extern int		sbd_post_detach_mem(sbd_handle_t *,
				sbd_devlist_t *, int);
extern int		sbd_post_attach_cpu(sbd_handle_t *hp,
					sbd_devlist_t *devlist, int devnum);
extern int		sbd_pre_release_cpu(sbd_handle_t *hp,
					sbd_devlist_t *devlist, int devnum);
extern int		sbd_pre_detach_cpu(sbd_handle_t *hp,
					sbd_devlist_t *devlist, int devnum);
extern int		sbd_post_detach_cpu(sbd_handle_t *hp,
					sbd_devlist_t *devlist, int devnum);
extern int		sbd_pre_attach_mem(sbd_handle_t *hp,
					sbd_devlist_t *devlist, int devnum);
extern int		sbd_pre_release_mem(sbd_handle_t *hp,
					sbd_devlist_t *devlist, int devnum);
extern int		sbd_disconnect_io(sbd_handle_t *hp, int unit);
extern void		sbd_check_devices(dev_info_t *dip, int *refcount,
					sbd_handle_t *handle);
extern struct memlist	*sbd_get_memlist(sbd_mem_unit_t *mp, sbderror_t *ep);
extern void		sbd_init_mem_unit(sbd_board_t *sbp, int unit,
					sbderror_t *ep);
extern void		sbd_release_mem_done(sbd_handle_t *hp, int unit);
extern void		sbd_release_cleanup(sbd_handle_t *hp);
extern int		sbd_cancel_cpu(sbd_handle_t *hp, int unit);
extern void		sbd_init_err(sbderror_t *ep);
extern int		sbd_cancel_mem(sbd_handle_t *hp, int unit);
extern sbd_comp_type_t	sbd_get_devtype(sbd_handle_t *hp, dev_info_t *dip);
extern int		sbd_get_board(dev_info_t *dip);
extern int		sfhw_get_base_physaddr(dev_info_t *dip,
					uint64_t *basepa);
extern int		sbd_pre_attach_cpu(sbd_handle_t *hp,
					sbd_devlist_t *devlist, int devnum);
extern int		sbd_move_memory(sbd_handle_t *hp, sbd_board_t
				*s_bp, sbd_board_t *t_bp);
extern void		memlist_delete(struct memlist *mlist);
extern struct memlist	*memlist_dup(struct memlist *mlist);
extern void		memlist_dump(struct memlist *mlist);
extern int		memlist_intersect(struct memlist *alist,
					struct memlist *blist);
extern int		sbd_juggle_bootproc(sbd_handle_t *hp,
					processorid_t cpuid);

extern sbd_cond_t	sbd_get_comp_cond(dev_info_t *);
void			sbd_attach_mem(sbd_handle_t *hp, sbderror_t *ep);
int			sbd_release_mem(sbd_handle_t *hp, dev_info_t *dip,
					int unit);

int			sbd_get_memhandle(sbd_handle_t *hp, dev_info_t *dip,
					memhandle_t *mhp);
int			sbd_detach_memory(sbd_handle_t *hp, sbderror_t *ep,
					sbd_mem_unit_t *s_mp, int unit);
void			sbd_release_memory_done(void *arg, int error);
int			sbd_set_err_in_hdl(sbd_handle_t *hp, sbderror_t *ep);
sbdp_handle_t		*sbd_get_sbdp_handle(sbd_board_t *sbp,
					sbd_handle_t *hp);
void			sbd_release_sbdp_handle(sbdp_handle_t *hp);
void			sbd_reset_error_sbdph(sbdp_handle_t *hp);
extern int		sbd_is_cmp_child(dev_info_t *dip);

typedef const char *const fn_t;

#ifdef	__cplusplus
}
#endif

#endif /* _SYS_SBDPRIV_H */