Exemple #1
0
static mblk_t *get_as_yuvmsg(MSFilter *f, DecData *s, AVFrame *orig){
	AVCodecContext *ctx=&s->av_context;

	if (s->outbuf.w!=ctx->width || s->outbuf.h!=ctx->height){
		if (s->sws_ctx!=NULL){
			sws_freeContext(s->sws_ctx);
			s->sws_ctx=NULL;
			freemsg(s->yuv_msg);
			s->yuv_msg=NULL;
		}
		ms_message("Getting yuv picture of %ix%i",ctx->width,ctx->height);
		s->yuv_msg=ms_yuv_buf_alloc(&s->outbuf,ctx->width,ctx->height);
		s->outbuf.w=ctx->width;
		s->outbuf.h=ctx->height;
		s->sws_ctx=sws_getContext(ctx->width,ctx->height,ctx->pix_fmt,
			ctx->width,ctx->height,PIX_FMT_YUV420P,SWS_FAST_BILINEAR,
                	NULL, NULL, NULL);
		ms_filter_notify_no_arg(f,MS_FILTER_OUTPUT_FMT_CHANGED);
	}
#if LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(0,9,0)
	if (sws_scale(s->sws_ctx,(const uint8_t * const *)orig->data,orig->linesize, 0,
					ctx->height, s->outbuf.planes, s->outbuf.strides)<0){
#else
	if (sws_scale(s->sws_ctx,(uint8_t **)orig->data,orig->linesize, 0,
					ctx->height, s->outbuf.planes, s->outbuf.strides)<0){
#endif
		ms_error("%s: error in sws_scale().",f->desc->name);
	}
	return dupmsg(s->yuv_msg);
}

static void update_sps(DecData *d, mblk_t *sps){
	if (d->sps)
		freemsg(d->sps);
	d->sps=dupb(sps);
}

static void update_pps(DecData *d, mblk_t *pps){
	if (d->pps)
		freemsg(d->pps);
	if (pps) d->pps=dupb(pps);
	else d->pps=NULL;
}


static bool_t check_sps_change(DecData *d, mblk_t *sps){
	bool_t ret=FALSE;
	if (d->sps){
		ret=(msgdsize(sps)!=msgdsize(d->sps)) || (memcmp(d->sps->b_rptr,sps->b_rptr,msgdsize(sps))!=0);
		if (ret) {
			ms_message("SPS changed ! %i,%i",(int)msgdsize(sps),(int)msgdsize(d->sps));
			update_sps(d,sps);
			update_pps(d,NULL);
		}
	} else {
		ms_message("Receiving first SPS");
		update_sps(d,sps);
	}
	return ret;
}
Exemple #2
0
/*
 * Return a chain of mblks representing the Multidata packet.
 */
mblk_t *
mmd_transform_link(pdesc_t *pd)
{
	multidata_t *mmd;
	pdescinfo_t *pdi;
	mblk_t *nmp = NULL;

	ASSERT(pd != NULL);
	ASSERT(pd->pd_magic == PDESC_MAGIC);

	mmd = pd->pd_slab->pds_mmd;
	ASSERT(mmd->mmd_magic == MULTIDATA_MAGIC);

	/* entry has been removed */
	if (pd->pd_flags & PDESC_REM_DEFER)
		return (NULL);

	pdi = &(pd->pd_pdi);

	/* duplicate header buffer */
	if ((pdi->flags & PDESC_HBUF_REF)) {
		if ((nmp = dupb(mmd->mmd_hbuf)) == NULL)
			return (NULL);
		nmp->b_rptr = pdi->hdr_rptr;
		nmp->b_wptr = pdi->hdr_wptr;
	}

	/* duplicate payload buffer(s) */
	if (pdi->flags & PDESC_PBUF_REF) {
		int i;
		mblk_t *mp;
		struct pld_ary_s *pa = &pdi->pld_ary[0];

		mutex_enter(&mmd->mmd_pd_slab_lock);
		for (i = 0; i < pdi->pld_cnt; i++, pa++) {
			ASSERT(mmd->mmd_pbuf[pa->pld_pbuf_idx] != NULL);

			/* skip empty ones */
			if (PDESC_PLD_SPAN_SIZE(pdi, i) == 0)
				continue;

			mp = dupb(mmd->mmd_pbuf[pa->pld_pbuf_idx]);
			if (mp == NULL) {
				if (nmp != NULL)
					freemsg(nmp);
				mutex_exit(&mmd->mmd_pd_slab_lock);
				return (NULL);
			}
			mp->b_rptr = pa->pld_rptr;
			mp->b_wptr = pa->pld_wptr;
			if (nmp == NULL)
				nmp = mp;
			else
				linkb(nmp, mp);
		}
		mutex_exit(&mmd->mmd_pd_slab_lock);
	}

	return (nmp);
}
Exemple #3
0
/* duplicates a complex mblk_t */
mblk_t	*dupmsg(mblk_t* m)
{
	mblk_t *newm=NULL,*mp,*prev;
	prev=newm=dupb(m);
	m=m->b_cont;
	while (m!=NULL){
		mp=dupb(m);
		prev->b_cont=mp;
		prev=mp;
		m=m->b_cont;
	}
	return newm;
}
Exemple #4
0
mblk_t *
nl7c_http_persist(struct sonode *so)
{
	uint64_t	flags = so->so_nl7c_flags & NL7C_SCHEMEPRIV;
	mblk_t		*mp;

	if (flags & HTTP_CONN_CL)
		mp = dupb(http_conn_cl);
	else if (flags & HTTP_CONN_KA)
		mp = dupb(http_conn_ka);
	else
		mp = NULL;
	return (mp);
}
/*
 * Given a request with it's body already composed,
 * rewind to the start and fill in the SMB header.
 * This is called after the request is enqueued,
 * so we have the final MID, seq num. etc.
 */
void
smb_rq_fillhdr(struct smb_rq *rqp)
{
	struct mbchain mbtmp, *mbp = &mbtmp;
	mblk_t *m;

	/*
	 * Fill in the SMB header using a dup of the first mblk,
	 * which points at the same data but has its own wptr,
	 * so we can rewind without trashing the message.
	 */
	m = dupb(rqp->sr_rq.mb_top);
	m->b_wptr = m->b_rptr;	/* rewind */
	mb_initm(mbp, m);

	mb_put_mem(mbp, SMB_SIGNATURE, 4, MB_MSYSTEM);
	mb_put_uint8(mbp, rqp->sr_cmd);
	mb_put_uint32le(mbp, 0);	/* status */
	mb_put_uint8(mbp, rqp->sr_rqflags);
	mb_put_uint16le(mbp, rqp->sr_rqflags2);
	mb_put_uint16le(mbp, 0);	/* pid-high */
	mb_put_mem(mbp, NULL, 8, MB_MZERO);	/* MAC sig. (later) */
	mb_put_uint16le(mbp, 0);	/* reserved */
	mb_put_uint16le(mbp, rqp->sr_rqtid);
	mb_put_uint16le(mbp, rqp->sr_pid);
	mb_put_uint16le(mbp, rqp->sr_rquid);
	mb_put_uint16le(mbp, rqp->sr_mid);

	/* This will free the mblk from dupb. */
	mb_done(mbp);
}
Exemple #6
0
void split_and_queue(queue_t *q, int maxrqsz, mblk_t *mp, rtp_header_t *rtp, int *discarded)
{
	mblk_t *mdata,*tmp;
	int header_size;
	*discarded=0;
	header_size=RTP_FIXED_HEADER_SIZE+ (4*rtp->cc);
	if ((mp->b_wptr - mp->b_rptr)==header_size){
		ortp_debug("Rtp packet contains no data.");
		(*discarded)++;
		freemsg(mp);
		return;
	}
	/* creates a new mblk_t to be linked with the rtp header*/
	mdata=dupb(mp);
	
	mp->b_wptr=mp->b_rptr+header_size;
	mdata->b_rptr+=header_size;
	/* link proto with data */
	mp->b_cont=mdata;
	/* and then add the packet to the queue */
	
	rtp_putq(q,mp);
	/* make some checks: q size must not exceed RtpStream::max_rq_size */
	while (q->q_mcount > maxrqsz)
	{
		/* remove the oldest mblk_t */
		tmp=getq(q);
		if (mp!=NULL)
		{
			ortp_debug("rtp_putq: Queue is full. Discarding message with ts=%i",((rtp_header_t*)mp->b_rptr)->timestamp);
			freemsg(tmp);
			(*discarded)++;
		}
	}
}
static void dec_process_frame(MSFilter *f, DecState *s, ogg_packet *op){
	yuv_buffer yuv;
	if (theora_decode_packetin(&s->tstate,op)==0){
		if (theora_decode_YUVout(&s->tstate,&yuv)==0){
			mblk_t *om;
			int i;
			int ylen=yuv.y_width*yuv.y_height;
			int uvlen=yuv.uv_width*yuv.uv_height;
			ms_debug("Got yuv buffer from theora decoder");
			if (s->yuv==NULL){
				int len=(ylen)+(2*uvlen);
				s->yuv=allocb(len,0);
			}
			om=dupb(s->yuv);
			for(i=0;i<yuv.y_height;++i){
				memcpy(om->b_wptr,yuv.y+yuv.y_stride*i,yuv.y_width);
				om->b_wptr+=yuv.y_width;
			}
			for(i=0;i<yuv.uv_height;++i){
				memcpy(om->b_wptr,yuv.u+yuv.uv_stride*i,yuv.uv_width);
				om->b_wptr+=yuv.uv_width;
			}
			for(i=0;i<yuv.uv_height;++i){
				memcpy(om->b_wptr,yuv.v+yuv.uv_stride*i,yuv.uv_width);
				om->b_wptr+=yuv.uv_width;
			}
			ms_queue_put(f->outputs[0],om);
		}
	}else{
		ms_warning("theora decoding error");
	}
}
Exemple #8
0
bool_t
xdrmblk_getmblk(XDR *xdrs, mblk_t **mm, uint_t *lenp)
{
	mblk_t *m, *nextm;
	struct xdrmblk_params *p;
	int len;
	uint32_t llen;

	if (!xdrmblk_getint32(xdrs, (int32_t *)&llen))
		return (FALSE);

	*lenp = llen;
	/* LINTED pointer alignment */
	m = (mblk_t *)xdrs->x_base;
	*mm = m;

	/*
	 * Walk the mblk chain until we get to the end or we've gathered
	 * enough data.
	 */
	len = 0;
	llen = roundup(llen, BYTES_PER_XDR_UNIT);
	while (m != NULL && len + (int)MBLKL(m) <= llen) {
		len += (int)MBLKL(m);
		m = m->b_cont;
	}
	if (len < llen) {
		if (m == NULL) {
			return (FALSE);
		} else {
			int tail_bytes = llen - len;

			/*
			 * Split the mblk with the last chunk of data and
			 * insert it into the chain.  The new mblk goes
			 * after the existing one so that it will get freed
			 * properly.
			 */
			nextm = dupb(m);
			if (nextm == NULL)
				return (FALSE);
			nextm->b_cont = m->b_cont;
			m->b_cont = nextm;
			m->b_wptr = m->b_rptr + tail_bytes;
			nextm->b_rptr += tail_bytes;
			ASSERT(nextm->b_rptr != nextm->b_wptr);

			m = nextm;	/* for x_base */
		}
	}
	xdrs->x_base = (caddr_t)m;
	xdrs->x_handy = m != NULL ? MBLKL(m) : 0;

	p = (struct xdrmblk_params *)xdrs->x_private;
	p->apos += p->rpos + llen;
	p->rpos = 0;

	return (TRUE);
}
Exemple #9
0
static void mire_process(MSFilter *f){
	MireData *d=(MireData*)f->data;
	float elapsed=(float)(f->ticker->time-d->starttime);
	if ((elapsed*d->fps/1000.0)>d->index){
		mire_draw(d);
		ms_queue_put(f->outputs[0],dupb(d->pic));
		d->index++;
	}
}
Exemple #10
0
static void vp8_fragment_and_send(MSFilter *f,EncState *s,mblk_t *frame, uint32_t timestamp, const vpx_codec_cx_pkt_t *pkt, bool_t lastPartition){
	uint8_t *rptr;
	mblk_t *packet=NULL;
	mblk_t* vp8_payload_desc = NULL;
	int len;

#if 0
	if ((pkt->data.frame.flags & VPX_FRAME_IS_KEY) == 0) {
		ms_debug("P-FRAME: %u\n", pkt->data.frame.sz);
	} else {
		ms_debug("I-FRAME: %u\n", pkt->data.frame.sz);
	}
#endif

	for (rptr=frame->b_rptr;rptr<frame->b_wptr;){
		vp8_payload_desc = allocb(1, 0);
		vp8_payload_desc->b_wptr=vp8_payload_desc->b_rptr+1;

		len=MIN(s->mtu,(frame->b_wptr-rptr));
		packet=dupb(frame);
		packet->b_rptr=rptr;
		packet->b_wptr=rptr+len;
		mblk_set_timestamp_info(packet,timestamp);
		mblk_set_timestamp_info(vp8_payload_desc,timestamp);

		/* insert 1 byte vp8 payload descriptor */
		(*vp8_payload_desc->b_rptr) = 0;
		/* X (extended) field, 0 */
		(*vp8_payload_desc->b_rptr) &= ~VP8_PAYLOAD_DESC_X_MASK;
		/* RSV field, always 0 */
		(*vp8_payload_desc->b_rptr) &= ~VP8_PAYLOAD_DESC_RSV_MASK;
		/* N : set to 1 if non reference frame */
		if ((pkt->data.frame.flags & VPX_FRAME_IS_KEY) == 0)
			(*vp8_payload_desc->b_rptr) |= VP8_PAYLOAD_DESC_N_MASK;
		/* S : partition start */
		if (rptr == frame->b_rptr) {
			(*vp8_payload_desc->b_rptr) |= VP8_PAYLOAD_DESC_S_MASK;
		}
		/* PartID : partition id */
		#ifdef FRAGMENT_ON_PARTITIONS
		(*vp8_payload_desc->b_rptr) |= (pkt->data.frame.partition_id & VP8_PAYLOAD_DESC_PARTID_MASK);
		#endif

		vp8_payload_desc->b_cont = packet;

		ms_queue_put(f->outputs[0], vp8_payload_desc);
		rptr+=len;
	}

	freeb(frame);

	/*set marker bit on last packet*/
	if (lastPartition) {
		mblk_set_marker_info(packet,TRUE);
		mblk_set_marker_info(vp8_payload_desc,TRUE);
	}
}
Exemple #11
0
/*
 * Return duplicate message block(s) of the associated buffer(s).
 */
int
mmd_dupbufs(multidata_t *mmd, mblk_t **hmp, mblk_t **pmp)
{
	ASSERT(mmd != NULL);
	ASSERT(mmd->mmd_magic == MULTIDATA_MAGIC);

	if (hmp != NULL) {
		*hmp = NULL;
		if (mmd->mmd_hbuf != NULL &&
		    (*hmp = dupb(mmd->mmd_hbuf)) == NULL)
			return (-1);
	}

	if (pmp != NULL) {
		int i;
		mblk_t *mp;

		mutex_enter(&mmd->mmd_pd_slab_lock);
		*pmp = NULL;
		for (i = 0; i < mmd->mmd_pbuf_cnt; i++) {
			ASSERT(mmd->mmd_pbuf[i] != NULL);
			mp = dupb(mmd->mmd_pbuf[i]);
			if (mp == NULL) {
				if (hmp != NULL && *hmp != NULL)
					freeb(*hmp);
				if (*pmp != NULL)
					freemsg(*pmp);
				mutex_exit(&mmd->mmd_pd_slab_lock);
				return (-1);
			}
			if (*pmp == NULL)
				*pmp = mp;
			else
				linkb(*pmp, mp);
		}
		mutex_exit(&mmd->mmd_pd_slab_lock);
	}

	return (0);
}
Exemple #12
0
void static_image_process(MSFilter *f){
	SIData *d=(SIData*)f->data;
	/*output a frame every second*/
	if ((f->ticker->time - d->lasttime>1000) || d->lasttime==0){
		if (d->pic) {
			mblk_t *o=dupb(d->pic);
			/*prevent mirroring at the output*/
			mblk_set_precious_flag(o,1);
			ms_queue_put(f->outputs[0],o);
		}
		d->lasttime=f->ticker->time;
	}
}
Exemple #13
0
static void msv4l2_process(MSFilter *f){
	V4l2State *s=(V4l2State*)f->data;
#ifdef V4L2_THREADED
	uint32_t timestamp;
	int cur_frame;
	if (s->frame_count==-1){
		s->start_time=f->ticker->time;
		s->frame_count=0;
	}
	cur_frame=((f->ticker->time-s->start_time)*s->fps/1000.0);
	
	if (cur_frame>=s->frame_count){
		mblk_t *om=NULL;
		ms_mutex_lock(&s->mutex);
		/*keep the most recent frame if several frames have been captured */
		if (s->fd!=-1){
			om=getq(&s->rq);
		}
		ms_mutex_unlock(&s->mutex);
		if (om!=NULL){
			timestamp=f->ticker->time*90;/* rtp uses a 90000 Hz clockrate for video*/
			mblk_set_timestamp_info(om,timestamp);
			mblk_set_marker_info(om,TRUE);
			ms_queue_put(f->outputs[0],om);
			/*ms_message("picture sent");*/
			s->frame_count++;
		}
	}else{
			flushq(&s->rq,0);
	}
#else
	uint32_t elapsed;
	
	if (s->fd!=-1){
		/*see it is necessary to output a frame:*/
		elapsed=f->ticker->time-s->start_time;
		if (((float)elapsed*s->fps/1000.0)>s->frame_count){
			mblk_t *m;
			m=v4lv2_grab_image(s);
			if (m){
				mblk_t *om=dupb(m);
				mblk_set_marker_info(om,(s->pix_fmt==MS_MJPEG));
				ms_queue_put(f->outputs[0],om);
				s->frame_count++;
			}
		}
	}
#endif
}
Exemple #14
0
static void *msv4l2_thread(void *ptr){
	V4l2State *s=(V4l2State*)ptr;
	int err=-1;
	ms_message("msv4l2_thread starting");
	if (s->fd!=-1)
	{
		ms_warning("msv4l2 file descriptor already openned fd:%d",s->fd);
		goto exit;
	}
	if( msv4l2_open(s)!=0){
		ms_warning("msv4l2 could not be openned");
		goto close;
	}
	if (!s->configured && msv4l2_configure(s)!=0){
		ms_warning("msv4l2 could not be configured");		
		goto close;
	}
	if (msv4l2_do_mmap(s)!=0)
	{
		ms_warning("msv4l2 do mmap");
		goto close;
	}
	ms_message("V4L2 video capture started.");
	while(s->thread_run)
	{
		mblk_t *m;
		if (s->fd!=-1){
			mblk_t *m;
			m=v4lv2_grab_image(s);
			if (m){
				mblk_t *om=dupb(m);
				mblk_set_marker_info(om,(s->pix_fmt==MS_MJPEG));
				ms_mutex_lock(&s->mutex);
				putq(&s->rq,om);
				ms_mutex_unlock(&s->mutex);
			}
		}
	}	
	ms_message("thread:%d",s->thread_run);
munmap:	
	msv4l2_do_munmap(s);
close:
	msv4l2_close(s);
exit:
	ms_message("msv4l2_thread exited.");
	s->fd = -1;
	ms_thread_exit(NULL);
}
Exemple #15
0
mblk_t *msgb_allocator_alloc(msgb_allocator_t *a, int size){
	queue_t *q=&a->q;
	mblk_t *m,*found=NULL;

	/*lookup for an unused msgb (data block with ref count ==1)*/
	for(m=qbegin(q);!qend(q,m);m=qnext(q,m)){
		if (m->b_datap->db_ref==1 && m->b_datap->db_lim-m->b_datap->db_base>=size){
			found=m;
			break;
		}
	}
	if (found==NULL){
		found=allocb(size,0);
		putq(q,found);
	}
	return dupb(found);
}
Exemple #16
0
/*process incoming rtp data and output NALUs, whenever possible*/
void rfc3984_unpack(Rfc3984Context *ctx, mblk_t *im, MSQueue *out){
	uint8_t type=nal_header_get_type(im->b_rptr);
	uint8_t *p;
	
	if (im->b_cont) msgpullup(im,-1);

	if (type==TYPE_STAP_A){
		ms_message("Receiving STAP-A");
		/*split into nalus*/
		uint16_t sz;
		uint8_t *buf=(uint8_t*)&sz;
		mblk_t *nal;
		for(p=im->b_rptr+1;p<im->b_wptr;){
			buf[0]=p[0];
			buf[1]=p[1];
			sz=ntohs(sz);
			nal=dupb(im);
			p+=2;
			nal->b_rptr=p;
			p+=sz;
			nal->b_wptr=p;
			if (p>im->b_wptr){
				ms_error("Malformed STAP-A packet");
				freemsg(nal);
				break;
			}
			ms_queue_put(&ctx->q,nal);
		}
		freemsg(im);
	}else if (type==TYPE_FU_A){
		ms_message("Receiving FU-A");
		mblk_t *o=aggregate_fua(ctx,im);
		if (o) ms_queue_put(&ctx->q,o);
	}else{
		/*single nal unit*/
		ms_message("Receiving single NAL");
		ms_queue_put(&ctx->q,im);
	}
	if (mblk_get_marker_info(im)){
		/*end of frame, output everything*/
		while(!ms_queue_empty(&ctx->q)){
			ms_queue_put(out,ms_queue_get(&ctx->q));
		}
	}
}
Exemple #17
0
static void v4l2_process(MSFilter *f){
	V4l2State *s=(V4l2State*)f->data;
	uint32_t elapsed;
	
	if (s->fd!=-1){
		/*see it is necessary to output a frame:*/
		elapsed=f->ticker->time-s->start_time;
		if (((float)elapsed*s->fps/1000.0)>s->frame_count){
			mblk_t *m;
			m=v4lv2_grab_image(s);
			if (m){
				mblk_t *om=dupb(m);
				mblk_set_marker_info(om,(s->pix_fmt==MS_MJPEG));
				ms_queue_put(f->outputs[0],om);
				s->frame_count++;
			}
		}
	}
}
Exemple #18
0
static void frag_nalu_and_send(MSQueue *rtpq, uint32_t ts, mblk_t *nalu, bool_t marker, int maxsize){
	mblk_t *m;
	int payload_max_size=maxsize-2;/*minus FUA header*/
	uint8_t fu_indicator;
	uint8_t type=nal_header_get_type(nalu->b_rptr);
	uint8_t nri=nal_header_get_nri(nalu->b_rptr);
	bool_t start=TRUE;

	nal_header_init(&fu_indicator,nri,TYPE_FU_A);
	while(nalu->b_wptr-nalu->b_rptr>payload_max_size){
		m=dupb(nalu);
		nalu->b_rptr+=payload_max_size;
		m->b_wptr=nalu->b_rptr;
		m=prepend_fu_indicator_and_header(m,fu_indicator,start,FALSE,type);
		send_packet(rtpq,ts,m,FALSE);
		start=FALSE;
	}
	/*send last packet */
	m=prepend_fu_indicator_and_header(nalu,fu_indicator,FALSE,TRUE,type);
	send_packet(rtpq,ts,m,marker);
}
Exemple #19
0
static void packetize_and_send(MSFilter *f, EncState *s, mblk_t *om, uint32_t timestamp, uint8_t tdt){
	mblk_t *packet;
	mblk_t *h;
	int npackets=0;
	static const int ident=0xdede;
	while(om!=NULL){
		if (om->b_wptr-om->b_rptr>=s->mtu){
			packet=dupb(om);
			packet->b_wptr=packet->b_rptr+s->mtu;
			om->b_rptr=packet->b_wptr;
		}else {
			packet=om;
			om=NULL;
		}
		++npackets;
		h=allocb(6,0);
		if (npackets==1){
			if (om==NULL)
				payload_header_set(h->b_wptr,ident,NOT_FRAGMENTED,tdt,1);
			else
				payload_header_set(h->b_wptr,ident,START_FRAGMENT,tdt,1);
		}else{
			if (om==NULL)
				payload_header_set(h->b_wptr,ident,END_FRAGMENT,tdt,1);
			else
				payload_header_set(h->b_wptr,ident,CONT_FRAGMENT,tdt,1);
		}
		h->b_wptr+=4;
		*((uint16_t*)h->b_wptr)=htons(msgdsize(packet));
		h->b_wptr+=2;
		h->b_cont=packet;
		mblk_set_timestamp_info(h,timestamp);
		ms_debug("sending theora frame of size %i",msgdsize(h));
		ms_queue_put(f->outputs[0],h);
	}
}
Exemple #20
0
static void winsnd_write_process(MSFilter *f){
	WinSnd *d=(WinSnd*)f->data;
	mblk_t *m,*old;
	MMRESULT mr;
	int i;
	int discarded=0;
	int possible_size=0;

	if (d->outdev==NULL) {
		ms_queue_flush(f->inputs[0]);
		return;
	}

	while((m=ms_queue_get(f->inputs[0]))!=NULL){
		possible_size = msgdsize(m);
#ifndef DISABLE_SPEEX
		if (d->pst_frame_size==0)
		{
			d->pst_frame_size=possible_size;

			d->pst = speex_preprocess_state_init(d->pst_frame_size/2, d->wfx.nSamplesPerSec);
			if (d->pst!=NULL) {
				float f;
				i=1;
				speex_preprocess_ctl(d->pst, SPEEX_PREPROCESS_SET_VAD, &i);
				i=0;
				speex_preprocess_ctl(d->pst, SPEEX_PREPROCESS_SET_DENOISE, &i);
				i=0;
				speex_preprocess_ctl(d->pst, SPEEX_PREPROCESS_SET_AGC, &i);
				f=8000;
				speex_preprocess_ctl(d->pst, SPEEX_PREPROCESS_SET_AGC_LEVEL, &f);
				i=0;
				speex_preprocess_ctl(d->pst, SPEEX_PREPROCESS_SET_DEREVERB, &i);
			}
		}
#endif

		putq(&d->write_rq,m);
	}

#ifdef AMD_HACK
	/* too many sound card are crappy on windows... */
	d->stat_minimumbuffer=15;
  if (d->wfx.nSamplesPerSec>=32000) /* better results for high rates */
  	d->stat_minimumbuffer=8;
#endif

  if (d->wfx.nSamplesPerSec>=32000) /* better results for high rates */
  {
	  if (d->nbufs_playing+d->write_rq.q_mcount<4)
	  {
		  d->ready=0;
	  }
  }
  else
  {
	  if (d->nbufs_playing+d->write_rq.q_mcount<7)
	  {
		  d->ready=0;
	  }
  }
#if defined(WCE_OPTICON_WORKAROUND)
	if (d->workaround==0)
	{
		d->workaround=1;
		Sleep(WCE_OPTICON_WORKAROUND);
	}
#endif

	while((m=peekq(&d->write_rq))!=NULL){

#ifndef DISABLE_SPEEX
		int vad=1;
		if (d->pst!=NULL && msgdsize(m)==d->pst_frame_size && d->pst_frame_size<=4096)
		{
			char tmp[4096];
			memcpy(tmp, m->b_rptr, msgdsize(m));
			vad = speex_preprocess(d->pst, (short*)tmp, NULL);

			if (d->ready==0)
			{
				if (vad==0)
				{
					int missing;
          missing = 10 - d->write_rq.q_mcount - d->nbufs_playing;
          if (d->wfx.nSamplesPerSec>=32000) /* better results for high rates */
            missing = 6 - d->write_rq.q_mcount - d->nbufs_playing;

		      ms_message("WINSND trouble: inserting %i silence", missing);
					while(missing>0)
					{
						old=dupb(m);
						putq(&d->write_rq,old);
						missing--;
					}
				}
				d->ready=1;
			}
		}
#else
		if (d->ready==0)
		{
      int missing;
			missing = 10 - d->write_rq.q_mcount - d->nbufs_playing;
      if (d->wfx.nSamplesPerSec>=32000) /* better results for high rates */
  			missing = 6 - d->write_rq.q_mcount - d->nbufs_playing;
			ms_message("WINSND trouble: inserting %i silence", missing);
			while(missing>0)
			{
				old=dupb(m);
				putq(&d->write_rq,old);
				missing--;
			}
			d->ready=1;
		}
#endif

		for(i=0;i<d->stat_minimumbuffer;++i){
			WAVEHDR *hdr=&d->hdrs_write[i];
			if (hdr->dwFlags & WHDR_DONE){
				old=(mblk_t*)hdr->dwUser;
				mr=waveOutUnprepareHeader(d->outdev,hdr,sizeof(*hdr));
				if (mr != MMSYSERR_NOERROR){
					ms_error("waveOutUnprepareHeader error");
				}
				freemsg(old);
				hdr->dwUser=0;
			}
			if (hdr->dwUser==0){
				hdr->lpData=(LPSTR)m->b_rptr;
				hdr->dwBufferLength=msgdsize(m);
				hdr->dwFlags = 0;
			    hdr->dwUser = (DWORD)m;
			    mr = waveOutPrepareHeader(d->outdev,hdr,sizeof(*hdr));
			    if (mr != MMSYSERR_NOERROR){
					ms_error("waveOutPrepareHeader() error");
					getq(&d->write_rq);
					freemsg(m);
					discarded++;
					d->stat_notplayed++;
					break;
				}
				mr=waveOutWrite(d->outdev,hdr,sizeof(*hdr));
				if (mr != MMSYSERR_NOERROR){
					ms_error("waveOutWrite() error");
					getq(&d->write_rq);
					freemsg(m);
					discarded++;
					d->stat_notplayed++;
					break;
				}else {
					getq(&d->write_rq);
					d->nbufs_playing++;
					/* ms_debug("waveOutWrite() done"); */
				}
				break;
			}
		}
		if (i==d->stat_minimumbuffer){
			//ms_error("winsnd_write_process: All buffers are busy.");
#ifndef DISABLE_SPEEX
			if (d->pst==NULL)
			{
				/* initial behavior (detection in process?) */
				getq(&d->write_rq);
				freemsg(m);
		    discarded++;
		    d->stat_notplayed++;
			}
			else
			{
				if (vad==0)
				{
					getq(&d->write_rq);
					freemsg(m);
          ms_message("WINSND trouble: silence removed");
			    discarded++;
			    d->stat_notplayed++;
				}
			}
#else
			getq(&d->write_rq);
			freemsg(m);
			discarded++;
			d->stat_notplayed++;
#endif

			break;
		}
	}
}
static void update_pps(DecData *d, mblk_t *pps){
	if (d->pps)
		freemsg(d->pps);
	if (pps) d->pps=dupb(pps);
	else d->pps=NULL;
}
static void update_sps(DecData *d, mblk_t *sps){
	if (d->sps)
		freemsg(d->sps);
	d->sps=dupb(sps);
}
Exemple #23
0
static int
hxge_start(p_hxge_t hxgep, p_tx_ring_t tx_ring_p, p_mblk_t mp)
{
	int 			dma_status, status = 0;
	p_tx_desc_t 		tx_desc_ring_vp;
	hpi_handle_t		hpi_desc_handle;
	hxge_os_dma_handle_t 	tx_desc_dma_handle;
	p_tx_desc_t 		tx_desc_p;
	p_tx_msg_t 		tx_msg_ring;
	p_tx_msg_t 		tx_msg_p;
	tx_desc_t		tx_desc, *tmp_desc_p;
	tx_desc_t		sop_tx_desc, *sop_tx_desc_p;
	p_tx_pkt_header_t	hdrp;
	p_tx_pkt_hdr_all_t	pkthdrp;
	uint8_t			npads = 0;
	uint64_t 		dma_ioaddr;
	uint32_t		dma_flags;
	int			last_bidx;
	uint8_t 		*b_rptr;
	caddr_t 		kaddr;
	uint32_t		nmblks;
	uint32_t		ngathers;
	uint32_t		clen;
	int 			len;
	uint32_t		pkt_len, pack_len, min_len;
	uint32_t		bcopy_thresh;
	int 			i, cur_index, sop_index;
	uint16_t		tail_index;
	boolean_t		tail_wrap = B_FALSE;
	hxge_dma_common_t	desc_area;
	hxge_os_dma_handle_t 	dma_handle;
	ddi_dma_cookie_t 	dma_cookie;
	hpi_handle_t		hpi_handle;
	p_mblk_t 		nmp;
	p_mblk_t		t_mp;
	uint32_t 		ncookies;
	boolean_t 		good_packet;
	boolean_t 		mark_mode = B_FALSE;
	p_hxge_stats_t 		statsp;
	p_hxge_tx_ring_stats_t	tdc_stats;
	t_uscalar_t 		start_offset = 0;
	t_uscalar_t 		stuff_offset = 0;
	t_uscalar_t 		end_offset = 0;
	t_uscalar_t 		value = 0;
	t_uscalar_t 		cksum_flags = 0;
	boolean_t		cksum_on = B_FALSE;
	uint32_t		boff = 0;
	uint64_t		tot_xfer_len = 0, tmp_len = 0;
	boolean_t		header_set = B_FALSE;
	tdc_tdr_kick_t		kick;
	uint32_t		offset;
#ifdef HXGE_DEBUG
	p_tx_desc_t 		tx_desc_ring_pp;
	p_tx_desc_t 		tx_desc_pp;
	tx_desc_t		*save_desc_p;
	int			dump_len;
	int			sad_len;
	uint64_t		sad;
	int			xfer_len;
	uint32_t		msgsize;
#endif

	HXGE_DEBUG_MSG((hxgep, TX_CTL,
	    "==> hxge_start: tx dma channel %d", tx_ring_p->tdc));
	HXGE_DEBUG_MSG((hxgep, TX_CTL,
	    "==> hxge_start: Starting tdc %d desc pending %d",
	    tx_ring_p->tdc, tx_ring_p->descs_pending));

	statsp = hxgep->statsp;

	if (hxgep->statsp->port_stats.lb_mode == hxge_lb_normal) {
		if (!statsp->mac_stats.link_up) {
			freemsg(mp);
			HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start: "
			    "link not up or LB mode"));
			goto hxge_start_fail1;
		}
	}

	mac_hcksum_get(mp, &start_offset, &stuff_offset, &end_offset, &value,
	    &cksum_flags);
	if (!HXGE_IS_VLAN_PACKET(mp->b_rptr)) {
		start_offset += sizeof (ether_header_t);
		stuff_offset += sizeof (ether_header_t);
	} else {
		start_offset += sizeof (struct ether_vlan_header);
		stuff_offset += sizeof (struct ether_vlan_header);
	}

	if (cksum_flags & HCK_PARTIALCKSUM) {
		HXGE_DEBUG_MSG((hxgep, TX_CTL,
		    "==> hxge_start: mp $%p len %d "
		    "cksum_flags 0x%x (partial checksum) ",
		    mp, MBLKL(mp), cksum_flags));
		cksum_on = B_TRUE;
	}

	MUTEX_ENTER(&tx_ring_p->lock);
