fore_buffer.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 773 行 · 第 1/2 页

C
773
字号
				cp, BUF1_SM_SIZE, BUF_DATA_ALIGN, 0);			if (bdp->bsd_buffer == NULL) {				/*				 * Unable to assign dma address - free up				 * this descriptor's buffer				 */				fup->fu_stats->st_drv.drv_bf_segdma++;				KB_FREEALL(m);				break;			}			/*			 * All set, so queue buffer (handle)			 */			ENQUEUE(bhp, Buf_handle, bh_qelem, fup->fu_buf1s_bq);		}		/*		 * If we we're not able to fill all the descriptors for		 * an entry, free up what's been partially built		 */		if (i != BUF1_SM_ENTSIZE) {			/*			 * Clean up each used descriptor			 */			for (bdp = hbp->hbq_descr; i; i--, bdp++) {				bhp = bdp->bsd_handle;				DEQUEUE(bhp, Buf_handle, bh_qelem, 					fup->fu_buf1s_bq);				m = (KBuffer *)					((caddr_t)bhp - BUF1_SM_HOFF);				KB_FREEALL(m);			}			break;		}		/*		 * Finally, we've got an entry ready for the CP.		 * So claim the host queue entry and setup the CP-resident		 * queue entry.  The CP will (potentially) grab the supplied		 * buffers when the descriptor pointer is set.		 */		fup->fu_buf1s_tail = hbp->hbq_next;		(*hbp->hbq_status) = QSTAT_PENDING;		cqp = hbp->hbq_cpelem;		cqp->cq_descr = (CP_dma) CP_WRITE((u_long)hbp->hbq_descr_dma);		/*		 * Update counters, etc for supplied buffers		 */		fup->fu_buf1s_cnt += BUF1_SM_ENTSIZE;		nbuf -= BUF1_SM_ENTSIZE;	}	return;}/* * Supply Strategy 1 Large Buffers to CP * * May be called in interrupt state. * Must be called with interrupts locked out. * * Arguments: *	fup		pointer to device unit structure * * Returns: *	none */static voidfore_buf_supply_1l(fup)	Fore_unit	*fup;{	H_buf_queue	*hbp;	Buf_queue	*cqp;	Buf_descr	*bdp;	Buf_handle	*bhp;	KBuffer		*m;	int		nvcc, nbuf, i;	/*	 * Figure out how many buffers we should be giving to the CP.	 * We're basing this calculation on the current number of open	 * VCCs thru this device, with certain minimum and maximum values	 * enforced.  This will then allow us to figure out how many more 	 * buffers we need to supply to the CP.  This will be rounded up 	 * to fill a supply queue entry.	 */	nvcc = MAX(fup->fu_open_vcc, BUF_MIN_VCC);	nbuf = nvcc * 4 * RECV_MAX_SEGS;	nbuf = MIN(nbuf, BUF1_LG_CPPOOL);	nbuf -= fup->fu_buf1l_cnt;	nbuf = roundup(nbuf, BUF1_LG_ENTSIZE);	/*	 * OK, now supply the buffers to the CP	 */	while (nbuf > 0) {		/*		 * Acquire a supply queue entry		 */		hbp = fup->fu_buf1l_tail;		if (!((*hbp->hbq_status) & QSTAT_FREE))			break;		bdp = hbp->hbq_descr;		/*		 * Get a buffer for each descriptor in the queue entry		 */		for (i = 0; i < BUF1_LG_ENTSIZE; i++, bdp++) {			caddr_t		cp;			/*			 * Get a cluster buffer			 */			KB_ALLOCEXT(m, BUF1_LG_SIZE, KB_F_NOWAIT, KB_T_DATA);			if (m == 0) {				break;			}			KB_HEADSET(m, BUF1_LG_DOFF);			/*			 * Point to buffer handle structure			 */			bhp = (Buf_handle *)((caddr_t)m + BUF1_LG_HOFF);			bhp->bh_type = BHT_S1_LARGE;			/*			 * Setup buffer descriptor			 */			bdp->bsd_handle = bhp;			KB_DATASTART(m, cp, caddr_t);			bhp->bh_dma = bdp->bsd_buffer = (H_dma) DMA_GET_ADDR(				cp, BUF1_LG_SIZE, BUF_DATA_ALIGN, 0);			if (bdp->bsd_buffer == NULL) {				/*				 * Unable to assign dma address - free up				 * this descriptor's buffer				 */				fup->fu_stats->st_drv.drv_bf_segdma++;				KB_FREEALL(m);				break;			}			/*			 * All set, so queue buffer (handle)			 */			ENQUEUE(bhp, Buf_handle, bh_qelem, fup->fu_buf1l_bq);		}		/*		 * If we we're not able to fill all the descriptors for		 * an entry, free up what's been partially built		 */		if (i != BUF1_LG_ENTSIZE) {			/*			 * Clean up each used descriptor			 */			for (bdp = hbp->hbq_descr; i; i--, bdp++) {				bhp = bdp->bsd_handle;				DEQUEUE(bhp, Buf_handle, bh_qelem, 					fup->fu_buf1l_bq);				m = (KBuffer *)					((caddr_t)bhp - BUF1_LG_HOFF);				KB_FREEALL(m);			}			break;		}		/*		 * Finally, we've got an entry ready for the CP.		 * So claim the host queue entry and setup the CP-resident		 * queue entry.  The CP will (potentially) grab the supplied		 * buffers when the descriptor pointer is set.		 */		fup->fu_buf1l_tail = hbp->hbq_next;		(*hbp->hbq_status) = QSTAT_PENDING;		cqp = hbp->hbq_cpelem;		cqp->cq_descr = (CP_dma) CP_WRITE((u_long)hbp->hbq_descr_dma);		/*		 * Update counters, etc for supplied buffers		 */		fup->fu_buf1l_cnt += BUF1_LG_ENTSIZE;		nbuf -= BUF1_LG_ENTSIZE;	}	return;}/* * Drain Buffer Supply Queues * * This function will free all completed entries at the head of each * buffer supply queue.  Since we consider the CP to "own" the buffers * once we put them on a supply queue and since a completed supply queue  * entry is only telling us that the CP has accepted the buffers that we  * gave to it, there's not much to do here. * * May be called in interrupt state. * Must be called with interrupts locked out. * * Arguments: *	fup		pointer to device unit structure * * Returns: *	none */static voidfore_buf_drain(fup)	Fore_unit	*fup;{	H_buf_queue	*hbp;	/*	 * Drain Strategy 1 Small Queue	 */	/*	 * Process each completed entry	 */	while (*fup->fu_buf1s_head->hbq_status & QSTAT_COMPLETED) {		hbp = fup->fu_buf1s_head;		if (*hbp->hbq_status & QSTAT_ERROR) {			/*			 * XXX - what does this mean???			 */			log(LOG_ERR, "fore_buf_drain: buf1s queue error\n");		}		/*		 * Mark this entry free for use and bump head pointer		 * to the next entry in the queue		 */		*hbp->hbq_status = QSTAT_FREE;		fup->fu_buf1s_head = hbp->hbq_next;	}	/*	 * Drain Strategy 1 Large Queue	 */	/*	 * Process each completed entry	 */	while (*fup->fu_buf1l_head->hbq_status & QSTAT_COMPLETED) {		hbp = fup->fu_buf1l_head;		if (*hbp->hbq_status & QSTAT_ERROR) {			/*			 * XXX - what does this mean???			 */			log(LOG_ERR, "fore_buf_drain: buf1l queue error\n");		}		/*		 * Mark this entry free for use and bump head pointer		 * to the next entry in the queue		 */		*hbp->hbq_status = QSTAT_FREE;		fup->fu_buf1l_head = hbp->hbq_next;	}	return;}/* * Free Buffer Supply Queue Data Structures * * Arguments: *	fup		pointer to device unit structure * * Returns: *	none */voidfore_buf_free(fup)	Fore_unit	*fup;{	Buf_handle	*bhp;	KBuffer		*m;	/*	 * Free any previously supplied and not returned buffers	 */	if (fup->fu_flags & CUF_INITED) {		/*		 * Run through Strategy 1 Small queue		 */		while (bhp = Q_HEAD(fup->fu_buf1s_bq, Buf_handle)) {			caddr_t		cp;			/*			 * Back off to buffer			 */			m = (KBuffer *)((caddr_t)bhp - BUF1_SM_HOFF);			/*			 * Dequeue handle and free buffer			 */			DEQUEUE(bhp, Buf_handle, bh_qelem, fup->fu_buf1s_bq);			KB_DATASTART(m, cp, caddr_t);			DMA_FREE_ADDR(cp, bhp->bh_dma, BUF1_SM_SIZE, 0);			KB_FREEALL(m);		}		/*		 * Run through Strategy 1 Large queue		 */		while (bhp = Q_HEAD(fup->fu_buf1l_bq, Buf_handle)) {			caddr_t		cp;			/*			 * Back off to buffer			 */			m = (KBuffer *)((caddr_t)bhp - BUF1_LG_HOFF);			/*			 * Dequeue handle and free buffer			 */			DEQUEUE(bhp, Buf_handle, bh_qelem, fup->fu_buf1l_bq);			KB_DATASTART(m, cp, caddr_t);			DMA_FREE_ADDR(cp, bhp->bh_dma, BUF1_LG_SIZE, 0);			KB_FREEALL(m);		}	}	/*	 * Free the status words	 */	if (fup->fu_buf1s_stat) {		if (fup->fu_buf1s_statd) {			DMA_FREE_ADDR(fup->fu_buf1s_stat, fup->fu_buf1s_statd,				sizeof(Q_status) *					(BUF1_SM_QUELEN + BUF1_LG_QUELEN),				ATM_DEV_NONCACHE);		}		atm_dev_free((void *)fup->fu_buf1s_stat);		fup->fu_buf1s_stat = NULL;		fup->fu_buf1s_statd = NULL;		fup->fu_buf1l_stat = NULL;		fup->fu_buf1l_statd = NULL;	}	/*	 * Free the transmit descriptors	 */	if (fup->fu_buf1s_desc) {		if (fup->fu_buf1s_descd) {			DMA_FREE_ADDR(fup->fu_buf1s_desc, fup->fu_buf1s_descd,				sizeof(Buf_descr) *					((BUF1_SM_QUELEN * BUF1_SM_ENTSIZE) +					 (BUF1_LG_QUELEN * BUF1_LG_ENTSIZE)),				0);		}		atm_dev_free(fup->fu_buf1s_desc);		fup->fu_buf1s_desc = NULL;		fup->fu_buf1s_descd = NULL;		fup->fu_buf1l_desc = NULL;		fup->fu_buf1l_descd = NULL;	}	return;}

⌨️ 快捷键说明

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