⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skfddi.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	skfddi_priv *lp = PRIV(dev);	struct s_skfp_ioctl ioc;	int status = 0;	copy_from_user(&ioc, rq->ifr_data, sizeof(struct s_skfp_ioctl));	switch (ioc.cmd) {	case SKFP_GET_STATS:	/* Get the driver statistics */		ioc.len = sizeof(lp->MacStat);		copy_to_user(ioc.data, skfp_ctl_get_stats(dev), ioc.len);		break;	case SKFP_CLR_STATS:	/* Zero out the driver statistics */		if (!capable(CAP_NET_ADMIN)) {			memset(&lp->MacStat, 0, sizeof(lp->MacStat));		} else {			status = -EPERM;		}		break;	default:		printk("ioctl for %s: unknow cmd: %04x\n", dev->name, ioc.cmd);	}			// switch	return status;}				// skfp_ioctl/* * ===================== * = skfp_send_pkt     = * ===================== *    * Overview: *   Queues a packet for transmission and try to transmit it. *   * Returns: *   Condition code *        * Arguments: *   skb - pointer to sk_buff to queue for transmission *   dev - pointer to device information * * Functional Description: *   Here we assume that an incoming skb transmit request *   is contained in a single physically contiguous buffer *   in which the virtual address of the start of packet *   (skb->data) can be converted to a physical address *   by using pci_map_single(). * *   We have an internal queue for packets we can not send  *   immediately. Packets in this queue can be given to the  *   adapter if transmit buffers are freed. * *   We can't free the skb until after it's been DMA'd *   out by the adapter, so we'll keep it in the driver and *   return it in mac_drv_tx_complete. * * Return Codes: *   0 - driver has queued and/or sent packet *       1 - caller should requeue the sk_buff for later transmission * * Assumptions: *   The entire packet is stored in one physically *   contiguous buffer which is not cached and whose *   32-bit physical address can be determined. * *   It's vital that this routine is NOT reentered for the *   same board and that the OS is not in another section of *   code (eg. skfp_interrupt) for the same board on a *   different thread. * * Side Effects: *   None */static int skfp_send_pkt(struct sk_buff *skb, struct net_device *dev){	skfddi_priv *bp = PRIV(dev);	PRINTK(KERN_INFO "skfp_send_pkt\n");	/*	 * Verify that incoming transmit request is OK	 *	 * Note: The packet size check is consistent with other	 *               Linux device drivers, although the correct packet	 *               size should be verified before calling the	 *               transmit routine.	 */	if (!(skb->len >= FDDI_K_LLC_ZLEN && skb->len <= FDDI_K_LLC_LEN)) {		bp->MacStat.tx_errors++;	/* bump error counter */		// dequeue packets from xmt queue and send them		netif_start_queue(dev);		dev_kfree_skb(skb);		return (0);	/* return "success" */	}	if (bp->QueueSkb == 0) {	// return with tbusy set: queue full		netif_stop_queue(dev);		return 1;	}	bp->QueueSkb--;	skb_queue_tail(&bp->SendSkbQueue, skb);	send_queued_packets((struct s_smc *) dev->priv);	if (bp->QueueSkb == 0) {		netif_stop_queue(dev);	}	dev->trans_start = jiffies;	return 0;}				// skfp_send_pkt/* * ======================= * = send_queued_packets = * ======================= *    * Overview: *   Send packets from the driver queue as long as there are some and *   transmit resources are available. *   * Returns: *   None *        * Arguments: *   smc - pointer to smc (adapter) structure * * Functional Description: *   Take a packet from queue if there is any. If not, then we are done. *   Check if there are resources to send the packet. If not, requeue it *   and exit.  *   Set packet descriptor flags and give packet to adapter. *   Check if any send resources can be freed (we do not use the *   transmit complete interrupt). */static void send_queued_packets(struct s_smc *smc){	skfddi_priv *bp = (skfddi_priv *) & smc->os;	struct sk_buff *skb;	unsigned char fc;	int queue;	struct s_smt_fp_txd *txd;	// Current TxD.	dma_addr_t dma_address;	unsigned long Flags;	int frame_status;	// HWM tx frame status.	PRINTK(KERN_INFO "send queued packets\n");	for (;;) {		// send first buffer from queue		skb = skb_dequeue(&bp->SendSkbQueue);		if (!skb) {			PRINTK(KERN_INFO "queue empty\n");			return;		}		// queue empty !		spin_lock_irqsave(&bp->DriverLock, Flags);		fc = skb->data[0];		queue = (fc & FC_SYNC_BIT) ? QUEUE_S : QUEUE_A0;#ifdef ESS		// Check if the frame may/must be sent as a synchronous frame.		if ((fc & ~(FC_SYNC_BIT | FC_LLC_PRIOR)) == FC_ASYNC_LLC) {			// It's an LLC frame.			if (!smc->ess.sync_bw_available)				fc &= ~FC_SYNC_BIT; // No bandwidth available.			else {	// Bandwidth is available.				if (smc->mib.fddiESSSynchTxMode) {					// Send as sync. frame.					fc |= FC_SYNC_BIT;				}			}		}#endif				// ESS		frame_status = hwm_tx_init(smc, fc, 1, skb->len, queue);		if ((frame_status & (LOC_TX | LAN_TX)) == 0) {			// Unable to send the frame.			if ((frame_status & RING_DOWN) != 0) {				// Ring is down.				PRINTK("Tx attempt while ring down.\n");			} else if ((frame_status & OUT_OF_TXD) != 0) {				PRINTK("%s: out of TXDs.\n", bp->dev->name);			} else {				PRINTK("%s: out of transmit resources",					bp->dev->name);			}			// Note: We will retry the operation as soon as			// transmit resources become available.			skb_queue_head(&bp->SendSkbQueue, skb);			spin_unlock_irqrestore(&bp->DriverLock, Flags);			return;	// Packet has been queued.		}		// if (unable to send frame)		bp->QueueSkb++;	// one packet less in local queue		// source address in packet ?		CheckSourceAddress(skb->data, smc->hw.fddi_canon_addr.a);		txd = (struct s_smt_fp_txd *) HWM_GET_CURR_TXD(smc, queue);		dma_address = pci_map_single(&bp->pdev, skb->data,					     skb->len, PCI_DMA_TODEVICE);		if (frame_status & LAN_TX) {			txd->txd_os.skb = skb;			// save skb			txd->txd_os.dma_addr = dma_address;	// save dma mapping		}		hwm_tx_frag(smc, skb->data, dma_address, skb->len,                      frame_status | FIRST_FRAG | LAST_FRAG | EN_IRQ_EOF);		if (!(frame_status & LAN_TX)) {		// local only frame			pci_unmap_single(&bp->pdev, dma_address,					 skb->len, PCI_DMA_TODEVICE);			dev_kfree_skb_irq(skb);		}		spin_unlock_irqrestore(&bp->DriverLock, Flags);	}			// for	return;			// never reached}				// send_queued_packets/************************ *  * CheckSourceAddress * * Verify if the source address is set. Insert it if necessary. * ************************/void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr){	unsigned char SRBit;	if ((((unsigned long) frame[1 + 6]) & ~0x01) != 0) // source routing bit		return;	if ((unsigned short) frame[1 + 10] != 0)		return;	SRBit = frame[1 + 6] & 0x01;	memcpy(&frame[1 + 6], hw_addr, 6);	frame[8] |= SRBit;}				// CheckSourceAddress/************************ * *	ResetAdapter * *	Reset the adapter and bring it back to operational mode. * Args *	smc - A pointer to the SMT context struct. * Out *	Nothing. * ************************/static void ResetAdapter(struct s_smc *smc){	PRINTK(KERN_INFO "[fddi: ResetAdapter]\n");	// Stop the adapter.	card_stop(smc);		// Stop all activity.	// Clear the transmit and receive descriptor queues.	mac_drv_clear_tx_queue(smc);	mac_drv_clear_rx_queue(smc);	// Restart the adapter.	smt_reset_defaults(smc, 1);	// Initialize the SMT module.	init_smt(smc, (smc->os.dev)->dev_addr);	// Initialize the hardware.	smt_online(smc, 1);	// Insert into the ring again.	STI_FBI();	// Restore original receive mode (multicasts, promiscuous, etc.).	skfp_ctl_set_multicast_list_wo_lock(smc->os.dev);}				// ResetAdapter//--------------- functions called by hardware module ----------------/************************ * *	llc_restart_tx * *	The hardware driver calls this routine when the transmit complete *	interrupt bits (end of frame) for the synchronous or asynchronous *	queue is set. * * NOTE The hardware driver calls this function also if no packets are queued. *	The routine must be able to handle this case. * Args *	smc - A pointer to the SMT context struct. * Out *	Nothing. * ************************/void llc_restart_tx(struct s_smc *smc){	skfddi_priv *bp = (skfddi_priv *) & smc->os;	PRINTK(KERN_INFO "[llc_restart_tx]\n");	// Try to send queued packets	spin_unlock(&bp->DriverLock);	send_queued_packets(smc);	spin_lock(&bp->DriverLock);	netif_start_queue(bp->dev);// system may send again if it was blocked}				// llc_restart_tx/************************ * *	mac_drv_get_space * *	The hardware module calls this function to allocate the memory *	for the SMT MBufs if the define MB_OUTSIDE_SMC is specified. * 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_space(struct s_smc *smc, unsigned int size){	void *virt;	PRINTK(KERN_INFO "mac_drv_get_space (%d bytes), ", size);	virt = (void *) (smc->os.SharedMemAddr + smc->os.SharedMemHeap);	if ((smc->os.SharedMemHeap + size) > smc->os.SharedMemSize) {		printk("Unexpected SMT memory size requested: %d\n", size);		return (NULL);	}	smc->os.SharedMemHeap += size;	// Move heap pointer.	PRINTK(KERN_INFO "mac_drv_get_space end\n");	PRINTK(KERN_INFO "virt addr: %lx\n", (ulong) virt);	PRINTK(KERN_INFO "bus  addr: %lx\n", (ulong)	       (smc->os.SharedMemDMA +		((char *) virt - (char *)smc->os.SharedMemAddr)));	return (virt);}				// mac_drv_get_space/************************ * *	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 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -