summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4/sys/ebus.h
blob: 92f193b92e43dc40e530bb755c68a357cfaba39f (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
/*
 * 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_EBUS_H
#define	_SYS_EBUS_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * driver state type:
 */
typedef enum { NEW = 0, ATTACHED, RESUMED, DETACHED,
		SUSPENDED, PM_SUSPENDED } driver_state_t;

/*
 * The i86pc specific code fragments are to support the debug of "honeynut"
 * and "multigrain" prototypes on i86pc platform.  Most of the fragments
 * deal with differences in the interrupt dispatching between the prototypes
 * and the cheerio ebus.  On the prototype boards, all interrupt lines are
 * tied together.  For this case, the nexus driver uses a common interrupt
 * handler to poll all of its children.
 */
#if defined(i86pc)
#define	MAX_EBUS_DEVS	6

/*
 * ebus device interrupt info;
 */
typedef struct {
	char *name;
	uint_t inuse;
	uint_t (*handler)();
	caddr_t arg;
} ebus_intr_slot_t;
#endif

struct ebus_intr_map {
	uint32_t ebus_phys_hi;
	uint32_t ebus_phys_low;
	uint32_t ebus_intr;
	uint32_t intr_ctlr_nodeid;
	uint32_t ino;
};

struct ebus_intr_map_mask {
	uint32_t ebus_phys_hi;
	uint32_t ebus_phys_low;
	uint32_t ebus_intr;
};

/*
 * definition of ebus reg spec entry:
 */
typedef struct {
	uint32_t addr_hi;
	uint32_t addr_low;
	uint32_t size;
} ebus_regspec_t;

/* Range entry for 3-cell parent address */
struct ebus_pci_rangespec {
	uint32_t phys_hi;			/* Child hi range address */
	uint32_t phys_low;			/* Child low range address */
	uint32_t par_phys_hi;			/* Parent hi rng addr */
	uint32_t par_phys_mid;			/* Parent mid rng addr */
	uint32_t par_phys_low;			/* Parent low rng addr */
	uint32_t rng_size;			/* Range size */
};

/* Range entry for 2-cell parent address */
struct ebus_jbus_rangespec {
	uint32_t phys_hi;			/* Child hi range address */
	uint32_t phys_low;			/* Child low range address */
	uint32_t par_phys_hi;			/* Parent hi rng addr */
	uint32_t par_phys_low;			/* Parent low rng addr */
	uint32_t rng_size;			/* Range size */
};

typedef union vrangespec {
	struct ebus_pci_rangespec	pci_rangespec;
	struct ebus_jbus_rangespec	jbus_rangespec;
} vrangespec_t;

typedef union vregspec {
	struct pci_phys_spec	pci_regspec;
	struct regspec		jbus_regspec;
} vregspec_t;

/*
 * driver soft state structure:
 */
typedef struct {
	dev_info_t *dip;
	driver_state_t state;
	pci_regspec_t *reg;
	int nreg;

	vrangespec_t *vrangep;
	int vrange_len;
	int vrange_cnt;

	kmutex_t ebus_mutex;
	uint_t ebus_soft_state;
#define	EBUS_SOFT_STATE_CLOSED		0x00
#define	EBUS_SOFT_STATE_OPEN		0x01
#define	EBUS_SOFT_STATE_OPEN_EXCL	0x02

#if defined(i86pc)
	ddi_iblock_cookie_t iblock;
	ddi_idevice_cookie_t idevice;
	ebus_intr_slot_t intr_slot[MAX_EBUS_DEVS];
#endif
#if defined(__sparc)
	/* Interrupt support */
	int intr_map_size;
	struct ebus_intr_map *intr_map;
	struct ebus_intr_map_mask *intr_map_mask;
#endif
	int ebus_addr_cells;
	int ebus_paddr_cells;
	int ebus_psz_cells;
	int ebus_sz_cells;
} ebus_devstate_t;


/*
 * use macros for soft state and driver properties:
 */
#define	get_ebus_soft_state(i)	\
	((ebus_devstate_t *)ddi_get_soft_state(per_ebus_state, (i)))

#define	alloc_ebus_soft_state(i)	\
	ddi_soft_state_zalloc(per_ebus_state, (i))

#define	free_ebus_soft_state(i)	\
	ddi_soft_state_free(per_ebus_state, (i))


#define	getprop(dip, name, addr, intp)		\
		ddi_getlongprop(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
				(name), (caddr_t)(addr), (intp))

#define	IS_RIO(dip) \
		((ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, \
		"device-id", -1) == 0x1100) && \
		(ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, \
		"vendor-id", -1) == 0x108e))

#define	EBUS_4MHZ	4000

/*
 * register offsets and lengths:
 */
#define	TCR_OFFSET	0x710000
#define	TCR_LENGTH	12

/*
 * timing control register settings:
 */
#define	TCR1		0x08101008
#define	TCR2		0x08100020
#define	TCR3		0x00000020

#if defined(DEBUG)
#define	D_IDENTIFY	0x00000001
#define	D_ATTACH	0x00000002
#define	D_DETACH	0x00000004
#define	D_MAP		0x00000008
#define	D_CTLOPS	0x00000010
#define	D_INTR		0x00000100

#define	DBG(flag, psp, fmt)	\
	ebus_debug(flag, psp, fmt, 0, 0, 0, 0, 0);
#define	DBG1(flag, psp, fmt, a1)	\
	ebus_debug(flag, psp, fmt, (uintptr_t)(a1), 0, 0, 0, 0);
#define	DBG2(flag, psp, fmt, a1, a2)	\
	ebus_debug(flag, psp, fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0);
#define	DBG3(flag, psp, fmt, a1, a2, a3)	\
	ebus_debug(flag, psp, fmt, (uintptr_t)(a1), (uintptr_t)(a2), \
	    (uintptr_t)(a3), 0, 0);
#define	DBG4(flag, psp, fmt, a1, a2, a3, a4)	\
	ebus_debug(flag, psp, fmt, (uintptr_t)(a1), (uintptr_t)(a2), \
	    (uintptr_t)(a3), \
		(uintptr_t)(a4), 0);
#define	DBG5(flag, psp, fmt, a1, a2, a3, a4, a5)	\
	ebus_debug(flag, psp, fmt, (uintptr_t)(a1), (uintptr_t)(a2), \
	    (uintptr_t)(a3), \
		(uintptr_t)(a4), (uintptr_t)(a5));
static void
ebus_debug(uint_t, ebus_devstate_t *, char *, uintptr_t, uintptr_t, uintptr_t,
    uintptr_t, uintptr_t);
#else
#define	DBG(flag, psp, fmt)
#define	DBG1(flag, psp, fmt, a1)
#define	DBG2(flag, psp, fmt, a1, a2)
#define	DBG3(flag, psp, fmt, a1, a2, a3)
#define	DBG4(flag, psp, fmt, a1, a2, a3, a4)
#define	DBG5(flag, psp, fmt, a1, a2, a3, a4, a5)
#endif

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_EBUS_H */