PSI sics-cvs-psi_pre-ansto
This commit is contained in:
528
sel2.c
Normal file
528
sel2.c
Normal file
@@ -0,0 +1,528 @@
|
||||
/************************************************************************/
|
||||
/* Hahn-Meitner-Institut Berlin */
|
||||
/* Bereich Strukturforschung */
|
||||
/* Abteilung NI / BENSC */
|
||||
/* Glienicker Strasse 100 */
|
||||
/* D-14109 Berlin (Wannsee) */
|
||||
/* Software:K. Emmelmann, Tel.(030)8062-2588, Mail: klaus@dvwbs5.hmi.de */
|
||||
/************************************************************************/
|
||||
/* Datei: SEL.C */
|
||||
/* Teil von: KWS.C */
|
||||
/* Anwendung bei: V4 - KWS */
|
||||
/* Titel: Treiberprogramm fuer Geschwindigkeitsselektor DORNIER */
|
||||
/* Version: 1.0 vom: 30.1.96 */
|
||||
/************************************************************************/
|
||||
/*
|
||||
Legende
|
||||
=======
|
||||
|
||||
30.1.96 Emmelmann Implementierung
|
||||
1.2.96 Emmelmann Statusdekodierung eingebaut
|
||||
27.2.96 Emmelmann Strom wird auch im Status geliefert
|
||||
|
||||
|
||||
Das Handbuch sagt Empfangsterminator ist Linefeed.
|
||||
|
||||
|
||||
Jeder Befehl erzeugt ein Echo; argumentlose Befehle werden im Echo
|
||||
zusaetzlich mit einer Zahl versehen, deren Bedeutung unbekannt ist.
|
||||
|
||||
|
||||
FEHLERMELDUNGEN, die bekannt sind:
|
||||
****************************************
|
||||
|
||||
1. Solldrehzahl zu klein !
|
||||
2. Solldrehzahl zu gross !
|
||||
3. derzeit keine Ausfuehrung moeglich !
|
||||
4. Solldrehzahl in einem kritischen Bereich
|
||||
- return to m
|
||||
5. HOCHFAHREN 1
|
||||
6.
|
||||
|
||||
zu 3: Abfrage der Istgeschwindigkeit ist waehrend des Hochfahrens aus dem
|
||||
Stillstand nur ueber Lesen des Gesamtstatus moeglich
|
||||
zu 4: es gibt verbotene Geschwindigkeitsbereiche
|
||||
zu 5: beim Uebergang von Stop in den gestarteten Zustand
|
||||
|
||||
Zeitliches Protokollverhalten
|
||||
-----------------------------
|
||||
Wird ein Befehl bearbeitet, werden alle weiteren ueber die serielle
|
||||
Schnittstelle einlaufenden Befehle ignoriert - auch nicht gepuffert !
|
||||
|
||||
Max. Befahlsrate: 1 Befehl / 5 Sekunden
|
||||
|
||||
Geraete-Verhalten
|
||||
-----------------
|
||||
Der Startbefehl faehrt den Selektor auf die Minimalgeschwindigkeit (3100U/min)
|
||||
|
||||
Das Protokoll: fuer jeden Befehl erzeugt der Selektor-PC ein Echo !
|
||||
|
||||
Host -> Selektor
|
||||
------------------------
|
||||
REM (disabled) Remote-Betrieb einschalten
|
||||
Rueckmeldung: ENABLED / Host nicht betriebsbereit!
|
||||
|
||||
TTY (disabled) Local-Betrieb einschalten
|
||||
Rueckmeldung: DISABLED
|
||||
|
||||
??? Sende Status (Status ist nicht fest und geht von der
|
||||
Interpretation der Kennworte aus !)
|
||||
|
||||
TIM (disabled) Setzen des Zeitintervalles zur Time-Out-Ueberwachung des PCs
|
||||
????
|
||||
|
||||
SST Start des Selektors und Ausregeln der Drehzahl (Nur wenn der
|
||||
Selektor steht !); liefert als Rueckmeldung die Solldrehzahl
|
||||
|
||||
SDR nnnnn Vorgabe einer Soll-Drehzahl und geregelten Betrieb einschalten.
|
||||
3100 => nnnnn <=28300 U/min; liegt der Wert in einem kritischen
|
||||
Bereich (geht aus Setup-Menue hervor), kommt eine entsprechende
|
||||
Rueckmeldung
|
||||
|
||||
FDR Sende die Solldrehzahl (Format 'RPM n')
|
||||
|
||||
STB Leerlauf ohne Regelung
|
||||
|
||||
BRE Beginne eine Verlustleistungsmessung - ist bei Statusabruf
|
||||
lesbar, wenn dort die Betriebsart regeln erscheint !
|
||||
|
||||
HAL Bremse Selektor bis zum Stillstand ab (unterhalb 3000 U/min.)
|
||||
|
||||
*/
|
||||
#include stdio.h
|
||||
#include descrip.h
|
||||
#include iodef.h
|
||||
#include errno.h
|
||||
#include lnmdef.h
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE !FALSE
|
||||
|
||||
#define OK 0L
|
||||
#define NOT_OK !OK
|
||||
|
||||
#define LIMIT_U 3100 /* niedrigste Drehzahl */
|
||||
#define LIMIT_O 28300
|
||||
|
||||
/* Verbotene Drehzahlbereiche (Resonanzgefahr) */
|
||||
|
||||
#define RESONANZ_1U 3648
|
||||
#define RESONANZ_1O 4552
|
||||
#define RESONANZ_2U 5248
|
||||
#define RESONANZ_2O 6449
|
||||
#define RESONANZ_3U 9148
|
||||
#define RESONANZ_3O 9949
|
||||
|
||||
#define TOK_BUF_L 25
|
||||
|
||||
#define SELE_LUN 0
|
||||
|
||||
extern FILE *fs;
|
||||
|
||||
static short chan_s=6;
|
||||
|
||||
/* *********************************************************************** */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
long select_setup()
|
||||
{
|
||||
register rc;
|
||||
$DESCRIPTOR(dev_descr, "TXA1:");
|
||||
chan_s=SELE_LUN;
|
||||
if ((rc=sys$assign(&dev_descr, &chan_s, NULL,NULL)) != 1)
|
||||
{printf("Error in Selector_SETUP: Ret = %d\n",rc); return(NOT_OK);}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Function liest ueberprueft das Befehlsecho */
|
||||
long sele_test_echo(cmd, lng)
|
||||
char *cmd[];
|
||||
int lng;
|
||||
{
|
||||
char echo[80];
|
||||
if (sele_read(&echo)!= OK) return(NOT_OK);
|
||||
if (strncmp(&echo, cmd, lng) != 0)
|
||||
{printf("Selector:protocol error%s\n",echo); return(NOT_OK);}
|
||||
else
|
||||
return(OK);
|
||||
}
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Function prueft die Anzahl der sich im Typeahead-Buffer befindenden Bytes
|
||||
und liefert das naechste dort anstehende Zeichen, jedoch ohne es
|
||||
aus dem Puffer zu entnehmen.
|
||||
*/
|
||||
long tst_buf_s(bt)
|
||||
int *bt;
|
||||
{
|
||||
int bytes;
|
||||
register rc;
|
||||
struct {unsigned short status, bytes;
|
||||
int pid; } iosb;
|
||||
if ((rc=sys$qiow(NULL,chan_s,IO$_SENSEMODE | IO$M_TYPEAHDCNT,&iosb,
|
||||
NULL, NULL, &bytes, NULL, NULL, NULL, NULL, NULL)) != 1)
|
||||
{print_error(fs,"Error in QIOW"); return(NOT_OK);}
|
||||
/**ch = (bytes >> 16) & 0xff;*/
|
||||
*bt = bytes & 0xffff;
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
long sele_read(message)
|
||||
char *message;
|
||||
{
|
||||
char char_l[8], *ptr;
|
||||
register rc;
|
||||
struct {unsigned short status, bytes;
|
||||
int pid; } iosb;
|
||||
ptr = message;
|
||||
for (;;)
|
||||
{
|
||||
if ((rc=sys$qiow(NULL,chan_s,IO$_READVBLK | IO$M_NOECHO,
|
||||
&iosb,NULL,
|
||||
NULL, char_l, 1, NULL, NULL, NULL, NULL)) != 1)
|
||||
{printf("Error in QIOW, READ_MESS: %d\n", rc);return(NOT_OK);}
|
||||
*ptr = char_l[0];
|
||||
/* Terminator (linefeed) ? */
|
||||
ptr++;
|
||||
if (char_l[0] == '\n') break;
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Pruefe ob der Selektor eine Fehlermeldung erzeugt hat und gib sie aus */
|
||||
|
||||
long select_error_msg(err)
|
||||
long *err;
|
||||
{
|
||||
char chr[10], msg[80];
|
||||
float waiti=3.0; /* Selektor PC hat 3 Sekunden Reaktionszeit !! */
|
||||
|
||||
/* Warte ein wenig - es koennte auf den Befehl hin eine Fehlermeldung erscheinen */
|
||||
lib$wait(&waiti);
|
||||
|
||||
/* Es koennen auch mehrere Zeilen sein */
|
||||
*err = FALSE;
|
||||
for (;;)
|
||||
{if (tst_buf_s(&chr) != OK) return(NOT_OK);
|
||||
if (chr[0] != NULL)
|
||||
{
|
||||
if (sele_read(&msg) != OK) return(NOT_OK);
|
||||
printf("Selektor failure:");
|
||||
printf("%s\n\7",msg);
|
||||
*err = TRUE;
|
||||
}
|
||||
else
|
||||
return(OK);
|
||||
}
|
||||
}
|
||||
/* ------------------------------------------------------------------------ */
|
||||
long sele_write(message)
|
||||
char message[];
|
||||
{
|
||||
char msg[80];
|
||||
long err;
|
||||
register rc;
|
||||
struct
|
||||
{
|
||||
unsigned short status, bytes;
|
||||
int pid; } iosb;
|
||||
|
||||
if (select_error_msg(&err) != OK) return(NOT_OK);
|
||||
if (err == TRUE) return(NOT_OK);
|
||||
|
||||
if ((rc=sys$qiow(NULL,chan_s,IO$_WRITEVBLK,&iosb,NULL, NULL,
|
||||
message, strlen(message), NULL, NULL, NULL, NULL)) != 1)
|
||||
{printf("Error in QIOW: %d\n",rc); return(NOT_OK);}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/*
|
||||
Ein-/ Ausschalten von Stoerungsmeldungen vom Selektor an den Host
|
||||
Diese Funktion ist z.Z. nur vom Selektor-PC aktivierbar
|
||||
*/
|
||||
long select_msg(tim)
|
||||
long tim;
|
||||
{
|
||||
int sts;
|
||||
long err;
|
||||
char cmd[20] = "TIM ";
|
||||
sprintf(&cmd+4,"%5u\0",tim);
|
||||
sts = sele_write(cmd);
|
||||
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
||||
if (select_error_msg(&err) != OK) return(NOT_OK);
|
||||
if (err == TRUE) return(NOT_OK);
|
||||
return(OK);
|
||||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Einschaltung der Fremdsteuerung des Selektors
|
||||
Diese Funktion ist z.Z. nur vom Selektor-PC aktivierbar
|
||||
*/
|
||||
long select_remote()
|
||||
{
|
||||
int sts;
|
||||
long err;
|
||||
char cmd[] = "REM";
|
||||
sts = sele_write(cmd);
|
||||
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
||||
if (select_error_msg(&err) != OK) return(NOT_OK);
|
||||
if (err == TRUE) return(NOT_OK);
|
||||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Ausschaltung der Fremdsteuerung des Selektors -
|
||||
ein Steuerung kann dann nur noch ueber den PC des Geraetes
|
||||
erfolgen.
|
||||
Diese Funktion ist z.Z. nur vom Selektor-PC aktivierbar
|
||||
*/
|
||||
long select_local()
|
||||
{
|
||||
int sts;
|
||||
long err;
|
||||
char cmd[] = "TTY";
|
||||
sts = sele_write(cmd);
|
||||
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
||||
if (select_error_msg(&err) != OK) return(NOT_OK);
|
||||
if (err == TRUE) return(NOT_OK);
|
||||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Starten des Selektors nach Stillstand auf die Minimaldrehzahl
|
||||
*/
|
||||
long select_start()
|
||||
{
|
||||
int sts;
|
||||
long err;
|
||||
char cmd[] = "SST";
|
||||
sts = sele_write(cmd);
|
||||
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
||||
if (select_error_msg(&err) != OK) return(NOT_OK);
|
||||
if (err == TRUE) return(NOT_OK);
|
||||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Bremsen des Selektors bis zum Stillstand; eine
|
||||
Drehzahlanzeige unterhalb 3000 U/min ist nicht moeglich.
|
||||
*/
|
||||
long select_stop()
|
||||
{
|
||||
int sts;
|
||||
long err;
|
||||
char cmd[] = "HAL";
|
||||
sts = sele_write(cmd);
|
||||
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
||||
if (select_error_msg(&err) != OK) return(NOT_OK);
|
||||
if (err == TRUE) return(NOT_OK);
|
||||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Einschalten des geregelten Betriebes mit dem Setzen eines Sollwertes
|
||||
der Drehzahl.
|
||||
Aenderungen werden spontan uebernommen und ausgefuehrt.
|
||||
Neben dem absoluten Minimum und Maximum existieren verbotene
|
||||
Drehzahlbereiche, die z.Z. noch nicht exakt bekannt sind.
|
||||
*/
|
||||
long select_set_rpm(rpm)
|
||||
int rpm;
|
||||
{
|
||||
int sts;
|
||||
long err;
|
||||
char cmd[] = "SDR", s_dat[10] = "SDR 00000";
|
||||
if ((rpm < LIMIT_U) || (rpm > LIMIT_O))
|
||||
{
|
||||
print_error(fs,"nominal value out of allowed range");
|
||||
return;
|
||||
}
|
||||
/* Resonanzbereiche sind auch verboten */
|
||||
if (
|
||||
((rpm >= RESONANZ_1U) && (rpm <= RESONANZ_1O)) ||
|
||||
((rpm >= RESONANZ_2U) && (rpm <= RESONANZ_2O)) ||
|
||||
((rpm >= RESONANZ_3U) && (rpm <= RESONANZ_3O)))
|
||||
{
|
||||
print_error(fs,"nominal value within inhibited range");
|
||||
return;
|
||||
}
|
||||
sprintf(&s_dat+4,"%5u",rpm);
|
||||
sts = sele_write(s_dat);
|
||||
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
||||
if (select_error_msg(&err) != OK) return(NOT_OK);
|
||||
if (err == TRUE) return(NOT_OK);
|
||||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Leerlauf des Selektors einschalten; weder Antrieb noch
|
||||
Verzoegerung erfolgen - eine anschliessende Abbremsung oder
|
||||
ein Uebergang zum geregelten Betrieb ist moeglich.
|
||||
*/
|
||||
long select_set_idle()
|
||||
{
|
||||
int sts;
|
||||
long err;
|
||||
char cmd[] = "STB";
|
||||
sts = sele_write(cmd);
|
||||
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
||||
if (select_error_msg(&err) != OK) return(NOT_OK);
|
||||
if (err == TRUE) return(NOT_OK);
|
||||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Starten der Messung der elektrischen Verlustleistung des
|
||||
Selektors. Anscheinend wird waehrend der Zeit die
|
||||
Regelung deaktiviert.
|
||||
Nach Abschluss der Messung erfolgt ein Uebergang in den\
|
||||
geregelten Berieb.
|
||||
Das Messergebnis wird in den Statusinformationsblock eingetragen.
|
||||
*/
|
||||
long select_read_power()
|
||||
{
|
||||
int sts;
|
||||
long err;
|
||||
char cmd[] = "BRE";
|
||||
sts = sele_write(cmd);
|
||||
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
||||
if (select_error_msg(&err) != OK) return(NOT_OK);
|
||||
if (err == TRUE) return(NOT_OK);
|
||||
}
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Lesen der aktuellen Drehzahl des Selektors */
|
||||
long select_read_rpm(rpm)
|
||||
int *rpm;
|
||||
{
|
||||
int sts, tmp;
|
||||
long err;
|
||||
char status[80], cmd[] = "FDR";
|
||||
sts = sele_write(cmd);
|
||||
if (sele_test_echo(&cmd,3)!= OK) lib$stop(-1);
|
||||
|
||||
sts = sele_read(&status);
|
||||
sscanf(&status+4,"%d",&tmp);
|
||||
*rpm = tmp;
|
||||
if (select_error_msg(&err) != OK) return(NOT_OK);
|
||||
if (err == TRUE) return(NOT_OK);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Auslesen des kompletten Statusblockes des Selektors.
|
||||
Der Informationseintrag 'Verlustleistung' ist anscheinend nur dann
|
||||
aktuell, wenn zuvor eine Verlustleistungsmessung aktiviert wurde.
|
||||
Argumente:
|
||||
rm = Betriebsstatus
|
||||
[REG == regelnd]
|
||||
[STB == im Leerlauf]
|
||||
[BRE == bremsend]
|
||||
nom_rpm = Soll der Drehzahl (U/min)
|
||||
cur_rpm = Ist der Drehzahl (U/min)
|
||||
pwr = Verlustleistung (W)
|
||||
curr = elektr. Stomstaerke (A)
|
||||
rot_temp= Temperatur des Rotors (C)
|
||||
cont_temp= Temperatur des Gehaeuses (C)
|
||||
inl_temp= Temperatur Kuehlwasser-Einlass
|
||||
outl_temp= Temperatur Kuehlwasser-Abfluss
|
||||
cool_wat= Kuehlwasser-Durchfluss (l/min)
|
||||
vacuum = Betriebsvakuum (mbar)
|
||||
accel = Rotationsbeschleunigung (g)
|
||||
komm = Kommunikation zwischen Selektor-PC und Host
|
||||
'ENABLED' oder "DISABLED'
|
||||
dat = Tagesdatum dd.m.yyyy
|
||||
tim = Tageszeit hh.mm.s
|
||||
|
||||
*/
|
||||
long select_read_status(rm,nom_rpm, cur_rpm, pwr, curr, rot_temp, cont_temp,
|
||||
inl_temp, outl_temp, cool_wat, vacuum, accel, komm, dat, tim)
|
||||
char *rm[];
|
||||
int *nom_rpm, *cur_rpm, *pwr, *rot_temp, *cont_temp, *inl_temp, *outl_temp;
|
||||
float *cool_wat, *vacuum, *accel, *curr;
|
||||
char *dat[], *tim[];
|
||||
short *komm;
|
||||
{
|
||||
int cnt, key_id, sl, sts;
|
||||
long err;
|
||||
char ena_str[] = "ENABLED";
|
||||
char dis_str[] = "DISABLED";
|
||||
char keys[15][9] =
|
||||
{
|
||||
"Status:\0 ",
|
||||
"S_DREH:\0 ",
|
||||
"I_DREH:\0 ",
|
||||
"P_VERL:\0 ",
|
||||
"STROM:\0 ",
|
||||
"T_ROT:\0 ",
|
||||
"T_GEH:\0 ",
|
||||
"T_VOR:\0 ",
|
||||
"T_RUECK:\0",
|
||||
"DURCHFL:\0",
|
||||
"VAKUUM:\0 ",
|
||||
"BESCHL:\0 ",
|
||||
"KOM: \0 ",
|
||||
"DATE: \0 ",
|
||||
"TIME: \0 "};
|
||||
|
||||
char tok_buf[TOK_BUF_L], *ptr_token, *ptr_src, *ptr, tok_c[] = "/\0";
|
||||
|
||||
char status[255], cmd[] = "???";
|
||||
|
||||
if (sele_write(cmd) != OK) return(NOT_OK);
|
||||
|
||||
if (sele_test_echo(&cmd, 3) == NOT_OK) lib$stop(-1);
|
||||
|
||||
if (sele_read(&status) != OK) return(NOT_OK); /* Und nun der Status */
|
||||
ptr_src = &status;
|
||||
for (;;)
|
||||
{
|
||||
/* Lies Zeichenfolge bis zum naechsten Trennzeichen '/' */
|
||||
ptr_token = strtok(ptr_src, &tok_c);
|
||||
ptr_src = NULL; /* fuer die weitere Suche notwendig */
|
||||
if (ptr_token == NULL) break;
|
||||
strcpy(&tok_buf,ptr_token);
|
||||
|
||||
for (key_id = 0; key_id<=14; key_id++)
|
||||
{
|
||||
/* Ist das Schluesselwort enthalten ? */
|
||||
sl = strlen(keys[key_id]);
|
||||
if (strncmp(&keys[key_id][0], &tok_buf, sl) == NULL)
|
||||
{
|
||||
/* Schiebe das Schluesselwort raus */
|
||||
for (cnt=0;cnt+sl < TOK_BUF_L; cnt++)
|
||||
tok_buf[cnt] = tok_buf[cnt+sl];
|
||||
switch (key_id)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
ptr = rm;
|
||||
strcpy(ptr, &tok_buf);
|
||||
break;
|
||||
}
|
||||
case 1: {sscanf(&tok_buf,"%d",nom_rpm); break;}
|
||||
case 2: {sscanf(&tok_buf,"%d",cur_rpm); break;}
|
||||
case 3: {sscanf(&tok_buf,"%d",pwr); break;}
|
||||
case 4: {sscanf(&tok_buf,"%f",curr); break;}
|
||||
case 5: {sscanf(&tok_buf,"%d",rot_temp); break;}
|
||||
case 6: {sscanf(&tok_buf,"%d",cont_temp); break;}
|
||||
case 7: {sscanf(&tok_buf,"%d",inl_temp); break;}
|
||||
case 8: {sscanf(&tok_buf,"%d",outl_temp); break;}
|
||||
case 9: {sscanf(&tok_buf,"%f",cool_wat); break;}
|
||||
case 10: {sscanf(&tok_buf,"%f",vacuum); break;}
|
||||
case 11: {sscanf(&tok_buf,"%f",accel); break;}
|
||||
case 12:
|
||||
{
|
||||
if (strcmp(&tok_buf, &ena_str) == NULL)
|
||||
{*komm = TRUE; break;}
|
||||
if (strcmp(&tok_buf, &dis_str) == NULL)
|
||||
{*komm = FALSE;break;}
|
||||
printf("Invalid Communication value");
|
||||
break;
|
||||
}
|
||||
case 13:
|
||||
{
|
||||
ptr = dat;
|
||||
strcpy(ptr, &tok_buf);
|
||||
break;
|
||||
}
|
||||
case 14:
|
||||
{
|
||||
ptr = tim;
|
||||
strcpy(ptr, &tok_buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (select_error_msg(&err) != OK) return(NOT_OK);
|
||||
if (err == TRUE) return(NOT_OK);
|
||||
return(OK);
|
||||
}
|
||||
Reference in New Issue
Block a user