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