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

📄 kernelnetworkdriver_amdpcnet.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "kernelBusPCI.h"#include "kernelLock.h"#include "kernelNetwork.h"#include "kernelProcessorX86.h"#include "kernelLog.h"#include "kernelMalloc.h"#include "kernelMemoryManager.h"#include "kernelPageManager.h"#include "kernelParameters.h"#include "kernelMiscFunctions.h"#include "kernelInterrupt.h"#include "kernelError.h"#include "kernelNetworkDriver_AmdPCNetRegisters.h"#include <errno.h>#include <stddef.h>/*#define NET_TRANSMIT_BUFFER_NUMBER 4#define NET_TRANSMIT_BUFFER_SIZE 1536#define NET_TOTAL_TRANSMIT_BUFFER_SIZE NET_TRANSMIT_BUFFER_NUMBER * NET_TRANSMIT_BUFFER_SIZE #define NET_RECEIVE_BUFFER_NUMBER 4#define NET_RECEIVE_BUFFER_SIZE 1536#define NET_TOTAL_RECEIVE_BUFFER_SIZE NET_RECEIVE_BUFFER_NUMBER * NET_RECEIVE_BUFFER_SIZE*/#define PCNET32_LOG_TX_BUFFERS 2#define PCNET32_LOG_RX_BUFFERS 2#define TX_RING_SIZE		(1 << (PCNET32_LOG_TX_BUFFERS))#define TX_RING_MOD_MASK	(TX_RING_SIZE - 1)#define TX_RING_LEN_BITS	((PCNET32_LOG_TX_BUFFERS) << 12)#define RX_RING_SIZE		(1 << (PCNET32_LOG_RX_BUFFERS))#define RX_RING_MOD_MASK	(RX_RING_SIZE - 1)#define RX_RING_LEN_BITS	((PCNET32_LOG_RX_BUFFERS) << 4)#define NET_TRANSMIT_BUFFER_NUMBER TX_RING_SIZE#define NET_TRANSMIT_BUFFER_SIZE 1536#define NET_TOTAL_TRANSMIT_BUFFER_SIZE NET_TRANSMIT_BUFFER_NUMBER * NET_TRANSMIT_BUFFER_SIZE #define NET_RECEIVE_BUFFER_NUMBER RX_RING_SIZE#define NET_RECEIVE_BUFFER_SIZE 1536#define NET_TOTAL_RECEIVE_BUFFER_SIZE NET_RECEIVE_BUFFER_NUMBER * NET_RECEIVE_BUFFER_SIZE#define NET_DEBUGstatic int kernelNetworkDriverInitialize_AmdPCNet(kernelNetworkInterface * nic);static int kernelNetworkDriverDestroy_AmdPCNet(kernelNetworkInterface * nic);static int kernelNetworkDriverHandleInterrupt_AmdPCNet(void * data);static int kernelNetworkDriverTransmit_AmdPCNet(kernelNetworkInterface * nic, void * data, int length);//one element of the transmit ringtypedef struct{	unsigned long bufferBaseAddress;		signed short bufferLength;		signed short statusBits;		unsigned long miscBits;		unsigned long reserved;} amdPCNetTransmitDescriptor;//One element of the receive ringtypedef struct {	//the physical address of the buffer this descriptor points to	unsigned long bufferBaseAddress;	//the two's complement of the buffer length	signed short bufferLength;	//some bits to set extra options	signed short statusBits;	//length of the received message	unsigned long messageLength;		unsigned long reserved;} amdPCNetReceiveDescriptor;typedef struct{	struct	{		unsigned short mode;		unsigned char receiveBufferLength;		unsigned char transmitBufferLength;		unsigned char physicalAddress[6];		unsigned short reserved;		unsigned long filter[2];		unsigned long receiveRingPointer;		unsigned long transmitRingPointer;	} initBlock;		amdPCNetTransmitDescriptor transmitDescriptor[NET_TRANSMIT_BUFFER_NUMBER];		amdPCNetReceiveDescriptor receiveDescriptor[NET_RECEIVE_BUFFER_NUMBER];		unsigned char transmitBuffer[NET_TRANSMIT_BUFFER_NUMBER][NET_TRANSMIT_BUFFER_SIZE];		unsigned char receiveBuffer[NET_RECEIVE_BUFFER_NUMBER][NET_RECEIVE_BUFFER_SIZE];		int currentTransmitBuffer;		int currentReceiveBuffer;		void * physicalAddress;	//physical address of this structure	} amdPCNetPrivate;//The PCNet chip can be accessed in two ways: first in word mode, and second in doubleword mode. In DW mode only the lower 2 byte contain data, but we use only word mode, which is mandytorily supported by all devicesstatic inline void amdPCNetReadControlStatusRegister(unsigned long baseIOAddress, int registerIndex, unsigned short * result){	kernelProcessorOutPort16(baseIOAddress + 0x12, registerIndex);	kernelProcessorInPort16(baseIOAddress + 0x10, *result);}static inline void amdPCNetWriteControlStatusRegister(unsigned long baseIOAddress, int registerIndex, unsigned short value){	kernelProcessorOutPort16(baseIOAddress + 0x12, registerIndex);	kernelProcessorOutPort16(baseIOAddress + 0x10, value);}static void amdPCNetReadBusControlRegister(unsigned long baseIOAddress, int registerIndex, unsigned short * result){	kernelProcessorOutPort16(baseIOAddress + 0x12, registerIndex);	kernelProcessorInPort16(baseIOAddress + 0x16, *result);}static inline void amdPCNetWriteBusControlRegister(unsigned long baseIOAddress, int registerIndex, unsigned short value){	kernelProcessorOutPort16(baseIOAddress + 0x12, registerIndex);	kernelProcessorOutPort16(baseIOAddress + 0x16, value);}static void amdPCNetReadRegisterAddressPort(unsigned long baseIOAddress, unsigned short * result){	kernelProcessorInPort16(baseIOAddress + 0x12, *result);}static void amdPCNetWriteRegisterAddressPort(unsigned long baseIOAddress, unsigned short value){	kernelProcessorOutPort16(baseIOAddress + 0x12, value);}static inline void amdPCNetReset(unsigned long baseIOAddress) {	unsigned short tmp;		//first 32bit-reset	kernelProcessorOutPort16(baseIOAddress + 0x18, 0x0000);		kernelProcessorInPort16(baseIOAddress + 0x18, tmp);	//then 16bit-reset so chip is afterwards reset and in 16bit mode	kernelProcessorOutPort16(baseIOAddress + 0x14, 0x0000);		kernelProcessorInPort16(baseIOAddress + 0x14, tmp);}#if defined(NET_DEBUG)static void debugDumpRegisters(kernelNetworkInterface * nic){	unsigned short tmp;	unsigned short tmp2;	unsigned short tmp3;	//the CSR0 register	amdPCNetReadControlStatusRegister(nic->portIOAddress, 0, &tmp);	kernelLog("%s->CSR0: %04x", nic->name, tmp); 	//the CSR3 register	amdPCNetReadControlStatusRegister(nic->portIOAddress, 3, &tmp);	kernelLog("%s->CSR3: %04x", nic->name, tmp); 	//the CSR4 register	amdPCNetReadControlStatusRegister(nic->portIOAddress, 4, &tmp);	kernelLog("%s->CSR4: %04x", nic->name, tmp);	//the CSR5 register	amdPCNetReadControlStatusRegister(nic->portIOAddress, 5, &tmp);	kernelLog("%s->CSR5: %04x", nic->name, tmp);  	//the CSR6 register	amdPCNetReadControlStatusRegister(nic->portIOAddress, 6, &tmp);	kernelLog("%s->CSR6: %04x", nic->name, tmp); 	//the CSR6 register	//tell chip to stop first or we cannot read address	amdPCNetReadControlStatusRegister(nic->portIOAddress, 0, &tmp);	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 0, tmp | CSR0_STOP);	amdPCNetReadControlStatusRegister(nic->portIOAddress, 12, &tmp);	amdPCNetReadControlStatusRegister(nic->portIOAddress, 13, &tmp2);	amdPCNetReadControlStatusRegister(nic->portIOAddress, 14, &tmp3);	kernelLog("%s->physicalAddress: %02x:%02x:%02x:%02x:%02x:%02x", nic->name, tmp & 0xff, tmp >> 8, tmp2 & 0xff, tmp2 >> 8, tmp3 & 0xff, tmp3 >> 8); 	amdPCNetReadControlStatusRegister(nic->portIOAddress, 0, &tmp);	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 0, tmp | CSR0_START);	}#endif/** *	Initializes the chip with its basic data. *	Sets up mode, etc and gives the NIC an init block from which it reads the configuration values. */	static void amdPCNetInitChip(kernelNetworkInterface * nic){	amdPCNetPrivate * privateVirtual = (amdPCNetPrivate *) nic->privateData;	amdPCNetPrivate * privatePhysical = (amdPCNetPrivate *) privateVirtual->physicalAddress;	unsigned short tmp;	int i;		//Setup the init block//	privateVirtual->initBlock.mode = 0x0000;//	privateVirtual->initBlock.receiveBufferLength = 2; //real length = 2^2 = 4//	privateVirtual->initBlock.transmitBufferLength = 2; //real length = 2^2 = 4 /*	privateVirtual->initBlock.physicalAddress[0] = 0x09;	privateVirtual->initBlock.physicalAddress[1] = 0x18;	privateVirtual->initBlock.physicalAddress[2] = 0x27;	privateVirtual->initBlock.physicalAddress[3] = 0x36;	privateVirtual->initBlock.physicalAddress[4] = 0x45;	privateVirtual->initBlock.physicalAddress[5] = 0x54;	i = 0;*//*	for(i = 0;  i< 6; i++)		privateVirtual->initBlock.physicalAddress[i] = nic->myAddress[i];	privateVirtual->initBlock.reserved = 0x0000;	privateVirtual->initBlock.filter[0] = 0x00000000;	privateVirtual->initBlock.filter[1] = 0x00000000;	privateVirtual->initBlock.receiveRingPointer = (unsigned long) &privatePhysical->receiveDescriptor[0];	privateVirtual->initBlock.transmitRingPointer = (unsigned long) &privatePhysical->transmitDescriptor[0];		if((unsigned long) &privatePhysical->initBlock.mode & 0x00000003)		kernelError(kernel_error, "%s: physical address of init block is not 32bit-aligned", nic->name); *///	if(privateVirtual->initBlock.receiveRingPointer & 0x00000003)//		kernelError(kernel_error, "%s: physical address of RX descriptor is not 32bit-aligned", nic->name);	//	if(privateVirtual->initBlock.transmitRingPointer & 0x00000003)//		kernelError(kernel_error, "%s: physical address of TX descriptor is not 32bit-aligned", nic->name);		//reset the chip	amdPCNetReset(nic->portIOAddress);		//stop the chip	amdPCNetWriteControlStatusRegister(nic->portIOAddress, CONTROLLER_STATUS, CSR0_STOP);	//wait a short while to give the chip time to reset	kernelProcessorDelay();	//Tell the chip we want 32bit mode (this method is different from the one described in the specs)	amdPCNetReadControlStatusRegister(nic->portIOAddress, SOFTWARE_MODE, &tmp);	amdPCNetWriteControlStatusRegister(nic->portIOAddress, SOFTWARE_MODE, tmp | CSR58_SOFTWARE_32BIT);	//Set some options	amdPCNetReadControlStatusRegister(nic->portIOAddress, TEST_FEATURES_CONTROL, &tmp);	amdPCNetWriteControlStatusRegister(nic->portIOAddress, TEST_FEATURES_CONTROL, tmp | CSR4_NO_TRANSMIT_INTERRUPT | CSR4_AUTO_PAD_TRANSMIT | CSR4_DISABLE_TX_POLLING | CSR4_DMAPLUS);	//Emable burst read and write	amdPCNetReadBusControlRegister(nic->portIOAddress, BURST_CONTROL, &tmp);	amdPCNetWriteBusControlRegister(nic->portIOAddress, BURST_CONTROL, tmp | BCR18_BURST_READ_ENABLED | BCR18_BURST_WRITE_ENABLED);/*	//write address of init block to chip	amdPCNetWriteControlStatusRegister(nic->portIOAddress, INIT_BLOCK_ADDRESS_LOW, (unsigned long) &privatePhysical->initBlock & 0xffff);	amdPCNetWriteControlStatusRegister(nic->portIOAddress, INIT_BLOCK_ADDRESS_HIGH, ((unsigned long) &privatePhysical->initBlock >> 16) & 0xffff); */	//set mode 0 (default)	amdPCNetWriteControlStatusRegister(nic->portIOAddress, MODE,  0x0000);	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 76, -NET_RECEIVE_BUFFER_NUMBER & 0xffff);	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 78, -NET_TRANSMIT_BUFFER_NUMBER & 0xffff);	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 24, (unsigned long) &privatePhysical->receiveDescriptor[0] & 0xffff);	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 25, ((unsigned long) &privatePhysical->receiveDescriptor[0] >> 16) & 0xffff);	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 30, (unsigned long) &privatePhysical->transmitDescriptor[0] & 0xffff);//	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 31, ((unsigned long) &privatePhysical->transmitDescriptor[0] >> 16) & 0xffff);	for(i = 0; i < 4; i++)		amdPCNetWriteControlStatusRegister(nic->portIOAddress, i + 8, 0x0000);	for(i = 0; i < 3; i++)		amdPCNetWriteControlStatusRegister(nic->portIOAddress, i + 12, nic->myAddress[i * 2] | (nic->myAddress[i * 2 + 1] << 8));//	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 25, ((unsigned long) &privatePhysical->receiveDescriptor[0] >> 16) & 0xffff);	//start chip	amdPCNetWriteControlStatusRegister(nic->portIOAddress, CONTROLLER_STATUS, CSR0_START | CSR0_INTERRUPT_ENABLE);	//Get link status	amdPCNetReadBusControlRegister(nic->portIOAddress, LINK_STATUS, (unsigned short *) &nic->linkStatus);#if defined(NET_DEBUG)	kernelLog("%s: Link status is %x", nic->name, nic->linkStatus);#endif  }/**	Function for the NIC driver. Opens the device and initializes all associated data structures.	Can be called several times, previously used memory is freed.*/static int kernelNetworkDriverInitialize_AmdPCNet(kernelNetworkInterface * nic){			int status = 0;	int i;	unsigned short tmp;	amdPCNetPrivate * privateVirtual;	amdPCNetPrivate * privatePhysical;		//Check parameters	if(!nic)	{#if defined(NET_DEBUG)		kernelLog("kernelNetworkDriverInitialize_AmdPCNet: nic == NULL\n");#endif		return (status = ERR_NULLPARAMETER);	}		if(nic->portIOAddress == 0xffffffff)	{#if defined(NET_DEBUG)				//no valid port address		kernelError(kernel_error, "kernelNetworkDriverInitialize_AmdPCNet: Device port is not valid.\n");#endif				return (status = ERR_IO);	} 		if(nic->privateData)	{#if defined(NET_DEBUG)				kernelLog("kernelNetworkDriverInitialize_AmdPCNet: nic->privateData is not NULL. trying to free it.\n");#endif					kernelFree(nic->privateData);	}		if(nic->privateData)	{#if defined(NET_DEBUG)				kernelLog("kernelNetworkDriverInitialize_AmdPCNet: nic->privateData is not NULL. trying to free it.\n");#endif				kernelPageUnmap(KERNELPROCID, nic->privateData, sizeof(amdPCNetPrivate));		kernelFree(nic->privateData);	}		//reset the NIC's chip	amdPCNetReset(nic->portIOAddress);		//read the physical adress from PROM	for(i = 0; i < 6; i++)		kernelProcessorInPort8(nic->portIOAddress + i, nic->myAddress[i]);			//Get chip version and name	amdPCNetReadControlStatusRegister(nic->portIOAddress, 89, &tmp);	nic->version = (unsigned long) tmp << 16;	amdPCNetReadControlStatusRegister(nic->portIOAddress, 88, &tmp);	nic->version = ((nic->version | tmp) >> 12) & 0xffff;	switch(nic->version)	{		case 0x2420:			nic->name = "PCnet/PCI 79C970"; // PCI 			break;		case 0x2621:			nic->name = "PCnet/PCI II 79C970A"; // PCI 			break;		case 0x2623:			nic->name = "PCnet/FAST 79C971"; // PCI 			break;		case 0x2624:			nic->name = "PCnet/FAST+ 79C972"; // PCI 			break;		case 0x2625:			nic->name = "PCnet/FAST III 79C973"; // PCI 			break;		case 0x2626:			nic->name = "PCnet/Home 79C978"; // PCI 			break;		case 0x2627:			nic->name = "PCnet/FAST III 79C975"; // PCI 			break;		case 0x2628:			nic->name = "PCnet/PRO 79C976";			break;	}#if defined(NET_DEBUG)	kernelLog("%s: My address is: %x:%x:%x:%x:%x:%x\n", nic->name, nic->myAddress[0], nic->myAddress[1], nic->myAddress[2], nic->myAddress[3], nic->myAddress[4], nic->myAddress[5]);

⌨️ 快捷键说明

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