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