start_again:
	ngathers = 0;
	sop_index = tx_ring_p->wr_index;
#ifdef	HXGE_DEBUG
	if (tx_ring_p->descs_pending) {
		HXGE_DEBUG_MSG((hxgep, TX_CTL,
		    "==> hxge_start: desc pending %d ",
		    tx_ring_p->descs_pending));
	}

	dump_len = (int)(MBLKL(mp));
	dump_len = (dump_len > 128) ? 128: dump_len;

	HXGE_DEBUG_MSG((hxgep, TX_CTL,
	    "==> hxge_start: tdc %d: dumping ...: b_rptr $%p "
	    "(Before header reserve: ORIGINAL LEN %d)",
	    tx_ring_p->tdc, mp->b_rptr, dump_len));

	HXGE_DEBUG_MSG((hxgep, TX_CTL,
	    "==> hxge_start: dump packets (IP ORIGINAL b_rptr $%p): %s",
	    mp->b_rptr, hxge_dump_packet((char *)mp->b_rptr, dump_len)));
#endif

	tdc_stats = tx_ring_p->tdc_stats;
	mark_mode = (tx_ring_p->descs_pending &&
	    ((tx_ring_p->tx_ring_size - tx_ring_p->descs_pending) <
	    hxge_tx_minfree));

	HXGE_DEBUG_MSG((hxgep, TX_CTL,
	    "TX Descriptor ring is channel %d mark mode %d",
	    tx_ring_p->tdc, mark_mode));

	if (!hxge_txdma_reclaim(hxgep, tx_ring_p, hxge_tx_minfree)) {
		HXGE_DEBUG_MSG((hxgep, TX_CTL,
		    "TX Descriptor ring is full: channel %d", tx_ring_p->tdc));
		HXGE_DEBUG_MSG((hxgep, TX_CTL,
		    "TX Descriptor ring is full: channel %d", tx_ring_p->tdc));
		(void) atomic_cas_32((uint32_t *)&tx_ring_p->queueing, 0, 1);
		tdc_stats->tx_no_desc++;
		MUTEX_EXIT(&tx_ring_p->lock);
		status = 1;
		goto hxge_start_fail1;
	}

	nmp = mp;
	i = sop_index = tx_ring_p->wr_index;
	nmblks = 0;
	ngathers = 0;
	pkt_len = 0;
	pack_len = 0;
	clen = 0;
	last_bidx = -1;
	good_packet = B_TRUE;

	desc_area = tx_ring_p->tdc_desc;
	hpi_handle = desc_area.hpi_handle;
	hpi_desc_handle.regh = (hxge_os_acc_handle_t)
	    DMA_COMMON_ACC_HANDLE(desc_area);
	hpi_desc_handle.hxgep = hxgep;
	tx_desc_ring_vp = (p_tx_desc_t)DMA_COMMON_VPTR(desc_area);
