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

📄 dsp.c

📁 mp2解压程序
💻 C
字号:
/* * MPEG Audio DSP Player Linux Module v0.1 * copyrights (c) 1996 by Michael Hipp *  * Read the README file before using the software!! *//* * gcc -O2 -Wall -m486 -fomit-frame-pointer -DMODULE -D__KERNEL__ -c dsp.c */#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/interrupt.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/in.h>#include <linux/malloc.h>#include <linux/string.h>#include <asm/system.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/dma.h>#include <linux/errno.h>#include "dsp_ld.h"#define BUFFER_SIZE 16384#define DSP_MAJOR 62struct cd {    unsigned char bufs[2][BUFFER_SIZE];    int rbuf;    int wbuf;    int rpos;    int wpos;    int state;	int wsize,rsize;    struct wait_queue *waitq;	int base_addr;	int dma;	int irq;	int interrupt;};static int dsp_open_dev(struct inode * inode, struct file * file);static void dsp_release_dev(struct inode * inode, struct file * file);static int dsp_read_dev(struct inode * inode, struct file * file,char *,int);static int dsp_write_dev(struct inode * inode, struct file * file,const char *,int);static int dsp_reset(struct cd *p);static int dsp_write(struct cd *d,unsigned char *buf,int count,int source);static int dsp_probe(struct cd *p);static void dsp_interrupt(int irq, void *dev_id, struct pt_regs *regs);static void dsp_init(struct cd *p, unsigned char *,int m);#define PSS_DATA      0x00#define PSS_STATUS    0x02#define PSS_CONTROL   0x02#define PSS_ID_VERS   0x04#define PSS_CONFIG 0x10#define WSS_CONFIG 0x12#define SB_CONFIG 0x14#define CD_CONFIG 0x16#define MIDI_CONFIG 0x18#define DSP_OPEN		0x1#define DSP_WRITE_READY	0x2#define DSP_RELEASE_WAIT 0x4static struct file_operations dsp_fops = {        NULL,        NULL,           /* read */        dsp_write_dev,	/* write */        NULL,           /* readdir */        NULL,           /* select */        NULL,        NULL,           /* lp_mmap */        dsp_open_dev,        dsp_release_dev};int debug = 0;#define NUM_DEV 1static struct cd devs[NUM_DEV];static int minor2dspnum[3] = { -1 , -1 , -1 };static int dsp_open_dev(struct inode * inode, struct file * file){	unsigned int minor = MINOR(inode->i_rdev);	int dspnum;	int i;	if(debug)		printk(KERN_DEBUG "dsp_open %d\n",minor);	if(minor < 0 || minor > 2) {		return -ENODEV;	}	for(i=0;i<3;i++)	/* currently, only one DSP supported */		if(minor2dspnum[i] >= 0)			return -EAGAIN;	minor2dspnum[minor] = 0;	dspnum = minor2dspnum[minor];	if(devs[dspnum].state)		return -EBUSY;    MOD_INC_USE_COUNT;	devs[dspnum].state = DSP_OPEN;	devs[dspnum].rsize = devs[dspnum].wsize = BUFFER_SIZE;	devs[dspnum].rpos = 0;	devs[dspnum].wpos = 0;	devs[dspnum].rbuf = 0;	devs[dspnum].wbuf = 0;	dsp_init(&devs[dspnum],dspcode,sizeof(dspcode));	return 0;}static void dsp_release_dev(struct inode * inode, struct file * file){	unsigned int minor = MINOR(inode->i_rdev);	int dspnum;	if(debug)		printk(KERN_DEBUG "dsp_release %d\n",minor);	if(minor < 0 || minor > 2) {		return;	}	dspnum = minor2dspnum[minor];	if(dspnum < 0 || !devs[dspnum].state)		return;	if(devs[dspnum].wpos > 0 && (devs[dspnum].wpos < devs[dspnum].wsize) )	/* buffer not empty */	{		char buf[1] = { 0 };		devs[dspnum].wsize = devs[dspnum].wpos + 1;		dsp_write(&devs[dspnum],buf,1,1);	}	devs[dspnum].state = DSP_RELEASE_WAIT;	while(devs[dspnum].wbuf != devs[dspnum].rbuf)		interruptible_sleep_on(&(devs[dspnum].waitq));	minor2dspnum[minor] = -1;	devs[dspnum].state = 0;#if 0	dsp_reset(devs[dspnum].dev);	wake_up_interruptible(&devs[dspnum].waitq);#endif	MOD_DEC_USE_COUNT;}static int dsp_write_dev(struct inode * inode, struct file * file,const char *buf , int count){	unsigned int minor = MINOR(inode->i_rdev);	struct cd *d;	int r,dspnum;	if(minor < 0 || minor > 2)		return -ENODEV;	dspnum = minor2dspnum[minor];    if(dspnum < 0 || !devs[dspnum].state)        return -ENXIO;    if ((r = verify_area(VERIFY_READ, (void *) buf, count)))       return r;	d = &devs[dspnum];	return dsp_write(d,(unsigned char *) buf,count,0);}static int dsp_write(struct cd *d,unsigned char *buf,int count,int source){	int cnt1 = count;	int pos = 0;	while(cnt1) {		if(d->wpos < d->wsize) {			int len = d->wsize - d->wpos;			if(len > cnt1)				len = cnt1;			if(debug)				printk("got %d bytes\n",len);			if(source)	        	memcpy(d->bufs[d->wbuf]+d->wpos,buf+pos,len);			else	        	memcpy_fromfs(d->bufs[d->wbuf]+d->wpos,buf+pos,len);			pos += len;			d->wpos += len;				cnt1 -= len;		}		if(d->wpos >= d->wsize) {			if(d->wbuf == d->rbuf) {				long flags;				d->wbuf++;				d->wbuf &= 0x1;				d->wpos = 0;				d->rpos = 0;				d->rsize = d->wsize;				d->wsize = BUFFER_SIZE;				save_flags(flags);				cli();				if( (inw(d->base_addr+PSS_STATUS) & 0x8000) ) {					unsigned short w;					w = d->bufs[d->rbuf][d->rpos]<<8;					w |= d->bufs[d->rbuf][d->rpos+1];					if(debug)						printk("initial write %02x\n",w);#if 0					outw(0x8000,d->base_addr+PSS_CONTROL);#endif					outw(w,d->base_addr+PSS_DATA);					d->rpos+=2;				}				restore_flags(flags);			}			else if(cnt1 > 0){		        interruptible_sleep_on(&(d->waitq));				if(debug)					printk("waked up %d %d\n",d->state,d->wpos);		        if(!d->state || d->wpos >= d->wsize)		            return 0;			}		}	}	return count;}static int dsp_read_dev(struct inode * inode, struct file * file, char *buf , int count){	unsigned int minor = MINOR(inode->i_rdev);	int dspnum;    if(minor < 0 || minor > 2) {        return -ENODEV;    }	dspnum = minor2dspnum[minor];    if(dspnum < 0 || !devs[dspnum].state)		return -ENXIO;	return 0;}int dsp_probe(struct cd *p){	static int irqtab[] = { -1,-1,-1,0x1,-1,0x2,-1,0x3,-1,0x4,0x5,0x6,0x7 ,-1,-1,-1 };	static int dmatab[] = { 0x1,0x2,-1,0x3,-1,0x5,0x6,0x7 };	unsigned short w;	int dspnum = 0;	p = &devs[dspnum];	outw(0,p->base_addr + PSS_CONFIG);	outw(0,p->base_addr + WSS_CONFIG);	outw(0,p->base_addr + SB_CONFIG);	outw(0,p->base_addr + CD_CONFIG);	outw(0,p->base_addr + MIDI_CONFIG);		/* Grab the region so that no one else tries to probe our ioports. */	if(p->dma <= 7 && dmatab[p->dma] < 0) {		printk("illegal DMA %d\n",p->dma);		return -EAGAIN;	}	if(p->irq < 0 || p->irq > 15 || irqtab[p->irq] < 0) {		printk("illegal IRQ %d\n",p->irq);		return -EAGAIN;	}	if(check_region(p->base_addr, 0x20 )) {		printk("dsp: region %#x-%#x in use.\n",p->base_addr,p->base_addr+0x20);#if 0		return -EAGAIN;#endif	}	request_region(p->base_addr, 0x20 ,"dsp");	if (request_irq(p->irq, &dsp_interrupt, 0, "dsp", NULL)) {		printk("Can't get IRQ %d\n",p->irq);		release_region(p->base_addr,0x20);		return -EAGAIN;	}		if(p->dma <= 7) {		if(request_dma(p->dma,"dsp")) {			printk("Can'T get DMA %d\n",p->dma);			free_irq(p->irq,NULL);			release_region(p->base_addr,0x20);			return -EAGAIN;		}		w = (irqtab[p->irq]<<3) | dmatab[p->dma];	}	else {		w = (irqtab[p->irq]<<3);	}	irq2dev_map[p->irq] = p;	outw(w,p->base_addr+PSS_CONFIG);	dsp_init(p,dspcode,sizeof(dspcode));	return 0;}static void dsp_interrupt(int irq, void *dev_id, struct pt_regs * regs){	struct cd *p = (struct cd *)(irq2dev_map[irq]);	int stat;	int fail = 32;	int mask = 0xf000;	if (p == NULL) {		printk(KERN_WARNING "%s: irq %d for unknown device.\n", "dsp" , irq);		return;	}	if(set_bit(0,&p->interrupt))		return;	stat=inw(p->base_addr+PSS_STATUS);    if(stat & 0x3000) {       outw(0x0,p->base_addr+0x4);    }    while( (stat & mask) && fail ) {		fail--;    	if(stat & 0x4000)	    {		  int k = inw(p->base_addr+PSS_DATA);          printk("dsp->%04x ",k);        }        if(stat & 0x8000)        {		  if(p->state && p->wbuf != p->rbuf) {              unsigned short w;              w = p->bufs[p->rbuf][p->rpos]<<8;              w |= p->bufs[p->rbuf][p->rpos+1];	          outw(w,p->base_addr+PSS_DATA);	          p->rpos+=2;			  if(p->rpos >= p->rsize) {				p->rbuf++;				p->rbuf &= 0x1;				p->rpos = 0;				if(p->wpos >= p->wsize) {					p->rsize = p->wsize;					p->wbuf++;					p->wbuf &= 0x1;					p->wpos = 0;					p->wsize = BUFFER_SIZE;				}				wake_up_interruptible(&(p->waitq));			  }		  }		  else {#if 0			mask = 0x7000;#endif		  }        }		stat=inw(p->base_addr+PSS_STATUS);	}	p->interrupt = 0;	return;}static int dsp_reset(struct cd *p){  int i;  outw (0x2000,p->base_addr + PSS_CONTROL);  for (i = 0; i < 32768 ; i++)    inw (p->base_addr + PSS_CONTROL);  outw (0x0000,p->base_addr + PSS_CONTROL);  return 1;}static void dsp_init(struct cd *p,unsigned char *block,int len ){   int i,j;	unsigned char *pnt1 = block;   dsp_reset(p);   outw(*block++,p->base_addr+PSS_DATA);   dsp_reset(p);   for(i=0;;i++)   {     for(j=0;j<100000;j++)       if(inw(p->base_addr+PSS_STATUS) & 0x800)         break;     if(j==100000)     {       printk("dsp TIMEOUT.\n");       break;     }     if(i == len-1)       break;     outw(*block++,p->base_addr+PSS_DATA);   }   printk("downloaded code: %d\n",block-pnt1);#if 0   outw(0x4000,p->base_addr+PSS_CONTROL);#endif   outw(0,p->base_addr+PSS_DATA);}#ifdef MODULEstatic int io = 0x220;static int irq = 10;static int dma = 255;int init_module(void){	int result,i;	/* Copy the parameters from insmod into the device structure. */	devs[0].base_addr = io;	devs[0].irq       = irq;	devs[0].dma       = dma;    for(i=0;i<NUM_DEV;i++)    {        devs[i].state = 0;        devs[i].waitq = NULL;    }	if (register_chrdev(DSP_MAJOR, "dsp", &dsp_fops)) {		printk(KERN_WARNING "dsp: Could not register control devices\n");		return -EIO;	}	result = dsp_probe(&devs[0]);	if(result) {		printk(KERN_ERR "dsp: Can't init board!\n");		unregister_chrdev(DSP_MAJOR,"dsp");		return result;	}	return result;}voidcleanup_module(void){	dsp_reset(&devs[0]);	free_irq(devs[0].irq, NULL);	if(devs[0].dma <= 7)		free_dma(devs[0].dma);	irq2dev_map[devs[0].irq] = 0;	unregister_chrdev(DSP_MAJOR,"dsp");	if(devs[0].base_addr)		release_region(devs[0].base_addr, 0x20);}#endif /* MODULE */

⌨️ 快捷键说明

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