diff options
Diffstat (limited to 'sys/dev/hfa/fore_vcm.c')
-rw-r--r-- | sys/dev/hfa/fore_vcm.c | 321 |
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); +} + |