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

📄 sb.c

📁 简介:一个tcp/ip协议实现的完整源代码包.包括arp,ax25,icmp,tcp, telnet,trace,udp的源代码,可同时作为客户端,服务端 ,ip包路由.同时处理多个服务器,客户端
💻 C
📖 第 1 页 / 共 2 页
字号:
long rate;	/* Sampling rate, Hz */
int stereo;	/* 1 = stereo, 0 = mono */
int bufsiz;	/* Size of mbufs to be generated (1/2 DMA buffer) */
{
	if(Sb.base == 0){
		printf("No SB16 card attached\n");
		return -1;
	}
	if(Sb.state != IDLE){
		printf("SB16 not idle\n");
		return -1;
	}
	/* Allocate DMA buffer */
	if((Sb.ioptr = Sb.dmabuf = dma_malloc(&Sb.selector,2*bufsiz,1)) == NULL){
		printf("Can't alloc dma buffer\n");
		return -1;
	}
	Sb.state = ADC;
	Sb.dmasize = 2*bufsiz;
	setup_dma(Sb.dma16,Sb.dmabuf,Sb.dmasize,0x54);

	/* Set sampling rate */
	sb_write_byte(Sb.base,0x42);
	sb_write_word_be(Sb.base,rate);

	sb_write_byte(Sb.base,0xbe);	/* 16-bit input, auto-init, fifo on */
	if(stereo)
		sb_write_byte(Sb.base,0x30);	/* stereo, signed */
	else
		sb_write_byte(Sb.base,0x10);	/* mono, signed */
	/* Write number of 16-bit words in half buffer, minus 1 */
	sb_write_word_le(Sb.base,Sb.dmasize/4-1);
	return 0;
}
/* Enter DAC mode */
int
sb_dac(rate,stereo,bufsiz)
long rate;	/* Sampling rate, Hz */
int stereo;	/* 1 = stereo, 0 = mono */
int bufsiz;	/* Size of buffer unit (1/2 DMA buffer) */
{
	if(Sb.base == 0){
		printf("No SB16 card attached\n");
		return -1;
	}
	if(Sb.state != IDLE){
		printf("SB16 not idle\n");
		return -1;
	}
	/* Allocate DMA buffer */
	if((Sb.ioptr = Sb.dmabuf = dma_malloc(&Sb.selector,2*bufsiz,1)) == 0){
		printf("Can't alloc dma buffer\n");
		return -1;
	}
	Sb.state = DAC;
	Sb.dmasize = 2*bufsiz;
	Sb.stuffsamples = 0;
	Sb.bufcnt = 0;
	{
		char *buf;

		buf = malloc(Sb.dmasize);
		memset(buf,0,Sb.dmasize);	
		dosmemput(buf,Sb.dmasize,Sb.dmabuf);
		free(buf);
	}
	sb_write_byte(Sb.base,0xd1);	/* spkr on */
	setup_dma(Sb.dma16,Sb.dmabuf,Sb.dmasize,0x58);

	/* Set up sampling rate */
	sb_write_byte(Sb.base,0x41);
	sb_write_word_be(Sb.base,rate);

	sb_write_byte(Sb.base,0xb6);	/* 16-bit output, auto-init, fifo on */
	if(stereo)
		sb_write_byte(Sb.base,0x30);	/* stereo, signed */
	else
		sb_write_byte(Sb.base,0x10);	/* mono, signed */
	/* Number of 16-bit words in a half-buffer, minus 1 */
	sb_write_word_le(Sb.base,Sb.dmasize/4-1);
	Sb.pause = 1;
	sb_write_byte(Sb.base,0xd5);	/* Pause until we get data */
	return 0;
}
/* Return soundblaster to idle condition */
int
sb_idle(void)
{
	int cnt;

	switch(Sb.state){
	case IDLE:
		return 0;	/* Already idle */		
	case DAC:
		/* Wait for output queue to drain to below one buffer */
		disable();
		while(Sb.bufcnt >= Sb.dmasize/2)
			kwait(&Sb);

		/* If an incomplete buffer remains, pad it out */ 
		cnt = Sb.bufcnt;
		enable();
		if(cnt > 0){
			struct mbuf *bp;

			bp = ambufw(Sb.dmasize/2 - cnt);
			bp->cnt = Sb.dmasize/2 - cnt;
			memset(bp->data,0,bp->cnt);
			sb_send(&bp);
		}	
		disable();
		while(!Sb.pause)
			kwait(&Sb);
		enable();
	case ADC:	/* note fall-thru */
		/* stop conversion */
		sb_write_byte(Sb.base,0xd9);
		break;
	}
	Sb.bufcnt = 0;
	Sb.state = IDLE;
	kwait(NULL);
	/* Ought to wait for last interrupt here */
	dma_disable(Sb.dma16);
	__dpmi_free_dos_memory(Sb.selector);
	Sb.dmabuf = 0;

	return 0;
}
/* Send buffer to the DAC, starting it if it was paused, and blocking as
 * needed
 */
