?? control.c
字號:
/*
* Higher level(?) Modem control routines.
*
* Copyright 1999 Pavel Machek
* Copyright 1999 Jamie Lokier
* Copyright 1999-2000 R.J.M. Close
*
* Can be distributed under GPL
*/
#include "control.h"
void go_offhook(void) /* Ouch, is it real command for going offhook? It looks like it is used only in some tests! */
{
printf( "Going offhook..." );
x_output(0x13);
x_output(0x11);
x_output(0x02);
dp_state = 0x14;
printf( "ok\n" );
}
// Command to actually go offhook.
// Based on Jamie's version with minor changes.
bool dp_offhook_cmd (void)
{
if (cell_active)
{
at_init_diagnostics ();
x_status[0] = 0;
return true;
}
// Wait until ring not detected or 3 seconds has expired.
// Basically wait up to 3 seconds for line to go quiet.
dp_timer = x_current_time();
do {
if (dp_ring_detected() == false) break;
printf ("~");
}
while (x_elapsed_time(dp_timer) < 3000);
x_output(14);
x_output(17);
x_output(2);
if (H_shunt_relay_on_time != 0xff)
x_output (15);
if (S_speaker_enable) {
switch (S_speaker_volume) {
case 3: x_output(0x0b); break;
case 2: x_output(0x0a); break;
default: x_output(0x09); break;
}
dp_modem_command(0x13, 0, 0);
x_output(8);
}
#if !PAVEL_FIX
if (H_overcurrent_sense_validation_time != 0
&& dp_dialing_status == 0)
{
unsigned local_timer;
x_output (28);
x_output (30);
START_TIMER (dp_timer);
local_timer = dp_timer;
while (ELAPSED_TIME (local_timer) <= 10)
{
if (x_input (65) == 0)
continue;
START_TIMER (local_timer);
if (ELAPSED_TIME (dp_timer)
>= (H_overcurrent_sense_validation_time * 10))
{
x_output (3);
x_send_mail (7, 1, 0, 0);
dp_over_current_alert ();
return false;
}
}
if (H_DC_loop_limiting_relay_flag != 0)
x_output (27);
if (H_DC_loop_VI_characteristics_relay_flag != 0)
x_output (29);
}
#endif
if (x_modem_mode != 2 && x_modem_mode != 3)
{
x_output (19);
at_init_diagnostics ();
x_status[0] = 0;
}
else
{
x_output (20);
if (CpqFlag) x_output (13);
}
#if !PAVEL_FIX
if (H_shunt_relay_on_time != 0xff)
{
int limit = H_shunt_relay_on_time * 10;
START_TIMER (dp_timer);
if (H_overcurrent_sense_validation_time != 0 && limit >= 10)
limit -= 10;
while ((dp_dialing_status == 0)
&& (ELAPSED_TIME (dp_timer) <= limit))
/*empty*/;
x_output (16);
}
#endif
dp_init_local_phone_timer ();
return true;
}
void dp_hdlc_mode(void)
{
DpIdleFillChar = 0x7e;
dp_modem_command_long(0x29, 0x7e, 1, 0x40, 0);
}
void dp_onhook_cmd(void)
{
printf( "Going onhook: " );
// printf( "Should call cell_onhook()\n" );
dp_modem_command(0x13, 0, 0);
x_output( 7);
x_output(0x0e);
x_output(0x14);
x_output(0x10);
if (S(0x72) == 0) {
x_output(0x19);
x_output( 3);
x_output(0x12);
} else
S(0x72) = 0x0a;
dp_write_dsp_ram(0xf20, 0x42f8);
dp_regwrite(0xd8, 0xff);
dp_regwrite(0xb7, 0xff);
dp_tad_downloaded = dp_fax_downloaded = 0;
if (S(0x74) == 1) {
S(0x74) = 0;
S(0x52) = 0;
}
v8bis_app_reset();
dp_init_local_phone_state();
V34Mode = 0;
dp_update_diagnostics();
if (x_status[0] != 0)
goto l2D1;
x_status[0] = 1;
// ll_save_diagnostics();
l2D1:
if ((S(0x72) == 0) && (x_modem_mode != 3))
dp_run_rom();
dp_first_call = 0;
printf( "\n" );
}
bool dp_carrier_loss(void)
{
unsigned char retVal;
// Read value from DSP RAM.
retVal = dp_read_dsp_ram(0x8E);
// Invert it.
retVal = ~retVal;
// Return bit 1 state as bool.
retVal = ((retVal >> 1) & 1);
if (retVal) {
printf ("Carrier lost.\n");
return true;
}
else {
printf ("Carrier present.\n");
return false;
}
}
unsigned char dp_retrain(void)
{
return ((dp_dsp_status >> 4) & 1);
}
// Sets the new modem rate.
void dp_modem_rate(void)
{
unsigned short new_line_rate;
dp_dsp_status = (0xff & dp_regread(0x32));
if (dp_dsp_status & 0x10) return;
new_line_rate = (dp_dsp_status & 0xf) + 2;
// If new line is same as old then just bugger off.
if (new_line_rate == x_line_rate) return;
if (new_line_rate < x_line_rate)
dp_bFallForward = 1;
else {
if (dp_bFallForward != 2)
dp_bFallForward = 0;
else
dp_bFallForward = 1;
}
//32d90:
if (V34Mode) return;
#if LT_DEBUG
printf("dp_modem_rate: new rate set to: %d.\n", new_line_rate);
#endif
x_line_rate = new_line_rate;
x_line_rate_tx = new_line_rate;
dp_bGoodAuto = 0;
}
void dp_async_8bit_mode(void)
{
DpIdleFillChar = 0xff;
dp_modem_command_long(0x29, 0xff, 1, 0x87, 0);
}
// Set speaker up acording to values held in globals:
// speakerVolume and speakerEnable.
void dp_56k_speaker_cmd (void)
{
if (!S_speaker_enable)
{
dp_write_dsp_ram(0xD, 0);
return;
}
if (S_speaker_volume == 3)
{
x_output(0xB);
x_output(8);
return;
}
if (S_speaker_volume == 2)
{
x_output(0xA);
x_output(8);
return;
}
// speakerVolume = 1, or not valid.
x_output(9);
x_output(8);
return;
}
// Fill in, if needed.
unsigned short dp_test_cmd (unsigned int arg1, unsigned char* arg2)
{
// Crude dummy to use args. Code does not do this!
*arg2 = arg1;
printf ("dp_test_cmd: not yet implemented!\n");
return 1;
}
void Modem_Resume(void)
{
x_send_mail (0x66, 1, 0, 0);
x_wakeup();
}
void dp_download_dsp (unsigned char* data, unsigned count)
{
unsigned char * local_ptr = (unsigned char *) data;
unsigned char save_rd7 = dp_bamil_rd7;
if (x_dsp_mars == 1)
{
Write_mdm_word (0x3c, 0x1ff);
Write_mdm_word (0x3e, 0);
}
dp_bamil_rd7 = 0xff;
dp_regwrite (0xd8, 0xff);
dp_regwrite (0xd7, 0xff);
dp_modem_command_long (0x29, 0, 0, 0, 0);
dp_write_dsp_ram (0x39, 0);
while (count != 0)
{
unsigned block_size = *(unsigned short *) (local_ptr + 2);
unsigned counter;
printf("count %x, ", count);
count -= (3 + block_size);
counter = 0;
dp_regwrite (0x30, 1);
do
dp_regwrite (0x31 + counter, *local_ptr++);
while (++counter < 6);
dp_regwrite (0xd8, 0x18);
dp_regwrite (0x37, 0x1a);
wait_for_core_read ();
while (block_size > 0)
{
unsigned tmp;
tmp = block_size >= 3 ? 3 : block_size;
block_size -= tmp;
tmp += tmp;
counter = 0;
do
dp_regwrite (0x30 + counter, *local_ptr++);
while (++counter < tmp);
dp_regwrite (0xd8, 0x18);
dp_regwrite (0x37, tmp | (block_size ? 0xc0 : 0xc8));
wait_for_core_read ();
}
}
dp_regwrite (0xb7, 0xff);
dp_regwrite (0xd8, 0xff);
dp_bamil_rd7 = save_rd7;
dp_regwrite (0xd7, dp_bamil_rd7);
if (x_dsp_mars == 1)
{
Write_mdm_word (0x3c, 0x1ff);
Write_mdm_word (0x3e, 1);
}
}
void dp_download_fax(void)
{
//printf( "Download fax: size is %x\n", sizeof(wDspFax));
dp_modem_command(0x13, 0, 0);
//dp_download_dsp(wDspFax, 0x7FA);
dp_modem_command(0x13, 0, 0);
}
void dp_retrain_cmd(void)
{
dp_modem_command(0x0F, 0, 0);
}
void dp_fast_retrain_cmd(void)
{
dp_lapm_error_check_init();
dp_update_rate();
dp_modem_command(2, 0, 0);
}
void dp_originate_cmd (void)
{
printf("dp_originate_cmd called.\n");
dp_modem_command(0x13, 0, 0);
dp_update_modem_options();
dp_modem_command(0x0e, 1, 0);
dp_v8_originate_msg();
}
void dp_answer_cmd(void)
{
dp_modem_command(0x13, 0, 0);
dp_update_modem_options();
dp_modem_command(0x0e, 0, 0);
}
bool dp_line_connect(void)
{
if (dp_regread(0x19) != 0x10) return true;
if (dp_regread(0x16) != 4) return true;
return false;
}
// Update the data rate.
void dp_update_rate(void)
{
unsigned char bl = 0;
unsigned int ebp = 0;
unsigned int esi = 0;
unsigned int eax = 0;
unsigned int edi = 0;
unsigned short ax;
unsigned char al;
//printf("dp_update_rate: setting up data rate...");
wSymbolRate = 0x3FF;
//edx = 5;
if (S(0x6f) == 0) goto loc_2C870;
al = S(0x10) - 1;
if (al <= 8) {
switch (al){
case 0: case 1: case 2:
bl = 3;
break;
case 3:
bl = 5;
break;
case 4:
bl = 6;
break;
case 5:
bl = 7;
break;
case 6:
bl = 9;
break;
case 7:
bl = 11;
break;
case 8:
bl = 13;
break;
}
}
loc_2C870:
al = S_dial_line_rate;
if (bl == 0) goto loc_2C881;
if (al == 0) goto loc_2C883;
if (bl <= al) goto loc_2C883;
loc_2C881:
bl = al;
loc_2C883:
al = bl;
al = al - 2;
//ecx = 0x10;
if (al > 16) goto loc_2CB1A; // Out of range. (same as case 2)
switch (al) {
case 0:
// loc_2C89B 0
edi = 0x80;
//goto loc_2C8DF;
// loc_2C8DF:
x_line_rate = 4;
break;
case 1:
// loc_2C8A2
if ((S(0x3a) == 0) && (country_code == COUNTRY_FRANCE)) {
edi = 0x20;
eax = 3 + H_data_or_fax_carrier_rx_threshold_dB;
dp_write_dsp_ram(0x37, eax);
}
else
edi = 0x10;
//loc_2C8CD:
x_line_rate = 2;
break; //goto loc_2CB9B;
case 2:
// loc_2CB1A 2
loc_2CB1A:
al = S(0x38);
if ((al == 8) || (al == 10) || (al == 0) || (al == 1)) {
//loc_2CB72: //Same as case: 16
ebp = 0xFFF0;
if (S_auto_rate)
eax = 0xffffffff; // -1
else
eax = 0;
edi = 0xb1;
eax = eax & 0x8FFF;
x_line_rate = 17;
eax = eax + 0x1000;
esi = eax;
break; //goto loc_2CB9B;
}
wSymbolRate = 0x07FF;
if (S_auto_rate == 0){
ebp = 0xC990;
esi = 0x2000;
}
else {
//loc_2CB4D:
ebp = 0xFFF0;
esi = 0xBFFF;
}
//loc_2CB57:
edi = 0xb1;
// S_V34_enable = S(0x1c) in 568 dis? (1c = 28)
// 568 code extract...
if (S_V34_enable)
x_line_rate = 18;
else
x_line_rate = 12;
// Replaces...
// S_V34_enable = al;
// neg al
// sbb eax, eax ( if al eax = fffffff else 0)
// and eax, 6
// eax, 0Ch
// mov dword__x_line_rate, eax
break;
case 3:
// loc_2C8DC 3
edi = 2;
//loc_2C8DF:
x_line_rate = 4;
break; //goto loc_2CB9B;
case 4:
//loc_2C8EE 4
//al = S_auto_rate; //byte_59E8A
if (S_auto_rate)
eax = 0xffffffff; // -1
else
eax = 0;
edi = 1;
eax = eax & 0x8000;
x_line_rate = 5; // 5.
eax++;
wSymbolRate = edi; // 1.
esi = eax;
break; //goto loc_2CB9B;
case 5:
// loc_2C914 5
//al = S_auto_rate;
ebp = 0x89B0;
if (S_auto_rate)
eax = 0xffffffff; // -1
else
eax = 0;
//0002C91E neg al
//0002C920 sbb eax, eax
edi = 0x0B1;
eax = eax & 0x8001;
x_line_rate = 6;
eax = eax + 2;
esi = eax;
break; //goto loc_2CB9B;
case 6:
//loc_2C93F (32011: in Jamie's dis.)
if (S_auto_rate == 0){
ebp = 0x8B90;
esi = 4;
}
else {
//loc_2C952:
ebp = 0x8BB0;
esi = 0x8007;
}
//loc_2C95C:
edi = 0xb1;
x_line_rate = 7;
break; //goto loc_2CB9B;
case 7:
//loc_2C970 7
if (S_auto_rate == 0){
ebp = 0x89D0;
esi = 8;
}
else {
//loc_2C983:
ebp = 0x8BF0;
esi = 0x800F;
}
// loc_2C98D:
edi = 0xb1;
x_line_rate = 8;
break; //goto loc_2CB9B;
case 8:
// loc_2C9A1 8
if (S_auto_rate == 0){
ebp = 0x89D0;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -