test/library/usereltest.c: Refined test to show that problem is not solved.
[AROS.git] / rom / isapnp / pnp_iterators.c
bloba273439b5f5ea8f471f0c63d63fee46375a95cdd
2 /* $Id$ */
4 /*
5 ISA-PnP -- A Plug And Play ISA software layer for AmigaOS.
6 Copyright (C) 2001 Martin Blom <martin@blom.org>
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
18 You should have received a copy of the GNU Library General Public
19 License along with this library; if not, write to the
20 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
21 MA 02139, USA.
24 #include "CompilerSpecific.h"
26 #include <exec/memory.h>
28 #include <clib/alib_protos.h>
29 #include <proto/exec.h>
31 #include <resources/isapnp.h>
32 #include "init.h"
33 #include "pnp_iterators.h"
34 #include "pnp_structs.h"
35 #include "isapnp_private.h"
38 struct ResourceIterator
40 struct MinNode m_MinNode;
41 struct ISAPNP_Resource* m_Resource;
42 UBYTE m_IRQBit;
43 UBYTE m_ChannelBit;
44 UWORD m_Base;
45 UWORD m_Length;
46 BOOL m_HasLock;
47 BOOL m_InConflict;
51 #undef DEBUG_ITERATORS
53 struct ResourceIteratorList
55 struct MinList m_ResourceIterators;
59 struct ResourceIteratorRef
61 struct MinNode m_MinNode;
62 struct ResourceIterator* m_Iterator;
66 struct ResourceContext
68 struct ResourceIterator* m_IRQ[ 16 ];
69 struct ResourceIterator* m_DMA[ 8 ];
70 struct MinList m_IO;
74 static struct ResourceIterator*
75 AllocResourceIterator( struct ISAPNP_Resource* resource,
76 struct ResourceContext* ctx );
78 static BOOL
79 FreeResourceIterator( struct ResourceIterator* iter,
80 struct ResourceContext* ctx );
82 static BOOL
83 IncResourceIterator( struct ResourceIterator* iter,
84 struct ResourceContext* ctx );
87 /******************************************************************************
88 ** Allocate a clean resource iterator context *********************************
89 ******************************************************************************/
91 struct ResourceContext*
92 AllocResourceIteratorContext( void )
94 struct ResourceContext* ctx;
96 ctx = AllocVec( sizeof( *ctx ), MEMF_PUBLIC | MEMF_CLEAR );
98 if( ctx != NULL )
100 NewList( (struct List*) &ctx->m_IO );
103 return ctx;
107 /******************************************************************************
108 ** Free a resource iterator context *******************************************
109 ******************************************************************************/
111 void
112 FreeResourceIteratorContext( struct ResourceContext* ctx )
114 struct ResourceIteratorRef* ref;
116 if( ctx == NULL )
118 return;
121 while( ( ref = (struct ResourceIteratorRef*)
122 RemHead( (struct List*) &ctx->m_IO ) ) )
124 FreeVec( ref );
127 FreeVec( ctx );
131 /******************************************************************************
132 ** Lock resources from the context ********************************************
133 ******************************************************************************/
135 static BOOL
136 LockResource( struct ResourceIterator* iter,
137 struct ResourceContext* ctx )
139 struct ResourceIterator* conflict = NULL;
141 switch( iter->m_Resource->isapnpr_Type )
143 case ISAPNP_NT_IRQ_RESOURCE:
145 #ifdef DEBUG_ITERATORS
146 KPrintF( "L IRQ %ld", iter->m_IRQBit );
147 #endif
148 if( ctx->m_IRQ[ iter->m_IRQBit ] == NULL )
150 ctx->m_IRQ[ iter->m_IRQBit ] = iter;
152 else
154 conflict = ctx->m_IRQ[ iter->m_IRQBit ];
157 break;
161 case ISAPNP_NT_DMA_RESOURCE:
163 #ifdef DEBUG_ITERATORS
164 KPrintF( "L DMA %ld", iter->m_ChannelBit );
165 #endif
166 if( ctx->m_DMA[ iter->m_ChannelBit ] == NULL )
168 ctx->m_DMA[ iter->m_ChannelBit ] = iter;
170 else
172 conflict = ctx->m_DMA[ iter->m_ChannelBit ];
175 break;
179 case ISAPNP_NT_IO_RESOURCE:
181 struct ResourceIteratorRef* io;
182 struct ResourceIteratorRef* new_io;
183 struct Node* position = NULL;
185 UWORD base = iter->m_Base;
186 UWORD length = iter->m_Length;
188 #ifdef DEBUG_ITERATORS
189 KPrintF( "L IO %lx-%lx", base, base + length );
190 #endif
192 for( io = (struct ResourceIteratorRef*) ctx->m_IO.mlh_Head;
193 io->m_MinNode.mln_Succ != NULL;
194 io = (struct ResourceIteratorRef*) io->m_MinNode.mln_Succ )
196 UWORD io_base = io->m_Iterator->m_Base;
197 UWORD io_length = io->m_Iterator->m_Length;
199 if( ( base <= io_base && ( base + length ) > io_base ) ||
200 ( base >= io_base && base < ( io_base + io_length ) ) )
202 // Collision!
204 conflict = io->m_Iterator;
205 break;
208 if( base + length <= io_base )
210 // No more collisions possible; insert before this one
212 position = (struct Node*) io->m_MinNode.mln_Pred;
214 break;
218 if( conflict == NULL )
220 // Insert the node
222 new_io = AllocVec( sizeof( *new_io ), MEMF_PUBLIC );
224 if( new_io == NULL )
226 return FALSE;
228 else
230 new_io->m_Iterator = iter;
232 if( position == NULL )
234 AddTail( (struct List*) &ctx->m_IO, (struct Node*) new_io );
236 else
238 Insert( (struct List*) &ctx->m_IO, (struct Node*) new_io, position );
243 break;
246 case ISAPNP_NT_MEMORY_RESOURCE:
247 default:
248 break;
251 if( conflict != NULL )
253 conflict->m_InConflict = TRUE;
254 iter->m_HasLock = FALSE;
256 else
258 iter->m_HasLock = TRUE;
261 #ifdef DEBUG_ITERATORS
262 if( iter->m_HasLock ) KPrintF( " OK\n" ); else KPrintF( " failed\n" );
263 #endif
265 return iter->m_HasLock;
269 /******************************************************************************
270 ** Unlock resources from the context ******************************************
271 ******************************************************************************/
273 static void
274 UnlockResource( struct ResourceIterator* iter,
275 struct ResourceContext* ctx )
277 if( ! iter->m_HasLock )
279 return;
282 switch( iter->m_Resource->isapnpr_Type )
284 case ISAPNP_NT_IRQ_RESOURCE:
286 #ifdef DEBUG_ITERATORS
287 KPrintF( "U IRQ %ld\n", iter->m_IRQBit );
288 #endif
289 ctx->m_IRQ[ iter->m_IRQBit ] = NULL;
291 break;
295 case ISAPNP_NT_DMA_RESOURCE:
297 #ifdef DEBUG_ITERATORS
298 KPrintF( "U DMA %ld\n", iter->m_ChannelBit );
299 #endif
300 ctx->m_DMA[ iter->m_ChannelBit ] = NULL;
302 break;
306 case ISAPNP_NT_IO_RESOURCE:
308 struct ResourceIteratorRef* io;
310 #ifdef DEBUG_ITERATORS
311 KPrintF( "U IO %lx-%lx\n", iter->m_Base,
312 iter->m_Base + iter->m_Length );
313 #endif
315 for( io = (struct ResourceIteratorRef*) ctx->m_IO.mlh_Head;
316 io->m_MinNode.mln_Succ != NULL;
317 io = (struct ResourceIteratorRef*) io->m_MinNode.mln_Succ )
319 if( io->m_Iterator->m_Base == iter->m_Base )
321 Remove( (struct Node*) io );
322 FreeVec( io );
323 break;
327 break;
330 case ISAPNP_NT_MEMORY_RESOURCE:
331 default:
332 break;
335 iter->m_HasLock = FALSE;
339 /******************************************************************************
340 ** Reset a resource iterator **************************************************
341 ******************************************************************************/
343 static BOOL
344 ResetResourceIterator( struct ResourceIterator* iter,
345 struct ResourceContext* ctx )
347 BOOL rc = FALSE;
349 switch( iter->m_Resource->isapnpr_Type )
351 case ISAPNP_NT_IRQ_RESOURCE:
353 struct ISAPNP_IRQResource* r;
355 r = (struct ISAPNP_IRQResource*) iter->m_Resource;
357 iter->m_IRQBit = 0;
359 while( iter->m_IRQBit < 16 )
361 if( r->isapnpirqr_IRQMask & ( 1 << iter->m_IRQBit ) )
363 if( LockResource( iter, ctx ) )
365 rc = TRUE;
366 break;
370 ++iter->m_IRQBit;
373 break;
377 case ISAPNP_NT_DMA_RESOURCE:
379 struct ISAPNP_DMAResource* r;
381 r = (struct ISAPNP_DMAResource*) iter->m_Resource;
383 iter->m_ChannelBit = 0;
385 while( iter->m_ChannelBit < 8 )
387 if( r->isapnpdmar_ChannelMask & ( 1 << iter->m_ChannelBit ) )
389 if( LockResource( iter, ctx ) )
391 rc = TRUE;
392 break;
396 ++iter->m_ChannelBit;
399 break;
403 case ISAPNP_NT_IO_RESOURCE:
405 struct ISAPNP_IOResource* r;
407 r = (struct ISAPNP_IOResource*) iter->m_Resource;
409 iter->m_Base = r->isapnpior_MinBase;
410 iter->m_Length = r->isapnpior_Length;
413 while( iter->m_Base <= r->isapnpior_MaxBase )
415 if( LockResource( iter, ctx ) )
417 rc = TRUE;
418 break;
421 iter->m_Base += r->isapnpior_Alignment;
424 break;
427 case ISAPNP_NT_MEMORY_RESOURCE:
428 default:
429 break;
432 return rc;
436 /******************************************************************************
437 ** Allocate a resource iterator ***********************************************
438 ******************************************************************************/
440 static struct ResourceIterator*
441 AllocResourceIterator( struct ISAPNP_Resource* resource,
442 struct ResourceContext* ctx )
444 struct ResourceIterator* iter;
446 iter = AllocVec( sizeof( *iter ), MEMF_PUBLIC | MEMF_CLEAR );
448 if( iter != NULL )
450 iter->m_Resource = resource;
452 if( ! ResetResourceIterator( iter, ctx ) )
454 FreeResourceIterator( iter, ctx );
455 iter = NULL;
459 return iter;
463 /******************************************************************************
464 ** Deallocate a resource iterator *********************************************
465 ******************************************************************************/
467 static BOOL
468 FreeResourceIterator( struct ResourceIterator* iter,
469 struct ResourceContext* ctx )
471 BOOL rc = FALSE;
473 if( iter == NULL )
475 return FALSE;
478 UnlockResource( iter, ctx );
480 rc = iter->m_InConflict;
482 FreeVec( iter );
484 return rc;
488 /******************************************************************************
489 ** Allocate a resource iterator list ******************************************
490 ******************************************************************************/
492 // This function cannot handle conflicts within the list itself
494 struct ResourceIteratorList*
495 AllocResourceIteratorList( struct MinList* resource_list,
496 struct ResourceContext* ctx )
498 struct ResourceIteratorList* result;
500 #ifdef DEBUG_ITERATORS
501 KPrintF( "AllocResourceIteratorList()\n" );
502 #endif
504 result = AllocVec( sizeof( *result ), MEMF_PUBLIC | MEMF_CLEAR );
506 if( result != NULL )
508 struct ISAPNP_Resource* r;
510 NewList( (struct List*) &result->m_ResourceIterators );
512 r = (struct ISAPNP_Resource*) resource_list->mlh_Head;
514 while( r->isapnpr_MinNode.mln_Succ != NULL )
516 struct ResourceIterator* iter;
518 iter = AllocResourceIterator( r, ctx );
520 if( iter == NULL )
522 FreeResourceIteratorList( result, ctx );
523 result = NULL;
524 break;
527 AddTail( (struct List*) &result->m_ResourceIterators,
528 (struct Node*) iter );
530 r = (struct ISAPNP_Resource*) r->isapnpr_MinNode.mln_Succ;
534 #ifdef DEBUG_ITERATORS
535 if( result ) KPrintF( "AllocResourceIteratorList() succeeded\n" );
536 else KPrintF( "AllocResourceIteratorList() failed\n" );
537 #endif
539 return result;
543 /******************************************************************************
544 ** Deallocate a resource iterator list ****************************************
545 ******************************************************************************/
547 BOOL
548 FreeResourceIteratorList( struct ResourceIteratorList* list,
549 struct ResourceContext* ctx )
551 BOOL rc = FALSE;
553 struct ResourceIterator* iter;
555 #ifdef DEBUG_ITERATORS
556 KPrintF( "FreeResourceIteratorList()\n" );
557 #endif
559 if( list == NULL )
561 return FALSE;
564 while( ( iter = (struct ResourceIterator*)
565 RemHead( (struct List*) &list->m_ResourceIterators ) ) )
567 if( FreeResourceIterator( iter, ctx ) )
569 rc = TRUE;
573 FreeVec( list );
575 #ifdef DEBUG_ITERATORS
576 if( rc ) KPrintF( "FreeResourceIteratorList() T\n" );
577 else KPrintF( "FreeResourceIteratorList() F\n" );
578 #endif
580 return rc;
584 /******************************************************************************
585 ** Increase a resource iterator ***********************************************
586 ******************************************************************************/
588 static BOOL
589 IncResourceIterator( struct ResourceIterator* iter,
590 struct ResourceContext* ctx )
592 BOOL rc = FALSE;
594 UnlockResource( iter, ctx );
596 switch( iter->m_Resource->isapnpr_Type )
598 case ISAPNP_NT_IRQ_RESOURCE:
600 struct ISAPNP_IRQResource* r;
602 r = (struct ISAPNP_IRQResource*) iter->m_Resource;
604 while( ! rc && iter->m_IRQBit < 16 )
606 ++iter->m_IRQBit;
608 if( r->isapnpirqr_IRQMask & ( 1 << iter->m_IRQBit ) )
610 rc = LockResource( iter, ctx );
614 break;
617 case ISAPNP_NT_DMA_RESOURCE:
619 struct ISAPNP_DMAResource* r;
621 r = (struct ISAPNP_DMAResource*) iter->m_Resource;
623 while( ! rc && iter->m_ChannelBit < 8 )
625 ++iter->m_ChannelBit;
627 if( r->isapnpdmar_ChannelMask & ( 1 << iter->m_ChannelBit ) )
629 rc = LockResource( iter, ctx );
633 break;
636 case ISAPNP_NT_IO_RESOURCE:
638 struct ISAPNP_IOResource* r;
640 r = (struct ISAPNP_IOResource*) iter->m_Resource;
642 while( ! rc && iter->m_Base <= r->isapnpior_MaxBase )
644 iter->m_Base += r->isapnpior_Alignment;
646 if( iter->m_Base <= r->isapnpior_MaxBase )
648 rc = LockResource( iter, ctx );
652 break;
655 case ISAPNP_NT_MEMORY_RESOURCE:
656 default:
657 break;;
660 return rc;
664 /******************************************************************************
665 ** Increase a resource iterator list ******************************************
666 ******************************************************************************/
668 BOOL
669 IncResourceIteratorList( struct ResourceIteratorList* iter_list,
670 struct ResourceContext* ctx )
672 BOOL rc = FALSE;
673 struct ResourceIterator* current;
675 #ifdef DEBUG_ITERATORS
676 KPrintF( "IncResourceIteratorList()\n" );
677 #endif
679 current = (struct ResourceIterator*) iter_list->m_ResourceIterators.mlh_Head;
681 while( ! rc && current->m_MinNode.mln_Succ != NULL )
683 if( current->m_InConflict )
685 rc = IncResourceIterator( current, ctx );
687 else
689 // This iterator is not in conflict. There is no need to
690 // try any more combinations
692 UnlockResource( current, ctx );
695 if( ! rc )
697 ResetResourceIterator( current, ctx );
699 current = (struct ResourceIterator*) current->m_MinNode.mln_Succ;
703 #ifdef DEBUG_ITERATORS
704 KPrintF( "IncResourceIteratorList(): %ld\n", rc );
705 #endif
707 return rc;
711 /******************************************************************************
712 ** Create a resource from an iterator *****************************************
713 ******************************************************************************/
715 struct ISAPNP_Resource*
716 CreateResource( struct ResourceIterator* iter,
717 struct ISAPNPBase* res )
719 struct ISAPNP_Resource* result = NULL;
721 result = ISAPNP_AllocResource( iter->m_Resource->isapnpr_Type, res );
723 if( result == NULL )
725 return NULL;
728 switch( iter->m_Resource->isapnpr_Type )
730 case ISAPNP_NT_IRQ_RESOURCE:
732 struct ISAPNP_IRQResource* r;
734 r = (struct ISAPNP_IRQResource*) result;
736 // Make a copy of the iterators resource
738 CopyMem( iter->m_Resource, r, sizeof( *r ) );
739 r->isapnpirqr_MinNode.mln_Succ = NULL;
740 r->isapnpirqr_MinNode.mln_Pred = NULL;
742 r->isapnpirqr_IRQMask = 1 << iter->m_IRQBit;
744 break;
747 case ISAPNP_NT_DMA_RESOURCE:
749 struct ISAPNP_DMAResource* r;
751 r = (struct ISAPNP_DMAResource*) result;
753 // Make a copy of the iterators resource
755 CopyMem( iter->m_Resource, r, sizeof( *r ) );
756 r->isapnpdmar_MinNode.mln_Succ = NULL;
757 r->isapnpdmar_MinNode.mln_Pred = NULL;
759 r->isapnpdmar_ChannelMask = 1 << iter->m_ChannelBit;
761 break;
764 case ISAPNP_NT_IO_RESOURCE:
766 struct ISAPNP_IOResource* r;
768 r = (struct ISAPNP_IOResource*) result;
770 // Make a copy of the iterators resource
772 CopyMem( iter->m_Resource, r, sizeof( *r ) );
773 r->isapnpior_MinNode.mln_Succ = NULL;
774 r->isapnpior_MinNode.mln_Pred = NULL;
776 r->isapnpior_MinBase = iter->m_Base;
777 r->isapnpior_MaxBase = iter->m_Base;
778 r->isapnpior_Alignment = 1;
780 break;
783 case ISAPNP_NT_MEMORY_RESOURCE:
784 default:
785 ISAPNP_FreeResource( result, res );
786 result = NULL;
787 break;;
790 return result;
794 /******************************************************************************
795 ** Create resources from a list of iterators **********************************
796 ******************************************************************************/
798 BOOL
799 CreateResouces( struct ResourceIteratorList* ril,
800 struct List* result,
801 struct ISAPNPBase* res )
803 // Allocate resources for current iterators
805 struct ResourceIterator* iter;
807 for( iter = (struct ResourceIterator*)
808 ril->m_ResourceIterators.mlh_Head;
809 iter->m_MinNode.mln_Succ != NULL;
810 iter = (struct ResourceIterator*)
811 iter->m_MinNode.mln_Succ )
813 struct ISAPNP_Resource* resource;
815 resource = CreateResource( iter, res );
817 if( resource == NULL )
819 return FALSE;
822 AddTail( result, (struct Node*) resource );
825 return TRUE;