cmd: remove sparc-only virtinfo
[unleashed.git] / usr / src / cmd / picl / plugins / sun4u / lib / fruaccess / cvrt_spd_data.c
blob504ce3bd95f9ef03bd0f339dcaea6d561fb16218
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include "fru_access_impl.h"
31 static uchar_t sp_sec_hdr[] = SP_SEC_HDR;
32 static uchar_t sp_seg_hdr[] = SP_SEG_HDR;
33 static uchar_t sp_seg_body[] = SP_DATA;
36 * function to return section header for simulated SPD fruid
38 * parameters:
39 * sec_hdr buffer to receive section header
40 * sec_hdr_len size of buffer sec_hdr
41 * return value:
42 * size of returned data (0 if sec_hdr_len too small)
44 size_t
45 get_sp_sec_hdr(void *sec_hdr, size_t sec_hdr_len)
47 if (sec_hdr_len < sizeof (sp_sec_hdr))
48 return (0);
49 (void) memcpy(sec_hdr, sp_sec_hdr, sizeof (sp_sec_hdr));
50 return (sizeof (sp_sec_hdr));
54 * function to return segment header for simulated SPD fruid
56 * parameters:
57 * seg_hdr buffer to receive segment header
58 * seg_hdr_len size of buffer seg_hdr
59 * return value:
60 * size of returned data (0 if seg_hdr_len too small)
62 size_t
63 get_sp_seg_hdr(void *seg_hdr, size_t seg_hdr_len)
65 if (seg_hdr_len < sizeof (sp_seg_hdr))
66 return (0);
67 (void) memcpy(seg_hdr, sp_seg_hdr, sizeof (sp_seg_hdr));
68 return (sizeof (sp_seg_hdr));
72 * Function to convert SPD data into SPD fruid segment.
73 * The segment comprises two tagged records: DIMM_Capacity and SPD_R.
75 * DIMM_Capacity is a text string showing the total usable size of the
76 * DIMM (i.e. not including error correction bits). This record is derived
77 * from module row density and number of rows.
79 * SPD_R contains the entire SPD data area from the DIMM. It is slightly
80 * massaged to make it easier to display:
81 * bytes 0 - 63 are presented as is
82 * bytes 64 - 71 (JEDEC code) are compressed into 2 bytes, matching the
83 * format used in ManR
84 * bytes 72 - 92 are copied as is (to bytes 66 - 86)
85 * byte 93 year of manufacture is expanded to a 2 byte (big endian)
86 * field which includes the century (to bytes 87 - 88)
87 * bytes 94 - 127 are copied as is (to bytes 89 - 122)
89 * parameters:
90 * spd_data pointer to SPD data
91 * spd_data_len length of supplied SPD data
92 * sp_seg_ptr pointer to receive address of converted data
93 * sp_seg_len pointer for size of converted data
94 * return value:
95 * 0 - success
96 * NZ - error code
98 int
99 cvrt_dim_data(const char *spd_data, size_t spd_data_len, uchar_t **sp_seg_ptr,
100 size_t *sp_seg_len)
102 int c;
103 ushort_t year;
104 int capacity;
105 spd_data_t *spd;
106 uint32_t sum;
108 if (spd_data_len < sizeof (spd_data_t))
109 return (EINVAL);
111 spd = (spd_data_t *)spd_data;
112 *sp_seg_ptr = malloc(sizeof (sp_seg_body));
114 if (*sp_seg_ptr == NULL)
115 return (ENOMEM);
117 /* set up template for SP seg */
118 (void) memcpy(*sp_seg_ptr, sp_seg_body, sizeof (sp_seg_body));
120 year = spd->manu_year;
122 if (year < 80)
123 year += 2000;
124 else
125 year += 1900;
128 * move first 64 bytes of SPD data into SPD-R record
130 (void) memcpy(*sp_seg_ptr + SPD_R_OFF, spd_data, 64);
133 * re-write full data width as big endian
135 (*sp_seg_ptr + SPD_R_OFF + DATA_WIDTH)[0] = spd->ms_data_width;
136 (*sp_seg_ptr + SPD_R_OFF + DATA_WIDTH)[1] = spd->ls_data_width;
139 * construct Sun compressed encoding for JEDEC code
141 for (c = 0; c < sizeof (spd->jedec) - 1; c++) {
142 if (spd->jedec[c] != 0x7F)
143 break;
146 (*sp_seg_ptr)[SPD_R_OFF + MANUF_ID] = (uchar_t)c;
147 (*sp_seg_ptr)[SPD_R_OFF + MANUF_ID + 1] = (uchar_t)spd->jedec[c];
150 * move other fields in place
152 (void) memcpy(*sp_seg_ptr + SPD_R_OFF + MANUF_LOC,
153 &spd->manu_loc, MANUF_YEAR - MANUF_LOC);
155 (*sp_seg_ptr + SPD_R_OFF + MANUF_YEAR)[0] = (uchar_t)(year >> 8);
156 (*sp_seg_ptr + SPD_R_OFF + MANUF_YEAR)[1] = (uchar_t)year;
158 (void) memcpy(*sp_seg_ptr + SPD_R_OFF + MANUF_WEEK,
159 &spd->manu_week, SPD_R_LEN - MANUF_WEEK);
162 * calculate the capacity and insert into capacity record
164 if ((spd->spd_rev >> 4) > 1) {
165 (void) snprintf((char *)(*sp_seg_ptr + DIMM_CAP_OFF), 8,
166 "ver %x.%x", spd->spd_rev >> 4, spd->spd_rev & 0x0f);
167 } else if ((spd->memory_type != SPDMEM_SDRAM) &&
168 (spd->memory_type != SPDMEM_SDRAM_DDR) &&
169 (spd->memory_type != SPDMEM_DDR2_SDRAM)) {
171 * can't handle this memory type
173 ((char *)(*sp_seg_ptr))[DIMM_CAP_OFF] = '\0';
174 } else if ((((spd->ms_data_width << 8) | spd->ls_data_width) == 72) &&
175 ((spd->n_rows & 0xf0) == 0) && ((spd->n_cols & 0xf0) == 0)) {
177 * OK it's 72-bits wide with equal width banks
179 char m_or_g = 'G';
180 capacity = spd->mod_row_density;
181 if (((spd->memory_type == SPDMEM_DDR2_SDRAM) &&
182 (capacity > 16)) ||
183 (capacity > 4)) {
184 capacity *= 4;
185 m_or_g = 'M';
187 c = spd->n_mod_rows;
188 if (spd->memory_type == SPDMEM_DDR2_SDRAM) {
189 c &= 7;
190 c++;
192 capacity *= c;
193 if ((m_or_g == 'M') && (capacity >= 1024)) {
194 capacity /= 1024;
195 m_or_g = 'G';
197 (void) snprintf((char *)(*sp_seg_ptr + DIMM_CAP_OFF), 8,
198 "%d %cB", capacity, m_or_g);
199 } else {
200 ((char *)(*sp_seg_ptr))[DIMM_CAP_OFF] = '\0';
204 * finally, set the checksum
206 sum = compute_crc32(*sp_seg_ptr, sizeof (sp_seg_body) - 5);
207 for (c = 0; c < 4; c++) {
208 (*sp_seg_ptr + sizeof (sp_seg_body) - 4)[c] =
209 ((char *)(&sum))[c];
211 *sp_seg_len = sizeof (sp_seg_body);
212 return (0);
216 * get_spd_data - reads raw data from container
217 * parameters:
218 * fd file descriptor for SPD device
219 * ctr_offset container offset
220 * ctr_len container size
221 * spd_data buffer to receive SPD data (length ctr_len)
222 * return value:
223 * 0 - success
224 * NZ - error code
227 get_spd_data(int fd, char *spd_data, size_t ctr_len, off_t ctr_offset)
229 if (ctr_len < sizeof (spd_data_t))
230 return (EINVAL);
232 (void) memset(spd_data, 0, ctr_len);
234 if (pread(fd, spd_data, sizeof (spd_data_t), ctr_offset) !=
235 sizeof (spd_data_t))
236 return (EIO);
237 return (0);