⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_scs.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
			/*			 * if the offset is nonzero then this is a 			 * leading cut mbuf.  We can only offset from the			 * beginning of a chain.  If we encounter a			 * second offset mbuf we have to copy the data			 * to a page aligned buffer and map the new buffer.			 */			if (pgoff) {			    if (msg->off)				break;			    msg->off = pgoff;			} 			/* Turn virtual address into a kernel map index */#define mxtob(x) (((int)x - (int)Sysbase) >> PGSHIFT)		        frompte = &Sysmap[mxtob(dp)];			for (rem = pgoff + m->m_len; rem >= NBPG; rem -= NBPG) {			    *topte++ = *frompte++;			    len -= NBPG;			    Tbis(tova);			    tova += NBPG;		        }			len += pgoff;  /* the above loop has to be adjusted					* for a mbuf that is offset					*/						/* 			 * if there is still something left in this mbuf			 * we can still map it if there is no other data.			 * Otherwise we have to copy the			 * remainder to a buffer.			 */			if (rem)  			    if (m->m_next) {				break;			    } else {			        *topte++ = *frompte++;			        Tbis(tova);				len -= rem;				tova += rem;  				rem = 0; /* dont need to do this I think */			    }			    		    	m = m->m_next;		    } else 			break;		}	        /* 		 * the rest of the data is in small mbufs or is		 * not page aligned. 		 * We grab as much space as needed and copy the 		 * rest of the mbuf chain to it.		 */		if (m)  {		    register int slen = 0;		    caddr_t clbuf_t;		    int alloc_len;		    caddr_t va = tova;		    /*		     * need things page aligned so grag at least a page		     */		    if (len < NBPG)		    	alloc_len =  NBPG;		    else 			alloc_len = len;		    KM_ALLOC(clbuf_t, caddr_t, alloc_len, KM_DEVBUF, KM_NOWAIT);		    if (clbuf_t == 0) {			if (scsnetdebug)	        	    printf("scsnet out: KM_ALLOC failed\n");			if (broadcast)				m_freem(mchain);			scscp->mchain = 0;			smp_unlock(&scs_dst->lk_netsys);			Scsnet_Return_ENOBUFS 		    }		    scscp->clbuf_t = clbuf_t;      /* save to free up later */		    scscp->clbuf_len = alloc_len;  /* save to free up later */		    /*		     *  map out the kmalloc'ed space and copy the remaining		     *	data 		     */		    frompte = &kmempt[btokmemx((struct pte *) clbuf_t)];		    for (i = rbtop(len) ; i > 0; i--) {			    *topte++ = *frompte++;			    Tbis(va);			    va += NBPG;		    }		    if (rem) {		        /*		     	 * take care of remainder from last big mbuf		     	 */#define remoff	(m->m_len - rem)		        bcopy(mtod(m, caddr_t) + remoff, tova, rem);#undef remoff		    	tova += rem;			slen += rem;		    	m = m->m_next;		    }					        		    while (m) {			if ((slen += m->m_len) > len) {			    panic("scsnet: NO ROOM for tail mbuf");			}		        bcopy(mtod(m, caddr_t), tova, m->m_len);		    	tova += m->m_len;		    	m = m->m_next;		    }	        }	        msg->totlen = tova - (caddr_t)scsxtob(scscp->xpte) - msg->off;			    }#ifdef notdef	    tbsync();   /* for multi-processor translation buffer */#endif#ifdef mips	    /*	     * map buffer before we send it. Can not pre-map for mips box	     * because of the pte translation that occurs for the CI	     */	    scscp->bufhdr.b_un.b_addr = (char *)scsxtob(scscp->xpte);	    scscp->bufhdr.b_bcount = msg->totlen + msg->off;	    scscp->bufhdr.b_flags = 0;	    scscp->csb.Sbh = &scscp->bufhdr;	    if ((status = scs_map_buf(&scscp->csb)) != RET_SUCCESS) {			printf("scsnet: could not map transmit buffer, status=%x\n", status);			if (broadcast)				m_freem(mchain);			scscp->mchain = 0;			if (scscp->clbuf_t)				KM_FREE(scscp->clbuf_t, KM_DEVBUF);			smp_unlock(&scs_dst->lk_netsys);			Scsnet_Return_ENOBUFS 	    }#endif	    Move_bhandle(scscp->csb.lbhandle, msg->bhandle);	    /* send message to remote - do not free mbufs till response */	    /* We will need a background timer to check up on things */	    scscp->csb.Disposal = RECEIVE_BUF;  /* for receive ack */	    if ((status=scs_send_msg(&scscp->csb)) != RET_SUCCESS) {		if (scsnetdebug)			printf("scs_net: send failed, %x\n", status);		if (broadcast)			m_freem(mchain);		scscp->mchain = 0;		if (scscp->clbuf_t)			KM_FREE(scscp->clbuf_t, KM_DEVBUF);		smp_unlock(&scs_dst->lk_netsys);		Scsnet_Return_ENOBUFS 	    }	    scscp->state = SCSNET_BSTARTED;	}	else  /* not a block transfer */	{			    notblock = 1;	    csb.connid = scs_dst->connid;	    if ((status=scs_alloc_dg(&csb))!=RET_SUCCESS) {		if (scsnetdebug)	            printf("scsnet: scs_alloc_dg failed, status= %x\n", status);		smp_unlock(&scs_dst->lk_netsys);		Scsnet_Return_ENOBUFS 	    }	    /* copy protocol type and data to scs buffer */	    bcopy(&type, csb.buf, SCSNET_HDR_SIZ);	    off = csb.buf + SCSNET_HDR_SIZ;	    while (m) {		bcopy(mtod(m, caddr_t), off, m->m_len);		off += m->m_len;		m = m->m_next;	    }	    if ((csb.size = off - csb.buf) > scs_dg_size) 		printf("scsnet data gram too large: %d\n", csb.size);	    csb.Disposal = DEALLOC_BUF;	    /* send data to remote host */	    if ((status = scs_send_dg(&csb)) != RET_SUCCESS)	        printf("scsnet: send_dg failed, status= %d\n",status);	}	ifp->if_opackets++;	smp_unlock(&scs_dst->lk_netsys);	(void)splx( ipl );	/* start timer to ensure that we eventually free mbuf chain */	/* moved here to improve smp performance */	if (notblock == 0 && !scsnet_timer++)		timeout(scsnet_watch, 0, scsnet_timeo);	if (broadcast) { 		goto broadcastloop;	}	/* 	 * do not free up mbuf chain if block transfer.  We will free 	 * the mbuf chain when we receive an acknowledgment	 */	if (notblock)		m_freem(m0);#ifdef  notdef	/* 	 * Check for more to send	 */    	IF_DEQUEUE(&scsnetif.if_snd, m)    	if (m == 0) 	      return(0);	 /* m contains temp info - the rest of the chain will	  * free up later.	  */ 	m0 = m->m_next;	/* initialize variables and try to send */	notblock = broadcast = 0; 	dst = mtod(m, stuct sockaddr *);	m = m0;	m_free(m);	goto start;#endif	return(0);}/* * Process an ioctl request. */scsnet_ioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	int error = 0;	switch (cmd) {	case SIOCSIFADDR:		/*		 * Everything else is done at a higher level.		 */		if (! (ifp->if_flags & IFF_UP) ) /* should use diff flag? */			if (scsnet_init())				return (EIO);			ifp->if_flags |= IFF_UP;					break;	default:		error = EINVAL;	}	return (error);}/* * scsnet_dgevent() - datagrams received here.  copy data into mbufs *	and insert them into appropriate queue (INET only for now) */voidscsnet_dgevent(csb)register CSB *csb;{	register struct ifnet *ifp = &scsnetif;	register u_long totlen = csb->size;  /* length of packet */	register u_char *cp = csb->buf;      /* pointer to packet data */	register struct mbuf **mp; 	     /* mp is the next spot in the				              * chain to assign mbuf 				     	      */	struct mbuf *top = 0;	     /* beginning of new mbuf chain */	int ret;        if (!(ifp->if_flags & IFF_UP))		goto requeue;	/* copy data from scs buffer to mbuf chain */	mp = &top;	while (totlen) {		register struct mbuf *m;		MGET(m, M_DONTWAIT, MT_DATA);		if (m==0) {			if (scsnetdebug)			    printf("scsnet_dgevent: could not copy csb to mbuf \n");			if (top)			    m_freem(top);			goto requeue;		}		if (totlen >= CLBYTES) {			struct mbuf *p;			MCLGET(m, p);			if (p==0) 				m->m_len = MIN(MLEN, totlen);			else 				m->m_len = CLBYTES;		} else 			m->m_len = MIN(MLEN, totlen);		bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len);		cp += m->m_len;		*mp = m;		mp = &m->m_next;		totlen -= m->m_len;	}	/* enqueue packet on protocol queue */	ifp->if_ipackets++;	Scsnet_enqueue(top)	/* requeue buffer for reception */requeue:	csb->Nbufs =0; 	if ((ret = scs_queue_dgs (csb)) != RET_SUCCESS) 		printf("scsnet_dgevent requeue failed 2, ret = %d\n", ret);}/* * scsnet_msgevent * Receive a message.  The message is either a request for starting a  * block transfer or an acknowledgment to the request. * If we are receiving an ack then we want to deallocate our message buffer. * If we are sending an ack we want to return the buffer to the receive  * pool to prepare for new requests. */struct pte zeropte = {0,0,0,0,0,0,0,0};voidscsnet_msgevent(csb)	register CSB *csb;{	register struct scsnet_msg *msg = (struct scsnet_msg *)csb->buf;	register int totlen = msg->totlen;	register struct scsnet_cntl *bp = 0;	register struct mbuf *m = 0;	register int recvx;	caddr_t recvbuf;	int status;		if (msg->cmd == SCSNET_BCMD_REQUEST) {	    /* start block transfer from the remote host 	     * First gather up required resources. 	     * If can not get resources send back a negative ack.	     */		    register int clen = csb->size - Scsnet_msg_hdr_siz;	    register struct mbuf *p;	    register struct ifnet *ifp = &scsnetif;	    void scsnet_freem();	    struct mbuf *mclgetx();            if (!(ifp->if_flags & IFF_UP))		goto bad;	    MGET(m, M_DONTWAIT, MT_DATA)	    if (m==0) 		goto bad;	    if (clen > MLEN) {	    	MCLGET(m,p)	    	if (p==0) 		    goto bad;	    }	    	    m->m_len = clen;	    /*	     * copy protocol header into mbuf 	     */	    bcopy(msg->proto_hdr, mtod(m, caddr_t), m->m_len);	     /*	      * get a free transfer control block	      */	    smp_lock(&lk_scsnetrecvs, LK_RETRY);	    for (recvx=0, bp=scsnet_recvs; bp < &scsnet_recvs[SCSNET_RECVS];		bp++,recvx++)			if (bp->state & SCSNET_BDONE)				break;	    if (recvx >= SCSNET_RECVS) {		if (scsnetdebug)			printf("scsnet: could not allocate recvbuf\n");	        smp_unlock(&lk_scsnetrecvs);		goto bad;	    }	    bp->state = SCSNET_BSTARTED;		    smp_unlock(&lk_scsnetrecvs);	    KM_ALLOC(recvbuf, caddr_t, totlen, KM_DEVBUF, KM_NOWAIT);	    if (recvbuf == 0) {		if (scsnetdebug)			printf("scsnet: could not kmalloc recvbuf\n");	        bp->state = SCSNET_BDONE;			goto bad;	    }	    m->m_next = mclgetx(scsnet_freem, (int)recvbuf, recvbuf, 			totlen, M_DONTWAIT);	    if (m->m_next == 0) {		KM_FREE(recvbuf, KM_DEVBUF);		if (scsnetdebug)			printf("scsnet: could not allocate recv cluster\n");	        bp->state = SCSNET_BDONE;			goto bad;	    }			    /*	     * set up buffer and map it 	     */	    bp->bufhdr.b_un.b_addr = recvbuf;	    bp->bufhdr.b_flags = 0;	    csb->Sbh = &bp->bufhdr;	    bp->bufhdr.b_bcount = msg->totlen;	    csb->Blockid = recvx;  /* will identify us during BLOCK_DONE */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -