Home | History | Annotate | Download | only in core
      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
    268