linux/drivers/isdn/hisax/arcofi.c
<<
>>
Prefs
   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        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