1 | #if 0 |
---|
2 | |
---|
3 | /* |
---|
4 | * pcmcia.c |
---|
5 | * |
---|
6 | * PCMCIA support routines for etherboot - generic stuff |
---|
7 | * |
---|
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 |
---|
13 | * |
---|
14 | * Distributed under GPL2 |
---|
15 | */ |
---|
16 | |
---|
17 | /* |
---|
18 | * |
---|
19 | * |
---|
20 | * ****************************** |
---|
21 | * PLEASE DO NOT YET WORK ON THIS |
---|
22 | * ****************************** |
---|
23 | * |
---|
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* |
---|
27 | */ |
---|
28 | #include <stdio.h> |
---|
29 | #include <pcmcia.h> |
---|
30 | #include <i82365.h> |
---|
31 | #define CODE_STATUS "alpha" |
---|
32 | #define CODE_VERSION "0.1.3" |
---|
33 | #include <pcmcia-opts.h> |
---|
34 | #include <console.h> |
---|
35 | #include <gpxe/init.h> |
---|
36 | |
---|
37 | int sockets; /* AHTODO: Phase this out! */ |
---|
38 | u_int pccsocks; |
---|
39 | struct pccsock_t pccsock[MAXPCCSOCKS]; |
---|
40 | int inited = -1; |
---|
41 | struct pcc_config_t pccconfig[MAXPCCCONFIGS]; |
---|
42 | |
---|
43 | struct driver_interact_t driver[] = { |
---|
44 | #ifdef SUPPORT_I82365 |
---|
45 | { I82365, i82365_interfacer, "Intel_82365" }, |
---|
46 | #endif |
---|
47 | }; |
---|
48 | |
---|
49 | #define NUM_DRIVERS (sizeof(driver)/(sizeof(struct driver_interact_t))) |
---|
50 | |
---|
51 | void sleepticks(int numticks ) { |
---|
52 | u_int tmo; |
---|
53 | for (tmo = currticks()+numticks; currticks() < tmo; ) { |
---|
54 | } |
---|
55 | return; |
---|
56 | } |
---|
57 | |
---|
58 | static void pcmcia_init_all(void) { |
---|
59 | u_int i, j, k, l, m, n, ui, configs = 0; |
---|
60 | u_int multicard[8]; |
---|
61 | u_char *uc, upc; |
---|
62 | if ( PDEBUG > 0 ) printf("Initializing PCMCIA subsystem (code-status: " CODE_STATUS ", Version " CODE_VERSION ")\n"); |
---|
63 | if ( PDEBUG > 2 ) { |
---|
64 | printf ( "Supporting %d driver(s): ", NUM_DRIVERS ); |
---|
65 | for ( i = 0; i < NUM_DRIVERS; ++i ) { |
---|
66 | printf ( "[%s] ", driver[i].name ); |
---|
67 | } |
---|
68 | printf ( "\n" ); |
---|
69 | } |
---|
70 | pccsocks = 0; |
---|
71 | sockets = 0; |
---|
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. |
---|
76 | } |
---|
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]" ); |
---|
81 | continue; |
---|
82 | } |
---|
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" ); |
---|
85 | if ( PDEBUG > 2 ) { |
---|
86 | printf ( "<press key. THIS CONDITION SHOULD BE REPORTED!>\n" ); getchar(); |
---|
87 | } |
---|
88 | continue; |
---|
89 | } |
---|
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; |
---|
95 | sleepticks(2); |
---|
96 | for ( l = ui = 0; ui < 0x800; ui += uc[(2*ui)+2] + 2 ) { |
---|
97 | if ( uc[(2*ui)] == 0xff ) { |
---|
98 | break; |
---|
99 | } |
---|
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 |
---|
103 | // - Anselm |
---|
104 | } |
---|
105 | sleepticks(2); |
---|
106 | configs = 0; |
---|
107 | inited = -1; |
---|
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)] ); |
---|
120 | } |
---|
121 | printf ( "]\nHighest config available is %d\n", uc[2*(ui+3)] ); |
---|
122 | m = uc[2*(ui+2)]; |
---|
123 | pccsock[i].configoffset = 0; |
---|
124 | for ( j = 0; j <= (m & 3); ++j ) { |
---|
125 | pccsock[i].configoffset += uc[2*(ui+4+j)] << (8*j); |
---|
126 | } |
---|
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); |
---|
130 | } |
---|
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] ); |
---|
136 | printf ( " " ); |
---|
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)] ); |
---|
141 | } |
---|
142 | // Parse this tuple into pccconfig[configs] |
---|
143 | // printf ( "]\n" ); |
---|
144 | if ( configs == MAXPCCCONFIGS ) continue; |
---|
145 | k = 2*ui+4; |
---|
146 | pccconfig[configs].index = uc[k] & 0x3f; |
---|
147 | if ( uc[k] & 0x80 ) { |
---|
148 | // printf ( "Special config, unsupp. for now\n" ); |
---|
149 | continue; |
---|
150 | } |
---|
151 | k+=2; |
---|
152 | // printf ( "Features: %2x\n", uc[k] ); |
---|
153 | if ( uc[k] & 0x7 ) { |
---|
154 | // printf ( "Cannot work with Vcc/Timing configs right now\n" ); |
---|
155 | continue; |
---|
156 | } |
---|
157 | pccconfig[configs].iowin = pccconfig[configs].iolen = 0; |
---|
158 | if ( 0 != ( uc[k] & 0x8 ) ) { |
---|
159 | k+=2; |
---|
160 | // printf ( "Reading IO config: " ); |
---|
161 | if ( 0 == ( uc[k] & 0x80 ) ) { |
---|
162 | // printf ( "Cannot work with auto/io config\n" ); |
---|
163 | continue; |
---|
164 | } |
---|
165 | k+=2; |
---|
166 | if ( 0 != ( uc[k] & 0x0f ) ) { |
---|
167 | // printf ( "Don't support more than 1 iowin right now\n" ); |
---|
168 | continue; |
---|
169 | } |
---|
170 | j = (uc[k] & 0x30) >> 4; |
---|
171 | m = (uc[k] & 0xc0) >> 6; |
---|
172 | if ( 3 == j ) ++j; |
---|
173 | if ( 3 == m ) ++m; |
---|
174 | k += 2; |
---|
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); |
---|
179 | } |
---|
180 | for ( n = 0; n < m; ++n, k+=2 ) { |
---|
181 | pccconfig[configs].iolen += uc[k] << (n*8); |
---|
182 | } |
---|
183 | // printf ( "io %x len %d (%d)\n", pccconfig[configs].iowin, pccconfig[configs].iolen,configs ); |
---|
184 | } |
---|
185 | for ( j = 0; j < (uc[k] & 3); ++j ) { |
---|
186 | // pccconfig[configs].iowin += (uc[k+(2*j)+2]) << (8*j); |
---|
187 | } |
---|
188 | ++configs; |
---|
189 | } |
---|
190 | } |
---|
191 | if ( pccsock[i].stringoffset > 0 ) { // If no identifier, it's not a valid CIS (as of documentation...) |
---|
192 | printf ( "[" ); |
---|
193 | for ( k = 0; ( k < pccsock[i].stringlength ) && ( k < 64 ); ++k ) { |
---|
194 | j = uc[pccsock[i].stringoffset + 2 * k]; |
---|
195 | printf ( "%c", (j>=' '? j:' ' ) ); |
---|
196 | } |
---|
197 | printf ("]\n is type %d (", pccsock[i].type ); |
---|
198 | switch ( pccsock[i].type ) { |
---|
199 | case 0x00: |
---|
200 | printf ( "MULTI" ); break; |
---|
201 | case 0x01: |
---|
202 | printf ( "Memory" ); break; |
---|
203 | case 0x02: |
---|
204 | printf ( "Serial" ); break; |
---|
205 | case 0x03: |
---|
206 | printf ( "Parallel" ); break; |
---|
207 | case 0x04: |
---|
208 | printf ( "Fixed" ); break; |
---|
209 | case 0x05: |
---|
210 | printf ( "Video" ); break; |
---|
211 | case 0x06: |
---|
212 | printf ( "Network" ); break; |
---|
213 | case 0x07: |
---|
214 | printf ( "AIMS" ); break; |
---|
215 | case 0x08: |
---|
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 |
---|
219 | default: |
---|
220 | printf ( "UNSUPPORTED/UNKNOWN" ); |
---|
221 | } |
---|
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 ); |
---|
227 | inited = i; |
---|
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); |
---|
233 | } |
---|
234 | printf ( "done!\n" ); |
---|
235 | continue; |
---|
236 | } |
---|
237 | } else { |
---|
238 | printf ( "unsupported - no identifier string found in CIS\n" ); |
---|
239 | } |
---|
240 | // unmap the PCMCIA device |
---|
241 | if ( i != inited ) { |
---|
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" ); |
---|
244 | if ( PDEBUG > 2 ) { |
---|
245 | printf ( "<press key. THIS CONDITION SHOULD BE REPORTED!>\n" ); getchar(); |
---|
246 | } |
---|
247 | continue; |
---|
248 | } |
---|
249 | } |
---|
250 | } |
---|
251 | if ( PDEBUG > 2 ) { |
---|
252 | printf ( "<press key to exit the pcmcia_init_all routine>\n" ); |
---|
253 | getchar(); |
---|
254 | } |
---|
255 | |
---|
256 | } |
---|
257 | |
---|
258 | static void pcmcia_shutdown_all(void) { |
---|
259 | int i; |
---|
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); |
---|
263 | } |
---|
264 | printf("Shutdown of PCMCIA subsystem completed"); |
---|
265 | } |
---|
266 | |
---|
267 | #endif |
---|