diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-01-29 01:41:54 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-01-29 01:41:54 +0000 |
commit | f969d69ba9f952e5bdd38278e25e26a3e4a61a70 (patch) | |
tree | b3530d803df59d726afaabebc6626987dee1ca05 /drivers/isdn/hisax/hfc_pci.c | |
parent | a10ce7ef2066b455d69187643ddf2073bfc4db24 (diff) |
Merge with 2.3.27.
Diffstat (limited to 'drivers/isdn/hisax/hfc_pci.c')
-rw-r--r-- | drivers/isdn/hisax/hfc_pci.c | 974 |
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"); |