1/* $Id: arcofi.c,v 1.14.2.3 2004/01/13 14:31:24 Exp $ 2 * 3 * Ansteuerung ARCOFI 2165 4 * 5 * Author Karsten Keil 6 * Copyright by Karsten Keil <keil@isdn4linux.de> 7 * 8 * This software may be used and distributed according to the terms 9 * of the GNU General Public License, incorporated herein by reference. 10 * 11 */ 12 13#include <linux/sched.h> 14#include "hisax.h" 15#include "isdnl1.h" 16#include "isac.h" 17#include "arcofi.h" 18 19#define ARCOFI_TIMER_VALUE 20 20 21static void 22add_arcofi_timer(struct IsdnCardState *cs) { 23 if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { 24 del_timer(&cs->dc.isac.arcofitimer); 25 } 26 init_timer(&cs->dc.isac.arcofitimer); 27 cs->dc.isac.arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ)/1000); 28 add_timer(&cs->dc.isac.arcofitimer); 29} 30 31static void 32send_arcofi(struct IsdnCardState *cs) { 33 u_char val; 34 35 add_arcofi_timer(cs); 36 cs->dc.isac.mon_txp = 0; 37 cs->dc.isac.mon_txc = cs->dc.isac.arcofi_list->len; 38 memcpy(cs->dc.isac.mon_tx, cs->dc.isac.arcofi_list->msg, cs->dc.isac.mon_txc); 39 switch(cs->dc.isac.arcofi_bc) { 40 case 0: break; 41 case 1: cs->dc.isac.mon_tx[1] |= 0x40; 42 break; 43 default: break; 44 } 45 cs->dc.isac.mocr &= 0x0f; 46 cs->dc.isac.mocr |= 0xa0; 47 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); 48 val = cs->readisac(cs, ISAC_MOSR); 49 cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); 50 cs->dc.isac.mocr |= 0x10; 51 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); 52} 53 54int 55arcofi_fsm(struct IsdnCardState *cs, int event, void *data) { 56 if (cs->debug & L1_DEB_MONITOR) { 57 debugl1(cs, "arcofi state %d event %d", cs->dc.isac.arcofi_state, event); 58 } 59 if (event == ARCOFI_TIMEOUT) { 60 cs->dc.isac.arcofi_state = ARCOFI_NOP; 61 test_and_set_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags); 62 wake_up(&cs->dc.isac.arcofi_wait); 63 return(1); 64 } 65 switch (cs->dc.isac.arcofi_state) { 66 case ARCOFI_NOP: 67 if (event == ARCOFI_START) { 68 cs->dc.isac.arcofi_list = data; 69 cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT; 70 send_arcofi(cs); 71 } 72 break; 73 case ARCOFI_TRANSMIT: 74 if (event == ARCOFI_TX_END) { 75 if (cs->dc.isac.arcofi_list->receive) { 76 add_arcofi_timer(cs); 77 cs->dc.isac.arcofi_state = ARCOFI_RECEIVE; 78 } else { 79 if (cs->dc.isac.arcofi_list->next) { 80 cs->dc.isac.arcofi_list = 81 cs->dc.isac.arcofi_list->next; 82 send_arcofi(cs); 83 } else { 84 if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { 85 del_timer(&cs->dc.isac.arcofitimer); 86 } 87 cs->dc.isac.arcofi_state = ARCOFI_NOP; 88 wake_up(&cs->dc.isac.arcofi_wait); 89 } 90 } 91 } 92 break; 93 case ARCOFI_RECEIVE: 94 if (event == ARCOFI_RX_END) { 95 if (cs->dc.isac.arcofi_list->next) { 96 cs->dc.isac.arcofi_list = 97 cs->dc.isac.arcofi_list->next; 98 cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT; 99 send_arcofi(cs); 100 } else { 101 if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { 102 del_timer(&cs->dc.isac.arcofitimer); 103 } 104 cs->dc.isac.arcofi_state = ARCOFI_NOP; 105 wake_up(&cs->dc.isac.arcofi_wait); 106 } 107 } 108 break; 109 default: 110 debugl1(cs, "Arcofi unknown state %x", cs->dc.isac.arcofi_state); 111 return(2); 112 } 113 return(0); 114} 115 116static void 117arcofi_timer(struct IsdnCardState *cs) { 118 arcofi_fsm(cs, ARCOFI_TIMEOUT, NULL); 119} 120 121void 122clear_arcofi(struct IsdnCardState *cs) { 123 if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { 124 del_timer(&cs->dc.isac.arcofitimer); 125 } 126} 127 128void 129init_arcofi(struct IsdnCardState *cs) { 130 cs->dc.isac.arcofitimer.function = (void *) arcofi_timer; 131 cs->dc.isac.arcofitimer.data = (long) cs; 132 init_timer(&cs->dc.isac.arcofitimer); 133 init_waitqueue_head(&cs->dc.isac.arcofi_wait); 134 test_and_set_bit(HW_ARCOFI, &cs->HW_Flags); 135} 136