Minor fixes to comments.
[AROS.git] / rom / isapnp / init.c
blob1dd948f479bb031cfd66f55cb083506575e28379
1 /* $Id$ */
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,
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;*/
121 if(OpenLibs() )
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 ) )
140 // No cards found
142 Req( "No PnP ISA cards found." );
143 FreeISAPNPBase( res );
145 else
147 if( ! PatchBrokenCards( res ) )
149 FreeISAPNPBase( res );
151 else
153 struct ISAPNP_Card* card;
155 card = ISAPNP_AllocCard( res );
157 if( card == NULL )
159 Req( "Out of memory!" );
160 FreeISAPNPBase( res );
162 else
164 static const char descr[] = "Non-PnP devices";
165 char* d;
167 d = AllocVec( sizeof( descr ), MEMF_PUBLIC );
169 if( d != NULL )
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;
180 // Add *first*
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,
189 card, res ) )
191 // Error requester already displayed.
192 FreeISAPNPBase( res );
194 else
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 );
206 else
207 ISAPNPBase = res;
208 /* }*/
214 return ISAPNPBase;
219 /******************************************************************************
220 ** Free all resources from ISAPNPBase *****************************************
221 ******************************************************************************/
223 void
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[] =
241 ISAC_SetMasterInt,
242 ISAC_GetMasterInt,
243 ISAC_SetWaitState,
244 ISAC_GetWaitState,
245 ISAC_GetInterruptStatus,
246 ISAC_GetRegByte,
247 ISAC_SetRegByte,
248 ISAC_GetRegWord,
249 ISAC_SetRegWord,
250 ISAC_GetRegLong,
251 ISAC_SetRegLong,
252 ISAC_ReadByte,
253 ISAC_WriteByte,
254 ISAC_ReadWord,
255 ISAC_WriteWord,
256 ISAC_ReadLong,
257 ISAC_WriteLong,
259 ISAPNP_AllocCard,
260 ISAPNP_FreeCard,
261 ISAPNP_AllocDevice,
262 ISAPNP_FreeDevice,
263 ISAPNP_AllocResourceGroup,
264 ISAPNP_FreeResourceGroup,
265 ISAPNP_AllocResource,
266 ISAPNP_FreeResource,
268 ISAPNP_ScanCards,
269 ISAPNP_ConfigureCards,
271 ISAPNP_FindCard,
272 ISAPNP_FindDevice,
274 ISAPNP_LockCardsA,
275 ISAPNP_UnlockCards,
276 ISAPNP_LockDevicesA,
277 ISAPNP_UnlockDevices,
279 (APTR) -1
283 static const APTR InitTable[4] =
285 (APTR) sizeof( struct ISAPNPBase ),
286 (APTR) &funcTable,
288 (APTR) initRoutine
291 /******************************************************************************
292 ** OpenLibs *******************************************************************
293 ******************************************************************************/
295 BOOL
296 OpenLibs( void )
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 )
307 return FALSE;
310 UtilityBase = (struct UtilityBase *) OpenLibrary( "utility.library", 37 );
312 if( UtilityBase == NULL)
314 return FALSE;
317 /* Timer Device */
319 TimerIO = (struct timerequest *) AllocVec( sizeof(struct timerequest),
320 MEMF_PUBLIC | MEMF_CLEAR );
322 if( TimerIO == NULL)
324 return FALSE;
327 if( OpenDevice( "timer.device",
328 UNIT_MICROHZ,
329 (struct IORequest *)
330 TimerIO,
331 0) != 0 )
333 return FALSE;
336 TimerBase = (struct Device *) TimerIO->tr_node.io_Device;
338 return TRUE;
342 /******************************************************************************
343 ** CloseLibs *******************************************************************
344 ******************************************************************************/
346 void
347 CloseLibs( void )
349 if( TimerIO != NULL )
351 CloseDevice( (struct IORequest *) TimerIO );
354 FreeVec( TimerIO );
356 CloseLibrary( (struct Library*) UtilityBase );
357 CloseLibrary( (struct Library*) IntuitionBase );
359 TimerIO = NULL;
360 TimerBase = NULL;
361 /*IntuitionBase = NULL;
362 UtilityBase = NULL;*/
366 /******************************************************************************
367 ** ReqA ***********************************************************************
368 ******************************************************************************/
370 void
371 ReqA( const char* text, APTR args )
373 struct EasyStruct es =
375 sizeof (struct EasyStruct),
377 (STRPTR) ISAPNPNAME " " VERS,
378 (STRPTR) text,
379 "OK"
382 if( IntuitionBase != NULL )
384 EasyRequestArgs( NULL, &es, NULL, args );
389 /******************************************************************************
390 ** Handle the tool types ******************************************************
391 ******************************************************************************/
393 static int
394 HexToInt( UBYTE c )
396 if( c >= '0' && c <= '9' )
398 return c - '0';
400 else if( c >= 'A' && c <= 'F' )
402 return c - 'A' + 10;
404 else if( c >= 'a' && c <= 'f' )
406 return c - 'a' + 10;
408 else
410 return -1;
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
419 static int
420 ParseID( UBYTE* string,
421 LONG* manufacturer,
422 WORD* product,
423 BYTE* revision,
424 LONG* serial,
425 WORD* logical_device )
427 int chars = 0;
428 LONG ser = -1;
429 LONG dev = -1;
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 ] ) );
440 if( *product == -1 )
442 return 0;
445 *revision = HexToInt( string[ 6 ] );
447 if( *revision == -1 )
449 return 0;
452 chars = 7;
454 if( string[ chars ] == '/' )
456 int conv;
458 if( serial == NULL )
460 // Not allowed if we don't ask for it
461 return NULL;
464 conv = StrToLong( string + chars + 1, &ser );
466 if( conv == -1 )
468 return 0;
470 else
472 chars += conv + 1;
477 if( serial != NULL )
479 *serial = ser;
482 if( string[ chars ] == ':' )
484 int conv;
486 if( logical_device == NULL )
488 // Not allowed if we don't ask for it
489 return NULL;
492 conv = StrToLong( string + chars + 1, &dev );
494 if( conv == -1 )
496 return 0;
498 else
500 chars += conv + 1;
505 if( logical_device != NULL )
507 *logical_device = dev;
510 if( string[ chars ] != 0 && string[ chars ] != ' ' )
512 return 0;
515 return chars;
519 static BOOL
520 HandleToolTypes( UBYTE** tool_types,
521 struct ISAPNP_Card* card,
522 struct ISAPNPBase* res )
524 while( *tool_types )
526 if( Strnicmp( *tool_types, "DISABLE_CARD=", 13 ) == 0 )
528 LONG manufacturer;
529 WORD product;
530 BYTE revision;
531 LONG serial;
533 if( ParseID( *tool_types + 13,
534 &manufacturer, &product, &revision, &serial, NULL ) )
536 struct ISAPNP_Card* card = NULL;
538 while( ( card = ISAPNP_FindCard( card,
539 manufacturer,
540 product,
541 revision,
542 serial,
543 res ) ) != NULL )
545 card->isapnpc_Disabled = TRUE;
548 else
550 Req( "Illegal tool type: %s\n", (ULONG) *tool_types );
551 return FALSE;
554 else if( Strnicmp( *tool_types, "DISABLE_DEVICE=", 15 ) == 0 )
556 LONG manufacturer;
557 WORD product;
558 BYTE revision;
559 LONG serial;
560 WORD log_dev;
562 if( ParseID( *tool_types + 15,
563 &manufacturer, &product, &revision, &serial, &log_dev ) )
565 if( log_dev == -1 )
567 struct ISAPNP_Device* dev = NULL;
569 while( ( dev = ISAPNP_FindDevice( dev,
570 manufacturer,
571 product,
572 revision,
573 res ) ) != NULL )
575 dev->isapnpd_Disabled = TRUE;
578 else
580 struct ISAPNP_Card* card = NULL;
582 while( ( card = ISAPNP_FindCard( card,
583 manufacturer,
584 product,
585 revision,
586 serial,
587 res ) ) != NULL )
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;
603 else
605 Req( "Illegal tool type value: %s\n", (ULONG) *tool_types );
606 return FALSE;
609 else if( Strnicmp( *tool_types, "LEGACY_DEVICE=", 14 ) == 0 )
611 UBYTE* str;
612 int conv;
613 LONG manufacturer;
614 WORD product;
615 BYTE revision;
616 UWORD dev_num = 0;
618 str = *tool_types + 14;
619 conv = ParseID( str, &manufacturer, &product, &revision, NULL, NULL );
621 str += conv;
623 if( conv != 0 )
625 struct ISAPNP_Device* dev;
626 struct ISAPNP_Identifier* id;
628 dev = ISAPNP_AllocDevice( res );
630 if( dev == NULL )
632 Req( "Out of memory!" );
633 return FALSE;
636 dev->isapnpd_Card = card;
638 id = AllocVec( sizeof( *id ), MEMF_PUBLIC | MEMF_CLEAR );
640 if( id == NULL )
642 Req( "Out of memory!" );
643 ISAPNP_FreeDevice( dev, res );
644 return FALSE;
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;
661 ++dev_num;
664 dev->isapnpd_DeviceNumber = dev_num;
666 AddTail( &card->isapnpc_Devices, (struct Node*) dev );
668 while( *str != 0 )
670 if( *str != ' ' )
672 if( Strnicmp( str, "IRQ=", 4 ) == 0 )
674 int irq;
676 irq = strtol( str + 4, (char**) &str, 0 );
678 if( irq <= 0 || irq >= 16 )
680 Req( "Invalid IRQ value '%ld' in tooltype line\n"
681 "'%s'",
682 irq,
683 (ULONG) *tool_types );
684 return FALSE;
686 else
688 struct ISAPNP_IRQResource* r;
690 r = (struct ISAPNP_IRQResource*)
691 ISAPNP_AllocResource( ISAPNP_NT_IRQ_RESOURCE, res );
693 if( r == NULL )
695 Req( "Out of memory!" );
696 return FALSE;
699 r->isapnpirqr_IRQMask = 1 << irq;
700 r->isapnpirqr_IRQType = ISAPNP_IRQRESOURCE_ITF_HIGH_EDGE;
702 AddTail( (struct List*) &dev->isapnpd_Options->isapnprg_Resources,
703 (struct Node*) r );
706 else if( Strnicmp( str, "DMA=", 4 ) == 0 )
708 int dma;
710 dma = strtol( str + 4, (char**) &str, 0 );
712 if( dma <= 0 || dma >= 8 )
714 Req( "Invalid DMA value '%ld' in tooltype line\n"
715 "'%s'",
716 dma,
717 (ULONG) *tool_types );
718 return FALSE;
720 else
722 struct ISAPNP_DMAResource* r;
724 r = (struct ISAPNP_DMAResource*)
725 ISAPNP_AllocResource( ISAPNP_NT_DMA_RESOURCE, res );
727 if( r == NULL )
729 Req( "Out of memory!" );
730 return FALSE;
733 r->isapnpdmar_ChannelMask = 1 << dma;
734 r->isapnpdmar_Flags = 0;
736 AddTail( (struct List*) &dev->isapnpd_Options->isapnprg_Resources,
737 (struct Node*) r );
740 else if( Strnicmp( str, "IO=", 3 ) == 0 )
742 int base;
743 int length;
745 struct ISAPNP_IOResource* r;
747 base = strtol( str + 3, (char**) &str, 0 );
749 if( *str != '/' )
751 Req( "Length missing from IO value in tooltype line\n"
752 "'%s'",
753 (ULONG) *tool_types );
754 return FALSE;
757 ++str;
759 length = strtol( str, (char**) &str, 0 );
761 if( base <= 0 || base >= 0xffff )
763 Req( "Invalid IO base value '%ld' in tooltype line\n"
764 "'%s'",
765 base,
766 (ULONG) *tool_types );
767 return FALSE;
770 if( length <= 0 || length >= 0xffff )
772 Req( "Invalid IO length value '%ld' in tooltype line\n"
773 "'%s'",
774 length,
775 (ULONG) *tool_types );
776 return FALSE;
779 r = (struct ISAPNP_IOResource*)
780 ISAPNP_AllocResource( ISAPNP_NT_IO_RESOURCE, res );
782 if( r == NULL )
784 Req( "Out of memory!" );
785 return FALSE;
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,
794 (struct Node*) r );
796 else
798 Req( "Parse error near '%s'\n"
799 "in tooltype line\n"
800 "'%s'",
801 (ULONG) str,
802 (ULONG) *tool_types );
803 return FALSE;
807 if( *str )
809 ++str;
813 else
815 Req( "Illegal tool type: '%s'\n", (ULONG) *tool_types );
816 return FALSE;
819 else
821 // Ignore unknown tool types
824 ++tool_types;
827 return TRUE;
830 /******************************************************************************
831 ** Fix cards that have broken PnP ROMs ****************************************
832 ******************************************************************************/
834 static BOOL
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'),
843 0x002,
845 res ) ) != NULL )
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 ) )
856 != NULL )
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 );
874 return FALSE;
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,
902 (struct Node*) rg );
905 return TRUE;