/* * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Copyright 2002-2004, Thomas Kurschel. All rights reserved. * * Distributed under the terms of the MIT License. */ #include "io_resources.h" #include #include //#define TRACE_IO_RESOURCES #ifdef TRACE_IO_RESOURCES # define TRACE(x) dprintf x #else # define TRACE(x) ; #endif typedef DoublyLinkedList > ResourceTypeList; static ResourceTypeList sMemoryList; static ResourceTypeList sPortList; static ResourceTypeList sDMAChannelList; io_resource_private::io_resource_private() { _Init(); } io_resource_private::~io_resource_private() { Release(); } void io_resource_private::_Init() { type = 0; base = 0; length = 0; } status_t io_resource_private::Acquire(const io_resource& resource) { if (!_IsValid(resource)) return B_BAD_VALUE; type = resource.type; base = resource.base; if (type != B_ISA_DMA_CHANNEL) length = resource.length; else length = 1; ResourceTypeList* list = NULL; switch (type) { case B_IO_MEMORY: list = &sMemoryList; break; case B_IO_PORT: list = &sPortList; break; case B_ISA_DMA_CHANNEL: list = &sDMAChannelList; break; } ResourceTypeList::Iterator iterator = list->GetIterator(); while (iterator.HasNext()) { io_resource* resource = iterator.Next(); // we need the "base + length - 1" trick to avoid wrap around at 4 GB if (resource->base >= base && resource->base + length - 1 <= base + length - 1) { // This range is already covered by someone else // TODO: we might want to ignore resources that belong to // a node that isn't used. _Init(); return B_RESOURCE_UNAVAILABLE; } } list->Add(this); return B_OK; } void io_resource_private::Release() { if (type == 0) return; switch (type) { case B_IO_MEMORY: sMemoryList.Remove(this); break; case B_IO_PORT: sPortList.Remove(this); break; case B_ISA_DMA_CHANNEL: sDMAChannelList.Remove(this); break; } _Init(); } /*static*/ bool io_resource_private::_IsValid(const io_resource& resource) { switch (resource.type) { case B_IO_MEMORY: return resource.base + resource.length > resource.base; case B_IO_PORT: return (uint16)resource.base == resource.base && (uint16)resource.length == resource.length && resource.base + resource.length > resource.base; case B_ISA_DMA_CHANNEL: return resource.base <= 8; default: return false; } } // #pragma mark - void dm_init_io_resources(void) { new(&sMemoryList) ResourceTypeList; new(&sPortList) ResourceTypeList; new(&sDMAChannelList) ResourceTypeList; }