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

📄 farsync.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		spin_unlock_irqrestore(&card->card_lock, flags);		schedule_timeout(1);		spin_lock_irqsave(&card->card_lock, flags);		if (++safety > 2000) {			printk_err("Mailbox safety timeout\n");			break;		}		mbval = FST_RDW(card, portMailbox[port->index][0]);	}	if (safety > 0) {		dbg(DBG_CMD, "Mailbox clear after %d jiffies\n", safety);	}	if (mbval == NAK) {		dbg(DBG_CMD, "issue_cmd: previous command was NAK'd\n");	}	FST_WRW(card, portMailbox[port->index][0], cmd);	if (cmd == ABORTTX || cmd == STARTPORT) {		port->txpos = 0;		port->txipos = 0;		port->start = 0;	}	spin_unlock_irqrestore(&card->card_lock, flags);}/*      Port output signals control */static inline voidfst_op_raise(struct fst_port_info *port, unsigned int outputs){	outputs |= FST_RDL(port->card, v24OpSts[port->index]);	FST_WRL(port->card, v24OpSts[port->index], outputs);	if (port->run)		fst_issue_cmd(port, SETV24O);}static inline voidfst_op_lower(struct fst_port_info *port, unsigned int outputs){	outputs = ~outputs & FST_RDL(port->card, v24OpSts[port->index]);	FST_WRL(port->card, v24OpSts[port->index], outputs);	if (port->run)		fst_issue_cmd(port, SETV24O);}/* *      Setup port Rx buffers */static voidfst_rx_config(struct fst_port_info *port){	int i;	int pi;	unsigned int offset;	unsigned long flags;	struct fst_card_info *card;	pi = port->index;	card = port->card;	spin_lock_irqsave(&card->card_lock, flags);	for (i = 0; i < NUM_RX_BUFFER; i++) {		offset = BUF_OFFSET(rxBuffer[pi][i][0]);		FST_WRW(card, rxDescrRing[pi][i].ladr, (u16) offset);		FST_WRB(card, rxDescrRing[pi][i].hadr, (u8) (offset >> 16));		FST_WRW(card, rxDescrRing[pi][i].bcnt, cnv_bcnt(LEN_RX_BUFFER));		FST_WRW(card, rxDescrRing[pi][i].mcnt, LEN_RX_BUFFER);		FST_WRB(card, rxDescrRing[pi][i].bits, DMA_OWN);	}	port->rxpos = 0;	spin_unlock_irqrestore(&card->card_lock, flags);}/* *      Setup port Tx buffers */static voidfst_tx_config(struct fst_port_info *port){	int i;	int pi;	unsigned int offset;	unsigned long flags;	struct fst_card_info *card;	pi = port->index;	card = port->card;	spin_lock_irqsave(&card->card_lock, flags);	for (i = 0; i < NUM_TX_BUFFER; i++) {		offset = BUF_OFFSET(txBuffer[pi][i][0]);		FST_WRW(card, txDescrRing[pi][i].ladr, (u16) offset);		FST_WRB(card, txDescrRing[pi][i].hadr, (u8) (offset >> 16));		FST_WRW(card, txDescrRing[pi][i].bcnt, 0);		FST_WRB(card, txDescrRing[pi][i].bits, 0);	}	port->txpos = 0;	port->txipos = 0;	port->start = 0;	spin_unlock_irqrestore(&card->card_lock, flags);}/*      TE1 Alarm change interrupt event */static voidfst_intr_te1_alarm(struct fst_card_info *card, struct fst_port_info *port){	u8 los;	u8 rra;	u8 ais;	los = FST_RDB(card, suStatus.lossOfSignal);	rra = FST_RDB(card, suStatus.receiveRemoteAlarm);	ais = FST_RDB(card, suStatus.alarmIndicationSignal);	if (los) {		/*		 * Lost the link		 */		if (netif_carrier_ok(port_to_dev(port))) {			dbg(DBG_INTR, "Net carrier off\n");			netif_carrier_off(port_to_dev(port));		}	} else {		/*		 * Link available		 */		if (!netif_carrier_ok(port_to_dev(port))) {			dbg(DBG_INTR, "Net carrier on\n");			netif_carrier_on(port_to_dev(port));		}	}	if (los)		dbg(DBG_INTR, "Assert LOS Alarm\n");	else		dbg(DBG_INTR, "De-assert LOS Alarm\n");	if (rra)		dbg(DBG_INTR, "Assert RRA Alarm\n");	else		dbg(DBG_INTR, "De-assert RRA Alarm\n");	if (ais)		dbg(DBG_INTR, "Assert AIS Alarm\n");	else		dbg(DBG_INTR, "De-assert AIS Alarm\n");}/*      Control signal change interrupt event */static voidfst_intr_ctlchg(struct fst_card_info *card, struct fst_port_info *port){	int signals;	signals = FST_RDL(card, v24DebouncedSts[port->index]);	if (signals & (((port->hwif == X21) || (port->hwif == X21D))		       ? IPSTS_INDICATE : IPSTS_DCD)) {		if (!netif_carrier_ok(port_to_dev(port))) {			dbg(DBG_INTR, "DCD active\n");			netif_carrier_on(port_to_dev(port));		}	} else {		if (netif_carrier_ok(port_to_dev(port))) {			dbg(DBG_INTR, "DCD lost\n");			netif_carrier_off(port_to_dev(port));		}	}}/*      Log Rx Errors */static voidfst_log_rx_error(struct fst_card_info *card, struct fst_port_info *port,		 unsigned char dmabits, int rxp, unsigned short len){	struct net_device *dev = port_to_dev(port);	struct net_device_stats *stats = hdlc_stats(dev);	/* 	 * Increment the appropriate error counter	 */	stats->rx_errors++;	if (dmabits & RX_OFLO) {		stats->rx_fifo_errors++;		dbg(DBG_ASS, "Rx fifo error on card %d port %d buffer %d\n",		    card->card_no, port->index, rxp);	}	if (dmabits & RX_CRC) {		stats->rx_crc_errors++;		dbg(DBG_ASS, "Rx crc error on card %d port %d\n",		    card->card_no, port->index);	}	if (dmabits & RX_FRAM) {		stats->rx_frame_errors++;		dbg(DBG_ASS, "Rx frame error on card %d port %d\n",		    card->card_no, port->index);	}	if (dmabits == (RX_STP | RX_ENP)) {		stats->rx_length_errors++;		dbg(DBG_ASS, "Rx length error (%d) on card %d port %d\n",		    len, card->card_no, port->index);	}}/*      Rx Error Recovery */static voidfst_recover_rx_error(struct fst_card_info *card, struct fst_port_info *port,		     unsigned char dmabits, int rxp, unsigned short len){	int i;	int pi;	pi = port->index;	/* 	 * Discard buffer descriptors until we see the start of the	 * next frame.  Note that for long frames this could be in	 * a subsequent interrupt. 	 */	i = 0;	while ((dmabits & (DMA_OWN | RX_STP)) == 0) {		FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN);		rxp = (rxp+1) % NUM_RX_BUFFER;		if (++i > NUM_RX_BUFFER) {			dbg(DBG_ASS, "intr_rx: Discarding more bufs"			    " than we have\n");			break;		}		dmabits = FST_RDB(card, rxDescrRing[pi][rxp].bits);		dbg(DBG_ASS, "DMA Bits of next buffer was %x\n", dmabits);	}	dbg(DBG_ASS, "There were %d subsequent buffers in error\n", i);	/* Discard the terminal buffer */	if (!(dmabits & DMA_OWN)) {		FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN);		rxp = (rxp+1) % NUM_RX_BUFFER;	}	port->rxpos = rxp;	return;}/*      Rx complete interrupt */static voidfst_intr_rx(struct fst_card_info *card, struct fst_port_info *port){	unsigned char dmabits;	int pi;	int rxp;	int rx_status;	unsigned short len;	struct sk_buff *skb;	struct net_device *dev = port_to_dev(port);	struct net_device_stats *stats = hdlc_stats(dev);	/* Check we have a buffer to process */	pi = port->index;	rxp = port->rxpos;	dmabits = FST_RDB(card, rxDescrRing[pi][rxp].bits);	if (dmabits & DMA_OWN) {		dbg(DBG_RX | DBG_INTR, "intr_rx: No buffer port %d pos %d\n",		    pi, rxp);		return;	}	if (card->dmarx_in_progress) {		return;	}	/* Get buffer length */	len = FST_RDW(card, rxDescrRing[pi][rxp].mcnt);	/* Discard the CRC */	len -= 2;	if (len == 0) {		/*		 * This seems to happen on the TE1 interface sometimes		 * so throw the frame away and log the event.		 */		printk_err("Frame received with 0 length. Card %d Port %d\n",			   card->card_no, port->index);		/* Return descriptor to card */		FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN);		rxp = (rxp+1) % NUM_RX_BUFFER;		port->rxpos = rxp;		return;	}	/* Check buffer length and for other errors. We insist on one packet	 * in one buffer. This simplifies things greatly and since we've	 * allocated 8K it shouldn't be a real world limitation	 */	dbg(DBG_RX, "intr_rx: %d,%d: flags %x len %d\n", pi, rxp, dmabits, len);	if (dmabits != (RX_STP | RX_ENP) || len > LEN_RX_BUFFER - 2) {		fst_log_rx_error(card, port, dmabits, rxp, len);		fst_recover_rx_error(card, port, dmabits, rxp, len);		return;	}	/* Allocate SKB */	if ((skb = dev_alloc_skb(len)) == NULL) {		dbg(DBG_RX, "intr_rx: can't allocate buffer\n");		stats->rx_dropped++;		/* Return descriptor to card */		FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN);		rxp = (rxp+1) % NUM_RX_BUFFER;		port->rxpos = rxp;		return;	}	/*	 * We know the length we need to receive, len.	 * It's not worth using the DMA for reads of less than	 * FST_MIN_DMA_LEN	 */	if ((len < FST_MIN_DMA_LEN) || (card->family == FST_FAMILY_TXP)) {		memcpy_fromio(skb_put(skb, len),			      card->mem + BUF_OFFSET(rxBuffer[pi][rxp][0]),			      len);		/* Reset buffer descriptor */		FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN);		/* Update stats */		stats->rx_packets++;		stats->rx_bytes += len;		/* Push upstream */		dbg(DBG_RX, "Pushing frame up the stack\n");		skb->mac.raw = skb->data;		skb->dev = dev;		if (port->mode == FST_RAW) {			/*			 * Mark it for our own raw sockets interface			 */			skb->protocol = htons(ETH_P_CUST);			skb->pkt_type = PACKET_HOST;		} else {			skb->protocol = hdlc_type_trans(skb, skb->dev);		}		rx_status = netif_rx(skb);		fst_process_rx_status(rx_status, port_to_dev(port)->name);		if (rx_status == NET_RX_DROP) {			stats->rx_dropped++;		}		dev->last_rx = jiffies;	} else {		card->dma_skb_rx = skb;		card->dma_port_rx = port;		card->dma_len_rx = len;		card->dma_rxpos = rxp;		fst_rx_dma(card, (char *) card->rx_dma_handle_card,			   (char *) BUF_OFFSET(rxBuffer[pi][rxp][0]), len);	}	if (rxp != port->rxpos) {		dbg(DBG_ASS, "About to increment rxpos by more than 1\n");		dbg(DBG_ASS, "rxp = %d rxpos = %d\n", rxp, port->rxpos);	}	rxp = (rxp+1) % NUM_RX_BUFFER;	port->rxpos = rxp;}/* *      The bottom halfs to the ISR * */static voiddo_bottom_half_tx(struct fst_card_info *card){	struct fst_port_info *port;	int pi;	int txq_length;	struct sk_buff *skb;	unsigned long flags;	struct net_device *dev;	struct net_device_stats *stats;	/*	 *  Find a free buffer for the transmit	 *  Step through each port on this card	 */	dbg(DBG_TX, "do_bottom_half_tx\n");	for (pi = 0, port = card->ports; pi < card->nports; pi++, port++) {		if (!port->run)			continue;                dev = port_to_dev(port);                stats = hdlc_stats(dev);		while (!		       (FST_RDB(card, txDescrRing[pi][port->txpos].bits) &			DMA_OWN)                       && !(card->dmatx_in_progress)) {			/*			 * There doesn't seem to be a txdone event per-se			 * We seem to have to deduce it, by checking the DMA_OWN			 * bit on the next buffer we think we can use			 */			spin_lock_irqsave(&card->card_lock, flags);			if ((txq_length = port->txqe - port->txqs) < 0) {				/*				 * This is the case where one has wrapped and the				 * maths gives us a negative number				 */				txq_length = txq_length + FST_TXQ_DEPTH;			}			spin_unlock_irqrestore(&card->card_lock, flags);			if (txq_length > 0) {				/*				 * There is something to send				 */				spin_lock_irqsave(&card->card_lock, flags);				skb = port->txq[port->txqs];				port->txqs++;				if (port->txqs == FST_TXQ_DEPTH) {					port->txqs = 0;				}				spin_unlock_irqrestore(&card->card_lock, flags);				/*				 * copy the data and set the required indicators on the				 * card.				 */				FST_WRW(card, txDescrRing[pi][port->txpos].bcnt,					cnv_bcnt(skb->len));				if ((skb->len < FST_MIN_DMA_LEN)				    || (card->family == FST_FAMILY_TXP)) {					/* Enqueue the packet with normal io */					memcpy_toio(card->mem +						    BUF_OFFSET(txBuffer[pi]							       [port->								txpos][0]),						    skb->data, skb->len);					FST_WRB(card,						txDescrRing[pi][port->txpos].						bits,						DMA_OWN | TX_STP | TX_ENP);					stats->tx_packets++;					stats->tx_bytes += skb->len;					dev->trans_start = jiffies;				} else {					/* Or do it through dma */					memcpy(card->tx_dma_handle_host,					       skb->data, skb->len);					card->dma_port_tx = port;					card->dma_len_tx = skb->len;					card->dma_txpos = port->txpos;					fst_tx_dma(card,						   (char *) card->						   tx_dma_handle_card,						   (char *)						   BUF_OFFSET(txBuffer[pi]							      [port->txpos][0]),						   skb->len);				}				if (++port->txpos >= NUM_TX_BUFFER)					port->txpos = 0;				/*				 * If we have flow control on, can we now release it?				 */				if (port->start) {					if (txq_length < fst_txq_low) {						netif_wake_queue(port_to_dev								 (port));						port->start = 0;					}				}				dev_kfree_skb(skb);			} else {				/*				 * Nothing to send so break out of the while loop				 */				break;			}		}

⌨️ 快捷键说明

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