1 /* 2 * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Copyright 2002-2004, Thomas Kurschel. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include "io_resources.h" 10 11 #include <stdlib.h> 12 #include <string.h> 13 14 15 //#define TRACE_IO_RESOURCES 16 #ifdef TRACE_IO_RESOURCES 17 # define TRACE(x) dprintf x 18 #else 19 # define TRACE(x) ; 20 #endif 21 22 23 typedef DoublyLinkedList<io_resource_private, 24 DoublyLinkedListMemberGetLink<io_resource_private, 25 &io_resource_private::fTypeLink> > ResourceTypeList; 26 27 28 static ResourceTypeList sMemoryList; 29 static ResourceTypeList sPortList; 30 static ResourceTypeList sDMAChannelList; 31 32 io_resource_private()33io_resource_private::io_resource_private() 34 { 35 _Init(); 36 } 37 38 ~io_resource_private()39io_resource_private::~io_resource_private() 40 { 41 Release(); 42 } 43 44 45 void _Init()46io_resource_private::_Init() 47 { 48 type = 0; 49 base = 0; 50 length = 0; 51 } 52 53 54 status_t Acquire(const io_resource & resource)55io_resource_private::Acquire(const io_resource& resource) 56 { 57 if (!_IsValid(resource)) 58 return B_BAD_VALUE; 59 60 type = resource.type; 61 base = resource.base; 62 63 if (type != B_ISA_DMA_CHANNEL) 64 length = resource.length; 65 else 66 length = 1; 67 68 ResourceTypeList* list = NULL; 69 70 switch (type) { 71 case B_IO_MEMORY: 72 list = &sMemoryList; 73 break; 74 case B_IO_PORT: 75 list = &sPortList; 76 break; 77 case B_ISA_DMA_CHANNEL: 78 list = &sDMAChannelList; 79 break; 80 } 81 82 ResourceTypeList::Iterator iterator = list->GetIterator(); 83 while (iterator.HasNext()) { 84 io_resource* resource = iterator.Next(); 85 86 // we need the "base + length - 1" trick to avoid wrap around at 4 GB 87 if (resource->base >= base 88 && resource->base + length - 1 <= base + length - 1) { 89 // This range is already covered by someone else 90 // TODO: we might want to ignore resources that belong to 91 // a node that isn't used. 92 _Init(); 93 return B_RESOURCE_UNAVAILABLE; 94 } 95 } 96 97 list->Add(this); 98 return B_OK; 99 } 100 101 102 void Release()103io_resource_private::Release() 104 { 105 if (type == 0) 106 return; 107 108 switch (type) { 109 case B_IO_MEMORY: 110 sMemoryList.Remove(this); 111 break; 112 case B_IO_PORT: 113 sPortList.Remove(this); 114 break; 115 case B_ISA_DMA_CHANNEL: 116 sDMAChannelList.Remove(this); 117 break; 118 } 119 120 _Init(); 121 } 122 123 124 /*static*/ bool _IsValid(const io_resource & resource)125io_resource_private::_IsValid(const io_resource& resource) 126 { 127 switch (resource.type) { 128 case B_IO_MEMORY: 129 return resource.base + resource.length > resource.base; 130 case B_IO_PORT: 131 return (uint16)resource.base == resource.base 132 && (uint16)resource.length == resource.length 133 && resource.base + resource.length > resource.base; 134 case B_ISA_DMA_CHANNEL: 135 return resource.base <= 8; 136 137 default: 138 return false; 139 } 140 } 141 142 143 // #pragma mark - 144 145 146 void dm_init_io_resources(void)147dm_init_io_resources(void) 148 { 149 new(&sMemoryList) ResourceTypeList; 150 new(&sPortList) ResourceTypeList; 151 new(&sDMAChannelList) ResourceTypeList; 152 } 153