6 * PCMCIA support routines for etherboot - generic stuff
8 * This code has partly be taken from the linux kernel sources, .../drivers/pcmcia/
9 * Started & put together by
10 * Anselm Martin Hoffmeister
11 * Stockholm Projekt Computer-Service
12 * Sankt Augustin / Bonn, Germany
14 * Distributed under GPL2
20 * ******************************
21 * PLEASE DO NOT YET WORK ON THIS
22 * ******************************
24 * I'm still fixing it up on every end, so we most probably would interfere
25 * at some point. If there's anything obvious or better, not-so-obvious,
26 * please contact me by e-mail: anselm (AT) hoffmeister (DOT) be *THANKS*
31 #define CODE_STATUS "alpha"
32 #define CODE_VERSION "0.1.3"
33 #include <pcmcia-opts.h>
35 #include <gpxe/init.h>
37 int sockets
; /* AHTODO: Phase this out! */
39 struct pccsock_t pccsock
[MAXPCCSOCKS
];
41 struct pcc_config_t pccconfig
[MAXPCCCONFIGS
];
43 struct driver_interact_t driver
[] = {
45 { I82365
, i82365_interfacer
, "Intel_82365" },
49 #define NUM_DRIVERS (sizeof(driver)/(sizeof(struct driver_interact_t)))
51 void sleepticks(int numticks
) {
53 for (tmo
= currticks()+numticks
; currticks() < tmo
; ) {
58 static void pcmcia_init_all(void) {
59 u_int i
, j
, k
, l
, m
, n
, ui
, configs
= 0;
62 if ( PDEBUG
> 0 ) printf("Initializing PCMCIA subsystem (code-status: " CODE_STATUS
", Version " CODE_VERSION
")\n");
64 printf ( "Supporting %d driver(s): ", NUM_DRIVERS
);
65 for ( i
= 0; i
< NUM_DRIVERS
; ++i
) {
66 printf ( "[%s] ", driver
[i
].name
);
72 // Init all drivers in the driver[] array:
73 for ( i
= 0; i
< NUM_DRIVERS
; ++i
) {
74 driver
[i
].f(INIT
,0,i
,0,0); // init needs no params. It uses pccsocks and pccsock[].
75 // Only i tells it which driver_id itself is.
77 for ( i
= 0; i
< pccsocks
; ++i
) {
78 printf ( "Socket %d: ", i
);
79 if ( pccsock
[i
].status
!= HASCARD
) {
80 printf ( "is %s: skipping\n", pccsock
[i
].status
== EMPTY
? "empty":"[status unknown]" );
83 if ( 0 != driver
[pccsock
[i
].drivernum
].f(MAPATTRMEM
,pccsock
[i
].internalid
,MAP_ATTRMEM_TO
, MAP_ATTRMEM_LEN
,0 ) ) {
84 printf ("PCMCIA controller failed to map attribute memory.\n**** SEVERE ERROR CONDITION. Skipping controller.\n" );
86 printf ( "<press key. THIS CONDITION SHOULD BE REPORTED!>\n" ); getchar();
90 // parse configuration information
91 uc
= ioremap ( MAP_ATTRMEM_TO
, MAP_ATTRMEM_LEN
);
92 pccsock
[i
].stringoffset
= pccsock
[i
].configoffset
= pccsock
[i
].stringlength
= 0;
93 pccsock
[i
].type
= 0xff;
94 for ( l
= 0; l
< 8; ++l
) multicard
[l
] = 0;
96 for ( l
= ui
= 0; ui
< 0x800; ui
+= uc
[(2*ui
)+2] + 2 ) {
97 if ( uc
[(2*ui
)] == 0xff ) {
100 // This loop is complete rubbish AFAICS.
101 // But without it, my test system won't come up.
102 // It's too bad to develop on broken hardware
108 for ( l
= ui
= 0; ui
< 0x800; ui
+= uc
[(2*ui
)+2] + 2 ) {
109 if ( uc
[(2*ui
)] == 0xff ) break;
110 else if ( uc
[2*ui
] == 0x15 ) {
111 for ( k
= 2 * ( ui
+ 2 ); ( uc
[k
] <= ' ' ) && ( k
< ( 2 * ( uc
[2*(ui
+1)] + ui
+ 2 ) ) ) ; k
+= 2 ) { ; }
112 pccsock
[i
].stringoffset
= k
;
113 pccsock
[i
].stringlength
= ( 2 * ( ui
+ 2 + uc
[(2*ui
)+2] ) - k
) / 2;
114 } else if ( uc
[2*ui
] == 0x21 ) {
115 pccsock
[i
].type
= uc
[(2*ui
)+4];
116 } else if ( uc
[2*ui
] == 0x1a ) { // Configuration map
117 printf ( "\nConfig map 0x1a found [" );
118 for ( k
= 0; k
< uc
[2*(ui
+1)]; ++k
) {
119 printf ( "%02x ", uc
[2*(ui
+k
+2)] );
121 printf ( "]\nHighest config available is %d\n", uc
[2*(ui
+3)] );
123 pccsock
[i
].configoffset
= 0;
124 for ( j
= 0; j
<= (m
& 3); ++j
) {
125 pccsock
[i
].configoffset
+= uc
[2*(ui
+4+j
)] << (8*j
);
127 pccsock
[i
].rmask0
= 0;
128 for ( j
= 0; j
<= ( ( ( m
& 0x3c ) >> 2 ) & 3 ); ++j
) {
129 pccsock
[i
].rmask0
+= uc
[2*(ui
+5+(m
&3)+j
)] << (8*j
);
131 j
= pccsock
[i
].rmask0
;
132 printf ( "Config offset is %x, card has regs: < %s%s%s%s%s>\n", pccsock
[i
].configoffset
,
133 j
& 1 ? "COR ":"", j
& 2 ? "CCSR ":"", j
& 4 ? "PRR ":"", j
& 8 ? "SCR ":"", j
& 16? "ESR ":"" );
134 printf ( "COR + CCSR contents (si/du) %x %x/%x %x\n", uc
[pccsock
[i
].configoffset
+0],
135 uc
[pccsock
[i
].configoffset
+2],uc
[pccsock
[i
].configoffset
*2],uc
[(pccsock
[i
].configoffset
*2)+2] );
137 } else if ( uc
[2*ui
] == 0x1b ) { // Configuration data entry
138 //printf ( "Config data 0x1b found [\n" );getchar();
139 for ( k
= 0; k
< uc
[2*(ui
+1)]; ++k
) {
140 // printf ( "%02x ", uc[2*(ui+k+2)] );
142 // Parse this tuple into pccconfig[configs]
144 if ( configs
== MAXPCCCONFIGS
) continue;
146 pccconfig
[configs
].index
= uc
[k
] & 0x3f;
147 if ( uc
[k
] & 0x80 ) {
148 // printf ( "Special config, unsupp. for now\n" );
152 // printf ( "Features: %2x\n", uc[k] );
154 // printf ( "Cannot work with Vcc/Timing configs right now\n" );
157 pccconfig
[configs
].iowin
= pccconfig
[configs
].iolen
= 0;
158 if ( 0 != ( uc
[k
] & 0x8 ) ) {
160 // printf ( "Reading IO config: " );
161 if ( 0 == ( uc
[k
] & 0x80 ) ) {
162 // printf ( "Cannot work with auto/io config\n" );
166 if ( 0 != ( uc
[k
] & 0x0f ) ) {
167 // printf ( "Don't support more than 1 iowin right now\n" );
170 j
= (uc
[k
] & 0x30) >> 4;
171 m
= (uc
[k
] & 0xc0) >> 6;
175 pccconfig
[configs
].iowin
= 0;
176 pccconfig
[configs
].iolen
= 1;
177 for ( n
= 0; n
< j
; ++n
, k
+=2 ) {
178 pccconfig
[configs
].iowin
+= uc
[k
] << (n
*8);
180 for ( n
= 0; n
< m
; ++n
, k
+=2 ) {
181 pccconfig
[configs
].iolen
+= uc
[k
] << (n
*8);
183 // printf ( "io %x len %d (%d)\n", pccconfig[configs].iowin, pccconfig[configs].iolen,configs );
185 for ( j
= 0; j
< (uc
[k
] & 3); ++j
) {
186 // pccconfig[configs].iowin += (uc[k+(2*j)+2]) << (8*j);
191 if ( pccsock
[i
].stringoffset
> 0 ) { // If no identifier, it's not a valid CIS (as of documentation...)
193 for ( k
= 0; ( k
< pccsock
[i
].stringlength
) && ( k
< 64 ); ++k
) {
194 j
= uc
[pccsock
[i
].stringoffset
+ 2 * k
];
195 printf ( "%c", (j
>=' '? j
:' ' ) );
197 printf ("]\n is type %d (", pccsock
[i
].type
);
198 switch ( pccsock
[i
].type
) {
200 printf ( "MULTI" ); break;
202 printf ( "Memory" ); break;
204 printf ( "Serial" ); break;
206 printf ( "Parallel" ); break;
208 printf ( "Fixed" ); break;
210 printf ( "Video" ); break;
212 printf ( "Network" ); break;
214 printf ( "AIMS" ); break;
216 printf ( "SCSI" ); break;
217 case 0x106: // Special / homebrew to say "Multi/network"
218 printf ( "MULTI, with Network" ); break; // AHTODO find a card for this
220 printf ( "UNSUPPORTED/UNKNOWN" );
222 printf ( ") with %d possible configuration(s)\n", configs
);
223 // Now set dependency: If it's Network or multi->network, accept
224 if ( (inited
<= 0 ) && (6 == (0xff & pccsock
[i
].type
) ) && (0 < configs
) ) {
225 printf ( "activating this device with ioport %x-%x (config #%d)\n",
226 pccconfig
[0].iowin
, pccconfig
[0].iowin
+pccconfig
[0].iolen
-1, pccconfig
[0].index
);
228 // And unmap attrmem ourselves!
229 printf ( "Activating config..." );
230 if ( m
=driver
[pccsock
[i
].drivernum
].f(SELECTCONFIG
,pccsock
[i
].internalid
,pccconfig
[0].index
,0,&pccconfig
[0]) ) {
231 printf ("Failure(%d)!",m
); inited
= -1;
232 driver
[pccsock
[i
].drivernum
].f(UNMAPATTRMEM
,pccsock
[i
].internalid
,0,0,0);
234 printf ( "done!\n" );
238 printf ( "unsupported - no identifier string found in CIS\n" );
240 // unmap the PCMCIA device
242 if ( 0 != driver
[pccsock
[i
].drivernum
].f(UNMAPATTRMEM
,pccsock
[i
].internalid
,0,0,0) ) {
243 printf ("PCMCIA controller failed to unmap attribute memory.\n**** SEVERE ERROR CONDITION ****\n" );
245 printf ( "<press key. THIS CONDITION SHOULD BE REPORTED!>\n" ); getchar();
252 printf ( "<press key to exit the pcmcia_init_all routine>\n" );
258 static void pcmcia_shutdown_all(void) {
260 //if ( PDEBUG > 2 ) {printf("<press key to continue>\n" ); getchar(); }
261 for ( i
= 0; i
< pccsocks
; ++i
) {
262 driver
[pccsock
[i
].drivernum
].f(SHUTDOWN
,pccsock
[i
].internalid
,0,0,0);
264 printf("Shutdown of PCMCIA subsystem completed");