iPXE
pcmcia.c
Go to the documentation of this file.
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 
29 FILE_LICENCE ( GPL2_ONLY );
30 
31 #include <stdio.h>
32 #include <pcmcia.h>
33 #include <i82365.h>
34 #define CODE_STATUS "alpha"
35 #define CODE_VERSION "0.1.3"
36 #include <pcmcia-opts.h>
37 #include <ipxe/init.h>
38 
39 int sockets; /* AHTODO: Phase this out! */
42 int inited = -1;
43 struct pcc_config_t pccconfig[MAXPCCCONFIGS];
44 
45 struct driver_interact_t driver[] = {
46 #ifdef SUPPORT_I82365
47  { I82365, i82365_interfacer, "Intel_82365" },
48 #endif
49 };
50 
51 #define NUM_DRIVERS (sizeof(driver)/(sizeof(struct driver_interact_t)))
52 
53 void sleepticks(int numticks ) {
54  u_int tmo;
55  for (tmo = currticks()+numticks; currticks() < tmo; ) {
56  }
57  return;
58 }
59 
60 static void pcmcia_init_all(void) {
61  u_int i, j, k, l, m, n, ui, configs = 0;
62  u_int multicard[8];
63  u_char *uc, upc;
64  if ( PDEBUG > 0 ) printf("Initializing PCMCIA subsystem (code-status: " CODE_STATUS ", Version " CODE_VERSION ")\n");
65  if ( PDEBUG > 2 ) {
66  printf ( "Supporting %d driver(s): ", NUM_DRIVERS );
67  for ( i = 0; i < NUM_DRIVERS; ++i ) {
68  printf ( "[%s] ", driver[i].name );
69  }
70  printf ( "\n" );
71  }
72  pccsocks = 0;
73  sockets = 0;
74  // Init all drivers in the driver[] array:
75  for ( i = 0; i < NUM_DRIVERS; ++i ) {
76  driver[i].f(INIT,0,i,0,0); // init needs no params. It uses pccsocks and pccsock[].
77  // Only i tells it which driver_id itself is.
78  }
79  for ( i = 0; i < pccsocks; ++i ) {
80  printf ( "Socket %d: ", i );
81  if ( pccsock[i].status != HASCARD ) {
82  printf ( "is %s: skipping\n", pccsock[i].status == EMPTY? "empty":"[status unknown]" );
83  continue;
84  }
85  if ( 0 != driver[pccsock[i].drivernum].f(MAPATTRMEM,pccsock[i].internalid,MAP_ATTRMEM_TO, MAP_ATTRMEM_LEN,0 ) ) {
86  printf ("PCMCIA controller failed to map attribute memory.\n**** SEVERE ERROR CONDITION. Skipping controller.\n" );
87  if ( PDEBUG > 2 ) {
88  printf ( "<press key. THIS CONDITION SHOULD BE REPORTED!>\n" ); getchar();
89  }
90  continue;
91  }
92  // parse configuration information
95  pccsock[i].type = 0xff;
96  for ( l = 0; l < 8; ++l ) multicard[l] = 0;
97  sleepticks(2);
98  for ( l = ui = 0; ui < 0x800; ui += uc[(2*ui)+2] + 2 ) {
99  if ( uc[(2*ui)] == 0xff ) {
100  break;
101  }
102  // This loop is complete rubbish AFAICS.
103  // But without it, my test system won't come up.
104  // It's too bad to develop on broken hardware
105  // - Anselm
106  }
107  sleepticks(2);
108  configs = 0;
109  inited = -1;
110  for ( l = ui = 0; ui < 0x800; ui += uc[(2*ui)+2] + 2 ) {
111  if ( uc[(2*ui)] == 0xff ) break;
112  else if ( uc[2*ui] == 0x15 ) {
113  for ( k = 2 * ( ui + 2 ); ( uc[k] <= ' ' ) && ( k < ( 2 * ( uc[2*(ui+1)] + ui + 2 ) ) ) ; k += 2 ) { ; }
114  pccsock[i].stringoffset = k;
115  pccsock[i].stringlength = ( 2 * ( ui + 2 + uc[(2*ui)+2] ) - k ) / 2;
116  } else if ( uc[2*ui] == 0x21 ) {
117  pccsock[i].type = uc[(2*ui)+4];
118  } else if ( uc[2*ui] == 0x1a ) { // Configuration map
119  printf ( "\nConfig map 0x1a found [" );
120  for ( k = 0; k < uc[2*(ui+1)]; ++k ) {
121  printf ( "%02x ", uc[2*(ui+k+2)] );
122  }
123  printf ( "]\nHighest config available is %d\n", uc[2*(ui+3)] );
124  m = uc[2*(ui+2)];
125  pccsock[i].configoffset = 0;
126  for ( j = 0; j <= (m & 3); ++j ) {
127  pccsock[i].configoffset += uc[2*(ui+4+j)] << (8*j);
128  }
129  pccsock[i].rmask0 = 0;
130  for ( j = 0; j <= ( ( ( m & 0x3c ) >> 2 ) & 3 ); ++j ) {
131  pccsock[i].rmask0 += uc[2*(ui+5+(m&3)+j)] << (8*j);
132  }
133  j = pccsock[i].rmask0;
134  printf ( "Config offset is %x, card has regs: < %s%s%s%s%s>\n", pccsock[i].configoffset,
135  j & 1 ? "COR ":"", j & 2 ? "CCSR ":"", j & 4 ? "PRR ":"", j & 8 ? "SCR ":"", j & 16? "ESR ":"" );
136  printf ( "COR + CCSR contents (si/du) %x %x/%x %x\n", uc[pccsock[i].configoffset+0],
137  uc[pccsock[i].configoffset+2],uc[pccsock[i].configoffset*2],uc[(pccsock[i].configoffset*2)+2] );
138  printf ( " " );
139  } else if ( uc[2*ui] == 0x1b ) { // Configuration data entry
140  //printf ( "Config data 0x1b found [\n" );getchar();
141  for ( k = 0; k < uc[2*(ui+1)]; ++k ) {
142  // printf ( "%02x ", uc[2*(ui+k+2)] );
143  }
144  // Parse this tuple into pccconfig[configs]
145  // printf ( "]\n" );
146  if ( configs == MAXPCCCONFIGS ) continue;
147  k = 2*ui+4;
148  pccconfig[configs].index = uc[k] & 0x3f;
149  if ( uc[k] & 0x80 ) {
150  // printf ( "Special config, unsupp. for now\n" );
151  continue;
152  }
153  k+=2;
154  // printf ( "Features: %2x\n", uc[k] );
155  if ( uc[k] & 0x7 ) {
156  // printf ( "Cannot work with Vcc/Timing configs right now\n" );
157  continue;
158  }
159  pccconfig[configs].iowin = pccconfig[configs].iolen = 0;
160  if ( 0 != ( uc[k] & 0x8 ) ) {
161  k+=2;
162  // printf ( "Reading IO config: " );
163  if ( 0 == ( uc[k] & 0x80 ) ) {
164  // printf ( "Cannot work with auto/io config\n" );
165  continue;
166  }
167  k+=2;
168  if ( 0 != ( uc[k] & 0x0f ) ) {
169  // printf ( "Don't support more than 1 iowin right now\n" );
170  continue;
171  }
172  j = (uc[k] & 0x30) >> 4;
173  m = (uc[k] & 0xc0) >> 6;
174  if ( 3 == j ) ++j;
175  if ( 3 == m ) ++m;
176  k += 2;
177  pccconfig[configs].iowin = 0;
178  pccconfig[configs].iolen = 1;
179  for ( n = 0; n < j; ++n, k+=2 ) {
180  pccconfig[configs].iowin += uc[k] << (n*8);
181  }
182  for ( n = 0; n < m; ++n, k+=2 ) {
183  pccconfig[configs].iolen += uc[k] << (n*8);
184  }
185  // printf ( "io %x len %d (%d)\n", pccconfig[configs].iowin, pccconfig[configs].iolen,configs );
186  }
187  for ( j = 0; j < (uc[k] & 3); ++j ) {
188  // pccconfig[configs].iowin += (uc[k+(2*j)+2]) << (8*j);
189  }
190  ++configs;
191  }
192  }
193  if ( pccsock[i].stringoffset > 0 ) { // If no identifier, it's not a valid CIS (as of documentation...)
194  printf ( "[" );
195  for ( k = 0; ( k < pccsock[i].stringlength ) && ( k < 64 ); ++k ) {
196  j = uc[pccsock[i].stringoffset + 2 * k];
197  printf ( "%c", (j>=' '? j:' ' ) );
198  }
199  printf ("]\n is type %d (", pccsock[i].type );
200  switch ( pccsock[i].type ) {
201  case 0x00:
202  printf ( "MULTI" ); break;
203  case 0x01:
204  printf ( "Memory" ); break;
205  case 0x02:
206  printf ( "Serial" ); break;
207  case 0x03:
208  printf ( "Parallel" ); break;
209  case 0x04:
210  printf ( "Fixed" ); break;
211  case 0x05:
212  printf ( "Video" ); break;
213  case 0x06:
214  printf ( "Network" ); break;
215  case 0x07:
216  printf ( "AIMS" ); break;
217  case 0x08:
218  printf ( "SCSI" ); break;
219  case 0x106: // Special / homebrew to say "Multi/network"
220  printf ( "MULTI, with Network" ); break; // AHTODO find a card for this
221  default:
222  printf ( "UNSUPPORTED/UNKNOWN" );
223  }
224  printf ( ") with %d possible configuration(s)\n", configs );
225  // Now set dependency: If it's Network or multi->network, accept
226  if ( (inited <= 0 ) && (6 == (0xff & pccsock[i].type) ) && (0 < configs ) ) {
227  printf ( "activating this device with ioport %x-%x (config #%d)\n",
228  pccconfig[0].iowin, pccconfig[0].iowin+pccconfig[0].iolen-1, pccconfig[0].index );
229  inited = i;
230  // And unmap attrmem ourselves!
231  printf ( "Activating config..." );
232  if ( m=driver[pccsock[i].drivernum].f(SELECTCONFIG,pccsock[i].internalid,pccconfig[0].index,0,&pccconfig[0]) ) {
233  printf ("Failure(%d)!",m); inited = -1;
234  driver[pccsock[i].drivernum].f(UNMAPATTRMEM,pccsock[i].internalid,0,0,0);
235  }
236  printf ( "done!\n" );
237  continue;
238  }
239  } else {
240  printf ( "unsupported - no identifier string found in CIS\n" );
241  }
242  // unmap the PCMCIA device
243  if ( i != inited ) {
244  if ( 0 != driver[pccsock[i].drivernum].f(UNMAPATTRMEM,pccsock[i].internalid,0,0,0) ) {
245  printf ("PCMCIA controller failed to unmap attribute memory.\n**** SEVERE ERROR CONDITION ****\n" );
246  if ( PDEBUG > 2 ) {
247  printf ( "<press key. THIS CONDITION SHOULD BE REPORTED!>\n" ); getchar();
248  }
249  continue;
250  }
251  }
252  }
253  if ( PDEBUG > 2 ) {
254  printf ( "<press key to exit the pcmcia_init_all routine>\n" );
255  getchar();
256  }
257 
258 }
259 
260 static void pcmcia_shutdown_all(void) {
261  int i;
262  //if ( PDEBUG > 2 ) {printf("<press key to continue>\n" ); getchar(); }
263  for ( i = 0; i < pccsocks; ++i ) {
264  driver[pccsock[i].drivernum].f(SHUTDOWN,pccsock[i].internalid,0,0,0);
265  }
266  printf("Shutdown of PCMCIA subsystem completed");
267 }
268 
269 #endif
#define MAP_ATTRMEM_TO
Definition: pcmcia-opts.h:14
unsigned int u_int
Definition: pcmcia.h:8
const char * name
Definition: ath9k_hw.c:1984
uint8_t l
Definition: registers.h:15
u_int pccsocks
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
Definition: pcmcia.h:18
struct pccsock_t pccsock[MAXPCCSOCKS]
int rmask0
Definition: pcmcia.h:39
int drivernum
Definition: pcmcia.h:28
#define MAP_ATTRMEM_LEN
Definition: pcmcia-opts.h:15
uint8_t status
Status.
Definition: ena.h:16
int stringoffset
Definition: pcmcia.h:37
Definition: pcmcia.h:17
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition: compiler.h:827
#define MAXPCCSOCKS
Definition: pcmcia.h:14
Definition: pcmcia.h:19
int sockets
int type
Definition: pcmcia.h:34
int getchar(void)
Read a single character from any console.
Definition: console.c:85
unsigned char u_char
Definition: pcmcia.h:6
u_int stringlength
Definition: pcmcia.h:38
static const uint32_t k[64]
MD5 constants.
Definition: md5.c:53
uint32_t type
Operating system type.
Definition: ena.h:12
int(* f)(interface_func_t, int, int, int, int)
Definition: pcmcia.h:23
void sleepticks(int)
uint32_t f
Definition: sha256.c:33
int i82365_interfacer(interface_func_t, int, int, int, void *)
#define PDEBUG
Definition: pcmcia-opts.h:17
#define MAXPCCCONFIGS
Definition: pcmcia.h:15
int configoffset
Definition: pcmcia.h:35
uint64_t index
Index of the first segment within the content.
Definition: pccrc.h:21
unsigned long currticks(void)
Get current system time in ticks.
Definition: timer.c:42
void * ioremap(unsigned long bus_addr, size_t len)
Map bus address as an I/O address.
Definition: pcmcia.h:19