int
sb_send(struct mbuf **bpp)
{
	int cnt;

	if(bpp == NULL || Sb.state != DAC)
		return -1;

	while(*bpp != NULL){
		/* Wait for space to open up in DMA buffer */
		disable();
		while(Sb.bufcnt >= Sb.dmasize)
			kwait(&Sb);
		cnt = Sb.dmasize-Sb.bufcnt;
		enable();

		/* In this round, we transfer the lesser of:
		 * -the available space in the DMA buffer
		 * -the data remaining in this packet
		 * -the free space in the high end of the DMA buffer
		 */
		cnt = min(cnt,(*bpp)->cnt);
		cnt = min(cnt,Sb.dmabuf+Sb.dmasize-Sb.ioptr);
		if(cnt == 0)
			break;	/* Nothing more to do */

		dosmemput((*bpp)->data,cnt,Sb.ioptr);

		disable();
		Sb.bufcnt += cnt;	/* Add to bytes in buffer */
		/* Resume output if there's now at least one full buffer */
		if(Sb.pause && Sb.bufcnt >= Sb.dmasize/2){
			Sb.pause = 0;
			sb_write_byte(Sb.base,0xd6);
		}
		enable();

		(*bpp)->data += cnt;
		(*bpp)->cnt -= cnt;
		if((*bpp)->cnt == 0)
			free_mbuf(bpp);

		/* Increment pointer, wrap around if necessary */
		Sb.ioptr += cnt;
		if(Sb.ioptr >= Sb.dmabuf + Sb.dmasize)
			Sb.ioptr -= Sb.dmasize;
	}
	return 0;
}
/* Read a buffer from the A/D, blocking if necessary */
struct mbuf *
sb_recv(void)
{
	struct mbuf *bp;
	int i;

	if(Sb.state != ADC)
		return NULL;	/* Not in A/D mode */

	while((i = Sb.bufcnt) == 0)
		kwait(&Sb);

	bp = alloc_mbuf(i);
	dosmemget(Sb.ioptr,i,bp->data);
	bp->cnt = i;
	Sb.ioptr += i;
	if(Sb.ioptr >= Sb.dmabuf + Sb.dmasize)
		Sb.ioptr -= Sb.dmasize;
	disable();
	Sb.bufcnt -= i;
	enable();
	return bp;
}

/* Reset Soundblaster card */
static int
sb_reset(int base)
{
	unsigned int i;

	outportb(base+SB_RESET,1);
	for(i=100;i !=0;i--)
		;
	outportb(base+SB_RESET,0);
	for(i=65535;i != 0;i--){
		if(sb_read_data(base) == 0xaa)
			break;
	}
	if(i == 0)
		return -1;
	return 0;
}
/* Wait for read data to become available, then read it. Return -1 on timeout */
static int
sb_read_data(int base)
{
	unsigned int i;

	for(i=65535;i!=0;i--){
		if(inportb(base+SB_RB_STAT) & 0x80)
			break;
	}
	if(i == 0)
		return -1;	/* Timeout */
	return inportb(base+SB_READ_DATA);
}

