define __KERNEL_STRICT_NAMES to avoid inclusion of kernel types on systems that carry...
[cake.git] / rom / isapnp / init.c
blobaf2d0a2c80a28e62e3add4a72e15103344d29319
1 /* $Id: init.c,v 1.23 2001/05/29 10:53:44 lcs Exp $ */
3 /*
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,
21 MA 02139, USA.
24 #define DEBUG 1
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>*/
36 #include <stdlib.h>
38 #include <resources/isapnp.h>
39 #include "isapnp_private.h"
40 #include "version.h"
42 #include "controller.h"
43 #include "devices.h"
44 #include "init.h"
45 #include "pnp.h"
46 #include "pnp_structs.h"
49 static BOOL
50 HandleToolTypes( UBYTE** tool_types,
51 struct ISAPNP_Card* card,
52 struct ISAPNPBase* res );
54 static BOOL
55 PatchBrokenCards( struct ISAPNPBase* res );
57 void
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 =
76 RTC_MATCHWORD,
77 (struct Resident *) &RomTag,
78 (struct Resident *) &LIBEND,
79 RTF_AUTOINIT|RTF_COLDSTART,
80 VERSION,
81 NT_RESOURCE,
82 12, /* priority */
83 (BYTE *) ResName,
84 (BYTE *) IDString,
85 (APTR) &InitTable
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;*/
119 if(OpenLibs() )
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 ) )
138 // No cards found
140 Req( "No PnP ISA cards found." );
141 FreeISAPNPBase( res );
143 else
145 if( ! PatchBrokenCards( res ) )
147 FreeISAPNPBase( res );
149 else
151 struct ISAPNP_Card* card;
153 card = ISAPNP_AllocCard( res );
155 if( card == NULL )
157 Req( "Out of memory!" );
158 FreeISAPNPBase( res );
160 else
162 static const char descr[] = "Non-PnP devices";
163 char* d;
165 d = AllocVec( sizeof( descr ), MEMF_PUBLIC );
167 if( d != NULL )
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;
178 // Add *first*
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,
187 card, res ) )
189 // Error requester already displayed.
190 FreeISAPNPBase( res );
192 else
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 );
204 else
205 ISAPNPBase = res;
206 /* }*/
212 return ISAPNPBase;
217 /******************************************************************************
218 ** Free all resources from ISAPNPBase *****************************************
219 ******************************************************************************/
221 void
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[] =
239 ISAC_SetMasterInt,
240 ISAC_GetMasterInt,
241 ISAC_SetWaitState,
242 ISAC_GetWaitState,
243 ISAC_GetInterruptStatus,
244 ISAC_GetRegByte,
245 ISAC_SetRegByte,
246 ISAC_GetRegWord,
247 ISAC_SetRegWord,
248 ISAC_GetRegLong,
249 ISAC_SetRegLong,
250 ISAC_ReadByte,
251 ISAC_WriteByte,
252 ISAC_ReadWord,
253 ISAC_WriteWord,
254 ISAC_ReadLong,
255 ISAC_WriteLong,
257 ISAPNP_AllocCard,
258 ISAPNP_FreeCard,
259 ISAPNP_AllocDevice,
260 ISAPNP_FreeDevice,
261 ISAPNP_AllocResourceGroup,
262 ISAPNP_FreeResourceGroup,
263 ISAPNP_AllocResource,
264 ISAPNP_FreeResource,
266 ISAPNP_ScanCards,
267 ISAPNP_ConfigureCards,
269 ISAPNP_FindCard,
270 ISAPNP_FindDevice,
272 ISAPNP_LockCardsA,
273 ISAPNP_UnlockCards,
274 ISAPNP_LockDevicesA,
275 ISAPNP_UnlockDevices,
277 (APTR) -1
281 static const APTR InitTable[4] =
283 (APTR) sizeof( struct ISAPNPBase ),
284 (APTR) &funcTable,
286 (APTR) initRoutine
289 /******************************************************************************
290 ** OpenLibs *******************************************************************
291 ******************************************************************************/
293 BOOL
294 OpenLibs( void )
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 )
305 return FALSE;
308 UtilityBase = (struct UtilityBase *) OpenLibrary( "utility.library", 37 );
310 if( UtilityBase == NULL)
312 return FALSE;
315 /* Timer Device */
317 TimerIO = (struct timerequest *) AllocVec( sizeof(struct timerequest),
318 MEMF_PUBLIC | MEMF_CLEAR );
320 if( TimerIO == NULL)
322 return FALSE;
325 if( OpenDevice( "timer.device",
326 UNIT_MICROHZ,
327 (struct IORequest *)
328 TimerIO,
329 0) != 0 )
331 return FALSE;
334 TimerBase = (struct Device *) TimerIO->tr_node.io_Device;
336 return TRUE;
340 /******************************************************************************
341 ** CloseLibs *******************************************************************
342 ******************************************************************************/
344 void
345 CloseLibs( void )
347 if( TimerIO != NULL )
349 CloseDevice( (struct IORequest *) TimerIO );
352 FreeVec( TimerIO );
354 CloseLibrary( (struct Library*) UtilityBase );
355 CloseLibrary( (struct Library*) IntuitionBase );
357 TimerIO = NULL;
358 TimerBase = NULL;
359 /*IntuitionBase = NULL;
360 UtilityBase = NULL;*/
364 /******************************************************************************
365 ** ReqA ***********************************************************************
366 ******************************************************************************/
368 void
369 ReqA( const char* text, APTR args )
371 struct EasyStruct es =
373 sizeof (struct EasyStruct),
375 (STRPTR) ISAPNPNAME " " VERS,
376 (STRPTR) text,
377 "OK"
380 if( IntuitionBase != NULL )
382 EasyRequestArgs( NULL, &es, NULL, args );
387 /******************************************************************************
388 ** Handle the tool types ******************************************************
389 ******************************************************************************/
391 static int
392 HexToInt( UBYTE c )
394 if( c >= '0' && c <= '9' )
396 return c - '0';
398 else if( c >= 'A' && c <= 'F' )
400 return c - 'A' + 10;
402 else if( c >= 'a' && c <= 'f' )
404 return c - 'a' + 10;
406 else
408 return -1;
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
417 static int
418 ParseID( UBYTE* string,
419 LONG* manufacturer,
420 WORD* product,
421 BYTE* revision,
422 LONG* serial,
423 WORD* logical_device )
425 int chars = 0;
426 LONG ser = -1;
427 LONG dev = -1;
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 ] ) );
438 if( *product == -1 )
440 return 0;
443 *revision = HexToInt( string[ 6 ] );
445 if( *revision == -1 )
447 return 0;
450 chars = 7;
452 if( string[ chars ] == '/' )
454 int conv;
456 if( serial == NULL )
458 // Not allowed if we don't ask for it
459 return NULL;
462 conv = StrToLong( string + chars + 1, &ser );
464 if( conv == -1 )
466 return 0;
468 else
470 chars += conv + 1;
475 if( serial != NULL )
477 *serial = ser;
480 if( string[ chars ] == ':' )
482 int conv;
484 if( logical_device == NULL )
486 // Not allowed if we don't ask for it
487 return NULL;
490 conv = StrToLong( string + chars + 1, &dev );
492 if( conv == -1 )
494 return 0;
496 else
498 chars += conv + 1;
503 if( logical_device != NULL )
505 *logical_device = dev;
508 if( string[ chars ] != 0 && string[ chars ] != ' ' )
510 return 0;
513 return chars;
517 static BOOL
518 HandleToolTypes( UBYTE** tool_types,
519 struct ISAPNP_Card* card,
520 struct ISAPNPBase* res )
522 while( *tool_types )
524 if( Strnicmp( *tool_types, "DISABLE_CARD=", 13 ) == 0 )
526 LONG manufacturer;
527 WORD product;
528 BYTE revision;
529 LONG serial;
531 if( ParseID( *tool_types + 13,
532 &manufacturer, &product, &revision, &serial, NULL ) )
534 struct ISAPNP_Card* card = NULL;
536 while( ( card = ISAPNP_FindCard( card,
537 manufacturer,
538 product,
539 revision,
540 serial,
541 res ) ) != NULL )
543 card->isapnpc_Disabled = TRUE;
546 else
548 Req( "Illegal tool type: %s\n", (ULONG) *tool_types );
549 return FALSE;
552 else if( Strnicmp( *tool_types, "DISABLE_DEVICE=", 15 ) == 0 )
554 LONG manufacturer;
555 WORD product;
556 BYTE revision;
557 LONG serial;
558 WORD log_dev;
560 if( ParseID( *tool_types + 15,
561 &manufacturer, &product, &revision, &serial, &log_dev ) )
563 if( log_dev == -1 )
565 struct ISAPNP_Device* dev = NULL;
567 while( ( dev = ISAPNP_FindDevice( dev,
568 manufacturer,
569 product,
570 revision,
571 res ) ) != NULL )
573 dev->isapnpd_Disabled = TRUE;
576 else
578 struct ISAPNP_Card* card = NULL;
580 while( ( card = ISAPNP_FindCard( card,
581 manufacturer,
582 product,
583 revision,
584 serial,
585 res ) ) != NULL )
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;
601 else
603 Req( "Illegal tool type value: %s\n", (ULONG) *tool_types );
604 return FALSE;
607 else if( Strnicmp( *tool_types, "LEGACY_DEVICE=", 14 ) == 0 )
609 UBYTE* str;
610 int conv;
611 LONG manufacturer;
612 WORD product;
613 BYTE revision;
614 UWORD dev_num = 0;
616 str = *tool_types + 14;
617 conv = ParseID( str, &manufacturer, &product, &revision, NULL, NULL );
619 str += conv;
621 if( conv != 0 )
623 struct ISAPNP_Device* dev;
624 struct ISAPNP_Identifier* id;
626 dev = ISAPNP_AllocDevice( res );
628 if( dev == NULL )
630 Req( "Out of memory!" );
631 return FALSE;
634 dev->isapnpd_Card = card;
636 id = AllocVec( sizeof( *id ), MEMF_PUBLIC | MEMF_CLEAR );
638 if( id == NULL )
640 Req( "Out of memory!" );
641 ISAPNP_FreeDevice( dev, res );
642 return FALSE;
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;
659 ++dev_num;
662 dev->isapnpd_DeviceNumber = dev_num;
664 AddTail( &card->isapnpc_Devices, (struct Node*) dev );
666 while( *str != 0 )
668 if( *str != ' ' )
670 if( Strnicmp( str, "IRQ=", 4 ) == 0 )
672 int irq;
674 irq = strtol( str + 4, (char**) &str, 0 );
676 if( irq <= 0 || irq >= 16 )
678 Req( "Invalid IRQ value '%ld' in tooltype line\n"
679 "'%s'",
680 irq,
681 (ULONG) *tool_types );
682 return FALSE;
684 else
686 struct ISAPNP_IRQResource* r;
688 r = (struct ISAPNP_IRQResource*)
689 ISAPNP_AllocResource( ISAPNP_NT_IRQ_RESOURCE, res );
691 if( r == NULL )
693 Req( "Out of memory!" );
694 return FALSE;
697 r->isapnpirqr_IRQMask = 1 << irq;
698 r->isapnpirqr_IRQType = ISAPNP_IRQRESOURCE_ITF_HIGH_EDGE;
700 AddTail( (struct List*) &dev->isapnpd_Options->isapnprg_Resources,
701 (struct Node*) r );
704 else if( Strnicmp( str, "DMA=", 4 ) == 0 )
706 int dma;
708 dma = strtol( str + 4, (char**) &str, 0 );
710 if( dma <= 0 || dma >= 8 )
712 Req( "Invalid DMA value '%ld' in tooltype line\n"
713 "'%s'",
714 dma,
715 (ULONG) *tool_types );
716 return FALSE;
718 else
720 struct ISAPNP_DMAResource* r;
722 r = (struct ISAPNP_DMAResource*)
723 ISAPNP_AllocResource( ISAPNP_NT_DMA_RESOURCE, res );
725 if( r == NULL )
727 Req( "Out of memory!" );
728 return FALSE;
731 r->isapnpdmar_ChannelMask = 1 << dma;
732 r->isapnpdmar_Flags = 0;
734 AddTail( (struct List*) &dev->isapnpd_Options->isapnprg_Resources,
735 (struct Node*) r );
738 else if( Strnicmp( str, "IO=", 3 ) == 0 )
740 int base;
741 int length;
743 struct ISAPNP_IOResource* r;
745 base = strtol( str + 3, (char**) &str, 0 );
747 if( *str != '/' )
749 Req( "Length missing from IO value in tooltype line\n"
750 "'%s'",
751 (ULONG) *tool_types );
752 return FALSE;
755 ++str;
757 length = strtol( str, (char**) &str, 0 );
759 if( base <= 0 || base >= 0xffff )
761 Req( "Invalid IO base value '%ld' in tooltype line\n"
762 "'%s'",
763 base,
764 (ULONG) *tool_types );
765 return FALSE;
768 if( length <= 0 || length >= 0xffff )
770 Req( "Invalid IO length value '%ld' in tooltype line\n"
771 "'%s'",
772 length,
773 (ULONG) *tool_types );
774 return FALSE;
777 r = (struct ISAPNP_IOResource*)
778 ISAPNP_AllocResource( ISAPNP_NT_IO_RESOURCE, res );
780 if( r == NULL )
782 Req( "Out of memory!" );
783 return FALSE;
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,
792 (struct Node*) r );
794 else
796 Req( "Parse error near '%s'\n"
797 "in tooltype line\n"
798 "'%s'",
799 (ULONG) str,
800 (ULONG) *tool_types );
801 return FALSE;
805 if( *str )
807 ++str;
811 else
813 Req( "Illegal tool type: '%s'\n", (ULONG) *tool_types );
814 return FALSE;
817 else
819 // Ignore unknown tool types
822 ++tool_types;
825 return TRUE;
828 /******************************************************************************
829 ** Fix cards that have broken PnP ROMs ****************************************
830 ******************************************************************************/
832 static BOOL
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'),
841 0x002,
843 res ) ) != NULL )
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 ) )
854 != NULL )
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 );
872 return FALSE;
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,
900 (struct Node*) rg );
903 return TRUE;