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