Exemple #1
0
static int MIXCOM_send_packet(struct net_device *dev, struct sk_buff *skb) 
{
	struct comx_channel *ch = dev->priv;
	struct mixcom_privdata *hw = ch->HW_privdata;
	unsigned long flags;

	if (ch->debug_flags & DEBUG_HW_TX) {
		comx_debug_bytes(dev, skb->data, skb->len, "MIXCOM_send_packet");
	}

	if (!(ch->line_status & LINE_UP)) {
		return FRAME_DROPPED;
	}

	if (skb->len > HSCX_MTU) {
		ch->stats.tx_errors++;	
		return FRAME_ERROR;
	}

	save_flags(flags); cli();

	if (test_and_set_bit(0, &hw->txbusy)) {
		printk(KERN_ERR "%s: transmitter called while busy... dropping frame (length %d)\n", dev->name, skb->len);
		restore_flags(flags);
		return FRAME_DROPPED;
	}


	hw->sending = skb;
	hw->tx_ptr = 0;
	hw->txbusy = 1;
//	atomic_inc(&skb->users);	// save it
	hscx_fill_fifo(dev);
	restore_flags(flags);

	ch->stats.tx_packets++;
	ch->stats.tx_bytes += skb->len; 

	if (ch->debug_flags & DEBUG_HW_TX) {
		comx_debug(dev, "MIXCOM_send_packet was successful\n\n");
	}

	return FRAME_ACCEPTED;
}
Exemple #2
0
static inline void
hscx_int_main(struct IsdnCardState *cs, u_char val)
{

	u_char exval;
	struct BCState *bcs;

	if (val & 0x01) {
		bcs = cs->bcs + 1;
		exval = READHSCX(cs, 1, HSCX_EXIR);
		if (exval & 0x40) {
			if (bcs->mode == 1)
				hscx_fill_fifo(bcs);
			else {
#ifdef ERROR_STATISTIC
				bcs->err_tx++;
#endif
				/* Here we lost an TX interrupt, so
				   * restart transmitting the whole frame.
				 */
				if (bcs->tx_skb) {
					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
					bcs->tx_cnt += bcs->hw.hscx.count;
					bcs->hw.hscx.count = 0;
				}
				WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
			}
		} else if (cs->debug & L1_DEB_HSCX)
			debugl1(cs, "HSCX B EXIR %x", exval);
	}
	if (val & 0xf8) {
		if (cs->debug & L1_DEB_HSCX)
			debugl1(cs, "HSCX B interrupt %x", val);
		hscx_interrupt(cs, val, 1);
	}
	if (val & 0x02) {
		bcs = cs->bcs;
		exval = READHSCX(cs, 0, HSCX_EXIR);
		if (exval & 0x40) {
			if (bcs->mode == L1_MODE_TRANS)
				hscx_fill_fifo(bcs);
			else {
				/* Here we lost an TX interrupt, so
				   * restart transmitting the whole frame.
				 */
#ifdef ERROR_STATISTIC
				bcs->err_tx++;
#endif
				if (bcs->tx_skb) {
					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
					bcs->tx_cnt += bcs->hw.hscx.count;
					bcs->hw.hscx.count = 0;
				}
				WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
			}
		} else if (cs->debug & L1_DEB_HSCX)
			debugl1(cs, "HSCX A EXIR %x", exval);
	}
	if (val & 0x04) {
		exval = READHSCX(cs, 0, HSCX_ISTA);
		if (cs->debug & L1_DEB_HSCX)
			debugl1(cs, "HSCX A interrupt %x", exval);
		hscx_interrupt(cs, exval, 0);
	}
}
Exemple #3
0
static inline void
hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
{
	u_char r;
	struct BCState *bcs = cs->bcs + hscx;
	struct sk_buff *skb;
	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
	int count;

	if (!test_bit(BC_FLG_INIT, &bcs->Flag))
		return;

	if (val & 0x80) {	/* RME */
		r = READHSCX(cs, hscx, HSCX_RSTA);
		if ((r & 0xf0) != 0xa0) {
			if (!(r & 0x80)) {
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "HSCX invalid frame");
#ifdef ERROR_STATISTIC
				bcs->err_inv++;
#endif
			}
			if ((r & 0x40) && bcs->mode) {
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "HSCX RDO mode=%d",
						bcs->mode);
#ifdef ERROR_STATISTIC
				bcs->err_rdo++;
#endif
			}
			if (!(r & 0x20)) {
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "HSCX CRC error");
#ifdef ERROR_STATISTIC
				bcs->err_crc++;
#endif
			}
			WriteHSCXCMDR(cs, hscx, 0x80);
		} else {
			count = READHSCX(cs, hscx, HSCX_RBCL) & (
				test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
			if (count == 0)
				count = fifo_size;
			hscx_empty_fifo(bcs, count);
			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
				if (cs->debug & L1_DEB_HSCX_FIFO)
					debugl1(cs, "HX Frame %d", count);
				if (!(skb = dev_alloc_skb(count)))
					printk(KERN_WARNING "HSCX: receive out of memory\n");
				else {
					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
					skb_queue_tail(&bcs->rqueue, skb);
				}
			}
		}
		bcs->hw.hscx.rcvidx = 0;
		hscx_sched_event(bcs, B_RCVBUFREADY);
	}
	if (val & 0x40) {	/* RPF */
		hscx_empty_fifo(bcs, fifo_size);
		if (bcs->mode == L1_MODE_TRANS) {
			/* receive audio data */
			if (!(skb = dev_alloc_skb(fifo_size)))
				printk(KERN_WARNING "HiSax: receive out of memory\n");
			else {
				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
				skb_queue_tail(&bcs->rqueue, skb);
			}
			bcs->hw.hscx.rcvidx = 0;
			hscx_sched_event(bcs, B_RCVBUFREADY);
		}
	}
	if (val & 0x10) {	/* XPR */
		if (bcs->tx_skb) {
			if (bcs->tx_skb->len) {
				hscx_fill_fifo(bcs);
				return;
			} else {
				if (bcs->st->lli.l1writewakeup &&
					(PACKET_NOACK != bcs->tx_skb->pkt_type))
					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
				dev_kfree_skb_irq(bcs->tx_skb);
				bcs->hw.hscx.count = 0; 
				bcs->tx_skb = NULL;
			}
		}
		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
			bcs->hw.hscx.count = 0;
			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
			hscx_fill_fifo(bcs);
		} else {
			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
			hscx_sched_event(bcs, B_XMTBUFREADY);
		}
	}
}
Exemple #4
0
static inline void
hscx_interrupt(struct IsdnCardState *sp, u_char val, u_char hscx)
{
	u_char r;
	struct HscxState *hsp = sp->hs + hscx;
	struct sk_buff *skb;
	int count;
	char tmp[32];

	if (!hsp->init)
		return;

	if (val & 0x80) {	/* RME */

		r = HscxReadReg(sp->hscx[hsp->hscx], hscx, HSCX_RSTA);
		if ((r & 0xf0) != 0xa0) {
			if (!(r & 0x80))
				if (sp->debug & L1_DEB_WARN)
					debugl1(sp, "HSCX invalid frame");
			if ((r & 0x40) && hsp->mode)
				if (sp->debug & L1_DEB_WARN) {
					sprintf(tmp, "HSCX RDO mode=%d",
						hsp->mode);
					debugl1(sp, tmp);
				}
			if (!(r & 0x20))
				if (sp->debug & L1_DEB_WARN)
					debugl1(sp, "HSCX CRC error");
			writehscxCMDR(sp->hscx[hsp->hscx], hsp->hscx, 0x80);
		} else {
			count = HscxReadReg(sp->hscx[hsp->hscx], hscx, HSCX_RBCL) & 0x1f;
			if (count == 0)
				count = 32;
			hscx_empty_fifo(hsp, count);
			if ((count = hsp->rcvidx - 1) > 0) {
				if (sp->debug & L1_DEB_HSCX_FIFO) {
					sprintf(tmp, "HX Frame %d", count);
					debugl1(sp, tmp);
				}
				if (!(skb = dev_alloc_skb(count)))
					printk(KERN_WARNING "IX1: receive out of memory\n");
				else {
					memcpy(skb_put(skb, count), hsp->rcvbuf, count);
					skb_queue_tail(&hsp->rqueue, skb);
				}
			}
		}
		hsp->rcvidx = 0;
		hscx_sched_event(hsp, HSCX_RCVBUFREADY);
	}
	if (val & 0x40) {	/* RPF */
		hscx_empty_fifo(hsp, 32);
		if (hsp->mode == 1) {
			/* receive audio data */
			if (!(skb = dev_alloc_skb(32)))
				printk(KERN_WARNING "IX1: receive out of memory\n");
			else {
				memcpy(skb_put(skb, 32), hsp->rcvbuf, 32);
				skb_queue_tail(&hsp->rqueue, skb);
			}
			hsp->rcvidx = 0;
			hscx_sched_event(hsp, HSCX_RCVBUFREADY);
		}
	}
	if (val & 0x10) {	/* XPR */
		if (hsp->tx_skb)
			if (hsp->tx_skb->len) {
				hscx_fill_fifo(hsp);
				return;
			} else {
				dev_kfree_skb(hsp->tx_skb, FREE_WRITE);
				hsp->count = 0;
				if (hsp->st->l4.l1writewakeup)
					hsp->st->l4.l1writewakeup(hsp->st);
				hsp->tx_skb = NULL;
			}
		if ((hsp->tx_skb = skb_dequeue(&hsp->squeue))) {
			hsp->count = 0;
			hscx_fill_fifo(hsp);
		} else
			hscx_sched_event(hsp, HSCX_XMTBUFREADY);
	}
}
Exemple #5
0
static void MIXCOM_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
	unsigned long flags;
	struct net_device *dev = (struct net_device *)dev_id;
	struct comx_channel *ch, *twin_ch;
	struct mixcom_privdata *hw, *twin_hw;
	register unsigned char ista;

	if (dev==NULL) {
		printk(KERN_ERR "comx_interrupt: irq %d for unknown device\n",irq);
		return;
	}

	ch = dev->priv; 
	hw = ch->HW_privdata;

	save_flags(flags); cli(); 

	while((ista = (rd_hscx(dev, HSCX_ISTA) & (HSCX_RME | HSCX_RPF | 
	    HSCX_XPR | HSCX_EXB | HSCX_EXA | HSCX_ICA)))) {
		register byte ista2 = 0;

		if (ista & HSCX_RME) {
			mixcom_receive_frame(dev);
		}
		if (ista & HSCX_RPF) {
			hscx_empty_fifo(dev, 32);
		}
		if (ista & HSCX_XPR) {
			if (hw->tx_ptr) {
				hscx_fill_fifo(dev);
			} else {
				clear_bit(0, &hw->txbusy);
               			ch->LINE_tx(dev);
			}
		}
		
		if (ista & HSCX_EXB) {
			mixcom_extended_interrupt(dev);
		}
		
		if ((ista & HSCX_EXA) && ch->twin)  {
			mixcom_extended_interrupt(ch->twin);
		}
	
		if ((ista & HSCX_ICA) && ch->twin &&
		    (ista2 = rd_hscx(ch->twin, HSCX_ISTA) &
		    (HSCX_RME | HSCX_RPF | HSCX_XPR ))) {
			if (ista2 & HSCX_RME) {
				mixcom_receive_frame(ch->twin);
			}
			if (ista2 & HSCX_RPF) {
				hscx_empty_fifo(ch->twin, 32);
			}
			if (ista2 & HSCX_XPR) {
				twin_ch=ch->twin->priv;
				twin_hw=twin_ch->HW_privdata;
				if (twin_hw->tx_ptr) {
					hscx_fill_fifo(ch->twin);
				} else {
					clear_bit(0, &twin_hw->txbusy);
					ch->LINE_tx(ch->twin);
				}
			}
		}
	}

	restore_flags(flags);
	return;
}