11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* $Id: teleint.c,v 1.16.2.5 2004/01/19 15:31:50 keil Exp $
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * low level stuff for TeleInt isdn cards
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author       Karsten Keil
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright    by Karsten Keil      <keil@isdn4linux.de>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software may be used and distributed according to the terms
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the GNU General Public License, incorporated herein by reference.
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "hisax.h"
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "isac.h"
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "hfc_2bs0.h"
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "isdnl1.h"
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic const char *TeleInt_revision = "$Revision: 1.16.2.5 $";
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define byteout(addr,val) outb(val,addr)
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define bytein(addr) inb(addr)
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u_char
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreadreg(unsigned int ale, unsigned int adr, u_char off)
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register u_char ret;
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int max_delay = 2000;
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	byteout(ale, off);
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = HFC_BUSY & bytein(ale);
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (ret && --max_delay)
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = HFC_BUSY & bytein(ale);
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!max_delay) {
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "TeleInt Busy not inactive\n");
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = bytein(adr);
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (ret);
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreadfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register u_char ret;
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register int max_delay = 20000;
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register int i;
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	byteout(ale, off);
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i<size; i++) {
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = HFC_BUSY & bytein(ale);
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (ret && --max_delay)
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = HFC_BUSY & bytein(ale);
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!max_delay) {
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_WARNING "TeleInt Busy not inactive\n");
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data[i] = bytein(adr);
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldswritereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register u_char ret;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int max_delay = 2000;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	byteout(ale, off);
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = HFC_BUSY & bytein(ale);
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (ret && --max_delay)
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = HFC_BUSY & bytein(ale);
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!max_delay) {
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "TeleInt Busy not inactive\n");
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	byteout(adr, data);
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldswritefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register u_char ret;
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register int max_delay = 20000;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register int i;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	byteout(ale, off);
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i<size; i++) {
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = HFC_BUSY & bytein(ale);
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (ret && --max_delay)
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = HFC_BUSY & bytein(ale);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!max_delay) {
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_WARNING "TeleInt Busy not inactive\n");
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		byteout(adr, data[i]);
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Interface functions */
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_char
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsReadISAC(struct IsdnCardState *cs, u_char offset)
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.cip = offset;
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset));
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsWriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.cip = offset;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset, value);
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.cip = 0;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	readfifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsWriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.cip = 0;
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writefifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size);
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u_char
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsReadHFC(struct IsdnCardState *cs, int data, u_char reg)
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register u_char ret;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data) {
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfc.cip = reg;
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		byteout(cs->hw.hfc.addr | 1, reg);
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = bytein(cs->hw.hfc.addr);
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "hfc RD %02x %02x", reg, ret);
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = bytein(cs->hw.hfc.addr | 1);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (ret);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsWriteHFC(struct IsdnCardState *cs, int data, u_char reg, u_char value)
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	byteout(cs->hw.hfc.addr | 1, reg);
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.cip = reg;
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (data)
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		byteout(cs->hw.hfc.addr, value);
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		debugl1(cs, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value);
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic irqreturn_t
1587d12e780e003f93433d49ce78cfedf4b4c52adc5David HowellsTeleInt_interrupt(int intno, void *dev_id)
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct IsdnCardState *cs = dev_id;
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char val;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long flags;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&cs->lock, flags);
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      Start_ISAC:
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (val)
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		isac_interrupt(cs, val);
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (val) {
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_ISAC)
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "ISAC IntStat after IntRoutine");
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto Start_ISAC;
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF);
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0);
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&cs->lock, flags);
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_HANDLED;
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsTeleInt_Timer(struct IsdnCardState *cs)
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int stat = 0;
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long flags;
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&cs->lock, flags);
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->bcs[0].mode) {
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		stat |= 1;
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		main_irq_hfc(&cs->bcs[0]);
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->bcs[1].mode) {
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		stat |= 2;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		main_irq_hfc(&cs->bcs[1]);
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&cs->lock, flags);
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stat = HZ/100;
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!stat)
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		stat = 1;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.timer.expires = jiffies + stat;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	add_timer(&cs->hw.hfc.timer);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
204672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic void
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsrelease_io_TeleInt(struct IsdnCardState *cs)
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	del_timer(&cs->hw.hfc.timer);
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	releasehfc(cs);
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->hw.hfc.addr)
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		release_region(cs->hw.hfc.addr, 2);
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreset_TeleInt(struct IsdnCardState *cs)
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "TeleInt: resetting card\n");
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.cirm |= HFC_RESET;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);	/* Reset On */
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mdelay(10);
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.cirm &= ~HFC_RESET;
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);	/* Reset Off */
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mdelay(10);
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsTeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg)
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long flags;
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int delay;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (mt) {
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case CARD_RESET:
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_lock_irqsave(&cs->lock, flags);
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			reset_TeleInt(cs);
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(&cs->lock, flags);
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return(0);
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case CARD_RELEASE:
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			release_io_TeleInt(cs);
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return(0);
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case CARD_INIT:
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_lock_irqsave(&cs->lock, flags);
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			reset_TeleInt(cs);
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			inithfc(cs);
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			clear_pending_isac_ints(cs);
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			initisac(cs);
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Reenable all IRQ */
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->writeisac(cs, ISAC_MASK, 0);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->writeisac(cs, ISAC_CMDR, 0x41);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(&cs->lock, flags);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			delay = HZ/100;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!delay)
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				delay = 1;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->hw.hfc.timer.expires = jiffies + delay;
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			add_timer(&cs->hw.hfc.timer);
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return(0);
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case CARD_TEST:
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return(0);
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return(0);
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26267eb5db5874076db01febed5a1a9281628fa9fb4Karsten Keilint __devinit
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetup_TeleInt(struct IsdnCard *card)
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct IsdnCardState *cs = card->cs;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char tmp[64];
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strcpy(tmp, TeleInt_revision);
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp));
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->typ != ISDN_CTYPE_TELEINT)
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.addr = card->para[1] & 0x3fe;
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->irq = card->para[0];
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.cirm = HFC_CIRM;
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.isac_spcr = 0x00;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.cip = 0;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.ctmt = HFC_CTMT | HFC_CLTIMER;
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->bcs[0].hw.hfc.send = NULL;
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->bcs[1].hw.hfc.send = NULL;
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.fifosize = 7 * 1024 + 512;
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.timer.function = (void *) TeleInt_Timer;
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfc.timer.data = (long) cs;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_timer(&cs->hw.hfc.timer);
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!request_region(cs->hw.hfc.addr, 2, "TeleInt isdn")) {
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING
2878349304d12cf1313bdbd6eb2083701d86809be24Jeff Garzik		       "HiSax: TeleInt config port %x-%x already in use\n",
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       cs->hw.hfc.addr,
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       cs->hw.hfc.addr + 2);
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* HW IO = IO */
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54);
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cs->irq) {
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 3:
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->hw.hfc.cirm |= HFC_INTA;
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 4:
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->hw.hfc.cirm |= HFC_INTB;
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 5:
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->hw.hfc.cirm |= HFC_INTC;
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 7:
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->hw.hfc.cirm |= HFC_INTD;
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 10:
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->hw.hfc.cirm |= HFC_INTE;
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 11:
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->hw.hfc.cirm |= HFC_INTF;
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_WARNING "TeleInt: wrong IRQ\n");
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			release_io_TeleInt(cs);
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return (0);
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt);
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "TeleInt: defined at 0x%x IRQ %d\n",
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfc.addr, cs->irq);
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	setup_isac(cs);
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->readisac = &ReadISAC;
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->writeisac = &WriteISAC;
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->readisacfifo = &ReadISACfifo;
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->writeisacfifo = &WriteISACfifo;
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->BC_Read_Reg = &ReadHFC;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->BC_Write_Reg = &WriteHFC;
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->cardmsg = &TeleInt_card_msg;
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->irq_func = &TeleInt_interrupt;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ISACVersion(cs, "TeleInt:");
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (1);
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
337