2 Copyright © 2011, The AROS Development Team. All rights reserved.
9 Copyright (C) 1999 David A. Hinds
10 Copyright (C) 2001,2002 Neil Cafferkey
12 Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
17 #include <exec/memory.h>
18 #include <utility/tagitem.h>
20 #include <proto/exec.h>
21 #include <proto/utility.h>
22 #include <proto/pccard.h>
24 #include "pccard_intern.h"
26 #define MAX_TUPLE PCCARD_TPL_ORG
28 #define MAX_POWER_COUNT 3
29 #define POWER_PARAM_COUNT 7
30 #define TIMING_COUNT 3
32 #define MAX_REGION_COUNT 4
35 static const struct TagItem device_tag_list
[]=
37 {PCCARD_RegionCount
,0},
38 {PCCARD_RegionLists
,0},
43 static const struct TagItem longlinkcb_tag_list
[]=
49 static const struct TagItem configcb_tag_list
[]=
55 static const struct TagItem cftableentrycb_tag_list
[]=
61 static const struct TagItem longlinkmfc_tag_list
[]=
67 static const struct TagItem bar_tag_list
[]=
73 static const struct TagItem checksum_tag_list
[]=
79 static const struct TagItem longlinka_tag_list
[]=
85 static const struct TagItem longlinkc_tag_list
[]=
91 static const struct TagItem linktarget_tag_list
[]=
97 static const struct TagItem nolink_tag_list
[]=
103 static const struct TagItem vers1_tag_list
[]=
105 {PCCARD_MajorVersion
,0},
106 {PCCARD_MinorVersion
,0},
107 {PCCARD_InfoStringCount
,0},
108 {PCCARD_InfoStrings
,0},
113 static const struct TagItem altstr_tag_list
[]=
119 static const struct TagItem jedecc_tag_list
[]=
125 static const struct TagItem jedeca_tag_list
[]=
131 static const struct TagItem config_tag_list
[]=
133 {PCCARD_RegisterBase
,0},
134 {PCCARD_ModeCount
,0},
139 static const struct TagItem cftableentry_tag_list
[]=
143 {PCCARD_VCCPowerTags
,0},
144 {PCCARD_VPP1PowerTags
,0},
145 {PCCARD_VPP2PowerTags
,0},
146 {PCCARD_WaitTimingTags
,0},
147 {PCCARD_ReadyTimingTags
,0},
148 {PCCARD_ReservedTimingTags
,0},
150 {PCCARD_IOLineCount
,0},
151 {PCCARD_IOWinCount
,0},
152 {PCCARD_IOWinBases
,0},
153 {PCCARD_IOWinLengths
,0},
156 {PCCARD_MemWinCount
,0},
157 {PCCARD_MemWinBases
,0},
158 {PCCARD_MemWinHostBases
,0},
159 {PCCARD_MemWinLengths
,0},
164 static const struct TagItem deviceoc_tag_list
[]=
170 static const struct TagItem deviceoa_tag_list
[]=
176 static const struct TagItem devicegeo_tag_list
[]=
182 static const struct TagItem devicegeoa_tag_list
[]=
188 static const struct TagItem manfid_tag_list
[]=
196 static const struct TagItem funcid_tag_list
[]=
204 static const struct TagItem funce_tag_list
[]=
210 static const struct TagItem swil_tag_list
[]=
216 static const struct TagItem vers2_tag_list
[]=
222 static const struct TagItem format_tag_list
[]=
228 static const struct TagItem geometry_tag_list
[]=
234 static const struct TagItem byteorder_tag_list
[]=
240 static const struct TagItem date_tag_list
[]=
246 static const struct TagItem battery_tag_list
[]=
252 static const struct TagItem org_tag_list
[]=
258 static const struct TagItem
*const tag_lists
[]=
265 cftableentrycb_tag_list
,
266 longlinkmfc_tag_list
,
287 cftableentry_tag_list
,
334 static const struct TagItem power_tag_list
[]=
336 {PCCARD_NominalVoltage
,0},
337 {PCCARD_MinVoltage
,0},
338 {PCCARD_MaxVoltage
,0},
339 {PCCARD_StaticCurrent
,0},
340 {PCCARD_AverageCurrent
,0},
341 {PCCARD_PeakCurrent
,0},
342 {PCCARD_DownCurrent
,0},
348 static const struct TagItem timing_tag_list
[]=
356 static const struct TagItem region_tag_list
[]=
367 static const Tag sublist_tags
[]=
370 PCCARD_VPP1PowerTags
,
371 PCCARD_VPP2PowerTags
,
372 PCCARD_WaitTimingTags
,
373 PCCARD_ReadyTimingTags
,
374 PCCARD_ReservedTimingTags
,
379 static const Tag array_tags
[]=
384 PCCARD_MemWinHostBases
,
385 PCCARD_MemWinLengths
,
390 static const Tag string_array_tags
[]=
396 #if !defined(__AROS__)
397 static const Tag sublist_array_tags
[]=
404 static const UBYTE region_speeds
[]=
410 static const UBYTE mantissas
[]=
412 10,12,13,15,20,25,30,35,40,45,50,55,60,70,80,90
416 static const ULONG exponents
[]=
418 1,10,100,1000,10000,100000,1000000,10000000
422 /* Convert an extended speed byte to a time in nanoseconds */
423 #define SPEED_CVT(v) \
424 (mantissas[(((v)>>3)&0xf)-1]*exponents[(v)&0x7]/10)
427 /* Convert a power byte to a current in 0.1 microamps */
428 #define POWER_CVT(v) \
429 (mantissas[((v)>>3)&0xf]*exponents[(v)&0x7]/10)
432 #define POWER_SCALE(v) (exponents[(v)&0x7])
436 static BOOL
ParseDevice(const UBYTE
*tuple
,struct TagItem
*tag_list
,
437 struct PCCardBase
*base
);
438 static BOOL
ParseVers1(const UBYTE
*tuple
,struct TagItem
*tag_list
,
439 struct PCCardBase
*base
);
440 static BOOL
ParseConfig(const UBYTE
*tuple
,struct TagItem
*tag_list
,
441 struct PCCardBase
*base
);
442 static BOOL
ParseCfTableEntry(const UBYTE
*tuple
,struct TagItem
*tag_list
,
443 struct PCCardBase
*base
);
444 static BOOL
ParseManfID(const UBYTE
*tuple
,struct TagItem
*tag_list
,
445 struct PCCardBase
*base
);
446 static BOOL
ParseFuncID(const UBYTE
*tuple
,struct TagItem
*tag_list
,
447 struct PCCardBase
*base
);
448 static BOOL
ParseStrings(const UBYTE
*tuple
,struct TagItem
*tag_list
,
449 struct PCCardBase
*base
);
450 static ULONG
StrLen(const TEXT
*s
);
454 /****** pccard.library/PCCard_GetTupleInfo *********************************
457 * PCCard_GetTupleInfo -- Parse a CIS tuple.
460 * tag_list = PCCard_GetTupleInfo(tuple)
463 * struct TagItem *PCCard_GetTupleInfo(UBYTE *);
466 * Reads the information held within a CIS tuple and presents it in the
467 * form of a tag list. The returned tag list is read-only and must be
468 * relinquished via PCCard_FreeTupleInfo().
470 * The tags available for each tuple type are described below.
472 * PCCARD_TPL_DEVICE/PCCARD_TPL_DEVICEA:
473 * PCCARD_RegionCount - The number of memory regions in either
474 * common memory (PCCARD_TPL_DEVICE) or attribute memory
475 * (PCCARD_TPL_DEVICEA).
476 * PCCARD_RegionLists - An array of tag lists, one for each memory
477 * region. Each sub-list may have the following tags:
478 * PCCARD_Flags - Currently only PCCARD_REGIONF_WP (write
479 * protection) is defined.
480 * PCCARD_Type - Region's memory type.
481 * PCCARD_Speed - Speed in nanoseconds.
482 * PCCARD_Base - Offset of start of region.
483 * PCCARD_Length - Length of region.
486 * PCCARD_MajorVersion - ?
487 * PCCARD_MinorVersion - ?
488 * PCCARD_InfoStringCount - Number of strings available.
489 * PCCARD_InfoStrings - An array of card information strings.
492 * PCCARD_RegisterBase - Offset within attribute memory of
493 * configuration registers.
494 * PCCARD_ModeCount - Number of operating modes.
496 * PCCARD_TPL_CFTABLEENTRY:
497 * PCCARD_ModeNo - Value to write to the COR to select this mode.
498 * PCCARD_Flags - See pccard.h for details.
499 * PCCARD_VCCPowerTags - Tag list for VCC power. The following tags
500 * may be present (voltages in 10-uV units, currents in 100-nA
502 * PCCARD_NominalVoltage - Nominal supply voltage.
503 * PCCARD_MinVoltage - Maximum supply voltage.
504 * PCCARD_MaxVoltage - Minimum supply voltage.
505 * PCCARD_StaticCurrent - Continuous supply current required.
506 * PCCARD_AverageCurrent - Maximum current averaged over one
508 * PCCARD_PeakCurrent - Maximum current averaged over 10 ms.
509 * PCCARD_DownCurrent - Current required in power-down mode.
510 * PCCARD_Flags - See pccard.h for details.
511 * PCCARD_VPP1PowerTags - Tag list for VPP1 power. Uses the same
512 * tags as PCCARD_VCCPowerTags.
513 * PCCARD_VPP2PowerTags - Tag list for VPP2 power. Uses the same
514 * tags as PCCARD_VCCPowerTags.
515 * PCCARD_WaitTimingTags - Tag list for wait timing. The following
516 * tags may be present:
517 * PCCARD_Value - Base value/mantissa (in nanoseconds).
518 * PCCARD_Scale - Multiplier/exponent to be applied to
520 * PCCARD_ReadyTimingTags - Tag list for ready timing. Uses the
521 * same tags as PCCARD_WaitTimingTags.
522 * PCCARD_ReservedTimingTags - Tag list for reserved timing. Uses
523 * the same tags as PCCARD_WaitTimingTags.
524 * PCCARD_IOFlags - See pccard.h for details.
525 * PCCARD_IOLineCount - Number of IO lines decoded by the card.
526 * PCCARD_IOWinCount - Number of IO windows.
527 * PCCARD_IOWinBases - An array of ULONGs giving the window bases
528 * as offsets into the card's IO space.
529 * PCCARD_IOWinLengths - An array of ULONGs giving the lengths of
531 * PCCARD_IRQFlags - See pccard.h for details.
532 * PCCARD_IRQMask - Interrupt numbers that may be used.
533 * PCCARD_MemWinCount - Number of memory windows.
534 * PCCARD_MemWinBases - An array of ULONGs giving the window bases
535 * as offsets into the card's memory space.
536 * PCCARD_MemWinHostBases - An array of ULONGs giving the window
537 * bases as offsets into the host memory space.
538 * PCCARD_MemWinLengths - An array of ULONGs giving the lengths of
539 * the memory windows.
542 * PCCARD_Maker - The card's manufacturer ID.
543 * PCCARD_Product - The card's product ID relative to its
547 * PCCARD_Type - The card's function, eg. network or memory.
548 * PCCARD_Flags - Card initialisation flags.
551 * tuple - Pointer to the tuple.
554 * tag_list - A tag list containing the tuple's properties.
563 * PCCard_FreeTupleInfo()
565 ****************************************************************************
569 AROS_LH1(struct TagItem
*, PCCard_GetTupleInfo
,
570 AROS_LHA(const UBYTE
*, tuple
, A0
),
571 struct PCCardBase
*, PCCardBase
, 5, PCCard
)
576 struct TagItem
*tag_list
=NULL
;
580 if(tuple_type
<=MAX_TUPLE
)
581 tag_list
=CloneTagItems(tag_lists
[tuple_type
]);
589 case PCCARD_TPL_DEVICE
:
590 case PCCARD_TPL_DEVICEA
:
591 ParseDevice(tuple
,tag_list
,PCCardBase
);
593 case PCCARD_TPL_VERS1
:
594 ParseVers1(tuple
,tag_list
,PCCardBase
);
596 case PCCARD_TPL_CONFIG
:
597 ParseConfig(tuple
,tag_list
,PCCardBase
);
599 case PCCARD_TPL_CFTABLEENTRY
:
600 ParseCfTableEntry(tuple
,tag_list
,PCCardBase
);
602 case PCCARD_TPL_MANFID
:
603 ParseManfID(tuple
,tag_list
,PCCardBase
);
605 case PCCARD_TPL_FUNCID
:
606 ParseFuncID(tuple
,tag_list
,PCCardBase
);
620 static BOOL
ParseDevice(const UBYTE
*tuple
,struct TagItem
*tag_list
,
621 struct PCCardBase
*base
)
624 struct TagItem
**lists
,*sub_tag_list
,*sub_tag
;
625 ULONG flags
=0,speed
=0,region_base
=0,region_length
;
628 /* Allocate tag-list array */
632 lists
=AllocVec(sizeof(struct TagItem
*)*(MAX_REGION_COUNT
+1),
633 MEMF_PUBLIC
|MEMF_CLEAR
);
637 /* Get region info */
642 for(region_count
=0;*tuple
!=0xff;region_count
++)
644 sub_tag_list
=CloneTagItems(region_tag_list
);
645 if(sub_tag_list
==NULL
)
650 lists
[region_count
]=sub_tag_list
;
652 /* Get flags and region type */
655 flags
=PCCARD_REGIONF_WP
;
656 NextTagItem(&sub_tag_list
)->ti_Data
=flags
;
657 NextTagItem(&sub_tag_list
)->ti_Data
=*tuple
>>4;
661 sub_tag
=NextTagItem(&sub_tag_list
);
665 sub_tag
->ti_Tag
=TAG_IGNORE
;
669 speed
=SPEED_CVT(*tuple
);
672 speed
=region_speeds
[*tuple
&0x7];
674 sub_tag
->ti_Data
=speed
;
677 /* Get base and length */
679 NextTagItem(&sub_tag_list
)->ti_Data
=region_base
;
680 region_length
=((*tuple
>>3)+1)*(512<<((*tuple
&0x7)*2));
681 NextTagItem(&sub_tag_list
)->ti_Data
=region_length
;
682 region_base
+=region_length
;
687 NextTagItem(&tag_list
)->ti_Data
=region_count
;
695 static BOOL
ParseVers1(const UBYTE
*tuple
,struct TagItem
*tag_list
,
696 struct PCCardBase
*base
)
698 /* Get version no. */
701 NextTagItem(&tag_list
)->ti_Data
=*tuple
++;
702 NextTagItem(&tag_list
)->ti_Data
=*tuple
++;
704 /* Get info strings */
706 return ParseStrings(tuple
,tag_list
,base
);
711 static BOOL
ParseConfig(const UBYTE
*tuple
,struct TagItem
*tag_list
,
712 struct PCCardBase
*base
)
719 base_size
=(*p
++)&0x3;
721 FindTagItem(PCCARD_ModeCount
,tag_list
)->ti_Data
=*(p
++);
723 for(q
=p
+base_size
;q
>=p
;q
--)
729 FindTagItem(PCCARD_RegisterBase
,tag_list
)->ti_Data
=reg_base
;
736 static BOOL
ParseCfTableEntry(const UBYTE
*tuple
,struct TagItem
*tag_list
,
737 struct PCCardBase
*base
)
739 ULONG n
,flags
=0,scale
,*win_bases
= NULL
,*host_bases
= NULL
,*win_lengths
= NULL
;
740 UBYTE base_size
,length_size
,i
=0,j
,present
,power_count
,features
,
741 timing_scales
[TIMING_COUNT
],win_count
=0,sub_flags
=0,sizes
=0,mask
=0;
743 struct TagItem
*tag
,*temp_tag
=tag_list
,*temp_sub_tag
,*sub_tag
,
750 NextTagItem(&temp_tag
)->ti_Data
=*p
&0x3f;
753 flags
|=PCCARD_CFTABLEF_DEFAULT
;
757 NextTagItem(&temp_tag
)->ti_Data
=flags
;
762 /* Parse power data */
764 for(power_count
=features
&0x3;i
<MAX_POWER_COUNT
;i
++)
766 tag
=NextTagItem(&temp_tag
);
770 temp_sub_tag
=sub_tag_list
=CloneTagItems(power_tag_list
);
771 if(sub_tag_list
==NULL
)
778 for(j
=0;j
<POWER_PARAM_COUNT
;j
++)
780 sub_tag
=NextTagItem(&temp_sub_tag
);
785 scale
=POWER_SCALE(*p
);
786 while((*(p
++)&0x80)!=0)
789 n
+=(*p
&0x7f)*scale
/100;
791 flags
|=PCCARD_POWERF_HIGHZOK
;
795 flags
|=PCCARD_POWERF_HIGHZREQ
;
800 sub_tag
->ti_Tag
=TAG_IGNORE
;
804 NextTagItem(&temp_sub_tag
)->ti_Data
=flags
;
807 tag
->ti_Data
=(UPINT
)sub_tag_list
;
810 tag
->ti_Tag
=TAG_IGNORE
;
813 /* Parse timing data */
815 if((features
&0x4)!=0)
820 for(i
=0;i
<TIMING_COUNT
;i
++)
822 timing_scales
[i
]=scale
&0x7;
825 if(timing_scales
[0]!=7)
826 timing_scales
[0]>>=1;
828 for(i
=0;i
<TIMING_COUNT
;i
++)
830 tag
=NextTagItem(&temp_tag
);
832 if(timing_scales
[i
]!=7)
834 temp_sub_tag
=sub_tag_list
=CloneTagItems(timing_tag_list
);
835 if(sub_tag_list
==NULL
)
841 NextTagItem(&temp_sub_tag
)->ti_Data
=SPEED_CVT(*p
);
842 NextTagItem(&temp_sub_tag
)->ti_Data
=
843 exponents
[timing_scales
[i
]];
846 tag
->ti_Data
=(UPINT
)sub_tag_list
;
849 tag
->ti_Tag
=TAG_IGNORE
;
856 tag
=NextTagItem(&temp_tag
);
857 tag
->ti_Tag
=TAG_SKIP
;
858 tag
->ti_Data
=TIMING_COUNT
-1;
862 /* Parse IO windows data */
864 if((features
&0x8)!=0)
868 if((sub_flags
&0x80)!=0)
872 win_count
=(sizes
&0xf)+1;
874 base_size
=1<<((sizes
&0x3)-1);
876 length_size
=1<<((sizes
&0x3)-1);
883 win_bases
=AllocVec(win_count
*sizeof(ULONG
),MEMF_PUBLIC
);
884 win_lengths
=AllocVec(win_count
*sizeof(ULONG
),MEMF_PUBLIC
);
885 if((win_bases
==NULL
)||(win_lengths
==NULL
))
890 if((sub_flags
&0x80)!=0)
892 for(i
=0;i
<win_count
;i
++)
894 for(n
=0,q
=p
+base_size
;q
>p
;n
|=*(--q
))
899 for(n
=0,q
=p
+length_size
;q
>p
;n
|=*(--q
))
908 *win_lengths
=1<<(sub_flags
&0x1f);
913 tag
=NextTagItem(&temp_tag
);
914 if((features
&0x8)==0)
915 tag
->ti_Tag
=TAG_IGNORE
;
916 tag
->ti_Data
=sub_flags
&(PCCARD_IOF_8BIT
|PCCARD_IOF_16BIT
);
918 tag
=NextTagItem(&temp_tag
);
919 if((features
&0x8)==0)
920 tag
->ti_Tag
=TAG_IGNORE
;
921 tag
->ti_Data
=sub_flags
&0x1f;
923 tag
=NextTagItem(&temp_tag
);
924 if((features
&0x8)==0)
925 tag
->ti_Tag
=TAG_IGNORE
;
926 tag
->ti_Data
=win_count
;
928 tag
=NextTagItem(&temp_tag
);
929 if((features
&0x8)==0)
930 tag
->ti_Tag
=TAG_IGNORE
;
931 tag
->ti_Data
=(UPINT
)win_bases
;
933 tag
=NextTagItem(&temp_tag
);
934 if((features
&0x8)==0)
935 tag
->ti_Tag
=TAG_IGNORE
;
936 tag
->ti_Data
=(UPINT
)win_lengths
;
940 if((features
&0x10)!=0)
943 if((sub_flags
&0x10)!=0)
949 mask
=1<<(sub_flags
&0xf); /* TO DO: check if single interrupt is "desired" or "allowed" */
954 tag
=NextTagItem(&temp_tag
);
955 if((features
&0x10)==0)
956 tag
->ti_Tag
=TAG_IGNORE
;
957 tag
->ti_Data
=sub_flags
;
959 tag
=NextTagItem(&temp_tag
);
960 if((features
&0x10)==0)
961 tag
->ti_Tag
=TAG_IGNORE
;
964 /* Parse memory windows data */
966 if((features
&0x60)!=0)
968 if((features
&0x60)==0x60)
971 win_count
=(sizes
&0x7)+1;
973 length_size
=sizes
&0x3;
984 win_bases
=AllocVec(win_count
*sizeof(ULONG
),MEMF_PUBLIC
);
985 win_lengths
=AllocVec(win_count
*sizeof(ULONG
),MEMF_PUBLIC
);
986 if((win_bases
==NULL
)||(win_lengths
==NULL
))
991 host_bases
=AllocVec(win_count
*sizeof(ULONG
),MEMF_PUBLIC
);
998 if((features
&0x60)==0x60)
1000 for(i
=0;i
<win_count
;i
++)
1002 for(n
=0,q
=p
+length_size
;q
>p
;n
<<=8)
1007 for(n
=0,q
=p
+base_size
;q
>p
;n
<<=8)
1014 for(n
=0,q
=p
+base_size
;q
>p
;n
<<=8)
1023 *win_lengths
=(*p
<<8)+(*(p
+1)<<16);
1026 if((features
&0x40)!=0)
1028 *win_bases
=(*p
<<8)+(*(p
+1)<<16);
1037 tag
=NextTagItem(&temp_tag
);
1038 if((features
&0x60)==0)
1039 tag
->ti_Tag
=TAG_IGNORE
;
1040 tag
->ti_Data
=win_count
;
1042 tag
=NextTagItem(&temp_tag
);
1043 if((features
&0x60)==0)
1044 tag
->ti_Tag
=TAG_IGNORE
;
1045 tag
->ti_Data
=(UPINT
)win_bases
;
1047 tag
=NextTagItem(&temp_tag
);
1048 if(((features
&0x60)==0)||(sizes
==0))
1049 tag
->ti_Tag
=TAG_IGNORE
;
1050 tag
->ti_Data
=(UPINT
)host_bases
;
1052 tag
=NextTagItem(&temp_tag
);
1053 if((features
&0x60)==0)
1054 tag
->ti_Tag
=TAG_IGNORE
;
1055 tag
->ti_Data
=(UPINT
)win_lengths
;
1057 /* Parse extra flags */
1059 if((features
&0x80)!=0)
1062 /* TO DO: parse extra flags and subtuples */
1072 static BOOL
ParseManfID(const UBYTE
*tuple
,struct TagItem
*tag_list
,
1073 struct PCCardBase
*base
)
1075 /* Get manufacturer and product IDs */
1078 NextTagItem(&tag_list
)->ti_Data
=LEWord(tuple
);
1080 NextTagItem(&tag_list
)->ti_Data
=LEWord(tuple
);
1087 static BOOL
ParseFuncID(const UBYTE
*tuple
,struct TagItem
*tag_list
,
1088 struct PCCardBase
*base
)
1090 /* Get function and intialisation info */
1093 NextTagItem(&tag_list
)->ti_Data
=*tuple
++;
1094 NextTagItem(&tag_list
)->ti_Data
=*tuple
;
1101 /****** pccard.library/PCCard_FreeTupleInfo ********************************
1104 * PCCard_FreeTupleInfo -- Relinquish a CIS tuple tag list.
1107 * PCCard_FreeTupleInfo(tag_list)
1110 * VOID PCCard_FreeTupleInfo(struct TagItem *);
1113 * Frees a tag list obtained via PCCard_GetTupleInfo().
1116 * tag_list - Tuple tag list (may be NULL).
1128 * PCCard_GetTupleInfo()
1130 ****************************************************************************
1134 AROS_LH1(void, PCCard_FreeTupleInfo
,
1135 AROS_LHA(struct TagItem
*, tag_list
, A0
),
1136 struct PCCardBase
*, PCCardBase
, 6, PCCard
)
1140 struct TagItem
*tag
,*temp_tag
;
1143 /* Free sub-tag lists and arrays */
1148 while((tag
=NextTagItem(&temp_tag
))!=NULL
)
1150 if(TagInArray(tag
->ti_Tag
,(Tag
*)sublist_tags
)&&(tag
->ti_Data
!=0))
1151 PCCard_FreeTupleInfo((APTR
)tag
->ti_Data
);
1152 else if(TagInArray(tag
->ti_Tag
,(Tag
*)array_tags
))
1153 FreeVec((APTR
)tag
->ti_Data
);
1154 else if(TagInArray(tag
->ti_Tag
,(Tag
*)string_array_tags
))
1156 for(p
=(APTR
)tag
->ti_Data
;*p
!=NULL
;p
++)
1162 /* Free main list and return */
1164 FreeTagItems(tag_list
);
1172 static BOOL
ParseStrings(const UBYTE
*tuple
,struct TagItem
*tag_list
,
1173 struct PCCardBase
*base
)
1175 UBYTE i
=0,string_count
=0,length
;
1182 for(p
=tuple
;*p
!=0xff;p
++)
1186 /* Allocate memory for and copy strings */
1188 strings
=AllocVec((string_count
+1)*sizeof(APTR
),MEMF_PUBLIC
|MEMF_CLEAR
);
1194 for(p
=tuple
;i
<string_count
;i
++)
1197 strings
[i
]=AllocVec(length
,MEMF_PUBLIC
);
1198 if(strings
[i
]!=NULL
)
1199 CopyMem(p
,strings
[i
],length
);
1206 NextTagItem(&tag_list
)->ti_Data
=string_count
;
1207 NextTagItem(&tag_list
)->ti_Data
=(UPINT
)strings
;
1216 static ULONG
StrLen(const TEXT
*s
)
1220 for(p
=s
;*p
!='\0';p
++);