1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2003-2004, Niels S. Reedijk 3 // 4 // AllocArea implementation (c) 2002 Marcus Overhagen <marcus@overhagen.de> 5 // 6 // Permission is hereby granted, free of charge, to any person obtaining a 7 // copy of this software and associated documentation files (the "Software"), 8 // to deal in the Software without restriction, including without limitation 9 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 // and/or sell copies of the Software, and to permit persons to whom the 11 // Software is furnished to do so, subject to the following conditions: 12 // 13 // The above copyright notice and this permission notice shall be included in 14 // all copies or substantial portions of the Software. 15 // 16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 // DEALINGS IN THE SOFTWARE. 23 24 #include <module.h> 25 #include <util/kernel_cpp.h> 26 27 #include "usb_p.h" 28 29 Stack::Stack() 30 { 31 //Init the master lock 32 m_master = create_sem( 1 , "usb master lock" ); 33 set_sem_owner( m_master , B_SYSTEM_TEAM ); 34 35 //Create the data lock 36 m_datalock = create_sem( 1 , "usb data lock" ); 37 set_sem_owner( m_datalock , B_SYSTEM_TEAM ); 38 39 //Set the global "data" variable to this 40 data = this; 41 42 //Initialise the memory chunks: create 8, 16 and 32 byte-heaps 43 //NOTE: This is probably the most ugly code you will see in the 44 //whole stack. Unfortunately this is needed because of the fact 45 //that the compiler doesn't like us to apply pointer arithmethic 46 //to (void *) pointers. 47 48 // 8-byte heap 49 m_areafreecount[0] = 0; 50 m_areas[0] = AllocateArea( &m_logical[0] , &m_physical[0] , B_PAGE_SIZE , 51 "8-byte chunk area" ); 52 if ( m_areas[0] < B_OK ) 53 { 54 dprintf( "USB: 8-byte chunk area failed to initialise\n" ); 55 return; 56 } 57 58 m_8_listhead = (addr_t)m_logical[0]; 59 60 for ( int i = 0 ; i < B_PAGE_SIZE/8 ; i++ ) 61 { 62 memory_chunk *chunk = (memory_chunk *)((addr_t)m_logical[0] + 8 * i); 63 chunk->physical = (addr_t)m_physical[0] + 8 * i; 64 if ( i != B_PAGE_SIZE / 8 - 1 ) 65 chunk->next_item = (addr_t)m_logical[0] + 8 * ( i + 1 ); 66 else 67 chunk->next_item = NULL; 68 } 69 70 // 16-byte heap 71 m_areafreecount[1] = 0; 72 m_areas[1] = AllocateArea( &m_logical[1] , &m_physical[1] , B_PAGE_SIZE , 73 "16-byte chunk area" ); 74 if ( m_areas[1] < B_OK ) 75 { 76 dprintf( "USB: 16-byte chunk area failed to initialise\n" ); 77 return; 78 } 79 80 m_16_listhead = (addr_t)m_logical[1]; 81 82 for ( int i = 0 ; i < B_PAGE_SIZE/16 ; i++ ) 83 { 84 memory_chunk *chunk = (memory_chunk *)((addr_t)m_logical[1] + 16 * i); 85 chunk->physical = (addr_t)m_physical[1] + 16 * i; 86 if ( i != B_PAGE_SIZE / 16 - 1 ) 87 chunk->next_item = (addr_t)m_logical[1] + 16 * ( i + 1 ); 88 else 89 chunk->next_item = NULL; 90 } 91 92 // 32-byte heap 93 m_areafreecount[2] = 0; 94 m_areas[2] = AllocateArea( &m_logical[2] , &m_physical[2] , B_PAGE_SIZE , 95 "32-byte chunk area" ); 96 if ( m_areas[2] < B_OK ) 97 { 98 dprintf( "USB: 32-byte chunk area failed to initialise\n" ); 99 return; 100 } 101 102 m_32_listhead = (addr_t)m_logical[2]; 103 104 for ( int i = 0 ; i < B_PAGE_SIZE/32 ; i++ ) 105 { 106 memory_chunk *chunk = (memory_chunk *)((addr_t)m_logical[2] + 32 * i); 107 chunk->physical = (addr_t)m_physical[2] + 32 * i; 108 if ( i != B_PAGE_SIZE / 32 - 1 ) 109 chunk->next_item = (addr_t)m_logical[2] + 32 * ( i + 1 ); 110 else 111 chunk->next_item = NULL; 112 } 113 114 115 //Check for host controller modules 116 void *list = open_module_list( "busses/usb" ); 117 char modulename[B_PATH_NAME_LENGTH]; 118 size_t buffersize = sizeof(modulename); 119 dprintf( "USB: Looking for host controller modules\n" ); 120 while( read_next_module_name( list , modulename , &buffersize ) == B_OK ) 121 { 122 dprintf( "USB: Found module %s\n" , modulename ); 123 host_controller_info *module = 0; 124 if ( get_module( modulename , (module_info **)&module ) != B_OK ) 125 continue; 126 if ( module->add_to( *this) != B_OK ) 127 continue; 128 dprintf( "USB: module %s successfully loaded\n" , modulename ); 129 } 130 131 if( m_busmodules.Count() == 0 ) 132 return; 133 } 134 135 Stack::~Stack() 136 { 137 //Release the bus modules 138 for( Vector<BusManager *>::Iterator i = m_busmodules.Begin() ; i != m_busmodules.End() ; i++ ) 139 delete (*i); 140 delete_area( m_areas[0] ); 141 delete_area( m_areas[1] ); 142 delete_area( m_areas[2] ); 143 } 144 145 146 status_t Stack::InitCheck() 147 { 148 if ( m_busmodules.Count() == 0 ) 149 return ENODEV; 150 return B_OK; 151 } 152 153 void Stack::Lock() 154 { 155 acquire_sem( m_master ); 156 } 157 158 void Stack::Unlock() 159 { 160 release_sem( m_master ); 161 } 162 163 void Stack::AddBusManager( BusManager *bus ) 164 { 165 m_busmodules.PushBack( bus ); 166 } 167 168 169 status_t Stack::AllocateChunk( void **log , void **phy , uint8 size ) 170 { 171 Lock(); 172 173 addr_t listhead; 174 if ( size <= 8 ) 175 listhead = m_8_listhead; 176 else if ( size <= 16 ) 177 listhead = m_16_listhead; 178 else if ( size <= 32 ) 179 listhead = m_32_listhead; 180 else 181 { 182 dprintf ( "USB Stack: Chunk size %i to big\n" , size ); 183 Unlock(); 184 return B_ERROR; 185 } 186 187 if ( listhead == NULL ) 188 { 189 Unlock(); 190 dprintf( "USB Stack: Out of memory on this list\n" ); 191 return B_ERROR; 192 } 193 194 dprintf( "USB Stack::Allocate() listhead: %ld\n" , listhead ); 195 196 memory_chunk *chunk = (memory_chunk *)listhead; 197 *log = (void *)listhead; 198 *phy = (void *)(chunk->physical); 199 if ( chunk->next_item == NULL ) 200 //TODO: allocate more memory 201 listhead = NULL; 202 else 203 listhead = chunk->next_item; 204 205 //Update our listhead pointers 206 if ( size <= 8 ) 207 m_8_listhead = listhead; 208 else if ( size <= 16 ) 209 m_16_listhead = listhead; 210 else if ( size <= 32 ) 211 m_32_listhead = listhead; 212 213 Unlock(); 214 dprintf( "USB Stack: allocated a new chunk with size %u\n" , size ); 215 return B_OK; 216 } 217 218 status_t Stack::FreeChunk( void *log , void *phy , uint8 size ) 219 { 220 Lock(); 221 addr_t listhead; 222 if ( size <= 8 ) 223 listhead = m_8_listhead; 224 else if ( size <= 16 ) 225 listhead = m_16_listhead; 226 else if ( size <= 32 ) 227 listhead = m_32_listhead; 228 else 229 { 230 dprintf ( "USB Stack: Chunk size %i invalid\n" , size ); 231 Unlock(); 232 return B_ERROR; 233 } 234 235 memory_chunk *chunk = (memory_chunk *)log; 236 237 chunk->next_item = listhead; 238 chunk->physical = (addr_t)phy; 239 240 if ( size <= 8 ) 241 m_8_listhead = (addr_t)log; 242 else if ( size <= 16 ) 243 m_16_listhead = (addr_t)log; 244 else if ( size <= 32 ) 245 m_32_listhead = (addr_t)log; 246 247 Unlock(); 248 return B_OK; 249 } 250 251 area_id Stack::AllocateArea( void **log , void **phy , size_t size , const char *name ) 252 { 253 physical_entry pe; 254 void * logadr; 255 area_id areaid; 256 status_t rv; 257 258 dprintf("allocating %ld bytes for %s\n",size,name); 259 260 size = (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); 261 areaid = create_area(name, &logadr, B_ANY_KERNEL_ADDRESS,size,B_FULL_LOCK | B_CONTIGUOUS, 0 ); 262 if (areaid < B_OK) { 263 dprintf("couldn't allocate area %s\n",name); 264 return B_ERROR; 265 } 266 rv = get_memory_map(logadr,size,&pe,1); 267 if (rv < B_OK) { 268 delete_area(areaid); 269 dprintf("couldn't map %s\n",name); 270 return B_ERROR; 271 } 272 memset(logadr,0,size); 273 if (log) 274 *log = logadr; 275 if (phy) 276 *phy = pe.address; 277 dprintf("area = %ld, size = %ld, log = %#08lX, phy = %#08lX\n",areaid,size,(uint32)logadr,(uint32)(pe.address)); 278 return areaid; 279 } 280 281 Stack *data = 0; 282