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

📄 kernelnetworkdriver_amdpcnet.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 2 页
字号:
#endif		//Allocate physical space for the NIC's private structure	privatePhysical = (amdPCNetPrivate *) kernelMemoryGetPhysical(sizeof(amdPCNetPrivate), MEMORY_PAGE_SIZE, "AMD PCNet buffers");	if(!privatePhysical)	{		kernelError(kernel_error, "kernelNetworkDriverInitialize_AmdPCNet: Can't allocate memory for buffers");		((kernelNetworkDriver * ) nic->driver)->destroy(nic);		return(status = ERR_MEMORY);	}		//map the physical address from above to a kernel virtual address	status = kernelPageMapToFree(KERNELPROCID, privatePhysical, (void **) &privateVirtual, sizeof(amdPCNetPrivate));	if(status < 0)	{		kernelError(kernel_error, "kernelNetworkDriverInitialize_AmdPCNet: Can't map physical address of buffers to virtual address");		((kernelNetworkDriver * ) nic->driver)->destroy(nic);		return(status);	}		//Save pointers in the NIC structure	privateVirtual->physicalAddress = (void *) privatePhysical;	nic->privateData = (void *) privateVirtual;	//Clear the memory	kernelMemClear(privateVirtual, sizeof(amdPCNetPrivate));	//Hook the card's interrupt BEFORE card can issue any interrupts	kernelInterruptHookShared(nic->irq, kernelNetworkDriverHandleInterrupt_AmdPCNet, (void *) nic);	//Set up some registers, setup and load init block and start card	amdPCNetInitChip(nic);		//	debugInterruptDo(10);	/*	 	//Get and save the MAC address and the broadcast address	for(i = 0; i < 3; i++)	{		amdPCNetReadControlStatusRegister(nic->portIOAddress, i + 0x0c, &tmp);		 		nic->myAddress[i * 2] = (unsigned char) (tmp & 0xff);				nic->myAddress[i * 2 + 1] = (unsigned char) ((tmp >> 8) & 0xff);				nic->broadcastAddress[i * 2] = 0xff;				nic->broadcastAddress[i * 2 + 1] = 0xff;	}		kernelLog("My MAC address: %x:%x:%x:%x:%x:%x\n", nic->myAddress[0], nic->myAddress[1], nic->myAddress[2], nic->myAddress[3], nic->myAddress[4], nic->myAddress[5]); 		//Get chip version	amdPCNetReadControlStatusRegister(nic->portIOAddress, 89, &tmp);	chipVersion = (unsigned long) tmp << 16;	amdPCNetReadControlStatusRegister(nic->portIOAddress, 88, &tmp);	chipVersion |= tmp;	chipVersion = (chipVersion >> 12) & 0xffff;		switch(chipVersion)	{		case 0x2420:			chipName = "PCnet/PCI 79C970"; // PCI 			break;		case 0x2430:			chipName = "PCnet/32 79C965"; // 486/VL bus 			break;		case 0x2621:			chipName = "PCnet/PCI II 79C970A"; // PCI 			break;		case 0x2623:			chipName = "PCnet/FAST 79C971"; // PCI 			break;		case 0x2624:			chipName = "PCnet/FAST+ 79C972"; // PCI 			break;		case 0x2625:			chipName = "PCnet/FAST III 79C973"; // PCI 			break;		case 0x2626:			chipName = "PCnet/Home 79C978"; // PCI 			break;		case 0x2627:			chipName = "PCnet/FAST III 79C975"; // PCI 			break;		case 0x2628:			chipName = "PCnet/PRO 79C976";			break;	}	//TODO: Register interrupt		if((chipVersion != 0x2420 && chipVersion < 0x2621 && chipVersion > 0x2628) || chipVersion == 0x2622)	{		//unsupported chip		//free resources and exit#if defined(NET_DEBUG)		kernelLog("Chip version \"%s\" of the AMD PCNet32 NIC is not supported!\n", chipName);#endif		((kernelNetworkDriver * ) nic->driver)->destroy(nic);				return(status = ERR_INVALID);	}		#if defined(NET_DEBUG)		kernelLog("Chip Name %s recognized (ID: %x)\n", chipName, chipVersion);	#endif	//Save the name of this network device	//TODO: What if there are two identical NICs in a computer?	nic->name = chipName;		//reset the chip again	amdPCNetReset(nic->portIOAddress);		//Clear logical address filter (since we want to receive packets from all MAC addresses)	for(i = 0; i < 4; i++)	{		amdPCNetWriteControlStatusRegister(nic->portIOAddress, i + 8, 0x0000);	} 		//program number of descriptors in transmit ring	//number to be set is the two's complement of the real number	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 78, -NET_TRANSMIT_BUFFER_NUMBER);		//program number of descriptors in receive ring	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 76, -NET_RECEIVE_BUFFER_NUMBER);		//allocate space for the device private structure 	//(the transmit and receive ring structures, the transmit and the receive buffer)	//memory must be 32bit-aligned	//TODO: Memory allocation is suboptimal since whole block is used. What to do?	privatePhysicalAddress = (amdPCNetPrivate *) kernelMemoryGetPhysical(sizeof(amdPCNetPrivate), MEMORY_PAGE_SIZE, "AMD PCNet buffers");		if(!privatePhysicalAddress)	{#if defined(NET_DEBUG)		kernelLog("Can't allocate memory for buffers\n");#endif		((kernelNetworkDriver * ) nic->driver)->destroy(nic);				return(status = ERR_MEMORY);	}		//map the physical address from above to a kernel virtual address	status = kernelPageMapToFree(KERNELPROCID, privatePhysicalAddress, (void **) &nic->privateData, sizeof(amdPCNetPrivate));	if(status < 0)	{#if defined(NET_DEBUG)		kernelLog("Can't map physical address of transmit buffer to virtual address\n");#endif		((kernelNetworkDriver * ) nic->driver)->destroy(nic);				return(status);	}		//save the physical address of the NIC's private structure	((amdPCNetPrivate *) nic->privateData)->thisStructurePhysicalAddress = (void *) privatePhysicalAddress;		//clear the NIC's private structure	kernelMemClear(nic->privateData, sizeof(amdPCNetPrivate));		//Setup the init block used to intialize the NIC	//Save pointers to transmit/receive ring into init block	((amdPCNetPrivate *) nic->privateData)->initBlock.receiveRingPointer = (unsigned long) &privatePhysicalAddress->receiveDescriptor[0];	((amdPCNetPrivate *) nic->privateData)->initBlock.transmitRingPointer = (unsigned long) &privatePhysicalAddress->transmitDescriptor[0];	//disable transmit and receive	((amdPCNetPrivate *) nic->privateData)->initBlock.mode = 0x0003;	//set receive and transmit ring size	((amdPCNetPrivate *) nic->privateData)->initBlock.receiveBufferLength_transmitBufferLength = TX_RING_LEN_BITS | RX_RING_LEN_BITS;	//set physical address    	for (i = 0; i < 6; i++)		((amdPCNetPrivate *) nic->privateData)->initBlock.physicalAddress[i] = nic->myAddress[i];	//Clear filters	((amdPCNetPrivate *) nic->privateData)->initBlock.filter[0] = 0x00000000;	((amdPCNetPrivate *) nic->privateData)->initBlock.filter[1] = 0x00000000; 		//Switch the NIC to 32 bit mode	amdPCNetWriteBaseControlRegister(nic->portIOAddress, 20, 2);		//give the NIC the address of the initialisation block	amdPCNetWriteBaseControlRegister(nic->portIOAddress, 1, (unsigned short) ((unsigned long) &privatePhysicalAddress->initBlock &0xffff));	amdPCNetWriteBaseControlRegister(nic->portIOAddress, 2, (unsigned short) ((unsigned long) &privatePhysicalAddress->initBlock >> 16)); 		//Clear both logical address filters	for(i = 0; i < 4; i++)		amdPCNetWriteControlStatusRegister(nic->portIOAddress, i + 8, 0x0000);		//store length of receive ring (value is the negative of the real length)	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 76, -RX_RING_SIZE);	//store length of transmit ring (value is the negative of the real length)	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 78, -TX_RING_SIZE);		//store physical address of first transmit descriptor in the NIC's registers	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 31, (unsigned short) ((unsigned long) &privatePhysicalAddress->transmitDescriptor[0] & 0xffff));		amdPCNetWriteControlStatusRegister(nic->portIOAddress, 31, (unsigned short) ((unsigned long) &privatePhysicalAddress->transmitDescriptor[0] >> 16));		//store physical address of first receive descriptor in the NIC's registers	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 25, (unsigned short) ((unsigned long) &privatePhysicalAddress->receiveDescriptor[0] & 0xffff));		amdPCNetWriteControlStatusRegister(nic->portIOAddress, 25, (unsigned short) ((unsigned long) &privatePhysicalAddress->receiveDescriptor[0] >> 16));		//Set default values in the mode register	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 15, 0x0000);	//enable the card's leds	amdPCNetWriteBusControlRegister(nic->portIOAddress, 2, 0x1002);		//Hook the card's interrupt	kernelInterruptHookShared(nic->irq, kernelNetworkDriverHandleInterrupt_AmdPCNet, (void *) nic);	//start the *** thing//	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 4, 0x9150);	amdPCNetWriteControlStatusRegister(nic->portIOAddress, 0, 0x0042);		amdPCNetReadControlStatusRegister(nic->portIOAddress, 0, &tmp);		kernelError(kernel_error, "CSR0: %x", tmp); */	/*	//wait until it is initialized	for(i = 0; i < 100; i++)	{		amdPCNetReadControlStatusRegister(nic->portIOAddress, 0, &tmp);		if(tmp & 0x0100) break; 	}		kernelError(kernel_error, "device has private struct at %x", privatePhysicalAddress);		amdPCNetWriteControlStatusRegister(nic->portIOAddress, 0, 0x0042);*/		return (status = 0);}/***************************************************************************************************************//** *	Releases all memory associated with the network device. *	Frees the pci information structure nic->busData, the NIC's private structure nic->privateData,  *	and at last the NIC's structure intself (nic). Unhooks the cards interrupt before it does so. *	NOTE: If you just want to reinitialize the pcnet, call kernelNetworkDriverInitialize again, it will  *	free memory previously used. */static int kernelNetworkDriverDestroy_AmdPCNet(kernelNetworkInterface * nic){	int status;		void * privatePhysical = NULL; 	//TODO: unregister interrupt	//get physical address of the private structure	if(!nic || !nic->privateData) privatePhysical = ((amdPCNetPrivate *) nic->privateData)->physicalAddress;	//disable the device (routine just returns errorcode if nic->busData is NULL)	if(!nic) kernelBusPCIDisable((kernelBusPCIDevice *) (nic->busData));	//free memory used by bus data structure (p. ex. kernelBusPCIDevice)	if(!nic || !nic->busData) kernelFree(nic->busData);	//free memory used by device private structure	if(!nic || !nic->privateData) kernelPageUnmap(KERNELPROCID, nic->privateData, sizeof(amdPCNetPrivate));	//release physical memory used by private structure	if(!privatePhysical) kernelMemoryReleasePhysical(privatePhysical);	//free memory used by driver structure	if(!nic || !nic->driver) kernelFree(nic->driver);	//free memory used by NIC structure	if(!nic) kernelFree((void *) nic);		return (status = 0);}/***************************************************************************************************************/static int kernelNetworkDriverHandleInterrupt_AmdPCNet(void * data){	int status;	kernelNetworkInterface * nic = (kernelNetworkInterface *) data;	unsigned short oldRapValue; //the value of the RegisterAddressPort before we modify it	unsigned short tmp;		kernelError(kernel_error, "Jippee! %s is handling an Interrupt!", nic->name);	//read value of register address port	amdPCNetReadRegisterAddressPort(nic->portIOAddress, &oldRapValue);	amdPCNetReadControlStatusRegister(nic->portIOAddress, CONTROLLER_STATUS, &tmp);	if(!(tmp & CSR0_INTERRUPT_OCCURED))	{		//this device did not cause the interrupt		//restore RAP and exit		amdPCNetWriteRegisterAddressPort(nic->portIOAddress, oldRapValue);		return (status = -1);	}	//disable interrupts	amdPCNetWriteControlStatusRegister(nic->portIOAddress, CONTROLLER_STATUS, 0);		debugDumpRegisters(nic);	//Restore RAP	amdPCNetWriteRegisterAddressPort(nic->portIOAddress, oldRapValue);		return (status = 0);}/***************************************************************************************************************/static int kernelNetworkDriverTransmit_AmdPCNet(kernelNetworkInterface * nic, void * data, int length){	int status;		amdPCNetPrivate * privateVirtual = (amdPCNetPrivate *) nic->privateData;		amdPCNetPrivate * privatePhysical = (amdPCNetPrivate *) privateVirtual->physicalAddress;		debugDumpRegisters(nic);		if(length >= NET_TRANSMIT_BUFFER_SIZE) 	{#if defined(NET_DEBUG)		kernelLog("%s: Packet length %u is too long. Max packet length is %u\n", nic->name, length, NET_TRANSMIT_BUFFER_SIZE);#endif		return (status = ERR_BOUNDS);	}		if((*privateVirtual).transmitDescriptor[privateVirtual->currentTransmitBuffer].statusBits & 0x8000)	{#if defined(NET_DEBUG)		kernelLog("%s: still sending packet in slot %u\n", nic->name, privateVirtual->currentTransmitBuffer);#endif		return (status = ERR_BUSY);//		while((*privateData).transmitDescriptor[privateData->currentTransmitBuffer].statusBits & 0x8000);	}#if defined(NET_DEBUG)		kernelLog("%s: sending packet of length %u in slot %u", nic->name, length, privateVirtual->currentTransmitBuffer);#endif	//get the lock on the NIC	kernelLockGet(&nic->interfaceLock);	//copy the data to the dma accessible memory	kernelMemCopy(data, (void *) &privateVirtual->transmitBuffer[privateVirtual->currentTransmitBuffer], length);	//Set the buffer base address in the descriptor	(*privateVirtual).transmitDescriptor[privateVirtual->currentTransmitBuffer].bufferBaseAddress = (unsigned long) &privatePhysical->transmitBuffer[privateVirtual->currentTransmitBuffer];	//set the negative message length in the descriptor	(*privateVirtual).transmitDescriptor[privateVirtual->currentTransmitBuffer].bufferLength = 0xf000 | -length;	//set the own bit, so the NIC owns this descriptor now	(*privateVirtual).transmitDescriptor[privateVirtual->currentTransmitBuffer].statusBits = TD_START_OF_PACKET | TD_END_OF_PACKET | TD_OWNED_BY_NIC;	//Tell the NIC to send the packet	amdPCNetWriteControlStatusRegister(nic->portIOAddress, CONTROLLER_STATUS, CSR0_INTERRUPT_ENABLE | CSR0_TRANSMIT_DEMAND);	//use next transmit buffer next time	privateVirtual->currentTransmitBuffer = (privateVirtual->currentTransmitBuffer + 1) % NET_TRANSMIT_BUFFER_NUMBER;	//free lock	kernelLockRelease(&nic->interfaceLock);		return (status = 0);}/******************************************************************************///		FUNCTION EXPORTED FOR EXTERNAL USE			      ///******************************************************************************/void kernelNetworkGetDriver_AmdPCNet(kernelNetworkInterface * nic){	kernelNetworkDriver * driver = (kernelNetworkDriver *) kernelMalloc(sizeof(kernelNetworkDriver));		nic->addressLength = ETHERNET_ADDRESS_LENGTH;		//netDriver->myAddress must be initialized by driver		nic->headerPreambleLength = ETHERNET_PREAMBLE_LENGTH;		driver->initialize = kernelNetworkDriverInitialize_AmdPCNet;		driver->destroy = kernelNetworkDriverDestroy_AmdPCNet;		driver->transmit = kernelNetworkDriverTransmit_AmdPCNet;		nic->driver = (void *) driver;		nic->privateData = (void *) 0;}

⌨️ 快捷键说明

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