/*
* 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
* 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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Hash table parameters for tpi_provinfo_table.
*/
/*
* Use the first element in the key for the hash.
*/
/*
* SAMESTR is a very confusing name. LAST_QUEUE is introduced for readability.
*/
static int tpi_hashshift;
/*
* In most cases there is some transport provider (like tcp or udp) below
* transport user (like timod or sockets). However, it is possible to construct
* stream without transport provider (e.g. by pushing timod into FIFO). It is
* hardly of any use, but this condition was observed with sparcv9 abi tests.
* To count for such special case, a special tpi_nullprov static data is
* provided to cache information about such degenerated null-transport case.
*/
/*
* Initialise the TPI support routines. Called from strinit().
*/
void
tpi_init()
{
/*
* Calculate the right shift for hashing a tpi_provinfo_t.
*/
}
/*
* Generate a downstream signature given the write-side queue. It
* passes back the size of the generated key in *keylenp. This routine
* cannot multithread as it returns a pointer to a static data item.
*
* There is no way (in the current module loading infrastructure) to
* _absolutely_ guarantee that the key below uniquely identifies an
* arrangement of modules and drivers. A module _might_ be unloaded and
* another module _might_ be loaded such that the qi_minfo is at _exactly_
* same kernel address, and then it _might_ be placed in a transport
* provider stream in exactly the same configuration (modules above and
* below all identical) - but it would take quite a few coincidences
* and modules loading and unloading does not usually happen n times a
* second...
*/
static void *
{
int i;
/* assert this queue is write queue and qprocson() is called before */
/*
* This can be global because tpi_makekey is called with
* tpi_provinfo_lock.
*/
/*
* Go down q_next to the driver, but no further. We use the qi_minfo
* because we can find in from the queue and it is a stable part of
*/
}
/*
* Allocate the actual key with the proper length, and pass it
* all back.
*/
return ((void *)key);
}
/*
* Find an existing provider entry given a queue pointer, or allocate a
* new empty entry if not found. Because this routine calls kmem_alloc
* with KM_SLEEP, and because it traverses the q_next pointers of a stream
* it must be called with a proper user context and within a perimeter
* which protects the STREAM e.g. an open routine. This routine always
* returns a valid pointer.
*/
{
void *key;
/*
* Must hold tpi_provinfo_lock since tpi_makekey() returns a pointer
* to static data.
*/
if (keylen == 0) {
/* there is nothing below us, return special nullprov entry */
return (&tpi_nullprov);
}
/*
* Look for an existing entry, or the place to put a new one.
*/
return (*tpp);
}
}
/*
* Allocate and fill in the new tpi_provinfo_t.
*/
return (*tpp);
}
/*
* Allocate a TPI ACK reusing the old message if possible.
*/
mblk_t *
{
return (NULL);
}
}
return (mp);
}