You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pcmcia.c 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. #if 0
  2. /*
  3. * pcmcia.c
  4. *
  5. * PCMCIA support routines for etherboot - generic stuff
  6. *
  7. * This code has partly be taken from the linux kernel sources, .../drivers/pcmcia/
  8. * Started & put together by
  9. * Anselm Martin Hoffmeister
  10. * Stockholm Projekt Computer-Service
  11. * Sankt Augustin / Bonn, Germany
  12. *
  13. * Distributed under GPL2
  14. */
  15. /*
  16. *
  17. *
  18. * ******************************
  19. * PLEASE DO NOT YET WORK ON THIS
  20. * ******************************
  21. *
  22. * I'm still fixing it up on every end, so we most probably would interfere
  23. * at some point. If there's anything obvious or better, not-so-obvious,
  24. * please contact me by e-mail: anselm (AT) hoffmeister (DOT) be *THANKS*
  25. */
  26. FILE_LICENCE ( GPL2_ONLY );
  27. #include <stdio.h>
  28. #include <pcmcia.h>
  29. #include <i82365.h>
  30. #define CODE_STATUS "alpha"
  31. #define CODE_VERSION "0.1.3"
  32. #include <pcmcia-opts.h>
  33. #include <ipxe/console.h>
  34. #include <ipxe/init.h>
  35. int sockets; /* AHTODO: Phase this out! */
  36. u_int pccsocks;
  37. struct pccsock_t pccsock[MAXPCCSOCKS];
  38. int inited = -1;
  39. struct pcc_config_t pccconfig[MAXPCCCONFIGS];
  40. struct driver_interact_t driver[] = {
  41. #ifdef SUPPORT_I82365
  42. { I82365, i82365_interfacer, "Intel_82365" },
  43. #endif
  44. };
  45. #define NUM_DRIVERS (sizeof(driver)/(sizeof(struct driver_interact_t)))
  46. void sleepticks(int numticks ) {
  47. u_int tmo;
  48. for (tmo = currticks()+numticks; currticks() < tmo; ) {
  49. }
  50. return;
  51. }
  52. static void pcmcia_init_all(void) {
  53. u_int i, j, k, l, m, n, ui, configs = 0;
  54. u_int multicard[8];
  55. u_char *uc, upc;
  56. if ( PDEBUG > 0 ) printf("Initializing PCMCIA subsystem (code-status: " CODE_STATUS ", Version " CODE_VERSION ")\n");
  57. if ( PDEBUG > 2 ) {
  58. printf ( "Supporting %d driver(s): ", NUM_DRIVERS );
  59. for ( i = 0; i < NUM_DRIVERS; ++i ) {
  60. printf ( "[%s] ", driver[i].name );
  61. }
  62. printf ( "\n" );
  63. }
  64. pccsocks = 0;
  65. sockets = 0;
  66. // Init all drivers in the driver[] array:
  67. for ( i = 0; i < NUM_DRIVERS; ++i ) {
  68. driver[i].f(INIT,0,i,0,0); // init needs no params. It uses pccsocks and pccsock[].
  69. // Only i tells it which driver_id itself is.
  70. }
  71. for ( i = 0; i < pccsocks; ++i ) {
  72. printf ( "Socket %d: ", i );
  73. if ( pccsock[i].status != HASCARD ) {
  74. printf ( "is %s: skipping\n", pccsock[i].status == EMPTY? "empty":"[status unknown]" );
  75. continue;
  76. }
  77. if ( 0 != driver[pccsock[i].drivernum].f(MAPATTRMEM,pccsock[i].internalid,MAP_ATTRMEM_TO, MAP_ATTRMEM_LEN,0 ) ) {
  78. printf ("PCMCIA controller failed to map attribute memory.\n**** SEVERE ERROR CONDITION. Skipping controller.\n" );
  79. if ( PDEBUG > 2 ) {
  80. printf ( "<press key. THIS CONDITION SHOULD BE REPORTED!>\n" ); getchar();
  81. }
  82. continue;
  83. }
  84. // parse configuration information
  85. uc = ioremap ( MAP_ATTRMEM_TO, MAP_ATTRMEM_LEN );
  86. pccsock[i].stringoffset = pccsock[i].configoffset = pccsock[i].stringlength = 0;
  87. pccsock[i].type = 0xff;
  88. for ( l = 0; l < 8; ++l ) multicard[l] = 0;
  89. sleepticks(2);
  90. for ( l = ui = 0; ui < 0x800; ui += uc[(2*ui)+2] + 2 ) {
  91. if ( uc[(2*ui)] == 0xff ) {
  92. break;
  93. }
  94. // This loop is complete rubbish AFAICS.
  95. // But without it, my test system won't come up.
  96. // It's too bad to develop on broken hardware
  97. // - Anselm
  98. }
  99. sleepticks(2);
  100. configs = 0;
  101. inited = -1;
  102. for ( l = ui = 0; ui < 0x800; ui += uc[(2*ui)+2] + 2 ) {
  103. if ( uc[(2*ui)] == 0xff ) break;
  104. else if ( uc[2*ui] == 0x15 ) {
  105. for ( k = 2 * ( ui + 2 ); ( uc[k] <= ' ' ) && ( k < ( 2 * ( uc[2*(ui+1)] + ui + 2 ) ) ) ; k += 2 ) { ; }
  106. pccsock[i].stringoffset = k;
  107. pccsock[i].stringlength = ( 2 * ( ui + 2 + uc[(2*ui)+2] ) - k ) / 2;
  108. } else if ( uc[2*ui] == 0x21 ) {
  109. pccsock[i].type = uc[(2*ui)+4];
  110. } else if ( uc[2*ui] == 0x1a ) { // Configuration map
  111. printf ( "\nConfig map 0x1a found [" );
  112. for ( k = 0; k < uc[2*(ui+1)]; ++k ) {
  113. printf ( "%02x ", uc[2*(ui+k+2)] );
  114. }
  115. printf ( "]\nHighest config available is %d\n", uc[2*(ui+3)] );
  116. m = uc[2*(ui+2)];
  117. pccsock[i].configoffset = 0;
  118. for ( j = 0; j <= (m & 3); ++j ) {
  119. pccsock[i].configoffset += uc[2*(ui+4+j)] << (8*j);
  120. }
  121. pccsock[i].rmask0 = 0;
  122. for ( j = 0; j <= ( ( ( m & 0x3c ) >> 2 ) & 3 ); ++j ) {
  123. pccsock[i].rmask0 += uc[2*(ui+5+(m&3)+j)] << (8*j);
  124. }
  125. j = pccsock[i].rmask0;
  126. printf ( "Config offset is %x, card has regs: < %s%s%s%s%s>\n", pccsock[i].configoffset,
  127. j & 1 ? "COR ":"", j & 2 ? "CCSR ":"", j & 4 ? "PRR ":"", j & 8 ? "SCR ":"", j & 16? "ESR ":"" );
  128. printf ( "COR + CCSR contents (si/du) %x %x/%x %x\n", uc[pccsock[i].configoffset+0],
  129. uc[pccsock[i].configoffset+2],uc[pccsock[i].configoffset*2],uc[(pccsock[i].configoffset*2)+2] );
  130. printf ( " " );
  131. } else if ( uc[2*ui] == 0x1b ) { // Configuration data entry
  132. //printf ( "Config data 0x1b found [\n" );getchar();
  133. for ( k = 0; k < uc[2*(ui+1)]; ++k ) {
  134. // printf ( "%02x ", uc[2*(ui+k+2)] );
  135. }
  136. // Parse this tuple into pccconfig[configs]
  137. // printf ( "]\n" );
  138. if ( configs == MAXPCCCONFIGS ) continue;
  139. k = 2*ui+4;
  140. pccconfig[configs].index = uc[k] & 0x3f;
  141. if ( uc[k] & 0x80 ) {
  142. // printf ( "Special config, unsupp. for now\n" );
  143. continue;
  144. }
  145. k+=2;
  146. // printf ( "Features: %2x\n", uc[k] );
  147. if ( uc[k] & 0x7 ) {
  148. // printf ( "Cannot work with Vcc/Timing configs right now\n" );
  149. continue;
  150. }
  151. pccconfig[configs].iowin = pccconfig[configs].iolen = 0;
  152. if ( 0 != ( uc[k] & 0x8 ) ) {
  153. k+=2;
  154. // printf ( "Reading IO config: " );
  155. if ( 0 == ( uc[k] & 0x80 ) ) {
  156. // printf ( "Cannot work with auto/io config\n" );
  157. continue;
  158. }
  159. k+=2;
  160. if ( 0 != ( uc[k] & 0x0f ) ) {
  161. // printf ( "Don't support more than 1 iowin right now\n" );
  162. continue;
  163. }
  164. j = (uc[k] & 0x30) >> 4;
  165. m = (uc[k] & 0xc0) >> 6;
  166. if ( 3 == j ) ++j;
  167. if ( 3 == m ) ++m;
  168. k += 2;
  169. pccconfig[configs].iowin = 0;
  170. pccconfig[configs].iolen = 1;
  171. for ( n = 0; n < j; ++n, k+=2 ) {
  172. pccconfig[configs].iowin += uc[k] << (n*8);
  173. }
  174. for ( n = 0; n < m; ++n, k+=2 ) {
  175. pccconfig[configs].iolen += uc[k] << (n*8);
  176. }
  177. // printf ( "io %x len %d (%d)\n", pccconfig[configs].iowin, pccconfig[configs].iolen,configs );
  178. }
  179. for ( j = 0; j < (uc[k] & 3); ++j ) {
  180. // pccconfig[configs].iowin += (uc[k+(2*j)+2]) << (8*j);
  181. }
  182. ++configs;
  183. }
  184. }
  185. if ( pccsock[i].stringoffset > 0 ) { // If no identifier, it's not a valid CIS (as of documentation...)
  186. printf ( "[" );
  187. for ( k = 0; ( k < pccsock[i].stringlength ) && ( k < 64 ); ++k ) {
  188. j = uc[pccsock[i].stringoffset + 2 * k];
  189. printf ( "%c", (j>=' '? j:' ' ) );
  190. }
  191. printf ("]\n is type %d (", pccsock[i].type );
  192. switch ( pccsock[i].type ) {
  193. case 0x00:
  194. printf ( "MULTI" ); break;
  195. case 0x01:
  196. printf ( "Memory" ); break;
  197. case 0x02:
  198. printf ( "Serial" ); break;
  199. case 0x03:
  200. printf ( "Parallel" ); break;
  201. case 0x04:
  202. printf ( "Fixed" ); break;
  203. case 0x05:
  204. printf ( "Video" ); break;
  205. case 0x06:
  206. printf ( "Network" ); break;
  207. case 0x07:
  208. printf ( "AIMS" ); break;
  209. case 0x08:
  210. printf ( "SCSI" ); break;
  211. case 0x106: // Special / homebrew to say "Multi/network"
  212. printf ( "MULTI, with Network" ); break; // AHTODO find a card for this
  213. default:
  214. printf ( "UNSUPPORTED/UNKNOWN" );
  215. }
  216. printf ( ") with %d possible configuration(s)\n", configs );
  217. // Now set dependency: If it's Network or multi->network, accept
  218. if ( (inited <= 0 ) && (6 == (0xff & pccsock[i].type) ) && (0 < configs ) ) {
  219. printf ( "activating this device with ioport %x-%x (config #%d)\n",
  220. pccconfig[0].iowin, pccconfig[0].iowin+pccconfig[0].iolen-1, pccconfig[0].index );
  221. inited = i;
  222. // And unmap attrmem ourselves!
  223. printf ( "Activating config..." );
  224. if ( m=driver[pccsock[i].drivernum].f(SELECTCONFIG,pccsock[i].internalid,pccconfig[0].index,0,&pccconfig[0]) ) {
  225. printf ("Failure(%d)!",m); inited = -1;
  226. driver[pccsock[i].drivernum].f(UNMAPATTRMEM,pccsock[i].internalid,0,0,0);
  227. }
  228. printf ( "done!\n" );
  229. continue;
  230. }
  231. } else {
  232. printf ( "unsupported - no identifier string found in CIS\n" );
  233. }
  234. // unmap the PCMCIA device
  235. if ( i != inited ) {
  236. if ( 0 != driver[pccsock[i].drivernum].f(UNMAPATTRMEM,pccsock[i].internalid,0,0,0) ) {
  237. printf ("PCMCIA controller failed to unmap attribute memory.\n**** SEVERE ERROR CONDITION ****\n" );
  238. if ( PDEBUG > 2 ) {
  239. printf ( "<press key. THIS CONDITION SHOULD BE REPORTED!>\n" ); getchar();
  240. }
  241. continue;
  242. }
  243. }
  244. }
  245. if ( PDEBUG > 2 ) {
  246. printf ( "<press key to exit the pcmcia_init_all routine>\n" );
  247. getchar();
  248. }
  249. }
  250. static void pcmcia_shutdown_all(void) {
  251. int i;
  252. //if ( PDEBUG > 2 ) {printf("<press key to continue>\n" ); getchar(); }
  253. for ( i = 0; i < pccsocks; ++i ) {
  254. driver[pccsock[i].drivernum].f(SHUTDOWN,pccsock[i].internalid,0,0,0);
  255. }
  256. printf("Shutdown of PCMCIA subsystem completed");
  257. }
  258. #endif