📄 ixj.c
字号:
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 * cp);static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE * 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); while (time_before(jiffies, j->pots_winkstart + j->winktime)) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); } SLIC_SetState(slicnow, j); return 0;}static int ixj_register(int index, IXJ_REGFUNC regfunc){ int cnt; int retval = 0; switch (index) { case G729LOADER: ixj_DownloadG729 = regfunc; for (cnt = 0; cnt < IXJMAX; cnt++) { IXJ *j = get_ixj(cnt); while(test_and_set_bit(cnt, (void *)&j->busyflags) != 0) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); } ixj_DownloadG729(j, 0L); clear_bit(cnt, &j->busyflags); } break; case TS85LOADER: ixj_DownloadTS85 = regfunc; for (cnt = 0; cnt < IXJMAX; cnt++) { IXJ *j = get_ixj(cnt); while(test_and_set_bit(cnt, (void *)&j->busyflags) != 0) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); } ixj_DownloadTS85(j, 0L); clear_bit(cnt, &j->busyflags); } break; case PRE_READ: ixj_PreRead = regfunc; break; case POST_READ: ixj_PostRead = regfunc; break; case PRE_WRITE: ixj_PreWrite = regfunc; break; case POST_WRITE: ixj_PostWrite = regfunc; break; case PRE_IOCTL: ixj_PreIoctl = regfunc; break; case POST_IOCTL: ixj_PostIoctl = regfunc; break; default: retval = 1; } return retval;}EXPORT_SYMBOL(ixj_register);static int ixj_unregister(int index){ int retval = 0; switch (index) { case G729LOADER: ixj_DownloadG729 = &Stub; break; case TS85LOADER: ixj_DownloadTS85 = &Stub; break; case PRE_READ: ixj_PreRead = &Stub; break; case POST_READ: ixj_PostRead = &Stub; break; case PRE_WRITE: ixj_PreWrite = &Stub; break; case POST_WRITE: ixj_PostWrite = &Stub; break; case PRE_IOCTL:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -