summaryrefslogtreecommitdiffstats
path: root/drivers/isdn/hisax/hfc_pci.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-01-29 01:41:54 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-01-29 01:41:54 +0000
commitf969d69ba9f952e5bdd38278e25e26a3e4a61a70 (patch)
treeb3530d803df59d726afaabebc6626987dee1ca05 /drivers/isdn/hisax/hfc_pci.c
parenta10ce7ef2066b455d69187643ddf2073bfc4db24 (diff)
Merge with 2.3.27.
Diffstat (limited to 'drivers/isdn/hisax/hfc_pci.c')
-rw-r--r--drivers/isdn/hisax/hfc_pci.c974
1 files changed, 553 insertions, 421 deletions
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 9d8968e98..518c1670a 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -1,4 +1,4 @@
-/* $Id: hfc_pci.c,v 1.18 1999/08/29 17:05:44 werner Exp $
+/* $Id: hfc_pci.c,v 1.23 1999/11/07 17:01:55 keil Exp $
* hfc_pci.c low level driver for CCD´s hfc-pci based cards
*
@@ -23,6 +23,25 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: hfc_pci.c,v $
+ * Revision 1.23 1999/11/07 17:01:55 keil
+ * fix for 2.3 pci structs
+ *
+ * Revision 1.22 1999/10/10 20:14:27 werner
+ *
+ * Correct B2-chan usage in conjuntion with echo mode. First implementation of NT-leased line mode.
+ *
+ * Revision 1.21 1999/10/02 17:47:49 werner
+ *
+ * Changed init order, added correction for page alignment with shared mem
+ *
+ * Revision 1.20 1999/09/07 06:18:55 werner
+ *
+ * Added io parameter for HFC-PCI based cards. Needed only with multiple cards
+ * when initialisation/selection order needs to be set.
+ *
+ * Revision 1.19 1999/09/04 06:20:06 keil
+ * Changes from kernel set_current_state()
+ *
* Revision 1.18 1999/08/29 17:05:44 werner
* corrected tx_lo line setup. Datasheet is not correct.
*
@@ -91,40 +110,40 @@
#include "hfc_pci.h"
#include "isdnl1.h"
#include <linux/pci.h>
-#ifndef COMPAT_HAS_NEW_PCI
-#include <linux/bios32.h>
-#endif
#include <linux/interrupt.h>
extern const char *CardType[];
-static const char *hfcpci_revision = "$Revision: 1.18 $";
+static const char *hfcpci_revision = "$Revision: 1.23 $";
/* table entry in the PCI devices list */
typedef struct {
- int vendor_id;
- int device_id;
- char *vendor_name;
- char *card_name;
- } PCI_ENTRY;
-
-static const PCI_ENTRY id_list[] = {
- {0x1397,0x2BD0,"CCD/Billion/Asuscom","2BD0"},
- {0x1397,0xB000,"Billion","B000"},
- {0x1397,0xB006,"Billion","B006"},
- {0x1397,0xB007,"Billion","B007"},
- {0x1397,0xB008,"Billion","B008"},
- {0x1397,0xB009,"Billion","B009"},
- {0x1397,0xB00A,"Billion","B00A"},
- {0x1397,0xB00B,"Billion","B00B"},
- {0x1397,0xB00C,"Billion","B00C"},
- {0x1043,0x0675,"Asuscom/Askey","675"},
- {0x0871,0xFFA2,"German telekom","T-Concept"},
- {0x0871,0xFFA1,"German telekom","A1T"},
- {0x1051,0x0100,"Motorola MC145575","MC145575"},
- {0x1397,0xB100,"Seyeon","B100"},
- {0x15B0,0x2BD0,"Zoltrix","2BD0"},
- {0,0,NULL,NULL},
+ int vendor_id;
+ int device_id;
+ char *vendor_name;
+ char *card_name;
+} PCI_ENTRY;
+
+#define NT_T1_COUNT 20 /* number of 3.125ms interrupts for G2 timeout */
+
+static const PCI_ENTRY id_list[] =
+{
+ {0x1397, 0x2BD0, "CCD/Billion/Asuscom", "2BD0"},
+ {0x1397, 0xB000, "Billion", "B000"},
+ {0x1397, 0xB006, "Billion", "B006"},
+ {0x1397, 0xB007, "Billion", "B007"},
+ {0x1397, 0xB008, "Billion", "B008"},
+ {0x1397, 0xB009, "Billion", "B009"},
+ {0x1397, 0xB00A, "Billion", "B00A"},
+ {0x1397, 0xB00B, "Billion", "B00B"},
+ {0x1397, 0xB00C, "Billion", "B00C"},
+ {0x1043, 0x0675, "Asuscom/Askey", "675"},
+ {0x0871, 0xFFA2, "German telekom", "T-Concept"},
+ {0x0871, 0xFFA1, "German telekom", "A1T"},
+ {0x1051, 0x0100, "Motorola MC145575", "MC145575"},
+ {0x1397, 0xB100, "Seyeon", "B100"},
+ {0x15B0, 0x2BD0, "Zoltrix", "2BD0"},
+ {0, 0, NULL, NULL},
};
@@ -151,9 +170,21 @@ releasehfcpci(struct IsdnCardState *cs)
void
release_io_hfcpci(struct IsdnCardState *cs)
{
+ int flags;
+
+ save_flags(flags);
+ cli();
+ cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */
+ Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+ restore_flags(flags);
+ Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */
+ sti();
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */
+ Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */
#if CONFIG_PCI
- pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0); /* disabe memory mapped ports + busmaster */
-#endif /* CONFIG_PCI */
+ pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0); /* disable memory mapped ports + busmaster */
+#endif /* CONFIG_PCI */
releasehfcpci(cs);
del_timer(&cs->hw.hfcpci.timer);
kfree(cs->hw.hfcpci.share_start);
@@ -170,16 +201,20 @@ reset_hfcpci(struct IsdnCardState *cs)
{
long flags;
+ save_flags(flags);
+ cli();
pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */
+ cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */
+ Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+
printk(KERN_INFO "HFC_PCI: resetting card\n");
pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO + PCI_ENA_MASTER); /* enable memory ports + busmaster */
Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */
- save_flags(flags);
sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */
Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */
if (Read_hfc(cs, HFCPCI_STATUS) & 2)
printk(KERN_WARNING "HFC-PCI init bit busy\n");
@@ -187,25 +222,23 @@ reset_hfcpci(struct IsdnCardState *cs)
cs->hw.hfcpci.fifo_en = 0x30; /* only D fifos enabled */
Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
- cs->hw.hfcpci.trm = 0 + HFCPCI_BTRANS_THRESMASK; /* no echo connect , threshold */
+ cs->hw.hfcpci.trm = 0 + HFCPCI_BTRANS_THRESMASK; /* no echo connect , threshold */
Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
Write_hfc(cs, HFCPCI_CLKDEL, 0x0e); /* ST-Bit delay for TE-Mode */
cs->hw.hfcpci.sctrl_e = HFCPCI_AUTO_AWAKE;
Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e); /* S/T Auto awake */
- cs->hw.hfcpci.bswapped = 0; /* no exchange */
+ cs->hw.hfcpci.bswapped = 0; /* no exchange */
+ cs->hw.hfcpci.nt_mode = 0; /* we are in TE mode */
cs->hw.hfcpci.ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER;
Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
- cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE;
- cs->hw.hfcpci.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC |
- HFCPCI_INTS_L1STATE | HFCPCI_CLTIMER;
+ cs->hw.hfcpci.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC |
+ HFCPCI_INTS_L1STATE | HFCPCI_INTS_TIMER;
Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
- Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
/* Clear already pending ints */
if (Read_hfc(cs, HFCPCI_INT_S1));
- if (Read_hfc(cs, HFCPCI_INT_S2));
Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 2); /* HFC ST 2 */
udelay(10);
@@ -213,24 +246,29 @@ reset_hfcpci(struct IsdnCardState *cs)
cs->hw.hfcpci.mst_m = HFCPCI_MASTER; /* HFC Master Mode */
Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
- cs->hw.hfcpci.sctrl = 0x40; /* set tx_lo mode, error in datasheet ! */
+ cs->hw.hfcpci.sctrl = 0x40; /* set tx_lo mode, error in datasheet ! */
Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
cs->hw.hfcpci.sctrl_r = 0;
Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
- /* Init GCI/IOM2 in master mode */
+ /* 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 */
+ /* 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.hfcpci.conn = 0x36; /* set data flow directions */
+ cs->hw.hfcpci.conn = 0x36; /* set data flow directions */
Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
- Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* B1-Slot 0 STIO1 out enabled */
- Write_hfc(cs, HFCPCI_B2_SSL, 0x81); /* B2-Slot 1 STIO1 out enabled */
- Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* B1-Slot 0 STIO2 in enabled */
- Write_hfc(cs, HFCPCI_B2_RSL, 0x81); /* B2-Slot 1 STIO2 in enabled */
+ Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* B1-Slot 0 STIO1 out enabled */
+ Write_hfc(cs, HFCPCI_B2_SSL, 0x81); /* B2-Slot 1 STIO1 out enabled */
+ Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* B1-Slot 0 STIO2 in enabled */
+ Write_hfc(cs, HFCPCI_B2_RSL, 0x81); /* B2-Slot 1 STIO2 in enabled */
+
+ /* Finally enable IRQ output */
+ cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE;
+ Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+ if (Read_hfc(cs, HFCPCI_INT_S2));
restore_flags(flags);
}
@@ -317,12 +355,11 @@ hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u_char * bdata, int cou
} else if (!(skb = dev_alloc_skb(count - 3)))
printk(KERN_WARNING "HFCPCI: receive out of memory\n");
else {
- SET_SKB_FREE(skb);
total = count;
count -= 3;
ptr = skb_put(skb, count);
- if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL)
+ if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL)
maxlen = count; /* complete transfer */
else
maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */
@@ -381,7 +418,6 @@ receive_dmsg(struct IsdnCardState *cs)
df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1); /* next buffer */
df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + rcnt) & (D_FIFO_SIZE - 1);
} else if ((skb = dev_alloc_skb(rcnt - 3))) {
- SET_SKB_FREE(skb);
total = rcnt;
rcnt -= 3;
ptr = skb_put(skb, rcnt);
@@ -415,55 +451,56 @@ receive_dmsg(struct IsdnCardState *cs)
/*******************************************************************************/
/* check for transparent receive data and read max one threshold size if avail */
/*******************************************************************************/
-int hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type *bz, u_char *bdata)
-{ unsigned short *z1r, *z2r;
- int new_z2, fcnt, maxlen;
- struct sk_buff *skb;
- u_char *ptr, *ptr1;
+int
+hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u_char * bdata)
+{
+ unsigned short *z1r, *z2r;
+ int new_z2, fcnt, maxlen;
+ struct sk_buff *skb;
+ u_char *ptr, *ptr1;
- z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */
- z2r = z1r + 1;
+ z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */
+ z2r = z1r + 1;
- if (!(fcnt = *z1r - *z2r))
- return(0); /* no data avail */
+ if (!(fcnt = *z1r - *z2r))
+ return (0); /* no data avail */
- if (fcnt <= 0)
- fcnt += B_FIFO_SIZE; /* bytes actually buffered */
- if (fcnt > HFCPCI_BTRANS_THRESHOLD)
- fcnt = HFCPCI_BTRANS_THRESHOLD; /* limit size */
+ if (fcnt <= 0)
+ fcnt += B_FIFO_SIZE; /* bytes actually buffered */
+ if (fcnt > HFCPCI_BTRANS_THRESHOLD)
+ fcnt = HFCPCI_BTRANS_THRESHOLD; /* limit size */
- new_z2 = *z2r + fcnt; /* new position in fifo */
- if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
- new_z2 -= B_FIFO_SIZE; /* buffer wrap */
+ new_z2 = *z2r + fcnt; /* new position in fifo */
+ if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
+ new_z2 -= B_FIFO_SIZE; /* buffer wrap */
- if (!(skb = dev_alloc_skb(fcnt)))
+ if (!(skb = dev_alloc_skb(fcnt)))
printk(KERN_WARNING "HFCPCI: receive out of memory\n");
- else {
- SET_SKB_FREE(skb);
- ptr = skb_put(skb, fcnt);
- if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
- maxlen = fcnt; /* complete transfer */
- else
- maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r; /* maximum */
-
- ptr1 = bdata + (*z2r - B_SUB_VAL); /* start of data */
- memcpy(ptr, ptr1, maxlen); /* copy data */
- fcnt -= maxlen;
-
- if (fcnt) { /* rest remaining */
- ptr += maxlen;
- ptr1 = bdata; /* start of buffer */
- memcpy(ptr, ptr1, fcnt); /* rest */
- }
- cli();
- skb_queue_tail(&bcs->rqueue, skb);
- sti();
- hfcpci_sched_event(bcs, B_RCVBUFREADY);
- }
-
- *z2r = new_z2; /* new position */
- return(1);
-} /* hfcpci_empty_fifo_trans */
+ else {
+ ptr = skb_put(skb, fcnt);
+ if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
+ maxlen = fcnt; /* complete transfer */
+ else
+ maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r; /* maximum */
+
+ ptr1 = bdata + (*z2r - B_SUB_VAL); /* start of data */
+ memcpy(ptr, ptr1, maxlen); /* copy data */
+ fcnt -= maxlen;
+
+ if (fcnt) { /* rest remaining */
+ ptr += maxlen;
+ ptr1 = bdata; /* start of buffer */
+ memcpy(ptr, ptr1, fcnt); /* rest */
+ }
+ cli();
+ skb_queue_tail(&bcs->rqueue, skb);
+ sti();
+ hfcpci_sched_event(bcs, B_RCVBUFREADY);
+ }
+
+ *z2r = new_z2; /* new position */
+ return (1);
+} /* hfcpci_empty_fifo_trans */
/**********************************/
/* B-channel main receive routine */
@@ -524,11 +561,10 @@ main_rec_hfcpci(struct BCState *bcs)
receive = 1;
else
receive = 0;
- } else
- if (bcs->mode == L1_MODE_TRANS)
- receive = hfcpci_empty_fifo_trans(bcs, bz, bdata);
- else
- receive = 0;
+ } else if (bcs->mode == L1_MODE_TRANS)
+ receive = hfcpci_empty_fifo_trans(bcs, bz, bdata);
+ else
+ receive = 0;
test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
if (count && receive)
goto Begin;
@@ -603,7 +639,7 @@ hfcpci_fill_dfifo(struct IsdnCardState *cs)
df->f1 = new_f1; /* next frame */
restore_flags(flags);
- idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+ dev_kfree_skb(cs->tx_skb);
cs->tx_skb = NULL;
return;
}
@@ -620,7 +656,7 @@ hfcpci_fill_fifo(struct BCState *bcs)
bzfifo_type *bz;
u_char *bdata;
u_char new_f1, *src, *dst;
- unsigned short *z1t, *z2t;
+ unsigned short *z1t, *z2t;
if (!bcs->tx_skb)
return;
@@ -639,57 +675,53 @@ hfcpci_fill_fifo(struct BCState *bcs)
}
if (bcs->mode == L1_MODE_TRANS) {
- z1t = &bz->za[MAX_B_FRAMES].z1;
- z2t = z1t + 1;
- if (cs->debug & L1_DEB_HSCX)
- debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)",
- bcs->channel, *z1t, *z2t);
- fcnt = *z2t - *z1t;
- if (fcnt <= 0)
- fcnt += B_FIFO_SIZE; /* fcnt contains available bytes in fifo */
- fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */
-
- while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) {
- if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) {
- /* data is suitable for fifo */
- count = bcs->tx_skb->len;
-
- new_z1 = *z1t + count; /* new buffer Position */
- if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
- new_z1 -= B_FIFO_SIZE; /* buffer wrap */
- src = bcs->tx_skb->data; /* source pointer */
- dst = bdata + (*z1t - B_SUB_VAL);
- maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t; /* end of fifo */
- if (maxlen > count)
- maxlen = count; /* limit size */
- memcpy(dst, src, maxlen); /* first copy */
-
- count -= maxlen; /* remaining bytes */
- if (count) {
- dst = bdata; /* start of buffer */
- src += maxlen; /* new position */
- memcpy(dst, src, count);
- }
- bcs->tx_cnt -= bcs->tx_skb->len;
- fcnt += bcs->tx_skb->len;
- *z1t = new_z1; /* now send data */
- }
- else
- if (cs->debug & L1_DEB_HSCX)
- debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded",
- bcs->channel, bcs->tx_skb->len);
-
- idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
- cli();
- bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */
- sti();
- }
- test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
- restore_flags(flags);
- return;
+ z1t = &bz->za[MAX_B_FRAMES].z1;
+ z2t = z1t + 1;
+ if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)",
+ bcs->channel, *z1t, *z2t);
+ fcnt = *z2t - *z1t;
+ if (fcnt <= 0)
+ fcnt += B_FIFO_SIZE; /* fcnt contains available bytes in fifo */
+ fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */
+
+ while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) {
+ if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) {
+ /* data is suitable for fifo */
+ count = bcs->tx_skb->len;
+
+ new_z1 = *z1t + count; /* new buffer Position */
+ if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
+ new_z1 -= B_FIFO_SIZE; /* buffer wrap */
+ src = bcs->tx_skb->data; /* source pointer */
+ dst = bdata + (*z1t - B_SUB_VAL);
+ maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t; /* end of fifo */
+ if (maxlen > count)
+ maxlen = count; /* limit size */
+ memcpy(dst, src, maxlen); /* first copy */
+
+ count -= maxlen; /* remaining bytes */
+ if (count) {
+ dst = bdata; /* start of buffer */
+ src += maxlen; /* new position */
+ memcpy(dst, src, count);
+ }
+ bcs->tx_cnt -= bcs->tx_skb->len;
+ fcnt += bcs->tx_skb->len;
+ *z1t = new_z1; /* now send data */
+ } else if (cs->debug & L1_DEB_HSCX)
+ debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded",
+ bcs->channel, bcs->tx_skb->len);
+
+ dev_kfree_skb(bcs->tx_skb);
+ cli();
+ bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */
+ sti();
+ }
+ test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+ restore_flags(flags);
+ return;
}
-
-
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "hfcpci_fill_fifo_hdlc %d f1(%d) f2(%d) z1(f1)(%x)",
bcs->channel, bz->f1, bz->f2,
@@ -749,57 +781,113 @@ hfcpci_fill_fifo(struct BCState *bcs)
bz->f1 = new_f1; /* next frame */
restore_flags(flags);
- idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ dev_kfree_skb(bcs->tx_skb);
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
return;
}
+/**********************************************/
+/* D-channel l1 state call for leased NT-mode */
+/**********************************************/
+static void
+dch_nt_l2l1(struct PStack *st, int pr, void *arg)
+{
+ struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
+
+ switch (pr) {
+ case (PH_DATA | REQUEST):
+ case (PH_PULL | REQUEST):
+ case (PH_PULL | INDICATION):
+ st->l1.l1hw(st, pr, arg);
+ break;
+ case (PH_ACTIVATE | REQUEST):
+ st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
+ break;
+ case (PH_TESTLOOP | REQUEST):
+ if (1 & (long) arg)
+ debugl1(cs, "PH_TEST_LOOP B1");
+ if (2 & (long) arg)
+ debugl1(cs, "PH_TEST_LOOP B2");
+ if (!(3 & (long) arg))
+ debugl1(cs, "PH_TEST_LOOP DISABLED");
+ st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg);
+ break;
+ default:
+ if (cs->debug)
+ debugl1(cs, "dch_nt_l2l1 msg %04X unhandled", pr);
+ break;
+ }
+}
+
+
+
/***********************/
/* set/reset echo mode */
-/***********************/
+/***********************/
static int
-hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic)
+hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic)
{
- int flags;
- int i = *(unsigned int *) ic->parm.num;
-
- if (cs->chanlimit > 1)
- return(-EINVAL);
-
- save_flags(flags);
- cli();
- if (i) {
- cs->logecho = 1;
- cs->hw.hfcpci.trm |= 0x20; /* enable echo chan */
- cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_B2REC;
- cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2RX;
- }
- else {
- cs->logecho = 0;
- cs->hw.hfcpci.trm &= ~0x20; /* enable echo chan */
- cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_B2REC;
- cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2RX;
- }
- cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA;
- cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA;
- cs->hw.hfcpci.conn |= 0x10; /* B2-IOM -> B2-ST */
- cs->hw.hfcpci.ctmt &= ~2;
- Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
- Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
- Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
- Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
- Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
- Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
- Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
- restore_flags(flags);
- return(0);
-} /* hfcpci_auxcmd */
+ int flags;
+ int i = *(unsigned int *) ic->parm.num;
+
+ if ((ic->arg == 98) &&
+ (!(cs->hw.hfcpci.int_m1 & (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC + HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC)))) {
+ save_flags(flags);
+ cli();
+ Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0); /* HFC ST G0 */
+ udelay(10);
+ cs->hw.hfcpci.sctrl |= SCTRL_MODE_NT;
+ Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); /* set NT-mode */
+ udelay(10);
+ Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 1); /* HFC ST G1 */
+ udelay(10);
+ Write_hfc(cs, HFCPCI_STATES, 1 | HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
+ cs->dc.hfcpci.ph_state = 1;
+ cs->hw.hfcpci.nt_mode = 1;
+ cs->hw.hfcpci.nt_timer = 0;
+ cs->stlist->l2.l2l1 = dch_nt_l2l1;
+ restore_flags(flags);
+ debugl1(cs, "NT mode activated");
+ return (0);
+ }
+ if ((cs->chanlimit > 1) || (cs->hw.hfcpci.bswapped) ||
+ (cs->hw.hfcpci.nt_mode) || (ic->arg != 12))
+ return (-EINVAL);
+
+ save_flags(flags);
+ cli();
+ if (i) {
+ cs->logecho = 1;
+ cs->hw.hfcpci.trm |= 0x20; /* enable echo chan */
+ cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_B2REC;
+ cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2RX;
+ } else {
+ cs->logecho = 0;
+ cs->hw.hfcpci.trm &= ~0x20; /* disable echo chan */
+ cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_B2REC;
+ cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2RX;
+ }
+ cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA;
+ cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA;
+ cs->hw.hfcpci.conn |= 0x10; /* B2-IOM -> B2-ST */
+ cs->hw.hfcpci.ctmt &= ~2;
+ Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
+ Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
+ Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
+ Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
+ Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
+ Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
+ Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+ restore_flags(flags);
+ return (0);
+} /* hfcpci_auxcmd */
/*****************************/
/* E-channel receive routine */
/*****************************/
-static void receive_emsg(struct IsdnCardState *cs)
+static void
+receive_emsg(struct IsdnCardState *cs)
{
long flags;
int rcnt;
@@ -836,55 +924,54 @@ static void receive_emsg(struct IsdnCardState *cs)
if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "hfcpci e_rec z1(%x) z2(%x) cnt(%d)",
zp->z1, zp->z2, rcnt);
- new_z2 = zp->z2 + rcnt; /* new position in fifo */
+ new_z2 = zp->z2 + rcnt; /* new position in fifo */
if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
- new_z2 -= B_FIFO_SIZE; /* buffer wrap */
+ new_z2 -= B_FIFO_SIZE; /* buffer wrap */
new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
- if ((rcnt > 256 + 3) || (count < 4) ||
+ if ((rcnt > 256 + 3) || (count < 4) ||
(*(bdata + (zp->z1 - B_SUB_VAL)))) {
- if (cs->debug & L1_DEB_WARN)
- debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt);
- bz->za[new_f2].z2 = new_z2;
- bz->f2 = new_f2; /* next buffer */
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt);
+ bz->za[new_f2].z2 = new_z2;
+ bz->f2 = new_f2; /* next buffer */
} else {
- total = rcnt;
- rcnt -= 3;
- ptr = e_buffer;
-
- if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL)
- maxlen = rcnt; /* complete transfer */
- else
- maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */
+ total = rcnt;
+ rcnt -= 3;
+ ptr = e_buffer;
- ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */
- memcpy(ptr, ptr1, maxlen); /* copy data */
- rcnt -= maxlen;
+ if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL)
+ maxlen = rcnt; /* complete transfer */
+ else
+ maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */
- if (rcnt) { /* rest remaining */
- ptr += maxlen;
- ptr1 = bdata; /* start of buffer */
- memcpy(ptr, ptr1, rcnt); /* rest */
- }
- bz->za[new_f2].z2 = new_z2;
- bz->f2 = new_f2; /* next buffer */
- if (cs->debug & DEB_DLOG_HEX) {
- ptr = cs->dlog;
- if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) {
- *ptr++ = 'E';
- *ptr++ = 'C';
- *ptr++ = 'H';
- *ptr++ = 'O';
- *ptr++ = ':';
- ptr += QuickHex(ptr, e_buffer, total - 3);
- ptr--;
- *ptr++ = '\n';
- *ptr = 0;
- HiSax_putstatus(cs, NULL, cs->dlog);
- } else
- HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3);
- }
+ ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */
+ memcpy(ptr, ptr1, maxlen); /* copy data */
+ rcnt -= maxlen;
- }
+ if (rcnt) { /* rest remaining */
+ ptr += maxlen;
+ ptr1 = bdata; /* start of buffer */
+ memcpy(ptr, ptr1, rcnt); /* rest */
+ }
+ bz->za[new_f2].z2 = new_z2;
+ bz->f2 = new_f2; /* next buffer */
+ if (cs->debug & DEB_DLOG_HEX) {
+ ptr = cs->dlog;
+ if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) {
+ *ptr++ = 'E';
+ *ptr++ = 'C';
+ *ptr++ = 'H';
+ *ptr++ = 'O';
+ *ptr++ = ':';
+ ptr += QuickHex(ptr, e_buffer, total - 3);
+ ptr--;
+ *ptr++ = '\n';
+ *ptr = 0;
+ HiSax_putstatus(cs, NULL, cs->dlog);
+ } else
+ HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3);
+ }
+ }
rcnt = bz->f1 - bz->f2;
if (rcnt < 0)
@@ -900,7 +987,7 @@ static void receive_emsg(struct IsdnCardState *cs)
goto Begin;
restore_flags(flags);
return;
-} /* receive_emsg */
+} /* receive_emsg */
/*********************/
/* Interrupt handler */
@@ -919,6 +1006,9 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
printk(KERN_WARNING "HFC-PCI: Spurious interrupt!\n");
return;
}
+ if (!(cs->hw.hfcpci.int_m2 & 0x08))
+ return; /* not initialised */
+
if (HFCPCI_ANYINT & (stat = Read_hfc(cs, HFCPCI_STATUS))) {
val = Read_hfc(cs, HFCPCI_INT_S1);
if (cs->debug & L1_DEB_ISAC)
@@ -931,7 +1021,7 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
"locked" : "unlocked");
val &= cs->hw.hfcpci.int_m1;
- if (val & 0x40) { /* TE state machine irq */
+ if (val & 0x40) { /* state machine irq */
exval = Read_hfc(cs, HFCPCI_STATES) & 0xf;
if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state,
@@ -940,6 +1030,14 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
sched_event_D_pci(cs, D_L1STATECHANGE);
val &= ~0x40;
}
+ if (val & 0x80) { /* timer irq */
+ if (cs->hw.hfcpci.nt_mode) {
+ if ((--cs->hw.hfcpci.nt_timer) < 0)
+ sched_event_D_pci(cs, D_L1STATECHANGE);
+ }
+ val &= ~0x80;
+ Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
+ }
while (val) {
save_flags(flags);
cli();
@@ -954,24 +1052,23 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
cs->hw.hfcpci.int_s1 = exval;
}
if (val & 0x08) {
- if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1:0))) {
+ if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) {
if (cs->debug)
debugl1(cs, "hfcpci spurious 0x08 IRQ");
} else
main_rec_hfcpci(bcs);
}
- if (val & 0x10) {
- if (cs->logecho)
- receive_emsg(cs);
- else
- if (!(bcs = Sel_BCS(cs, 1))) {
+ if (val & 0x10) {
+ if (cs->logecho)
+ receive_emsg(cs);
+ else if (!(bcs = Sel_BCS(cs, 1))) {
if (cs->debug)
debugl1(cs, "hfcpci spurious 0x10 IRQ");
} else
main_rec_hfcpci(bcs);
}
if (val & 0x01) {
- if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1:0))) {
+ if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) {
if (cs->debug)
debugl1(cs, "hfcpci spurious 0x01 IRQ");
} else {
@@ -1036,7 +1133,7 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
}
goto afterXPR;
} else {
- idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+ dev_kfree_skb(cs->tx_skb);
cs->tx_cnt = 0;
cs->tx_skb = NULL;
}
@@ -1070,20 +1167,6 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
static void
hfcpci_dbusy_timer(struct IsdnCardState *cs)
{
-#if 0
- struct PStack *stptr;
- if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
- if (cs->debug)
- debugl1(cs, "D-Channel Busy");
- test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
- stptr = cs->stlist;
-
- while (stptr != NULL) {
- stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
- stptr = stptr->next;
- }
- }
-#endif
}
/*************************************/
@@ -1094,6 +1177,7 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
{
struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
struct sk_buff *skb = arg;
+ int flags;
switch (pr) {
case (PH_DATA | REQUEST):
@@ -1169,39 +1253,46 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
break;
case (HW_DEACTIVATE | REQUEST):
- cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER;
+ cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER;
Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
break;
case (HW_INFO3 | REQUEST):
cs->hw.hfcpci.mst_m |= HFCPCI_MASTER;
Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
break;
-#if 0
case (HW_TESTLOOP | REQUEST):
- u_char val = 0;
- if (1 & (int) arg)
- val |= 0x0c;
- if (2 & (int) arg)
- val |= 0x3;
- if (test_bit(HW_IOM1, &cs->HW_Flags)) {
- /* IOM 1 Mode */
- if (!val) {
- cs->writeisac(cs, ISAC_SPCR, 0xa);
- cs->writeisac(cs, ISAC_ADF1, 0x2);
- } else {
- cs->writeisac(cs, ISAC_SPCR, val);
- cs->writeisac(cs, ISAC_ADF1, 0xa);
- }
- } else {
- /* IOM 2 Mode */
- cs->writeisac(cs, ISAC_SPCR, val);
- if (val)
- cs->writeisac(cs, ISAC_ADF1, 0x8);
- else
- cs->writeisac(cs, ISAC_ADF1, 0x0);
+ switch ((int) arg) {
+ case (1):
+ Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* tx slot */
+ Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* rx slot */
+ save_flags(flags);
+ cli();
+ cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~7) | 1;
+ Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
+ restore_flags(flags);
+ break;
+
+ case (2):
+ Write_hfc(cs, HFCPCI_B2_SSL, 0x81); /* tx slot */
+ Write_hfc(cs, HFCPCI_B2_RSL, 0x81); /* rx slot */
+ save_flags(flags);
+ cli();
+ cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~0x38) | 0x08;
+ Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
+ restore_flags(flags);
+ break;
+
+ default:
+ if (cs->debug & L1_DEB_WARN)
+ debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg);
+ return;
}
+ save_flags(flags);
+ cli();
+ cs->hw.hfcpci.trm |= 0x80; /* enable IOM-loop */
+ Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
+ restore_flags(flags);
break;
-#endif
default:
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hfcpci_l1hw unknown pr %4x", pr);
@@ -1241,113 +1332,127 @@ mode_hfcpci(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
bzfifo_type *bzr, *bzt;
- int flags;
+ int flags, fifo2;
if (cs->debug & L1_DEB_HSCX)
debugl1(cs, "HFCPCI bchannel mode %d bchan %d/%d",
mode, bc, bcs->channel);
bcs->mode = mode;
bcs->channel = bc;
- if (cs->chanlimit > 1) {
- cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */
- cs->hw.hfcpci.sctrl_e &= ~0x80;
- }
- else {
- if (bc) {
- cs->hw.hfcpci.bswapped = 1; /* B1 and B2 exchanged */
- cs->hw.hfcpci.sctrl_e |= 0x80;
- bc = 0; /* B1 controller used */
- }
- else {
- cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */
- cs->hw.hfcpci.sctrl_e &= ~0x80;
- }
- }
+ fifo2 = bc;
save_flags(flags);
cli();
+ if (cs->chanlimit > 1) {
+ cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */
+ cs->hw.hfcpci.sctrl_e &= ~0x80;
+ } else {
+ if (bc) {
+ if (mode != L1_MODE_NULL) {
+ cs->hw.hfcpci.bswapped = 1; /* B1 and B2 exchanged */
+ cs->hw.hfcpci.sctrl_e |= 0x80;
+ } else {
+ cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */
+ cs->hw.hfcpci.sctrl_e &= ~0x80;
+ }
+ fifo2 = 0;
+ } else {
+ cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */
+ cs->hw.hfcpci.sctrl_e &= ~0x80;
+ }
+ }
switch (mode) {
case (L1_MODE_NULL):
if (bc) {
cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA;
cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA;
- cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2;
- cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC);
} else {
cs->hw.hfcpci.sctrl &= ~SCTRL_B1_ENA;
cs->hw.hfcpci.sctrl_r &= ~SCTRL_B1_ENA;
+ }
+ if (fifo2) {
+ cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2;
+ cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
+ } else {
cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1;
- cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
+ cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
}
break;
case (L1_MODE_TRANS):
if (bc) {
- cs->hw.hfcpci.ctmt |= 2;
- cs->hw.hfcpci.conn &= ~0x18;
cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
- cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
- cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC);
- bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
- bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2;
} else {
- cs->hw.hfcpci.ctmt |= 1;
- cs->hw.hfcpci.conn &= ~0x03;
cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
+ }
+ if (fifo2) {
+ cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
+ cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
+ cs->hw.hfcpci.ctmt |= 2;
+ cs->hw.hfcpci.conn &= ~0x18;
+ bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
+ bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2;
+ } else {
cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
- cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
- bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1;
- bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1;
+ cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
+ cs->hw.hfcpci.ctmt |= 1;
+ cs->hw.hfcpci.conn &= ~0x03;
+ bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1;
+ bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1;
}
bzr->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
- bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1;
+ bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1;
bzr->f1 = MAX_B_FRAMES;
- bzr->f2 = bzr->f1; /* init F pointers to remain constant */
+ bzr->f2 = bzr->f1; /* init F pointers to remain constant */
bzt->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
- bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1;
+ bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1;
bzt->f1 = MAX_B_FRAMES;
- bzt->f2 = bzt->f1; /* init F pointers to remain constant */
+ bzt->f2 = bzt->f1; /* init F pointers to remain constant */
break;
case (L1_MODE_HDLC):
if (bc) {
- cs->hw.hfcpci.ctmt &= ~2;
- cs->hw.hfcpci.conn &= ~0x18;
cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
- cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
- cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC);
} else {
- cs->hw.hfcpci.ctmt &= ~1;
- cs->hw.hfcpci.conn &= ~0x3;
cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
+ }
+ if (fifo2) {
+ cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
+ cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
+ cs->hw.hfcpci.ctmt &= ~2;
+ cs->hw.hfcpci.conn &= ~0x18;
+ } else {
cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
- cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
+ cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
+ cs->hw.hfcpci.ctmt &= ~1;
+ cs->hw.hfcpci.conn &= ~0x03;
}
break;
case (L1_MODE_EXTRN):
if (bc) {
- cs->hw.hfcpci.conn |= 0x10;
+ cs->hw.hfcpci.conn |= 0x10;
cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2;
- cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC);
+ cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
} else {
- cs->hw.hfcpci.conn |= 0x02;
+ cs->hw.hfcpci.conn |= 0x02;
cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1;
- cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
+ cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
}
break;
}
+ Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e);
Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
- restore_flags(flags);
Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
+ restore_flags(flags);
}
/******************************/
@@ -1420,7 +1525,7 @@ close_hfcpci(struct BCState *bcs)
discard_queue(&bcs->rqueue);
discard_queue(&bcs->squeue);
if (bcs->tx_skb) {
- idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+ dev_kfree_skb(bcs->tx_skb);
bcs->tx_skb = NULL;
test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
}
@@ -1467,40 +1572,72 @@ setstack_2b(struct PStack *st, struct BCState *bcs)
static void
hfcpci_bh(struct IsdnCardState *cs)
{
+ int flags;
/* struct PStack *stptr;
*/
if (!cs)
return;
-#if 0
- if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
- if (cs->debug)
- debugl1(cs, "D-Channel Busy cleared");
- stptr = cs->stlist;
- while (stptr != NULL) {
- stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
- stptr = stptr->next;
- }
- }
-#endif
if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
- switch (cs->dc.hfcpci.ph_state) {
- case (0):
- l1_msg(cs, HW_RESET | INDICATION, NULL);
- break;
- case (3):
- l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
- break;
- case (8):
- l1_msg(cs, HW_RSYNC | INDICATION, NULL);
- break;
- case (6):
- l1_msg(cs, HW_INFO2 | INDICATION, NULL);
- break;
- case (7):
- l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
- break;
- default:
- break;
+ if (!cs->hw.hfcpci.nt_mode)
+ switch (cs->dc.hfcpci.ph_state) {
+ case (0):
+ l1_msg(cs, HW_RESET | INDICATION, NULL);
+ break;
+ case (3):
+ l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
+ break;
+ case (8):
+ l1_msg(cs, HW_RSYNC | INDICATION, NULL);
+ break;
+ case (6):
+ l1_msg(cs, HW_INFO2 | INDICATION, NULL);
+ break;
+ case (7):
+ l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
+ break;
+ default:
+ break;
+ } else {
+ switch (cs->dc.hfcpci.ph_state) {
+ case (2):
+ save_flags(flags);
+ cli();
+ if (cs->hw.hfcpci.nt_timer < 0) {
+ cs->hw.hfcpci.nt_timer = 0;
+ cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
+ Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+ /* Clear already pending ints */
+ if (Read_hfc(cs, HFCPCI_INT_S1));
+
+ Write_hfc(cs, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE);
+ udelay(10);
+ Write_hfc(cs, HFCPCI_STATES, 4);
+ cs->dc.hfcpci.ph_state = 4;
+ } else {
+ cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_TIMER;
+ Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+ cs->hw.hfcpci.ctmt &= ~HFCPCI_AUTO_TIMER;
+ cs->hw.hfcpci.ctmt |= HFCPCI_TIM3_125;
+ Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
+ Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
+ cs->hw.hfcpci.nt_timer = NT_T1_COUNT;
+ Write_hfc(cs, HFCPCI_STATES, 2 | HFCPCI_NT_G2_G3); /* allow G2 -> G3 transition */
+ }
+ restore_flags(flags);
+ break;
+ case (1):
+ case (3):
+ case (4):
+ save_flags(flags);
+ cli();
+ cs->hw.hfcpci.nt_timer = 0;
+ cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
+ Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+ restore_flags(flags);
+ break;
+ default:
+ break;
+ }
}
}
if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
@@ -1513,8 +1650,8 @@ hfcpci_bh(struct IsdnCardState *cs)
/*************************************/
/* Alloc memory send data for queues */
/*************************************/
-unsigned int * __init
- init_send_hfcpci(int cnt)
+__initfunc(unsigned int
+ *init_send_hfcpci(int cnt))
{
int i, *send;
@@ -1531,18 +1668,14 @@ unsigned int * __init
/********************************/
/* called for card init message */
/********************************/
-void __init
- inithfcpci(struct IsdnCardState *cs)
+__initfunc(void
+ inithfcpci(struct IsdnCardState *cs))
{
cs->setstack_d = setstack_hfcpci;
cs->dbusytimer.function = (void *) hfcpci_dbusy_timer;
cs->dbusytimer.data = (long) cs;
init_timer(&cs->dbusytimer);
cs->tqueue.routine = (void *) (void *) hfcpci_bh;
-#if 0
- if (!cs->hw.hfcpci.send)
- cs->hw.hfcpci.send = init_send_hfcpci(16);
-#endif
if (!cs->bcs[0].hw.hfc.send)
cs->bcs[0].hw.hfc.send = init_send_hfcpci(32);
if (!cs->bcs[1].hw.hfc.send)
@@ -1579,7 +1712,7 @@ hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
inithfcpci(cs);
save_flags(flags);
sti();
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */
/* now switch timer interrupt off */
cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
@@ -1596,52 +1729,49 @@ hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
/* this variable is used as card index when more than one cards are present */
-#ifdef COMPAT_HAS_NEW_PCI
static struct pci_dev *dev_hfcpci __initdata = NULL;
-#else
-static int pci_index __initdata = 0;
-#endif
#endif /* CONFIG_PCI */
-int __init
- setup_hfcpci(struct IsdnCard *card)
+__initfunc(int
+ setup_hfcpci(struct IsdnCard *card))
{
struct IsdnCardState *cs = card->cs;
+ unsigned short cmd;
char tmp[64];
int i;
-#ifdef COMPAT_HAS_NEW_PCI
- struct pci_dev *tmp_hfcpci = NULL;
-#endif
+ struct pci_dev *tmp_hfcpci = NULL;
strcpy(tmp, hfcpci_revision);
printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
#if CONFIG_PCI
cs->hw.hfcpci.int_s1 = 0;
-#if 0
- cs->hw.hfcpci.send = NULL;
-#endif
cs->bcs[0].hw.hfc.send = NULL;
cs->bcs[1].hw.hfc.send = NULL;
cs->dc.hfcpci.ph_state = 0;
cs->hw.hfcpci.fifo = 255;
if (cs->typ == ISDN_CTYPE_HFC_PCI) {
-#ifdef COMPAT_HAS_NEW_PCI
if (!pci_present()) {
printk(KERN_ERR "HFC-PCI: no PCI bus present\n");
return (0);
}
i = 0;
- while (id_list[i].vendor_id) {
- tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
- id_list[i].device_id,
- dev_hfcpci);
- if (tmp_hfcpci) break;
- i++;
- }
-
+ while (id_list[i].vendor_id) {
+ tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
+ id_list[i].device_id,
+ dev_hfcpci);
+ i++;
+ if (tmp_hfcpci) {
+ if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
+ continue;
+ else
+ break;
+ }
+ }
+
if (tmp_hfcpci) {
- dev_hfcpci = tmp_hfcpci; /* old device */
+ i--;
+ dev_hfcpci = tmp_hfcpci; /* old device */
cs->hw.hfcpci.pci_bus = dev_hfcpci->bus->number;
cs->hw.hfcpci.pci_device_fn = dev_hfcpci->devfn;
cs->irq = dev_hfcpci->irq;
@@ -1649,43 +1779,45 @@ int __init
printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
return (0);
}
- cs->hw.hfcpci.pci_io = (char *) get_pcibase(dev_hfcpci, 1);
- printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n",id_list[i].vendor_name,id_list[i].card_name);
+ cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->resource[ 1].start;
+ printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
} else {
printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
return (0);
}
-#else
- for (; pci_index < 255; pci_index++) {
- unsigned char irq;
-
- i = 0;
- while (id_list[i].vendor_id) {
- if (pcibios_find_device(id_list[i].vendor_id,
- id_list[i].device_id, pci_index,
- &cs->hw.hfcpci.pci_bus, &cs->hw.hfcpci.pci_device_fn) == 0)
- break;
- i++;
- }
- if (!id_list[i].vendor_id)
- continue;
-
- pcibios_read_config_byte(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn,
- PCI_INTERRUPT_LINE, &irq);
- cs->irq = irq;
-
+ if (((int) cs->hw.hfcpci.pci_io & (PAGE_SIZE - 1))) {
+ printk(KERN_WARNING "HFC-PCI shared mem address will be corrected\n");
+ pcibios_write_config_word(cs->hw.hfcpci.pci_bus,
+ cs->hw.hfcpci.pci_device_fn,
+ PCI_COMMAND,
+ 0x0103); /* set SERR */
+ pcibios_read_config_word(cs->hw.hfcpci.pci_bus,
+ cs->hw.hfcpci.pci_device_fn,
+ PCI_COMMAND,
+ &cmd);
+ pcibios_write_config_word(cs->hw.hfcpci.pci_bus,
+ cs->hw.hfcpci.pci_device_fn,
+ PCI_COMMAND,
+ cmd & ~2);
+ (int) cs->hw.hfcpci.pci_io &= ~(PAGE_SIZE - 1);
+ pcibios_write_config_dword(cs->hw.hfcpci.pci_bus,
+ cs->hw.hfcpci.pci_device_fn,
+ PCI_BASE_ADDRESS_1,
+ (int) cs->hw.hfcpci.pci_io);
+ pcibios_write_config_word(cs->hw.hfcpci.pci_bus,
+ cs->hw.hfcpci.pci_device_fn,
+ PCI_COMMAND,
+ cmd);
pcibios_read_config_dword(cs->hw.hfcpci.pci_bus,
- cs->hw.hfcpci.pci_device_fn, PCI_BASE_ADDRESS_1,
- (void *) &cs->hw.hfcpci.pci_io);
- printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n",id_list[i].vendor_name,id_list[i].card_name);
- break;
- }
- if (pci_index == 255) {
- printk(KERN_WARNING "HFC-PCI: No card found\n");
- return (0);
+ cs->hw.hfcpci.pci_device_fn,
+ PCI_BASE_ADDRESS_1,
+ (void *) &cs->hw.hfcpci.pci_io);
+ if (((int) cs->hw.hfcpci.pci_io & (PAGE_SIZE - 1))) {
+ printk(KERN_WARNING "HFC-PCI unable to align address %x\n", (unsigned) cs->hw.hfcpci.pci_io);
+ return (0);
+ }
+ dev_hfcpci->resource[1].start = (int) cs->hw.hfcpci.pci_io;
}
- pci_index++;
-#endif /* COMPAT_HAS_NEW_PCI */
if (!cs->hw.hfcpci.pci_io) {
printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
return (0);
@@ -1701,16 +1833,16 @@ int __init
(((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
pcibios_write_config_dword(cs->hw.hfcpci.pci_bus,
cs->hw.hfcpci.pci_device_fn, 0x80,
- (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
+ (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
printk(KERN_INFO
- "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
+ "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
(u_int) cs->hw.hfcpci.pci_io,
(u_int) cs->hw.hfcpci.fifos,
(u_int) virt_to_bus(cs->hw.hfcpci.fifos),
cs->irq, HZ);
pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */
- cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */
+ cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */
cs->hw.hfcpci.int_m1 = 0;
Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
@@ -1735,7 +1867,7 @@ int __init
reset_hfcpci(cs);
cs->cardmsg = &hfcpci_card_msg;
- cs->auxcmd = &hfcpci_auxcmd;
+ cs->auxcmd = &hfcpci_auxcmd;
return (1);
#else
printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n");