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

📄 main.cc

📁 一个mips虚拟机非常好代码,使用C++来编写的,希望大家多学学,
💻 CC
字号:
// DEC Tulip Plus Ethernet Controller// Matt Chapman <matthewc@cse.unsw.edu.au>#include <stdio.h>#include <string.h>#include <unistd.h>#include <assert.hh>#include <checkpoint.hh>#include <device.hh>#include <inttypes.hh>#include <module.hh>#include <serial.hh>#include <simarg.hh>#include <sulima.hh>#include "tulip.hh"// Serialization information.SerialType<Tulip> Tulip::type(    "Tulip",    "DEC Tulip Plus Ethernet Controller");// Runtime constructor.Tulip::Tulip(const SimArgs& args)    : Module(args), PCIDevice(32, PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS, PCI_CLASS_NETWORK_ETHERNET){    if (args.length() > 2)	throw Error("Too many arguments to \"sim::install Tulip\".");}// Serialized constructor.Tulip::Tulip(Checkpoint& cp)    : Module(cp), PCIDevice(32, PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS, PCI_CLASS_NETWORK_ETHERNET){	reset(false);}// Module interface.voidTulip::reset(bool warm){	irq_status = irq_mask = 0;	setup_tap();	memset(srom, 0, sizeof(srom));	srom[9] = 1 | (1 << 8);	/* SROM Format Version, Controller Count */	srom[10] = 0x10; /* MAC address 10:00:00:00:00:00 */	srom[63] = 0xffff;	/* Checksum */}voidTulip::init(Bus *b, InterruptSink *intc, UInt64 base_address, UInt64 size, int base_irq){	int i;	bus = b;	intctrl = intc;	bar[0] = base_address | 1;	for (i = 1; i <= 5; i++)		bar[i] = 0;	irq = base_irq;}// Serialization interface.voidTulip::checkpoint(Checkpoint& cp, bool parent) const{}voidTulip::read_uint32(UInt32 address, UInt32 *value){	UInt64 buf_64;	bus->read(address, &buf_64, 4);	*value = buf_64;	/* when to byte swap? */}voidTulip::write_uint32(UInt32 address, UInt32 value){	UInt64 buf_64 = value;	/* when to byte swap? */	bus->write(address, &buf_64, 4);}voidTulip::tx_fragment(UInt32 address, UInt32 length){	UInt64 buf;	if (tx_offset + length > sizeof(tx_buffer))		return;	while (length > 0)	{		bus->read(address, &buf, 1);		tx_buffer[tx_offset++] = buf;		address++;		length--;	}}voidTulip::tx_frame(void){#if 0	UInt32 i;	printf("network: send ");	for (i = 0; i < tx_offset; i++)		printf("%02x", tx_buffer[i]);	printf("\n");#endif	::write(io_fd, tx_buffer, tx_offset);	tx_offset = 0;}voidTulip::tx_poll(void){	struct tdes tdes;	while (1)	{		/* fetch descriptor */		read_uint32(tx_next,    &tdes.tdes0.raw);		read_uint32(tx_next+4,  &tdes.tdes1.raw);		read_uint32(tx_next+8,  &tdes.tdes2);		read_uint32(tx_next+12, &tdes.tdes3);		if (!tdes.tdes0.x.own)		{			irq_status |= IRQ_TU;			break;		}		if (!tdes.tdes1.x.set) /* ignore setup packets */		{			/* send data */			tx_fragment(tdes.tdes2, tdes.tdes1.x.tbs1);			if (!tdes.tdes1.x.tch)				tx_fragment(tdes.tdes3, tdes.tdes1.x.tbs2);			if (tdes.tdes1.x.ls)				tx_frame();		}		/* write back status */		tdes.tdes0.raw = 0;		write_uint32(tx_next, tdes.tdes0.raw);		if (tdes.tdes1.x.ic)			irq_status |= IRQ_TI;		/* proceed to next descriptor */		if (tdes.tdes1.x.ter)			tx_next = tx_base;		else if (tdes.tdes1.x.tch)			tx_next = tdes.tdes3;		else			tx_next += sizeof(tdes) + 4*bus_mode.r.dsl;	}	check_interrupts();}voidTulip::rx_fragment(UInt32 address, UInt32 length, UInt8 *buffer, UInt32 &offset, UInt32 &remaining){	UInt64 buf;	if (length > remaining)		length = remaining;	remaining -= length;	while (length > 0)	{		buf = buffer[offset++];		bus->write(address, &buf, 1);		address++;		length--;	}}voidTulip::rx_input(UInt8 *buffer, UInt32 length){	struct rdes rdes;	UInt32 remaining = length, offset = 0;	bool first = true;	/* append (bogus) CRC - hopefully the OS doesn't check */	buffer[length] = buffer[length+1] = buffer[length+2] = buffer[length+3] = 0xff;	length += 4;	while (1)	{		/* fetch descriptor */		read_uint32(rx_next,    &rdes.rdes0.raw);		read_uint32(rx_next+4,  &rdes.rdes1.raw);		read_uint32(rx_next+8,  &rdes.rdes2);		read_uint32(rx_next+12, &rdes.rdes3);		if (!rdes.rdes0.x.own)		{			irq_status |= IRQ_RU;			break;		}		if (remaining == 0)			break;		/* receive data */		rx_fragment(rdes.rdes2, rdes.rdes1.x.rbs1, buffer, offset, remaining);		if (!rdes.rdes1.x.rch)			rx_fragment(rdes.rdes3, rdes.rdes1.x.rbs2, buffer, offset, remaining);		/* write back status */		rdes.rdes0.raw = 0;		rdes.rdes0.x.fl = length;		rdes.rdes0.x.fs = first;		rdes.rdes0.x.ls = (remaining == 0);		write_uint32(rx_next, rdes.rdes0.raw);		first = false;		/* proceed to next descriptor */		if (rdes.rdes1.x.rer)			rx_next = rx_base;		else if (rdes.rdes1.x.rch)			rx_next = rdes.rdes3;		else			rx_next += sizeof(rdes) + 4*bus_mode.r.dsl;	}	irq_status |= IRQ_RI;	check_interrupts();}voidTulip::check_interrupts(void){	bool intr = false;	/* recalculate these bits */	irq_status &= ~(IRQ_NIS|IRQ_AIS);	if ((irq_mask & irq_status) & (IRQ_TI|IRQ_TU|IRQ_RI))	{		if (irq_mask & IRQ_NIS)			intr = true;		irq_status |= IRQ_NIS;	}	if ((irq_mask & irq_status) & (IRQ_RU))	{		if (irq_mask & IRQ_AIS)			intr = true;		irq_status |= IRQ_AIS;	}	if (intr)		intctrl->deliver_interrupt(irq);	else		intctrl->clear_interrupt(irq);}ClockValueTulip::read(UInt64 addr, UInt64* buf, int size){	unsigned int reg = (addr >> 3) & 0xf;	UInt32 val;	switch (reg)	{	case 0: /* Bus Mode Register */		val = bus_mode.data;		break;	case 1: /* Transmit Poll Demand Register */	case 2: /* Receive Poll Demand Register */		val = 0;		break;	case 3: /* Rx Descriptor Base */		val = rx_base;		break;	case 4: /* Tx Descriptor Base */		val = tx_base;		break;	case 5: /* Status Register */		val = irq_status;		if (op_mode.r.start_rcv)			val |= (3 << 17); /* Rx running */		if (op_mode.r.start_send)			val |= (6 << 20); /* Tx active (but suspended) */		break;	case 6: /* Operating Mode Register */		val = op_mode.data;		break;	case 7: /* Interrupt Mask */		val = irq_mask;		break;	case 9: /* Boot and Ethernet ROMs Register */		val = srom_mii.data;		break;	case 12: /* SIA Status Register */		val = (1 << 4) | (1 << 5); /* PLL Self Test Done | PLL Self Test Pass */		break;	default:		log("Read unimplemented register %d", reg);		val = 0;		break;	}	*buf = val;	return 0; // ignore latency}ClockValueTulip::write(UInt64 addr, const UInt64* buf, int size){	unsigned int reg = (addr >> 3) & 0xf;	UInt32 val = *buf;	switch (reg)	{	case 0: /* Bus Mode Register */		bus_mode.data = val;		/* Should handle swr */		if (bus_mode.r.swr == 1) {			bus_mode.r.swr = 0;		}		break;	case 1: /* Transmit Poll Demand Register */		tx_poll();		break;	case 2: /* Receive Poll Demand Register */		break;	case 3: /* Rx Descriptor Base */		rx_next = rx_base = val;		break;	case 4: /* Tx Descriptor Base */		tx_next = tx_base = val;		break;	case 5: /* Status Register */		/* writing 1 clears corresponding IRQ status bit */		irq_status &= ~val;		check_interrupts();		break;	case 6: /* Operating Mode Register */		op_mode.data = val;		if (op_mode.r.start_send)			tx_poll();		break;	case 7: /* Interrupt Mask */		irq_mask = val;		break;	case 9: /* Boot and Ethernet ROMs Register */		srom_mii.data = val;		if (srom_mii.r.sr)		{			if (srom_mii.r.cs && srom_mii.r.clk)			{				srom_out <<= 1;				srom_out |= srom_mii.r.dout;				srom_mii.r.din = srom_in >> 15;				srom_in <<= 1;				if ((srom_out >> srom_address_bits) == 6)					srom_in = srom[srom_out & 63];			}			else if (!srom_mii.r.cs)			{				srom_out = srom_in = 0;			}		}		break;	default:		log("Write unimplemented register %d %x", reg, val);		break;	}	return 0; // ignore latency}

⌨️ 快捷键说明

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