pcmcia.c

Go to the documentation of this file.
00001 #if 0
00002 
00003 /*
00004  *      pcmcia.c
00005  *
00006  *      PCMCIA support routines for etherboot - generic stuff
00007  *
00008  *      This code has partly be taken from the linux kernel sources, .../drivers/pcmcia/
00009  *      Started & put together by
00010  *              Anselm Martin Hoffmeister
00011  *              Stockholm Projekt Computer-Service
00012  *              Sankt Augustin / Bonn, Germany
00013  *
00014  *      Distributed under GPL2
00015  */
00016 
00017 /*
00018  *
00019  *
00020  *                      ******************************
00021  *                      PLEASE DO NOT YET WORK ON THIS
00022  *                      ******************************
00023  *
00024  *      I'm still fixing it up on every end, so we most probably would interfere
00025  *      at some point. If there's anything obvious or better, not-so-obvious,
00026  *      please contact me by e-mail: anselm (AT) hoffmeister (DOT) be   *THANKS*
00027  */
00028 #include <stdio.h>
00029 #include <pcmcia.h>
00030 #include <i82365.h>
00031 #define CODE_STATUS "alpha"
00032 #define CODE_VERSION "0.1.3"
00033 #include <pcmcia-opts.h>
00034 #include <console.h>
00035 #include <gpxe/init.h>
00036 
00037 int     sockets; /* AHTODO: Phase this out! */
00038 u_int   pccsocks;
00039 struct  pccsock_t pccsock[MAXPCCSOCKS];
00040 int     inited = -1;
00041 struct  pcc_config_t pccconfig[MAXPCCCONFIGS];
00042 
00043 struct  driver_interact_t driver[] = {
00044 #ifdef  SUPPORT_I82365
00045         { I82365, i82365_interfacer, "Intel_82365" },
00046 #endif
00047 };
00048 
00049 #define NUM_DRIVERS (sizeof(driver)/(sizeof(struct driver_interact_t)))
00050 
00051 void    sleepticks(int numticks ) {
00052         u_int   tmo;
00053         for (tmo = currticks()+numticks; currticks() < tmo; ) {
00054         }
00055         return;
00056 }
00057 
00058 static void pcmcia_init_all(void) {
00059         u_int i, j, k, l, m, n, ui, configs = 0;
00060         u_int multicard[8];
00061         u_char  *uc, upc;
00062         if ( PDEBUG > 0 ) printf("Initializing PCMCIA subsystem (code-status: " CODE_STATUS ", Version " CODE_VERSION ")\n");
00063         if ( PDEBUG > 2 ) {
00064                 printf ( "Supporting %d driver(s): ", NUM_DRIVERS );
00065                 for ( i = 0; i < NUM_DRIVERS; ++i ) {
00066                         printf ( "[%s] ", driver[i].name );
00067                 }
00068                 printf ( "\n" );
00069         }
00070         pccsocks = 0;
00071         sockets = 0;
00072         // Init all drivers in the driver[] array:
00073         for ( i = 0; i < NUM_DRIVERS; ++i ) {
00074                 driver[i].f(INIT,0,i,0,0);      // init needs no params. It uses pccsocks and pccsock[].
00075                                                 // Only i tells it which driver_id itself is.
00076         }
00077         for ( i = 0; i < pccsocks; ++i ) {
00078                 printf ( "Socket %d: ", i );
00079                 if ( pccsock[i].status != HASCARD ) {
00080                         printf ( "is %s: skipping\n", pccsock[i].status == EMPTY? "empty":"[status unknown]" );
00081                         continue;
00082                 }
00083                 if ( 0 != driver[pccsock[i].drivernum].f(MAPATTRMEM,pccsock[i].internalid,MAP_ATTRMEM_TO, MAP_ATTRMEM_LEN,0 ) ) {
00084                         printf ("PCMCIA controller failed to map attribute memory.\n**** SEVERE ERROR CONDITION. Skipping controller.\n" );
00085                         if ( PDEBUG > 2 ) {
00086                                 printf ( "<press key. THIS CONDITION SHOULD BE REPORTED!>\n" ); getchar();
00087                         }
00088                         continue;
00089                 }
00090                 // parse configuration information
00091                 uc = ioremap ( MAP_ATTRMEM_TO, MAP_ATTRMEM_LEN );
00092                 pccsock[i].stringoffset = pccsock[i].configoffset = pccsock[i].stringlength = 0;
00093                 pccsock[i].type = 0xff;
00094                 for ( l = 0; l < 8; ++l ) multicard[l] = 0;
00095                 sleepticks(2);
00096                 for ( l = ui = 0; ui < 0x800; ui += uc[(2*ui)+2] + 2 ) {
00097                         if ( uc[(2*ui)] == 0xff ) {
00098                                 break;
00099                         }
00100                         // This loop is complete rubbish AFAICS.
00101                         // But without it, my test system won't come up.
00102                         // It's too bad to develop on broken hardware
00103                         //                              - Anselm
00104                 }
00105                 sleepticks(2);
00106                 configs = 0;
00107                 inited = -1;
00108                 for ( l = ui = 0; ui < 0x800; ui += uc[(2*ui)+2] + 2 ) {
00109                         if ( uc[(2*ui)] == 0xff ) break;
00110                         else if ( uc[2*ui] == 0x15 ) {
00111                                 for ( k = 2 * ( ui + 2 ); ( uc[k] <= ' ' ) && ( k < ( 2 * ( uc[2*(ui+1)] + ui + 2 ) ) ) ; k += 2 ) { ; }
00112                                 pccsock[i].stringoffset = k;
00113                                 pccsock[i].stringlength = ( 2 * ( ui + 2 + uc[(2*ui)+2] ) - k ) / 2;
00114                         } else if ( uc[2*ui] == 0x21 ) {
00115                                 pccsock[i].type = uc[(2*ui)+4];
00116                         } else if ( uc[2*ui] == 0x1a ) { // Configuration map
00117                                 printf ( "\nConfig map 0x1a found [" );
00118                                 for ( k = 0; k < uc[2*(ui+1)]; ++k ) {
00119                                         printf ( "%02x ", uc[2*(ui+k+2)] );
00120                                 }
00121                                 printf ( "]\nHighest config available is %d\n", uc[2*(ui+3)] );
00122                                 m = uc[2*(ui+2)];
00123                                 pccsock[i].configoffset = 0;
00124                                 for ( j = 0; j <= (m & 3); ++j ) {
00125                                         pccsock[i].configoffset += uc[2*(ui+4+j)] << (8*j);
00126                                 }
00127                                 pccsock[i].rmask0 = 0;
00128                                 for ( j = 0; j <= ( ( ( m & 0x3c ) >> 2 ) & 3 ); ++j ) {
00129                                         pccsock[i].rmask0 += uc[2*(ui+5+(m&3)+j)] << (8*j);
00130                                 }
00131                                 j = pccsock[i].rmask0;
00132                                 printf ( "Config offset is %x, card has regs: < %s%s%s%s%s>\n", pccsock[i].configoffset,
00133                                         j & 1 ? "COR ":"", j & 2 ? "CCSR ":"", j & 4 ? "PRR ":"", j & 8 ? "SCR ":"", j & 16? "ESR ":"" );
00134                                 printf ( "COR + CCSR contents (si/du) %x %x/%x %x\n", uc[pccsock[i].configoffset+0],
00135                                         uc[pccsock[i].configoffset+2],uc[pccsock[i].configoffset*2],uc[(pccsock[i].configoffset*2)+2] );
00136                                 printf ( "          " );
00137                         } else if ( uc[2*ui] == 0x1b ) { // Configuration data entry
00138                                 //printf ( "Config data 0x1b found [\n" );getchar();
00139                                 for ( k = 0; k < uc[2*(ui+1)]; ++k ) {
00140                                 //      printf ( "%02x ", uc[2*(ui+k+2)] );
00141                                 }
00142                                 // Parse this tuple into pccconfig[configs]
00143                                 // printf ( "]\n" );
00144                                 if ( configs == MAXPCCCONFIGS ) continue;
00145                                 k = 2*ui+4;
00146                                 pccconfig[configs].index = uc[k] & 0x3f;
00147                                 if ( uc[k] & 0x80 ) {
00148                                 //      printf ( "Special config, unsupp. for now\n" );
00149                                         continue;
00150                                 }
00151                                 k+=2;
00152                                 // printf ( "Features: %2x\n", uc[k] );
00153                                 if ( uc[k] & 0x7 ) {
00154                                         // printf ( "Cannot work with Vcc/Timing configs right now\n" );
00155                                         continue;
00156                                 }
00157                                 pccconfig[configs].iowin = pccconfig[configs].iolen = 0;
00158                                 if ( 0 != ( uc[k] & 0x8 ) ) {
00159                                         k+=2;
00160                                         // printf ( "Reading IO config: " );
00161                                         if ( 0 == ( uc[k] & 0x80 ) ) {
00162                                         //      printf ( "Cannot work with auto/io config\n" );
00163                                                 continue;
00164                                         }
00165                                         k+=2;
00166                                         if ( 0 != ( uc[k] & 0x0f ) ) {
00167                                         //      printf ( "Don't support more than 1 iowin right now\n" );
00168                                                 continue;
00169                                         }
00170                                         j = (uc[k] & 0x30) >> 4;
00171                                         m = (uc[k] & 0xc0) >> 6;
00172                                         if ( 3 == j ) ++j;
00173                                         if ( 3 == m ) ++m;
00174                                         k += 2;
00175                                         pccconfig[configs].iowin = 0;
00176                                         pccconfig[configs].iolen = 1;
00177                                         for ( n = 0; n < j; ++n, k+=2 ) {
00178                                                 pccconfig[configs].iowin += uc[k] << (n*8);
00179                                         }
00180                                         for ( n = 0; n < m; ++n, k+=2 ) {
00181                                                 pccconfig[configs].iolen += uc[k] << (n*8);
00182                                         }
00183                                         // printf ( "io %x len %d (%d)\n", pccconfig[configs].iowin, pccconfig[configs].iolen,configs );
00184                                 }
00185                                 for ( j = 0; j < (uc[k] & 3); ++j ) {
00186                                 //      pccconfig[configs].iowin += (uc[k+(2*j)+2]) << (8*j);
00187                                 }
00188                                 ++configs;
00189                         }
00190                 }
00191                 if ( pccsock[i].stringoffset > 0 ) {    // If no identifier, it's not a valid CIS (as of documentation...)
00192                         printf ( "[" );
00193                         for ( k = 0; ( k <  pccsock[i].stringlength ) && ( k < 64 ); ++k ) {
00194                                 j = uc[pccsock[i].stringoffset + 2 * k];
00195                                 printf ( "%c", (j>=' '? j:' ' ) );
00196                         }
00197                         printf ("]\n          is type %d (", pccsock[i].type );
00198                         switch ( pccsock[i].type ) {
00199                           case  0x00:
00200                                 printf ( "MULTI" ); break;
00201                           case  0x01:
00202                                 printf ( "Memory" ); break;
00203                           case  0x02:
00204                                 printf ( "Serial" ); break;
00205                           case  0x03:
00206                                 printf ( "Parallel" ); break;
00207                           case  0x04:
00208                                 printf ( "Fixed" ); break;
00209                           case  0x05:
00210                                 printf ( "Video" ); break;
00211                           case  0x06:
00212                                 printf ( "Network" ); break;
00213                           case  0x07:
00214                                 printf ( "AIMS" ); break;
00215                           case  0x08:
00216                                 printf ( "SCSI" ); break;
00217                           case  0x106: // Special / homebrew to say "Multi/network"
00218                                 printf ( "MULTI, with Network" ); break; // AHTODO find a card for this
00219                           default:
00220                                 printf ( "UNSUPPORTED/UNKNOWN" );
00221                         }
00222                         printf ( ") with %d possible configuration(s)\n", configs );
00223                         // Now set dependency: If it's Network or multi->network, accept
00224                         if ( (inited <= 0 ) && (6 == (0xff & pccsock[i].type) ) && (0 < configs ) ) {
00225                                 printf ( "activating this device with ioport %x-%x (config #%d)\n", 
00226                                 pccconfig[0].iowin, pccconfig[0].iowin+pccconfig[0].iolen-1, pccconfig[0].index );
00227                                 inited = i;
00228                                 // And unmap attrmem ourselves!
00229                                 printf ( "Activating config..." );
00230                                 if ( m=driver[pccsock[i].drivernum].f(SELECTCONFIG,pccsock[i].internalid,pccconfig[0].index,0,&pccconfig[0]) ) {
00231                                         printf ("Failure(%d)!",m); inited = -1;
00232                                         driver[pccsock[i].drivernum].f(UNMAPATTRMEM,pccsock[i].internalid,0,0,0);
00233                                 }
00234                                 printf ( "done!\n" );
00235                                 continue;
00236                         }
00237                 } else {
00238                         printf ( "unsupported - no identifier string found in CIS\n" );
00239                 }
00240                 // unmap the PCMCIA device
00241                 if ( i != inited ) {
00242                     if ( 0 != driver[pccsock[i].drivernum].f(UNMAPATTRMEM,pccsock[i].internalid,0,0,0) ) {
00243                         printf ("PCMCIA controller failed to unmap attribute memory.\n**** SEVERE ERROR CONDITION ****\n" );
00244                         if ( PDEBUG > 2 ) {
00245                                 printf ( "<press key. THIS CONDITION SHOULD BE REPORTED!>\n" ); getchar();
00246                         }
00247                         continue;
00248                     }
00249                 }
00250         }
00251         if ( PDEBUG > 2 ) {
00252                 printf ( "<press key to exit the pcmcia_init_all routine>\n" );
00253                 getchar();
00254         }
00255 
00256 }
00257 
00258 static void     pcmcia_shutdown_all(void) {
00259         int i;
00260         //if ( PDEBUG > 2 ) {printf("<press key to continue>\n" ); getchar(); }
00261         for ( i = 0; i < pccsocks; ++i ) {
00262                 driver[pccsock[i].drivernum].f(SHUTDOWN,pccsock[i].internalid,0,0,0);
00263         }
00264         printf("Shutdown of PCMCIA subsystem completed");
00265 }
00266 
00267 #endif

Generated on Tue Apr 6 20:00:51 2010 for gPXE by  doxygen 1.5.7.1