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