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 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 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 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 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 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