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