static void tx_d_frame(struct hfc4s8s_l1 *l1p) { struct sk_buff *skb; u_char f1, f2; u_char *cp; long cnt; if (l1p->l1_state != 7) return; /* TX fifo */ Write_hfc8(l1p->hw, R_FIFO, (l1p->st_num * 8 + 4)); wait_busy(l1p->hw); f1 = Read_hfc8(l1p->hw, A_F1); f2 = Read_hfc8_stable(l1p->hw, A_F2); if ((f1 ^ f2) & MAX_F_CNT) return; /* fifo is still filled */ if (l1p->tx_cnt > 0) { cnt = l1p->tx_cnt; l1p->tx_cnt = 0; l1p->d_if.ifc.l1l2(&l1p->d_if.ifc, PH_DATA | CONFIRM, (void *) cnt); } if ((skb = skb_dequeue(&l1p->d_tx_queue))) { cp = skb->data; cnt = skb->len; SetRegAddr(l1p->hw, A_FIFO_DATA0); while (cnt >= 4) { SetRegAddr(l1p->hw, A_FIFO_DATA0); fWrite_hfc32(l1p->hw, *(unsigned long *) cp); cp += 4; cnt -= 4; } while (cnt--) fWrite_hfc8(l1p->hw, *cp++); l1p->tx_cnt = skb->truesize; Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1); /* increment f counter */ wait_busy(l1p->hw); dev_kfree_skb(skb); } } /* tx_d_frame */
static void tx_b_frame(struct hfc4s8s_btype *bch) { struct sk_buff *skb; struct hfc4s8s_l1 *l1 = bch->l1p; u_char *cp; int cnt, max, hdlc_num; long ack_len = 0; if (!l1->enabled || (bch->mode == L1_MODE_NULL)) return; /* TX fifo */ Write_hfc8(l1->hw, R_FIFO, (l1->st_num * 8 + ((bch->bchan == 1) ? 0 : 2))); wait_busy(l1->hw); do { if (bch->mode == L1_MODE_HDLC) { hdlc_num = Read_hfc8(l1->hw, A_F1) & MAX_F_CNT; hdlc_num -= (Read_hfc8_stable(l1->hw, A_F2) & MAX_F_CNT); if (hdlc_num < 0) hdlc_num += 16; if (hdlc_num >= 15) break; /* fifo still filled up with hdlc frames */ } else hdlc_num = 0; if (!(skb = bch->tx_skb)) { if (!(skb = skb_dequeue(&bch->tx_queue))) { l1->hw->mr.fifo_slow_timer_service[l1-> st_num] &= ~((bch->bchan == 1) ? 1 : 4); break; /* list empty */ } bch->tx_skb = skb; bch->tx_cnt = 0; } if (!hdlc_num) l1->hw->mr.fifo_slow_timer_service[l1->st_num] |= ((bch->bchan == 1) ? 1 : 4); else l1->hw->mr.fifo_slow_timer_service[l1->st_num] &= ~((bch->bchan == 1) ? 1 : 4); max = Read_hfc16_stable(l1->hw, A_Z2); max -= Read_hfc16(l1->hw, A_Z1); if (max <= 0) max += 384; max--; if (max < 16) break; /* don't write to small amounts of bytes */ cnt = skb->len - bch->tx_cnt; if (cnt > max) cnt = max; cp = skb->data + bch->tx_cnt; bch->tx_cnt += cnt; #ifndef HISAX_HFC4S8S_PCIMEM SetRegAddr(l1->hw, A_FIFO_DATA0); #endif while (cnt >= 4) { #ifdef HISAX_HFC4S8S_PCIMEM fWrite_hfc32(l1->hw, A_FIFO_DATA0, *(unsigned long *) cp); #else fWrite_hfc32(l1->hw, *(unsigned long *) cp); #endif cp += 4; cnt -= 4; } while (cnt--) #ifdef HISAX_HFC4S8S_PCIMEM fWrite_hfc8(l1->hw, A_FIFO_DATA0, *cp++); #else fWrite_hfc8(l1->hw, *cp++); #endif if (bch->tx_cnt >= skb->len) { if (bch->mode == L1_MODE_HDLC) { /* increment f counter */ Write_hfc8(l1->hw, A_INC_RES_FIFO, 1); } ack_len += skb->truesize; bch->tx_skb = NULL; bch->tx_cnt = 0; dev_kfree_skb(skb); } else /* Re-Select */ Write_hfc8(l1->hw, R_FIFO, (l1->st_num * 8 + ((bch->bchan == 1) ? 0 : 2))); wait_busy(l1->hw); } while (1); if (ack_len) bch->b_if.ifc.l1l2((struct hisax_if *) &bch->b_if, PH_DATA | CONFIRM, (void *) ack_len); } /* tx_b_frame */
static void rx_b_frame(struct hfc4s8s_btype *bch) { int z1, z2, hdlc_complete; u_char f1, f2; struct hfc4s8s_l1 *l1 = bch->l1p; struct sk_buff *skb; if (!l1->enabled || (bch->mode == L1_MODE_NULL)) return; do { /* RX Fifo */ Write_hfc8(l1->hw, R_FIFO, (l1->st_num * 8 + ((bch->bchan == 1) ? 1 : 3))); wait_busy(l1->hw); if (bch->mode == L1_MODE_HDLC) { f1 = Read_hfc8_stable(l1->hw, A_F1); f2 = Read_hfc8(l1->hw, A_F2); hdlc_complete = ((f1 ^ f2) & MAX_F_CNT); } else hdlc_complete = 0; z1 = Read_hfc16_stable(l1->hw, A_Z1); z2 = Read_hfc16(l1->hw, A_Z2); z1 = (z1 - z2); if (hdlc_complete) z1++; if (z1 < 0) z1 += 384; if (!z1) break; if (!(skb = bch->rx_skb)) { if (! (skb = dev_alloc_skb((bch->mode == L1_MODE_TRANS) ? z1 : (MAX_B_FRAME_SIZE + 3)))) { printk(KERN_ERR "HFC-4S/8S: Could not allocate B " "channel receive buffer"); return; } bch->rx_ptr = skb->data; bch->rx_skb = skb; } skb->len = (bch->rx_ptr - skb->data) + z1; /* HDLC length check */ if ((bch->mode == L1_MODE_HDLC) && ((hdlc_complete && (skb->len < 4)) || (skb->len > (MAX_B_FRAME_SIZE + 3)))) { skb->len = 0; bch->rx_ptr = skb->data; Write_hfc8(l1->hw, A_INC_RES_FIFO, 2); /* reset fifo */ wait_busy(l1->hw); return; } #ifndef HISAX_HFC4S8S_PCIMEM SetRegAddr(l1->hw, A_FIFO_DATA0); #endif while (z1 >= 4) { #ifdef HISAX_HFC4S8S_PCIMEM *((unsigned long *) bch->rx_ptr) = Read_hfc32(l1->hw, A_FIFO_DATA0); #else *((unsigned long *) bch->rx_ptr) = fRead_hfc32(l1->hw); #endif bch->rx_ptr += 4; z1 -= 4; } while (z1--) #ifdef HISAX_HFC4S8S_PCIMEM *(bch->rx_ptr++) = Read_hfc8(l1->hw, A_FIFO_DATA0); #else *(bch->rx_ptr++) = fRead_hfc8(l1->hw); #endif if (hdlc_complete) { /* increment f counter */ Write_hfc8(l1->hw, A_INC_RES_FIFO, 1); wait_busy(l1->hw); /* hdlc crc check */ bch->rx_ptr--; if (*bch->rx_ptr) { skb->len = 0; bch->rx_ptr = skb->data; continue; } skb->len -= 3; } if (hdlc_complete || (bch->mode == L1_MODE_TRANS)) { bch->rx_skb = NULL; bch->rx_ptr = NULL; bch->b_if.ifc.l1l2(&bch->b_if.ifc, PH_DATA | INDICATION, skb); } } while (1); } /* rx_b_frame */
static void rx_d_frame(struct hfc4s8s_l1 *l1p, int ech) { int z1, z2; u_char f1, f2, df; struct sk_buff *skb; u_char *cp; if (!l1p->enabled) return; do { /* E/D RX fifo */ Write_hfc8(l1p->hw, R_FIFO, (l1p->st_num * 8 + ((ech) ? 7 : 5))); wait_busy(l1p->hw); f1 = Read_hfc8_stable(l1p->hw, A_F1); f2 = Read_hfc8(l1p->hw, A_F2); df = f1 - f2; if ((f1 - f2) < 0) df = f1 - f2 + MAX_F_CNT + 1; if (!df) { return; /* no complete frame in fifo */ } z1 = Read_hfc16_stable(l1p->hw, A_Z1); z2 = Read_hfc16(l1p->hw, A_Z2); z1 = z1 - z2 + 1; if (z1 < 0) z1 += 384; if (!(skb = dev_alloc_skb(MAX_D_FRAME_SIZE))) { printk(KERN_INFO "HFC-4S/8S: Could not allocate D/E " "channel receive buffer"); Write_hfc8(l1p->hw, A_INC_RES_FIFO, 2); wait_busy(l1p->hw); return; } if (((z1 < 4) || (z1 > MAX_D_FRAME_SIZE))) { if (skb) dev_kfree_skb(skb); /* remove errornous D frame */ if (df == 1) { /* reset fifo */ Write_hfc8(l1p->hw, A_INC_RES_FIFO, 2); wait_busy(l1p->hw); return; } else { /* read errornous D frame */ #ifndef HISAX_HFC4S8S_PCIMEM SetRegAddr(l1p->hw, A_FIFO_DATA0); #endif while (z1 >= 4) { #ifdef HISAX_HFC4S8S_PCIMEM Read_hfc32(l1p->hw, A_FIFO_DATA0); #else fRead_hfc32(l1p->hw); #endif z1 -= 4; } while (z1--) #ifdef HISAX_HFC4S8S_PCIMEM Read_hfc8(l1p->hw, A_FIFO_DATA0); #else fRead_hfc8(l1p->hw); #endif Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1); wait_busy(l1p->hw); return; } } cp = skb->data; #ifndef HISAX_HFC4S8S_PCIMEM SetRegAddr(l1p->hw, A_FIFO_DATA0); #endif while (z1 >= 4) { #ifdef HISAX_HFC4S8S_PCIMEM *((unsigned long *) cp) = Read_hfc32(l1p->hw, A_FIFO_DATA0); #else *((unsigned long *) cp) = fRead_hfc32(l1p->hw); #endif cp += 4; z1 -= 4; } while (z1--) #ifdef HISAX_HFC4S8S_PCIMEM *cp++ = Read_hfc8(l1p->hw, A_FIFO_DATA0); #else *cp++ = fRead_hfc8(l1p->hw); #endif Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1); /* increment f counter */ wait_busy(l1p->hw); if (*(--cp)) { dev_kfree_skb(skb); } else { skb->len = (cp - skb->data) - 2; if (ech) l1p->d_if.ifc.l1l2(&l1p->d_if.ifc, PH_DATA_E | INDICATION, skb); else l1p->d_if.ifc.l1l2(&l1p->d_if.ifc, PH_DATA | INDICATION, skb); } } while (1); } /* rx_d_frame */
static void tx_d_frame(struct hfc4s8s_l1 *l1p) { struct sk_buff *skb; u_char f1, f2; u_char *cp; long cnt; if (l1p->l1_state != 7) return; /* */ Write_hfc8(l1p->hw, R_FIFO, (l1p->st_num * 8 + 4)); wait_busy(l1p->hw); f1 = Read_hfc8(l1p->hw, A_F1); f2 = Read_hfc8_stable(l1p->hw, A_F2); if ((f1 ^ f2) & MAX_F_CNT) return; /* */ if (l1p->tx_cnt > 0) { cnt = l1p->tx_cnt; l1p->tx_cnt = 0; l1p->d_if.ifc.l1l2(&l1p->d_if.ifc, PH_DATA | CONFIRM, (void *) cnt); } if ((skb = skb_dequeue(&l1p->d_tx_queue))) { cp = skb->data; cnt = skb->len; #ifndef HISAX_HFC4S8S_PCIMEM SetRegAddr(l1p->hw, A_FIFO_DATA0); #endif while (cnt >= 4) { #ifdef HISAX_HFC4S8S_PCIMEM fWrite_hfc32(l1p->hw, A_FIFO_DATA0, *(unsigned long *) cp); #else SetRegAddr(l1p->hw, A_FIFO_DATA0); fWrite_hfc32(l1p->hw, *(unsigned long *) cp); #endif cp += 4; cnt -= 4; } #ifdef HISAX_HFC4S8S_PCIMEM while (cnt--) fWrite_hfc8(l1p->hw, A_FIFO_DATA0, *cp++); #else while (cnt--) fWrite_hfc8(l1p->hw, *cp++); #endif l1p->tx_cnt = skb->truesize; Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1); /* */ wait_busy(l1p->hw); dev_kfree_skb(skb); } } /* */