xref: /illumos-gate/usr/src/uts/sun4u/serengeti/os/sg_unum.c (revision cbcdac8f95bd87f5b3243184b35ed7bd79fc1533)
103831d35Sstevel /*
203831d35Sstevel  * CDDL HEADER START
303831d35Sstevel  *
403831d35Sstevel  * The contents of this file are subject to the terms of the
5*cbcdac8fSmb91622  * Common Development and Distribution License (the "License").
6*cbcdac8fSmb91622  * You may not use this file except in compliance with the License.
703831d35Sstevel  *
803831d35Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
903831d35Sstevel  * or http://www.opensolaris.org/os/licensing.
1003831d35Sstevel  * See the License for the specific language governing permissions
1103831d35Sstevel  * and limitations under the License.
1203831d35Sstevel  *
1303831d35Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
1403831d35Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1503831d35Sstevel  * If applicable, add the following below this CDDL HEADER, with the
1603831d35Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
1703831d35Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
1803831d35Sstevel  *
1903831d35Sstevel  * CDDL HEADER END
2003831d35Sstevel  */
2103831d35Sstevel /*
22*cbcdac8fSmb91622  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2303831d35Sstevel  * Use is subject to license terms.
2403831d35Sstevel  */
2503831d35Sstevel 
2603831d35Sstevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
2703831d35Sstevel 
2803831d35Sstevel #include <sys/types.h>
2903831d35Sstevel #include <sys/serengeti.h>
3003831d35Sstevel #include <sys/errno.h>
3103831d35Sstevel #include <sys/systm.h>
3203831d35Sstevel #include <sys/cmn_err.h>
33*cbcdac8fSmb91622 #include <sys/cheetahregs.h>
34*cbcdac8fSmb91622 #include <sys/cpuvar.h>
3503831d35Sstevel 
3603831d35Sstevel /*
3703831d35Sstevel  * When an ECC error occurs on an E$ DIMM, the error handling code requests a
3803831d35Sstevel  * unum to provide a human-readable physical location to the part that
3903831d35Sstevel  * experienced the error.
4003831d35Sstevel  *
4103831d35Sstevel  * Previously, on Serengeti and LW8, a prom call was made to get this
4203831d35Sstevel  * information.  However, calling COBP to do a simple string format is
4303831d35Sstevel  * inefficient.  All the necessary information is now kept here.
4403831d35Sstevel  *
4503831d35Sstevel  * Since this data is now kept in two places (COBP and here), care must be
4603831d35Sstevel  * taken so that the two locations are kept the same.  Any changes to the
4703831d35Sstevel  * jnumber array will require a change to COBP code so that the two arrays
4803831d35Sstevel  * match.  Any changes to the unum string format will require changes in both
4903831d35Sstevel  * the COBP code (to match the code here) and plat_ecc_unum.c (to read the
5003831d35Sstevel  * new format).  These changes should not be necessary, except to reflect a
5103831d35Sstevel  * new cpu or board type.
5203831d35Sstevel  */
5303831d35Sstevel 
5403831d35Sstevel /*
5503831d35Sstevel  * The following array holds the jnumbers for Ecache DIMMs.  The first index
5603831d35Sstevel  * is the proc position on the board (0 through 3) and the second index is
5703831d35Sstevel  * the DIMM number (0 or 1).
5803831d35Sstevel  */
5903831d35Sstevel static int sg_j_number[SG_MAX_CMPS_PER_BD][SG_NUM_ECACHE_DIMMS_PER_CPU] = {
6003831d35Sstevel 	{ 4400, 4300 },
6103831d35Sstevel 	{ 5400, 5300 },
6203831d35Sstevel 	{ 6400, 6300 },
6303831d35Sstevel 	{ 7400, 7300 }
6403831d35Sstevel };
6503831d35Sstevel 
6603831d35Sstevel /*
6703831d35Sstevel  * Generate the unum for the specified cpuid and physical address.  Put the
6803831d35Sstevel  * unum in buf, which is of size buflen.  Return the length of the string in
6903831d35Sstevel  * lenp.
7003831d35Sstevel  *
7103831d35Sstevel  * Return 0 if successful, and an error number otherwise.
7203831d35Sstevel  */
7303831d35Sstevel int
sg_get_ecacheunum(int cpuid,uint64_t physaddr,char * buf,uint_t buflen,int * lenp)7403831d35Sstevel sg_get_ecacheunum(int cpuid, uint64_t physaddr, char *buf, uint_t buflen,
7503831d35Sstevel     int *lenp)
7603831d35Sstevel {
7703831d35Sstevel 	int node = SG_PORTID_TO_NODEID(cpuid);
7803831d35Sstevel 	int board = SG_CPU_BD_PORTID_TO_BD_NUM(cpuid);
7903831d35Sstevel 	int proc = SG_PORTID_TO_CPU_POSN(cpuid);
80*cbcdac8fSmb91622 	int dimm;
8103831d35Sstevel 
8203831d35Sstevel 	/*
8303831d35Sstevel 	 * node and dimm will always be valid.  board and proc may be -1 if
8403831d35Sstevel 	 * an invalid cpuid is passed in.
8503831d35Sstevel 	 */
8603831d35Sstevel 	if ((board == -1) || (proc == -1)) {
8703831d35Sstevel 		return (EINVAL);
8803831d35Sstevel 	}
8903831d35Sstevel 
90*cbcdac8fSmb91622 	/* Find the DIMM number (0 or 1) based on the value of physaddr bit 4 */
91*cbcdac8fSmb91622 	if (IS_PANTHER(cpunodes[CPU->cpu_id].implementation) ||
92*cbcdac8fSmb91622 	    IS_JAGUAR(cpunodes[CPU->cpu_id].implementation))
93*cbcdac8fSmb91622 		dimm = (physaddr & SG_ECACHE_DIMM_MASK) ? 0 : 1;
94*cbcdac8fSmb91622 	else
95*cbcdac8fSmb91622 		dimm = (physaddr & SG_ECACHE_DIMM_MASK) ? 1 : 0;
96*cbcdac8fSmb91622 
9703831d35Sstevel 	*lenp = snprintf(buf, buflen, "/N%d/SB%d/P%d/E%d J%d",
9803831d35Sstevel 	    node, board, proc, dimm, sg_j_number[proc][dimm]);
9903831d35Sstevel 
10003831d35Sstevel 	return (0);
10103831d35Sstevel }
102