aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/hfa/fore_vcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/hfa/fore_vcm.c')
-rw-r--r--sys/dev/hfa/fore_vcm.c321
1 files changed, 321 insertions, 0 deletions
diff --git a/sys/dev/hfa/fore_vcm.c b/sys/dev/hfa/fore_vcm.c
new file mode 100644
index 000000000000..3efea6a46deb
--- /dev/null
+++ b/sys/dev/hfa/fore_vcm.c
@@ -0,0 +1,321 @@
+/*
+ *
+ * ===================================
+ * HARP | Host ATM Research Platform
+ * ===================================
+ *
+ *
+ * This Host ATM Research Platform ("HARP") file (the "Software") is
+ * made available by Network Computing Services, Inc. ("NetworkCS")
+ * "AS IS". NetworkCS does not provide maintenance, improvements or
+ * support of any kind.
+ *
+ * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
+ * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
+ * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
+ * In no event shall NetworkCS be responsible for any damages, including
+ * but not limited to consequential damages, arising from or relating to
+ * any use of the Software or related support.
+ *
+ * Copyright 1994-1998 Network Computing Services, Inc.
+ *
+ * Copies of this Software may be made, however, the above copyright
+ * notice must be reproduced on all copies.
+ *
+ * @(#) $Id: fore_vcm.c,v 1.7 1998/06/29 21:42:20 mks Exp $
+ *
+ */
+
+/*
+ * FORE Systems 200-Series Adapter Support
+ * ---------------------------------------
+ *
+ * Virtual Channel Management
+ *
+ */
+
+#ifndef lint
+static char *RCSid = "@(#) $Id: fore_vcm.c,v 1.7 1998/06/29 21:42:20 mks Exp $";
+#endif
+
+#include <dev/hfa/fore_include.h>
+
+
+/*
+ * VCC Stack Instantiation
+ *
+ * This function is called via the common driver code during a device VCC
+ * stack instantiation. The common code has already validated some of
+ * the request so we just need to check a few more Fore-specific details.
+ *
+ * Called at splnet.
+ *
+ * Arguments:
+ * cup pointer to device common unit
+ * cvp pointer to common VCC entry
+ *
+ * Returns:
+ * 0 instantiation successful
+ * err instantiation failed - reason indicated
+ *
+ */
+int
+fore_instvcc(cup, cvp)
+ Cmn_unit *cup;
+ Cmn_vcc *cvp;
+{
+ Fore_vcc *fvp = (Fore_vcc *)cvp;
+ Atm_attributes *ap = &fvp->fv_connvc->cvc_attr;
+
+ /*
+ * Validate requested AAL
+ */
+ switch (ap->aal.type) {
+
+ case ATM_AAL0:
+ fvp->fv_aal = FORE_AAL_0;
+ break;
+
+ case ATM_AAL3_4:
+ fvp->fv_aal = FORE_AAL_4;
+ if ((ap->aal.v.aal4.forward_max_SDU_size > FORE_IFF_MTU) ||
+ (ap->aal.v.aal4.backward_max_SDU_size > FORE_IFF_MTU))
+ return (EINVAL);
+ break;
+
+ case ATM_AAL5:
+ fvp->fv_aal = FORE_AAL_5;
+ if ((ap->aal.v.aal5.forward_max_SDU_size > FORE_IFF_MTU) ||
+ (ap->aal.v.aal5.backward_max_SDU_size > FORE_IFF_MTU))
+ return (EINVAL);
+ break;
+
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+
+/*
+ * Open a VCC
+ *
+ * This function is called via the common driver code after receiving a
+ * stack *_INIT command. The common code has already validated most of
+ * the request so we just need to check a few more Fore-specific details.
+ * Then we just issue the command to the CP. Note that we can't wait around
+ * for the CP to process the command, so we return success for now and abort
+ * the connection if the command later fails.
+ *
+ * Called at splimp.
+ *
+ * Arguments:
+ * cup pointer to device common unit
+ * cvp pointer to common VCC entry
+ *
+ * Returns:
+ * 0 open successful
+ * else open failed
+ *
+ */
+int
+fore_openvcc(cup, cvp)
+ Cmn_unit *cup;
+ Cmn_vcc *cvp;
+{
+ Fore_unit *fup = (Fore_unit *)cup;
+ Fore_vcc *fvp = (Fore_vcc *)cvp;
+ H_cmd_queue *hcp;
+ Cmd_queue *cqp;
+ struct vccb *vcp;
+
+ vcp = fvp->fv_connvc->cvc_vcc;
+
+ ATM_DEBUG4("fore_openvcc: fup=0x%x, fvp=0x%x, vcc=(%d,%d)\n",
+ (int)fup, (int)fvp, vcp->vc_vpi, vcp->vc_vci);
+
+ /*
+ * Validate the VPI and VCI values
+ */
+ if ((vcp->vc_vpi > fup->fu_pif.pif_maxvpi) ||
+ (vcp->vc_vci > fup->fu_pif.pif_maxvci)) {
+ return (1);
+ }
+
+ /*
+ * Only need to tell the CP about incoming VCCs
+ */
+ if ((vcp->vc_type & VCC_IN) == 0) {
+ DEVICE_LOCK((Cmn_unit *)fup);
+ fup->fu_open_vcc++;
+ fvp->fv_state = CVS_ACTIVE;
+ DEVICE_UNLOCK((Cmn_unit *)fup);
+ return (0);
+ }
+
+ /*
+ * Queue command at end of command queue
+ */
+ hcp = fup->fu_cmd_tail;
+ if ((*hcp->hcq_status) & QSTAT_FREE) {
+
+ /*
+ * Queue entry available, so set our view of things up
+ */
+ hcp->hcq_code = CMD_ACT_VCCIN;
+ hcp->hcq_arg = fvp;
+ fup->fu_cmd_tail = hcp->hcq_next;
+ fvp->fv_flags |= FVF_ACTCMD;
+
+ /*
+ * Now set the CP-resident queue entry - the CP will grab
+ * the command when the op-code is set.
+ */
+ cqp = hcp->hcq_cpelem;
+ (*hcp->hcq_status) = QSTAT_PENDING;
+ cqp->cmdq_act.act_vccid = CP_WRITE(vcp->vc_vci);
+ if (fvp->fv_aal == FORE_AAL_0)
+ cqp->cmdq_act.act_batch = CP_WRITE(1);
+ cqp->cmdq_act.act_spec = CP_WRITE(
+ ACT_SET_SPEC(BUF_STRAT_1, fvp->fv_aal,
+ CMD_ACT_VCCIN | CMD_INTR_REQ));
+ } else {
+ /*
+ * Command queue full
+ */
+ fup->fu_stats->st_drv.drv_cm_full++;
+ return (1);
+ }
+
+ return (0);
+}
+
+
+/*
+ * Close a VCC
+ *
+ * This function is called via the common driver code after receiving a
+ * stack *_TERM command. The common code has already validated most of
+ * the request so we just need to check a few more Fore-specific details.
+ * Then we just issue the command to the CP. Note that we can't wait around
+ * for the CP to process the command, so we return success for now and whine
+ * if the command later fails.
+ *
+ * Called at splimp.
+ *
+ * Arguments:
+ * cup pointer to device common unit
+ * cvp pointer to common VCC entry
+ *
+ * Returns:
+ * 0 close successful
+ * else close failed
+ *
+ */
+int
+fore_closevcc(cup, cvp)
+ Cmn_unit *cup;
+ Cmn_vcc *cvp;
+{
+ Fore_unit *fup = (Fore_unit *)cup;
+ Fore_vcc *fvp = (Fore_vcc *)cvp;
+ H_xmit_queue *hxp;
+ H_cmd_queue *hcp;
+ Cmd_queue *cqp;
+ struct vccb *vcp;
+ int i, err = 0;
+
+ vcp = fvp->fv_connvc->cvc_vcc;
+
+ ATM_DEBUG4("fore_closevcc: fup=0x%x, fvp=0x%x, vcc=(%d,%d)\n",
+ (int)fup, (int)fvp, vcp->vc_vpi, vcp->vc_vci);
+
+ DEVICE_LOCK((Cmn_unit *)fup);
+
+ /*
+ * Clear any references to this VCC in our transmit queue
+ */
+ for (hxp = fup->fu_xmit_head, i = 0;
+ (*hxp->hxq_status != QSTAT_FREE) && (i < XMIT_QUELEN);
+ hxp = hxp->hxq_next, i++) {
+ if (hxp->hxq_vcc == fvp) {
+ hxp->hxq_vcc = NULL;
+ }
+ }
+
+ /*
+ * Clear any references to this VCC in our command queue
+ */
+ for (hcp = fup->fu_cmd_head, i = 0;
+ (*hcp->hcq_status != QSTAT_FREE) && (i < CMD_QUELEN);
+ hcp = hcp->hcq_next, i++) {
+ switch (hcp->hcq_code) {
+
+ case CMD_ACT_VCCIN:
+ case CMD_ACT_VCCOUT:
+ if (hcp->hcq_arg == fvp) {
+ hcp->hcq_arg = NULL;
+ }
+ break;
+ }
+ }
+
+ /*
+ * If this VCC has been previously activated, then we need to tell
+ * the CP to deactivate it.
+ */
+ if (fvp->fv_flags & FVF_ACTCMD) {
+
+ /*
+ * Queue command at end of command queue
+ */
+ hcp = fup->fu_cmd_tail;
+ if ((*hcp->hcq_status) & QSTAT_FREE) {
+
+ /*
+ * Queue entry available, so set our view of things up
+ */
+ hcp->hcq_code = CMD_DACT_VCCIN;
+ hcp->hcq_arg = fvp;
+ fup->fu_cmd_tail = hcp->hcq_next;
+
+ /*
+ * Now set the CP-resident queue entry - the CP will
+ * grab the command when the op-code is set.
+ */
+ cqp = hcp->hcq_cpelem;
+ (*hcp->hcq_status) = QSTAT_PENDING;
+ cqp->cmdq_dact.dact_vccid = CP_WRITE(vcp->vc_vci);
+ cqp->cmdq_dact.dact_cmd =
+ CP_WRITE(CMD_DACT_VCCIN|CMD_INTR_REQ);
+ } else {
+ /*
+ * Command queue full
+ *
+ * If we get here, we'll be getting out-of-sync with
+ * the CP because we can't (for now at least) do
+ * anything about close errors in the common code.
+ * This won't be too bad, since we'll just toss any
+ * PDUs received from the VCC and the sigmgr's will
+ * always get open failures when trying to use this
+ * (vpi,vci)...oh, well...always gotta have that one
+ * last bug to fix! XXX
+ */
+ fup->fu_stats->st_drv.drv_cm_full++;
+ err = 1;
+ }
+ }
+
+ /*
+ * Finish up...
+ */
+ if (fvp->fv_state == CVS_ACTIVE)
+ fup->fu_open_vcc--;
+
+ DEVICE_UNLOCK((Cmn_unit *)fup);
+
+ return (err);
+}
+