/*++

Name: 
	RingBufferRead()

Description:
	Read and advance the read index

--*/
int
RingBufferRead(
	RING_BUFFER_INFO*	InRingInfo,
	PVOID				Buffer,
	UINT32				BufferLen,
	UINT32				Offset
	)
{
	UINT32 bytesAvailToWrite;
	UINT32 bytesAvailToRead;
	UINT32 nextReadLocation=0;
	UINT64 prevIndices=0;

	ASSERT(BufferLen > 0);
	
	SpinlockAcquire(InRingInfo->RingLock);

	GetRingBufferAvailBytes(InRingInfo, &bytesAvailToRead, &bytesAvailToWrite);

	DPRINT_DBG(VMBUS, "Reading %u bytes...", BufferLen);

	//DumpRingInfo(InRingInfo, "BEFORE ");

	// Make sure there is something to read
	if (bytesAvailToRead < BufferLen )
	{
		DPRINT_DBG(VMBUS, "got callback but not enough to read <avail to read %d read size %d>!!", bytesAvailToRead, BufferLen);

		SpinlockRelease(InRingInfo->RingLock);

		return -1;
	}

	nextReadLocation = GetNextReadLocationWithOffset(InRingInfo, Offset);

	nextReadLocation = CopyFromRingBuffer(InRingInfo,
											Buffer,
											BufferLen,
											nextReadLocation);

	nextReadLocation = CopyFromRingBuffer(InRingInfo,
											&prevIndices,
											sizeof(UINT64),
											nextReadLocation);

	// Make sure all reads are done before we update the read index since 
	// the writer may start writing to the read area once the read index is updated
	MemoryFence();

	// Update the read index
	SetNextReadLocation(InRingInfo, nextReadLocation);
	
	//DumpRingInfo(InRingInfo, "AFTER ");

	SpinlockRelease(InRingInfo->RingLock);

	return 0;
}
Пример #2
0
/* Allocate Physical Page below 1 mb */
PhysAddr_t MmPhysicalAllocateBlockDma(void)
{
	/* Get free bit */
	int bit;

	/* Get Spinlock */
	SpinlockAcquire(&MemoryLock);

	/* Get bit */
	bit = MmGetFreeMapBitLow();

	/* Release Spinlock */
	SpinlockRelease(&MemoryLock);

	/* Sanity */
	assert(bit != -1);

	/* Set it */
	MmMemoryMapSetBit(bit);

	/* Statistics */
	MemoryBlocksUsed++;

	return (PhysAddr_t)(bit * PAGE_SIZE);
}
Пример #3
0
/* Free Physical Page */
void MmPhysicalFreeBlock(PhysAddr_t Addr)
{
	/* Calculate Bit */
	int bit = (int32_t)(Addr / PAGE_SIZE);

	/* Sanity */
	if (Addr > MemorySize
		|| Addr < 0x200000)
		return;

	/* Get Spinlock */
	SpinlockAcquire(&MemoryLock);

	/* Sanity */
	assert(MmMemoryMapTestBit(bit) != 0);

	/* Free it */
	MmMemoryMapUnsetBit(bit);

	/* Release Spinlock */
	SpinlockRelease(&MemoryLock);

	/* Statistics */
	if (MemoryBlocksUsed != 0)
		MemoryBlocksUsed--;
}
Пример #4
0
DevId_t DmCreateDevice(char *Name, MCoreDevice_t *Device)
{
	/* Grap lock */
	SpinlockAcquire(&GlbDmLock);
	
	/* Set name and data */
	Device->Name = strdup(Name);
	Device->Id = GlbDmIdentfier;

	/* Increase */
	GlbDmIdentfier++;

	/* Release */
	SpinlockRelease(&GlbDmLock);

	/* Add to list */
	list_append(GlbDmDeviceList, list_create_node(Device->Id, (void*)Device));

	/* Call some broadcast function so systems know a new device is avaiable
	 * depending on the device type */
	switch (Device->Type)
	{
		/* Give access to timer */
		case DeviceTimer:
		{
			/* Cast */
			MCoreTimerDevice_t *Timer = (MCoreTimerDevice_t*)Device->Data;
			Timer->ReportMs = TimersApplyMs;

		} break;

		/* Give access to input */
		case DeviceInput:
		{
			/* Cast */
			MCoreInputDevice_t *Input = (MCoreInputDevice_t*)Device->Data;
			Input->ReportEvent = EmCreateEvent;

		} break;

		/* Register with Vfs */
		case DeviceStorage:
		{
			/* Call */
			VfsRegisterDisk(Device->Id);

		} break;

		/* No special actions */
		default:
			break;
	}

	/* Info Log */
	LogInformation("DRVM", "New Device: %s", Name);

	/* Done */
	return Device->Id;
}
/*++

Name: 
	RingBufferPeek()

Description:
	Read without advancing the read index

--*/
int
RingBufferPeek(
	RING_BUFFER_INFO*	InRingInfo,
	void*				Buffer,
	UINT32				BufferLen
	)
{
	UINT32 bytesAvailToWrite;
	UINT32 bytesAvailToRead;
	UINT32 nextReadLocation=0;

	SpinlockAcquire(InRingInfo->RingLock);

	GetRingBufferAvailBytes(InRingInfo, &bytesAvailToRead, &bytesAvailToWrite);

	// Make sure there is something to read
	if (bytesAvailToRead < BufferLen )
	{
		//DPRINT_DBG(VMBUS, "got callback but not enough to read <avail to read %d read size %d>!!", bytesAvailToRead, BufferLen);

		SpinlockRelease(InRingInfo->RingLock);

		return -1;
	}

	// Convert to byte offset
	nextReadLocation = GetNextReadLocation(InRingInfo);

	nextReadLocation = CopyFromRingBuffer(InRingInfo,
											Buffer,
											BufferLen,
											nextReadLocation);

	SpinlockRelease(InRingInfo->RingLock);

	return 0;
}
/*++

Name: 
	RingBufferWrite()

Description:
	Write to the ring buffer

--*/
int
RingBufferWrite(
	RING_BUFFER_INFO*	OutRingInfo,
	SG_BUFFER_LIST		SgBuffers[],
	UINT32				SgBufferCount
	)
{
	int i=0;
	UINT32 byteAvailToWrite;
	UINT32 byteAvailToRead;
	UINT32 totalBytesToWrite=0;

	volatile UINT32 nextWriteLocation;
	UINT64 prevIndices=0;

	DPRINT_ENTER(VMBUS);

	for (i=0; i < SgBufferCount; i++)
	{
		totalBytesToWrite += SgBuffers[i].Length;
	}

	totalBytesToWrite += sizeof(UINT64);

	SpinlockAcquire(OutRingInfo->RingLock);

	GetRingBufferAvailBytes(OutRingInfo, &byteAvailToRead, &byteAvailToWrite);
	
	DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite);

	//DumpRingInfo(OutRingInfo, "BEFORE ");
	
	// If there is only room for the packet, assume it is full. Otherwise, the next time around, we think the ring buffer
	// is empty since the read index == write index
	if (byteAvailToWrite <= totalBytesToWrite)
	{
		DPRINT_DBG(VMBUS, "No more space left on outbound ring buffer (needed %u, avail %u)", totalBytesToWrite, byteAvailToWrite);

		SpinlockRelease(OutRingInfo->RingLock);

		DPRINT_EXIT(VMBUS);

		return -1;
	}

	// Write to the ring buffer
	nextWriteLocation = GetNextWriteLocation(OutRingInfo);

	for (i=0; i < SgBufferCount; i++)
	{
		 nextWriteLocation = CopyToRingBuffer(OutRingInfo,
												nextWriteLocation,
												SgBuffers[i].Data,
												SgBuffers[i].Length);
	}

	// Set previous packet start
	prevIndices = GetRingBufferIndices(OutRingInfo);

	nextWriteLocation = CopyToRingBuffer(OutRingInfo,
												nextWriteLocation,
												&prevIndices,
												sizeof(UINT64));

	// Make sure we flush all writes before updating the writeIndex
	MemoryFence();

	// Now, update the write location
	SetNextWriteLocation(OutRingInfo, nextWriteLocation);

	//DumpRingInfo(OutRingInfo, "AFTER ");

	SpinlockRelease(OutRingInfo->RingLock);
		
	DPRINT_EXIT(VMBUS);

	return 0;
}