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