📄 if_scs.c
字号:
if ((status = scs_map_buf(csb)) != RET_SUCCESS) { printf("scsnet: could not map recv buffer\n"); bp->state = SCSNET_BDONE; goto bad; } /* * Save info for Block Done event. When the block transfer * completes we will need the protocol header in the csb * buffer and we will need the pointer to the rest of data (m). * The local block handle (lbhandle) is needed to * unmap the block when we are finished with it. * We also save the buffer to use for an ACK later on. */ Move_bhandle(csb->lbhandle, bp->csb.lbhandle) bp->csb.buf = csb->buf; bp->mchain = m; /* * Start up the block transfer */ Move_bhandle(msg->bhandle, csb->rbhandle) csb->Rboff = msg->off; csb->Lboff = 0; csb->size = msg->totlen; if ((status=scs_req_data(csb))!=RET_SUCCESS){ if (scsnetdebug) printf("scsnet: req_data failed , status= %x\n",status); if ((status = scs_unmap_buf(csb) != RET_SUCCESS)) printf("scsnet0: unmap failed, status=%d\n", status); bp->state = SCSNET_BDONE; goto bad; } bp->csb.Aux = csb->Aux; /* save address of netsystem structure */ return;bad: if (m) m_freem(m); msg->cmd = SCSNET_BCMD_NACK; csb->size = Scsnet_msg_hdr_siz; csb->Disposal = RECEIVE_BUF; if (bp) bp->mchain = 0; if ((status=scs_send_msg(csb)) != RET_SUCCESS) printf("scsnet: send nack failed, status = %d\n", status); return; } else if (msg->cmd == SCSNET_BCMD_ACK || msg->cmd == SCSNET_BCMD_NACK) { /* * acknowledgement. * free mbuf chain. */ register struct scsnet_cntl *scscp = scsnet_xfers + msg->rspid; #ifdef notdef register struct pte *topte = &scsmemptmap[scscp->xpte]; register caddr_t tova = (caddr_t) scsxtob(scscp->xpte); register int i;#endif if (scscp->state & SCSNET_BDONE) { panic("scsnet: block transfer dup"); } if (scscp->mchain) m_freem(scscp->mchain); scscp->mchain = 0;#ifdef mips /* * unmap buffer for mips only */ if ((status = scs_unmap_buf(&scscp->csb)) != RET_SUCCESS) printf("scsnet: could not unmap xmit buffer, status %x, %x\n", status, scscp);#endif /* * reuse msg buffer for next xmit */ scscp->csb.buf = csb->buf;#ifdef notdef /* * invalidate pte's and buffer cache entries */ for(i=0; i<scscp->clbuf_len; i += NBPG) { *topte++ = zeropte; Tbis(tova); tova += NBPG; }#endif if (scscp->clbuf_t) { KM_FREE(scscp->clbuf_t, KM_DEVBUF); scscp->clbuf_t = 0; } scscp->state = SCSNET_BDONE; /* * Since we have freed up one output buffer we can check * for a pending transmission and send it. */ smp_lock(&scsnetif.if_snd.lk_ifqueue, LK_RETRY); IF_DEQUEUE(&scsnetif.if_snd, m) smp_unlock(&scsnetif.if_snd.lk_ifqueue); if (m == 0) return; scsnet_output(&scsnetif, m->m_next, mtod(m, struct sockaddr *)); m_free(m); /* only free temp header - the rest of the chain will * free up elsewhere. */ return; } else printf("scsnet: received invalid message\n", msg->cmd); }/* * scsnet_add_sys() - add system to list of known systems. First * check to see if inet address is valid. * Inputs: * rmthost - host number of system to add. * sys - netsystem structure that contains connection info. * ASSUME: sys is smp locked. * IPL_SCS * cmsb - contains connid. * Outputs: * updated knownsystems list. * initialized block transfer structures; * Return value: * RET_SUCCESS - ok. * RET_FAILURE - invalid inet address. */intscsnet_add_sys(rmthost, sys, cmsb) register int rmthost; struct _netsystem *sys; CMSB *cmsb;{ register struct scsnet_cntl *scscp; register int firstpte, i; int status; if (scsnetdebug) printf("scsnet_add_sys: rmthost=%d\n", rmthost); /* check validity of inet address */ if (rmthost>=SCSNET_MAXHOSTS || rmthost<0) { printf("scs_net: can not add invalid host %d\n", rmthost); return(RET_FAILURE); } smp_lock(&lk_scsnetknownsys, LK_RETRY); if (knownsystems[rmthost] != SCSNET_NO_SYS) if (rmthost == scsnet_lhost) { /* we already have connection info for the localhost */ sys->status = SCSNET_CONN_CLOSED; sys->retries = 0; Move_scaaddr( scsnet_nosysid, sys->sys_info.sysid) smp_unlock(&lk_scsnetknownsys); return(RET_SUCCESS); } else { mprintf("scsnet: conn already exists to %d, state = %x\n", rmthost, knownsystems[rmthost]->status); smp_unlock(&lk_scsnetknownsys); return(RET_FAILURE); } Insert_entry( sys->flink, netsys_head ); /* initialize block transfer buffers */ scscp = scsnet_xfers + rmthost*SCSNET_XFERS; firstpte = rmthost*SCSNET_XFERS*(SCSNET_XFER_SIZ+1); /* +1 for offset */ for (i=0; i<SCSNET_XFERS; i++, scscp++) { scscp->xindex = i; scscp->xpte = firstpte + i*(SCSNET_XFER_SIZ+1); scscp->bufhdr.b_un.b_addr = (char *)scsxtob(scscp->xpte); scscp->bufhdr.b_bcount = (SCSNET_XFER_SIZ+1) * NBPG; scscp->bufhdr.b_flags = 0; scscp->csb.Sbh = &scscp->bufhdr; scscp->netsys = sys; Move_connid( cmsb->connid, scscp->csb.connid )#ifdef vax if ((status = scs_map_buf(&scscp->csb)) != RET_SUCCESS) { printf("scsnet: could not map vax xmit buffer, status %x\n", status); knownsystems[rmthost] = SCSNET_NO_SYS; smp_unlock(&lk_scsnetknownsys); return(RET_FAILURE); }#endif scscp->state = SCSNET_BDONE; /* * allocate a msg buffer and save it for the acknowledgement * We may want to preallocate our buffers to save time */ if ((status = scs_alloc_msg(&scscp->csb)) != RET_SUCCESS) { printf("scsnet add: no free seq msgs for host= %d\n", rmthost); knownsystems[rmthost] = SCSNET_NO_SYS; smp_unlock(&lk_scsnetknownsys); return(RET_FAILURE); } } Move_scaaddr( cmsb->rport_addr, sys->msb.rport_addr ) sys->msb.lport_name = cmsb->lport_name; Move_name( SYSAP_NET, sys->msb.Lproc_name ) Move_scaaddr( cmsb->sysid, sys->sys_info.sysid) sys->connid = cmsb->connid; sys->rmt_index = rmthost; sys->status = SCSNET_CONN_OPEN; knownsystems[rmthost] = sys; smp_unlock(&lk_scsnetknownsys); return(RET_SUCCESS);}/* * scsnet_rem_sys: remove system from known system data base and deallocate * any resources reserved for communication with that system * * Inputs: * sys - for system identication. * ASSUME - sys is smp locked. * IPL_SCS * cmsb - for connection identification. * * Outputs: * knownsystems * scsnet_xmits * scsnet_recvs * * Return Value: * RET_FAILURE - invalid system id * RET_SUCCESS * */scsnet_rem_sys(sys, cmsb) register struct _netsystem *sys; register CMSB *cmsb;{ register int rmthost = sys->rmt_index; register struct scsnet_cntl *scscp; register int firstpte, i; int status; if (scsnetdebug) printf("scsnet_rem_sys: rmthost=%d, status=%d\n", rmthost, sys->status); if (sys->status != SCSNET_CONN_OPEN) { sys->status = SCSNET_CONN_CLOSED; sys->retries = 0; sys->rmt_index = SCSNET_NO_INDEX; Move_scaaddr( scsnet_nosysid, sys->sys_info.sysid) return(RET_SUCCESS); } /* * check validity of inet address */ if (rmthost>=SCSNET_MAXHOSTS || rmthost<0) { printf("scsnet_rem_sys: invalid host %d\n", rmthost); return(RET_FAILURE); } smp_lock(&lk_scsnetknownsys, LK_RETRY); Remove_entry( sys->flink); knownsystems[rmthost] = SCSNET_NO_SYS; /* * unmap all xmit blocks dedicated to remote host */ scscp = scsnet_xfers + rmthost*SCSNET_XFERS; for (i=0; i<SCSNET_XFERS; i++, scscp++) { if (scscp->state&SCSNET_BDONE) if ((status=scs_dealloc_msg(&scscp->csb)) != RET_SUCCESS) printf("scsnet: dealloc0 failed, status = %x\n", status);#ifdef vax if ((status = scs_unmap_buf(&scscp->csb)) != RET_SUCCESS) printf("scsnet: could not unmap xmit buffer, status %x, %x\n", status, scscp);#endif if (scscp->clbuf_t) KM_FREE(scscp->clbuf_t, KM_DEVBUF); if (scscp->mchain) { m_freem(scscp->mchain); scscp->mchain = 0; } scscp->clbuf_t = 0; scscp->state = SCSNET_BDONE; scscp->timer = 0; } /* * look for block transfer requests that were in progress and * clean them up. * Note the aux/Aux field of the CMSB and the CSB respectively * contain the address of the netsystem structure dedicated to * a connection. */ for (scscp=scsnet_recvs; scscp < &scsnet_recvs[SCSNET_RECVS]; scscp++){ if ((scscp->state&SCSNET_BDONE)==0 && (cmsb->aux == scscp->csb.Aux) ) { /* * The assumption is made that a disconnect is not * sent while a block transfer is in progress. * The only way to get here is with a path failure. */ if (scsnetdebug) printf("scsnet: unmapping recv buffer\n"); if ((status = scs_unmap_buf(&scscp->csb)) != RET_SUCCESS) printf("scsnet: could not unmap recv buffer, status %x, %x\n", status, scscp); scscp->state = SCSNET_BDONE; scscp->timer = 0; scscp->csb.Aux = 0; if (scscp->mchain) { m_freem(scscp->mchain); scscp->mchain = 0; } if ((status=scs_dealloc_msg(&scscp->csb)) != RET_SUCCESS) printf("scsnet: dealloc2 failed, status = %x\n", status); } } sys->status = SCSNET_CONN_CLOSED; sys->retries = 0; Move_scaaddr( scsnet_nosysid, sys->sys_info.sysid) smp_unlock(&lk_scsnetknownsys); return(RET_SUCCESS);}/* scsnet_connect - start a connection to a remote node. * * Inputs: * netsystem - system status information. * ASSUME: netsystem is smp locked. * scs_inet_addr - internet address of local host * scsnetif - network interface information * isb - ISB * Outputs: * netsystem - connection status * Return Values: * RET_SUCCESS * RET_FAILURE - scs connect failed */scsnet_connect(netsystem, isb)struct _netsystem *netsystem;ISB *isb;{ register struct ifaddr *ifa; struct ifnet *ifp = &scsnetif; extern struct in_addr scs_inet_addr; SIB *sib = &netsystem->sys_info; int error; int ipl; CMSB cmsb; struct scsnet_conn_data *scd = (struct scsnet_conn_data *)cmsb.conn_data; ipl = Splscs(); if (scs_info_system( isb, sib ) == RET_NOSYSTEM){ printf("scsnet connect - no systems\n"); (void)splx( ipl ); return(RET_FAILURE); } /* check for correct type */ if (U_long(*"U-32") != sib->swtype) { (void)splx( ipl ); return(RET_FAILURE); } bzero((caddr_t)&cmsb, sizeof(CMSB)); Move_scaaddr( isb->sysid, cmsb.sysid ) cmsb.control = scsnet_control; bcopy (SYSAP_NET, cmsb.lproc_name, NAME_SIZE); bcopy (SYSAP_NET, cmsb.rproc_name, NAME_SIZE); cmsb.dg_event = scsnet_dgevent; cmsb.msg_event = scsnet_msgevent; cmsb.init_rec_credit = 5; cmsb.init_dg_credit = 5; cmsb.min_snd_credit = 5; Zero_scaaddr( cmsb.rport_addr ) Move_scaaddr( sib->sysid, cmsb.sysid ) cmsb.aux = (u_char *)netsystem; /* * send our internet address to the remote site * so it can be used later on to determine correct connection */ scd->rmt_inaddr = scs_inet_addr; scd->version = SCSNET_VERSION_ID; if ((error=scs_connect(&cmsb))!=RET_SUCCESS) { if (scsnetdebug) printf("scsnet_connect: failed to sysid: %x %x %x, error= %x\n", Scaaddr_hi( cmsb.sysid ), Scaaddr_mid( cmsb.sysid ), Scaaddr_low( cmsb.sysid ), error); (void)splx( ipl ); return(RET_FAILURE); } netsystem->retries = 0; netsystem->status = SCSNET_CONN_SENT; netsystem->rmt_index = SCSNET_NO_INDEX; (void)splx( ipl ); if (scsnetdebug) printf("scsnet_connect: connecting to :: %x,%x,%x\n", Scaaddr_hi( cmsb.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -