pcmcia.c
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:10k
源码类别:

Windows CE

开发平台:

Windows_Unix

  1. /*++
  2. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. PARTICULAR PURPOSE.
  6. Copyright (c) 2001. Samsung Electronics, co. ltd  All rights reserved.
  7. --*/
  8. #include <windows.h>
  9. #include <ethdbg.h>
  10. #include <halether.h>
  11. #include "....driverspcmciasockpd.h"
  12. #include "....driverspcmciapd6710.h"
  13. #include <S2440.h> 
  14. #define PCMCIA_ATTR_READ(x)    ((*(volatile unsigned char *)(x+attr_addr)))
  15. #define CIS_R0 0x3F8
  16. #define CARD_IS_UNKNOWN 0
  17. #define CARD_IS_MEMORY 1
  18. #define CARD_IS_ENET 2
  19. #define PD6710_MEM_BASE_ADDRESS     (0xA4000000) //(0x10000000) // nGCS2 (A24 == 0)
  20. #define PD6710_IO_BASE_ADDRESS      (0xA5000000) //(0x11000000) //       (A24 == 1)
  21. #define rPD6710_INDEX (*(volatile unsigned char *)(PD6710_IO_BASE_ADDRESS+0x3e0))
  22. #define rPD6710_DATA (*(volatile unsigned char *)(PD6710_IO_BASE_ADDRESS+0x3e1))
  23. void PCICDataWrite_(unsigned char index, unsigned char data)
  24. {
  25.     rPD6710_INDEX=index;
  26.     rPD6710_DATA=data;
  27. }
  28. unsigned char PCICDataRead_(unsigned char index)
  29. {
  30.     rPD6710_INDEX=index;
  31.     return rPD6710_DATA;
  32. }
  33. void PCICDataModify_(unsigned char index,unsigned char mask,unsigned char data)
  34. {
  35.     rPD6710_INDEX=index;
  36.     rPD6710_DATA=(rPD6710_DATA)&~mask|data;
  37. }
  38. static void Delay(DWORD dwMSecs) 
  39. {
  40. #define MSEC_DELAY_SCALER 0x200
  41. volatile DWORD dwScaledSecs = (dwMSecs * MSEC_DELAY_SCALER);
  42. while (dwScaledSecs)
  43. {
  44. dwScaledSecs--;
  45. }
  46. }
  47. int PrintTuples(unsigned long attr_addr)
  48. {
  49. UCHAR data, tuple_id, *pData;
  50. UCHAR buf[256];
  51. int offset;
  52. int size;
  53. int i, numBytes;
  54. ULONG configBase;
  55. EdbgOutputDebugString("n[Tuple Listing]n");
  56. offset = 0;
  57. while (1) {
  58. tuple_id = PCMCIA_ATTR_READ(offset);
  59. if (tuple_id == 0xFF) {
  60. break; /* End of Chain */
  61. }
  62. EdbgOutputDebugString ("[%x] ID=0x%xn", offset, tuple_id);
  63. offset+=2;
  64. size = PCMCIA_ATTR_READ(offset);
  65. EdbgOutputDebugString ("[%x] SIZE=0x%x", offset, size);
  66. offset+=2;
  67. pData = buf;
  68. for (i=0; i<size; i++, offset+=2) {
  69. data = PCMCIA_ATTR_READ(offset);
  70. if ((i%8) == 0) {
  71. EdbgOutputDebugString ("n[%x] DATA=", offset);
  72. }
  73. *pData ++ = data;
  74. EdbgOutputDebugString ("0x%x ", data);
  75. }
  76. EdbgOutputDebugString ("nn");
  77. pData = buf;
  78. switch (tuple_id) {
  79. case 0x15:
  80. EdbgOutputDebugString ("*  Major version= %sn",
  81. (*pData==4) ? "for 2.01/2.1" : "for PCCard 95");
  82. pData ++;
  83. EdbgOutputDebugString ("*  Minor version= %sn",
  84. (*pData==1) ? "for 2.0/2.01/2.1" : "for PCCard 95");
  85. pData ++;
  86. EdbgOutputDebugString ("*   Menufacturer= %sn", pData);
  87. pData += (strlen (pData) + 1);
  88. EdbgOutputDebugString ("*        Product= %sn", pData);
  89. pData += (strlen (pData) + 1);
  90. EdbgOutputDebugString ("* Product info 1= %sn", pData);
  91. pData += (strlen (pData) + 1);
  92. EdbgOutputDebugString ("* Product info 2= %sn", pData);
  93. EdbgOutputDebugString ("n");
  94. break;
  95. case 0x1a:
  96. numBytes = ((*pData) & 0x3)+1;
  97. pData += 2;
  98. configBase = 0;
  99. for (i=numBytes; i>0; i--) {
  100. configBase <<= 8;
  101. configBase  |= *(pData + i - 1);
  102. }
  103. EdbgOutputDebugString ("* Config Base= 0x%xn", configBase);
  104. EdbgOutputDebugString ("n");
  105. break;
  106. default:
  107. break;
  108. } /* switch-tuple_id */
  109. }
  110. return 0;
  111. } /* PrintTuples */
  112. PVOID PCMCIA_Init(void)
  113. {
  114. unsigned char tmp, uByte;
  115. int Offset;      
  116.     volatile unsigned char *pAttr;
  117. volatile IOPreg *v_pIOPRegs  = (volatile IOPreg *)IOP_BASE;
  118. volatile MEMreg *v_pMEMRegs = (volatile MEMreg *)MEMCTRL_BASE;
  119.     UINT EbootDeviceAddress = 0;
  120.     // Initialize S3C2440 for PD6710
  121.     // EINT3(GPF3) is enabled.
  122.     v_pIOPRegs->rGPFCON = (v_pIOPRegs->rGPFCON & ~(0x3<<6)) | (0x2<<6);
  123.     // EINT3 is PULLUP enabled.
  124.     v_pIOPRegs->rGPFUP = (v_pIOPRegs->rGPFUP & ~(0x1<<3));
  125.     // EINT8(GPG0) is enabled.
  126.     v_pIOPRegs->rGPGCON = (v_pIOPRegs->rGPGCON & ~(0x3<<0)) | (0x2<<0);
  127.     // EINT8 is *not* PULLUP enabled.
  128. v_pIOPRegs->rGPGUP = (v_pIOPRegs->rGPGUP | (0x1<<0));
  129.     // nGCS2=nUB/nLB(nSBHE),nWAIT,16-bit
  130.     v_pMEMRegs->rBWSCON = (v_pMEMRegs->rBWSCON & ~(0xf<<8)) | (0xd<<8);
  131.     // BANK2 access timing
  132.     v_pMEMRegs->rBANKCON2 = ((B6710_Tacs<<13)+(B6710_Tcos<<11)+(B6710_Tacc<<8)+(B6710_Tcoh<<6)
  133.             +(B6710_Tah<<4)+(B6710_Tacp<<2)+(B6710_PMC));
  134.     // EINT8=Level-high triggered, IRQ3.
  135.     // EINT3=Falling Edge triggering -> connected INTR(controller)
  136.     v_pIOPRegs->rEXTINT1=(v_pIOPRegs->rEXTINT1 & ~(0xf<<0)) | (0x1<<0);
  137.     v_pIOPRegs->rEXTINT0=(v_pIOPRegs->rEXTINT0 & ~(0xf<<12)) | (0x2<<12);
  138. //
  139.     // 0x3E0 is the standard Intel compatible socket controller I/O port.
  140.     //
  141. tmp = PCICDataRead_(REG_CHIP_REVISION);
  142. if ((tmp != 0x83) && (tmp != 0x82)) {
  143.      EdbgOutputDebugString("PDCardInitServices CHIP_REVISION = 0x%x, expected = 0x83 !!!rn", tmp);
  144. return(NULL);
  145.     }
  146. //output2card_disable,AUTO_POWER,VCC_POWER_OFF,Vpp1=0V
  147.     PCICDataWrite_(REG_POWER_CONTROL, (0<<7)|(1<<5)|(0<<4)|(0<<0));
  148.      
  149. // Management int -> edge triggering(PULSE), System int -> LEVEL triggering 
  150. PCICDataWrite_(REG_GENERAL_CONTROL, (MISC1_VCC_33|MISC1_PM_IRQ|MISC1_SPK_ENABLE));
  151. // 25Mhz_bypass,low_power_dynamic,IRQ12=drive_LED
  152. // PCICDataWrite_(REG_GLOBAL_CONTROL, (MISC2_BFS|MISC2_LOW_POWER_MODE|MISC2_LED_ENABLE));
  153. PCICDataWrite_(REG_GLOBAL_CONTROL, (MISC2_LOW_POWER_MODE|MISC2_LED_ENABLE));
  154. //status_change_int_enable, card_detect_int_enable, IRQ disabled(IRQ_3)
  155.     PCICDataWrite_(REG_STATUS_CHANGE_INT_CONFIG, (1<<0)|(1<<3)|(3<<4)); 
  156. //IO0=16bit,timing_set_0
  157.     PCICDataWrite_(REG_IO_WINDOW_CONTROL, 1|(1<<1)|(0<<3));
  158.     // I/O windows must never include 3e0h and 3e1h 
  159.     // IO AREA=0x300~0x340(NE2K) -> 0x300~0x340
  160.     PCICDataWrite_(REG_IO_MAP0_START_ADDR_LO, 0x00);
  161.     PCICDataWrite_(REG_IO_MAP0_START_ADDR_HI, 0x3);
  162.     PCICDataWrite_(REG_IO_MAP0_END_ADDR_LO, 0x40);
  163.     PCICDataWrite_(REG_IO_MAP0_END_ADDR_HI, 0x3);           
  164.     PCICDataWrite_(REG_CARD_IO_MAP0_OFFSET_L, 0x0);
  165.     PCICDataWrite_(REG_CARD_IO_MAP0_OFFSET_H, 0x0);
  166.     //If this is memory window, the lowest 64KB should be reserved.
  167. //MEM AREA=0x0~0xFFFF ->0x0~0xFFFFFF
  168.     PCICDataWrite_(REG_MEM_MAP0_START_ADDR_LO, 0x00);  //MEM0=8bit data width
  169.     PCICDataWrite_(REG_MEM_MAP0_START_ADDR_HI, 0x00);
  170.     PCICDataWrite_(REG_MEM_MAP0_END_ADDR_LO, 0x01); //0x0 ~ 0xffff
  171.     PCICDataWrite_(REG_MEM_MAP0_END_ADDR_HI, 0x00|(0<<6));  //timing_set_0
  172.     PCICDataWrite_(REG_MEM_MAP0_ADDR_OFFSET_LO, 0x0);
  173.     PCICDataWrite_(REG_MEM_MAP0_ADDR_OFFSET_HI, 0x0|(1<<6));  //nREG=active 
  174.     
  175. //memory map 0 enabled, I/O map 0 enabled
  176.     PCICDataWrite_(REG_WINDOW_ENABLE, 1|(1<<6));
  177.         
  178.     // before configuring timing register, FIFO should be cleared.
  179. PCICDataWrite_(REG_FIFO_CTRL, FIFO_EMPTY_WRITE); //Flush FIFO
  180.     //default access time is 300ns
  181. PCICDataWrite_(REG_SETUP_TIMING0, 2); //80ns(no spec)
  182. PCICDataWrite_(REG_CMD_TIMING0, 8); //320ns(by spec,25Mhz clock)
  183. PCICDataWrite_(REG_RECOVERY_TIMING0, 2); //80ns(no spec)
  184.     //default access time is 300ns
  185. PCICDataWrite_(REG_SETUP_TIMING1, 2); //80ns(no spec)
  186. PCICDataWrite_(REG_CMD_TIMING1, 8); //320ns(by spec,25Mhz clock)
  187. PCICDataWrite_(REG_RECOVERY_TIMING1, 2); //80ns(no spec)
  188.         
  189.     PCICDataWrite_(REG_CHIP_INFO,0x0);
  190.     if((PCICDataRead_(REG_CHIP_INFO)&0xc0) != 0xc0 || (PCICDataRead_(REG_CHIP_INFO)&0xc0) != 0x00 )
  191.     {
  192.      EdbgOutputDebugString("PD6710 hardware identification error!!!n");
  193.      return(NULL);
  194.     }
  195.  
  196. EbootDeviceAddress = PD6710_MEM_BASE_ADDRESS;
  197.     if((PCICDataRead_(REG_INTERFACE_STATUS)&0xc)==0xc) 
  198.     {
  199. EdbgOutputDebugString("Card is inserted.n");
  200. //For card contact stablization. This delay is needed for stable operation.
  201. //If this delay isn't here, CF card will not be identified.
  202.     if(PCICDataRead_(REG_GENERAL_CONTROL)&0x1)  //MISC_CTRL1[0] 0=3.3V  1=5.0V 
  203. {
  204.      PCICDataModify_(REG_GENERAL_CONTROL,0x2,0x0); //nVCC_5_enabled
  205.      EdbgOutputDebugString("5.0V card is detected.n");
  206.      }
  207. else
  208.      {
  209.      PCICDataModify_(REG_GENERAL_CONTROL,0x2,0x2); //nVCC_3_enabled
  210.      EdbgOutputDebugString("3.3V card is detected.n");
  211.      }
  212.      PCICDataModify_(REG_POWER_CONTROL,(1<<4)|3,(1<<4)|1);
  213.      //VCC_POWER_on,VPP=Vcc(3.3V or 5.0V)
  214.      Delay(20); 
  215.      //Delay 10ms should be here for power stabilization.
  216.      //If this time is not here, the program may halt 
  217. // in case that the pc card has been inserted before power_on   
  218. //But, Why?
  219.     
  220. Delay(2); //RESET should be Hi-Z for minimum 1ms
  221.      PCICDataModify_(REG_INTERRUPT_AND_GENERAL_CONTROL,(1<<6),0); //RESET=active(H)
  222.      PCICDataModify_(REG_POWER_CONTROL,(1<<7),(1<<7));  //output2card_enable(RESET=Hi-Z -> output)
  223.      PCICDataModify_(REG_INTERRUPT_AND_GENERAL_CONTROL,(1<<6),0); //RESET=active(H)
  224.      Delay(1); //wait for minimum 10us
  225.      PCICDataModify_(REG_INTERRUPT_AND_GENERAL_CONTROL, (1<<6),(1<<6)); //RESET=inactive(L)
  226.      Delay(40); //wait for 20ms
  227. // Watch for RDY signal to be asserted by the card.  The NE2000 card will initially come up in memory mode so it's
  228. // safe to watch for RDY.  Later, we put the NE2000 in IO mode.
  229. //
  230.      while(!(PCICDataRead_(REG_INTERFACE_STATUS)&0x20));
  231.      PCICDataModify_(REG_INTERRUPT_AND_GENERAL_CONTROL,(1<<5),(1<<5)); //mem_card -> mem_io_card
  232.      PCICDataModify_(REG_INTERRUPT_AND_GENERAL_CONTROL, 0xf, 0x3); // IREQ == IRQ3.
  233.     
  234.      Delay(200); 
  235. //If this delay isn't here, some CF card will not be identified.
  236.     //In oder to remove this delay, I think, we have to check READY signal.
  237. }
  238. else {
  239. EdbgOutputDebugString("NO card is detected.n");
  240. return(NULL);
  241. }
  242.  
  243. // Switch the NE2000 card to 16-bit IO mode.
  244. //
  245. if(PCICDataRead_(REG_GENERAL_CONTROL)&0x1)
  246. {
  247. // 5V.
  248. //
  249. uByte  = 0x21;
  250. Offset = CIS_R0;
  251. pAttr  = (PUCHAR) EbootDeviceAddress;
  252. pAttr += Offset;
  253. *pAttr = uByte;
  254. uByte  = 0x1;
  255. Offset = CIS_R0 + 2;
  256. pAttr  = (PUCHAR) EbootDeviceAddress;
  257. pAttr += Offset;
  258. *pAttr = uByte;
  259. }
  260. else
  261. {
  262. // 3.3V.
  263. //
  264. uByte  = 0x20;
  265. Offset = CIS_R0;
  266. pAttr  = (PUCHAR) EbootDeviceAddress;
  267. pAttr += Offset;
  268. *pAttr = uByte;
  269. }
  270. Delay(200); 
  271.  
  272. #if 0
  273. // Print tuple information from the PCMCIA/CF card.
  274. //
  275. PrintTuples(EbootDeviceAddress);
  276. #endif
  277.  
  278. return ((PVOID)(PD6710_IO_BASE_ADDRESS + 0x300));
  279. }