⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hfc_sx.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: hfc_sx.c,v 1.12.2.5 2004/02/11 13:21:33 keil Exp $ * * level driver for Cologne Chip Designs hfc-s+/sp based cards * * Author       Werner Cornelius *              based on existing driver for CCD HFC PCI cards * Copyright    by Werner Cornelius  <werner@isdn4linux.de> *  * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * */#include <linux/init.h>#include "hisax.h"#include "hfc_sx.h"#include "isdnl1.h"#include <linux/interrupt.h>#include <linux/isapnp.h>extern const char *CardType[];static const char *hfcsx_revision = "$Revision: 1.12.2.5 $";/***************************************//* IRQ-table for CCDs demo board       *//* IRQs 6,5,10,11,12,15 are supported  *//***************************************//* Teles 16.3c Vendor Id TAG2620, Version 1.0, Vendor version 2.1 * * Thanks to Uwe Wisniewski * * ISA-SLOT  Signal      PIN * B25        IRQ3     92 IRQ_G * B23        IRQ5     94 IRQ_A * B4         IRQ2/9   95 IRQ_B * D3         IRQ10    96 IRQ_C * D4         IRQ11    97 IRQ_D * D5         IRQ12    98 IRQ_E * D6         IRQ15    99 IRQ_F */#undef CCD_DEMO_BOARD#ifdef CCD_DEMO_BOARDstatic u_char ccd_sp_irqtab[16] = {  0,0,0,0,0,2,1,0,0,0,3,4,5,0,0,6};#else /* Teles 16.3c */static u_char ccd_sp_irqtab[16] = {  0,0,0,7,0,1,0,0,0,2,3,4,5,0,0,6};#endif#define NT_T1_COUNT 20		/* number of 3.125ms interrupts for G2 timeout */#define byteout(addr,val) outb(val,addr)#define bytein(addr) inb(addr)/******************************//* In/Out access to registers *//******************************/static inline voidWrite_hfc(struct IsdnCardState *cs, u_char regnum, u_char val){        byteout(cs->hw.hfcsx.base+1, regnum);	byteout(cs->hw.hfcsx.base, val);} static inline u_charRead_hfc(struct IsdnCardState *cs, u_char regnum){        u_char ret;         byteout(cs->hw.hfcsx.base+1, regnum);	ret = bytein(cs->hw.hfcsx.base);	return(ret);} /**************************************************//* select a fifo and remember which one for reuse *//**************************************************/static voidfifo_select(struct IsdnCardState *cs, u_char fifo){        if (fifo == cs->hw.hfcsx.last_fifo) 	  return; /* still valid */        byteout(cs->hw.hfcsx.base+1, HFCSX_FIF_SEL);	byteout(cs->hw.hfcsx.base, fifo);	while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */	udelay(4);	byteout(cs->hw.hfcsx.base, fifo);	while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */}/******************************************//* reset the specified fifo to defaults.  *//* If its a send fifo init needed markers *//******************************************/static voidreset_fifo(struct IsdnCardState *cs, u_char fifo){	fifo_select(cs, fifo); /* first select the fifo */	byteout(cs->hw.hfcsx.base+1, HFCSX_CIRM);	byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.cirm | 0x80); /* reset cmd */	udelay(1);	while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */} /*************************************************************//* write_fifo writes the skb contents to the desired fifo    *//* if no space is available or an error occurs 0 is returned *//* the skb is not released in any way.                       *//*************************************************************/static intwrite_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u_char fifo, int trans_max){       unsigned short *msp;        int fifo_size, count, z1, z2;	u_char f_msk, f1, f2, *src;	if (skb->len <= 0) return(0);        if (fifo & 1) return(0); /* no write fifo */	fifo_select(cs, fifo);	if (fifo & 4) {	  fifo_size = D_FIFO_SIZE; /* D-channel */	  f_msk = MAX_D_FRAMES;	  if (trans_max) return(0); /* only HDLC */	}	else {	  fifo_size = cs->hw.hfcsx.b_fifo_size; /* B-channel */	  f_msk = MAX_B_FRAMES;	}        z1 = Read_hfc(cs, HFCSX_FIF_Z1H);	z1 = ((z1 << 8) | Read_hfc(cs, HFCSX_FIF_Z1L));	/* Check for transparent mode */	if (trans_max) {	  z2 = Read_hfc(cs, HFCSX_FIF_Z2H);	  z2 = ((z2 << 8) | Read_hfc(cs, HFCSX_FIF_Z2L));	  count = z2 - z1;	  if (count <= 0)	    count += fifo_size; /* free bytes */	  if (count < skb->len+1) return(0); /* no room */	  count = fifo_size - count; /* bytes still not send */	  if (count > 2 * trans_max) return(0); /* delay to long */	  count = skb->len;	  src = skb->data;	  while (count--)	    Write_hfc(cs, HFCSX_FIF_DWR, *src++);	  return(1); /* success */	}        msp = ((struct hfcsx_extra *)(cs->hw.hfcsx.extra))->marker;	msp += (((fifo >> 1) & 3) * (MAX_B_FRAMES+1));	f1 = Read_hfc(cs, HFCSX_FIF_F1) & f_msk;	f2 = Read_hfc(cs, HFCSX_FIF_F2) & f_msk;	count = f1 - f2; /* frame count actually buffered */	if (count < 0)		count += (f_msk + 1);	/* if wrap around */	if (count > f_msk-1) {	  if (cs->debug & L1_DEB_ISAC_FIFO)	    debugl1(cs, "hfcsx_write_fifo %d more as %d frames",fifo,f_msk-1);	  return(0);	}	*(msp + f1) = z1; /* remember marker */	if (cs->debug & L1_DEB_ISAC_FIFO)		debugl1(cs, "hfcsx_write_fifo %d f1(%x) f2(%x) z1(f1)(%x)",			fifo, f1, f2, z1);	/* now determine free bytes in FIFO buffer */	count = *(msp + f2) - z1;	if (count <= 0)	  count += fifo_size;	/* count now contains available bytes */	if (cs->debug & L1_DEB_ISAC_FIFO)	  debugl1(cs, "hfcsx_write_fifo %d count(%ld/%d)",		  fifo, skb->len, count);	if (count < skb->len) {	  if (cs->debug & L1_DEB_ISAC_FIFO)	    debugl1(cs, "hfcsx_write_fifo %d no fifo mem", fifo);	  return(0);	}		count = skb->len; /* get frame len */	src = skb->data;	/* source pointer */	while (count--)	  Write_hfc(cs, HFCSX_FIF_DWR, *src++);		Read_hfc(cs, HFCSX_FIF_INCF1); /* increment F1 */	udelay(1);	while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */	return(1);} /***************************************************************//* read_fifo reads data to an skb from the desired fifo        *//* if no data is available or an error occurs NULL is returned *//* the skb is not released in any way.                         *//***************************************************************/static struct sk_buff * read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max){       int fifo_size, count, z1, z2;	u_char f_msk, f1, f2, *dst;	struct sk_buff *skb;        if (!(fifo & 1)) return(NULL); /* no read fifo */	fifo_select(cs, fifo);	if (fifo & 4) {	  fifo_size = D_FIFO_SIZE; /* D-channel */	  f_msk = MAX_D_FRAMES;	  if (trans_max) return(NULL); /* only hdlc */	}	else {	  fifo_size = cs->hw.hfcsx.b_fifo_size; /* B-channel */	  f_msk = MAX_B_FRAMES;	}	/* transparent mode */	if (trans_max) {	  z1 = Read_hfc(cs, HFCSX_FIF_Z1H);	  z1 = ((z1 << 8) | Read_hfc(cs, HFCSX_FIF_Z1L));	  z2 = Read_hfc(cs, HFCSX_FIF_Z2H);	  z2 = ((z2 << 8) | Read_hfc(cs, HFCSX_FIF_Z2L));	  /* now determine bytes in actual FIFO buffer */	  count = z1 - z2;	  if (count <= 0)	    count += fifo_size;	/* count now contains buffered bytes */	  count++;	  if (count > trans_max) 	    count = trans_max; /* limit length */	    if ((skb = dev_alloc_skb(count))) {	      dst = skb_put(skb, count);	      while (count--) 		*dst++ = Read_hfc(cs, HFCSX_FIF_DRD);	      return(skb);	    }	    else return(NULL); /* no memory */	}	do {	  f1 = Read_hfc(cs, HFCSX_FIF_F1) & f_msk;	  f2 = Read_hfc(cs, HFCSX_FIF_F2) & f_msk;	  if (f1 == f2) return(NULL); /* no frame available */	  z1 = Read_hfc(cs, HFCSX_FIF_Z1H);	  z1 = ((z1 << 8) | Read_hfc(cs, HFCSX_FIF_Z1L));	  z2 = Read_hfc(cs, HFCSX_FIF_Z2H);	  z2 = ((z2 << 8) | Read_hfc(cs, HFCSX_FIF_Z2L));	  if (cs->debug & L1_DEB_ISAC_FIFO)	    debugl1(cs, "hfcsx_read_fifo %d f1(%x) f2(%x) z1(f2)(%x) z2(f2)(%x)",			fifo, f1, f2, z1, z2);	  /* now determine bytes in actual FIFO buffer */	  count = z1 - z2;	  if (count <= 0)	    count += fifo_size;	/* count now contains buffered bytes */	  count++;	  if (cs->debug & L1_DEB_ISAC_FIFO)	    debugl1(cs, "hfcsx_read_fifo %d count %ld)",		    fifo, count);	  if ((count > fifo_size) || (count < 4)) {	    if (cs->debug & L1_DEB_WARN)	      debugl1(cs, "hfcsx_read_fifo %d paket inv. len %d ", fifo , count);	    while (count) {	      count--; /* empty fifo */	      Read_hfc(cs, HFCSX_FIF_DRD);	    }	    skb = NULL;	  } else 	    if ((skb = dev_alloc_skb(count - 3))) {	      count -= 3;	      dst = skb_put(skb, count);	      while (count--) 		*dst++ = Read_hfc(cs, HFCSX_FIF_DRD);		    	      Read_hfc(cs, HFCSX_FIF_DRD); /* CRC 1 */	      Read_hfc(cs, HFCSX_FIF_DRD); /* CRC 2 */	      if (Read_hfc(cs, HFCSX_FIF_DRD)) {		dev_kfree_skb_irq(skb);		if (cs->debug & L1_DEB_ISAC_FIFO)		  debugl1(cs, "hfcsx_read_fifo %d crc error", fifo);		skb = NULL;	      }	    } else {	      printk(KERN_WARNING "HFC-SX: receive out of memory\n");	      return(NULL);	    }	  Read_hfc(cs, HFCSX_FIF_INCF2); /* increment F2 */	  udelay(1);	  while (bytein(cs->hw.hfcsx.base+1) & 1); /* wait for busy */	  udelay(1);	} while (!skb); /* retry in case of crc error */	return(skb);} /******************************************//* free hardware resources used by driver *//******************************************/static voidrelease_io_hfcsx(struct IsdnCardState *cs){	cs->hw.hfcsx.int_m2 = 0;	/* interrupt output off ! */	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);	Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET);	/* Reset On */	msleep(30);				/* Timeout 30ms */	Write_hfc(cs, HFCSX_CIRM, 0);	/* Reset Off */	del_timer(&cs->hw.hfcsx.timer);	release_region(cs->hw.hfcsx.base, 2); /* release IO-Block */	kfree(cs->hw.hfcsx.extra);	cs->hw.hfcsx.extra = NULL;}/**********************************************************//* set_fifo_size determines the size of the RAM and FIFOs *//* returning 0 -> need to reset the chip again.           *//**********************************************************/static int set_fifo_size(struct IsdnCardState *cs){                if (cs->hw.hfcsx.b_fifo_size) return(1); /* already determined */	if ((cs->hw.hfcsx.chip >> 4) == 9) {	  cs->hw.hfcsx.b_fifo_size = B_FIFO_SIZE_32K;	  return(1);	}	  cs->hw.hfcsx.b_fifo_size = B_FIFO_SIZE_8K;	  cs->hw.hfcsx.cirm |= 0x10; /* only 8K of ram */	  return(0);}/********************************************************************************//* function called to reset the HFC SX chip. A complete software reset of chip *//* and fifos is done.                                                           *//********************************************************************************/static voidreset_hfcsx(struct IsdnCardState *cs){	cs->hw.hfcsx.int_m2 = 0;	/* interrupt output off ! */	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);	printk(KERN_INFO "HFC_SX: resetting card\n");	while (1) {	  Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET | cs->hw.hfcsx.cirm ); /* Reset */	  mdelay(30);	  Write_hfc(cs, HFCSX_CIRM, cs->hw.hfcsx.cirm); /* Reset Off */	  mdelay(20);	  if (Read_hfc(cs, HFCSX_STATUS) & 2)	    printk(KERN_WARNING "HFC-SX init bit busy\n");	  cs->hw.hfcsx.last_fifo = 0xff; /* invalidate */	  if (!set_fifo_size(cs)) continue;	  break;	}	cs->hw.hfcsx.trm = 0 + HFCSX_BTRANS_THRESMASK;	/* no echo connect , threshold */	Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm);	Write_hfc(cs, HFCSX_CLKDEL, 0x0e);	/* ST-Bit delay for TE-Mode */	cs->hw.hfcsx.sctrl_e = HFCSX_AUTO_AWAKE;	Write_hfc(cs, HFCSX_SCTRL_E, cs->hw.hfcsx.sctrl_e);	/* S/T Auto awake */	cs->hw.hfcsx.bswapped = 0;	/* no exchange */	cs->hw.hfcsx.nt_mode = 0;	/* we are in TE mode */	cs->hw.hfcsx.ctmt = HFCSX_TIM3_125 | HFCSX_AUTO_TIMER;	Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt);	cs->hw.hfcsx.int_m1 = HFCSX_INTS_DTRANS | HFCSX_INTS_DREC | 	    HFCSX_INTS_L1STATE | HFCSX_INTS_TIMER;	Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1);	/* Clear already pending ints */	if (Read_hfc(cs, HFCSX_INT_S1));	Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 2);	/* HFC ST 2 */	udelay(10);	Write_hfc(cs, HFCSX_STATES, 2);	/* HFC ST 2 */	cs->hw.hfcsx.mst_m = HFCSX_MASTER;	/* HFC Master Mode */	Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m);	cs->hw.hfcsx.sctrl = 0x40;	/* set tx_lo mode, error in datasheet ! */	Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl);	cs->hw.hfcsx.sctrl_r = 0;	Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r);	/* Init GCI/IOM2 in master mode */	/* Slots 0 and 1 are set for B-chan 1 and 2 */	/* D- and monitor/CI channel are not enabled */	/* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */	/* STIO2 is used as data input, B1+B2 from IOM->ST */	/* ST B-channel send disabled -> continous 1s */	/* The IOM slots are always enabled */	cs->hw.hfcsx.conn = 0x36;	/* set data flow directions */	Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);	Write_hfc(cs, HFCSX_B1_SSL, 0x80);	/* B1-Slot 0 STIO1 out enabled */	Write_hfc(cs, HFCSX_B2_SSL, 0x81);	/* B2-Slot 1 STIO1 out enabled */	Write_hfc(cs, HFCSX_B1_RSL, 0x80);	/* B1-Slot 0 STIO2 in enabled */	Write_hfc(cs, HFCSX_B2_RSL, 0x81);	/* B2-Slot 1 STIO2 in enabled */	/* Finally enable IRQ output */	cs->hw.hfcsx.int_m2 = HFCSX_IRQ_ENABLE;	Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2);	if (Read_hfc(cs, HFCSX_INT_S2));}/***************************************************//* Timer function called when kernel timer expires *//***************************************************/static voidhfcsx_Timer(struct IsdnCardState *cs){	cs->hw.hfcsx.timer.expires = jiffies + 75;	/* WD RESET *//*      WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcsx.ctmt | 0x80);   add_timer(&cs->hw.hfcsx.timer); */}/************************************************//* select a b-channel entry matching and active *//************************************************/staticstruct BCState *Sel_BCS(struct IsdnCardState *cs, int channel){	if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))		return (&cs->bcs[0]);	else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))		return (&cs->bcs[1]);	else		return (NULL);}/*******************************//* D-channel receive procedure *//*******************************/staticintreceive_dmsg(struct IsdnCardState *cs){	struct sk_buff *skb;	int count = 5;	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {		debugl1(cs, "rec_dmsg blocked");		return (1);	}	do {	  skb = read_fifo(cs, HFCSX_SEL_D_RX, 0);	  if (skb) {	    skb_queue_tail(&cs->rq, skb);	    schedule_event(cs, D_RCVBUFREADY);	  }	} while (--count && skb);	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);	return (1);}/**********************************//* B-channel main receive routine *//**********************************/static voidmain_rec_hfcsx(struct BCState *bcs){	struct IsdnCardState *cs = bcs->cs;	int count = 5;	struct sk_buff *skb;      Begin:	count--;	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {		debugl1(cs, "rec_data %d blocked", bcs->channel);		return;	}	skb = read_fifo(cs, ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ? 			HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX,			(bcs->mode == L1_MODE_TRANS) ? 			HFCSX_BTRANS_THRESHOLD : 0);	if (skb) {	  skb_queue_tail(&bcs->rqueue, skb);	  schedule_event(bcs, B_RCVBUFREADY);	}	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);	if (count && skb)		goto Begin;	return;}/**************************//* D-channel send routine *//**************************/static voidhfcsx_fill_dfifo(struct IsdnCardState *cs)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -