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