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