#ifdef	HXGE_DEBUG
#if defined(__i386)
	tx_desc_ring_pp = (p_tx_desc_t)(uint32_t)DMA_COMMON_IOADDR(desc_area);
#else
	tx_desc_ring_pp = (p_tx_desc_t)DMA_COMMON_IOADDR(desc_area);
#endif
#endif
	tx_desc_dma_handle = (hxge_os_dma_handle_t)DMA_COMMON_HANDLE(desc_area);
	tx_msg_ring = tx_ring_p->tx_msg_ring;

	HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start: wr_index %d i %d",
	    sop_index, i));

#ifdef	HXGE_DEBUG
	msgsize = msgdsize(nmp);
	HXGE_DEBUG_MSG((hxgep, TX_CTL,
	    "==> hxge_start(1): wr_index %d i %d msgdsize %d",
	    sop_index, i, msgsize));
#endif
	/*
	 * The first 16 bytes of the premapped buffer are reserved
	 * for header. No padding will be used.
	 */
	pkt_len = pack_len = boff = TX_PKT_HEADER_SIZE;
	if (hxge_tx_use_bcopy) {
		bcopy_thresh = (hxge_bcopy_thresh - TX_PKT_HEADER_SIZE);
	} else {
		bcopy_thresh = (TX_BCOPY_SIZE - TX_PKT_HEADER_SIZE);
	}
	while (nmp) {
		good_packet = B_TRUE;
		b_rptr = nmp->b_rptr;
		len = MBLKL(nmp);
		if (len <= 0) {
			nmp = nmp->b_cont;
			continue;
		}
		nmblks++;

		HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start(1): nmblks %d "
		    "len %d pkt_len %d pack_len %d",
		    nmblks, len, pkt_len, pack_len));
		/*
		 * Hardware limits the transfer length to 4K.
		 * If len is more than 4K, we need to break
		 * nmp into two chunks: Make first chunk smaller
		 * than 4K. The second chunk will be broken into
		 * less than 4K (if needed) during the next pass.
		 */
		if (len > (TX_MAX_TRANSFER_LENGTH - TX_PKT_HEADER_SIZE)) {
			if ((t_mp = dupb(nmp)) != NULL) {
				nmp->b_wptr = nmp->b_rptr +
				    (TX_MAX_TRANSFER_LENGTH -
				    TX_PKT_HEADER_SIZE);
				t_mp->b_rptr = nmp->b_wptr;
				t_mp->b_cont = nmp->b_cont;
				nmp->b_cont = t_mp;
				len = MBLKL(nmp);
			} else {
				good_packet = B_FALSE;
				goto hxge_start_fail2;
			}
		}
		tx_desc.value = 0;
		tx_desc_p = &tx_desc_ring_vp[i];
