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

📄 3c509.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 2 页
字号:
/***  File:	3c509.c		Jun. 01, 2000****  Author:	Giovanni Falzoni <gfalzoni@inwind.it>****  This file contains specific implementation of the ethernet**  device driver for 3Com Etherlink III (3c509) boards.**  NOTE: The board has to be setup to disable PnP and to assign**	  I/O base and IRQ.  The driver is for ISA bus only****  $Id: 3c509.c,v 1.3 2005/08/05 19:08:43 beng Exp $*/#include "drivers.h"#include <minix/com.h>#include <net/hton.h>#include <net/gen/ether.h>#include <net/gen/eth_io.h>#include "dp.h"#if (ENABLE_3C509 == 1)#include "3c509.h"static const char *const IfNamesMsg[] = {	"10BaseT", "AUI", "unknown", "BNC",};/***  Name:	void el3_update_stats(dpeth_t *dep)**  Function:	Reads statistic counters from board**  		and updates local counters.*/static void el3_update_stats(dpeth_t * dep){  /* Disables statistics while reading and switches to the correct window */  outw_el3(dep, REG_CmdStatus, CMD_StatsDisable);  SetWindow(WNO_Statistics);  /* Reads everything, adding values to the local counters */  dep->de_stat.ets_sendErr += inb_el3(dep, REG_TxCarrierLost);	/* Reg. 00 */  dep->de_stat.ets_sendErr += inb_el3(dep, REG_TxNoCD);		/* Reg. 01 */  dep->de_stat.ets_collision += inb_el3(dep, REG_TxMultColl);	/* Reg. 02 */  dep->de_stat.ets_collision += inb_el3(dep, REG_TxSingleColl);	/* Reg. 03 */  dep->de_stat.ets_collision += inb_el3(dep, REG_TxLate);	/* Reg. 04 */  dep->de_stat.ets_recvErr += inb_el3(dep, REG_RxDiscarded);	/* Reg. 05 */  dep->de_stat.ets_packetT += inb_el3(dep, REG_TxFrames);	/* Reg. 06 */  dep->de_stat.ets_packetR += inb_el3(dep, REG_RxFrames);	/* Reg. 07 */  dep->de_stat.ets_transDef += inb_el3(dep, REG_TxDefer);	/* Reg. 08 */  dep->bytes_Rx += (unsigned) inw_el3(dep, REG_RxBytes);	/* Reg. 10 */  dep->bytes_Tx += (unsigned) inw_el3(dep, REG_TxBytes);	/* Reg. 12 */  /* Goes back to operating window and enables statistics */  SetWindow(WNO_Operating);  outw_el3(dep, REG_CmdStatus, CMD_StatsEnable);  return;}/***  Name:	void el3_getstats(dpeth_t *dep)**  Function:	Reads statistics counters from board.*/static void el3_getstats(dpeth_t * dep){  lock();  el3_update_stats(dep);  unlock();  return;}/***  Name:	void el3_dodump(dpeth_t *dep)**  Function:	Dumps counter on screen (support for console display).*/static void el3_dodump(dpeth_t * dep){  el3_getstats(dep);  return;}/***  Name:	void el3_rx_mode(dpeth_t *dep)**  Function:	Initializes receiver mode*/static void el3_rx_mode(dpeth_t * dep){  dep->de_recv_mode = FilterIndividual;  if (dep->de_flags & DEF_BROAD) dep->de_recv_mode |= FilterBroadcast;  if (dep->de_flags & DEF_MULTI) dep->de_recv_mode |= FilterMulticast;  if (dep->de_flags & DEF_PROMISC) dep->de_recv_mode |= FilterPromiscuous;  outw_el3(dep, REG_CmdStatus, CMD_RxReset);  outw_el3(dep, REG_CmdStatus, CMD_SetRxFilter | dep->de_recv_mode);  outw_el3(dep, REG_CmdStatus, CMD_RxEnable);  return;}/***  Name:	void el3_reset(dpeth_t *dep)**  Function:	Reset function specific for Etherlink hardware.*/static void el3_reset(dpeth_t * dep){  return;			/* Done */}/***  Name:	void el3_write_fifo(dpeth_t * dep, int pktsize);**  Function:	Writes a packet from user area to board.**  Remark:	Writing a word/dword at a time may result faster**  		but is a lot more complicated. Let's go simpler way.*/static void el3_write_fifo(dpeth_t * dep, int pktsize){  phys_bytes phys_user;  int bytes, ix = 0;  iovec_dat_t *iovp = &dep->de_write_iovec;  int padding = pktsize;  do {				/* Writes chuncks of packet from user buffers */	bytes = iovp->iod_iovec[ix].iov_size;	/* Size of buffer */	if (bytes > pktsize) bytes = pktsize;	/* Writes from user buffer to Tx FIFO */        outsb(dep->de_data_port, iovp->iod_proc_nr,              (void*)(iovp->iod_iovec[ix].iov_addr), bytes);	if (++ix >= IOVEC_NR) {	/* Next buffer of IO vector */		dp_next_iovec(iovp);		ix = 0;	}	/* Till packet done */  } while ((pktsize -= bytes) > 0);  while ((padding++ % sizeof(long)) != 0) outb(dep->de_data_port, 0x00);  return;}/***  Name:	void el3_recv(dpeth_t *dep, int fromint, int size)**  Function:	Receive function.  Called from interrupt handler or**  		from main to unload recv. buffer (packet to client)*/static void el3_recv(dpeth_t *dep, int fromint, int size){  buff_t *rxptr;  while ((dep->de_flags & DEF_READING) && (rxptr = dep->de_recvq_head)) {	lock();			/* Remove buffer from queue */	if (dep->de_recvq_tail == dep->de_recvq_head)		dep->de_recvq_head = dep->de_recvq_tail = NULL;	else		dep->de_recvq_head = rxptr->next;	unlock();	/* Copy buffer to user area and free it */	mem2user(dep, rxptr);	dep->de_read_s = rxptr->size;	dep->de_flags |= DEF_ACK_RECV;	dep->de_flags &= NOT(DEF_READING);	/* Return buffer to the idle pool */	free_buff(dep, rxptr);  }  return;}/***  Name:	void el3_rx_complete(dpeth_t * dep);**  Function:	Upon receiving a packet, provides status checks**  		and if packet is OK copies it to local buffer.*/static void el3_rx_complete(dpeth_t * dep){  short int RxStatus;  int pktsize;  buff_t *rxptr;  RxStatus = inw_el3(dep, REG_RxStatus);  pktsize = RxStatus & RXS_Length;	/* Mask off packet length */  if (RxStatus & RXS_Error) {	/* First checks for receiving errors */	RxStatus &= RXS_ErrType;	switch (RxStatus) {	/* Bad packet (see error type) */	    case RXS_Dribble:	    case RXS_Oversize:	    case RXS_Runt:	dep->de_stat.ets_recvErr += 1;	break;	    case RXS_Overrun:	dep->de_stat.ets_OVW += 1;	break;	    case RXS_Framing:	dep->de_stat.ets_frameAll += 1;	break;	    case RXS_CRC:	dep->de_stat.ets_CRCerr += 1;	break;	}  } else if ((rxptr = alloc_buff(dep, pktsize + sizeof(buff_t))) == NULL) {	/* Memory not available. Drop packet */	dep->de_stat.ets_fifoOver += 1;  } else {	/* Good packet.  Read it from FIFO */	insb(dep->de_data_port, SELF, rxptr->buffer, pktsize);	rxptr->next = NULL;	rxptr->size = pktsize;	lock();			/* Queue packet to receive queue */	if (dep->de_recvq_head == NULL)		dep->de_recvq_head = rxptr;	else		dep->de_recvq_tail->next = rxptr;	dep->de_recvq_tail = rxptr;	unlock();	/* Reply to pending Receive requests, if any */	el3_recv(dep, TRUE, pktsize);  }  /* Discard top packet from queue */  outw_el3(dep, REG_CmdStatus, CMD_RxDiscard);  return;}/***  Name:	void el3_send(dpeth_t *dep, int count)**  Function:	Send function.  Called from main to transit a packet or**  		from interrupt handler when Tx FIFO gets available.*/static void el3_send(dpeth_t * dep, int from_int, int count){  clock_t now;  int ix;  short int TxStatus;  getuptime(&now);  if ((dep->de_flags & DEF_XMIT_BUSY) &&      (now - dep->de_xmit_start) > 4) {	DEBUG(printf("3c509:  Transmitter timed out. Resetting ....\n");)	dep->de_stat.ets_sendErr += 1;	/* Resets and restars the transmitter */	outw_el3(dep, REG_CmdStatus, CMD_TxReset);	outw_el3(dep, REG_CmdStatus, CMD_TxEnable);	dep->de_flags &= NOT(DEF_XMIT_BUSY);  }  if (!(dep->de_flags & DEF_XMIT_BUSY)) {	/* Writes Transmitter preamble 1st Word (packet len, no ints) */	outw_el3(dep, REG_TxFIFO, count);	/* Writes Transmitter preamble 2nd Word (all zero) */	outw_el3(dep, REG_TxFIFO, 0);	/* Writes packet */	el3_write_fifo(dep, count);	getuptime(&dep->de_xmit_start);	dep->de_flags |= (DEF_XMIT_BUSY | DEF_ACK_SEND);	if (inw_el3(dep, REG_TxFree) > ETH_MAX_PACK_SIZE) {		/* Tx has enough room for a packet of maximum size */		dep->de_flags &= NOT(DEF_XMIT_BUSY | DEF_SENDING);	} else {		/* Interrupt driver when enough room is available */		outw_el3(dep, REG_CmdStatus, CMD_SetTxAvailable | ETH_MAX_PACK_SIZE);		dep->de_flags &= NOT(DEF_SENDING);	}	/* Pops Tx status stack */	for (ix = 4; --ix && (TxStatus = inb_el3(dep, REG_TxStatus)) > 0;) {		if (TxStatus & 0x38) dep->de_stat.ets_sendErr += 1;		if (TxStatus & 0x30)			outw_el3(dep, REG_CmdStatus, CMD_TxReset);		if (TxStatus & 0x3C)			outw_el3(dep, REG_CmdStatus, CMD_TxEnable);		outb_el3(dep, REG_TxStatus, 0);	}  }  return;}/***  Name:	void el3_close(dpeth_t *dep)**  Function:	Stops board and makes it ready to shut down.*/static void el3_close(dpeth_t * dep){  /* Disables statistics, Receiver and Transmitter */  outw_el3(dep, REG_CmdStatus, CMD_StatsDisable);  outw_el3(dep, REG_CmdStatus, CMD_RxDisable);  outw_el3(dep, REG_CmdStatus, CMD_TxDisable);  if (dep->de_if_port == BNC_XCVR) {

⌨️ 快捷键说明

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