📄 skfddi.c
字号:
/************************ * * mac_drv_get_desc_mem * * This function is called by the hardware dependent module. * It allocates the memory for the RxD and TxD descriptors. * * This memory must be non-cached, non-movable and non-swappable. * This memory should start at a physical page boundary. * Args * smc - A pointer to the SMT context struct. * * size - Size of memory in bytes to allocate. * Out * != 0 A pointer to the virtual address of the allocated memory. * == 0 Allocation error. * ************************/void *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size){ char *virt; PRINTK(KERN_INFO "mac_drv_get_desc_mem\n"); // Descriptor memory must be aligned on 16-byte boundary. virt = mac_drv_get_space(smc, size); size = (u_int) (16 - (((unsigned long) virt) & 15UL)); size = size % 16; PRINTK("Allocate %u bytes alignment gap ", size); PRINTK("for descriptor memory.\n"); if (!mac_drv_get_space(smc, size)) { printk("fddi: Unable to align descriptor memory.\n"); return (NULL); } return (virt + size);} // mac_drv_get_desc_mem/************************ * * mac_drv_virt2phys * * Get the physical address of a given virtual address. * Args * smc - A pointer to the SMT context struct. * * virt - A (virtual) pointer into our 'shared' memory area. * Out * Physical address of the given virtual address. * ************************/unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt){ return (smc->os.SharedMemDMA + ((char *) virt - (char *)smc->os.SharedMemAddr));} // mac_drv_virt2phys/************************ * * dma_master * * The HWM calls this function, when the driver leads through a DMA * transfer. If the OS-specific module must prepare the system hardware * for the DMA transfer, it should do it in this function. * * The hardware module calls this dma_master if it wants to send an SMT * frame. This means that the virt address passed in here is part of * the 'shared' memory area. * Args * smc - A pointer to the SMT context struct. * * virt - The virtual address of the data. * * len - The length in bytes of the data. * * flag - Indicates the transmit direction and the buffer type: * DMA_RD (0x01) system RAM ==> adapter buffer memory * DMA_WR (0x02) adapter buffer memory ==> system RAM * SMT_BUF (0x80) SMT buffer * * >> NOTE: SMT_BUF and DMA_RD are always set for PCI. << * Out * Returns the pyhsical address for the DMA transfer. * ************************/u_long dma_master(struct s_smc * smc, void *virt, int len, int flag){ return (smc->os.SharedMemDMA + ((char *) virt - (char *)smc->os.SharedMemAddr));} // dma_master/************************ * * dma_complete * * The hardware module calls this routine when it has completed a DMA * transfer. If the operating system dependent module has set up the DMA * channel via dma_master() (e.g. Windows NT or AIX) it should clean up * the DMA channel. * Args * smc - A pointer to the SMT context struct. * * descr - A pointer to a TxD or RxD, respectively. * * flag - Indicates the DMA transfer direction / SMT buffer: * DMA_RD (0x01) system RAM ==> adapter buffer memory * DMA_WR (0x02) adapter buffer memory ==> system RAM * SMT_BUF (0x80) SMT buffer (managed by HWM) * Out * Nothing. * ************************/void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, int flag){ /* For TX buffers, there are two cases. If it is an SMT transmit * buffer, there is nothing to do since we use consistent memory * for the 'shared' memory area. The other case is for normal * transmit packets given to us by the networking stack, and in * that case we cleanup the PCI DMA mapping in mac_drv_tx_complete * below. * * For RX buffers, we have to unmap dynamic PCI DMA mappings here * because the hardware module is about to potentially look at * the contents of the buffer. If we did not call the PCI DMA * unmap first, the hardware module could read inconsistent data. */ if (flag & DMA_WR) { skfddi_priv *bp = &smc->os; volatile struct s_smt_fp_rxd *r = &descr->r; /* If SKB is NULL, we used the local buffer. */ if (r->rxd_os.skb && r->rxd_os.dma_addr) { int MaxFrameSize = bp->MaxFrameSize; pci_unmap_single(&bp->pdev, r->rxd_os.dma_addr, MaxFrameSize, PCI_DMA_FROMDEVICE); r->rxd_os.dma_addr = 0; } }} // dma_complete/************************ * * mac_drv_tx_complete * * Transmit of a packet is complete. Release the tx staging buffer. * * Args * smc - A pointer to the SMT context struct. * * txd - A pointer to the last TxD which is used by the frame. * Out * Returns nothing. * ************************/void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd){ struct sk_buff *skb; PRINTK(KERN_INFO "entering mac_drv_tx_complete\n"); // Check if this TxD points to a skb if (!(skb = txd->txd_os.skb)) { PRINTK("TXD with no skb assigned.\n"); return; } txd->txd_os.skb = NULL; // release the DMA mapping pci_unmap_single(&smc->os.pdev, txd->txd_os.dma_addr, skb->len, PCI_DMA_TODEVICE); txd->txd_os.dma_addr = 0; smc->os.MacStat.gen.tx_packets++; // Count transmitted packets. smc->os.MacStat.gen.tx_bytes+=skb->len; // Count bytes // free the skb dev_kfree_skb_irq(skb); PRINTK(KERN_INFO "leaving mac_drv_tx_complete\n");} // mac_drv_tx_complete/************************ * * dump packets to logfile * ************************/#ifdef DUMPPACKETSvoid dump_data(unsigned char *Data, int length){ int i, j; unsigned char s[255], sh[10]; if (length > 64) { length = 64; } printk(KERN_INFO "---Packet start---\n"); for (i = 0, j = 0; i < length / 8; i++, j += 8) printk(KERN_INFO "%02x %02x %02x %02x %02x %02x %02x %02x\n", Data[j + 0], Data[j + 1], Data[j + 2], Data[j + 3], Data[j + 4], Data[j + 5], Data[j + 6], Data[j + 7]); strcpy(s, ""); for (i = 0; i < length % 8; i++) { sprintf(sh, "%02x ", Data[j + i]); strcat(s, sh); } printk(KERN_INFO "%s\n", s); printk(KERN_INFO "------------------\n");} // dump_data#else#define dump_data(data,len)#endif // DUMPPACKETS/************************ * * mac_drv_rx_complete * * The hardware module calls this function if an LLC frame is received * in a receive buffer. Also the SMT, NSA, and directed beacon frames * from the network will be passed to the LLC layer by this function * if passing is enabled. * * mac_drv_rx_complete forwards the frame to the LLC layer if it should * be received. It also fills the RxD ring with new receive buffers if * some can be queued. * Args * smc - A pointer to the SMT context struct. * * rxd - A pointer to the first RxD which is used by the receive frame. * * frag_count - Count of RxDs used by the received frame. * * len - Frame length. * Out * Nothing. * ************************/void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, int frag_count, int len){ skfddi_priv *bp = &smc->os; struct sk_buff *skb; unsigned char *virt, *cp; unsigned short ri; u_int RifLength; PRINTK(KERN_INFO "entering mac_drv_rx_complete (len=%d)\n", len); if (frag_count != 1) { // This is not allowed to happen. printk("fddi: Multi-fragment receive!\n"); goto RequeueRxd; // Re-use the given RXD(s). } skb = rxd->rxd_os.skb; if (!skb) { PRINTK(KERN_INFO "No skb in rxd\n"); smc->os.MacStat.gen.rx_errors++; goto RequeueRxd; } virt = skb->data; // The DMA mapping was released in dma_complete above. dump_data(skb->data, len); /* * FDDI Frame format: * +-------+-------+-------+------------+--------+------------+ * | FC[1] | DA[6] | SA[6] | RIF[0..18] | LLC[3] | Data[0..n] | * +-------+-------+-------+------------+--------+------------+ * * FC = Frame Control * DA = Destination Address * SA = Source Address * RIF = Routing Information Field * LLC = Logical Link Control */ // Remove Routing Information Field (RIF), if present. if ((virt[1 + 6] & FDDI_RII) == 0) RifLength = 0; else { int n;// goos: RIF removal has still to be tested PRINTK(KERN_INFO "RIF found\n"); // Get RIF length from Routing Control (RC) field. cp = virt + FDDI_MAC_HDR_LEN; // Point behind MAC header. ri = ntohs(*((unsigned short *) cp)); RifLength = ri & FDDI_RCF_LEN_MASK; if (len < (int) (FDDI_MAC_HDR_LEN + RifLength)) { printk("fddi: Invalid RIF.\n"); goto RequeueRxd; // Discard the frame. } virt[1 + 6] &= ~FDDI_RII; // Clear RII bit. // regions overlap virt = cp + RifLength; for (n = FDDI_MAC_HDR_LEN; n; n--) *--virt = *--cp; // adjust sbd->data pointer skb_pull(skb, RifLength); len -= RifLength; RifLength = 0; } // Count statistics. smc->os.MacStat.gen.rx_packets++; // Count indicated receive // packets. smc->os.MacStat.gen.rx_bytes+=len; // Count bytes. // virt points to header again if (virt[1] & 0x01) { // Check group (multicast) bit. smc->os.MacStat.gen.multicast++; } // deliver frame to system rxd->rxd_os.skb = NULL; skb_trim(skb, len); skb->protocol = fddi_type_trans(skb, bp->dev); skb->dev = bp->dev; /* pass up device pointer */ netif_rx(skb); bp->dev->last_rx = jiffies; HWM_RX_CHECK(smc, RX_LOW_WATERMARK); return; RequeueRxd: PRINTK(KERN_INFO "Rx: re-queue RXD.\n"); mac_drv_requeue_rxd(smc, rxd, frag_count); smc->os.MacStat.gen.rx_errors++; // Count receive packets // not indicated.} // mac_drv_rx_complete/************************ * * mac_drv_requeue_rxd * * The hardware module calls this function to request the OS-specific * module to queue the receive buffer(s) represented by the pointer * to the RxD and the frag_count into the receive queue again. This * buffer was filled with an invalid frame or an SMT frame. * Args * smc - A pointer to the SMT context struct. * * rxd - A pointer to the first RxD which is used by the receive frame. * * frag_count - Count of RxDs used by the received frame. * Out * Nothing. * ************************/void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, int frag_count){ volatile struct s_smt_fp_rxd *next_rxd; volatile struct s_smt_fp_rxd *src_rxd; struct sk_buff *skb; int MaxFrameSize; unsigned char *v_addr; dma_addr_t b_addr; if (frag_count != 1) // This is not allowed to happen. printk("fddi: Multi-fragment requeue!\n"); MaxFrameSize = smc->os.MaxFrameSize; src_rxd = rxd; for (; frag_count > 0; frag_count--) { next_rxd = src_rxd->rxd_next; rxd = HWM_GET_CURR_RXD(smc); skb = src_rxd->rxd_os.skb; if (skb == NULL) { // this should not happen PRINTK("Requeue with no skb in rxd!\n"); skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC); if (skb) { // we got a skb rxd->rxd_os.skb = 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 PRINTK("Queueing invalid buffer!\n"); rxd->rxd_os.skb = NULL; v_addr = smc->os.LocalRxBuffer; b_addr = smc->os.LocalRxBufferDMA; } } else { // we use skb from old rxd rxd->rxd_os.skb = skb; 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; } hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize, FIRST_FRAG | LAST_FRAG); src_rxd = next_rxd; }} // mac_drv_requeue_rxd/************************ * * mac_drv_fill_rxd * * The hardware module calls this function at initialization time * to fill the RxD ring with receive buffers. It is also called by * mac_drv_rx_complete if rx_free is large enough to queue some new * receive buffers into the RxD ring. mac_drv_fill_rxd queues new * receive buffers as long as enough RxDs and receive buffers are * available. * Args * smc - A pointer to the SMT context struct. * Out * Nothing. * ************************/void mac_drv_fill_rxd(struct s_smc *smc){ int MaxFrameSize; unsigned char *v_addr; unsigned long b_addr; struct sk_buff *skb; volatile struct s_smt_fp_rxd *rxd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -