📄 gazel.c
字号:
/* $Id: gazel.c,v 2.19.2.4 2004/01/14 16:04:48 keil Exp $ * * low level stuff for Gazel isdn cards * * Author BeWan Systems * based on source code from Karsten Keil * Copyright by BeWan Systems * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * */#include <linux/config.h>#include <linux/init.h>#include "hisax.h"#include "isac.h"#include "hscx.h"#include "isdnl1.h"#include "ipac.h"#include <linux/pci.h>extern const char *CardType[];static const char *gazel_revision = "$Revision: 2.19.2.4 $";#define R647 1#define R685 2#define R753 3#define R742 4#define PLX_CNTRL 0x50 /* registre de controle PLX */#define RESET_GAZEL 0x4#define RESET_9050 0x40000000#define PLX_INCSR 0x4C /* registre d'IT du 9050 */#define INT_ISAC_EN 0x8 /* 1 = enable IT isac */#define INT_ISAC 0x20 /* 1 = IT isac en cours */#define INT_HSCX_EN 0x1 /* 1 = enable IT hscx */#define INT_HSCX 0x4 /* 1 = IT hscx en cours */#define INT_PCI_EN 0x40 /* 1 = enable IT PCI */#define INT_IPAC_EN 0x3 /* enable IT ipac */#define byteout(addr,val) outb(val,addr)#define bytein(addr) inb(addr)static inline u_charreadreg(unsigned int adr, u_short off){ return bytein(adr + off);}static inline voidwritereg(unsigned int adr, u_short off, u_char data){ byteout(adr + off, data);}static inline voidread_fifo(unsigned int adr, u_char * data, int size){ insb(adr, data, size);}static voidwrite_fifo(unsigned int adr, u_char * data, int size){ outsb(adr, data, size);}static inline u_charreadreg_ipac(unsigned int adr, u_short off){ register u_char ret; byteout(adr, off); ret = bytein(adr + 4); return ret;}static inline voidwritereg_ipac(unsigned int adr, u_short off, u_char data){ byteout(adr, off); byteout(adr + 4, data);}static inline voidread_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size){ byteout(adr, off); insb(adr + 4, data, size);}static voidwrite_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size){ byteout(adr, off); outsb(adr + 4, data, size);}/* Interface functions */static u_charReadISAC(struct IsdnCardState *cs, u_char offset){ u_short off2 = offset; switch (cs->subtyp) { case R647: off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); case R685: return (readreg(cs->hw.gazel.isac, off2)); case R753: case R742: return (readreg_ipac(cs->hw.gazel.ipac, 0x80 + off2)); } return 0;}static voidWriteISAC(struct IsdnCardState *cs, u_char offset, u_char value){ u_short off2 = offset; switch (cs->subtyp) { case R647: off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); case R685: writereg(cs->hw.gazel.isac, off2, value); break; case R753: case R742: writereg_ipac(cs->hw.gazel.ipac, 0x80 + off2, value); break; }}static voidReadISACfifo(struct IsdnCardState *cs, u_char * data, int size){ switch (cs->subtyp) { case R647: case R685: read_fifo(cs->hw.gazel.isacfifo, data, size); break; case R753: case R742: read_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size); break; }}static voidWriteISACfifo(struct IsdnCardState *cs, u_char * data, int size){ switch (cs->subtyp) { case R647: case R685: write_fifo(cs->hw.gazel.isacfifo, data, size); break; case R753: case R742: write_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size); break; }}static voidReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size){ switch (cs->subtyp) { case R647: case R685: read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); break; case R753: case R742: read_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size); break; }}static voidWriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size){ switch (cs->subtyp) { case R647: case R685: write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); break; case R753: case R742: write_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size); break; }}static u_charReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset){ u_short off2 = offset; switch (cs->subtyp) { case R647: off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); case R685: return (readreg(cs->hw.gazel.hscx[hscx], off2)); case R753: case R742: return (readreg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2)); } return 0;}static voidWriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value){ u_short off2 = offset; switch (cs->subtyp) { case R647: off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); case R685: writereg(cs->hw.gazel.hscx[hscx], off2, value); break; case R753: case R742: writereg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2, value); break; }}/* * fast interrupt HSCX stuff goes here */#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt)#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)#include "hscx_irq.c"static irqreturn_tgazel_interrupt(int intno, void *dev_id, struct pt_regs *regs){#define MAXCOUNT 5 struct IsdnCardState *cs = dev_id; u_char valisac, valhscx; int count = 0; u_long flags; spin_lock_irqsave(&cs->lock, flags); do { valhscx = ReadHSCX(cs, 1, HSCX_ISTA); if (valhscx) hscx_int_main(cs, valhscx); valisac = ReadISAC(cs, ISAC_ISTA); if (valisac) isac_interrupt(cs, valisac); count++; } while ((valhscx || valisac) && (count < MAXCOUNT)); WriteHSCX(cs, 0, HSCX_MASK, 0xFF); WriteHSCX(cs, 1, HSCX_MASK, 0xFF); WriteISAC(cs, ISAC_MASK, 0xFF); WriteISAC(cs, ISAC_MASK, 0x0); WriteHSCX(cs, 0, HSCX_MASK, 0x0); WriteHSCX(cs, 1, HSCX_MASK, 0x0); spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED;}static irqreturn_tgazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs){ struct IsdnCardState *cs = dev_id; u_char ista, val; int count = 0; u_long flags; spin_lock_irqsave(&cs->lock, flags); ista = ReadISAC(cs, IPAC_ISTA - 0x80); do { if (ista & 0x0f) { val = ReadHSCX(cs, 1, HSCX_ISTA); if (ista & 0x01) val |= 0x01; if (ista & 0x04) val |= 0x02; if (ista & 0x08) val |= 0x04; if (val) { hscx_int_main(cs, val); } } if (ista & 0x20) { val = 0xfe & ReadISAC(cs, ISAC_ISTA); if (val) { isac_interrupt(cs, val); } } if (ista & 0x10) { val = 0x01; isac_interrupt(cs, val); } ista = ReadISAC(cs, IPAC_ISTA - 0x80); count++; } while ((ista & 0x3f) && (count < MAXCOUNT)); WriteISAC(cs, IPAC_MASK - 0x80, 0xFF); WriteISAC(cs, IPAC_MASK - 0x80, 0xC0); spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED;}static voidrelease_io_gazel(struct IsdnCardState *cs){ unsigned int i; switch (cs->subtyp) { case R647: for (i = 0x0000; i < 0xC000; i += 0x1000) release_region(i + cs->hw.gazel.hscx[0], 16); release_region(0xC000 + cs->hw.gazel.hscx[0], 1); break; case R685: release_region(cs->hw.gazel.hscx[0], 0x100); release_region(cs->hw.gazel.cfg_reg, 0x80); break; case R753: release_region(cs->hw.gazel.ipac, 0x8); release_region(cs->hw.gazel.cfg_reg, 0x80); break; case R742: release_region(cs->hw.gazel.ipac, 8); break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -