xref: /onnv-gate/usr/src/lib/cfgadm_plugins/ac/common/mema_prom.c (revision 2305:7954d746a1b5)
1*2305Sstevel /*
2*2305Sstevel  * CDDL HEADER START
3*2305Sstevel  *
4*2305Sstevel  * The contents of this file are subject to the terms of the
5*2305Sstevel  * Common Development and Distribution License, Version 1.0 only
6*2305Sstevel  * (the "License").  You may not use this file except in compliance
7*2305Sstevel  * with the License.
8*2305Sstevel  *
9*2305Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*2305Sstevel  * or http://www.opensolaris.org/os/licensing.
11*2305Sstevel  * See the License for the specific language governing permissions
12*2305Sstevel  * and limitations under the License.
13*2305Sstevel  *
14*2305Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
15*2305Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*2305Sstevel  * If applicable, add the following below this CDDL HEADER, with the
17*2305Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
18*2305Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
19*2305Sstevel  *
20*2305Sstevel  * CDDL HEADER END
21*2305Sstevel  */
22*2305Sstevel /*
23*2305Sstevel  * Copyright (c) 1996-1998 by Sun Microsystems, Inc.
24*2305Sstevel  * All rights reserved.
25*2305Sstevel  */
26*2305Sstevel 
27*2305Sstevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*2305Sstevel 
29*2305Sstevel #include <stddef.h>
30*2305Sstevel #include <stdlib.h>
31*2305Sstevel #include <fcntl.h>
32*2305Sstevel #include <unistd.h>
33*2305Sstevel #include <string.h>
34*2305Sstevel #include <errno.h>
35*2305Sstevel #include <assert.h>
36*2305Sstevel #include <sys/param.h>
37*2305Sstevel #include <sys/obpdefs.h>
38*2305Sstevel #include <sys/fhc.h>
39*2305Sstevel #include <sys/ac.h>
40*2305Sstevel #include <sys/sysctrl.h>
41*2305Sstevel #include <sys/openpromio.h>
42*2305Sstevel #include "mema_prom.h"
43*2305Sstevel #include <config_admin.h>
44*2305Sstevel 
45*2305Sstevel 
46*2305Sstevel /*
47*2305Sstevel  * PROM access routines to get and set disabled lists
48*2305Sstevel  * Based on code in the usr/src/cmd/eeprom directory.
49*2305Sstevel  */
50*2305Sstevel #define	PROMDEV		"/dev/openprom"
51*2305Sstevel /*
52*2305Sstevel  * 128 is the size of the largest (currently) property name
53*2305Sstevel  * 8192 - MAXPROPSIZE - sizeof (int) is the size of the largest
54*2305Sstevel  * (currently) property value, viz. nvramrc.
55*2305Sstevel  * the sizeof(u_int) is from struct openpromio
56*2305Sstevel  */
57*2305Sstevel 
58*2305Sstevel #define	MAXPROPSIZE	128
59*2305Sstevel #define	MAXNAMESIZE	MAXPROPSIZE
60*2305Sstevel #define	MAXVALSIZE	(8192 - MAXPROPSIZE - sizeof (u_int))
61*2305Sstevel #define	BUFSIZE		(MAXPROPSIZE + MAXVALSIZE + sizeof (u_int))
62*2305Sstevel typedef union {
63*2305Sstevel 	char buf[BUFSIZE];
64*2305Sstevel 	struct openpromio opp;
65*2305Sstevel } Oppbuf;
66*2305Sstevel #define	PROP_MEMORY_LIST	"disabled-memory-list"
67*2305Sstevel 
68*2305Sstevel static int prom_read_one(mema_disabled_t *, int, int, char *, u_int);
69*2305Sstevel static int prom_write_one(mema_disabled_t *, int, int, char *, u_int);
70*2305Sstevel 
71*2305Sstevel int
prom_read_disabled_list(mema_disabled_t * dp,int bd)72*2305Sstevel prom_read_disabled_list(mema_disabled_t *dp, int bd)
73*2305Sstevel {
74*2305Sstevel 	int prom_fd;
75*2305Sstevel 	int ret;
76*2305Sstevel 
77*2305Sstevel 	(void) memset((void *)dp, 0, sizeof (*dp));
78*2305Sstevel 	prom_fd = open(PROMDEV, O_RDONLY);
79*2305Sstevel 	if (prom_fd == -1) {
80*2305Sstevel 		return (0);
81*2305Sstevel 	}
82*2305Sstevel 	ret = prom_read_one(dp, bd, prom_fd,
83*2305Sstevel 	    PROP_MEMORY_LIST, PROM_MEMORY_DISABLED);
84*2305Sstevel 	(void) close(prom_fd);
85*2305Sstevel 	return (ret);
86*2305Sstevel }
87*2305Sstevel 
88*2305Sstevel int
prom_write_disabled_list(mema_disabled_t * dp,int bd)89*2305Sstevel prom_write_disabled_list(mema_disabled_t *dp, int bd)
90*2305Sstevel {
91*2305Sstevel 	int prom_fd;
92*2305Sstevel 	int ret;
93*2305Sstevel 
94*2305Sstevel 	prom_fd = open(PROMDEV, O_RDWR);
95*2305Sstevel 	if (prom_fd == -1) {
96*2305Sstevel 		return (0);
97*2305Sstevel 	}
98*2305Sstevel 	ret = prom_write_one(dp, bd, prom_fd,
99*2305Sstevel 	    PROP_MEMORY_LIST, PROM_MEMORY_DISABLED);
100*2305Sstevel 	(void) close(prom_fd);
101*2305Sstevel 	return (ret);
102*2305Sstevel }
103*2305Sstevel 
104*2305Sstevel static int
prom_read_one(mema_disabled_t * dp,int bd,int prom_fd,char * var,u_int bit)105*2305Sstevel prom_read_one(
106*2305Sstevel 	mema_disabled_t *dp,
107*2305Sstevel 	int bd,
108*2305Sstevel 	int prom_fd,
109*2305Sstevel 	char *var,
110*2305Sstevel 	u_int bit)
111*2305Sstevel {
112*2305Sstevel 	Oppbuf oppbuf;
113*2305Sstevel 	struct openpromio *opp = &oppbuf.opp;
114*2305Sstevel 	int ret;
115*2305Sstevel 
116*2305Sstevel 	(void) memset((void *)&oppbuf, 0, sizeof (oppbuf));
117*2305Sstevel 	(void) strncpy(opp->oprom_array, var, MAXNAMESIZE);
118*2305Sstevel 	opp->oprom_size = MAXVALSIZE;
119*2305Sstevel 	if (ioctl(prom_fd, OPROMGETOPT, opp) == -1) {
120*2305Sstevel 		ret = 0;
121*2305Sstevel 	} else
122*2305Sstevel 	if (opp->oprom_size == 0) {
123*2305Sstevel 		/* Not a failure - just not set to anything */
124*2305Sstevel 		ret = 1;
125*2305Sstevel 	} else {
126*2305Sstevel 		char *cp;
127*2305Sstevel 		int board;
128*2305Sstevel 
129*2305Sstevel 		ret = 1;
130*2305Sstevel 		for (cp = opp->oprom_array; *cp != '\0'; cp++) {
131*2305Sstevel 			switch (*cp) {
132*2305Sstevel 			case '0':
133*2305Sstevel 			case '1':
134*2305Sstevel 			case '2':
135*2305Sstevel 			case '3':
136*2305Sstevel 			case '4':
137*2305Sstevel 			case '5':
138*2305Sstevel 			case '6':
139*2305Sstevel 			case '7':
140*2305Sstevel 			case '8':
141*2305Sstevel 			case '9':
142*2305Sstevel 				board = *cp - '0';
143*2305Sstevel 				break;
144*2305Sstevel 			case 'a':
145*2305Sstevel 			case 'b':
146*2305Sstevel 			case 'c':
147*2305Sstevel 			case 'd':
148*2305Sstevel 			case 'e':
149*2305Sstevel 			case 'f':
150*2305Sstevel 				board = *cp - 'a' + 10;
151*2305Sstevel 				break;
152*2305Sstevel 			case 'A':
153*2305Sstevel 			case 'B':
154*2305Sstevel 			case 'C':
155*2305Sstevel 			case 'D':
156*2305Sstevel 			case 'E':
157*2305Sstevel 			case 'F':
158*2305Sstevel 				board = *cp - 'A' + 10;
159*2305Sstevel 				break;
160*2305Sstevel 			default:
161*2305Sstevel 				/* Ignore bad characters. */
162*2305Sstevel 				/* TODO: maybe should set ret to 0? */
163*2305Sstevel 				board = -1;
164*2305Sstevel 				break;
165*2305Sstevel 			}
166*2305Sstevel 			if (board == bd)
167*2305Sstevel 				*dp |= bit;
168*2305Sstevel 		}
169*2305Sstevel 	}
170*2305Sstevel 	return (ret);
171*2305Sstevel }
172*2305Sstevel 
173*2305Sstevel static int
prom_write_one(mema_disabled_t * dp,int bd,int prom_fd,char * var,u_int bit)174*2305Sstevel prom_write_one(
175*2305Sstevel 	mema_disabled_t *dp,
176*2305Sstevel 	int bd,
177*2305Sstevel 	int prom_fd,
178*2305Sstevel 	char *var,
179*2305Sstevel 	u_int bit)
180*2305Sstevel {
181*2305Sstevel 	Oppbuf in_oppbuf;
182*2305Sstevel 	struct openpromio *in_opp = &in_oppbuf.opp;
183*2305Sstevel 	Oppbuf oppbuf;
184*2305Sstevel 	struct openpromio *opp = &oppbuf.opp;
185*2305Sstevel 	int ret;
186*2305Sstevel 	char *cp;
187*2305Sstevel 
188*2305Sstevel 	/* Setup output buffer. */
189*2305Sstevel 	(void) memset((void *)&oppbuf, 0, sizeof (oppbuf));
190*2305Sstevel 	(void) strncpy(opp->oprom_array, var, MAXNAMESIZE);
191*2305Sstevel 	opp->oprom_size = strlen(var) + 1;
192*2305Sstevel 	cp = opp->oprom_array + opp->oprom_size;
193*2305Sstevel 
194*2305Sstevel 	/*
195*2305Sstevel 	 * First read the existing list, filtering out 'bd' if 'bit'
196*2305Sstevel 	 * not set.
197*2305Sstevel 	 */
198*2305Sstevel 	(void) memset((void *)&in_oppbuf, 0, sizeof (in_oppbuf));
199*2305Sstevel 	(void) strncpy(in_opp->oprom_array, var, MAXNAMESIZE);
200*2305Sstevel 	in_opp->oprom_size = MAXVALSIZE;
201*2305Sstevel 	if (ioctl(prom_fd, OPROMGETOPT, in_opp) != -1 &&
202*2305Sstevel 	    in_opp->oprom_size != 0) {
203*2305Sstevel 		char *icp;
204*2305Sstevel 		int board;
205*2305Sstevel 
206*2305Sstevel 		for (icp = in_opp->oprom_array; *icp != '\0'; icp++) {
207*2305Sstevel 			switch (*icp) {
208*2305Sstevel 			case '0': case '1': case '2': case '3':
209*2305Sstevel 			case '4': case '5': case '6': case '7':
210*2305Sstevel 			case '8': case '9':
211*2305Sstevel 				board = *icp - '0';
212*2305Sstevel 				break;
213*2305Sstevel 			case 'a': case 'b': case 'c':
214*2305Sstevel 			case 'd': case 'e': case 'f':
215*2305Sstevel 				board = *icp - 'a' + 10;
216*2305Sstevel 				break;
217*2305Sstevel 			case 'A': case 'B': case 'C':
218*2305Sstevel 			case 'D': case 'E': case 'F':
219*2305Sstevel 				board = *icp - 'A' + 10;
220*2305Sstevel 				break;
221*2305Sstevel 			default:
222*2305Sstevel 				/* Ignore bad characters. */
223*2305Sstevel 				continue;
224*2305Sstevel 			}
225*2305Sstevel 			/* If enabling this board ... */
226*2305Sstevel 			if (board == bd && (*dp & bit) == 0)
227*2305Sstevel 				continue;
228*2305Sstevel 			*cp++ = "0123456789abcdef"[board];
229*2305Sstevel 			opp->oprom_size++;
230*2305Sstevel 		}
231*2305Sstevel 	}
232*2305Sstevel 
233*2305Sstevel 	if ((*dp & bit) != 0) {
234*2305Sstevel 		*cp++ = "0123456789abcdef"[bd];
235*2305Sstevel 		opp->oprom_size++;
236*2305Sstevel 	}
237*2305Sstevel 	if (ioctl(prom_fd, OPROMSETOPT, opp) == -1) {
238*2305Sstevel 		ret = 0;
239*2305Sstevel 	} else {
240*2305Sstevel 		ret = 1;
241*2305Sstevel 	}
242*2305Sstevel 
243*2305Sstevel 	return (ret);
244*2305Sstevel }
245*2305Sstevel 
246*2305Sstevel /*
247*2305Sstevel  * The PROM only has board-level disable of memory.  If two banks are present
248*2305Sstevel  * on the board, both are either enabled or disabled at boot.
249*2305Sstevel  * The caller of this routine must set the PROM_MEMORY_PRESENT bits
250*2305Sstevel  * before calling this function.
251*2305Sstevel  */
252*2305Sstevel 
253*2305Sstevel /*ARGSUSED*/
254*2305Sstevel int
prom_viable_disabled_list(mema_disabled_t * dp)255*2305Sstevel prom_viable_disabled_list(mema_disabled_t *dp)
256*2305Sstevel {
257*2305Sstevel #ifdef	XXX
258*2305Sstevel 	int board;
259*2305Sstevel 
260*2305Sstevel 	for (board = 0; board < MAX_BOARDS; board++) {
261*2305Sstevel 		if ((dp->bank_A[board] & PROM_MEMORY_PRESENT) != 0 &&
262*2305Sstevel 		    (dp->bank_B[board] & PROM_MEMORY_PRESENT) != 0 &&
263*2305Sstevel 		    (dp->bank_A[board] & PROM_MEMORY_DISABLED) !=
264*2305Sstevel 		    (dp->bank_B[board] & PROM_MEMORY_DISABLED)) {
265*2305Sstevel 			return (0);
266*2305Sstevel 		}
267*2305Sstevel 	}
268*2305Sstevel #endif
269*2305Sstevel 	return (1);
270*2305Sstevel }
271