/*++ 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; }
/* 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); }
/* 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--; }
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; }