/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _MEM_H
#define	_MEM_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <sys/types.h>
#include <sys/nvpair.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * FMRI plugin for the `mem' scheme.
 *
 * The mem scheme can be used to name individual memory modules, as well as
 * groups of memory modules, also known as banks.  The name `dimm' is used as a
 * synonym for individual memory modules, for no good reason.  Mem FMRIs can
 * be further refined with the addition of a member which identifies a
 * particular physical page within the bank or DIMM.  The named page is as
 * viewed by the VM system, and may thus span multiple memory modules.  It will,
 * however, be at least partially contained by the named bank or DIMM.
 *
 * Memory modules are identified by two things - their physical position, or
 * slot, in the machine, and their serial number.  DIMMs are identified by this
 * tuple on platforms which support the retrieval of serial numbers.  Platforms
 * which don't have this support rely on the slot number, with the corresponding
 * degradation in their ability to detect hardware changees.
 *
 * The physical location is embodied by the unum, which is highly specific to
 * each platform, and bears a passing resemblance to the name of the slot, as
 * printed on the actual hardware.  The unum is mapped to a DIMM-specific
 * device, which is then read to determine the serial number.  See mem_disc.c
 * for details of the process by which unums are mapped to devices, and
 * mem_read.c for the code which actually retrieves the serial number from the
 * device.
 *
 * Banks are also identified by unums, which must be broken apart into the
 * unums which identify each constituent memory module.  Serial numbers are
 * retrieved for banks - one per member module - in the same way as for
 * individual modules.  See mem_unum.c for the code which bursts bank unums.
 *
 * Serial number retrieval, on platforms which support it, is very expensive
 * (on the order of several tenths of a second, which adds up in a hurry on
 * larger machines).  So, while we pre-generate the list of DIMM device paths,
 * we only read their serial numbers when requested by plugin consumers.  To
 * further reduce the perceived cost, we don't re-read until/unless we detect
 * that a DR operation has taken place.
 *
 * Using the facilities described above, the plugin implements the following
 * entry points: (see mem.c)
 *
 *   - nvl2str: The printed representation of the named bank or DIMM is
 *     generated.  No attempt is made to determine whether or not the named
 *     item is still present in the system.
 *
 *   - expand: At the time of this writing, no platforms include bank or DIMM
 *     serial numbers in their ereports.  As such, the serial number(s) must
 *     be added by the diagnosis engine.  This entry point will read the
 *     serial number(s) for the named item, and will add it/them to the passed
 *     FMRI.  Errors will be returned if the FMRI (unum) was unparseable, or if
 *     the serial number could not be retrieved.
 *
 *   - present: Given a mem-schemed FMRI with a serial number, this entry
 *     point will attempt to determine whether the bank or module named in the
 *     FMRI is still present in the system at the same location.  Programmer
 *     errors (invalid FMRIs) will be signalled to the caller.  Warnings will
 *     be emitted for otherwise-valid FMRIs whose serial numbers could not be
 *     read, with the caller told that the FMRI is not present.
 *
 *   - contains: Used to determine whether a given bank contains a given DIMM.
 *     No attempt is made to determine whether the module named by the FMRIs are
 *     actually present in the system.  Programmer errors (invalidd FMRIs) will
 *     be returned to the caller.  Warnings will be emitted for otherwise-valid
 *     FMRIs whose relationship could not be determined, with the caller told
 *     that there is no relationship.
 */

/* 8+nul for SPD, 6+nul for SEEPROM, 15+nul max for Serengeti, Starcat, LW8 */
#define	MEM_SERID_MAXLEN	16

typedef struct mem_dimm_map {
	struct mem_dimm_map *dm_next;	/* The next DIMM map */
	char *dm_label;			/* The UNUM for this DIMM */
	char *dm_device;		/* Path to I2C device for DIMM */
	char dm_serid[MEM_SERID_MAXLEN]; /* Cached serial number */
	uint64_t dm_drgen;		/* DR gen count for cached S/N */
} mem_dimm_map_t;

typedef struct mem {
	mem_dimm_map_t *mem_dm;		/* List supported DIMMs */
	uint64_t mem_memconfig;		/* HV memory-configuration-id# */
} mem_t;

extern int mem_discover(void);
extern int mem_get_serid(const char *, char *, size_t);

extern int mem_unum_burst(const char *, char ***, size_t *);
extern int mem_unum_contains(const char *, const char *);
extern int mem_unum_rewrite(nvlist_t *, nvlist_t **);

extern void mem_strarray_free(char **, size_t);
extern int mem_page_cmd(int, nvlist_t *);

extern mem_t mem;

#ifdef __cplusplus
}
#endif

#endif /* _MEM_H */