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