Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);