2 /* $Id: pnp_iterators.c,v 1.6 2001/05/07 12:32:42 lcs Exp $ */
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,
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>
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
;
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 ];
74 static struct ResourceIterator
*
75 AllocResourceIterator( struct ISAPNP_Resource
* resource
,
76 struct ResourceContext
* ctx
);
79 FreeResourceIterator( struct ResourceIterator
* iter
,
80 struct ResourceContext
* ctx
);
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
);
100 NewList( (struct List
*) &ctx
->m_IO
);
107 /******************************************************************************
108 ** Free a resource iterator context *******************************************
109 ******************************************************************************/
112 FreeResourceIteratorContext( struct ResourceContext
* ctx
)
114 struct ResourceIteratorRef
* ref
;
121 while( ( ref
= (struct ResourceIteratorRef
*)
122 RemHead( (struct List
*) &ctx
->m_IO
) ) )
131 /******************************************************************************
132 ** Lock resources from the context ********************************************
133 ******************************************************************************/
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
);
148 if( ctx
->m_IRQ
[ iter
->m_IRQBit
] == NULL
)
150 ctx
->m_IRQ
[ iter
->m_IRQBit
] = iter
;
154 conflict
= ctx
->m_IRQ
[ iter
->m_IRQBit
];
161 case ISAPNP_NT_DMA_RESOURCE
:
163 #ifdef DEBUG_ITERATORS
164 KPrintF( "L DMA %ld", iter
->m_ChannelBit
);
166 if( ctx
->m_DMA
[ iter
->m_ChannelBit
] == NULL
)
168 ctx
->m_DMA
[ iter
->m_ChannelBit
] = iter
;
172 conflict
= ctx
->m_DMA
[ iter
->m_ChannelBit
];
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
);
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
) ) )
204 conflict
= io
->m_Iterator
;
208 if( base
+ length
<= io_base
)
210 // No more collisions possible; insert before this one
212 position
= (struct Node
*) io
->m_MinNode
.mln_Pred
;
218 if( conflict
== NULL
)
222 new_io
= AllocVec( sizeof( *new_io
), MEMF_PUBLIC
);
230 new_io
->m_Iterator
= iter
;
232 if( position
== NULL
)
234 AddTail( (struct List
*) &ctx
->m_IO
, (struct Node
*) new_io
);
238 Insert( (struct List
*) &ctx
->m_IO
, (struct Node
*) new_io
, position
);
246 case ISAPNP_NT_MEMORY_RESOURCE
:
251 if( conflict
!= NULL
)
253 conflict
->m_InConflict
= TRUE
;
254 iter
->m_HasLock
= FALSE
;
258 iter
->m_HasLock
= TRUE
;
261 #ifdef DEBUG_ITERATORS
262 if( iter
->m_HasLock
) KPrintF( " OK\n" ); else KPrintF( " failed\n" );
265 return iter
->m_HasLock
;
269 /******************************************************************************
270 ** Unlock resources from the context ******************************************
271 ******************************************************************************/
274 UnlockResource( struct ResourceIterator
* iter
,
275 struct ResourceContext
* ctx
)
277 if( ! iter
->m_HasLock
)
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
);
289 ctx
->m_IRQ
[ iter
->m_IRQBit
] = NULL
;
295 case ISAPNP_NT_DMA_RESOURCE
:
297 #ifdef DEBUG_ITERATORS
298 KPrintF( "U DMA %ld\n", iter
->m_ChannelBit
);
300 ctx
->m_DMA
[ iter
->m_ChannelBit
] = NULL
;
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
);
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
);
330 case ISAPNP_NT_MEMORY_RESOURCE
:
335 iter
->m_HasLock
= FALSE
;
339 /******************************************************************************
340 ** Reset a resource iterator **************************************************
341 ******************************************************************************/
344 ResetResourceIterator( struct ResourceIterator
* iter
,
345 struct ResourceContext
* ctx
)
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
;
359 while( iter
->m_IRQBit
< 16 )
361 if( r
->isapnpirqr_IRQMask
& ( 1 << iter
->m_IRQBit
) )
363 if( LockResource( iter
, ctx
) )
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
) )
396 ++iter
->m_ChannelBit
;
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
) )
421 iter
->m_Base
+= r
->isapnpior_Alignment
;
427 case ISAPNP_NT_MEMORY_RESOURCE
:
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
);
450 iter
->m_Resource
= resource
;
452 if( ! ResetResourceIterator( iter
, ctx
) )
454 FreeResourceIterator( iter
, ctx
);
463 /******************************************************************************
464 ** Deallocate a resource iterator *********************************************
465 ******************************************************************************/
468 FreeResourceIterator( struct ResourceIterator
* iter
,
469 struct ResourceContext
* ctx
)
478 UnlockResource( iter
, ctx
);
480 rc
= iter
->m_InConflict
;
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" );
504 result
= AllocVec( sizeof( *result
), MEMF_PUBLIC
| MEMF_CLEAR
);
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
);
522 FreeResourceIteratorList( result
, ctx
);
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" );
543 /******************************************************************************
544 ** Deallocate a resource iterator list ****************************************
545 ******************************************************************************/
548 FreeResourceIteratorList( struct ResourceIteratorList
* list
,
549 struct ResourceContext
* ctx
)
553 struct ResourceIterator
* iter
;
555 #ifdef DEBUG_ITERATORS
556 KPrintF( "FreeResourceIteratorList()\n" );
564 while( ( iter
= (struct ResourceIterator
*)
565 RemHead( (struct List
*) &list
->m_ResourceIterators
) ) )
567 if( FreeResourceIterator( iter
, ctx
) )
575 #ifdef DEBUG_ITERATORS
576 if( rc
) KPrintF( "FreeResourceIteratorList() T\n" );
577 else KPrintF( "FreeResourceIteratorList() F\n" );
584 /******************************************************************************
585 ** Increase a resource iterator ***********************************************
586 ******************************************************************************/
589 IncResourceIterator( struct ResourceIterator
* iter
,
590 struct ResourceContext
* ctx
)
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 )
608 if( r
->isapnpirqr_IRQMask
& ( 1 << iter
->m_IRQBit
) )
610 rc
= LockResource( iter
, ctx
);
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
);
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
);
655 case ISAPNP_NT_MEMORY_RESOURCE
:
664 /******************************************************************************
665 ** Increase a resource iterator list ******************************************
666 ******************************************************************************/
669 IncResourceIteratorList( struct ResourceIteratorList
* iter_list
,
670 struct ResourceContext
* ctx
)
673 struct ResourceIterator
* current
;
675 #ifdef DEBUG_ITERATORS
676 KPrintF( "IncResourceIteratorList()\n" );
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
);
689 // This iterator is not in conflict. There is no need to
690 // try any more combinations
692 UnlockResource( current
, ctx
);
697 ResetResourceIterator( current
, ctx
);
699 current
= (struct ResourceIterator
*) current
->m_MinNode
.mln_Succ
;
703 #ifdef DEBUG_ITERATORS
704 KPrintF( "IncResourceIteratorList(): %ld\n", 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
);
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
;
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
;
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;
783 case ISAPNP_NT_MEMORY_RESOURCE
:
785 ISAPNP_FreeResource( result
, res
);
794 /******************************************************************************
795 ** Create resources from a list of iterators **********************************
796 ******************************************************************************/
799 CreateResouces( struct ResourceIteratorList
* ril
,
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
)
822 AddTail( result
, (struct Node
*) resource
);