diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/hisax/arcofi.c |
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/isdn/hisax/arcofi.c')
-rw-r--r-- | drivers/isdn/hisax/arcofi.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c new file mode 100644 index 00000000000..d30ce5b978c --- /dev/null +++ b/drivers/isdn/hisax/arcofi.c @@ -0,0 +1,134 @@ +/* $Id: arcofi.c,v 1.14.2.3 2004/01/13 14:31:24 keil Exp $ + * + * Ansteuerung ARCOFI 2165 + * + * Author Karsten Keil + * Copyright by Karsten Keil <keil@isdn4linux.de> + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +#include "hisax.h" +#include "isdnl1.h" +#include "isac.h" +#include "arcofi.h" + +#define ARCOFI_TIMER_VALUE 20 + +static void +add_arcofi_timer(struct IsdnCardState *cs) { + if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { + del_timer(&cs->dc.isac.arcofitimer); + } + init_timer(&cs->dc.isac.arcofitimer); + cs->dc.isac.arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ)/1000); + add_timer(&cs->dc.isac.arcofitimer); +} + +static void +send_arcofi(struct IsdnCardState *cs) { + u_char val; + + add_arcofi_timer(cs); + cs->dc.isac.mon_txp = 0; + cs->dc.isac.mon_txc = cs->dc.isac.arcofi_list->len; + memcpy(cs->dc.isac.mon_tx, cs->dc.isac.arcofi_list->msg, cs->dc.isac.mon_txc); + switch(cs->dc.isac.arcofi_bc) { + case 0: break; + case 1: cs->dc.isac.mon_tx[1] |= 0x40; + break; + default: break; + } + cs->dc.isac.mocr &= 0x0f; + cs->dc.isac.mocr |= 0xa0; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + val = cs->readisac(cs, ISAC_MOSR); + cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); + cs->dc.isac.mocr |= 0x10; + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); +} + +int +arcofi_fsm(struct IsdnCardState *cs, int event, void *data) { + if (cs->debug & L1_DEB_MONITOR) { + debugl1(cs, "arcofi state %d event %d", cs->dc.isac.arcofi_state, event); + } + if (event == ARCOFI_TIMEOUT) { + cs->dc.isac.arcofi_state = ARCOFI_NOP; + test_and_set_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags); + wake_up(&cs->dc.isac.arcofi_wait); + return(1); + } + switch (cs->dc.isac.arcofi_state) { + case ARCOFI_NOP: + if (event == ARCOFI_START) { + cs->dc.isac.arcofi_list = data; + cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT; + send_arcofi(cs); + } + break; + case ARCOFI_TRANSMIT: + if (event == ARCOFI_TX_END) { + if (cs->dc.isac.arcofi_list->receive) { + add_arcofi_timer(cs); + cs->dc.isac.arcofi_state = ARCOFI_RECEIVE; + } else { + if (cs->dc.isac.arcofi_list->next) { + cs->dc.isac.arcofi_list = + cs->dc.isac.arcofi_list->next; + send_arcofi(cs); + } else { + if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { + del_timer(&cs->dc.isac.arcofitimer); + } + cs->dc.isac.arcofi_state = ARCOFI_NOP; + wake_up(&cs->dc.isac.arcofi_wait); + } + } + } + break; + case ARCOFI_RECEIVE: + if (event == ARCOFI_RX_END) { + if (cs->dc.isac.arcofi_list->next) { + cs->dc.isac.arcofi_list = + cs->dc.isac.arcofi_list->next; + cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT; + send_arcofi(cs); + } else { + if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { + del_timer(&cs->dc.isac.arcofitimer); + } + cs->dc.isac.arcofi_state = ARCOFI_NOP; + wake_up(&cs->dc.isac.arcofi_wait); + } + } + break; + default: + debugl1(cs, "Arcofi unknown state %x", cs->dc.isac.arcofi_state); + return(2); + } + return(0); +} + +static void +arcofi_timer(struct IsdnCardState *cs) { + arcofi_fsm(cs, ARCOFI_TIMEOUT, NULL); +} + +void +clear_arcofi(struct IsdnCardState *cs) { + if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { + del_timer(&cs->dc.isac.arcofitimer); + } +} + +void +init_arcofi(struct IsdnCardState *cs) { + cs->dc.isac.arcofitimer.function = (void *) arcofi_timer; + cs->dc.isac.arcofitimer.data = (long) cs; + init_timer(&cs->dc.isac.arcofitimer); + init_waitqueue_head(&cs->dc.isac.arcofi_wait); + test_and_set_bit(HW_ARCOFI, &cs->HW_Flags); +} |