hisax_hfcpci.c
来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 1,647 行 · 第 1/3 页
C
1,647 行
f2 = get_b_tx_f2(bcs); if (f1 != f2) BUG(); z1 = get_b_tx_z1(bcs, f1); z2 = get_b_tx_z2(bcs, f1); cnt = z2 - z1; if (cnt <= 0) cnt += B_FIFO_SIZE; if (tx_skb->len > cnt) BUG(); if (z1 + cnt <= B_FIFO_END) { memcpy(fifo_adr + z1, tx_skb->data, cnt); } else { memcpy(fifo_adr + z1, tx_skb->data, B_FIFO_END - z1); memcpy(fifo_adr + B_FIFO_START, tx_skb->data + (B_FIFO_END - z1), cnt - (B_FIFO_END - z1)); } z1 += cnt; if (z1 >= B_FIFO_END) z1 -= B_FIFO_SIZE; mb(); set_b_tx_z1(bcs, f1, z1);}static inline voidhfcpci_fill_b_fifo(struct hfcpci_bcs *bcs){ if (!bcs->tx_skb) { DBG(DBG_WARN, "?"); return; } switch (bcs->mode) { case L1_MODE_TRANS: hfcpci_fill_b_fifo_trans(bcs); break; case L1_MODE_HDLC: hfcpci_fill_b_fifo_hdlc(bcs); break; default: DBG(DBG_WARN, "?"); }}static void hfcpci_clear_b_rx_fifo(struct hfcpci_bcs *bcs);static void hfcpci_clear_b_tx_fifo(struct hfcpci_bcs *bcs);static voidhfcpci_b_mode(struct hfcpci_bcs *bcs, int mode){ struct hfcpci_adapter *adapter = bcs->adapter; DBG(DBG_B_XMIT, "B%d mode %d --> %d", bcs->channel + 1, bcs->mode, mode); if (bcs->mode == mode) return; switch (mode) { case L1_MODE_NULL: if (bcs->channel == 0) { adapter->sctrl &= ~SCTRL_B1_ENA; adapter->sctrl_r &= ~SCTRL_B1_ENA; adapter->fifo_en &= ~HFCPCI_FIFOEN_B1; adapter->int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); } else { adapter->sctrl &= ~SCTRL_B2_ENA; adapter->sctrl_r &= ~SCTRL_B2_ENA; adapter->fifo_en &= ~HFCPCI_FIFOEN_B2; adapter->int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); } break; case L1_MODE_TRANS: case L1_MODE_HDLC: hfcpci_clear_b_rx_fifo(bcs); hfcpci_clear_b_tx_fifo(bcs); if (bcs->channel == 0) { adapter->sctrl |= SCTRL_B1_ENA; adapter->sctrl_r |= SCTRL_B1_ENA; adapter->fifo_en |= HFCPCI_FIFOEN_B1; adapter->int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); if (mode == L1_MODE_TRANS) adapter->ctmt |= 1; else adapter->ctmt &= ~1; } else { adapter->sctrl |= SCTRL_B2_ENA; adapter->sctrl_r |= SCTRL_B2_ENA; adapter->fifo_en |= HFCPCI_FIFOEN_B2; adapter->int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); if (mode == L1_MODE_TRANS) adapter->ctmt |= 2; else adapter->ctmt &= ~2; } break; } hfcpci_writeb(adapter, adapter->int_m1, HFCPCI_INT_M1); hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); hfcpci_writeb(adapter, adapter->sctrl, HFCPCI_SCTRL); hfcpci_writeb(adapter, adapter->sctrl_r, HFCPCI_SCTRL_R); hfcpci_writeb(adapter, adapter->ctmt, HFCPCI_CTMT); hfcpci_writeb(adapter, adapter->conn, HFCPCI_CONNECT); bcs->mode = mode;}// ----------------------------------------------------------------------// Layer 1 state machinestatic struct Fsm l1fsm;enum { ST_L1_F0, ST_L1_F2, ST_L1_F3, ST_L1_F4, ST_L1_F5, ST_L1_F6, ST_L1_F7, ST_L1_F8,};#define L1_STATE_COUNT (ST_L1_F8+1)static char *strL1State[] ={ "ST_L1_F0", "ST_L1_F2", "ST_L1_F3", "ST_L1_F4", "ST_L1_F5", "ST_L1_F6", "ST_L1_F7", "ST_L1_F8",};enum { EV_PH_F0, EV_PH_1, EV_PH_F2, EV_PH_F3, EV_PH_F4, EV_PH_F5, EV_PH_F6, EV_PH_F7, EV_PH_F8, EV_PH_ACTIVATE_REQ, EV_PH_DEACTIVATE_REQ, EV_TIMER3,};#define L1_EVENT_COUNT (EV_TIMER3 + 1)static char *strL1Event[] ={ "EV_PH_F0", "EV_PH_1", "EV_PH_F2", "EV_PH_F3", "EV_PH_F4", "EV_PH_F5", "EV_PH_F6", "EV_PH_F7", "EV_PH_F8", "EV_PH_ACTIVATE_REQ", "EV_PH_DEACTIVATE_REQ", "EV_TIMER3",};static void l1_ignore(struct FsmInst *fi, int event, void *arg){}static void l1_go_f3(struct FsmInst *fi, int event, void *arg){ FsmChangeState(fi, ST_L1_F3);}static void l1_go_f3_deact_ind(struct FsmInst *fi, int event, void *arg){ struct hfcpci_adapter *adapter = fi->userdata; FsmChangeState(fi, ST_L1_F3); D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);}static void l1_go_f4(struct FsmInst *fi, int event, void *arg){ FsmChangeState(fi, ST_L1_F3);}static void l1_go_f5(struct FsmInst *fi, int event, void *arg){ FsmChangeState(fi, ST_L1_F3);}static void l1_go_f6(struct FsmInst *fi, int event, void *arg){ FsmChangeState(fi, ST_L1_F6);}static void l1_go_f6_deact_ind(struct FsmInst *fi, int event, void *arg){ struct hfcpci_adapter *adapter = fi->userdata; FsmChangeState(fi, ST_L1_F6); D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);}static void l1_go_f7(struct FsmInst *fi, int event, void *arg){ FsmChangeState(fi, ST_L1_F7);}static void l1_go_f7_act_ind(struct FsmInst *fi, int event, void *arg){ struct hfcpci_adapter *adapter = fi->userdata; FsmChangeState(fi, ST_L1_F7); D_L1L2(adapter, PH_ACTIVATE | INDICATION, NULL);}static void l1_go_f8(struct FsmInst *fi, int event, void *arg){ FsmChangeState(fi, ST_L1_F8);}static void l1_go_f8_deact_ind(struct FsmInst *fi, int event, void *arg){ struct hfcpci_adapter *adapter = fi->userdata; FsmChangeState(fi, ST_L1_F8); D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL);}static void l1_act_req(struct FsmInst *fi, int event, void *arg){ struct hfcpci_adapter *adapter = fi->userdata; hfcpci_writeb(adapter, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION, HFCPCI_STATES);}static struct FsmNode L1FnList[] __initdata ={ {ST_L1_F2, EV_PH_F3, l1_go_f3}, {ST_L1_F2, EV_PH_F6, l1_go_f6}, {ST_L1_F2, EV_PH_F7, l1_go_f7_act_ind}, {ST_L1_F3, EV_PH_F3, l1_ignore}, {ST_L1_F3, EV_PH_F4, l1_go_f4}, {ST_L1_F3, EV_PH_F5, l1_go_f5}, {ST_L1_F3, EV_PH_F6, l1_go_f6}, {ST_L1_F3, EV_PH_F7, l1_go_f7_act_ind}, {ST_L1_F3, EV_PH_ACTIVATE_REQ, l1_act_req}, {ST_L1_F4, EV_PH_F7, l1_ignore}, {ST_L1_F4, EV_PH_F3, l1_go_f3}, {ST_L1_F4, EV_PH_F5, l1_go_f5}, {ST_L1_F4, EV_PH_F6, l1_go_f6}, {ST_L1_F4, EV_PH_F7, l1_go_f7}, {ST_L1_F5, EV_PH_F7, l1_ignore}, {ST_L1_F5, EV_PH_F3, l1_go_f3}, {ST_L1_F5, EV_PH_F6, l1_go_f6}, {ST_L1_F5, EV_PH_F7, l1_go_f7}, {ST_L1_F6, EV_PH_F7, l1_ignore}, {ST_L1_F6, EV_PH_F3, l1_go_f3}, {ST_L1_F6, EV_PH_F7, l1_go_f7_act_ind}, {ST_L1_F6, EV_PH_F8, l1_go_f8}, {ST_L1_F7, EV_PH_F7, l1_ignore}, {ST_L1_F7, EV_PH_F3, l1_go_f3_deact_ind}, {ST_L1_F7, EV_PH_F6, l1_go_f6_deact_ind}, {ST_L1_F7, EV_PH_F8, l1_go_f8_deact_ind}, {ST_L1_F8, EV_PH_F7, l1_ignore}, {ST_L1_F8, EV_PH_F3, l1_go_f3}, {ST_L1_F8, EV_PH_F6, l1_go_f6}, {ST_L1_F8, EV_PH_F7, l1_go_f7_act_ind},};static void l1m_debug(struct FsmInst *fi, char *fmt, ...){ va_list args; char buf[256]; va_start(args, fmt); vsprintf(buf, fmt, args); DBG(DBG_L1M, "%s", buf); va_end(args);}// ----------------------------------------------------------------------// clear FIFOsstatic voidhfcpci_clear_d_rx_fifo(struct hfcpci_adapter *adapter){ u8 fifo_state; DBG(DBG_D_RECV, ""); fifo_state = adapter->fifo_en & HFCPCI_FIFOEN_DRX; if (fifo_state) { // enabled // XXX locking adapter->fifo_en &= ~fifo_state; hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); } adapter->last_fcnt = 0; set_d_rx_z1(adapter, MAX_D_FRAMES - 1, D_FIFO_END - 1); set_d_rx_z2(adapter, MAX_D_FRAMES - 1, D_FIFO_END - 1); mb(); set_d_rx_f1(adapter, MAX_D_FRAMES - 1); set_d_rx_f2(adapter, MAX_D_FRAMES - 1); mb(); if (fifo_state) { adapter->fifo_en |= fifo_state; hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); }} static voidhfcpci_clear_b_rx_fifo(struct hfcpci_bcs *bcs){ struct hfcpci_adapter *adapter = bcs->adapter; int nr = bcs->channel; u8 fifo_state; DBG(DBG_B_RECV, ""); fifo_state = adapter->fifo_en & (nr ? HFCPCI_FIFOEN_B2RX : HFCPCI_FIFOEN_B1RX); if (fifo_state) { // enabled adapter->fifo_en &= ~fifo_state; hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); } bcs->last_fcnt = 0; set_b_rx_z1(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1); set_b_rx_z2(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1); mb(); set_b_rx_f1(bcs, MAX_B_FRAMES - 1); set_b_rx_f2(bcs, MAX_B_FRAMES - 1); mb(); if (fifo_state) { adapter->fifo_en |= fifo_state; hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); }} // XXX clear d_tx_fifo?static voidhfcpci_clear_b_tx_fifo(struct hfcpci_bcs *bcs){ struct hfcpci_adapter *adapter = bcs->adapter; int nr = bcs->channel; u8 fifo_state; fifo_state = adapter->fifo_en & (nr ? HFCPCI_FIFOEN_B2TX : HFCPCI_FIFOEN_B1TX); if (fifo_state) { // enabled adapter->fifo_en &= ~fifo_state; hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); } bcs->last_fcnt = 0; set_b_rx_z1(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1); set_b_rx_z2(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1); mb(); set_b_rx_f1(bcs, MAX_B_FRAMES - 1); set_b_rx_f2(bcs, MAX_B_FRAMES - 1); mb(); if (fifo_state) { adapter->fifo_en |= fifo_state; hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); }} // ----------------------------------------------------------------------// receive messages from upper layersstatic voidhfcpci_d_l2l1(struct hisax_if *ifc, int pr, void *arg){ struct hfcpci_adapter *adapter = ifc->priv; struct sk_buff *skb = arg; DBG(DBG_PR, "pr %#x", pr); switch (pr) { case PH_ACTIVATE | REQUEST: FsmEvent(&adapter->l1m, EV_PH_ACTIVATE_REQ, NULL); break; case PH_DEACTIVATE | REQUEST: FsmEvent(&adapter->l1m, EV_PH_DEACTIVATE_REQ, NULL); break; case PH_DATA | REQUEST: DBG(DBG_PR, "PH_DATA REQUEST len %d", skb->len); DBG_SKB(DBG_D_XMIT, skb); if (adapter->l1m.state != ST_L1_F7) { DBG(DBG_WARN, "L1 wrong state %d", adapter->l1m.state); break; } if (adapter->tx_skb) BUG(); adapter->tx_skb = skb; hfcpci_fill_d_fifo(adapter); break; }}static voidhfcpci_b_l2l1(struct hisax_if *ifc, int pr, void *arg){ struct hfcpci_bcs *bcs = ifc->priv; struct sk_buff *skb = arg; int mode; DBG(DBG_PR, "pr %#x", pr); switch (pr) { case PH_DATA | REQUEST: if (bcs->tx_skb) BUG(); bcs->tx_skb = skb; DBG_SKB(DBG_B_XMIT, skb); hfcpci_fill_b_fifo(bcs); break; case PH_ACTIVATE | REQUEST: mode = (int) arg; DBG(DBG_PR,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode); hfcpci_b_mode(bcs, mode); B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL); break; case PH_DEACTIVATE | REQUEST: DBG(DBG_PR,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1); hfcpci_b_mode(bcs, L1_MODE_NULL); B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL); break; }}// ----------------------------------------------------------------------// receive IRQstatic inline voidhfcpci_d_recv_irq(struct hfcpci_adapter *adapter){ struct sk_buff *skb; char *fifo_adr = adapter->fifo + 0x4000; char *p; int cnt, fcnt; int loop = 5; u8 f1, f2; u16 z1, z2; while (loop-- > 0) { f1 = get_d_rx_f1(adapter); f2 = get_d_rx_f2(adapter); DBG(DBG_D_RECV, "f1 %#x f2 %#x", f1, f2); fcnt = f1 - f2; if (fcnt < 0) fcnt += 16; if (!fcnt) return; if (fcnt < adapter->last_fcnt) /* overrun */ hfcpci_clear_d_rx_fifo(adapter); // XXX init last_fcnt z1 = get_d_rx_z1(adapter, f2); z2 = get_d_rx_z2(adapter, f2); DBG(DBG_D_RECV, "z1 %#x z2 %#x", z1, z2); cnt = z1 - z2; if (cnt < 0) cnt += D_FIFO_SIZE; cnt++; if (cnt < 4) { DBG(DBG_WARN, "frame too short"); goto next; } if (fifo_adr[z1] != 0) { DBG(DBG_WARN, "CRC error"); goto next; } cnt -= 3; skb = dev_alloc_skb(cnt); if (!skb) { DBG(DBG_WARN, "no mem"); goto next; } p = skb_put(skb, cnt); if (z2 + cnt <= D_FIFO_END) { memcpy(p, fifo_adr + z2, cnt); } else { memcpy(p, fifo_adr + z2, D_FIFO_END - z2); memcpy(p + (D_FIFO_END - z2), fifo_adr + D_FIFO_START, cnt - (D_FIFO_END - z2)); } DBG_SKB(DBG_D_RECV, skb); D_L1L2(adapter, PH_DATA | INDICATION, skb); next: if (++z1 >= D_FIFO_END) z1 -= D_FIFO_START; f2 = (f2 + 1) & (MAX_D_FRAMES - 1); mb(); set_d_rx_z2(adapter, f2, z1); mb(); set_d_rx_f2(adapter, f2); adapter->last_fcnt = fcnt - 1; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?