/* Write data byte to soundblaster when it's ready. return 0 normally, -1 on err */
static int
sb_write_byte(int base, int data)
{
	int i;

	for(i=65535;i!=0;i--){
		if((inportb(base+SB_WB_STAT) & 0x80) == 0)
			break;
	}
	if(i == 0)
		return -1;
	outportb(base+SB_WB,data);
	return 0;
}
/* Write 16-bit word in big-endian order */
static int
sb_write_word_be(int base,int data)
{
	sb_write_byte(base,data >> 8);
	sb_write_byte(base,data);
	return 0;
}
/* Write 16-bit word in little-endian order */
static int
sb_write_word_le(int base,int data)
{
	sb_write_byte(base,data);
	sb_write_byte(base,data >> 8);
	return 0;
}
/* Read the mixer */
static int
sb_read_mix(int base,int reg)
{
	outportb(base+SB_MIX_INDEX,reg);
	return inportb(base+SB_MIX_DATA);
}

/* Write data to soundblaster when it's ready. return 0 normally, -1 on err */
static int
sb_write_mix(int base,int reg,int data)
{
	outportb(base+SB_MIX_INDEX,reg);
	outportb(base+SB_MIX_DATA,data);
	return 0;
}

dosbcal(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	long rate;

	rate = atol(argv[1]);
	sb_calibrate(rate);
	return 0;
}

/* Find DC offsets of each channel */
sb_calibrate(long rate)
{
	long leftavg,rightavg;
	uint8 omixl,omixr;
	long samples;
	struct mbuf *bp;
	uint left,right;

	/* Save previous mixer state,
	 * then turn everything off
	 */
	omixl = sb_read_mix(Sb.base,SB_INMIXL);
	omixr = sb_read_mix(Sb.base,SB_INMIXR);
	sb_write_mix(Sb.base,SB_INMIXL,0);		/* All inputs off */
	sb_write_mix(Sb.base,SB_INMIXR,0);

	/* Collect and analyze some data */
	sb_adc(rate,1,TXBUF);
	leftavg = rightavg = 0;
	samples = 0;

	bp = sb_recv();
	while(bp != NULL){
		left = pull16le(&bp);
		right = pull16le(&bp);

		leftavg += left;
		rightavg += right;		
		samples++;
	}
	sb_idle();
	/* Restore previous mixer switches */
	sb_write_mix(Sb.base,SB_INMIXL,omixl);
	sb_write_mix(Sb.base,SB_INMIXR,omixr);

	leftavg /= samples;
	rightavg /= samples;
	printf("Left channel avg: %ld Right channel avg: %ld\n",
	 leftavg,rightavg);

	return 0;
}
unsigned short
pull16le(struct mbuf **bpp)
{
	uint x;

	x = pull16(bpp);
	return (x >> 8) | (x << 8);
}
/* Soundblaster interrupt handler */
void
sbhandle(int dev)
{
	int i;

	Sb.interrupts++;
	i = sb_read_mix(Sb.base,0x82);
	if(i & 1)	/* 8-bit transfers not used, reset anyway */
		(void)inportb(Sb.base+0xe);

	if(i & 2)
		(void)inportb(Sb.base+0xf);
	else
		return;

	switch(Sb.state){
	case IDLE:
		break;
	case ADC:
		if(Sb.bufcnt != Sb.dmasize)
			Sb.bufcnt += Sb.dmasize/2;
		ksignal(&Sb,1);
		break;
	case DAC:
		Sb.bufcnt -= Sb.dmasize/2;	/* Amount sent */
		if(Sb.bufcnt < Sb.dmasize/2){
			/* buffer not ready, pause */
			Sb.pause = 1;
			sb_write_byte(Sb.base,0xd5);
		}
		ksignal(&Sb,1);
		break;
	}
}

⌨️ 快捷键说明

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