150 lines
3.4 KiB
C
150 lines
3.4 KiB
C
/* $Id$
|
|
*
|
|
* arcofi.c Ansteuerung ARCOFI 2165
|
|
*
|
|
* Author Karsten Keil (keil@isdn4linux.de)
|
|
*
|
|
* This file is (c) under GNU PUBLIC LICENSE
|
|
*
|
|
*/
|
|
|
|
#include "channel.h"
|
|
#include "layer1.h"
|
|
#include "isac.h"
|
|
#include "arcofi.h"
|
|
#include "debug.h"
|
|
#include "helper.h"
|
|
|
|
#define ARCOFI_TIMER_VALUE 20
|
|
|
|
static void
|
|
add_arcofi_timer(channel_t *dch) {
|
|
isac_chip_t *isac = dch->hw;
|
|
|
|
if (test_and_set_bit(FLG_ARCOFI_TIMER, &dch->Flags)) {
|
|
del_timer(&isac->arcofitimer);
|
|
}
|
|
init_timer(&isac->arcofitimer);
|
|
isac->arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ)/1000);
|
|
add_timer(&isac->arcofitimer);
|
|
}
|
|
|
|
static void
|
|
send_arcofi(channel_t *dch) {
|
|
u_char val;
|
|
isac_chip_t *isac = dch->hw;
|
|
|
|
add_arcofi_timer(dch);
|
|
isac->mon_txp = 0;
|
|
isac->mon_txc = isac->arcofi_list->len;
|
|
memcpy(isac->mon_tx, isac->arcofi_list->msg, isac->mon_txc);
|
|
switch(isac->arcofi_bc) {
|
|
case 0: break;
|
|
case 1: isac->mon_tx[1] |= 0x40;
|
|
break;
|
|
default: break;
|
|
}
|
|
isac->mocr &= 0x0f;
|
|
isac->mocr |= 0xa0;
|
|
dch->write_reg(dch->inst.privat, ISAC_MOCR, isac->mocr);
|
|
val = dch->read_reg(dch->inst.privat, ISAC_MOSR);
|
|
dch->write_reg(dch->inst.privat, ISAC_MOX1, isac->mon_tx[isac->mon_txp++]);
|
|
isac->mocr |= 0x10;
|
|
dch->write_reg(dch->inst.privat, ISAC_MOCR, isac->mocr);
|
|
}
|
|
|
|
int
|
|
arcofi_fsm(channel_t *dch, int event, void *data) {
|
|
isac_chip_t *isac = dch->hw;
|
|
|
|
if (dch->debug & L1_DEB_MONITOR) {
|
|
mISDN_debugprint(&dch->inst, "arcofi state %d event %d", isac->arcofi_state, event);
|
|
}
|
|
if (event == ARCOFI_TIMEOUT) {
|
|
isac->arcofi_state = ARCOFI_NOP;
|
|
test_and_set_bit(FLG_ARCOFI_ERROR, &dch->Flags);
|
|
wake_up(&isac->arcofi_wait);
|
|
return(1);
|
|
}
|
|
switch (isac->arcofi_state) {
|
|
case ARCOFI_NOP:
|
|
if (event == ARCOFI_START) {
|
|
isac->arcofi_list = data;
|
|
isac->arcofi_state = ARCOFI_TRANSMIT;
|
|
send_arcofi(dch);
|
|
}
|
|
break;
|
|
case ARCOFI_TRANSMIT:
|
|
if (event == ARCOFI_TX_END) {
|
|
if (isac->arcofi_list->receive) {
|
|
add_arcofi_timer(dch);
|
|
isac->arcofi_state = ARCOFI_RECEIVE;
|
|
} else {
|
|
if (isac->arcofi_list->next) {
|
|
isac->arcofi_list =
|
|
isac->arcofi_list->next;
|
|
send_arcofi(dch);
|
|
} else {
|
|
if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->Flags)) {
|
|
del_timer(&isac->arcofitimer);
|
|
}
|
|
isac->arcofi_state = ARCOFI_NOP;
|
|
wake_up(&isac->arcofi_wait);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case ARCOFI_RECEIVE:
|
|
if (event == ARCOFI_RX_END) {
|
|
struct sk_buff *skb = data;
|
|
|
|
// FIXME handle message
|
|
if (skb)
|
|
kfree_skb(skb);
|
|
else
|
|
int_error();
|
|
if (isac->arcofi_list->next) {
|
|
isac->arcofi_list =
|
|
isac->arcofi_list->next;
|
|
isac->arcofi_state = ARCOFI_TRANSMIT;
|
|
send_arcofi(dch);
|
|
} else {
|
|
if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->Flags)) {
|
|
del_timer(&isac->arcofitimer);
|
|
}
|
|
isac->arcofi_state = ARCOFI_NOP;
|
|
wake_up(&isac->arcofi_wait);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
mISDN_debugprint(&dch->inst, "Arcofi unknown state %x", isac->arcofi_state);
|
|
return(2);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
static void
|
|
arcofi_timer(channel_t *dch) {
|
|
arcofi_fsm(dch, ARCOFI_TIMEOUT, NULL);
|
|
}
|
|
|
|
void
|
|
clear_arcofi(channel_t *dch) {
|
|
isac_chip_t *isac = dch->hw;
|
|
|
|
if (test_and_clear_bit(FLG_ARCOFI_TIMER, &dch->Flags)) {
|
|
del_timer(&isac->arcofitimer);
|
|
}
|
|
}
|
|
|
|
void
|
|
init_arcofi(channel_t *dch) {
|
|
isac_chip_t *isac = dch->hw;
|
|
|
|
isac->arcofitimer.function = (void *) arcofi_timer;
|
|
isac->arcofitimer.data = (long) dch;
|
|
init_timer(&isac->arcofitimer);
|
|
dch->type |= ISAC_TYPE_ARCOFI;
|
|
}
|