📄 skfddi.c
字号:
PRINTK(KERN_INFO "entering mac_drv_fill_rxd\n"); // Walk through the list of free receive buffers, passing receive // buffers to the HWM as long as RXDs are available. MaxFrameSize = smc->os.MaxFrameSize; // Check if there is any RXD left. while (HWM_GET_RX_FREE(smc) > 0) { PRINTK(KERN_INFO ".\n"); rxd = HWM_GET_CURR_RXD(smc); skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC); if (skb) { // we got a skb skb_reserve(skb, 3); skb_put(skb, MaxFrameSize); v_addr = skb->data; b_addr = pci_map_single(&smc->os.pdev, v_addr, MaxFrameSize, PCI_DMA_FROMDEVICE); rxd->rxd_os.dma_addr = b_addr; } else { // no skb available, use local buffer // System has run out of buffer memory, but we want to // keep the receiver running in hope of better times. // Multiple descriptors may point to this local buffer, // so data in it must be considered invalid. PRINTK("Queueing invalid buffer!\n"); v_addr = smc->os.LocalRxBuffer; b_addr = smc->os.LocalRxBufferDMA; } rxd->rxd_os.skb = skb; // Pass receive buffer to HWM. hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize, FIRST_FRAG | LAST_FRAG); } PRINTK(KERN_INFO "leaving mac_drv_fill_rxd\n");} // mac_drv_fill_rxd/************************ * * mac_drv_clear_rxd * * The hardware module calls this function to release unused * receive buffers. * Args * smc - A pointer to the SMT context struct. * * rxd - A pointer to the first RxD which is used by the receive buffer. * * frag_count - Count of RxDs used by the receive buffer. * Out * Nothing. * ************************/void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, int frag_count){ struct sk_buff *skb; PRINTK("entering mac_drv_clear_rxd\n"); if (frag_count != 1) // This is not allowed to happen. printk("fddi: Multi-fragment clear!\n"); for (; frag_count > 0; frag_count--) { skb = rxd->rxd_os.skb; if (skb != NULL) { skfddi_priv *bp = &smc->os; int MaxFrameSize = bp->MaxFrameSize; pci_unmap_single(&bp->pdev, rxd->rxd_os.dma_addr, MaxFrameSize, PCI_DMA_FROMDEVICE); dev_kfree_skb(skb); rxd->rxd_os.skb = NULL; } rxd = rxd->rxd_next; // Next RXD. }} // mac_drv_clear_rxd/************************ * * mac_drv_rx_init * * The hardware module calls this routine when an SMT or NSA frame of the * local SMT should be delivered to the LLC layer. * * It is necessary to have this function, because there is no other way to * copy the contents of SMT MBufs into receive buffers. * * mac_drv_rx_init allocates the required target memory for this frame, * and receives the frame fragment by fragment by calling mac_drv_rx_frag. * Args * smc - A pointer to the SMT context struct. * * len - The length (in bytes) of the received frame (FC, DA, SA, Data). * * fc - The Frame Control field of the received frame. * * look_ahead - A pointer to the lookahead data buffer (may be NULL). * * la_len - The length of the lookahead data stored in the lookahead * buffer (may be zero). * Out * Always returns zero (0). * ************************/int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead, int la_len){ struct sk_buff *skb; PRINTK("entering mac_drv_rx_init(len=%d)\n", len); // "Received" a SMT or NSA frame of the local SMT. if (len != la_len || len < FDDI_MAC_HDR_LEN || !look_ahead) { PRINTK("fddi: Discard invalid local SMT frame\n"); PRINTK(" len=%d, la_len=%d, (ULONG) look_ahead=%08lXh.\n", len, la_len, (unsigned long) look_ahead); return (0); } skb = alloc_skb(len + 3, GFP_ATOMIC); if (!skb) { PRINTK("fddi: Local SMT: skb memory exhausted.\n"); return (0); } skb_reserve(skb, 3); skb_put(skb, len); memcpy(skb->data, look_ahead, len); // deliver frame to system skb->protocol = fddi_type_trans(skb, smc->os.dev); skb->dev->last_rx = jiffies; netif_rx(skb); return (0);} // mac_drv_rx_init/************************ * * smt_timer_poll * * This routine is called periodically by the SMT module to clean up the * driver. * * Return any queued frames back to the upper protocol layers if the ring * is down. * Args * smc - A pointer to the SMT context struct. * Out * Nothing. * ************************/void smt_timer_poll(struct s_smc *smc){} // smt_timer_poll/************************ * * ring_status_indication * * This function indicates a change of the ring state. * Args * smc - A pointer to the SMT context struct. * * status - The current ring status. * Out * Nothing. * ************************/void ring_status_indication(struct s_smc *smc, u_long status){ PRINTK("ring_status_indication( "); if (status & RS_RES15) PRINTK("RS_RES15 "); if (status & RS_HARDERROR) PRINTK("RS_HARDERROR "); if (status & RS_SOFTERROR) PRINTK("RS_SOFTERROR "); if (status & RS_BEACON) PRINTK("RS_BEACON "); if (status & RS_PATHTEST) PRINTK("RS_PATHTEST "); if (status & RS_SELFTEST) PRINTK("RS_SELFTEST "); if (status & RS_RES9) PRINTK("RS_RES9 "); if (status & RS_DISCONNECT) PRINTK("RS_DISCONNECT "); if (status & RS_RES7) PRINTK("RS_RES7 "); if (status & RS_DUPADDR) PRINTK("RS_DUPADDR "); if (status & RS_NORINGOP) PRINTK("RS_NORINGOP "); if (status & RS_VERSION) PRINTK("RS_VERSION "); if (status & RS_STUCKBYPASSS) PRINTK("RS_STUCKBYPASSS "); if (status & RS_EVENT) PRINTK("RS_EVENT "); if (status & RS_RINGOPCHANGE) PRINTK("RS_RINGOPCHANGE "); if (status & RS_RES0) PRINTK("RS_RES0 "); PRINTK("]\n");} // ring_status_indication/************************ * * smt_get_time * * Gets the current time from the system. * Args * None. * Out * The current time in TICKS_PER_SECOND. * * TICKS_PER_SECOND has the unit 'count of timer ticks per second'. It is * defined in "targetos.h". The definition of TICKS_PER_SECOND must comply * to the time returned by smt_get_time(). * ************************/unsigned long smt_get_time(void){ return jiffies;} // smt_get_time/************************ * * smt_stat_counter * * Status counter update (ring_op, fifo full). * Args * smc - A pointer to the SMT context struct. * * stat - = 0: A ring operational change occurred. * = 1: The FORMAC FIFO buffer is full / FIFO overflow. * Out * Nothing. * ************************/void smt_stat_counter(struct s_smc *smc, int stat){// BOOLEAN RingIsUp ; PRINTK(KERN_INFO "smt_stat_counter\n"); switch (stat) { case 0: PRINTK(KERN_INFO "Ring operational change.\n"); break; case 1: PRINTK(KERN_INFO "Receive fifo overflow.\n"); smc->os.MacStat.gen.rx_errors++; break; default: PRINTK(KERN_INFO "Unknown status (%d).\n", stat); break; }} // smt_stat_counter/************************ * * cfm_state_change * * Sets CFM state in custom statistics. * Args * smc - A pointer to the SMT context struct. * * c_state - Possible values are: * * EC0_OUT, EC1_IN, EC2_TRACE, EC3_LEAVE, EC4_PATH_TEST, * EC5_INSERT, EC6_CHECK, EC7_DEINSERT * Out * Nothing. * ************************/void cfm_state_change(struct s_smc *smc, int c_state){#ifdef DRIVERDEBUG char *s; switch (c_state) { case SC0_ISOLATED: s = "SC0_ISOLATED"; break; case SC1_WRAP_A: s = "SC1_WRAP_A"; break; case SC2_WRAP_B: s = "SC2_WRAP_B"; break; case SC4_THRU_A: s = "SC4_THRU_A"; break; case SC5_THRU_B: s = "SC5_THRU_B"; break; case SC7_WRAP_S: s = "SC7_WRAP_S"; break; case SC9_C_WRAP_A: s = "SC9_C_WRAP_A"; break; case SC10_C_WRAP_B: s = "SC10_C_WRAP_B"; break; case SC11_C_WRAP_S: s = "SC11_C_WRAP_S"; break; default: PRINTK(KERN_INFO "cfm_state_change: unknown %d\n", c_state); return; } PRINTK(KERN_INFO "cfm_state_change: %s\n", s);#endif // DRIVERDEBUG} // cfm_state_change/************************ * * ecm_state_change * * Sets ECM state in custom statistics. * Args * smc - A pointer to the SMT context struct. * * e_state - Possible values are: * * SC0_ISOLATED, SC1_WRAP_A (5), SC2_WRAP_B (6), SC4_THRU_A (12), * SC5_THRU_B (7), SC7_WRAP_S (8) * Out * Nothing. * ************************/void ecm_state_change(struct s_smc *smc, int e_state){#ifdef DRIVERDEBUG char *s; switch (e_state) { case EC0_OUT: s = "EC0_OUT"; break; case EC1_IN: s = "EC1_IN"; break; case EC2_TRACE: s = "EC2_TRACE"; break; case EC3_LEAVE: s = "EC3_LEAVE"; break; case EC4_PATH_TEST: s = "EC4_PATH_TEST"; break; case EC5_INSERT: s = "EC5_INSERT"; break; case EC6_CHECK: s = "EC6_CHECK"; break; case EC7_DEINSERT: s = "EC7_DEINSERT"; break; default: s = "unknown"; break; } PRINTK(KERN_INFO "ecm_state_change: %s\n", s);#endif //DRIVERDEBUG} // ecm_state_change/************************ * * rmt_state_change * * Sets RMT state in custom statistics. * Args * smc - A pointer to the SMT context struct. * * r_state - Possible values are: * * RM0_ISOLATED, RM1_NON_OP, RM2_RING_OP, RM3_DETECT, * RM4_NON_OP_DUP, RM5_RING_OP_DUP, RM6_DIRECTED, RM7_TRACE * Out * Nothing. * ************************/void rmt_state_change(struct s_smc *smc, int r_state){#ifdef DRIVERDEBUG char *s; switch (r_state) { case RM0_ISOLATED: s = "RM0_ISOLATED"; break; case RM1_NON_OP: s = "RM1_NON_OP - not operational"; break; case RM2_RING_OP: s = "RM2_RING_OP - ring operational"; break; case RM3_DETECT: s = "RM3_DETECT - detect dupl addresses"; break; case RM4_NON_OP_DUP: s = "RM4_NON_OP_DUP - dupl. addr detected"; break; case RM5_RING_OP_DUP: s = "RM5_RING_OP_DUP - ring oper. with dupl. addr"; break; case RM6_DIRECTED: s = "RM6_DIRECTED - sending directed beacons"; break; case RM7_TRACE: s = "RM7_TRACE - trace initiated"; break; default: s = "unknown"; break; } PRINTK(KERN_INFO "[rmt_state_change: %s]\n", s);#endif // DRIVERDEBUG} // rmt_state_change/************************ * * drv_reset_indication * * This function is called by the SMT when it has detected a severe * hardware problem. The d
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -