📄 if_cs.c
字号:
/* if_cs.c - Crystal Semiconductor CS8900 network interface driver *//* * Copyright 1996 Crystal Semiconductor Corp. * Copyright 1984-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01c,23feb98,vin converted to BSD44 driver, merge from SENS01b,13jun97,map doc updates [SPR# 8138]01a,16dec96,hdn adapted.*//*DESCRIPTIONThis module implements a driver for a Crystal Semiconductor CS8900 Ethernetcontroller chip.The CS8900 is a single chip Ethernet controller with a direct ISA businterface which can operate in either memory space or I/O space. It alsosupports a direct interface to a host DMA controller to transfer receiveframes to host memory. The device has a 4K RAM which is used for transmit,and receive buffers; a serial EEPROM interface; and both 10BASE-T/AUI portsupport.This driver is capable of supporting both memory mode and I/O mode operationsof the chip. When configured for memory mode, the intenal RAM of the chip ismapped to a contiguous 4K address block, providing the CPU direct access tothe internal registers and frame buffers. When configured for I/O mode, theinternal registers are accessible through eight contiguous, 16-bit I/O ports.The driver also supports an interface to an EEPROM containing deviceconfiguration.While the DMA slave mode is supported by the device for receive frametransfers, this driver does not enable DMA.This network interface driver does not support output hook routines,because to do so requires that an image of the transmit packet be built inmemory before the image is copied to the CS8900 chip. It is much moreefficient to copy the image directly from the mbuf chain to the CS8900 chip.However, this network interface driver does support input hook routines.CONFIGURATIONThe defined I/O address and IRQ in config.h must match the one storedin EEPROM by the vendor's DOS utility program.The I/O Address parameter is the only required csAttach() parameter. If theCS8900 chip has a EEPROM attached, then the I/O Address parameter, passed tothe csAttach() routine, must match the I/O address programmed into the EEPROM.If the CS8900 chip does not have a EEPROM attached, then the I/O Addressparameter must be 0x300.The Interrupt Level parameter must have one of the following values: 0 - Get interrupt level from EEPROM 5 - IRQ 5 10 - IRQ 10 11 - IRQ 11 12 - IRQ 12If the Interrupt Vector parameter is zero, then the network interface driverderives the interrupt vector from the interrupt level if possible. It ispossible to derive the interrupt vector in an IBM PC compatible system. Thisparameter is present for systems which are not IBM PC compatible.The Memory Address parameter specifies the base address of the CS8900 chip'smemory buffer (PacketPage). If the Memory Address parameter is not zero, thenthe CS8900 chip operates in memory mode at the specified address. If theMemory Address parameter is zero, then the CS8900 chip operates in the modespecified by the EEPROM or the Configuration Flags parameter.The Media Type parameter must have one of the following values:.CS 0 - Get media type from EEPROM 1 - AUI (Thick Cable) 2 - BNC 10Base2 (Thin Cable) 3 - RJ45 10BaseT (Twisted Pair).CEThe Configuration Flags parameter is usually passed to the csAttach() routineas zero and the Configuration Flags information is retrieved from the EEPROM.The bits in the Configuration Flags parameter are usually specified by ahardware engineer and not by the end user. However, if the CS8900 chip doesnot have a EEPROM attached, then this information must be passed as a parameterto the csAttach() routine. The Configuration Flags are:.CS 0x8000 - CS_CFGFLG_NOT_EEPROM Don't get Config. Flags from the EEPROM 0x0001 - CS_CFGFLG_MEM_MODE Use memory mode to access the chip 0x0002 - CS_CFGFLG_USE_SA Use system addr to qualify MEMCS16 signal 0x0004 - CS_CFGFLG_IOCHRDY Use IO Channel Ready signal to slow access 0x0008 - CS_CFGFLG_DCDC_POL The DC/DC conv. enable pin is active high 0x0010 - CS_CFGFLG_FDX 10BaseT is full duplex.CEIf configuration flag information is passed to the csAttach() routine, then theCS_CFGFLG_NOT_EEPROM flag should be set. This ensures that the ConfigurationFlags parameter is not zero, even if all specified flags are zero.If the Memory Address parameter is not zero and the Configuration Flagsparameter is zero, then the CS8900 network interface driver implicitly setsthe CS_CFGFLG_MEM_MODE flag and the CS8900 chip operates in memory mode.However, if the Configuration Flags parameter is not zero, then the CS8900chip operates in memory mode only if the CS_CFGFLG_MEM_MODE flag is explicitlyset. If the Configuration Flags parameter in not zero and theCS_CFGFLG_MEM_MODE flag is not set, then the CS8900 chip operates in I/O mode.The Ethernet Address parameter is usually passed to the csAttach() routine aszero and the Ethernet address is retrieved from the EEPROM. The Ethernetaddress (also called hardware address and individual address) is usuallysupplied by the adapter manufacturer and is stored in the EEPROM. However, ifthe CS8900 chip does not have a EEPROM attached, then the Ethernet address mustbe passed as a parameter to the csAttach() routine.The Ethernet Address parameter, passed to the csAttach() routine, contains theaddress of a NULL terminated string. The string consists of 6 hexadecimalnumbers separated by colon characters. Each hexadecimal number is in the range00 - FF. An example of this string is:.CS "00:24:20:10:FF:2A".CEBOARD LAYOUTThis device is soft-configured. No jumpering diagram is required.EXTERNAL INTERFACEThe only user-callable routines are csAttach():.iP csAttach() 14publishes the `cs' interface and initializes the driver and device..LPThe network interface driver includes a show routine, called csShow(), whichdisplays driver configuration and statistics information. To invoke the showroutine, type at the shell prompt:.CS -> csShow.CETo reset the statistics to zero, type at the shell prompt:.CS -> csShow 0, 1.CEAnother routine that you may find useful is:.CS -> ifShow "cs0".CEEXTERNAL ROUTINESFor debugging purposes, this driver calls logMsg() to print error and debugginginformation. This will cause the logLib library to be linked with any imagecontaining this driver.This driver needs the following macros defined for proper execution. Eachhas a default definition that assumes a PC386/PC486 system and BSP.The macro CS_IN_BYTE(reg,pAddr) reads one byte from the I/O address 'reg',placing the result at address 'pAddr'. There is no status result from thisoperation, we assume the operation completes normally, or a bus exceptionwill occur. By default, this macro assumes there is a BSP routine sysInByte()to perform the I/O operation.The macro CS_IN_WORD(reg,pAddr) read a short word (2 bytes) from the I/Oaddress 'reg', storing the result at address 'pAddr'. We assume thiscompletes normally, or causes a bus exception. The default declarationassumes a BSP routine sysInWord() to perform the operation.The macro CS_OUT_WORD(reg,data) writes a short word value 'data' at theI/O address 'reg'. The default declaration assumes a BSP routine sysOutWord().The macro CS_INT_ENABLE(level, pResult) is used to enable the interruptlevel passed as an argument to csAttach. The default definition call theBSP routine sysIntEnablePIC(level). The STATUS return value from the actual routine is stored at 'pResult' for the driver to examine.The macro CS_INT_CONNECT(ivec,rtn,arg,pResult) macro is used to connectthe driver interrupt routine to the vector provided as an argument to csAttach (after translaction by INUM_TO_IVEC). The default definitioncalls the cpu architecture routine intConnect().The macro CS_IRQ0_VECTOR(pAddr) is used to fetch the base vector for theinterrupt level mechanism. If the int vector argument to csAttach is zero,then the driver will compute a vector number by adding the interrupt levelto the value returned by this macro. If the user supplies a non-zerointerrupt vector number, then this macro is not used. The default definitionof this macro fetches the base vector number from a global valuecalled 'sysVectorIRQ0'.The macro CS_MSEC_DELAY(msec) is used to delay execution for a specifiednumber of milliseconds. The default definition uses taskDelay to suspendtask for some number of clock ticks. The resolution of the system clockis usually around 16 milliseconds (msecs), which is fairly coarse.*/#include "vxWorks.h"#include "sysLib.h"#include "intLib.h"#include "logLib.h"#include "netLib.h"#include "etherLib.h"#include "stdio.h"#include "iv.h"#include "ioctl.h"#include "taskLib.h"#include "net/if_subr.h"#include "drv/netif/if_cs.h"/* defines */#define MAXUNITS 2 /* Maximum number of CS8900 chips */#ifndef CS_IN_BYTE /* read one byte from I/O space */#define CS_IN_BYTE(reg,pAddr) \ (*(pAddr) = sysInByte(reg))#endif /*CS_IN_BYTE*/#ifndef CS_IN_WORD /* read a short (16bits) from I/O */#define CS_IN_WORD(reg,pAddr) \ (*(pAddr) = sysInWord(reg))#endif /*CS_IN_WORD*/#ifndef CS_OUT_WORD /* write a short to I/O space */#define CS_OUT_WORD(reg,data) \ (sysOutWord((reg),(data)))#endif /*CS_OUT_WORD*/#ifndef CS_INT_ENABLE /* enable interrupt level */#define CS_INT_ENABLE(level,pResult) \ (*pResult = sysIntEnablePIC(level))#endif /*CS_INT_ENABLE*/#ifndef CS_INT_CONNECT /* connect routine to intr. vector */#define CS_INT_CONNECT(ivec,rtn,arg,pResult) \ (*pResult = intConnect(ivec,rtn,arg))#endif /*CS_INT_CONNECT*/#ifndef CS_IRQ0_VECTOR /* get vector for intr. level 0 */#define CS_IRQ0_VECTOR(pAddr) \ { \ IMPORT UINT sysVectorIRQ0; \ *pAddr = sysVectorIRQ0; \ }#endif /*CS_IRQ0_VECTOR*/#ifndef CS_MSEC_DELAY /* delay for (x) milliseconds */#define CS_MSEC_DELAY(msec) \ taskDelay ((((msec) * sysClkRateGet()) + sysClkRateGet() - 1)/ 1000);#endif /*CS_MSEC_DELAY*//* typedefs */typedef struct ether_header ETH_HDR; /* globals *//* locals */LOCAL CS_SOFTC cs_softc[MAXUNITS]; /* Instance global variables *//* prototypes */#if defined(__STDC__) || defined(__cplusplus) STATUS csAttach (int unit, int ioAddr, int intVector, int intLevel, int memAddr, int mediaType, int configFlags, char *pEnetAddr); void csShow (int unit, BOOL zap);LOCAL STATUS csInit (int unit);LOCAL void csReset (int unit);LOCAL void csIntr (int unit);LOCAL int csIoctl (struct ifnet *pIf, int command, char *pData);#ifdef BSD43_DRIVERLOCAL void csStartOutput (int unit);LOCAL int csOutput (struct ifnet *pIf, struct mbuf *pMbufChain, SOCKADDR *pDst);#elseLOCAL void csStartOutput (CS_SOFTC *pCs);#endifLOCAL STATUS csChipVerify (CS_SOFTC *pCs);LOCAL STATUS csChipReset (CS_SOFTC *pCs);LOCAL void csChipInit (CS_SOFTC *pCs);LOCAL void csIntrBuffer (CS_SOFTC *pCs, USHORT buffEvent);LOCAL void csIntrTx (CS_SOFTC *pCs, USHORT txEvent);LOCAL void csIntrRx (CS_SOFTC *pCs, USHORT rxEvent);LOCAL void csTxFrameCopy (CS_SOFTC *pCs, struct mbuf *pMbufChain);LOCAL void csRxFrameCopy (CS_SOFTC *pCs, CS_RXBUF *pRxBuff);LOCAL void csRxProcess (CS_SOFTC *pCs, CS_RXBUF *pRxBuff);LOCAL STATUS csRxBuffInit (CS_SOFTC *pCs);LOCAL CS_RXBUF *csRxBuffAlloc (CS_SOFTC *pCs);LOCAL void csRxBuffFree (CS_SOFTC *pCs, CS_RXBUF *pRxBuff);LOCAL USHORT csPacketPageR (CS_SOFTC *pCs, USHORT offset);LOCAL void csPacketPageW (CS_SOFTC *pCs, USHORT offset, USHORT value);LOCAL void csError (CS_SOFTC *pCs, char *pString);LOCAL STATUS csParmsGet (CS_SOFTC *pCs);LOCAL STATUS csParmsValidate (CS_SOFTC *pCs);LOCAL STATUS csEnetAddrGet (CS_SOFTC *pCs, char *pEnetAddr);LOCAL STATUS csEepromRead (CS_SOFTC *pCs, USHORT offset, USHORT *pValue);LOCAL char *csHexWord (char *pChar, USHORT *pWord);LOCAL char *csHexByte (char *pChar, UCHAR *pByte);#else /* Not ANSI C or C++ */ STATUS csAttach (); void csShow ();LOCAL STATUS csInit ();LOCAL void csReset ();LOCAL void csStartOutput ();LOCAL void csIntr ();LOCAL int csIoctl ();LOCAL int csOutput ();LOCAL STATUS csChipVerify ();LOCAL STATUS csChipReset ();LOCAL void csChipInit ();LOCAL void csIntrBuffer ();LOCAL void csIntrTx ();LOCAL void csIntrRx ();LOCAL void csTxFrameCopy ();LOCAL void csRxFrameCopy ();LOCAL void csRxProcess ();LOCAL STATUS csRxBuffInit ();LOCAL CS_RXBUF *csRxBuffAlloc ();LOCAL void csRxBuffFree ();LOCAL USHORT csPacketPageR ();LOCAL void csPacketPageW ();LOCAL void csError ();LOCAL STATUS csParmsGet ();LOCAL STATUS csParmsValidate ();LOCAL STATUS csEnetAddrGet ();LOCAL STATUS csEepromRead ();LOCAL char *csHexWord ();LOCAL char *csHexByte ();#endif /* defined(__STDC__) || defined(__cplusplus) *//********************************************************************************* csAttach - publish the `cs' network interface and initialize the driver.** This routine is a major entry point to this network interface driver and is* called only once per operating system reboot by the operating system startup* code. This routine is called before the csInit() routine.** This routine takes passed-in configuration parameters and parameters from* the EEPROM and fills in the instance global variables in the cs_softc* structure. These variables are later used by the csChipInit() routine.** This routine connects the interrupt handler, csIntr(), to the specified* interrupt vector, initializes the 8259 PIC and resets the CS8900 chip.** Finally, this routine calls the ether_attach() routine, to fill in the ifnet* structure and attach this network interface driver to the system. The* driver's main entry points (csInit(), csIoctl(), csOutput(), csReset()) are* made visable to the protocol stack.** Refer to "man if_cs" for detailed description of the configuration flags.** RETURNS: OK or ERROR.*/STATUS csAttach ( int unit, /* unit number */ int ioAddr, /* base IO address */ int intVector, /* interrupt vector, or zero */ int intLevel, /* interrupt level */ int memAddr, /* base memory address */ int mediaType, /* 0: Autodetect 1: AUI 2: BNC 3: RJ45 */ int configFlags, /* configuration flag */ char *pEnetAddr /* ethernet address */ ) { FAST CS_SOFTC *pCs = &cs_softc[unit]; STATUS result; if (unit >= MAXUNITS) { printf ("\ncs%d - Invalid unit number (%d)\n", unit, unit); return (ERROR); } /* Save the passed-in parameters */ pCs->ioAddr = ioAddr; pCs->intLevel = intLevel; pCs->intVector = intVector; pCs->pPacketPage = (USHORT *)memAddr; pCs->mediaType = mediaType; pCs->configFlags = configFlags; /* Start out in IO mode */ pCs->inMemoryMode = FALSE; /* Set counters to zero */ pCs->rxDepth = 0; pCs->maxRxDepth = 0; pCs->maxTxDepth = 0; pCs->loanCount = 0; /* Allocate the receive frame buffers */ if (csRxBuffInit (pCs) == ERROR) { printf ("\ncs%d - Can not allocate receive buffers\n", unit); return (ERROR); } /* Verify that it is the correct chip */ if (csChipVerify (pCs) == ERROR) return (ERROR); /* Get parameters, which were not specified, from the EEPROM */ if (csParmsGet (pCs) == ERROR) return (ERROR); /* Verify that parameters are valid */ if (csParmsValidate (pCs) == ERROR) return (ERROR); /* Get and store the Ethernet address */ if (csEnetAddrGet (pCs,pEnetAddr) == ERROR) return (ERROR); /* If memory address was specified but configuration flags were not */ if (memAddr!=0 && configFlags==0) pCs->configFlags |= CS_CFGFLG_MEM_MODE; /* Implictly set memory mode */ /* If the interrupt vector was not specified then derive it */ if (intVector == 0) { CS_IRQ0_VECTOR(&intVector); pCs->intVector = intVector + pCs->intLevel; } /* Setup the interrupt handler and the IDT table entry */ CS_INT_CONNECT (INUM_TO_IVEC (pCs->intVector), csIntr, unit, &result); if (result == ERROR) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -