Leaked source code of windows server 2003
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.

303 lines
8.8 KiB

  1. /****************************************************************************
  2. ** COPYRIGHT (C) 1994-1997 INTEL CORPORATION **
  3. ** DEVELOPED FOR MICROSOFT BY INTEL CORP., HILLSBORO, OREGON **
  4. ** HTTP://WWW.INTEL.COM/ **
  5. ** THIS FILE IS PART OF THE INTEL ETHEREXPRESS PRO/100B(TM) AND **
  6. ** ETHEREXPRESS PRO/100+(TM) NDIS 5.0 MINIPORT SAMPLE DRIVER **
  7. ****************************************************************************/
  8. /****************************************************************************
  9. Module Name:
  10. eeprom.c
  11. This driver runs on the following hardware:
  12. - 82558 based PCI 10/100Mb ethernet adapters
  13. (aka Intel EtherExpress(TM) PRO Adapters)
  14. Environment:
  15. Kernel Mode - Or whatever is the equivalent on WinNT
  16. Revision History
  17. - JCB 8/14/97 Example Driver Created
  18. - Dchen 11-01-99 Modified for the new sample driver
  19. *****************************************************************************/
  20. #include "precomp.h"
  21. #pragma hdrstop
  22. #pragma warning (disable: 4244 4514)
  23. #define EEPROM_MAX_SIZE 256
  24. //*****************************************************************************
  25. //
  26. // I/O based Read EEPROM Routines
  27. //
  28. //*****************************************************************************
  29. //-----------------------------------------------------------------------------
  30. // Procedure: EEpromAddressSize
  31. //
  32. // Description: determines the number of bits in an address for the eeprom
  33. // acceptable values are 64, 128, and 256
  34. //
  35. // Arguments:
  36. // Size -- size of the eeprom
  37. //
  38. // Returns:
  39. // bits in an address for that size eeprom
  40. //-----------------------------------------------------------------------------
  41. USHORT GetEEpromAddressSize(
  42. IN USHORT Size)
  43. {
  44. switch (Size)
  45. {
  46. case 64: return 6;
  47. case 128: return 7;
  48. case 256: return 8;
  49. }
  50. return 0;
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Procedure: GetEEpromSize
  54. //
  55. // Description: This routine determines the size of the EEPROM.
  56. //
  57. // Arguments:
  58. // Reg - EEPROM word to read.
  59. //
  60. // Returns:
  61. // Size of the EEPROM, or zero if error.
  62. //-----------------------------------------------------------------------------
  63. USHORT GetEEpromSize(
  64. IN PUCHAR CSRBaseIoAddress)
  65. {
  66. USHORT x, data;
  67. USHORT size = 1;
  68. // select EEPROM, reset bits, set EECS
  69. x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
  70. x &= ~(EEDI | EEDO | EESK);
  71. x |= EECS;
  72. WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x);
  73. // write the read opcode
  74. ShiftOutBits(EEPROM_READ_OPCODE, 3, CSRBaseIoAddress);
  75. // experiment to discover the size of the eeprom. request register zero
  76. // and wait for the eeprom to tell us it has accepted the entire address.
  77. x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
  78. do
  79. {
  80. size *= 2; // each bit of address doubles eeprom size
  81. x |= EEDO; // set bit to detect "dummy zero"
  82. x &= ~EEDI; // address consists of all zeros
  83. WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x);
  84. NdisStallExecution(100);
  85. RaiseClock(&x, CSRBaseIoAddress);
  86. LowerClock(&x, CSRBaseIoAddress);
  87. // check for "dummy zero"
  88. x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
  89. if (size > EEPROM_MAX_SIZE)
  90. {
  91. size = 0;
  92. break;
  93. }
  94. }
  95. while (x & EEDO);
  96. // Now read the data (16 bits) in from the selected EEPROM word
  97. data = ShiftInBits(CSRBaseIoAddress);
  98. EEpromCleanup(CSRBaseIoAddress);
  99. return size;
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Procedure: ReadEEprom
  103. //
  104. // Description: This routine serially reads one word out of the EEPROM.
  105. //
  106. // Arguments:
  107. // Reg - EEPROM word to read.
  108. //
  109. // Returns:
  110. // Contents of EEPROM word (Reg).
  111. //-----------------------------------------------------------------------------
  112. USHORT ReadEEprom(
  113. IN PUCHAR CSRBaseIoAddress,
  114. IN USHORT Reg,
  115. IN USHORT AddressSize)
  116. {
  117. USHORT x;
  118. USHORT data;
  119. // select EEPROM, reset bits, set EECS
  120. x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
  121. x &= ~(EEDI | EEDO | EESK);
  122. x |= EECS;
  123. WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x);
  124. // write the read opcode and register number in that order
  125. // The opcode is 3bits in length, reg is 6 bits long
  126. ShiftOutBits(EEPROM_READ_OPCODE, 3, CSRBaseIoAddress);
  127. ShiftOutBits(Reg, AddressSize, CSRBaseIoAddress);
  128. // Now read the data (16 bits) in from the selected EEPROM word
  129. data = ShiftInBits(CSRBaseIoAddress);
  130. EEpromCleanup(CSRBaseIoAddress);
  131. return data;
  132. }
  133. //-----------------------------------------------------------------------------
  134. // Procedure: ShiftOutBits
  135. //
  136. // Description: This routine shifts data bits out to the EEPROM.
  137. //
  138. // Arguments:
  139. // data - data to send to the EEPROM.
  140. // count - number of data bits to shift out.
  141. //
  142. // Returns: (none)
  143. //-----------------------------------------------------------------------------
  144. VOID ShiftOutBits(
  145. IN USHORT data,
  146. IN USHORT count,
  147. IN PUCHAR CSRBaseIoAddress)
  148. {
  149. USHORT x,mask;
  150. mask = 0x01 << (count - 1);
  151. x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
  152. x &= ~(EEDO | EEDI);
  153. do
  154. {
  155. x &= ~EEDI;
  156. if(data & mask)
  157. x |= EEDI;
  158. WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x);
  159. NdisStallExecution(100);
  160. RaiseClock(&x, CSRBaseIoAddress);
  161. LowerClock(&x, CSRBaseIoAddress);
  162. mask = mask >> 1;
  163. } while(mask);
  164. x &= ~EEDI;
  165. WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x);
  166. }
  167. //-----------------------------------------------------------------------------
  168. // Procedure: ShiftInBits
  169. //
  170. // Description: This routine shifts data bits in from the EEPROM.
  171. //
  172. // Arguments:
  173. //
  174. // Returns:
  175. // The contents of that particular EEPROM word
  176. //-----------------------------------------------------------------------------
  177. USHORT ShiftInBits(
  178. IN PUCHAR CSRBaseIoAddress)
  179. {
  180. USHORT x,d,i;
  181. x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
  182. x &= ~( EEDO | EEDI);
  183. d = 0;
  184. for(i=0; i<16; i++)
  185. {
  186. d = d << 1;
  187. RaiseClock(&x, CSRBaseIoAddress);
  188. x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
  189. x &= ~(EEDI);
  190. if(x & EEDO)
  191. d |= 1;
  192. LowerClock(&x, CSRBaseIoAddress);
  193. }
  194. return d;
  195. }
  196. //-----------------------------------------------------------------------------
  197. // Procedure: RaiseClock
  198. //
  199. // Description: This routine raises the EEPOM's clock input (EESK)
  200. //
  201. // Arguments:
  202. // x - Ptr to the EEPROM control register's current value
  203. //
  204. // Returns: (none)
  205. //-----------------------------------------------------------------------------
  206. VOID RaiseClock(
  207. IN OUT USHORT *x,
  208. IN PUCHAR CSRBaseIoAddress)
  209. {
  210. *x = *x | EESK;
  211. WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), *x);
  212. NdisStallExecution(100);
  213. }
  214. //-----------------------------------------------------------------------------
  215. // Procedure: LowerClock
  216. //
  217. // Description: This routine lower's the EEPOM's clock input (EESK)
  218. //
  219. // Arguments:
  220. // x - Ptr to the EEPROM control register's current value
  221. //
  222. // Returns: (none)
  223. //-----------------------------------------------------------------------------
  224. VOID LowerClock(
  225. IN OUT USHORT *x,
  226. IN PUCHAR CSRBaseIoAddress)
  227. {
  228. *x = *x & ~EESK;
  229. WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), *x);
  230. NdisStallExecution(100);
  231. }
  232. //-----------------------------------------------------------------------------
  233. // Procedure: EEpromCleanup
  234. //
  235. // Description: This routine returns the EEPROM to an idle state
  236. //
  237. // Arguments:
  238. //
  239. // Returns: (none)
  240. //-----------------------------------------------------------------------------
  241. VOID EEpromCleanup(
  242. IN PUCHAR CSRBaseIoAddress)
  243. {
  244. USHORT x;
  245. x = READ_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG));
  246. x &= ~(EECS | EEDI);
  247. WRITE_PORT_USHORT((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x);
  248. RaiseClock(&x, CSRBaseIoAddress);
  249. LowerClock(&x, CSRBaseIoAddress);
  250. }