ixj.c

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

C
2,169
字号
static void ixj_play_stop(IXJ *j);static int ixj_set_tone_on(unsigned short arg, IXJ *j);static int ixj_set_tone_off(unsigned short, IXJ *j);static int ixj_play_tone(IXJ *j, char tone);static void ixj_aec_start(IXJ *j, int level);static int idle(IXJ *j);static void ixj_ring_on(IXJ *j);static void ixj_ring_off(IXJ *j);static void aec_stop(IXJ *j);static void ixj_ringback(IXJ *j);static void ixj_busytone(IXJ *j);static void ixj_dialtone(IXJ *j);static void ixj_cpt_stop(IXJ *j);static char daa_int_read(IXJ *j);static char daa_CR_read(IXJ *j, int cr);static int daa_set_mode(IXJ *j, int mode);static int ixj_linetest(IXJ *j);static int ixj_daa_write(IXJ *j);static int ixj_daa_cid_read(IXJ *j);static void DAA_Coeff_US(IXJ *j);static void DAA_Coeff_UK(IXJ *j);static void DAA_Coeff_France(IXJ *j);static void DAA_Coeff_Germany(IXJ *j);static void DAA_Coeff_Australia(IXJ *j);static void DAA_Coeff_Japan(IXJ *j);static int ixj_init_filter(IXJ *j, IXJ_FILTER * jf);static int ixj_init_filter_raw(IXJ *j, IXJ_FILTER_RAW * jfr);static int ixj_init_tone(IXJ *j, IXJ_TONE * ti);static int ixj_build_cadence(IXJ *j, IXJ_CADENCE __user * cp);static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp);/* Serial Control Interface funtions */static int SCI_Control(IXJ *j, int control);static int SCI_Prepare(IXJ *j);static int SCI_WaitHighSCI(IXJ *j);static int SCI_WaitLowSCI(IXJ *j);static DWORD PCIEE_GetSerialNumber(WORD wAddress);static int ixj_PCcontrol_wait(IXJ *j);static void ixj_pre_cid(IXJ *j);static void ixj_write_cid(IXJ *j);static void ixj_write_cid_bit(IXJ *j, int bit);static int set_base_frame(IXJ *j, int size);static int set_play_codec(IXJ *j, int rate);static void set_rec_depth(IXJ *j, int depth);static int ixj_mixer(long val, IXJ *j);/************************************************************************CT8020/CT8021 Host Programmers ModelHost address	Function					AccessDSPbase +0-1		Aux Software Status Register (reserved)		Read Only2-3		Software Status Register			Read Only4-5		Aux Software Control Register (reserved)	Read Write6-7		Software Control Register			Read Write8-9		Hardware Status Register			Read OnlyA-B		Hardware Control Register			Read WriteC-D Host Transmit (Write) Data Buffer Access Port (buffer input)Write OnlyE-F Host Recieve (Read) Data Buffer Access Port (buffer input)	Read Only************************************************************************/static inline void ixj_read_HSR(IXJ *j){	j->hsr.bytes.low = inb_p(j->DSPbase + 8);	j->hsr.bytes.high = inb_p(j->DSPbase + 9);}static inline int IsControlReady(IXJ *j){	ixj_read_HSR(j);	return j->hsr.bits.controlrdy ? 1 : 0;}static inline int IsPCControlReady(IXJ *j){	j->pccr1.byte = inb_p(j->XILINXbase + 3);	return j->pccr1.bits.crr ? 1 : 0;}static inline int IsStatusReady(IXJ *j){	ixj_read_HSR(j);	return j->hsr.bits.statusrdy ? 1 : 0;}static inline int IsRxReady(IXJ *j){	ixj_read_HSR(j);	ixj_perfmon(j->rxreadycheck);	return j->hsr.bits.rxrdy ? 1 : 0;}static inline int IsTxReady(IXJ *j){	ixj_read_HSR(j);	ixj_perfmon(j->txreadycheck);	return j->hsr.bits.txrdy ? 1 : 0;}static inline void set_play_volume(IXJ *j, int volume){	if (ixjdebug & 0x0002)		printk(KERN_INFO "IXJ: /dev/phone%d Setting Play Volume to 0x%4.4x\n", j->board, volume);	ixj_WriteDSPCommand(0xCF02, j);	ixj_WriteDSPCommand(volume, j);}static int set_play_volume_linear(IXJ *j, int volume){	int newvolume, dspplaymax;	if (ixjdebug & 0x0002)		printk(KERN_INFO "IXJ: /dev/phone %d Setting Linear Play Volume to 0x%4.4x\n", j->board, volume);	if(volume > 100 || volume < 0) {		return -1;	}	/* This should normalize the perceived volumes between the different cards caused by differences in the hardware */	switch (j->cardtype) {	case QTI_PHONEJACK:		dspplaymax = 0x380;		break;	case QTI_LINEJACK:		if(j->port == PORT_PSTN) {			dspplaymax = 0x48;		} else {			dspplaymax = 0x100;		}		break;	case QTI_PHONEJACK_LITE:		dspplaymax = 0x380;		break;	case QTI_PHONEJACK_PCI:		dspplaymax = 0x6C;		break;	case QTI_PHONECARD:		dspplaymax = 0x50;		break;	default:		return -1;	}	newvolume = (dspplaymax * volume) / 100;	set_play_volume(j, newvolume);	return 0;}static inline void set_play_depth(IXJ *j, int depth){	if (depth > 60)		depth = 60;	if (depth < 0)		depth = 0;	ixj_WriteDSPCommand(0x5280 + depth, j);}static inline int get_play_volume(IXJ *j){	ixj_WriteDSPCommand(0xCF00, j);	return j->ssr.high << 8 | j->ssr.low;}static int get_play_volume_linear(IXJ *j){	int volume, newvolume, dspplaymax;	/* This should normalize the perceived volumes between the different cards caused by differences in the hardware */	switch (j->cardtype) {	case QTI_PHONEJACK:		dspplaymax = 0x380;		break;	case QTI_LINEJACK:		if(j->port == PORT_PSTN) {			dspplaymax = 0x48;		} else {			dspplaymax = 0x100;		}		break;	case QTI_PHONEJACK_LITE:		dspplaymax = 0x380;		break;	case QTI_PHONEJACK_PCI:		dspplaymax = 0x6C;		break;	case QTI_PHONECARD:		dspplaymax = 100;		break;	default:		return -1;	}	volume = get_play_volume(j);	newvolume = (volume * 100) / dspplaymax;	if(newvolume > 100)		newvolume = 100;	return newvolume;}static inline BYTE SLIC_GetState(IXJ *j){	if (j->cardtype == QTI_PHONECARD) {		j->pccr1.byte = 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;		ixj_PCcontrol_wait(j);		if (j->pslic.bits.powerdown)			return PLD_SLIC_STATE_OC;		else if (!j->pslic.bits.ring0 && !j->pslic.bits.ring1)			return PLD_SLIC_STATE_ACTIVE;		else			return PLD_SLIC_STATE_RINGING;	} else {		j->pld_slicr.byte = inb_p(j->XILINXbase + 0x01);	}	return j->pld_slicr.bits.state;}static bool SLIC_SetState(BYTE byState, IXJ *j){	bool fRetVal = false;	if (j->cardtype == QTI_PHONECARD) {		if (j->flags.pcmciasct) {			switch (byState) {			case PLD_SLIC_STATE_TIPOPEN:			case PLD_SLIC_STATE_OC:				j->pslic.bits.powerdown = 1;				j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0;				fRetVal = true;				break;			case PLD_SLIC_STATE_RINGING:				if (j->readers || j->writers) {					j->pslic.bits.powerdown = 0;					j->pslic.bits.ring0 = 1;					j->pslic.bits.ring1 = 0;					fRetVal = true;				}				break;			case PLD_SLIC_STATE_OHT:	/* On-hook transmit */			case PLD_SLIC_STATE_STANDBY:			case PLD_SLIC_STATE_ACTIVE:				if (j->readers || j->writers) {					j->pslic.bits.powerdown = 0;				} else {					j->pslic.bits.powerdown = 1;				}				j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0;				fRetVal = true;				break;			case PLD_SLIC_STATE_APR:	/* Active polarity reversal */			case PLD_SLIC_STATE_OHTPR:	/* OHT polarity reversal */			default:				fRetVal = false;				break;			}			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);		}	} else {		/* Set the C1, C2, C3 & B2EN signals. */		switch (byState) {		case PLD_SLIC_STATE_OC:			j->pld_slicw.bits.c1 = 0;			j->pld_slicw.bits.c2 = 0;			j->pld_slicw.bits.c3 = 0;			j->pld_slicw.bits.b2en = 0;			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);			fRetVal = true;			break;		case PLD_SLIC_STATE_RINGING:			j->pld_slicw.bits.c1 = 1;			j->pld_slicw.bits.c2 = 0;			j->pld_slicw.bits.c3 = 0;			j->pld_slicw.bits.b2en = 1;			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);			fRetVal = true;			break;		case PLD_SLIC_STATE_ACTIVE:			j->pld_slicw.bits.c1 = 0;			j->pld_slicw.bits.c2 = 1;			j->pld_slicw.bits.c3 = 0;			j->pld_slicw.bits.b2en = 0;			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);			fRetVal = true;			break;		case PLD_SLIC_STATE_OHT:	/* On-hook transmit */			j->pld_slicw.bits.c1 = 1;			j->pld_slicw.bits.c2 = 1;			j->pld_slicw.bits.c3 = 0;			j->pld_slicw.bits.b2en = 0;			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);			fRetVal = true;			break;		case PLD_SLIC_STATE_TIPOPEN:			j->pld_slicw.bits.c1 = 0;			j->pld_slicw.bits.c2 = 0;			j->pld_slicw.bits.c3 = 1;			j->pld_slicw.bits.b2en = 0;			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);			fRetVal = true;			break;		case PLD_SLIC_STATE_STANDBY:			j->pld_slicw.bits.c1 = 1;			j->pld_slicw.bits.c2 = 0;			j->pld_slicw.bits.c3 = 1;			j->pld_slicw.bits.b2en = 1;			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);			fRetVal = true;			break;		case PLD_SLIC_STATE_APR:	/* Active polarity reversal */			j->pld_slicw.bits.c1 = 0;			j->pld_slicw.bits.c2 = 1;			j->pld_slicw.bits.c3 = 1;			j->pld_slicw.bits.b2en = 0;			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);			fRetVal = true;			break;		case PLD_SLIC_STATE_OHTPR:	/* OHT polarity reversal */			j->pld_slicw.bits.c1 = 1;			j->pld_slicw.bits.c2 = 1;			j->pld_slicw.bits.c3 = 1;			j->pld_slicw.bits.b2en = 0;			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);			fRetVal = true;			break;		default:			fRetVal = false;			break;		}	}	return fRetVal;}static int ixj_wink(IXJ *j){	BYTE slicnow;	slicnow = SLIC_GetState(j);	j->pots_winkstart = jiffies;	SLIC_SetState(PLD_SLIC_STATE_OC, j);	msleep(jiffies_to_msecs(j->winktime));	SLIC_SetState(slicnow, j);	return 0;}static void ixj_init_timer(IXJ *j){	init_timer(&j->timer);	j->timer.function = ixj_timeout;	j->timer.data = (unsigned long)j;}static void ixj_add_timer(IXJ *j){	j->timer.expires = jiffies + (hertz / samplerate);	add_timer(&j->timer);}static void ixj_tone_timeout(IXJ *j){	IXJ_TONE ti;	j->tone_state++;	if (j->tone_state == 3) {		j->tone_state = 0;		if (j->cadence_t) {			j->tone_cadence_state++;			if (j->tone_cadence_state >= j->cadence_t->elements_used) {				switch (j->cadence_t->termination) {				case PLAY_ONCE:					ixj_cpt_stop(j);					break;				case REPEAT_LAST_ELEMENT:					j->tone_cadence_state--;					ixj_play_tone(j, j->cadence_t->ce[j->tone_cadence_state].index);					break;				case REPEAT_ALL:					j->tone_cadence_state = 0;					if (j->cadence_t->ce[j->tone_cadence_state].freq0) {						ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index;						ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0;						ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;						ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1;						ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1;						ixj_init_tone(j, &ti);					}					ixj_set_tone_on(j->cadence_t->ce[0].tone_on_time, j);					ixj_set_tone_off(j->cadence_t->ce[0].tone_off_time, j);					ixj_play_tone(j, j->cadence_t->ce[0].index);					break;				}			} else {				if (j->cadence_t->ce[j->tone_cadence_state].gain0) {					ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index;					ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0;					ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;					ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1;					ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1;					ixj_init_tone(j, &ti);				}				ixj_set_tone_on(j->cadence_t->ce[j->tone_cadence_state].tone_on_time, j);				ixj_set_tone_off(j->cadence_t->ce[j->tone_cadence_state].tone_off_time, j);				ixj_play_tone(j, j->cadence_t->ce[j->tone_cadence_state].index);			}		}	}}static inline void ixj_kill_fasync(IXJ *j, IXJ_SIGEVENT event, int dir){	if(j->ixj_signals[event]) {		if(ixjdebug & 0x0100)			printk("Sending signal for event %d\n", event);			/* Send apps notice of change */		/* see config.h for macro definition */		kill_fasync(&(j->async_queue), j->ixj_signals[event], dir);	}}static void ixj_pstn_state(IXJ *j){	int var;	union XOPXR0 XR0, daaint;

⌨️ 快捷键说明

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