patch-2.2.14 linux/drivers/isdn/hisax/hfc_pci.c
Next file: linux/drivers/isdn/hisax/hfc_pci.h
Previous file: linux/drivers/isdn/hisax/hfc_2bs0.h
Back to the patch index
Back to the overall index
- Lines: 1284
- Date:
Tue Jan 4 10:12:16 2000
- Orig file:
v2.2.13/linux/drivers/isdn/hisax/hfc_pci.c
- Orig date:
Tue Jan 4 11:10:34 2000
diff -u --recursive --new-file v2.2.13/linux/drivers/isdn/hisax/hfc_pci.c linux/drivers/isdn/hisax/hfc_pci.c
@@ -1,4 +1,4 @@
-/* $Id: hfc_pci.c,v 1.20 1999/09/07 06:18:55 werner Exp $
+/* $Id: hfc_pci.c,v 1.25 1999/12/19 13:09:42 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.25 1999/12/19 13:09:42 keil
+ * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for
+ * signal proof delays
+ *
+ * Revision 1.24 1999/11/17 23:59:55 werner
+ *
+ * removed unneeded data
+ *
+ * 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
@@ -103,52 +122,40 @@
extern const char *CardType[];
-static const char *hfcpci_revision = "$Revision: 1.20 $";
+static const char *hfcpci_revision = "$Revision: 1.25 $";
/* 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},
};
#if CONFIG_PCI
-/*****************************/
-/* release D- and B-channels */
-/*****************************/
-void
-releasehfcpci(struct IsdnCardState *cs)
-{
- if (cs->bcs[0].hw.hfc.send) {
- kfree(cs->bcs[0].hw.hfc.send);
- cs->bcs[0].hw.hfc.send = NULL;
- }
- if (cs->bcs[1].hw.hfc.send) {
- kfree(cs->bcs[1].hw.hfc.send);
- cs->bcs[1].hw.hfc.send = NULL;
- }
-}
/******************************************/
/* free hardware resources used by driver */
@@ -156,10 +163,21 @@
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();
+ current->state = TASK_UNINTERRUPTIBLE;
+ 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 */
- releasehfcpci(cs);
+ 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 */
del_timer(&cs->hw.hfcpci.timer);
kfree(cs->hw.hfcpci.share_start);
cs->hw.hfcpci.share_start = NULL;
@@ -175,16 +193,20 @@
{
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;
+ current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */
Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */
- current->state = TASK_INTERRUPTIBLE;
+ current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */
if (Read_hfc(cs, HFCPCI_STATUS) & 2)
printk(KERN_WARNING "HFC-PCI init bit busy\n");
@@ -192,25 +214,23 @@
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);
@@ -218,24 +238,29 @@
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);
}
@@ -326,7 +351,7 @@
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 */
@@ -418,54 +443,56 @@
/*******************************************************************************/
/* 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;
-
- 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 <= 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 */
+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;
+
+ 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 */
+
+ 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 {
- 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 */
@@ -526,11 +553,10 @@
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;
@@ -622,7 +648,7 @@
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;
@@ -641,57 +667,53 @@
}
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 */
+ 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);
- 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;
+ 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,
@@ -757,51 +779,107 @@
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;
@@ -838,55 +916,54 @@
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)
@@ -902,7 +979,7 @@
goto Begin;
restore_flags(flags);
return;
-} /* receive_emsg */
+} /* receive_emsg */
/*********************/
/* Interrupt handler */
@@ -921,6 +998,9 @@
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)
@@ -933,7 +1013,7 @@
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,
@@ -942,6 +1022,14 @@
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();
@@ -956,24 +1044,23 @@
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 {
@@ -1082,6 +1169,7 @@
{
struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
struct sk_buff *skb = arg;
+ int flags;
switch (pr) {
case (PH_DATA | REQUEST):
@@ -1157,13 +1245,46 @@
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;
+ case (HW_TESTLOOP | REQUEST):
+ 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;
default:
if (cs->debug & L1_DEB_WARN)
debugl1(cs, "hfcpci_l1hw unknown pr %4x", pr);
@@ -1203,113 +1324,127 @@
{
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);
}
/******************************/
@@ -1429,29 +1564,72 @@
static void
hfcpci_bh(struct IsdnCardState *cs)
{
+ int flags;
/* struct PStack *stptr;
*/
if (!cs)
return;
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))
@@ -1461,24 +1639,6 @@
}
-/*************************************/
-/* Alloc memory send data for queues */
-/*************************************/
-__initfunc(unsigned int
- *init_send_hfcpci(int cnt))
-{
- int i, *send;
-
- if (!(send = kmalloc(cnt * sizeof(unsigned int), GFP_ATOMIC))) {
- printk(KERN_WARNING
- "HiSax: No memory for hfcpci.send\n");
- return (NULL);
- }
- for (i = 0; i < cnt; i++)
- send[i] = 0x1fff;
- return (send);
-}
-
/********************************/
/* called for card init message */
/********************************/
@@ -1490,10 +1650,6 @@
cs->dbusytimer.data = (long) cs;
init_timer(&cs->dbusytimer);
cs->tqueue.routine = (void *) (void *) hfcpci_bh;
- if (!cs->bcs[0].hw.hfc.send)
- cs->bcs[0].hw.hfc.send = init_send_hfcpci(32);
- if (!cs->bcs[1].hw.hfc.send)
- cs->bcs[1].hw.hfc.send = init_send_hfcpci(32);
cs->BC_Send_Data = &hfcpci_send_data;
cs->bcs[0].BC_SetStack = setstack_2b;
cs->bcs[1].BC_SetStack = setstack_2b;
@@ -1526,7 +1682,7 @@
inithfcpci(cs);
save_flags(flags);
sti();
- current->state = TASK_INTERRUPTIBLE;
+ current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */
/* now switch timer interrupt off */
cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
@@ -1551,16 +1707,15 @@
setup_hfcpci(struct IsdnCard *card))
{
struct IsdnCardState *cs = card->cs;
+ unsigned short cmd;
char tmp[64];
int i;
- struct pci_dev *tmp_hfcpci = NULL;
+ 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;
- 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) {
@@ -1569,22 +1724,22 @@
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);
- i++;
- if (tmp_hfcpci) {
- if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->base_address[0] & PCI_BASE_ADDRESS_IO_MASK)))
- continue;
- else
- break;
- }
- }
-
+ 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->base_address[ 0] & PCI_BASE_ADDRESS_IO_MASK)))
+ continue;
+ else
+ break;
+ }
+ }
+
if (tmp_hfcpci) {
- i--;
- 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;
@@ -1593,11 +1748,44 @@
return (0);
}
cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->base_address[ 1];
- printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n",id_list[i].vendor_name,id_list[i].card_name);
+ 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);
}
+ 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);
+ 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->base_address[1] = (int) cs->hw.hfcpci.pci_io;
+ }
if (!cs->hw.hfcpci.pci_io) {
printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
return (0);
@@ -1613,16 +1801,16 @@
(((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);
@@ -1647,7 +1835,7 @@
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");
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)