ixj.c

来自「linux 内核源代码」· C语言 代码 · 共 2,169 行 · 第 1/5 页

C
2,169
字号
}static int ixj_sidac(IXJ *j, int val){	if(j->cardtype == QTI_PHONECARD){		if(j->flags.pcmciascp){			if(val == -1)				return j->sidac.bits.txg;			if(val < 0 || val > 0x1F)				return -1;			j->sidac.bits.srm = 1;				/* Speaker Right Mute */			j->sidac.bits.slm = 1;				/* Speaker Left Mute */			j->sidac.bits.txg = val;			/* (0xC000 - 0x45E4) / 0x5D3;	 TX PGA Gain */			j->psccr.bits.addr = 7;				/* R/W Smart Cable Register Address */			j->psccr.bits.rw = 0;				/* Read / Write flag */			j->psccr.bits.dev = 0;			outb(j->sidac.byte, j->XILINXbase + 0x00);			outb(j->psccr.byte, j->XILINXbase + 0x01);			ixj_PCcontrol_wait(j);			return j->sidac.bits.txg;		}	}	return -1;}static int ixj_pcmcia_cable_check(IXJ *j){	j->pccr1.byte = inb_p(j->XILINXbase + 0x03);	if (!j->flags.pcmciastate) {		j->pccr2.byte = inb_p(j->XILINXbase + 0x02);		if (j->pccr1.bits.drf || j->pccr2.bits.rstc) {			j->flags.pcmciastate = 4;			return 0;		}		if (j->pccr1.bits.ed) {			j->pccr1.bits.ed = 0;			j->psccr.bits.dev = 3;			j->psccr.bits.rw = 1;			outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00);			ixj_PCcontrol_wait(j);			j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF;			j->pslic.bits.led2 = j->pslic.bits.det ? 1 : 0;			j->psccr.bits.dev = 3;			j->psccr.bits.rw = 0;			outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);			ixj_PCcontrol_wait(j);			return j->pslic.bits.led2 ? 1 : 0;		} else if (j->flags.pcmciasct) {			return j->r_hook;		} else {			return 1;		}	} else if (j->flags.pcmciastate == 4) {		if (!j->pccr1.bits.drf) {			j->flags.pcmciastate = 3;		}		return 0;	} else if (j->flags.pcmciastate == 3) {		j->pccr2.bits.pwr = 0;		j->pccr2.bits.rstc = 1;		outb(j->pccr2.byte, j->XILINXbase + 0x02);		j->checkwait = jiffies + (hertz * 2);		j->flags.incheck = 1;		j->flags.pcmciastate = 2;		return 0;	} else if (j->flags.pcmciastate == 2) {		if (j->flags.incheck) {			if (time_before(jiffies, j->checkwait)) {				return 0;			} else {				j->flags.incheck = 0;			}		}		j->pccr2.bits.pwr = 0;		j->pccr2.bits.rstc = 0;		outb_p(j->pccr2.byte, j->XILINXbase + 0x02);		j->flags.pcmciastate = 1;		return 0;	} else if (j->flags.pcmciastate == 1) {		j->flags.pcmciastate = 0;		if (!j->pccr1.bits.drf) {			j->psccr.bits.dev = 3;			j->psccr.bits.rw = 1;			outb_p(j->psccr.byte, j->XILINXbase + 0x01);			ixj_PCcontrol_wait(j);			j->flags.pcmciascp = 1;		/* Set Cable Present Flag */			j->flags.pcmciasct = (inw_p(j->XILINXbase + 0x00) >> 8) & 0x03;		/* Get Cable Type */			if (j->flags.pcmciasct == 3) {				j->flags.pcmciastate = 4;				return 0;			} else if (j->flags.pcmciasct == 0) {				j->pccr2.bits.pwr = 1;				j->pccr2.bits.rstc = 0;				outb_p(j->pccr2.byte, j->XILINXbase + 0x02);				j->port = PORT_SPEAKER;			} else {				j->port = PORT_POTS;			}			j->sic1.bits.cpd = 0;				/* Chip Power Down */			j->sic1.bits.mpd = 0;				/* MIC Bias Power Down */			j->sic1.bits.hpd = 0;				/* Handset Bias Power Down */			j->sic1.bits.lpd = 0;				/* Line Bias Power Down */			j->sic1.bits.spd = 1;				/* Speaker Drive Power Down */			j->psccr.bits.addr = 1;				/* R/W Smart Cable Register Address */			j->psccr.bits.rw = 0;				/* Read / Write flag */			j->psccr.bits.dev = 0;			outb(j->sic1.byte, j->XILINXbase + 0x00);			outb(j->psccr.byte, j->XILINXbase + 0x01);			ixj_PCcontrol_wait(j);			j->sic2.bits.al = 0;				/* Analog Loopback DAC analog -> ADC analog */			j->sic2.bits.dl2 = 0;				/* Digital Loopback DAC -> ADC one bit */			j->sic2.bits.dl1 = 0;				/* Digital Loopback ADC -> DAC one bit */			j->sic2.bits.pll = 0;				/* 1 = div 10, 0 = div 5 */			j->sic2.bits.hpd = 0;				/* HPF disable */			j->psccr.bits.addr = 2;				/* R/W Smart Cable Register Address */			j->psccr.bits.rw = 0;				/* Read / Write flag */			j->psccr.bits.dev = 0;			outb(j->sic2.byte, j->XILINXbase + 0x00);			outb(j->psccr.byte, j->XILINXbase + 0x01);			ixj_PCcontrol_wait(j);			j->psccr.bits.addr = 3;				/* R/W Smart Cable Register Address */			j->psccr.bits.rw = 0;				/* Read / Write flag */			j->psccr.bits.dev = 0;			outb(0x00, j->XILINXbase + 0x00);		/* PLL Divide N1 */			outb(j->psccr.byte, j->XILINXbase + 0x01);			ixj_PCcontrol_wait(j);			j->psccr.bits.addr = 4;				/* R/W Smart Cable Register Address */			j->psccr.bits.rw = 0;				/* Read / Write flag */			j->psccr.bits.dev = 0;			outb(0x09, j->XILINXbase + 0x00);		/* PLL Multiply M1 */			outb(j->psccr.byte, j->XILINXbase + 0x01);			ixj_PCcontrol_wait(j);			j->sirxg.bits.lig = 1;				/* Line In Gain */			j->sirxg.bits.lim = 1;				/* Line In Mute */			j->sirxg.bits.mcg = 0;				/* MIC In Gain was 3 */			j->sirxg.bits.mcm = 0;				/* MIC In Mute */			j->sirxg.bits.him = 0;				/* Handset In Mute */			j->sirxg.bits.iir = 1;				/* IIR */			j->psccr.bits.addr = 5;				/* R/W Smart Cable Register Address */			j->psccr.bits.rw = 0;				/* Read / Write flag */			j->psccr.bits.dev = 0;			outb(j->sirxg.byte, j->XILINXbase + 0x00);			outb(j->psccr.byte, j->XILINXbase + 0x01);			ixj_PCcontrol_wait(j);			ixj_siadc(j, 0x17);			ixj_sidac(j, 0x1D);			j->siaatt.bits.sot = 0;			j->psccr.bits.addr = 9;				/* R/W Smart Cable Register Address */			j->psccr.bits.rw = 0;				/* Read / Write flag */			j->psccr.bits.dev = 0;			outb(j->siaatt.byte, j->XILINXbase + 0x00);			outb(j->psccr.byte, j->XILINXbase + 0x01);			ixj_PCcontrol_wait(j);			if (j->flags.pcmciasct == 1 && !j->readers && !j->writers) {				j->psccr.byte = j->pslic.byte = 0;				j->pslic.bits.powerdown = 1;				j->psccr.bits.dev = 3;				j->psccr.bits.rw = 0;				outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);				ixj_PCcontrol_wait(j);			}		}		return 0;	} else {		j->flags.pcmciascp = 0;		return 0;	}	return 0;}static int ixj_hookstate(IXJ *j){	int fOffHook = 0;	switch (j->cardtype) {	case QTI_PHONEJACK:		ixj_gpio_read(j);		fOffHook = j->gpio.bits.gpio3read ? 1 : 0;		break;	case QTI_LINEJACK:	case QTI_PHONEJACK_LITE:	case QTI_PHONEJACK_PCI:		SLIC_GetState(j);		if(j->cardtype == QTI_LINEJACK && j->flags.pots_pstn == 1 && (j->readers || j->writers)) {			fOffHook = j->pld_slicr.bits.potspstn ? 1 : 0;			if(fOffHook != j->p_hook) {				if(!j->checkwait) {					j->checkwait = jiffies;				} 				if(time_before(jiffies, j->checkwait + 2)) {					fOffHook ^= 1;				} else {					j->checkwait = 0;				}				j->p_hook = fOffHook;	 			printk("IXJ : /dev/phone%d pots-pstn hookstate check %d at %ld\n", j->board, fOffHook, jiffies);			}		} else {			if (j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE ||			    j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) {				if (j->flags.ringing || j->flags.cringing) {					if (!in_interrupt()) {						msleep(20);					}					SLIC_GetState(j);					if (j->pld_slicr.bits.state == PLD_SLIC_STATE_RINGING) {						ixj_ring_on(j);					}				}				if (j->cardtype == QTI_PHONEJACK_PCI) {					j->pld_scrr.byte = inb_p(j->XILINXbase);					fOffHook = j->pld_scrr.pcib.det ? 1 : 0;				} else					fOffHook = j->pld_slicr.bits.det ? 1 : 0;			}		}		break;	case QTI_PHONECARD:		fOffHook = ixj_pcmcia_cable_check(j);		break;	}	if (j->r_hook != fOffHook) {		j->r_hook = fOffHook;		if (j->port == PORT_SPEAKER || j->port == PORT_HANDSET) { // || (j->port == PORT_PSTN && j->flags.pots_pstn == 0)) {			j->ex.bits.hookstate = 1;			ixj_kill_fasync(j, SIG_HOOKSTATE, POLL_IN);		} else if (!fOffHook) {			j->flash_end = jiffies + ((60 * hertz) / 100);		}	}	if (fOffHook) {		if(time_before(jiffies, j->flash_end)) {			j->ex.bits.flash = 1;			j->flash_end = 0;			ixj_kill_fasync(j, SIG_FLASH, POLL_IN);		}	} else {		if(time_before(jiffies, j->flash_end)) {			fOffHook = 1;		}	}	if (j->port == PORT_PSTN && j->daa_mode == SOP_PU_CONVERSATION)		fOffHook |= 2;	if (j->port == PORT_SPEAKER) {		if(j->cardtype == QTI_PHONECARD) {			if(j->flags.pcmciascp && j->flags.pcmciasct) {				fOffHook |= 2;			}		} else {			fOffHook |= 2;		}	}	if (j->port == PORT_HANDSET)		fOffHook |= 2;	return fOffHook;}static void ixj_ring_off(IXJ *j){	if (j->dsp.low == 0x20)	/* Internet PhoneJACK */	 {		if (ixjdebug & 0x0004)			printk(KERN_INFO "IXJ Ring Off\n");		j->gpio.bytes.high = 0x0B;		j->gpio.bytes.low = 0x00;		j->gpio.bits.gpio1 = 0;		j->gpio.bits.gpio2 = 1;		j->gpio.bits.gpio5 = 0;		ixj_WriteDSPCommand(j->gpio.word, j);	} else			/* Internet LineJACK */	{		if (ixjdebug & 0x0004)			printk(KERN_INFO "IXJ Ring Off\n");		if(!j->flags.cidplay)			SLIC_SetState(PLD_SLIC_STATE_STANDBY, j);		SLIC_GetState(j);	}}static void ixj_ring_start(IXJ *j){	j->flags.cringing = 1;	if (ixjdebug & 0x0004)		printk(KERN_INFO "IXJ Cadence Ringing Start /dev/phone%d\n", j->board);	if (ixj_hookstate(j) & 1) {		if (j->port == PORT_POTS)			ixj_ring_off(j);		j->flags.cringing = 0;		if (ixjdebug & 0x0004)			printk(KERN_INFO "IXJ Cadence Ringing Stopped /dev/phone%d off hook\n", j->board);	} else if(j->cadence_f[5].enable && (!j->cadence_f[5].en_filter)) {		j->ring_cadence_jif = jiffies;		j->flags.cidsent = j->flags.cidring = 0;		j->cadence_f[5].state = 0;		if(j->cadence_f[5].on1)			ixj_ring_on(j);	} else {		j->ring_cadence_jif = jiffies;		j->ring_cadence_t = 15;		if (j->ring_cadence & 1 << j->ring_cadence_t) {			ixj_ring_on(j);		} else {			ixj_ring_off(j);		}		j->flags.cidsent = j->flags.cidring = j->flags.firstring = 0;	}}static int ixj_ring(IXJ *j){	char cntr;	unsigned long jif;	j->flags.ringing = 1;	if (ixj_hookstate(j) & 1) {		ixj_ring_off(j);		j->flags.ringing = 0;		return 1;	}	for (cntr = 0; cntr < j->maxrings; cntr++) {		jif = jiffies + (1 * hertz);		ixj_ring_on(j);		while (time_before(jiffies, jif)) {			if (ixj_hookstate(j) & 1) {				ixj_ring_off(j);				j->flags.ringing = 0;				return 1;			}			schedule_timeout_interruptible(1);			if (signal_pending(current))				break;		}		jif = jiffies + (3 * hertz);		ixj_ring_off(j);		while (time_before(jiffies, jif)) {			if (ixj_hookstate(j) & 1) {				msleep(10);				if (ixj_hookstate(j) & 1) {					j->flags.ringing = 0;					return 1;				}			}			schedule_timeout_interruptible(1);			if (signal_pending(current))				break;		}	}	ixj_ring_off(j);	j->flags.ringing = 0;	return 0;}static int ixj_open(struct phone_device *p, struct file *file_p){	IXJ *j = get_ixj(p->board);	file_p->private_data = j;	if (!j->DSPbase)		return -ENODEV;        if (file_p->f_mode & FMODE_READ) {		if(!j->readers) {	                j->readers++;        	} else {                	return -EBUSY;		}        }	if (file_p->f_mode & FMODE_WRITE) {		if(!j->writers) {			j->writers++;		} else {			if (file_p->f_mode & FMODE_READ){				j->readers--;			}			return -EBUSY;		}	}	if (j->cardtype == QTI_PHONECARD) {		j->pslic.bits.powerdown = 0;		j->psccr.bits.dev = 3;		j->psccr.bits.rw = 0;		outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);		ixj_PCcontrol_wait(j);	}	j->flags.cidplay = 0;	j->flags.cidcw_ack = 0;	if (ixjdebug & 0x0002)		printk(KERN_INFO "Opening board %d\n", p->board);	j->framesread = j->frameswritten = 0;	return 0;}static int ixj_release(struct inode *inode, struct file *file_p){	IXJ_TONE ti;	int cnt;	IXJ *j = file_p->private_data;	int board = j->p.board;	/*	 *    Set up locks to ensure that only one process is talking to the DSP at a time.	 *    This is necessary to keep the DSP from locking up.	 */	while(test_and_set_bit(board, (void *)&j->busyflags) != 0)		schedule_timeout_interruptible(1);	if (ixjdebug & 0x0002)		printk(KERN_INFO "Closing board %d\n", NUM(inode));	if (j->cardtype == QTI_PHONECARD)		ixj_set_port(j, PORT_SPEAKER);	el

⌨️ 快捷键说明

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