^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * isac.c ISAC specific routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author Karsten Keil <keil@isdn4linux.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/irqreturn.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mISDNhw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "ipac.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define DBUSY_TIMER_VALUE 80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define ARCOFI_USE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define ISAC_REV "2.0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) MODULE_AUTHOR("Karsten Keil");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) MODULE_VERSION(ISAC_REV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define ReadISAC(is, o) (is->read_reg(is->dch.hw, o + is->off))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define WriteISAC(is, o, v) (is->write_reg(is->dch.hw, o + is->off, v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define ReadHSCX(h, o) (h->ip->read_reg(h->ip->hw, h->off + o))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define WriteHSCX(h, o, v) (h->ip->write_reg(h->ip->hw, h->off + o, v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define ReadIPAC(ip, o) (ip->read_reg(ip->hw, o))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define WriteIPAC(ip, o, v) (ip->write_reg(ip->hw, o, v))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) ph_command(struct isac_hw *isac, u8 command)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) pr_debug("%s: ph_command %x\n", isac->name, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (isac->type & IPAC_TYPE_ISACX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) WriteISAC(isac, ISACX_CIX0, (command << 4) | 0xE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) WriteISAC(isac, ISAC_CIX0, (command << 2) | 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) isac_ph_state_change(struct isac_hw *isac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) switch (isac->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) case (ISAC_IND_RS):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) case (ISAC_IND_EI):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ph_command(isac, ISAC_CMD_DUI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) schedule_event(&isac->dch, FLG_PHCHANGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) isac_ph_state_bh(struct dchannel *dch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) switch (isac->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) case ISAC_IND_RS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) case ISAC_IND_EI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) dch->state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) l1_event(dch->l1, HW_RESET_IND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) case ISAC_IND_DID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) dch->state = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) l1_event(dch->l1, HW_DEACT_CNF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) case ISAC_IND_DR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) case ISAC_IND_DR6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) dch->state = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) l1_event(dch->l1, HW_DEACT_IND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) case ISAC_IND_PU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) dch->state = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) l1_event(dch->l1, HW_POWERUP_IND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) case ISAC_IND_RSY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (dch->state <= 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) dch->state = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) l1_event(dch->l1, ANYSIGNAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) dch->state = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) l1_event(dch->l1, LOSTFRAMING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) case ISAC_IND_ARD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) dch->state = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) l1_event(dch->l1, INFO2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) case ISAC_IND_AI8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) dch->state = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) l1_event(dch->l1, INFO4_P8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) case ISAC_IND_AI10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) dch->state = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) l1_event(dch->l1, INFO4_P10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) pr_debug("%s: TE newstate %x\n", isac->name, dch->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) isac_empty_fifo(struct isac_hw *isac, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) u8 *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) pr_debug("%s: %s %d\n", isac->name, __func__, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (!isac->dch.rx_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) isac->dch.rx_skb = mI_alloc_skb(isac->dch.maxlen, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!isac->dch.rx_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) pr_info("%s: D receive out of memory\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) WriteISAC(isac, ISAC_CMDR, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if ((isac->dch.rx_skb->len + count) >= isac->dch.maxlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) pr_debug("%s: %s overrun %d\n", isac->name, __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) isac->dch.rx_skb->len + count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) WriteISAC(isac, ISAC_CMDR, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ptr = skb_put(isac->dch.rx_skb, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) isac->read_fifo(isac->dch.hw, isac->off, ptr, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) WriteISAC(isac, ISAC_CMDR, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (isac->dch.debug & DEBUG_HW_DFIFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) char pfx[MISDN_MAX_IDLEN + 16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-recv %s %d ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) isac->name, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) isac_fill_fifo(struct isac_hw *isac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) int count, more;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) u8 *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (!isac->dch.tx_skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) count = isac->dch.tx_skb->len - isac->dch.tx_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (count <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) more = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (count > 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) more = !0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) count = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) pr_debug("%s: %s %d\n", isac->name, __func__, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ptr = isac->dch.tx_skb->data + isac->dch.tx_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) isac->dch.tx_idx += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) isac->write_fifo(isac->dch.hw, isac->off, ptr, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) WriteISAC(isac, ISAC_CMDR, more ? 0x8 : 0xa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (test_and_set_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) pr_debug("%s: %s dbusytimer running\n", isac->name, __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) del_timer(&isac->dch.timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) isac->dch.timer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) add_timer(&isac->dch.timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (isac->dch.debug & DEBUG_HW_DFIFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) char pfx[MISDN_MAX_IDLEN + 16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) snprintf(pfx, MISDN_MAX_IDLEN + 15, "D-send %s %d ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) isac->name, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) print_hex_dump_bytes(pfx, DUMP_PREFIX_OFFSET, ptr, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) isac_rme_irq(struct isac_hw *isac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) u8 val, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) val = ReadISAC(isac, ISAC_RSTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if ((val & 0x70) != 0x20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (val & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) pr_debug("%s: ISAC RDO\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #ifdef ERROR_STATISTIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) isac->dch.err_rx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (!(val & 0x20)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) pr_debug("%s: ISAC CRC error\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #ifdef ERROR_STATISTIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) isac->dch.err_crc++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) WriteISAC(isac, ISAC_CMDR, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) dev_kfree_skb(isac->dch.rx_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) isac->dch.rx_skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) count = ReadISAC(isac, ISAC_RBCL) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) count = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) isac_empty_fifo(isac, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) recv_Dchannel(&isac->dch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) isac_xpr_irq(struct isac_hw *isac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) del_timer(&isac->dch.timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (isac->dch.tx_skb && isac->dch.tx_idx < isac->dch.tx_skb->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) isac_fill_fifo(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) dev_kfree_skb(isac->dch.tx_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (get_next_dframe(&isac->dch))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) isac_fill_fifo(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) isac_retransmit(struct isac_hw *isac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) del_timer(&isac->dch.timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (test_bit(FLG_TX_BUSY, &isac->dch.Flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* Restart frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) isac->dch.tx_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) isac_fill_fifo(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) } else if (isac->dch.tx_skb) { /* should not happen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) pr_info("%s: tx_skb exist but not busy\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) test_and_set_bit(FLG_TX_BUSY, &isac->dch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) isac->dch.tx_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) isac_fill_fifo(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) pr_info("%s: ISAC XDU no TX_BUSY\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (get_next_dframe(&isac->dch))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) isac_fill_fifo(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) isac_mos_irq(struct isac_hw *isac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) val = ReadISAC(isac, ISAC_MOSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) pr_debug("%s: ISAC MOSR %02x\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #if ARCOFI_USE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (val & 0x08) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (!isac->mon_rx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (!isac->mon_rx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) pr_info("%s: ISAC MON RX out of memory!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) isac->mocr &= 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) isac->mocr |= 0x0a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) goto afterMONR0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) isac->mon_rxp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (isac->mon_rxp >= MAX_MON_FRAME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) isac->mocr &= 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) isac->mocr |= 0x0a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) isac->mon_rxp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) pr_debug("%s: ISAC MON RX overflow!\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) goto afterMONR0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) pr_debug("%s: ISAC MOR0 %02x\n", isac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) isac->mon_rx[isac->mon_rxp - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (isac->mon_rxp == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) isac->mocr |= 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) afterMONR0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (val & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (!isac->mon_rx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) isac->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (!isac->mon_rx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) pr_info("%s: ISAC MON RX out of memory!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) isac->mocr &= 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) isac->mocr |= 0xa0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) goto afterMONR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) isac->mon_rxp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (isac->mon_rxp >= MAX_MON_FRAME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) isac->mocr &= 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) isac->mocr |= 0xa0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) isac->mon_rxp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) pr_debug("%s: ISAC MON RX overflow!\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) goto afterMONR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) isac->mon_rx[isac->mon_rxp++] = ReadISAC(isac, ISAC_MOR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) pr_debug("%s: ISAC MOR1 %02x\n", isac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) isac->mon_rx[isac->mon_rxp - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) isac->mocr |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) afterMONR1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (val & 0x04) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) isac->mocr &= 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) isac->mocr |= 0x0a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (isac->monitor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) ret = isac->monitor(isac->dch.hw, MONITOR_RX_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) isac->mon_rx, isac->mon_rxp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) kfree(isac->mon_rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) pr_info("%s: MONITOR 0 received %d but no user\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) isac->name, isac->mon_rxp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) kfree(isac->mon_rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) isac->mon_rx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) isac->mon_rxp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (val & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) isac->mocr &= 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) isac->mocr |= 0xa0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (isac->monitor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ret = isac->monitor(isac->dch.hw, MONITOR_RX_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) isac->mon_rx, isac->mon_rxp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) kfree(isac->mon_rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) pr_info("%s: MONITOR 1 received %d but no user\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) isac->name, isac->mon_rxp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) kfree(isac->mon_rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) isac->mon_rx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) isac->mon_rxp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (val & 0x02) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if ((!isac->mon_tx) || (isac->mon_txc &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) (isac->mon_txp >= isac->mon_txc) && !(val & 0x08))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) isac->mocr &= 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) isac->mocr |= 0x0a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (isac->monitor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) isac->monitor(isac->dch.hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) MONITOR_TX_0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) kfree(isac->mon_tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) isac->mon_tx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) isac->mon_txc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) isac->mon_txp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) goto AfterMOX0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (isac->monitor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) isac->monitor(isac->dch.hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) MONITOR_TX_0, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) kfree(isac->mon_tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) isac->mon_tx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) isac->mon_txc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) isac->mon_txp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) goto AfterMOX0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) WriteISAC(isac, ISAC_MOX0, isac->mon_tx[isac->mon_txp++]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) pr_debug("%s: ISAC %02x -> MOX0\n", isac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) isac->mon_tx[isac->mon_txp - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) AfterMOX0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (val & 0x20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if ((!isac->mon_tx) || (isac->mon_txc &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) (isac->mon_txp >= isac->mon_txc) && !(val & 0x80))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) isac->mocr &= 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) isac->mocr |= 0xa0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) WriteISAC(isac, ISAC_MOCR, isac->mocr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (isac->monitor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) isac->monitor(isac->dch.hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) MONITOR_TX_1, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) kfree(isac->mon_tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) isac->mon_tx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) isac->mon_txc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) isac->mon_txp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) goto AfterMOX1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (isac->mon_txc && (isac->mon_txp >= isac->mon_txc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (isac->monitor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) isac->monitor(isac->dch.hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) MONITOR_TX_1, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) kfree(isac->mon_tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) isac->mon_tx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) isac->mon_txc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) isac->mon_txp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) goto AfterMOX1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) WriteISAC(isac, ISAC_MOX1, isac->mon_tx[isac->mon_txp++]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) pr_debug("%s: ISAC %02x -> MOX1\n", isac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) isac->mon_tx[isac->mon_txp - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) AfterMOX1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) val = 0; /* dummy to avoid warning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) isac_cisq_irq(struct isac_hw *isac) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) val = ReadISAC(isac, ISAC_CIR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) pr_debug("%s: ISAC CIR0 %02X\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (val & 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) pr_debug("%s: ph_state change %x->%x\n", isac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) isac->state, (val >> 2) & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) isac->state = (val >> 2) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) isac_ph_state_change(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (val & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) val = ReadISAC(isac, ISAC_CIR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) pr_debug("%s: ISAC CIR1 %02X\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) isacsx_cic_irq(struct isac_hw *isac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) val = ReadISAC(isac, ISACX_CIR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (val & ISACX_CIR0_CIC0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) pr_debug("%s: ph_state change %x->%x\n", isac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) isac->state, val >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) isac->state = val >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) isac_ph_state_change(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) isacsx_rme_irq(struct isac_hw *isac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) val = ReadISAC(isac, ISACX_RSTAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if ((val & (ISACX_RSTAD_VFR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ISACX_RSTAD_RDO |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) ISACX_RSTAD_CRC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ISACX_RSTAD_RAB))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) != (ISACX_RSTAD_VFR | ISACX_RSTAD_CRC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) pr_debug("%s: RSTAD %#x, dropped\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) #ifdef ERROR_STATISTIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (val & ISACX_RSTAD_CRC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) isac->dch.err_rx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) isac->dch.err_crc++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) dev_kfree_skb(isac->dch.rx_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) isac->dch.rx_skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) count = ReadISAC(isac, ISACX_RBCLD) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) count = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) isac_empty_fifo(isac, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (isac->dch.rx_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) skb_trim(isac->dch.rx_skb, isac->dch.rx_skb->len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) pr_debug("%s: dchannel received %d\n", isac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) isac->dch.rx_skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) recv_Dchannel(&isac->dch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) irqreturn_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) mISDNisac_irq(struct isac_hw *isac, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (unlikely(!val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) pr_debug("%s: ISAC interrupt %02x\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (isac->type & IPAC_TYPE_ISACX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (val & ISACX__CIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) isacsx_cic_irq(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (val & ISACX__ICD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) val = ReadISAC(isac, ISACX_ISTAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) pr_debug("%s: ISTAD %02x\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (val & ISACX_D_XDU) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) pr_debug("%s: ISAC XDU\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) #ifdef ERROR_STATISTIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) isac->dch.err_tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) isac_retransmit(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (val & ISACX_D_XMR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) pr_debug("%s: ISAC XMR\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) #ifdef ERROR_STATISTIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) isac->dch.err_tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) isac_retransmit(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (val & ISACX_D_XPR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) isac_xpr_irq(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (val & ISACX_D_RFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) pr_debug("%s: ISAC RFO\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (val & ISACX_D_RME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) isacsx_rme_irq(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (val & ISACX_D_RPF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) isac_empty_fifo(isac, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (val & 0x80) /* RME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) isac_rme_irq(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (val & 0x40) /* RPF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) isac_empty_fifo(isac, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (val & 0x10) /* XPR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) isac_xpr_irq(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (val & 0x04) /* CISQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) isac_cisq_irq(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (val & 0x20) /* RSC - never */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) pr_debug("%s: ISAC RSC interrupt\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (val & 0x02) /* SIN - never */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) pr_debug("%s: ISAC SIN interrupt\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (val & 0x01) { /* EXI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) val = ReadISAC(isac, ISAC_EXIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) pr_debug("%s: ISAC EXIR %02x\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (val & 0x80) /* XMR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) pr_debug("%s: ISAC XMR\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (val & 0x40) { /* XDU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) pr_debug("%s: ISAC XDU\n", isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) #ifdef ERROR_STATISTIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) isac->dch.err_tx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) isac_retransmit(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (val & 0x04) /* MOS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) isac_mos_irq(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) EXPORT_SYMBOL(mISDNisac_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) isac_l1hw(struct mISDNchannel *ch, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct dchannel *dch = container_of(dev, struct dchannel, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) struct mISDNhead *hh = mISDN_HEAD_P(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) u_long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) switch (hh->prim) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) case PH_DATA_REQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) spin_lock_irqsave(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) ret = dchannel_senddata(dch, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (ret > 0) { /* direct TX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) id = hh->id; /* skb can be freed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) isac_fill_fifo(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) spin_unlock_irqrestore(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) queue_ch_frame(ch, PH_DATA_CNF, id, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) spin_unlock_irqrestore(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) case PH_ACTIVATE_REQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) ret = l1_event(dch->l1, hh->prim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) case PH_DEACTIVATE_REQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) ret = l1_event(dch->l1, hh->prim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) isac_ctrl(struct isac_hw *isac, u32 cmd, unsigned long para)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) u8 tl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) case HW_TESTLOOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) spin_lock_irqsave(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (!(isac->type & IPAC_TYPE_ISACX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) /* TODO: implement for IPAC_TYPE_ISACX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (para & 1) /* B1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) tl |= 0x0c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) else if (para & 2) /* B2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) tl |= 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* we only support IOM2 mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) WriteISAC(isac, ISAC_SPCR, tl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (tl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) WriteISAC(isac, ISAC_ADF1, 0x8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) WriteISAC(isac, ISAC_ADF1, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) spin_unlock_irqrestore(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) case HW_TIMER3_VALUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) ret = l1_event(isac->dch.l1, HW_TIMER3_VALUE | (para & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) pr_debug("%s: %s unknown command %x %lx\n", isac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) __func__, cmd, para);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) isac_l1cmd(struct dchannel *dch, u32 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) u_long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) pr_debug("%s: cmd(%x) state(%02x)\n", isac->name, cmd, isac->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) case INFO3_P8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) spin_lock_irqsave(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) ph_command(isac, ISAC_CMD_AR8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) spin_unlock_irqrestore(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) case INFO3_P10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) spin_lock_irqsave(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) ph_command(isac, ISAC_CMD_AR10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) spin_unlock_irqrestore(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) case HW_RESET_REQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) spin_lock_irqsave(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if ((isac->state == ISAC_IND_EI) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) (isac->state == ISAC_IND_DR) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) (isac->state == ISAC_IND_DR6) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) (isac->state == ISAC_IND_RS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ph_command(isac, ISAC_CMD_TIM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) ph_command(isac, ISAC_CMD_RS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) spin_unlock_irqrestore(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) case HW_DEACT_REQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) skb_queue_purge(&dch->squeue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (dch->tx_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) dev_kfree_skb(dch->tx_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) dch->tx_skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) dch->tx_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (dch->rx_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) dev_kfree_skb(dch->rx_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) dch->rx_skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) del_timer(&dch->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) case HW_POWERUP_REQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) spin_lock_irqsave(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) ph_command(isac, ISAC_CMD_TIM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) spin_unlock_irqrestore(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) case PH_ACTIVATE_IND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) test_and_set_bit(FLG_ACTIVE, &dch->Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) case PH_DEACTIVATE_IND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) pr_debug("%s: %s unknown command %x\n", isac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) __func__, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) isac_release(struct isac_hw *isac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (isac->type & IPAC_TYPE_ISACX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) WriteISAC(isac, ISACX_MASK, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) else if (isac->type != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) WriteISAC(isac, ISAC_MASK, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (isac->dch.timer.function != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) del_timer(&isac->dch.timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) isac->dch.timer.function = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) kfree(isac->mon_rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) isac->mon_rx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) kfree(isac->mon_tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) isac->mon_tx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (isac->dch.l1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) l1_event(isac->dch.l1, CLOSE_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) mISDN_freedchannel(&isac->dch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) dbusy_timer_handler(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct isac_hw *isac = from_timer(isac, t, dch.timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) int rbch, star;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) u_long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (test_bit(FLG_BUSY_TIMER, &isac->dch.Flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) spin_lock_irqsave(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) rbch = ReadISAC(isac, ISAC_RBCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) star = ReadISAC(isac, ISAC_STAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) pr_debug("%s: D-Channel Busy RBCH %02x STAR %02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) isac->name, rbch, star);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (rbch & ISAC_RBCH_XAC) /* D-Channel Busy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) test_and_set_bit(FLG_L1_BUSY, &isac->dch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) /* discard frame; reset transceiver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) test_and_clear_bit(FLG_BUSY_TIMER, &isac->dch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (isac->dch.tx_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) isac->dch.tx_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) pr_info("%s: ISAC D-Channel Busy no tx_idx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) isac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) /* Transmitter reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) WriteISAC(isac, ISAC_CMDR, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) spin_unlock_irqrestore(isac->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) open_dchannel_caller(struct isac_hw *isac, struct channel_req *rq, void *caller)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) pr_debug("%s: %s dev(%d) open from %p\n", isac->name, __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) isac->dch.dev.id, caller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (rq->protocol != ISDN_P_TE_S0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (rq->adr.channel == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) /* E-Channel not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) rq->ch = &isac->dch.dev.D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) rq->ch->protocol = rq->protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (isac->dch.state == 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) _queue_data(rq->ch, PH_ACTIVATE_IND, MISDN_ID_ANY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 0, NULL, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) open_dchannel(struct isac_hw *isac, struct channel_req *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return open_dchannel_caller(isac, rq, __builtin_return_address(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) static const char *ISACVer[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) {"2086/2186 V1.1", "2085 B1", "2085 B2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) "2085 V2.3"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) isac_init(struct isac_hw *isac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (!isac->dch.l1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) err = create_l1(&isac->dch, isac_l1cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) isac->mon_tx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) isac->mon_rx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) timer_setup(&isac->dch.timer, dbusy_timer_handler, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) isac->mocr = 0xaa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (isac->type & IPAC_TYPE_ISACX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) /* Disable all IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) WriteISAC(isac, ISACX_MASK, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) val = ReadISAC(isac, ISACX_STARD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) pr_debug("%s: ISACX STARD %x\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) val = ReadISAC(isac, ISACX_ISTAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) pr_debug("%s: ISACX ISTAD %x\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) val = ReadISAC(isac, ISACX_ISTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) pr_debug("%s: ISACX ISTA %x\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) /* clear LDD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) WriteISAC(isac, ISACX_TR_CONF0, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /* enable transmitter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) WriteISAC(isac, ISACX_TR_CONF2, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /* transparent mode 0, RAC, stop/go */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) WriteISAC(isac, ISACX_MODED, 0xc9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) /* all HDLC IRQ unmasked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) val = ReadISAC(isac, ISACX_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (isac->dch.debug & DEBUG_HW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) pr_notice("%s: ISACX Design ID %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) isac->name, val & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) val = ReadISAC(isac, ISACX_CIR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) pr_debug("%s: ISACX CIR0 %02X\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) isac->state = val >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) isac_ph_state_change(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) ph_command(isac, ISAC_CMD_RS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) WriteISAC(isac, ISACX_MASK, IPACX__ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) WriteISAC(isac, ISACX_MASKD, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) } else { /* old isac */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) WriteISAC(isac, ISAC_MASK, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) val = ReadISAC(isac, ISAC_STAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) pr_debug("%s: ISAC STAR %x\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) val = ReadISAC(isac, ISAC_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) pr_debug("%s: ISAC MODE %x\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) val = ReadISAC(isac, ISAC_ADF2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) pr_debug("%s: ISAC ADF2 %x\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) val = ReadISAC(isac, ISAC_ISTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) pr_debug("%s: ISAC ISTA %x\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (val & 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) val = ReadISAC(isac, ISAC_EXIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) pr_debug("%s: ISAC EXIR %x\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) val = ReadISAC(isac, ISAC_RBCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (isac->dch.debug & DEBUG_HW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) pr_notice("%s: ISAC version (%x): %s\n", isac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) val, ISACVer[(val >> 5) & 3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) isac->type |= ((val >> 5) & 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (!isac->adf2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) isac->adf2 = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (!(isac->adf2 & 0x80)) { /* only IOM 2 Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) pr_info("%s: only support IOM2 mode but adf2=%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) isac->name, isac->adf2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) isac_release(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) WriteISAC(isac, ISAC_ADF2, isac->adf2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) WriteISAC(isac, ISAC_SQXR, 0x2f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) WriteISAC(isac, ISAC_SPCR, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) WriteISAC(isac, ISAC_STCR, 0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) WriteISAC(isac, ISAC_MODE, 0xc9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) WriteISAC(isac, ISAC_TIMR, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) WriteISAC(isac, ISAC_ADF1, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) val = ReadISAC(isac, ISAC_CIR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) pr_debug("%s: ISAC CIR0 %x\n", isac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) isac->state = (val >> 2) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) isac_ph_state_change(isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) ph_command(isac, ISAC_CMD_RS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) WriteISAC(isac, ISAC_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) mISDNisac_init(struct isac_hw *isac, void *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) mISDN_initdchannel(&isac->dch, MAX_DFRAME_LEN_L1, isac_ph_state_bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) isac->dch.hw = hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) isac->dch.dev.D.send = isac_l1hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) isac->init = isac_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) isac->release = isac_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) isac->ctrl = isac_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) isac->open = open_dchannel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) isac->dch.dev.Dprotocols = (1 << ISDN_P_TE_S0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) isac->dch.dev.nrbchan = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) EXPORT_SYMBOL(mISDNisac_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) waitforCEC(struct hscx_hw *hx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) u8 starb, to = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) while (to) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) starb = ReadHSCX(hx, IPAC_STARB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (!(starb & 0x04))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) to--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (to < 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) pr_debug("%s: B%1d CEC %d us\n", hx->ip->name, hx->bch.nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 50 - to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (!to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) pr_info("%s: B%1d CEC timeout\n", hx->ip->name, hx->bch.nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) waitforXFW(struct hscx_hw *hx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) u8 starb, to = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) while (to) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) starb = ReadHSCX(hx, IPAC_STARB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if ((starb & 0x44) == 0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) to--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if (to < 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) pr_debug("%s: B%1d XFW %d us\n", hx->ip->name, hx->bch.nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) 50 - to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (!to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) pr_info("%s: B%1d XFW timeout\n", hx->ip->name, hx->bch.nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) hscx_cmdr(struct hscx_hw *hx, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (hx->ip->type & IPAC_TYPE_IPACX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) WriteHSCX(hx, IPACX_CMDRB, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) waitforCEC(hx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) WriteHSCX(hx, IPAC_CMDRB, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) hscx_empty_fifo(struct hscx_hw *hscx, u8 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) u8 *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) int maxlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) pr_debug("%s: B%1d %d\n", hscx->ip->name, hscx->bch.nr, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) if (test_bit(FLG_RX_OFF, &hscx->bch.Flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) hscx->bch.dropcnt += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) hscx_cmdr(hscx, 0x80); /* RMC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) maxlen = bchannel_get_rxbuf(&hscx->bch, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) if (maxlen < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) hscx_cmdr(hscx, 0x80); /* RMC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) if (hscx->bch.rx_skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) skb_trim(hscx->bch.rx_skb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) pr_warn("%s.B%d: No bufferspace for %d bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) hscx->ip->name, hscx->bch.nr, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) p = skb_put(hscx->bch.rx_skb, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (hscx->ip->type & IPAC_TYPE_IPACX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) hscx->ip->read_fifo(hscx->ip->hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) hscx->off + IPACX_RFIFOB, p, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) hscx->ip->read_fifo(hscx->ip->hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) hscx->off, p, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) hscx_cmdr(hscx, 0x80); /* RMC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) if (hscx->bch.debug & DEBUG_HW_BFIFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) snprintf(hscx->log, 64, "B%1d-recv %s %d ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) hscx->bch.nr, hscx->ip->name, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) hscx_fill_fifo(struct hscx_hw *hscx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) int count, more;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) u8 *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (!hscx->bch.tx_skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (!test_bit(FLG_TX_EMPTY, &hscx->bch.Flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) count = hscx->fifo_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) more = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) p = hscx->log;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) memset(p, hscx->bch.fill[0], count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) count = hscx->bch.tx_skb->len - hscx->bch.tx_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if (count <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) p = hscx->bch.tx_skb->data + hscx->bch.tx_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) more = test_bit(FLG_TRANSPARENT, &hscx->bch.Flags) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (count > hscx->fifo_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) count = hscx->fifo_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) more = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) pr_debug("%s: B%1d %d/%d/%d\n", hscx->ip->name, hscx->bch.nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) count, hscx->bch.tx_idx, hscx->bch.tx_skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) hscx->bch.tx_idx += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (hscx->ip->type & IPAC_TYPE_IPACX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) hscx->ip->write_fifo(hscx->ip->hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) hscx->off + IPACX_XFIFOB, p, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) waitforXFW(hscx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) hscx->ip->write_fifo(hscx->ip->hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) hscx->off, p, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) hscx_cmdr(hscx, more ? 0x08 : 0x0a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) if (hscx->bch.tx_skb && (hscx->bch.debug & DEBUG_HW_BFIFO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) snprintf(hscx->log, 64, "B%1d-send %s %d ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) hscx->bch.nr, hscx->ip->name, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) print_hex_dump_bytes(hscx->log, DUMP_PREFIX_OFFSET, p, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) hscx_xpr(struct hscx_hw *hx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) hscx_fill_fifo(hx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) dev_kfree_skb(hx->bch.tx_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (get_next_bframe(&hx->bch)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) hscx_fill_fifo(hx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) test_and_clear_bit(FLG_TX_EMPTY, &hx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) } else if (test_bit(FLG_TX_EMPTY, &hx->bch.Flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) hscx_fill_fifo(hx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) ipac_rme(struct hscx_hw *hx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) u8 rstab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) if (hx->ip->type & IPAC_TYPE_IPACX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) rstab = ReadHSCX(hx, IPACX_RSTAB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) rstab = ReadHSCX(hx, IPAC_RSTAB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) pr_debug("%s: B%1d RSTAB %02x\n", hx->ip->name, hx->bch.nr, rstab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) if ((rstab & 0xf0) != 0xa0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) /* !(VFR && !RDO && CRC && !RAB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if (!(rstab & 0x80)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (hx->bch.debug & DEBUG_HW_BCHANNEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) pr_notice("%s: B%1d invalid frame\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) hx->ip->name, hx->bch.nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (rstab & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (hx->bch.debug & DEBUG_HW_BCHANNEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) pr_notice("%s: B%1d RDO proto=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) hx->ip->name, hx->bch.nr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) hx->bch.state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if (!(rstab & 0x20)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) if (hx->bch.debug & DEBUG_HW_BCHANNEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) pr_notice("%s: B%1d CRC error\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) hx->ip->name, hx->bch.nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) hscx_cmdr(hx, 0x80); /* Do RMC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (hx->ip->type & IPAC_TYPE_IPACX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) count = ReadHSCX(hx, IPACX_RBCLB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) count = ReadHSCX(hx, IPAC_RBCLB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) count &= (hx->fifo_size - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) count = hx->fifo_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) hscx_empty_fifo(hx, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (!hx->bch.rx_skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) if (hx->bch.rx_skb->len < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) pr_debug("%s: B%1d frame to short %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) hx->ip->name, hx->bch.nr, hx->bch.rx_skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) skb_trim(hx->bch.rx_skb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) skb_trim(hx->bch.rx_skb, hx->bch.rx_skb->len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) recv_Bchannel(&hx->bch, 0, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) ipac_irq(struct hscx_hw *hx, u8 ista)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) u8 istab, m, exirb = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) if (hx->ip->type & IPAC_TYPE_IPACX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) istab = ReadHSCX(hx, IPACX_ISTAB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) else if (hx->ip->type & IPAC_TYPE_IPAC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) istab = ReadHSCX(hx, IPAC_ISTAB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) m = (hx->bch.nr & 1) ? IPAC__EXA : IPAC__EXB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (m & ista) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) exirb = ReadHSCX(hx, IPAC_EXIRB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) hx->bch.nr, exirb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) } else if (hx->bch.nr & 2) { /* HSCX B */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (ista & (HSCX__EXA | HSCX__ICA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) ipac_irq(&hx->ip->hscx[0], ista);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (ista & HSCX__EXB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) exirb = ReadHSCX(hx, IPAC_EXIRB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) hx->bch.nr, exirb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) istab = ista & 0xF8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) } else { /* HSCX A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) istab = ReadHSCX(hx, IPAC_ISTAB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (ista & HSCX__EXA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) exirb = ReadHSCX(hx, IPAC_EXIRB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) pr_debug("%s: B%1d EXIRB %02x\n", hx->ip->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) hx->bch.nr, exirb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) istab = istab & 0xF8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (exirb & IPAC_B_XDU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) istab |= IPACX_B_XDU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) if (exirb & IPAC_B_RFO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) istab |= IPACX_B_RFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) pr_debug("%s: B%1d ISTAB %02x\n", hx->ip->name, hx->bch.nr, istab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) if (!test_bit(FLG_ACTIVE, &hx->bch.Flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (istab & IPACX_B_RME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) ipac_rme(hx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (istab & IPACX_B_RPF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) hscx_empty_fifo(hx, hx->fifo_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) recv_Bchannel(&hx->bch, 0, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (istab & IPACX_B_RFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) pr_debug("%s: B%1d RFO error\n", hx->ip->name, hx->bch.nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) hscx_cmdr(hx, 0x40); /* RRES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (istab & IPACX_B_XPR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) hscx_xpr(hx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) if (istab & IPACX_B_XDU) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) if (test_bit(FLG_TRANSPARENT, &hx->bch.Flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (test_bit(FLG_FILLEMPTY, &hx->bch.Flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) test_and_set_bit(FLG_TX_EMPTY, &hx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) hscx_xpr(hx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) pr_debug("%s: B%1d XDU error at len %d\n", hx->ip->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) hx->bch.nr, hx->bch.tx_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) hx->bch.tx_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) hscx_cmdr(hx, 0x01); /* XRES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) irqreturn_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) int cnt = maxloop + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) u8 ista, istad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) struct isac_hw *isac = &ipac->isac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) if (ipac->type & IPAC_TYPE_IPACX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) ista = ReadIPAC(ipac, ISACX_ISTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) while (ista && --cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) pr_debug("%s: ISTA %02x\n", ipac->name, ista);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) if (ista & IPACX__ICA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) ipac_irq(&ipac->hscx[0], ista);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) if (ista & IPACX__ICB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) ipac_irq(&ipac->hscx[1], ista);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (ista & (ISACX__ICD | ISACX__CIC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) mISDNisac_irq(&ipac->isac, ista);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) ista = ReadIPAC(ipac, ISACX_ISTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) } else if (ipac->type & IPAC_TYPE_IPAC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) ista = ReadIPAC(ipac, IPAC_ISTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) while (ista && --cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) pr_debug("%s: ISTA %02x\n", ipac->name, ista);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) if (ista & (IPAC__ICD | IPAC__EXD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) istad = ReadISAC(isac, ISAC_ISTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) pr_debug("%s: ISTAD %02x\n", ipac->name, istad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if (istad & IPAC_D_TIN2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) pr_debug("%s TIN2 irq\n", ipac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) if (ista & IPAC__EXD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) istad |= 1; /* ISAC EXI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) mISDNisac_irq(isac, istad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) if (ista & (IPAC__ICA | IPAC__EXA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) ipac_irq(&ipac->hscx[0], ista);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (ista & (IPAC__ICB | IPAC__EXB))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) ipac_irq(&ipac->hscx[1], ista);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) ista = ReadIPAC(ipac, IPAC_ISTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) } else if (ipac->type & IPAC_TYPE_HSCX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) while (--cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) ista = ReadIPAC(ipac, IPAC_ISTAB + ipac->hscx[1].off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) pr_debug("%s: B2 ISTA %02x\n", ipac->name, ista);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) if (ista)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) ipac_irq(&ipac->hscx[1], ista);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) istad = ReadISAC(isac, ISAC_ISTA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) pr_debug("%s: ISTAD %02x\n", ipac->name, istad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) if (istad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) mISDNisac_irq(isac, istad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (0 == (ista | istad))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (cnt > maxloop) /* only for ISAC/HSCX without PCI IRQ test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (cnt < maxloop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) pr_debug("%s: %d irqloops cpu%d\n", ipac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) maxloop - cnt, smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) if (maxloop && !cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) pr_notice("%s: %d IRQ LOOP cpu%d\n", ipac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) maxloop, smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) EXPORT_SYMBOL(mISDNipac_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) hscx_mode(struct hscx_hw *hscx, u32 bprotocol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) pr_debug("%s: HSCX %c protocol %x-->%x ch %d\n", hscx->ip->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) '@' + hscx->bch.nr, hscx->bch.state, bprotocol, hscx->bch.nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if (hscx->ip->type & IPAC_TYPE_IPACX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (hscx->bch.nr & 1) { /* B1 and ICA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) WriteIPAC(hscx->ip, ISACX_BCHA_TSDP_BC1, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) WriteIPAC(hscx->ip, ISACX_BCHA_CR, 0x88);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) } else { /* B2 and ICB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) WriteIPAC(hscx->ip, ISACX_BCHB_TSDP_BC1, 0x81);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) WriteIPAC(hscx->ip, ISACX_BCHB_CR, 0x88);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) switch (bprotocol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) case ISDN_P_NONE: /* init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) WriteHSCX(hscx, IPACX_MODEB, 0xC0); /* rec off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) WriteHSCX(hscx, IPACX_EXMB, 0x30); /* std adj. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) WriteHSCX(hscx, IPACX_MASKB, 0xFF); /* ints off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) hscx_cmdr(hscx, 0x41);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) case ISDN_P_B_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) WriteHSCX(hscx, IPACX_MODEB, 0x88); /* ex trans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) WriteHSCX(hscx, IPACX_EXMB, 0x00); /* trans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) hscx_cmdr(hscx, 0x41);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) WriteHSCX(hscx, IPACX_MASKB, IPACX_B_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) case ISDN_P_B_HDLC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) WriteHSCX(hscx, IPACX_MODEB, 0xC0); /* trans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) WriteHSCX(hscx, IPACX_EXMB, 0x00); /* hdlc,crc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) hscx_cmdr(hscx, 0x41);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) WriteHSCX(hscx, IPACX_MASKB, IPACX_B_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) pr_info("%s: protocol not known %x\n", hscx->ip->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) bprotocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) return -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) } else if (hscx->ip->type & IPAC_TYPE_IPAC) { /* IPAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) WriteHSCX(hscx, IPAC_CCR1, 0x82);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) WriteHSCX(hscx, IPAC_CCR2, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) WriteHSCX(hscx, IPAC_XCCR, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) WriteHSCX(hscx, IPAC_RCCR, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) WriteHSCX(hscx, IPAC_TSAX, hscx->slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) WriteHSCX(hscx, IPAC_TSAR, hscx->slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) switch (bprotocol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) case ISDN_P_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) WriteHSCX(hscx, IPAC_TSAX, 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) WriteHSCX(hscx, IPAC_TSAR, 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) WriteHSCX(hscx, IPAC_MODEB, 0x84);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) WriteHSCX(hscx, IPAC_CCR1, 0x82);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) WriteHSCX(hscx, IPAC_MASKB, 0xFF); /* ints off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) case ISDN_P_B_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) WriteHSCX(hscx, IPAC_MODEB, 0xe4); /* ex trans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) WriteHSCX(hscx, IPAC_CCR1, 0x82);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) hscx_cmdr(hscx, 0x41);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) WriteHSCX(hscx, IPAC_MASKB, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) case ISDN_P_B_HDLC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) WriteHSCX(hscx, IPAC_MODEB, 0x8c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) WriteHSCX(hscx, IPAC_CCR1, 0x8a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) hscx_cmdr(hscx, 0x41);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) WriteHSCX(hscx, IPAC_MASKB, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) pr_info("%s: protocol not known %x\n", hscx->ip->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) bprotocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) return -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) } else if (hscx->ip->type & IPAC_TYPE_HSCX) { /* HSCX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) WriteHSCX(hscx, IPAC_CCR1, 0x85);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) WriteHSCX(hscx, IPAC_CCR2, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) WriteHSCX(hscx, IPAC_XCCR, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) WriteHSCX(hscx, IPAC_RCCR, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) WriteHSCX(hscx, IPAC_TSAX, hscx->slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) WriteHSCX(hscx, IPAC_TSAR, hscx->slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) switch (bprotocol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) case ISDN_P_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) WriteHSCX(hscx, IPAC_TSAX, 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) WriteHSCX(hscx, IPAC_TSAR, 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) WriteHSCX(hscx, IPAC_MODEB, 0x84);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) WriteHSCX(hscx, IPAC_CCR1, 0x85);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) WriteHSCX(hscx, IPAC_MASKB, 0xFF); /* ints off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) test_and_clear_bit(FLG_HDLC, &hscx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) test_and_clear_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) case ISDN_P_B_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) WriteHSCX(hscx, IPAC_MODEB, 0xe4); /* ex trans */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) WriteHSCX(hscx, IPAC_CCR1, 0x85);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) hscx_cmdr(hscx, 0x41);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) WriteHSCX(hscx, IPAC_MASKB, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) test_and_set_bit(FLG_TRANSPARENT, &hscx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) case ISDN_P_B_HDLC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) WriteHSCX(hscx, IPAC_MODEB, 0x8c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) WriteHSCX(hscx, IPAC_CCR1, 0x8d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) hscx_cmdr(hscx, 0x41);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) WriteHSCX(hscx, IPAC_MASKB, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) test_and_set_bit(FLG_HDLC, &hscx->bch.Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) pr_info("%s: protocol not known %x\n", hscx->ip->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) bprotocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) return -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) hscx->bch.state = bprotocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) hscx_l2l1(struct mISDNchannel *ch, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) struct bchannel *bch = container_of(ch, struct bchannel, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) struct mISDNhead *hh = mISDN_HEAD_P(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) switch (hh->prim) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) case PH_DATA_REQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) spin_lock_irqsave(hx->ip->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) ret = bchannel_senddata(bch, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) if (ret > 0) { /* direct TX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) hscx_fill_fifo(hx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) spin_unlock_irqrestore(hx->ip->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) case PH_ACTIVATE_REQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) spin_lock_irqsave(hx->ip->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) ret = hscx_mode(hx, ch->protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) spin_unlock_irqrestore(hx->ip->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) NULL, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) case PH_DEACTIVATE_REQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) spin_lock_irqsave(hx->ip->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) mISDN_clear_bchannel(bch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) hscx_mode(hx, ISDN_P_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) spin_unlock_irqrestore(hx->ip->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) NULL, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) pr_info("%s: %s unknown prim(%x,%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) hx->ip->name, __func__, hh->prim, hh->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) return mISDN_ctrl_bchannel(bch, cq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) struct bchannel *bch = container_of(ch, struct bchannel, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) struct hscx_hw *hx = container_of(bch, struct hscx_hw, bch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) u_long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) pr_debug("%s: %s cmd:%x %p\n", hx->ip->name, __func__, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) case CLOSE_CHANNEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) test_and_clear_bit(FLG_OPEN, &bch->Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) cancel_work_sync(&bch->workq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) spin_lock_irqsave(hx->ip->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) mISDN_clear_bchannel(bch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) hscx_mode(hx, ISDN_P_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) spin_unlock_irqrestore(hx->ip->hwlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) ch->protocol = ISDN_P_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) ch->peer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) module_put(hx->ip->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) case CONTROL_CHANNEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) ret = channel_bctrl(bch, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) pr_info("%s: %s unknown prim(%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) hx->ip->name, __func__, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) free_ipac(struct ipac_hw *ipac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) isac_release(&ipac->isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) static const char *HSCXVer[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) {"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) hscx_init(struct hscx_hw *hx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) WriteHSCX(hx, IPAC_RAH2, 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) WriteHSCX(hx, IPAC_XBCH, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) WriteHSCX(hx, IPAC_RLCR, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) if (hx->ip->type & IPAC_TYPE_HSCX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) WriteHSCX(hx, IPAC_CCR1, 0x85);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) val = ReadHSCX(hx, HSCX_VSTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) pr_debug("%s: HSCX VSTR %02x\n", hx->ip->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) if (hx->bch.debug & DEBUG_HW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) pr_notice("%s: HSCX version %s\n", hx->ip->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) HSCXVer[val & 0x0f]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) WriteHSCX(hx, IPAC_CCR1, 0x82);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) WriteHSCX(hx, IPAC_CCR2, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) WriteHSCX(hx, IPAC_XCCR, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) WriteHSCX(hx, IPAC_RCCR, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) ipac_init(struct ipac_hw *ipac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) if (ipac->type & IPAC_TYPE_HSCX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) hscx_init(&ipac->hscx[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) hscx_init(&ipac->hscx[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) val = ReadIPAC(ipac, IPAC_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) } else if (ipac->type & IPAC_TYPE_IPAC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) hscx_init(&ipac->hscx[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) hscx_init(&ipac->hscx[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) WriteIPAC(ipac, IPAC_MASK, IPAC__ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) val = ReadIPAC(ipac, IPAC_CONF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) /* conf is default 0, but can be overwritten by card setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) pr_debug("%s: IPAC CONF %02x/%02x\n", ipac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) val, ipac->conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) WriteIPAC(ipac, IPAC_CONF, ipac->conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) val = ReadIPAC(ipac, IPAC_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (ipac->hscx[0].bch.debug & DEBUG_HW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) pr_notice("%s: IPAC Design ID %02x\n", ipac->name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) /* nothing special for IPACX to do here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) return isac_init(&ipac->isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) open_bchannel(struct ipac_hw *ipac, struct channel_req *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) struct bchannel *bch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) if (rq->adr.channel == 0 || rq->adr.channel > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) if (rq->protocol == ISDN_P_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) bch = &ipac->hscx[rq->adr.channel - 1].bch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) if (test_and_set_bit(FLG_OPEN, &bch->Flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) return -EBUSY; /* b-channel can be only open once */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) bch->ch.protocol = rq->protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) rq->ch = &bch->ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) channel_ctrl(struct ipac_hw *ipac, struct mISDN_ctrl_req *cq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) switch (cq->op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) case MISDN_CTRL_GETOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) case MISDN_CTRL_LOOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) if (cq->channel < 0 || cq->channel > 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) ret = ipac->ctrl(ipac, HW_TESTLOOP, cq->channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) case MISDN_CTRL_L1_TIMER3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) ret = ipac->isac.ctrl(&ipac->isac, HW_TIMER3_VALUE, cq->p1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) pr_info("%s: unknown CTRL OP %x\n", ipac->name, cq->op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) ipac_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) struct dchannel *dch = container_of(dev, struct dchannel, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) struct isac_hw *isac = container_of(dch, struct isac_hw, dch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) struct ipac_hw *ipac = container_of(isac, struct ipac_hw, isac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) struct channel_req *rq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) pr_debug("%s: DCTRL: %x %p\n", ipac->name, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) case OPEN_CHANNEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) rq = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) if (rq->protocol == ISDN_P_TE_S0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) err = open_dchannel_caller(isac, rq, __builtin_return_address(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) err = open_bchannel(ipac, rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) if (!try_module_get(ipac->owner))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) pr_info("%s: cannot get module\n", ipac->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) case CLOSE_CHANNEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) pr_debug("%s: dev(%d) close from %p\n", ipac->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) dch->dev.id, __builtin_return_address(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) module_put(ipac->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) case CONTROL_CHANNEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) err = channel_ctrl(ipac, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) pr_debug("%s: unknown DCTRL command %x\n", ipac->name, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) mISDNipac_init(struct ipac_hw *ipac, void *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) u32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) u8 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) ipac->hw = hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) if (ipac->isac.dch.debug & DEBUG_HW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) pr_notice("%s: ipac type %x\n", ipac->name, ipac->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) if (ipac->type & IPAC_TYPE_HSCX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) ipac->isac.type = IPAC_TYPE_ISAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) ipac->hscx[0].off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) ipac->hscx[1].off = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) ipac->hscx[0].fifo_size = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) ipac->hscx[1].fifo_size = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) } else if (ipac->type & IPAC_TYPE_IPAC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) ipac->isac.type = IPAC_TYPE_IPAC | IPAC_TYPE_ISAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) ipac->hscx[0].off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) ipac->hscx[1].off = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) ipac->hscx[0].fifo_size = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) ipac->hscx[1].fifo_size = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) } else if (ipac->type & IPAC_TYPE_IPACX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) ipac->isac.type = IPAC_TYPE_IPACX | IPAC_TYPE_ISACX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) ipac->hscx[0].off = IPACX_OFF_ICA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) ipac->hscx[1].off = IPACX_OFF_ICB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) ipac->hscx[0].fifo_size = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) ipac->hscx[1].fifo_size = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) mISDNisac_init(&ipac->isac, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) ipac->isac.dch.dev.D.ctrl = ipac_dctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) ipac->hscx[i].bch.nr = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) set_channelmap(i + 1, ipac->isac.dch.dev.channelmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) list_add(&ipac->hscx[i].bch.ch.list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) &ipac->isac.dch.dev.bchannels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) mISDN_initbchannel(&ipac->hscx[i].bch, MAX_DATA_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) ipac->hscx[i].fifo_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) ipac->hscx[i].bch.ch.nr = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) ipac->hscx[i].bch.ch.send = &hscx_l2l1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) ipac->hscx[i].bch.ch.ctrl = hscx_bctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) ipac->hscx[i].bch.hw = hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) ipac->hscx[i].ip = ipac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) /* default values for IOM time slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) * can be overwritten by card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) ipac->hscx[i].slot = (i == 0) ? 0x2f : 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) ipac->init = ipac_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) ipac->release = free_ipac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) ret = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) EXPORT_SYMBOL(mISDNipac_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) static int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) isac_mod_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) pr_notice("mISDNipac module version %s\n", ISAC_REV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) static void __exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) isac_mod_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) pr_notice("mISDNipac module unloaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) module_init(isac_mod_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) module_exit(isac_mod_cleanup);