📄 clm_dspdrv.c
字号:
/* * CLModem v0.3.0 - Low level DSP routines * * Copyright (C) 2000 Mikhail Moreyra * * This file may be redistributed under the terms of the GNU Public * License. */#define __NO_VERSION__#include <linux/kernel.h>#include <linux/module.h>#include <linux/wrapper.h>#include <asm/io.h>#include <asm/irq.h>#include "clm_config.h"#include "clm_data.h"#include "clm_dspdrv.h"#include "clm_modem.h"#define BUF_SIZE 4096extern int BaseIOAddress;extern int modem_irq;unsigned char current_command[40];unsigned char dsp_response_data[16];unsigned char Cdata[64];int hook = 1;int spkr_volume_level = 0;int spkr_on = 0;int _dsp_timer;volatile int dsp_done;int mt_x2_connection;int mt_v90_connection;int ack_or_response;int mt_v90_configured;volatile int v8_configured = 0;unsigned char line_mode = 0;unsigned short mt_RateSeq1;unsigned short mt_RateSeq2;unsigned short mt_RateSeq3;unsigned short mt_rate_seq_map, mt_set_rate_seq_param3;int mt_conn_orig = 1;int line_bit_rate;int call_progress_state = 0;int PcmEnabled = 0;int mt_IdleSendPwron = 0;volatile int mt_RingState = 0;char mt_call_progress;volatile char line_io_enabled = 0;volatile char dce_length_semaphore = 0;volatile char dce_status_semaphore = 0;volatile int dce_tx_count = 0;volatile int dce_rx_count = 0;volatile int dce_tx_interrupt_expected = 0;volatile unsigned char dce_tx_buffer[BUF_SIZE];volatile unsigned char dce_rx_buffer[BUF_SIZE];volatile int dce_tx_remove = 0;volatile int dce_rx_insert = 0;volatile int dte_rx_remove = 0;volatile int dte_tx_insert = 0;volatile int stat_tx_count = 0;volatile int stat_rx_count = 0;int dce_rx_errors = 0;unsigned char v8_tx_buffer[32];int sending_CM, sending_JM;int JM_received, CM_received;int CM_count, JM_count;unsigned char v8_tx_msg_size;volatile int jm_seq_match;int v8_status, length, old_length;int ci_count, v8_rx_msg_size;int RX_stat[32];int TX_stat[32];volatile int critical = 0;/* ************************************************ */void cmd_packet_callback(unsigned char x);void mt_CallProgressCallback(void);void line_int(void);void line_rx_int(void);void line_tx_int(void);void sync_rx_int(void);void sync_tx_int(void);void v8_rx_int(void);void v8_tx_int(void);/* ************************************************ */voidset_register(int reg, unsigned char val){ outb (val, BaseIOAddress + reg);}unsigned charget_register(int reg){ return inb (BaseIOAddress + reg);}/*************************************************//* INTERRUPT HANDLER *//*************************************************/voiddspdrv_CommRamHandler(void){ unsigned char x, rv; rv = get_register (0x0); if (rv) { x = dspdrv_GetCRAM (Cdata); cmd_packet_callback (x); }}voiddspdrv_CommRamISR(void){ critical = 1; get_register (0xff); dspdrv_CommRamHandler(); line_int(); critical = 0;}voidcmd_packet_callback (unsigned char x){ if (x == 0xd1) mt_CallProgressCallback(); else dsp_done = 1;}voidmt_CallProgressCallback(void){ static short LastTimeStamp = 0; short nt, xt, dt; int x; if (Cdata[4] != 1) return; nt = (Cdata[7] << 8) | Cdata[6]; xt = (Cdata[9] << 8) | Cdata[8]; if (nt > LastTimeStamp) dt = nt - LastTimeStamp; else { dt = nt - LastTimeStamp; dt += 0x1aab; } /* Dbg("Ring time: %2d - dtime: %4d -- ", xt, dt); */ if (xt) { if (dt) x = (xt * 0x3e8) / dt; else x = 0; if ((x >= 0xf) && (x <= 0x44)) mt_RingState = 7; else mt_RingState = 0; /* Dbg("Ring length= %d -- ", x); */ } else { if (mt_RingState == 2) mt_RingState = 0; else mt_RingState = 2; } Msg("RingState = %d\n", mt_RingState); LastTimeStamp = nt;}/* CRAM_CallBack */voidline_int(void){ if (line_io_enabled == 0) return; dspdrv_ReadCram(0x34, &dce_length_semaphore, 1); dspdrv_ReadCram(0x35, &dce_status_semaphore, 1); if (dce_status_semaphore) dspdrv_ReadCram(0x34, &dce_length_semaphore, 1);#if 1 if (dce_status_semaphore>1) Dbg("RX StSem: %#x\n", dce_status_semaphore);#endif if (dce_length_semaphore || dce_status_semaphore) line_rx_int(); dspdrv_ReadCram(0x74, &dce_length_semaphore, 1); dspdrv_ReadCram(0x75, &dce_status_semaphore, 1);#if 1 if (dce_status_semaphore>1) Dbg("TX StSem: %#x\n", dce_status_semaphore);#endif if ((dce_length_semaphore == 0) && (dce_status_semaphore == 0)) line_tx_int();}voidline_rx_int(void){ if (v8_configured) v8_rx_int(); else sync_rx_int();}voidline_tx_int(void){ if (v8_configured) v8_tx_int(); else sync_tx_int();}voidsync_rx_int(void){ char reg = 0x14; if (dce_status_semaphore == 6) { /* Msg("RX Error\n"); */ dce_rx_errors++; } RX_stat[(int)dce_length_semaphore-1]++; if (dce_length_semaphore > 32) Dbg("ERROR: dce_length_semaphore > 32\n"); while (dce_length_semaphore) { dspdrv_ReadCram(reg++, &dce_rx_buffer[dce_rx_insert], 1); if (dce_rx_count < BUF_SIZE) { dce_rx_insert++; dce_rx_count++; stat_rx_count++; if (dce_rx_insert == BUF_SIZE) dce_rx_insert = 0; } else Dbg("ERROR: RX buffer full\n"); dce_length_semaphore--; } dce_status_semaphore = 0; dspdrv_WriteCram(0x34, &dce_length_semaphore, 1); dspdrv_WriteCram(0x35, &dce_status_semaphore, 1);}voidsync_tx_int(void){ char reg, xs, tcnt; if (dce_tx_count == 0) { dce_tx_interrupt_expected = 0; return; } reg = 0x54; tcnt = 0; while (tcnt < 0x20) { /* 32 Tx bytes Max */ dspdrv_WriteCram(reg++, &dce_tx_buffer[dce_tx_remove++], 1); dce_tx_count--; tcnt++; stat_tx_count++; if (dce_tx_remove == BUF_SIZE) dce_tx_remove = 0; if (dce_tx_count == 0) break; } TX_stat[(int)tcnt-1]++; xs = 0; dspdrv_WriteCram(0x75, &xs, 1); dspdrv_WriteCram(0x74, &tcnt, 1);}voidv8_rx_int(void){ unsigned char c, reg = 0x14; while (dce_length_semaphore) { dspdrv_ReadCram(reg++, &c, 1); dce_length_semaphore--; /* Dbg("%4x ", c); */ if (v8_status == 0) { if (c == 0xe0) { v8_status = 1; old_length = 0; dce_rx_buffer[0] = 0xe0; length = 1; } } else if (v8_status == 1) { if (c != 0xe0) dce_rx_buffer[length++] = c; else if (length < 3) length = 1; else { v8_status = 2; old_length = length - 1; length = 1; } } else if (v8_status == 2) { if (dce_rx_buffer[length] == c) { length++; old_length--; } else if (c != 0xe0) { v8_status = 1; dce_rx_buffer[length++] = c; } else { if (old_length == 0) { /* Dbg("JM Match\n"); */ v8_rx_msg_size = length; jm_seq_match = 1; dce_length_semaphore = 0; v8_status = 3; } else { Dbg("Old lenght not 0...\n"); if (length < 3) { length = 1; v8_status = 1; } else { old_length = length - 1; length = 1; } } } } else { dce_length_semaphore = 0; } } dspdrv_WriteCram(0x34, &dce_length_semaphore, 1); dce_status_semaphore = 0; dspdrv_WriteCram(0x35, &dce_status_semaphore, 1);}voidv8_tx_int(void){ char xs = 0; if (!sending_CM && !sending_JM) return; dspdrv_WriteCram(0x54, v8_tx_buffer, v8_tx_msg_size); dspdrv_WriteCram(0x75, &xs, 1); dspdrv_WriteCram(0x74, &v8_tx_msg_size, 1); if (sending_CM) CM_count++; else JM_count++;}voidline_enable_interrupts(void){ enable_irq(modem_irq);}voidline_disable_interrupts(void){ disable_irq(modem_irq);}/* ************************************************ */voiddelay(int milliseconds){ /* mdelay(milliseconds); This doesn't work well */ current->state = TASK_INTERRUPTIBLE; schedule_timeout((milliseconds * HZ + 1000 - HZ) / 1000); /* 100ths sec */}/* ************************************************ */voiddspdrv_clear_dsp_interrupt(void){ get_register (0xff);}voiddspdrv_ping_cram_intr(void){ set_register (0xfe, 0);}voidSetDspCfg (int p1){ unsigned char rv; rv = get_register (0xf6); if (p1 == 0) rv &= 0xfe; else rv |= 0x1; set_register (0xf6, rv);}voidWaitForDspReady(void){ /* delay(1000); */ delay(500); /* How much should this be ? */}voidResetDspInternal(void){ set_register (0xfc, 2); set_register (0xf7, 0); SetDspCfg (1); set_register (0xfc, 1); WaitForDspReady();}#define LO_B(x) ((unsigned short)x & 0xff)#define HI_B(x) (((unsigned short)x >> 8) & 0xff)intDnldViaHw(unsigned short *data){ unsigned short xc, wc, w; unsigned char xl=0, xh=0; int i, rv=1; xc = data[0]; i = 1; set_register(0xfc, 0xa); while (xc) { wc = data[i++]; set_register(0xf9, HI_B(data[i])); set_register(0xf8, LO_B(data[i])); i++; while (wc) { set_register(0xfa, LO_B(data[i])); set_register(0xfa, HI_B(data[i])); i++; wc--; } xc--; } i = 1; xc = data[0]; while (xc) { wc = data[i++]; xl = LO_B(data[i]); xh = HI_B(data[i]); set_register(0xf8, xl); set_register(0xf9, xh); i++; rv = 1; while (wc) { w = get_register(0xfa) | (get_register(0xfa) << 8); if (data[i] != w) rv = 0; i++; wc--; } xc--; } set_register(0xf9, 0x8); set_register(0xf8, 0); set_register(0xfa, xl); set_register(0xfa, xh); set_register(0xfc, 0x9); return rv;}intDnldBootx(void) { /* return DnldViaHw(bootx_array); */ return 0;}intDnldPcmPage(void){ return 0; /* No PCM modes supported yet. (x2 & V.90) */}voidDnldPoweronPatch(void){ DnldViaHw(pwr_on_patch); WaitForDspReady(); DspPatch(1);}voidResetDspPoweron(void){ int al; set_register (0xf7, 0x2); SetDspCfg (1); if (DnldBootx() && DnldPcmPage()) { if (mt_v90_configured == 0) al = 0; else al = 1; PcmEnabled = al+1; } DnldPoweronPatch();}voidDnldPatch(unsigned char *patch){ int i, ps, pcnt, j, wx, b; ps = (patch[2] | (patch[3] << 8))*2 + 1; i = 2; ack_or_response = 2; current_command[0] = 0xc; current_command[1] = 0; current_command[3] = 0; current_command[6] = 0; current_command[7] = 0; while (i != ps) { pcnt = 4; j = 8; current_command[4] = patch[i*2]; current_command[5] = patch[i*2+1]; wx = patch[i*2] | (patch[i*2+1] << 8); for (b=1; b<4; b++) { i++; pcnt+=2; current_command[j++] = patch[i*2]; current_command[j++] = patch[i*2+1]; if (i == ps) break; i++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -