/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Domain Services Module System Specific Code.
*
* The Domain Services (DS) module is responsible for communication
* with external service entities. It provides a kernel API for clients to
* publish capabilities and handles the low level communication and
* version negotiation required to export those capabilities to any
* interested service entity. Once a capability has been successfully
* registered with a service entity, the DS module facilitates all
* data transfers between the service entity and the client providing
* that particular capability.
*
* This file provides the system interfaces that are required for
* the ds.c module, which is common to both Solaris and VBSC (linux).
*/
#include <sys/mach_descrip.h>
/*
* All DS ports in the system
*
* The list of DS ports is read in from the MD when the DS module is
* initialized and is never modified. This eliminates the need for
* locking to access the port array itself. Access to the individual
* ports are synchronized at the port level.
*/
/*
* Table of registered services
*
* Locking: Accesses to the table of services are synchronized using
* a mutex lock. The reader lock must be held when looking up service
* information in the table. The writer lock must be held when any
* service information is being modified.
*/
/*
* Taskq for internal task processing
*/
/*
* The actual required number of parallel threads is not expected
* to be very large. Use the maximum number of CPUs in the system
* as a rough upper bound.
*/
#ifdef DEBUG
/*
* Debug Flag
*/
#endif /* DEBUG */
/* initialization functions */
static void ds_init(void);
static void ds_fini(void);
static int ds_ports_init(void);
static int ds_ports_fini(void);
/* port utilities */
/* log functions */
static void ds_log_init(void);
static void ds_log_fini(void);
static int ds_log_remove(void);
static void ds_log_purge(void *arg);
"Domain Services 1.9"
};
(void *)&modlmisc,
};
int
_init(void)
{
int rv;
/*
* Perform all internal setup before initializing
* the DS ports. This ensures that events can be
* processed as soon as the port comes up.
*/
ds_init();
/* force attach channel nexus */
(void) i_ddi_attach_hw_nodes("cnex");
if ((rv = ds_ports_init()) != 0) {
ds_fini();
return (rv);
}
(void) ds_ports_fini();
ds_fini();
}
return (rv);
}
int
{
}
int
_fini(void)
{
int rv;
(void) ds_ports_fini();
ds_fini();
}
return (rv);
}
static void
ds_fini(void)
{
/*
* Flip the enabled switch to make sure that no
* incoming events get dispatched while things
* are being torn down.
*/
/*
* Destroy the taskq.
*/
/*
* Destroy the message log.
*/
ds_log_fini();
/*
* Deallocate the table of registered services
*/
/* clear out all entries */
/* destroy the table itself */
}
/*
* Initialize the list of ports based on the MD.
*/
static int
ds_ports_init(void)
{
int idx;
int rv = 0;
int num_nodes;
int listsz;
int nport;
int nchan;
return (-1);
}
/* allocate temporary storage for MD scans */
/*
* The root of the search for DS port nodes is the
* DS node. Perform a scan to find that node.
*/
if (nport <= 0) {
goto done;
}
/* expecting only one DS node */
if (nport != 1) {
}
/* find all the DS ports in the MD */
if (nport <= 0) {
goto done;
}
/*
* Initialize all the ports found in the MD.
*/
/* get the channels for this port */
if (nchan <= 0) {
rv = -1;
goto done;
}
/* expecting only one channel */
if (nchan != 1) {
}
rv = -1;
goto done;
}
}
done:
if (rv != 0)
(void) ds_ports_fini();
(void) md_fini_handle(mdp);
return (rv);
}
static int
ds_ports_fini(void)
{
int idx;
/*
* Tear down each initialized port.
*/
}
}
return (0);
}
static int
{
int len;
/* get the ID for this port */
__func__);
return (-1);
}
/* sanity check the port id */
if (port_id > DS_MAX_PORT_ID) {
return (-1);
}
/* get the channel ID for this port */
return (-1);
}
return (-1);
/*
* Identify the SP Port. The SP port is the only one with
* the "ldc-ids" property, and is only on the primary domain.
*/
if (ds_sp_port_id == DS_PORTID_INVALID &&
}
return (0);
}
void
{
if (ds_my_domain_name != NULL) {
}
}
}
void
ds_init()
{
/*
* Create taskq for internal processing threads. This
* includes processing incoming request messages and
* sending out of band registration messages.
*/
/*
* Initialize the message log.
*/
ds_log_init();
}
int
{
}
/*
* Drain event queue, if necessary.
*/
void
{
}
/*
* System specific port initalization.
*/
void
{
}
/*
* System specific port teardown.
*/
void
{
}
/*
* System specific LDC channel initialization.
*/
void
{
int rv;
return;
}
}
/*
* DS message log
*
* Locking: The message log is protected by a single mutex. This
* protects all fields in the log structure itself as well as
* everything in the entry structures on both the log and the
* free list.
*/
static struct log {
} ds_log;
/* log soft limit */
/* initial pool of log entry structures */
/*
* Logging Support
*/
static void
ds_log_init(void)
{
/* initialize global lock */
/* initialize the log */
/* initialize the free list */
}
}
static void
ds_log_fini(void)
{
/* clear out the log */
(void) ds_log_remove();
/*
* Now all the entries are on the free list.
* Clear out the free list, deallocating any
* entry that was dynamically allocated.
*/
}
}
}
static ds_log_entry_t *
ds_log_entry_alloc(void)
{
}
/* free list was empty */
}
return (new);
}
static void
{
return;
}
/* place entry on the free list */
}
/*
* Add a message to the end of the log
*/
static int
{
} else {
}
/* increase the log size, including the metadata size */
return (0);
}
/*
* Remove an entry from the head of the log
*/
static int
ds_log_remove(void)
{
/* empty list */
return (0);
/* one element list */
} else {
}
return (0);
}
/*
* Replace the data in the entry at the front of the list with then
* new data. This has the effect of removing the oldest entry and
* adding the new entry.
*/
static int
{
return (0);
}
static void
{
(void) ds_log_remove();
}
}
int
{
int rv = 0;
void *data;
/* allocate a local copy of the data */
/* check if the log is larger than the soft limit */
/*
* The log is larger than the soft limit.
* Swap the oldest entry for the newest.
*/
__func__);
} else {
/*
* Still have headroom under the soft limit.
* Add the new entry to the log.
*/
new = ds_log_entry_alloc();
/* fill in message data */
}
/* check if the log is larger than the hard limit */
/*
* Wakeup the thread to remove entries
* from the log until it is smaller than
* the soft limit.
*/
__func__);
}
}
return (rv);
}
int
{
/* sanity check the port id */
if (port_id > DS_MAX_PORT_ID) {
return (EINVAL);
}
/* get the port structure from the array of ports */
/* check for a duplicate port in the MD */
if (verbose) {
}
}
}
return (EBUSY);
}
/* initialize the port */
if (dom_name) {
} else
return (0);
}
/* ARGSUSED */
int
{
port_id);
return (EINVAL);
}
/* shut down the LDC for this port */
(void) ds_ldc_fini(port);
}
if (port->domain_name) {
}
/* clean up the port structure */
return (0);
}
/*
* Interface for ds_service_lookup in lds driver.
*/
int
{
(u_longlong_t)hdl);
return (ENXIO);
}
return (0);
}
/*
* Interface for ds_domain_lookup in lds driver.
*/
int
{
(u_longlong_t)hdl);
return (ENXIO);
}
else
return (0);
}
/*
* Interface for ds_hdl_isready in lds driver.
*/
int
{
(u_longlong_t)hdl);
return (ENXIO);
}
return (0);
}
/*
* Interface for ds_dom_name_to_hdl in lds driver.
*/
int
{
int i;
if (domain_name == NULL) {
return (ENXIO);
}
if (ds_my_domain_name != NULL &&
return (0);
}
return (0);
}
}
return (ENXIO);
}
/*
* Interface for ds_dom_hdl_to_name in lds driver.
*/
int
{
int i;
if (dhdl == ds_my_domain_hdl) {
if (ds_my_domain_name != NULL) {
return (0);
}
return (ENXIO);
}
return (0);
}
}
return (ENXIO);
}
/*
* Unregister all handles related to device open instance.
*/
void
{
int idx;
/* walk every table entry */
if (DS_SVC_ISFREE(svc))
continue;
(void) ds_unreg_hdl(hdl);
}
}
}
/*
* Special callbacks to allow the lds module revision-independent access
* to service structure data in the callback routines. This assumes that
* we put a special "cookie" in the arg argument passed to those
* routines (for now, a ptr to the svc structure, but it could be a svc
* table index or something that we could get back to the svc table entry).
*/
void
{
}
void
{
}
void
{
}
void
{
}
void
{
else
}
void
{
}
void
{
}
void
{
}
int
{
return (0);
}
return (ENXIO);
}
int
{
int rv = 0;
(u_longlong_t)hdl);
} else if (instance == DS_INVALID_INSTANCE) {
}
(u_longlong_t)hdl);
}
return (rv);
}