1 /* $Id: init.c,v 1.23 2001/05/29 10:53:44 lcs Exp $ */
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
,
89 /******************************************************************************
90 ** Globals ********************************************************************
91 ******************************************************************************/
93 struct Device
* TimerBase
= NULL
;
94 /*struct ExecBase* SysBase = NULL;*/
95 /*struct IntuitionBase* IntuitionBase = NULL;*/
96 struct ISAPNPBase
* ISAPNPBase
= NULL
;
97 /*struct UtilityBase* UtilityBase = NULL;*/
99 static struct timerequest
*TimerIO
= NULL
;
101 const char ResName
[] = ISAPNPNAME
;
102 const char IDString
[] = ISAPNPNAME
" " VERS
"\r\n";
104 static const char VersTag
[] =
105 "$VER: " ISAPNPNAME
" " VERS
" ©2001 Martin Blom.\r\n";
107 /******************************************************************************
108 ** Resource initialization ****************************************************
109 ******************************************************************************/
111 struct ISAPNPBase
* ASMCALL
112 initRoutine( REG( d0
, struct ISAPNPBase
* res
),
113 REG( a0
, APTR seglist
),
114 REG( a6
, struct ExecBase
* sysbase
) )
116 D(bug("[ISAPNP] Init\n"));
117 /* SysBase = sysbase;*/
121 // Set up the ISAPNPBase structure
123 res
->m_Library
.lib_Node
.ln_Type
= NT_RESOURCE
;
124 res
->m_Library
.lib_Node
.ln_Name
= (STRPTR
) ResName
;
125 res
->m_Library
.lib_Flags
= LIBF_SUMUSED
| LIBF_CHANGED
;
126 res
->m_Library
.lib_Version
= VERSION
;
127 res
->m_Library
.lib_Revision
= REVISION
;
128 res
->m_Library
.lib_IdString
= (STRPTR
) IDString
;
130 NewList( &res
->m_Cards
);
132 /* Base address, on i386 we don't have any mapping
133 res->m_Base = NULL; */
134 res
->m_RegReadData
= 0x0000;
136 if( ! ISAPNP_ScanCards( res
) )
140 Req( "No PnP ISA cards found." );
141 FreeISAPNPBase( res
);
145 if( ! PatchBrokenCards( res
) )
147 FreeISAPNPBase( res
);
151 struct ISAPNP_Card
* card
;
153 card
= ISAPNP_AllocCard( res
);
157 Req( "Out of memory!" );
158 FreeISAPNPBase( res
);
162 static const char descr
[] = "Non-PnP devices";
165 d
= AllocVec( sizeof( descr
), MEMF_PUBLIC
);
169 CopyMem( (void*) descr
, d
, sizeof( descr
) );
170 card
->isapnpc_Node
.ln_Name
= d
;
173 card
->isapnpc_ID
.isapnpid_Vendor
[ 0 ] = '?';
174 card
->isapnpc_ID
.isapnpid_Vendor
[ 1 ] = '?';
175 card
->isapnpc_ID
.isapnpid_Vendor
[ 2 ] = '?';
176 card
->isapnpc_SerialNumber
= -1;
179 AddHead( &res
->m_Cards
, (struct Node
*) card
);
181 // Let's see if we're to disable any cards or devices etc
182 /* TODO: We will start up early because we can have even ISA PnP video
183 cards, disk controllers, etc. Because of this we can't load
184 any list of disabled devices. Think off what to do with them
185 is really a big TODO.
186 if( ! HandleToolTypes( current_binding.cb_ToolTypes,
189 // Error requester already displayed.
190 FreeISAPNPBase( res );
194 if( ! ISAPNP_ConfigureCards( res
) )
196 // Unable to configure cards
198 Req( "Unable to configure the cards. This is most likely\n"
199 "because of an unresolvable hardware conflict.\n\n"
200 "Use the DISABLE_DEVICE tool type to disable one of\n"
201 "the devices in conflict." );
202 FreeISAPNPBase( res
);
217 /******************************************************************************
218 ** Free all resources from ISAPNPBase *****************************************
219 ******************************************************************************/
222 FreeISAPNPBase( struct ISAPNPBase
* res
)
224 struct ISAPNP_Card
* card
;
226 while( ( card
= (struct ISAPNP_Card
*) RemHead( &res
->m_Cards
) ) )
228 ISAPNP_FreeCard( card
, ISAPNPBase
);
233 /******************************************************************************
234 ** Initialization tables ******************************************************
235 ******************************************************************************/
237 static const APTR funcTable
[] =
243 ISAC_GetInterruptStatus
,
261 ISAPNP_AllocResourceGroup
,
262 ISAPNP_FreeResourceGroup
,
263 ISAPNP_AllocResource
,
267 ISAPNP_ConfigureCards
,
275 ISAPNP_UnlockDevices
,
281 static const APTR InitTable
[4] =
283 (APTR
) sizeof( struct ISAPNPBase
),
289 /******************************************************************************
290 ** OpenLibs *******************************************************************
291 ******************************************************************************/
296 /* Utility Library (libnix depends on it, and our startup-code is not
297 executed when BindDriver LoadSeg()s us!) */
299 /* Intuition Library */
301 IntuitionBase = (struct IntuitionBase*) OpenLibrary( "intuition.library", 37 );
303 if( IntuitionBase == NULL )
308 UtilityBase = (struct UtilityBase *) OpenLibrary( "utility.library", 37 );
310 if( UtilityBase == NULL)
317 TimerIO
= (struct timerequest
*) AllocVec( sizeof(struct timerequest
),
318 MEMF_PUBLIC
| MEMF_CLEAR
);
325 if( OpenDevice( "timer.device",
334 TimerBase
= (struct Device
*) TimerIO
->tr_node
.io_Device
;
340 /******************************************************************************
341 ** CloseLibs *******************************************************************
342 ******************************************************************************/
347 if( TimerIO
!= NULL
)
349 CloseDevice( (struct IORequest
*) TimerIO
);
354 CloseLibrary( (struct Library*) UtilityBase );
355 CloseLibrary( (struct Library*) IntuitionBase );
359 /*IntuitionBase = NULL;
360 UtilityBase = NULL;*/
364 /******************************************************************************
365 ** ReqA ***********************************************************************
366 ******************************************************************************/
369 ReqA( const char* text, APTR args )
371 struct EasyStruct es =
373 sizeof (struct EasyStruct),
375 (STRPTR) ISAPNPNAME " " VERS,
380 if( IntuitionBase != NULL )
382 EasyRequestArgs( NULL, &es, NULL, args );
387 /******************************************************************************
388 ** Handle the tool types ******************************************************
389 ******************************************************************************/
394 if( c >= '0' && c <= '9' )
398 else if( c >= 'A' && c <= 'F' )
402 else if( c >= 'a' && c <= 'f' )
412 // CTL0048 => "CTL\0" 4 8 -1 -1
413 // CTL0048/1236 => "CTL\0" 4 8 1236 -1
414 // CTL0048:0 => "CTL\0" 4 8 -1 0
415 // CTL0048/1236:0 => "CTL\0" 4 8 1236 0
418 ParseID( UBYTE* string,
423 WORD* logical_device )
429 *manufacturer = ISAPNP_MAKE_ID( ToUpper( string[ 0 ] ),
430 ToUpper( string[ 1 ] ),
431 ToUpper( string[ 2 ] ) );
433 *product = ( HexToInt( string[ 3 ] ) << 8 ) |
434 ( HexToInt( string[ 4 ] ) << 4 ) |
435 ( HexToInt( string[ 5 ] ) );
443 *revision = HexToInt( string[ 6 ] );
445 if( *revision == -1 )
452 if( string[ chars ] == '/' )
458 // Not allowed if we don't ask for it
462 conv = StrToLong( string + chars + 1, &ser );
480 if( string[ chars ] == ':' )
484 if( logical_device == NULL )
486 // Not allowed if we don't ask for it
490 conv = StrToLong( string + chars + 1, &dev );
503 if( logical_device != NULL )
505 *logical_device = dev;
508 if( string[ chars ] != 0 && string[ chars ] != ' ' )
518 HandleToolTypes( UBYTE** tool_types,
519 struct ISAPNP_Card* card,
520 struct ISAPNPBase* res )
524 if( Strnicmp( *tool_types, "DISABLE_CARD=", 13 ) == 0 )
531 if( ParseID( *tool_types + 13,
532 &manufacturer, &product, &revision, &serial, NULL ) )
534 struct ISAPNP_Card* card = NULL;
536 while( ( card = ISAPNP_FindCard( card,
543 card->isapnpc_Disabled = TRUE;
548 Req( "Illegal tool type: %s\n", (ULONG) *tool_types );
552 else if( Strnicmp( *tool_types, "DISABLE_DEVICE=", 15 ) == 0 )
560 if( ParseID( *tool_types + 15,
561 &manufacturer, &product, &revision, &serial, &log_dev ) )
565 struct ISAPNP_Device* dev = NULL;
567 while( ( dev = ISAPNP_FindDevice( dev,
573 dev->isapnpd_Disabled = TRUE;
578 struct ISAPNP_Card* card = NULL;
580 while( ( card = ISAPNP_FindCard( card,
587 struct ISAPNP_Device* dev;
589 for( dev = (struct ISAPNP_Device*) card->isapnpc_Devices.lh_Head;
590 dev->isapnpd_Node.ln_Succ != NULL;
591 dev = (struct ISAPNP_Device*) dev->isapnpd_Node.ln_Succ )
593 if( dev->isapnpd_DeviceNumber == (UWORD) log_dev )
595 dev->isapnpd_Disabled = TRUE;
603 Req( "Illegal tool type value: %s\n", (ULONG) *tool_types );
607 else if( Strnicmp( *tool_types, "LEGACY_DEVICE=", 14 ) == 0 )
616 str = *tool_types + 14;
617 conv = ParseID( str, &manufacturer, &product, &revision, NULL, NULL );
623 struct ISAPNP_Device* dev;
624 struct ISAPNP_Identifier* id;
626 dev = ISAPNP_AllocDevice( res );
630 Req( "Out of memory!" );
634 dev->isapnpd_Card = card;
636 id = AllocVec( sizeof( *id ), MEMF_PUBLIC | MEMF_CLEAR );
640 Req( "Out of memory!" );
641 ISAPNP_FreeDevice( dev, res );
645 id->isapnpid_Vendor[ 0 ] = ( manufacturer >> 24 ) & 0xff;
646 id->isapnpid_Vendor[ 1 ] = ( manufacturer >> 16 ) & 0xff;
647 id->isapnpid_Vendor[ 2 ] = ( manufacturer >> 8 ) & 0xff;
648 id->isapnpid_Vendor[ 3 ] = 0;
650 id->isapnpid_ProductID = product;
651 id->isapnpid_Revision = revision;
653 AddTail( (struct List*) &dev->isapnpd_IDs, (struct Node*) id );
655 if( card->isapnpc_Devices.lh_Head->ln_Succ != NULL )
657 dev_num = ( (struct ISAPNP_Device*)
658 card->isapnpc_Devices.lh_TailPred )->isapnpd_DeviceNumber;
662 dev->isapnpd_DeviceNumber = dev_num;
664 AddTail( &card->isapnpc_Devices, (struct Node*) dev );
670 if( Strnicmp( str, "IRQ=", 4 ) == 0 )
674 irq = strtol( str + 4, (char**) &str, 0 );
676 if( irq <= 0 || irq >= 16 )
678 Req( "Invalid IRQ value '%ld' in tooltype line\n"
681 (ULONG) *tool_types );
686 struct ISAPNP_IRQResource* r;
688 r = (struct ISAPNP_IRQResource*)
689 ISAPNP_AllocResource( ISAPNP_NT_IRQ_RESOURCE, res );
693 Req( "Out of memory!" );
697 r->isapnpirqr_IRQMask = 1 << irq;
698 r->isapnpirqr_IRQType = ISAPNP_IRQRESOURCE_ITF_HIGH_EDGE;
700 AddTail( (struct List*) &dev->isapnpd_Options->isapnprg_Resources,
704 else if( Strnicmp( str, "DMA=", 4 ) == 0 )
708 dma = strtol( str + 4, (char**) &str, 0 );
710 if( dma <= 0 || dma >= 8 )
712 Req( "Invalid DMA value '%ld' in tooltype line\n"
715 (ULONG) *tool_types );
720 struct ISAPNP_DMAResource* r;
722 r = (struct ISAPNP_DMAResource*)
723 ISAPNP_AllocResource( ISAPNP_NT_DMA_RESOURCE, res );
727 Req( "Out of memory!" );
731 r->isapnpdmar_ChannelMask = 1 << dma;
732 r->isapnpdmar_Flags = 0;
734 AddTail( (struct List*) &dev->isapnpd_Options->isapnprg_Resources,
738 else if( Strnicmp( str, "IO=", 3 ) == 0 )
743 struct ISAPNP_IOResource* r;
745 base = strtol( str + 3, (char**) &str, 0 );
749 Req( "Length missing from IO value in tooltype line\n"
751 (ULONG) *tool_types );
757 length = strtol( str, (char**) &str, 0 );
759 if( base <= 0 || base >= 0xffff )
761 Req( "Invalid IO base value '%ld' in tooltype line\n"
764 (ULONG) *tool_types );
768 if( length <= 0 || length >= 0xffff )
770 Req( "Invalid IO length value '%ld' in tooltype line\n"
773 (ULONG) *tool_types );
777 r = (struct ISAPNP_IOResource*)
778 ISAPNP_AllocResource( ISAPNP_NT_IO_RESOURCE, res );
782 Req( "Out of memory!" );
786 r->isapnpior_MinBase = base;
787 r->isapnpior_MaxBase = base;
788 r->isapnpior_Length = length;
789 r->isapnpior_Alignment = 1;
791 AddTail( (struct List*) &dev->isapnpd_Options->isapnprg_Resources,
796 Req( "Parse error near '%s'\n"
800 (ULONG) *tool_types );
813 Req( "Illegal tool type: '%s'\n", (ULONG) *tool_types );
819 // Ignore unknown tool types
828 /******************************************************************************
829 ** Fix cards that have broken PnP ROMs ****************************************
830 ******************************************************************************/
833 PatchBrokenCards( struct ISAPNPBase
* res
)
835 struct ISAPNP_Device
* dev
= NULL
;
837 // Patch the wavetable device on SB AWE32 and AWE64
839 while( ( dev
= ISAPNP_FindDevice( dev
,
840 ISAPNP_MAKE_ID('C','T','L'),
845 struct ISAPNP_ResourceGroup
* rg
;
846 struct ISAPNP_IOResource
* r1
;
847 struct ISAPNP_IOResource
* r2
;
848 struct ISAPNP_IOResource
* r3
;
850 // Nuke all dependent options
852 while( ( rg
= (struct ISAPNP_ResourceGroup
*)
853 RemHead( (struct List
*) &dev
->isapnpd_Options
->isapnprg_ResourceGroups
) )
856 ISAPNP_FreeResourceGroup( rg
, res
);
859 rg
= ISAPNP_AllocResourceGroup( ISAPNP_RG_PRI_ACCEPTABLE
, res
);
861 r1
= (struct ISAPNP_IOResource
*) ISAPNP_AllocResource( ISAPNP_NT_IO_RESOURCE
, res
);
862 r2
= (struct ISAPNP_IOResource
*) ISAPNP_AllocResource( ISAPNP_NT_IO_RESOURCE
, res
);
863 r3
= (struct ISAPNP_IOResource
*) ISAPNP_AllocResource( ISAPNP_NT_IO_RESOURCE
, res
);
865 if( rg
== NULL
|| r1
== NULL
|| r2
== NULL
|| r3
== NULL
)
867 ISAPNP_FreeResourceGroup( rg
, res
);
868 ISAPNP_FreeResource( (struct ISAPNP_Resource
*) r1
, res
);
869 ISAPNP_FreeResource( (struct ISAPNP_Resource
*) r2
, res
);
870 ISAPNP_FreeResource( (struct ISAPNP_Resource
*) r3
, res
);
875 r1
->isapnpior_Flags
= ISAPNP_IORESOURCE_FF_FULL_DECODE
;
876 r2
->isapnpior_Flags
= ISAPNP_IORESOURCE_FF_FULL_DECODE
;
877 r3
->isapnpior_Flags
= ISAPNP_IORESOURCE_FF_FULL_DECODE
;
879 r1
->isapnpior_Alignment
= 1;
880 r2
->isapnpior_Alignment
= 1;
881 r3
->isapnpior_Alignment
= 1;
883 r1
->isapnpior_Length
= 4;
884 r2
->isapnpior_Length
= 4;
885 r3
->isapnpior_Length
= 4;
887 r1
->isapnpior_MinBase
= 0x620;
888 r2
->isapnpior_MinBase
= 0xa20;
889 r3
->isapnpior_MinBase
= 0xe20;
891 r1
->isapnpior_MaxBase
= 0x620;
892 r2
->isapnpior_MaxBase
= 0xa20;
893 r3
->isapnpior_MaxBase
= 0xe20;
895 AddTail( (struct List
*) &rg
->isapnprg_Resources
, (struct Node
*) r1
);
896 AddTail( (struct List
*) &rg
->isapnprg_Resources
, (struct Node
*) r2
);
897 AddTail( (struct List
*) &rg
->isapnprg_Resources
, (struct Node
*) r3
);
899 AddTail( (struct List
*) &dev
->isapnpd_Options
->isapnprg_ResourceGroups
,