4 ISA-PnP -- A Plug And Play ISA software layer for AmigaOS.
5 Copyright (C) 2001 Martin Blom <martin@blom.org>
6 Copyright (C) 2009 The AROS Development Team
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,
26 #include "CompilerSpecific.h"
28 #include <exec/memory.h>
29 #include <exec/resident.h>
30 #include <devices/timer.h>
32 #include <clib/alib_protos.h>
33 #include <proto/exec.h>
34 /*#include <proto/utility.h>*/
38 #include <resources/isapnp.h>
39 #include "isapnp_private.h"
42 #include "controller.h"
46 #include "pnp_structs.h"
50 HandleToolTypes( UBYTE** tool_types,
51 struct ISAPNP_Card* card,
52 struct ISAPNPBase* res );
55 PatchBrokenCards( struct ISAPNPBase
* res
);
58 ReqA( const char* text, APTR args );
60 #define Req( text, args...) \
61 ( { ULONG _args[] = { args }; ReqA( (text), (APTR) _args ); } )
63 #define Req(args...) bug(args); bug("\n")
65 /******************************************************************************
66 ** Resource resident structure ************************************************
67 ******************************************************************************/
69 extern const char LIBEND
;
70 extern const char ResName
[];
71 extern const char IDString
[];
72 static const APTR InitTable
[4];
74 const struct Resident RomTag
=
77 (struct Resident
*) &RomTag
,
78 (struct Resident
*) &LIBEND
,
79 RTF_AUTOINIT
|RTF_COLDSTART
,
91 /******************************************************************************
92 ** Globals ********************************************************************
93 ******************************************************************************/
95 struct Device
* TimerBase
= NULL
;
96 /*struct ExecBase* SysBase = NULL;*/
97 /*struct IntuitionBase* IntuitionBase = NULL;*/
98 struct ISAPNPBase
* ISAPNPBase
= NULL
;
99 /*struct UtilityBase* UtilityBase = NULL;*/
101 static struct timerequest
*TimerIO
= NULL
;
103 const char ResName
[] = ISAPNPNAME
;
104 const char IDString
[] = ISAPNPNAME
" " VERS
"\r\n";
106 static const char VersTag
[] =
107 "$VER: " ISAPNPNAME
" " VERS
" ©2001 Martin Blom.\r\n";
109 /******************************************************************************
110 ** Resource initialization ****************************************************
111 ******************************************************************************/
113 struct ISAPNPBase
* ASMCALL
114 initRoutine( REG( d0
, struct ISAPNPBase
* res
),
115 REG( a0
, APTR seglist
),
116 REG( a6
, struct ExecBase
* sysbase
) )
118 D(bug("[ISAPNP] Init\n"));
119 /* SysBase = sysbase;*/
123 // Set up the ISAPNPBase structure
125 res
->m_Library
.lib_Node
.ln_Type
= NT_RESOURCE
;
126 res
->m_Library
.lib_Node
.ln_Name
= (STRPTR
) ResName
;
127 res
->m_Library
.lib_Flags
= LIBF_SUMUSED
| LIBF_CHANGED
;
128 res
->m_Library
.lib_Version
= VERSION
;
129 res
->m_Library
.lib_Revision
= REVISION
;
130 res
->m_Library
.lib_IdString
= (STRPTR
) IDString
;
132 NewList( &res
->m_Cards
);
134 /* Base address, on i386 we don't have any mapping
135 res->m_Base = NULL; */
136 res
->m_RegReadData
= 0x0000;
138 if( ! ISAPNP_ScanCards( res
) )
142 Req( "No PnP ISA cards found." );
143 FreeISAPNPBase( res
);
147 if( ! PatchBrokenCards( res
) )
149 FreeISAPNPBase( res
);
153 struct ISAPNP_Card
* card
;
155 card
= ISAPNP_AllocCard( res
);
159 Req( "Out of memory!" );
160 FreeISAPNPBase( res
);
164 static const char descr
[] = "Non-PnP devices";
167 d
= AllocVec( sizeof( descr
), MEMF_PUBLIC
);
171 CopyMem( (void*) descr
, d
, sizeof( descr
) );
172 card
->isapnpc_Node
.ln_Name
= d
;
175 card
->isapnpc_ID
.isapnpid_Vendor
[ 0 ] = '?';
176 card
->isapnpc_ID
.isapnpid_Vendor
[ 1 ] = '?';
177 card
->isapnpc_ID
.isapnpid_Vendor
[ 2 ] = '?';
178 card
->isapnpc_SerialNumber
= -1;
181 AddHead( &res
->m_Cards
, (struct Node
*) card
);
183 // Let's see if we're to disable any cards or devices etc
184 /* TODO: We will start up early because we can have even ISA PnP video
185 cards, disk controllers, etc. Because of this we can't load
186 any list of disabled devices. Think off what to do with them
187 is really a big TODO.
188 if( ! HandleToolTypes( current_binding.cb_ToolTypes,
191 // Error requester already displayed.
192 FreeISAPNPBase( res );
196 if( ! ISAPNP_ConfigureCards( res
) )
198 // Unable to configure cards
200 Req( "Unable to configure the cards. This is most likely\n"
201 "because of an unresolvable hardware conflict.\n\n"
202 "Use the DISABLE_DEVICE tool type to disable one of\n"
203 "the devices in conflict." );
204 FreeISAPNPBase( res
);
219 /******************************************************************************
220 ** Free all resources from ISAPNPBase *****************************************
221 ******************************************************************************/
224 FreeISAPNPBase( struct ISAPNPBase
* res
)
226 struct ISAPNP_Card
* card
;
228 while( ( card
= (struct ISAPNP_Card
*) RemHead( &res
->m_Cards
) ) )
230 ISAPNP_FreeCard( card
, ISAPNPBase
);
235 /******************************************************************************
236 ** Initialization tables ******************************************************
237 ******************************************************************************/
239 static const APTR funcTable
[] =
245 ISAC_GetInterruptStatus
,
263 ISAPNP_AllocResourceGroup
,
264 ISAPNP_FreeResourceGroup
,
265 ISAPNP_AllocResource
,
269 ISAPNP_ConfigureCards
,
277 ISAPNP_UnlockDevices
,
283 static const APTR InitTable
[4] =
285 (APTR
) sizeof( struct ISAPNPBase
),
291 /******************************************************************************
292 ** OpenLibs *******************************************************************
293 ******************************************************************************/
298 /* Utility Library (libnix depends on it, and our startup-code is not
299 executed when BindDriver LoadSeg()s us!) */
301 /* Intuition Library */
303 IntuitionBase = (struct IntuitionBase*) OpenLibrary( "intuition.library", 37 );
305 if( IntuitionBase == NULL )
310 UtilityBase = (struct UtilityBase *) OpenLibrary( "utility.library", 37 );
312 if( UtilityBase == NULL)
319 TimerIO
= (struct timerequest
*) AllocVec( sizeof(struct timerequest
),
320 MEMF_PUBLIC
| MEMF_CLEAR
);
327 if( OpenDevice( "timer.device",
336 TimerBase
= (struct Device
*) TimerIO
->tr_node
.io_Device
;
342 /******************************************************************************
343 ** CloseLibs *******************************************************************
344 ******************************************************************************/
349 if( TimerIO
!= NULL
)
351 CloseDevice( (struct IORequest
*) TimerIO
);
356 CloseLibrary( (struct Library*) UtilityBase );
357 CloseLibrary( (struct Library*) IntuitionBase );
361 /*IntuitionBase = NULL;
362 UtilityBase = NULL;*/
366 /******************************************************************************
367 ** ReqA ***********************************************************************
368 ******************************************************************************/
371 ReqA( const char* text, APTR args )
373 struct EasyStruct es =
375 sizeof (struct EasyStruct),
377 (STRPTR) ISAPNPNAME " " VERS,
382 if( IntuitionBase != NULL )
384 EasyRequestArgs( NULL, &es, NULL, args );
389 /******************************************************************************
390 ** Handle the tool types ******************************************************
391 ******************************************************************************/
396 if( c >= '0' && c <= '9' )
400 else if( c >= 'A' && c <= 'F' )
404 else if( c >= 'a' && c <= 'f' )
414 // CTL0048 => "CTL\0" 4 8 -1 -1
415 // CTL0048/1236 => "CTL\0" 4 8 1236 -1
416 // CTL0048:0 => "CTL\0" 4 8 -1 0
417 // CTL0048/1236:0 => "CTL\0" 4 8 1236 0
420 ParseID( UBYTE* string,
425 WORD* logical_device )
431 *manufacturer = ISAPNP_MAKE_ID( ToUpper( string[ 0 ] ),
432 ToUpper( string[ 1 ] ),
433 ToUpper( string[ 2 ] ) );
435 *product = ( HexToInt( string[ 3 ] ) << 8 ) |
436 ( HexToInt( string[ 4 ] ) << 4 ) |
437 ( HexToInt( string[ 5 ] ) );
445 *revision = HexToInt( string[ 6 ] );
447 if( *revision == -1 )
454 if( string[ chars ] == '/' )
460 // Not allowed if we don't ask for it
464 conv = StrToLong( string + chars + 1, &ser );
482 if( string[ chars ] == ':' )
486 if( logical_device == NULL )
488 // Not allowed if we don't ask for it
492 conv = StrToLong( string + chars + 1, &dev );
505 if( logical_device != NULL )
507 *logical_device = dev;
510 if( string[ chars ] != 0 && string[ chars ] != ' ' )
520 HandleToolTypes( UBYTE** tool_types,
521 struct ISAPNP_Card* card,
522 struct ISAPNPBase* res )
526 if( Strnicmp( *tool_types, "DISABLE_CARD=", 13 ) == 0 )
533 if( ParseID( *tool_types + 13,
534 &manufacturer, &product, &revision, &serial, NULL ) )
536 struct ISAPNP_Card* card = NULL;
538 while( ( card = ISAPNP_FindCard( card,
545 card->isapnpc_Disabled = TRUE;
550 Req( "Illegal tool type: %s\n", (ULONG) *tool_types );
554 else if( Strnicmp( *tool_types, "DISABLE_DEVICE=", 15 ) == 0 )
562 if( ParseID( *tool_types + 15,
563 &manufacturer, &product, &revision, &serial, &log_dev ) )
567 struct ISAPNP_Device* dev = NULL;
569 while( ( dev = ISAPNP_FindDevice( dev,
575 dev->isapnpd_Disabled = TRUE;
580 struct ISAPNP_Card* card = NULL;
582 while( ( card = ISAPNP_FindCard( card,
589 struct ISAPNP_Device* dev;
591 for( dev = (struct ISAPNP_Device*) card->isapnpc_Devices.lh_Head;
592 dev->isapnpd_Node.ln_Succ != NULL;
593 dev = (struct ISAPNP_Device*) dev->isapnpd_Node.ln_Succ )
595 if( dev->isapnpd_DeviceNumber == (UWORD) log_dev )
597 dev->isapnpd_Disabled = TRUE;
605 Req( "Illegal tool type value: %s\n", (ULONG) *tool_types );
609 else if( Strnicmp( *tool_types, "LEGACY_DEVICE=", 14 ) == 0 )
618 str = *tool_types + 14;
619 conv = ParseID( str, &manufacturer, &product, &revision, NULL, NULL );
625 struct ISAPNP_Device* dev;
626 struct ISAPNP_Identifier* id;
628 dev = ISAPNP_AllocDevice( res );
632 Req( "Out of memory!" );
636 dev->isapnpd_Card = card;
638 id = AllocVec( sizeof( *id ), MEMF_PUBLIC | MEMF_CLEAR );
642 Req( "Out of memory!" );
643 ISAPNP_FreeDevice( dev, res );
647 id->isapnpid_Vendor[ 0 ] = ( manufacturer >> 24 ) & 0xff;
648 id->isapnpid_Vendor[ 1 ] = ( manufacturer >> 16 ) & 0xff;
649 id->isapnpid_Vendor[ 2 ] = ( manufacturer >> 8 ) & 0xff;
650 id->isapnpid_Vendor[ 3 ] = 0;
652 id->isapnpid_ProductID = product;
653 id->isapnpid_Revision = revision;
655 AddTail( (struct List*) &dev->isapnpd_IDs, (struct Node*) id );
657 if( card->isapnpc_Devices.lh_Head->ln_Succ != NULL )
659 dev_num = ( (struct ISAPNP_Device*)
660 card->isapnpc_Devices.lh_TailPred )->isapnpd_DeviceNumber;
664 dev->isapnpd_DeviceNumber = dev_num;
666 AddTail( &card->isapnpc_Devices, (struct Node*) dev );
672 if( Strnicmp( str, "IRQ=", 4 ) == 0 )
676 irq = strtol( str + 4, (char**) &str, 0 );
678 if( irq <= 0 || irq >= 16 )
680 Req( "Invalid IRQ value '%ld' in tooltype line\n"
683 (ULONG) *tool_types );
688 struct ISAPNP_IRQResource* r;
690 r = (struct ISAPNP_IRQResource*)
691 ISAPNP_AllocResource( ISAPNP_NT_IRQ_RESOURCE, res );
695 Req( "Out of memory!" );
699 r->isapnpirqr_IRQMask = 1 << irq;
700 r->isapnpirqr_IRQType = ISAPNP_IRQRESOURCE_ITF_HIGH_EDGE;
702 AddTail( (struct List*) &dev->isapnpd_Options->isapnprg_Resources,
706 else if( Strnicmp( str, "DMA=", 4 ) == 0 )
710 dma = strtol( str + 4, (char**) &str, 0 );
712 if( dma <= 0 || dma >= 8 )
714 Req( "Invalid DMA value '%ld' in tooltype line\n"
717 (ULONG) *tool_types );
722 struct ISAPNP_DMAResource* r;
724 r = (struct ISAPNP_DMAResource*)
725 ISAPNP_AllocResource( ISAPNP_NT_DMA_RESOURCE, res );
729 Req( "Out of memory!" );
733 r->isapnpdmar_ChannelMask = 1 << dma;
734 r->isapnpdmar_Flags = 0;
736 AddTail( (struct List*) &dev->isapnpd_Options->isapnprg_Resources,
740 else if( Strnicmp( str, "IO=", 3 ) == 0 )
745 struct ISAPNP_IOResource* r;
747 base = strtol( str + 3, (char**) &str, 0 );
751 Req( "Length missing from IO value in tooltype line\n"
753 (ULONG) *tool_types );
759 length = strtol( str, (char**) &str, 0 );
761 if( base <= 0 || base >= 0xffff )
763 Req( "Invalid IO base value '%ld' in tooltype line\n"
766 (ULONG) *tool_types );
770 if( length <= 0 || length >= 0xffff )
772 Req( "Invalid IO length value '%ld' in tooltype line\n"
775 (ULONG) *tool_types );
779 r = (struct ISAPNP_IOResource*)
780 ISAPNP_AllocResource( ISAPNP_NT_IO_RESOURCE, res );
784 Req( "Out of memory!" );
788 r->isapnpior_MinBase = base;
789 r->isapnpior_MaxBase = base;
790 r->isapnpior_Length = length;
791 r->isapnpior_Alignment = 1;
793 AddTail( (struct List*) &dev->isapnpd_Options->isapnprg_Resources,
798 Req( "Parse error near '%s'\n"
802 (ULONG) *tool_types );
815 Req( "Illegal tool type: '%s'\n", (ULONG) *tool_types );
821 // Ignore unknown tool types
830 /******************************************************************************
831 ** Fix cards that have broken PnP ROMs ****************************************
832 ******************************************************************************/
835 PatchBrokenCards( struct ISAPNPBase
* res
)
837 struct ISAPNP_Device
* dev
= NULL
;
839 // Patch the wavetable device on SB AWE32 and AWE64
841 while( ( dev
= ISAPNP_FindDevice( dev
,
842 ISAPNP_MAKE_ID('C','T','L'),
847 struct ISAPNP_ResourceGroup
* rg
;
848 struct ISAPNP_IOResource
* r1
;
849 struct ISAPNP_IOResource
* r2
;
850 struct ISAPNP_IOResource
* r3
;
852 // Nuke all dependent options
854 while( ( rg
= (struct ISAPNP_ResourceGroup
*)
855 RemHead( (struct List
*) &dev
->isapnpd_Options
->isapnprg_ResourceGroups
) )
858 ISAPNP_FreeResourceGroup( rg
, res
);
861 rg
= ISAPNP_AllocResourceGroup( ISAPNP_RG_PRI_ACCEPTABLE
, res
);
863 r1
= (struct ISAPNP_IOResource
*) ISAPNP_AllocResource( ISAPNP_NT_IO_RESOURCE
, res
);
864 r2
= (struct ISAPNP_IOResource
*) ISAPNP_AllocResource( ISAPNP_NT_IO_RESOURCE
, res
);
865 r3
= (struct ISAPNP_IOResource
*) ISAPNP_AllocResource( ISAPNP_NT_IO_RESOURCE
, res
);
867 if( rg
== NULL
|| r1
== NULL
|| r2
== NULL
|| r3
== NULL
)
869 ISAPNP_FreeResourceGroup( rg
, res
);
870 ISAPNP_FreeResource( (struct ISAPNP_Resource
*) r1
, res
);
871 ISAPNP_FreeResource( (struct ISAPNP_Resource
*) r2
, res
);
872 ISAPNP_FreeResource( (struct ISAPNP_Resource
*) r3
, res
);
877 r1
->isapnpior_Flags
= ISAPNP_IORESOURCE_FF_FULL_DECODE
;
878 r2
->isapnpior_Flags
= ISAPNP_IORESOURCE_FF_FULL_DECODE
;
879 r3
->isapnpior_Flags
= ISAPNP_IORESOURCE_FF_FULL_DECODE
;
881 r1
->isapnpior_Alignment
= 1;
882 r2
->isapnpior_Alignment
= 1;
883 r3
->isapnpior_Alignment
= 1;
885 r1
->isapnpior_Length
= 4;
886 r2
->isapnpior_Length
= 4;
887 r3
->isapnpior_Length
= 4;
889 r1
->isapnpior_MinBase
= 0x620;
890 r2
->isapnpior_MinBase
= 0xa20;
891 r3
->isapnpior_MinBase
= 0xe20;
893 r1
->isapnpior_MaxBase
= 0x620;
894 r2
->isapnpior_MaxBase
= 0xa20;
895 r3
->isapnpior_MaxBase
= 0xe20;
897 AddTail( (struct List
*) &rg
->isapnprg_Resources
, (struct Node
*) r1
);
898 AddTail( (struct List
*) &rg
->isapnprg_Resources
, (struct Node
*) r2
);
899 AddTail( (struct List
*) &rg
->isapnprg_Resources
, (struct Node
*) r3
);
901 AddTail( (struct List
*) &dev
->isapnpd_Options
->isapnprg_ResourceGroups
,