#ifdef	HXGE_DEBUG
		tx_desc_pp = &tx_desc_ring_pp[i];
#endif
		tx_msg_p = &tx_msg_ring[i];
#if defined(__i386)
		hpi_desc_handle.regp = (uint32_t)tx_desc_p;
#else
		hpi_desc_handle.regp = (uint64_t)tx_desc_p;
#endif
		if (!header_set &&
		    ((!hxge_tx_use_bcopy && (len > TX_BCOPY_SIZE)) ||
		    (len >= bcopy_thresh))) {
			header_set = B_TRUE;
			bcopy_thresh += TX_PKT_HEADER_SIZE;
			boff = 0;
			pack_len = 0;
			kaddr = (caddr_t)DMA_COMMON_VPTR(tx_msg_p->buf_dma);
			hdrp = (p_tx_pkt_header_t)kaddr;
			clen = pkt_len;
			dma_handle = tx_msg_p->buf_dma_handle;
			dma_ioaddr = DMA_COMMON_IOADDR(tx_msg_p->buf_dma);
			offset = tx_msg_p->offset_index * hxge_bcopy_thresh;
			(void) ddi_dma_sync(dma_handle,
			    offset, hxge_bcopy_thresh, DDI_DMA_SYNC_FORDEV);

			tx_msg_p->flags.dma_type = USE_BCOPY;
			goto hxge_start_control_header_only;
		}

		pkt_len += len;
		pack_len += len;

		HXGE_DEBUG_MSG((hxgep, TX_CTL,
		    "==> hxge_start(3): desc entry %d DESC IOADDR $%p "
		    "desc_vp $%p tx_desc_p $%p desc_pp $%p tx_desc_pp $%p "
		    "len %d pkt_len %d pack_len %d",
		    i,
		    DMA_COMMON_IOADDR(desc_area),
		    tx_desc_ring_vp, tx_desc_p,
		    tx_desc_ring_pp, tx_desc_pp,
		    len, pkt_len, pack_len));

		if (len < bcopy_thresh) {
			HXGE_DEBUG_MSG((hxgep, TX_CTL,
			    "==> hxge_start(4): USE BCOPY: "));
			if (hxge_tx_tiny_pack) {
				uint32_t blst = TXDMA_DESC_NEXT_INDEX(i, -1,
				    tx_ring_p->tx_wrap_mask);
				HXGE_DEBUG_MSG((hxgep, TX_CTL,
				    "==> hxge_start(5): pack"));
				if ((pack_len <= bcopy_thresh) &&
				    (last_bidx == blst)) {
					HXGE_DEBUG_MSG((hxgep, TX_CTL,
					    "==> hxge_start: pack(6) "
					    "(pkt_len %d pack_len %d)",
					    pkt_len, pack_len));
					i = blst;
					tx_desc_p = &tx_desc_ring_vp[i];
#ifdef	HXGE_DEBUG
					tx_desc_pp = &tx_desc_ring_pp[i];
#endif
					tx_msg_p = &tx_msg_ring[i];
					boff = pack_len - len;
					ngathers--;
				} else if (pack_len > bcopy_thresh &&
				    header_set) {
					pack_len = len;
					boff = 0;
					bcopy_thresh = hxge_bcopy_thresh;
					HXGE_DEBUG_MSG((hxgep, TX_CTL,
					    "==> hxge_start(7): > max NEW "
					    "bcopy thresh %d "
					    "pkt_len %d pack_len %d(next)",
					    bcopy_thresh, pkt_len, pack_len));
				}
				last_bidx = i;
			}
			kaddr = (caddr_t)DMA_COMMON_VPTR(tx_msg_p->buf_dma);
			if ((boff == TX_PKT_HEADER_SIZE) && (nmblks == 1)) {
				hdrp = (p_tx_pkt_header_t)kaddr;
				header_set = B_TRUE;
				HXGE_DEBUG_MSG((hxgep, TX_CTL,
				    "==> hxge_start(7_x2): "
				    "pkt_len %d pack_len %d (new hdrp $%p)",
				    pkt_len, pack_len, hdrp));
			}
			tx_msg_p->flags.dma_type = USE_BCOPY;
			kaddr += boff;
			HXGE_DEBUG_MSG((hxgep, TX_CTL,
			    "==> hxge_start(8): USE BCOPY: before bcopy "
			    "DESC IOADDR $%p entry %d bcopy packets %d "
			    "bcopy kaddr $%p bcopy ioaddr (SAD) $%p "
			    "bcopy clen %d bcopy boff %d",
			    DMA_COMMON_IOADDR(desc_area), i,
			    tdc_stats->tx_hdr_pkts, kaddr, dma_ioaddr,
			    clen, boff));
			HXGE_DEBUG_MSG((hxgep, TX_CTL,
			    "==> hxge_start: 1USE BCOPY: "));
			HXGE_DEBUG_MSG((hxgep, TX_CTL,
			    "==> hxge_start: 2USE BCOPY: "));
			HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start: "
			    "last USE BCOPY: copy from b_rptr $%p "
			    "to KADDR $%p (len %d offset %d",
			    b_rptr, kaddr, len, boff));
			bcopy(b_rptr, kaddr, len);
