/*
* 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 specific portion of the Starcat Management Network Driver
*/
#include <sys/ethernet.h>
#include <sys/byteorder.h>
#include <sys/iosramio.h>
#include <netinet/igmp_var.h>
#include <sys/ddi_impldefs.h>
/*
* Domain side function prototypes.
*/
int man_get_iosram(manc_t *);
int man_domain_configure(void);
int man_domain_deconfigure(void);
int man_path_discovery(void);
int man_dossc_switch(uint32_t);
int man_dr_attach(dev_info_t *);
int man_dr_detach(dev_info_t *);
static int man_dr_submit_work_wait(dev_info_t *, int);
static int man_dip_is_schizoxmits0_pcib(dev_info_t *, int *, int *);
static int man_dip_is_attached(dev_info_t *);
/*
* Externs
*/
extern void *man_softstate;
extern man_work_t *man_work_alloc(int, int);
extern void man_work_free(man_work_t *);
extern man_workq_t *man_bwork_q;
extern man_workq_t *man_iwork_q;
extern queue_t *man_ctl_wq;
#if defined(DEBUG)
static void man_print_manc(manc_t *);
#endif /* DEBUG */
int
man_domain_configure(void)
{
int status = 0;
/*
* man_mbox_initialized is protected by inner perimiter lock.
*/
if (man_mbox_initialized == TRUE)
goto exit;
if (status != 0) {
" MBOXSC_MBOX_IN, errno = %d", status);
goto exit;
}
if (status != 0) {
(void) mboxsc_fini(IOSRAM_KEY_SCMD);
" MBOXSC_MBOX_OUT, errno = %d", status);
goto exit;
}
status = man_path_discovery();
if (status != 0) {
(void) mboxsc_fini(IOSRAM_KEY_SCMD);
(void) mboxsc_fini(IOSRAM_KEY_MDSC);
}
exit:
return (status);
}
/*
* Build pathgroup connecting a domain to the SSC. Only called on domains
* at first man_open. On the SSC, pathgroups are built by IOCTL requests
* from the MAN daemon (see man_ioctl and mand(1M)).
*
* Locks held
* - exclusive innerperim.
*/
int
man_path_discovery(void)
{
int num_devs;
int status = 0;
int i;
goto exit;
}
/*
* If manc_ip_type indicates MAN network is not enabled
* for this domain, then lets just bailout from here as if no
* devices were found.
*/
goto exit;
}
/*
* Extract SC ethernet address from IOSRAM.
*/
/*
* Get list of present devices, and update man_paths[] as needed.
*/
if (num_devs <= 0) {
goto exit;
}
if (status) {
goto exit;
}
/*
* Now activate the ethernet on the golden io board.
*/
for (i = 0; i < num_devs; i++) {
}
exit:
return (status);
}
int
man_domain_deconfigure(void)
{
(void) mboxsc_fini(IOSRAM_KEY_SCMD);
(void) mboxsc_fini(IOSRAM_KEY_MDSC);
/*
* We are about to unload and know that there are no open
* streams, so this change outside of the perimiter is ok.
*/
return (0);
}
/*
* Add a work request to the inner perimeter with the new eri device info.
*/
/* ARGSUSED */
int
{
int status = 0;
goto exit;
}
goto exit;
}
goto exit;
}
if (man_ctl_wq)
exit:
return (status);
}
int
{
int status = 0;
int retries = 0;
goto exit;
}
/*
* Arrange to have the detaching path switched if it is active.
* We will cv_wait_sig for the switch to complete if it is needed.
*/
/*
* Delay a bit and retry.
*/
("man_dr_detach(switch): EAGAIN - retrying..."));
retries++;
goto again;
}
if (status)
goto exit;
retries = 0;
/*
* Detaching device no longer in use, remove it from our
* pathgroup.
*/
("man_dr_detach(detach): EAGAIN - retrying..."));
retries++;
goto again;
}
exit:
return (status);
}
static int
{
int status = 0;
goto exit;
}
/* TBD - change to ASSERT ? */
if (man_ctl_wq)
break;
}
}
/*
* Note that if cv_wait_sig() returns zero because a signal
* was received, MAN_WFLAGS_DONE may not be set.
* This will happen if man_dr_submit_work_wait() reacquires
* man_lock before man_iwork() can acquire man_lock just before
* signalling its work is complete.
* In this case, it is not necessary to call man_work_free()
* here because it will be called by man_iwork() because
* MAN_WFLAGS_CVWAITER was cleared.
* Should man_iwork() obtain man_lock to signal completion,
* MAN_WFLAGS_DONE will be set which will ensure man_work_free()
* is called here.
*/
}
exit:
return (status);
}
/*
* Notify SSC of switch request and wait for response.
*/
int
{
int status = 0;
/*
* There should be nothing in inbound mailbox.
*/
length = sizeof (man_mbox_msg_t);
length = sizeof (man_mbox_msg_t);
}
req_tid = 0;
if (status != 0) {
" errno = %d", status);
goto exit;
}
length = sizeof (man_mbox_msg_t);
if (status != 0) {
" errno = %d", status);
goto exit;
}
goto exit;
}
if (status != 0) {
status);
}
exit:
return (status);
}
/*
* Read IOSRAM info.
*/
int
{
int status;
return (EINVAL);
if (status) {
" errno = %d\n", status);
return (status);
}
}
return (status);
}
#if defined(MAN_NO_IOSRAM)
0,
/* 0x10010102, Two */
0x10010103, /* Scot */
0xFF000000, /* Scot netmask */
0x10010101, /* SC 10.1.1.1 */
{0}, /* AF_INET6 addrs */
{0}, /* AF_INET6 addrs */
{0},
/* {0x8, 0x0, 0x20, 0x21, 0x44, 0x83}, Domain eaddr "two" */
{0x8, 0x0, 0x20, 0x8f, 0x84, 0x63}, /* Domain eaddr "scot" */
{0x8, 0x0, 0x20, 0x1f, 0xe3, 0x46}, /* SC eaddr "one" */
0x1,
0x1
};
/*
* Get IOSRAM info or release it.
*/
int
{
int status = 0;
return (EINVAL);
}
return (status);
}
#endif /* MAN_NO_IOSRAM */
/*
* Find all RIOs on the IO boards for the domain. We walk all the children
* of the root node looking for a PCI devinfo with a safari port ID of
* 0xDC that has a child with device ID of 3. This is gauranteed to be
* the network portion of the RIO by virtue of the way Starcats are
* physically built.
*/
static int
{
int exp_id;
int found = 0;
int circ;
int circ2;
int xmits;
(void *)(mipathp), golden_iob));
/*
* Hold parent busy while walking its child list.
*/
rdip = ddi_root_node();
exp_id = -1;
xmits = 0;
if (xmits) {
/*
* If this is XMITS0 PCI_B leaf, then the
* pci_pci bridge which is the only child,
* is the parent to MAN RIO.
*/
continue;
}
}
"eri_dip %s\n",
found++;
("man_find_devs: found eri maj(%d) "
"ppa(%d) on expander(%d)\n",
}
}
}
}
return (found);
}
/*
* Verify if the dip passed is an instance of 'eri' and set
* the device info in mdevp.
*/
static int
{
int exp_id;
int xmits;
char *name;
/*
* Verify if the parent is schizo(xmits)0 and pci B leaf.
*/
return (FALSE);
/*
* This RIO could be on XMITS, so get the dip to
* XMITS PCI Leaf.
*/
return (FALSE);
return (FALSE);
}
}
return (FALSE);
/*
* Make sure it is attached.
*/
"dip 0x%p not attached\n", (void *)dip));
return (FALSE);
}
return (TRUE);
}
/*
* Incase of XMITS, it is actually connected to a PCI Bridge(21154)
* which is directly connected to the PCI_B leaf of XMITS0.
*
* PCI_B Leaf. This is done as follows:
*
* - Verify the Device type to be "pci".
* - Verify the PortID to be ending with 0x1C
* - Verify the the CSR base to be 0x70.0000.
*/
static int
{
int portid;
char *name;
*exp_id = -1;
return (FALSE);
"SCHIZO found 0x%p\n", (void *)dip));
"XMITS found 0x%p\n", (void *)dip));
} else
return (FALSE);
goto notfound;
/*
* Get safari ID (DDI port ID).
*/
goto notfound;
}
/*
* All schizo 0 safari IDs end in 0x1C.
*/
goto notfound;
/*
* All PCI nodes "B" are at configspace 0x70.0000
*/
&length) != DDI_PROP_SUCCESS) {
goto notfound;
}
if (pci_csr_base == MAN_PCI_B_CSR_BASE) {
" found PCI B at dip(0x%p)\n", (void *)dip));
return (TRUE);
}
}
return (FALSE);
}
static int
{
int length = 0;
&length) == DDI_PROP_SUCCESS) {
/*
* The network function of the RIO ASIC will always
* be device 3 and function 1 ("network@3,1").
*/
return (TRUE);
}
}
return (FALSE);
}
static int
{
int state;
/*
* The instance info is more important for us,
* so verify.
*/
if (ddi_get_instance(dip) >= 0) {
return (TRUE);
}
"eri 0x%p instance is not set yet", (void *)dip);
}
return (FALSE);
}
#if defined(DEBUG)
static void
{
return;
}
#endif /* DEBUG */