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

📄 skfddi.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
					PRINTK(" %02x %02x %02x ",					       dmi->dmi_addr[0],					       dmi->dmi_addr[1],					       dmi->dmi_addr[2]);					PRINTK("%02x %02x %02x\n",					       dmi->dmi_addr[3],					       dmi->dmi_addr[4],					       dmi->dmi_addr[5]);					dmi = dmi->next;				}	// for			} else {	// more MC addresses than HW supports				mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);				PRINTK(KERN_INFO "ENABLE ALL MC ADDRESSES\n");			}		} else {	// no MC addresses			PRINTK(KERN_INFO "DISABLE ALL MC ADDRESSES\n");		}		/* Update adapter filters */		mac_update_multicast(smc);	}	return;}				// skfp_ctl_set_multicast_list_wo_lock/* * =========================== * = skfp_ctl_set_mac_address = * =========================== *    * Overview: *   set new mac address on adapter and update dev_addr field in device table. *   * Returns: *   None *        * Arguments: *   dev  - pointer to device information *   addr - pointer to sockaddr structure containing unicast address to set * * Assumptions: *   The address pointed to by addr->sa_data is a valid unicast *   address and is presented in canonical (LSB) format. */static int skfp_ctl_set_mac_address(struct net_device *dev, void *addr){	struct s_smc *smc = netdev_priv(dev);	struct sockaddr *p_sockaddr = (struct sockaddr *) addr;	skfddi_priv *bp = &smc->os;	unsigned long Flags;	memcpy(dev->dev_addr, p_sockaddr->sa_data, FDDI_K_ALEN);	spin_lock_irqsave(&bp->DriverLock, Flags);	ResetAdapter(smc);	spin_unlock_irqrestore(&bp->DriverLock, Flags);	return (0);		/* always return zero */}				// skfp_ctl_set_mac_address/* * ============== * = skfp_ioctl = * ============== *    * Overview: * * Perform IOCTL call functions here. Some are privileged operations and the * effective uid is checked in those cases. *   * Returns: *   status value *   0 - success *   other - failure *        * Arguments: *   dev  - pointer to device information *   rq - pointer to ioctl request structure *   cmd - ? * */static int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	struct s_smc *smc = netdev_priv(dev);	skfddi_priv *lp = &smc->os;	struct s_skfp_ioctl ioc;	int status = 0;	if (copy_from_user(&ioc, rq->ifr_data, sizeof(struct s_skfp_ioctl)))		return -EFAULT;	switch (ioc.cmd) {	case SKFP_GET_STATS:	/* Get the driver statistics */		ioc.len = sizeof(lp->MacStat);		status = copy_to_user(ioc.data, skfp_ctl_get_stats(dev), ioc.len)				? -EFAULT : 0;		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);		status = -EOPNOTSUPP;	}			// 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){	struct s_smc *smc = netdev_priv(dev);	skfddi_priv *bp = &smc->os;	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.gen.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(netdev_priv(dev));	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 = &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 = &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

⌨️ 快捷键说明

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