#ifdef	HXGE_DEBUG
			dump_len = (len > 128) ? 128: len;
			HXGE_DEBUG_MSG((hxgep, TX_CTL,
			    "==> hxge_start: dump packets "
			    "(After BCOPY len %d)"
			    "(b_rptr $%p): %s", len, nmp->b_rptr,
			    hxge_dump_packet((char *)nmp->b_rptr,
			    dump_len)));
#endif
			dma_handle = tx_msg_p->buf_dma_handle;
			dma_ioaddr = DMA_COMMON_IOADDR(tx_msg_p->buf_dma);
			offset = tx_msg_p->offset_index * hxge_bcopy_thresh;
			(void) ddi_dma_sync(dma_handle,
			    offset, hxge_bcopy_thresh, DDI_DMA_SYNC_FORDEV);
			clen = len + boff;
			tdc_stats->tx_hdr_pkts++;
			HXGE_DEBUG_MSG((hxgep, TX_CTL, "==> hxge_start(9): "
			    "USE BCOPY: DESC IOADDR $%p entry %d "
			    "bcopy packets %d bcopy kaddr $%p "
			    "bcopy ioaddr (SAD) $%p bcopy clen %d "
			    "bcopy boff %d",
			    DMA_COMMON_IOADDR(desc_area), i,
			    tdc_stats->tx_hdr_pkts, kaddr, dma_ioaddr,
			    clen, boff));
		} else {
			HXGE_DEBUG_MSG((hxgep, TX_CTL,
			    "==> hxge_start(12): USE DVMA: len %d", len));
			tx_msg_p->flags.dma_type = USE_DMA;
			dma_flags = DDI_DMA_WRITE;
			if (len < hxge_dma_stream_thresh) {
				dma_flags |= DDI_DMA_CONSISTENT;
			} else {
				dma_flags |= DDI_DMA_STREAMING;
			}

			dma_handle = tx_msg_p->dma_handle;
			dma_status = ddi_dma_addr_bind_handle(dma_handle, NULL,
			    (caddr_t)b_rptr, len, dma_flags,
			    DDI_DMA_DONTWAIT, NULL,
			    &dma_cookie, &ncookies);
			if (dma_status == DDI_DMA_MAPPED) {
				dma_ioaddr = dma_cookie.dmac_laddress;
				len = (int)dma_cookie.dmac_size;
				clen = (uint32_t)dma_cookie.dmac_size;
				HXGE_DEBUG_MSG((hxgep, TX_CTL,
				    "==> hxge_start(12_1): "
				    "USE DVMA: len %d clen %d ngathers %d",
				    len, clen, ngathers));
#if defined(__i386)
				hpi_desc_handle.regp = (uint32_t)tx_desc_p;
#else
				hpi_desc_handle.regp = (uint64_t)tx_desc_p;
#endif
				while (ncookies > 1) {
					ngathers++;
					/*
					 * this is the fix for multiple
					 * cookies, which are basically
					 * a descriptor entry, we don't set
					 * SOP bit as well as related fields
					 */

					(void) hpi_txdma_desc_gather_set(
					    hpi_desc_handle, &tx_desc,
					    (ngathers -1), mark_mode,
					    ngathers, dma_ioaddr, clen);
					tx_msg_p->tx_msg_size = clen;
					HXGE_DEBUG_MSG((hxgep, TX_CTL,
					    "==> hxge_start:  DMA "
					    "ncookie %d ngathers %d "
					    "dma_ioaddr $%p len %d"
					    "desc $%p descp $%p (%d)",
					    ncookies, ngathers,
					    dma_ioaddr, clen,
					    *tx_desc_p, tx_desc_p, i));

					ddi_dma_nextcookie(dma_handle,
					    &dma_cookie);
					dma_ioaddr = dma_cookie.dmac_laddress;

					len = (int)dma_cookie.dmac_size;
					clen = (uint32_t)dma_cookie.dmac_size;
					HXGE_DEBUG_MSG((hxgep, TX_CTL,
					    "==> hxge_start(12_2): "
					    "USE DVMA: len %d clen %d ",
					    len, clen));

					i = TXDMA_DESC_NEXT_INDEX(i, 1,
					    tx_ring_p->tx_wrap_mask);
					tx_desc_p = &tx_desc_ring_vp[i];

					hpi_desc_handle.regp =
#if defined(__i386)
					    (uint32_t)tx_desc_p;
#else
						(uint64_t)tx_desc_p;
#endif
					tx_msg_p = &tx_msg_ring[i];
					tx_msg_p->flags.dma_type = USE_NONE;
					tx_desc.value = 0;
					ncookies--;
				}
				tdc_stats->tx_ddi_pkts++;
				HXGE_DEBUG_MSG((hxgep, TX_CTL,
				    "==> hxge_start: DMA: ddi packets %d",
				    tdc_stats->tx_ddi_pkts));
			} else {
				HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL,
				    "dma mapping failed for %d "
				    "bytes addr $%p flags %x (%d)",
				    len, b_rptr, status, status));
				good_packet = B_FALSE;
				tdc_stats->tx_dma_bind_fail++;
				tx_msg_p->flags.dma_type = USE_NONE;
				status = 1;
				goto hxge_start_fail2;
			}
		} /* ddi dvma */

		nmp = nmp->b_cont;
hxge_start_control_header_only:
#if defined(__i386)
		hpi_desc_handle.regp = (uint32_t)tx_desc_p;
#else
		hpi_desc_handle.regp = (uint64_t)tx_desc_p;
#endif
		ngathers++;

		if (ngathers == 1) {
#ifdef	HXGE_DEBUG
			save_desc_p = &sop_tx_desc;
#endif
			sop_tx_desc_p = &sop_tx_desc;
			sop_tx_desc_p->value = 0;
			sop_tx_desc_p->bits.tr_len = clen;
			sop_tx_desc_p->bits.sad = dma_ioaddr >> 32;
			sop_tx_desc_p->bits.sad_l = dma_ioaddr & 0xffffffff;
		} else {
void
sctp_wput_asconf(sctp_t *sctp, sctp_faddr_t *fp)
{
#define	SCTP_SET_SENT_FLAG(mp)	((mp)->b_flag = SCTP_CHUNK_FLAG_SENT)

	mblk_t 			*mp;
	mblk_t			*ipmp;
	uint32_t 		*snp;
	sctp_parm_hdr_t		*ph;
	boolean_t		isv4;
	sctp_stack_t		*sctps = sctp->sctp_sctps;
	boolean_t		saddr_set;

	if (sctp->sctp_cchunk_pend || sctp->sctp_cxmit_list == NULL ||
	    /* Queue it for later transmission if not yet established */
	    sctp->sctp_state < SCTPS_ESTABLISHED) {
		ip2dbg(("sctp_wput_asconf: cchunk pending? (%d) or null "\
		    "sctp_cxmit_list? (%s) or incorrect state? (%x)\n",
		    sctp->sctp_cchunk_pend, sctp->sctp_cxmit_list == NULL ?
		    "yes" : "no", sctp->sctp_state));
		return;
	}

	if (fp == NULL)
		fp = sctp->sctp_current;

	/* OK to send */
	ipmp = sctp_make_mp(sctp, fp, 0);
	if (ipmp == NULL) {
		SCTP_FADDR_RC_TIMER_RESTART(sctp, fp, fp->rto);
		SCTP_KSTAT(sctps, sctp_send_asconf_failed);
		return;
	}
	mp = sctp->sctp_cxmit_list;
	/* Fill in the mandatory  Address Parameter TLV */
	isv4 = (fp != NULL) ? fp->isv4 : sctp->sctp_current->isv4;
	ph = (sctp_parm_hdr_t *)(mp->b_rptr + sizeof (sctp_chunk_hdr_t) +
	    sizeof (uint32_t));
	if (isv4) {
		ipha_t		*ipha = (ipha_t *)ipmp->b_rptr;
		in6_addr_t	ipaddr;
		ipaddr_t	addr4;

		ph->sph_type = htons(PARM_ADDR4);
		ph->sph_len = htons(PARM_ADDR4_LEN);
		if (ipha->ipha_src != INADDR_ANY) {
			bcopy(&ipha->ipha_src, ph + 1, IP_ADDR_LEN);
		} else {
			ipaddr = sctp_get_valid_addr(sctp, B_FALSE, &saddr_set);
			/*
			 * All the addresses are down.
			 * Maybe we might have better luck next time.
			 */
			if (!saddr_set) {
				SCTP_FADDR_RC_TIMER_RESTART(sctp, fp, fp->rto);
				freeb(ipmp);
				return;
			}
			IN6_V4MAPPED_TO_IPADDR(&ipaddr, addr4);
			bcopy(&addr4, ph + 1, IP_ADDR_LEN);
		}
	} else {
		ip6_t		*ip6 = (ip6_t *)ipmp->b_rptr;
		in6_addr_t	ipaddr;

		ph->sph_type = htons(PARM_ADDR6);
		ph->sph_len = htons(PARM_ADDR6_LEN);
		if (!IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
			bcopy(&ip6->ip6_src, ph + 1, IPV6_ADDR_LEN);
		} else {
			ipaddr = sctp_get_valid_addr(sctp, B_TRUE, &saddr_set);
			/*
			 * All the addresses are down.
			 * Maybe we might have better luck next time.
			 */
			if (!saddr_set) {
				SCTP_FADDR_RC_TIMER_RESTART(sctp, fp, fp->rto);
				freeb(ipmp);
				return;
			}
			bcopy(&ipaddr, ph + 1, IPV6_ADDR_LEN);
		}
	}

	/* Don't exceed CWND */
	if ((MBLKL(mp) > (fp->cwnd - fp->suna)) ||
	    ((mp = dupb(sctp->sctp_cxmit_list)) == NULL)) {
		SCTP_FADDR_RC_TIMER_RESTART(sctp, fp, fp->rto);
		freeb(ipmp);
		return;
	}

	/* Set the serial number now, if sending for the first time */
	if (!SCTP_CHUNK_WANT_REXMIT(mp)) {
		snp = (uint32_t *)(mp->b_rptr + sizeof (sctp_chunk_hdr_t));
		*snp = htonl(sctp->sctp_lcsn++);
	}
	SCTP_CHUNK_CLEAR_FLAGS(mp);
	fp->suna += MBLKL(mp);
	/* Attach the header and send the chunk */
	ipmp->b_cont = mp;
	sctp->sctp_cchunk_pend = 1;

	SCTP_SET_SENT_FLAG(sctp->sctp_cxmit_list);
	SCTP_SET_CHUNK_DEST(sctp->sctp_cxmit_list, fp);
	sctp_set_iplen(sctp, ipmp, fp->ixa);
	(void) conn_ip_output(ipmp, fp->ixa);
	BUMP_LOCAL(sctp->sctp_opkts);
	SCTP_FADDR_RC_TIMER_RESTART(sctp, fp, fp->rto);
#undef	SCTP_SET_SENT_FLAG
}
Exemple #25
0
/*
 * This routine is called from read put/service procedure and parses
 * message block to check for telnet protocol by detecting an IAC.
 * The routine processes the data part of the message block first and
 * then sends protocol followed after IAC to the telnet daemon. The
 * routine also processes CR/LF by eliminating LF/NULL followed after CR.
 *
 * Since the code to do this with streams mblks is complicated, some
 * explanations are in order.  If an IAC is found, a dupb() is done,
 * and the pointers are adjusted to create two streams message.  The
 * (possibly empty) first message contains preceeding data, and the
 * second begins with the IAC and contains the rest of the streams
 * message.
 *
 * The variables:
 * datamp:	Points to the head of a chain of mblks containing data
 *		which requires no expansion, and can be forwarded directly
 *		to the pty.
 * prevmp:	Points to the last mblk on the datamp chain, used to add
 *		to the chain headed by datamp.
 * newmp:	When an M_CTL header is required, this pointer references
 *		that "header" mblk.
 * protomp:	When an IAC is discovered, a dupb() is done on the first mblk
 *		containing an IAC.  protomp points to this dup'ed mblk.
 *		This mblk is eventually forwarded to the daemon.
 */
static int
rcv_parse(queue_t *q, mblk_t *mp)
{
	mblk_t	*protomp, *newmp, *datamp, *prevmp;
	unsigned char *tmp;
	size_t	msgsize;

	struct telmod_info    *tmip = (struct telmod_info *)q->q_ptr;

	datamp = mp;
	prevmp = protomp = 0;

	while (mp) {
		/*
		 * If the mblk is empty, just continue scanning.
		 */
		if (mp->b_rptr == mp->b_wptr) {
			prevmp = mp;
			mp = mp->b_cont;
			continue;
		}
		/*
		 * First check to see if we have received CR and are checking
		 * for a following LF/NULL.  If so, do what's necessary to
		 * trim the LF/NULL.  This case is for when the LF/NULL is
		 * at the beginning of a subsequent mblk.
		 */
		if (!(tmip->flags & TEL_BINARY_IN) &&
		    (tmip->flags & TEL_CRRCV)) {
			if ((*mp->b_rptr == '\n') || (*mp->b_rptr == NULL)) {
				if (mp->b_wptr == (mp->b_rptr + 1)) {
					tmip->flags &= ~TEL_CRRCV;
					if (prevmp) {
						prevmp->b_cont = mp->b_cont;
						freeb(mp);
						mp = prevmp->b_cont;
						continue;
					} else {
						datamp = mp->b_cont;
						freeb(mp);
						if (datamp == NULL) {
							/*
							 * Message contained
							 * only a '\0' after
							 * a '\r' in a previous
							 * message, so we can
							 * read more, even
							 * though we have
							 * nothing to putnext.
							 */
							return (1);
						} else {
							mp = datamp;
							continue;
						}
					}
				}
				mp->b_rptr += 1;
			}
			tmip->flags &= ~TEL_CRRCV;
		}
		tmp = mp->b_rptr;
		/*
		 * Now scan through the entire message block, for IACs
		 * and CR characters, which need processing.
		 */
		while (tmp < mp->b_wptr) {

			if (tmp[0] == IAC) {
				/*
				 * Telnet protocol - parse it now
				 * process data part of mblk
				 * before sending the protocol.
				 */
				if (tmp > mp->b_rptr) {
					if ((protomp = dupb(mp)) == NULL) {
						msgsize = msgdsize(datamp);
						recover(q, datamp, msgsize);
						return (0);
					}
					ASSERT(tmp >= mp->b_datap->db_base);
					ASSERT(tmp <= mp->b_datap->db_lim);
					ASSERT(tmp >=
					    protomp->b_datap->db_base);
					ASSERT(tmp <= protomp->b_datap->db_lim);
					mp->b_wptr = tmp;
					protomp->b_rptr = tmp;
					protomp->b_cont = mp->b_cont;
					mp->b_cont = 0;

					if (prevmp)
						prevmp->b_cont = mp;

				} else {
					protomp = mp;

					if (prevmp)
						prevmp->b_cont = 0;
					else
						datamp = 0;
				}
				if (datamp) {
					putnext(q, datamp);
				}
				/*
				 * create a 1 byte M_CTL message block with
				 * protomp and send it down.
				 */

				if ((newmp = allocb(sizeof (char),
					BPRI_MED)) == NULL) {
					/*
					 * Save the dup'ed mp containing
					 * the protocol information which
					 * we couldn't get an M_CTL header
					 * for.
					 */
					msgsize = msgdsize(protomp);
					recover(q, protomp, msgsize);
					return (0);
				}
				newmp->b_datap->db_type = M_CTL;
				newmp->b_wptr = newmp->b_rptr + 1;
				*(newmp->b_rptr) = M_CTL_MAGIC_NUMBER;
				newmp->b_cont = protomp;
				noenable(q);
				tmip->flags |= TEL_STOPPED;
				putnext(q, newmp);

				return (0);
			}
			if (!(tmip->flags & TEL_BINARY_IN)) {
				/*
				 * Set TEL_CRRCV flag if last character is CR
				 */
				if ((tmp == (mp->b_wptr - 1)) &&
					(tmp[0] == '\r')) {
					tmip->flags |= TEL_CRRCV;
					break;
				}

				/*
				 * If CR is followed by LF/NULL, get rid of
				 * LF/NULL and realign the message block.
				 */
				if ((tmp[0] == '\r') && ((tmp[1] == '\n') ||
				    (tmp[1] == NULL))) {
					/*
					 * If CR is in the middle of a block,
					 * we need to get rid of LF and join
					 * the two pieces together.
					 */
					if (mp->b_wptr > (tmp + 2)) {
						bcopy(tmp + 2, tmp + 1,
						    (mp->b_wptr - tmp - 2));
						mp->b_wptr -= 1;
					} else {
						mp->b_wptr = tmp + 1;
					}

					if (prevmp)
						prevmp->b_cont = mp;
				}
			}
			tmp++;
		}
		prevmp = mp;
		mp = mp->b_cont;
	}
	putnext(q, datamp);

	return (1);
}