1 /* 2 * Copyright 2003-2006, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Niels S. Reedijk 7 */ 8 9 #include <module.h> 10 #include <util/kernel_cpp.h> 11 #include "usb_p.h" 12 13 14 #define TRACE_STACK 15 #ifdef TRACE_STACK 16 #define TRACE(x) dprintf x 17 #else 18 #define TRACE(x) /* nothing */ 19 #endif 20 21 22 Stack::Stack() 23 { 24 TRACE(("usb stack: stack init\n")); 25 26 // Create the master lock 27 fMasterLock = create_sem(1, "usb master lock"); 28 set_sem_owner(fMasterLock, B_SYSTEM_TEAM); 29 30 // Create the data lock 31 fDataLock = create_sem(1, "usb data lock"); 32 set_sem_owner(fDataLock, B_SYSTEM_TEAM); 33 34 // Set the global "data" variable to this 35 usb_stack = this; 36 37 // Initialise the memory chunks: create 8, 16 and 32 byte-heaps 38 // NOTE: This is probably the most ugly code you will see in the 39 // whole stack. Unfortunately this is needed because of the fact 40 // that the compiler doesn't like us to apply pointer arithmethic 41 // to (void *) pointers. 42 43 // 8-byte heap 44 fAreaFreeCount[0] = 0; 45 fAreas[0] = AllocateArea(&fLogical[0], &fPhysical[0], B_PAGE_SIZE, 46 "8-byte chunk area"); 47 48 if (fAreas[0] < B_OK) { 49 TRACE(("usb stack: 8-byte chunk area failed to initialise\n")); 50 return; 51 } 52 53 fListhead8 = (addr_t)fLogical[0]; 54 for (int32 i = 0; i < B_PAGE_SIZE / 8; i++) { 55 memory_chunk *chunk = (memory_chunk *)((addr_t)fLogical[0] + 8 * i); 56 chunk->physical = (addr_t)fPhysical[0] + 8 * i; 57 58 if (i < B_PAGE_SIZE / 8 - 1) 59 chunk->next_item = (addr_t)fLogical[0] + 8 * (i + 1); 60 else 61 chunk->next_item = NULL; 62 } 63 64 // 16-byte heap 65 fAreaFreeCount[1] = 0; 66 fAreas[1] = AllocateArea(&fLogical[1], &fPhysical[1], B_PAGE_SIZE, 67 "16-byte chunk area"); 68 69 if (fAreas[1] < B_OK) { 70 TRACE(("usb stack: 16-byte chunk area failed to initialise\n")); 71 return; 72 } 73 74 fListhead16 = (addr_t)fLogical[1]; 75 for (int32 i = 0; i < B_PAGE_SIZE / 16; i++) { 76 memory_chunk *chunk = (memory_chunk *)((addr_t)fLogical[1] + 16 * i); 77 chunk->physical = (addr_t)fPhysical[1] + 16 * i; 78 79 if (i < B_PAGE_SIZE / 16 - 1) 80 chunk->next_item = (addr_t)fLogical[1] + 16 * (i + 1); 81 else 82 chunk->next_item = NULL; 83 } 84 85 // 32-byte heap 86 fAreaFreeCount[2] = 0; 87 fAreas[2] = AllocateArea(&fLogical[2], &fPhysical[2], B_PAGE_SIZE, 88 "32-byte chunk area"); 89 90 if (fAreas[2] < B_OK) { 91 TRACE(("usb stack: 32-byte chunk area failed to initialise\n")); 92 return; 93 } 94 95 fListhead32 = (addr_t)fLogical[2]; 96 for (int32 i = 0; i < B_PAGE_SIZE / 32; i++) { 97 memory_chunk *chunk = (memory_chunk *)((addr_t)fLogical[2] + 32 * i); 98 chunk->physical = (addr_t)fPhysical[2] + 32 * i; 99 100 if (i < B_PAGE_SIZE / 32 - 1) 101 chunk->next_item = (addr_t)fLogical[2] + 32 * (i + 1); 102 else 103 chunk->next_item = NULL; 104 } 105 106 // Check for host controller modules 107 void *moduleList = open_module_list("busses/usb"); 108 char moduleName[B_PATH_NAME_LENGTH]; 109 size_t bufferSize = sizeof(moduleName); 110 111 TRACE(("usb stack: Looking for host controller modules\n")); 112 while(read_next_module_name(moduleList, moduleName, &bufferSize) == B_OK) { 113 bufferSize = sizeof(moduleName); 114 TRACE(("usb stack: Found module %s\n", moduleName)); 115 116 host_controller_info *module = NULL; 117 if (get_module(moduleName, (module_info **)&module) != B_OK) 118 continue; 119 120 if (module->add_to(*this) != B_OK) 121 continue; 122 123 TRACE(("usb stack: module %s successfully loaded\n", moduleName)); 124 } 125 126 if (fBusManagers.Count() == 0) 127 return; 128 } 129 130 131 Stack::~Stack() 132 { 133 //Release the bus modules 134 for (Vector<BusManager *>::Iterator i = fBusManagers.Begin(); 135 i != fBusManagers.End(); i++) { 136 delete (*i); 137 } 138 139 delete_area(fAreas[0]); 140 delete_area(fAreas[1]); 141 delete_area(fAreas[2]); 142 } 143 144 145 status_t 146 Stack::InitCheck() 147 { 148 if (fBusManagers.Count() == 0) 149 return ENODEV; 150 151 return B_OK; 152 } 153 154 155 void 156 Stack::Lock() 157 { 158 acquire_sem(fMasterLock); 159 } 160 161 162 void 163 Stack::Unlock() 164 { 165 release_sem(fMasterLock); 166 } 167 168 169 void 170 Stack::AddBusManager(BusManager *busManager) 171 { 172 fBusManagers.PushBack(busManager); 173 } 174 175 176 status_t 177 Stack::AllocateChunk(void **logicalAddress, void **physicalAddress, uint8 size) 178 { 179 Lock(); 180 181 addr_t listhead; 182 if (size <= 8) 183 listhead = fListhead8; 184 else if (size <= 16) 185 listhead = fListhead16; 186 else if (size <= 32) 187 listhead = fListhead32; 188 else { 189 TRACE(("usb stack: Chunk size %d to big\n", size)); 190 Unlock(); 191 return B_ERROR; 192 } 193 194 if (listhead == NULL) { 195 TRACE(("usb stack: Out of memory on this list\n")); 196 Unlock(); 197 return B_ERROR; 198 } 199 200 //TRACE(("usb stack: Stack::Allocate() listhead: 0x%08x\n", listhead)); 201 memory_chunk *chunk = (memory_chunk *)listhead; 202 *logicalAddress = (void *)listhead; 203 *physicalAddress = (void *)chunk->physical; 204 if (chunk->next_item == NULL) { 205 //TODO: allocate more memory 206 listhead = NULL; 207 } else { 208 listhead = chunk->next_item; 209 } 210 211 // Update our listhead pointers 212 if (size <= 8) 213 fListhead8 = listhead; 214 else if (size <= 16) 215 fListhead16 = listhead; 216 else if (size <= 32) 217 fListhead32 = listhead; 218 219 Unlock(); 220 //TRACE(("usb stack: allocated a new chunk with size %u\n", size)); 221 return B_OK; 222 } 223 224 225 status_t 226 Stack::FreeChunk(void *logicalAddress, void *physicalAddress, uint8 size) 227 { 228 Lock(); 229 230 addr_t listhead; 231 if (size <= 8) 232 listhead = fListhead8; 233 else if (size <= 16) 234 listhead = fListhead16; 235 else if (size <= 32) 236 listhead = fListhead32; 237 else { 238 TRACE(("usb stack: Chunk size %d invalid\n", size)); 239 Unlock(); 240 return B_ERROR; 241 } 242 243 memory_chunk *chunk = (memory_chunk *)logicalAddress; 244 chunk->next_item = listhead; 245 chunk->physical = (addr_t)physicalAddress; 246 247 if (size <= 8) 248 fListhead8 = (addr_t)logicalAddress; 249 else if (size <= 16) 250 fListhead16 = (addr_t)logicalAddress; 251 else if (size <= 32) 252 fListhead32 = (addr_t)logicalAddress; 253 254 Unlock(); 255 return B_OK; 256 } 257 258 259 area_id 260 Stack::AllocateArea(void **logicalAddress, void **physicalAddress, size_t size, 261 const char *name) 262 { 263 TRACE(("usb stack: allocating %ld bytes for %s\n", size, name)); 264 265 void *logAddress; 266 size = (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); 267 area_id area = create_area(name, &logAddress, B_ANY_KERNEL_ADDRESS, size, 268 B_FULL_LOCK | B_CONTIGUOUS, 0); 269 270 if (area < B_OK) { 271 TRACE(("usb stack: couldn't allocate area %s\n", name)); 272 return B_ERROR; 273 } 274 275 physical_entry physicalEntry; 276 status_t result = get_memory_map(logAddress, size, &physicalEntry, 1); 277 if (result < B_OK) { 278 delete_area(area); 279 TRACE(("usb stack: couldn't map area %s\n", name)); 280 return B_ERROR; 281 } 282 283 memset(logAddress, 0, size); 284 if (logicalAddress) 285 *logicalAddress = logAddress; 286 287 if (physicalAddress) 288 *physicalAddress = physicalEntry.address; 289 290 TRACE(("usb stack: area = 0x%08x, size = %ld, log = 0x%08x, phy = 0x%08x\n", 291 area, size, logAddress, physicalEntry.address)); 292 return area; 293 } 294 295 296 Stack *usb_stack = NULL; 297