Source code of Windows XP (NT5)
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.

422 lines
12 KiB

  1. /*
  2. ************************************************************************
  3. *
  4. * REQUEST.c
  5. *
  6. *
  7. * (C) Copyright 1996 National Semiconductor Corp.
  8. * (C) Copyright 1996 Microsoft Corp.
  9. *
  10. *
  11. * (ep)
  12. *
  13. *************************************************************************
  14. */
  15. #include "nsc.h"
  16. #include "newdong.h"
  17. const NDIS_OID NSCGlobalSupportedOids[] = {
  18. OID_GEN_SUPPORTED_LIST,
  19. OID_GEN_HARDWARE_STATUS,
  20. OID_GEN_MEDIA_SUPPORTED,
  21. OID_GEN_MEDIA_IN_USE,
  22. OID_GEN_MAXIMUM_LOOKAHEAD,
  23. OID_GEN_MAXIMUM_FRAME_SIZE,
  24. OID_GEN_MAXIMUM_SEND_PACKETS,
  25. OID_GEN_MAXIMUM_TOTAL_SIZE,
  26. OID_GEN_MAC_OPTIONS,
  27. OID_GEN_PROTOCOL_OPTIONS,
  28. OID_GEN_LINK_SPEED,
  29. OID_GEN_TRANSMIT_BUFFER_SPACE,
  30. OID_GEN_RECEIVE_BUFFER_SPACE,
  31. OID_GEN_TRANSMIT_BLOCK_SIZE,
  32. OID_GEN_RECEIVE_BLOCK_SIZE,
  33. OID_GEN_VENDOR_DESCRIPTION,
  34. OID_GEN_VENDOR_DRIVER_VERSION,
  35. OID_GEN_DRIVER_VERSION,
  36. OID_GEN_CURRENT_PACKET_FILTER,
  37. OID_GEN_CURRENT_LOOKAHEAD,
  38. OID_GEN_MEDIA_CONNECT_STATUS,
  39. OID_IRDA_RECEIVING,
  40. OID_IRDA_SUPPORTED_SPEEDS,
  41. OID_IRDA_LINK_SPEED,
  42. OID_IRDA_MEDIA_BUSY,
  43. OID_IRDA_TURNAROUND_TIME,
  44. OID_IRDA_MAX_RECEIVE_WINDOW_SIZE,
  45. OID_IRDA_EXTRA_RCV_BOFS,
  46. OID_IRDA_MAX_SEND_WINDOW_SIZE
  47. };
  48. //////////////////////////////////////////////////////////////////////////
  49. // //
  50. // Function: MiniportQueryInformation //
  51. // //
  52. // Description: //
  53. // Query the capabilities and status of the miniport driver. //
  54. // //
  55. //////////////////////////////////////////////////////////////////////////
  56. NDIS_STATUS MiniportQueryInformation (
  57. IN NDIS_HANDLE MiniportAdapterContext,
  58. IN NDIS_OID Oid,
  59. IN PVOID InformationBuffer,
  60. IN ULONG InformationBufferLength,
  61. OUT PULONG BytesWritten,
  62. OUT PULONG BytesNeeded)
  63. {
  64. NDIS_STATUS result = NDIS_STATUS_SUCCESS;
  65. IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
  66. INT i, speeds, speedSupported;
  67. UINT *infoPtr;
  68. NDIS_MEDIUM Medium = NdisMediumIrda;
  69. ULONG GenericUlong;
  70. PVOID SourceBuffer = (PVOID) (&GenericUlong);
  71. ULONG SourceLength = sizeof(ULONG);
  72. ULONG BaudRateTable[NUM_BAUDRATES];
  73. switch (Oid){
  74. case OID_GEN_SUPPORTED_LIST:
  75. SourceBuffer = (PVOID) (NSCGlobalSupportedOids);
  76. SourceLength = sizeof(NSCGlobalSupportedOids);
  77. break;
  78. case OID_GEN_HARDWARE_STATUS:
  79. GenericUlong = thisDev->hardwareStatus;
  80. break;
  81. case OID_GEN_MEDIA_SUPPORTED:
  82. case OID_GEN_MEDIA_IN_USE:
  83. SourceBuffer = (PVOID) (&Medium);
  84. SourceLength = sizeof(NDIS_MEDIUM);
  85. break;
  86. case OID_IRDA_RECEIVING:
  87. DBGOUT(("MiniportQueryInformation(OID_IRDA_RECEIVING)"));
  88. GenericUlong = (ULONG)thisDev->nowReceiving;
  89. break;
  90. case OID_IRDA_SUPPORTED_SPEEDS:
  91. DBGOUT(("MiniportQueryInformation(OID_IRDA_SUPPORTED_SPEEDS)"));
  92. speeds = thisDev->portInfo.hwCaps.supportedSpeedsMask &
  93. thisDev->AllowedSpeedMask &
  94. ALL_IRDA_SPEEDS;
  95. for (i = 0, infoPtr = (PUINT)BaudRateTable, SourceLength=0;
  96. (i < NUM_BAUDRATES) && speeds;
  97. i++){
  98. if (supportedBaudRateTable[i].ndisCode & speeds){
  99. *infoPtr++ = supportedBaudRateTable[i].bitsPerSec;
  100. SourceLength += sizeof(UINT);
  101. speeds &= ~supportedBaudRateTable[i].ndisCode;
  102. DBGOUT((" - supporting speed %d bps", supportedBaudRateTable[i].bitsPerSec));
  103. }
  104. }
  105. SourceBuffer = (PVOID) BaudRateTable;
  106. break;
  107. case OID_GEN_LINK_SPEED:
  108. // The maximum speed of NIC is 4Mbps
  109. GenericUlong = 40000; // 100bps increments
  110. break;
  111. case OID_IRDA_LINK_SPEED:
  112. DBGOUT(("MiniportQueryInformation(OID_IRDA_LINK_SPEED)"));
  113. if (thisDev->linkSpeedInfo){
  114. GenericUlong = (ULONG)thisDev->linkSpeedInfo->bitsPerSec;
  115. }
  116. else {
  117. GenericUlong = DEFAULT_BAUD_RATE;
  118. }
  119. break;
  120. case OID_IRDA_MEDIA_BUSY:
  121. DBGOUT(("MiniportQueryInformation(OID_IRDA_MEDIA_BUSY)"));
  122. GenericUlong = (UINT)thisDev->mediaBusy;
  123. break;
  124. case OID_GEN_CURRENT_LOOKAHEAD:
  125. case OID_GEN_MAXIMUM_LOOKAHEAD:
  126. DBGOUT(("MiniportQueryInformation(OID_GEN_MAXIMUM_LOOKAHEAD)"));
  127. GenericUlong = MAX_I_DATA_SIZE;
  128. break;
  129. case OID_GEN_MAXIMUM_TOTAL_SIZE:
  130. case OID_GEN_TRANSMIT_BLOCK_SIZE:
  131. case OID_GEN_RECEIVE_BLOCK_SIZE:
  132. case OID_GEN_MAXIMUM_FRAME_SIZE:
  133. DBGOUT(("MiniportQueryInformation(OID_GEN_MAXIMUM_LOOKAHEAD)"));
  134. // Normally there's some difference in these values, based on the
  135. // MAC header, but IrDA doesn't have one.
  136. GenericUlong = MAX_I_DATA_SIZE;
  137. break;
  138. case OID_GEN_RECEIVE_BUFFER_SPACE:
  139. case OID_GEN_TRANSMIT_BUFFER_SPACE:
  140. GenericUlong = (ULONG) (MAX_IRDA_DATA_SIZE * 8);
  141. break;
  142. case OID_GEN_MAC_OPTIONS:
  143. DBGOUT(("MiniportQueryInformation(OID_GEN_MAC_OPTIONS)"));
  144. GenericUlong = 0;
  145. break;
  146. case OID_GEN_MAXIMUM_SEND_PACKETS:
  147. DBGOUT(("MiniportQueryInformation(OID_GEN_MAXIMUM_SEND_PACKETS)"));
  148. GenericUlong = 16;
  149. break;
  150. case OID_IRDA_TURNAROUND_TIME:
  151. // Indicate the amount of time that the transceiver needs
  152. // to recuperate after a send.
  153. DBGOUT(("MiniportQueryInformation(OID_IRDA_TURNAROUND_TIME)"));
  154. GenericUlong =
  155. (ULONG)thisDev->portInfo.hwCaps.turnAroundTime_usec;
  156. break;
  157. case OID_IRDA_EXTRA_RCV_BOFS:
  158. // Pass back the number of _extra_ BOFs to be prepended
  159. // to packets sent to this unit at 115.2 baud, the
  160. // maximum Slow IR speed. This will be scaled for other
  161. // speed according to the table in the
  162. // Infrared Extensions to NDIS' spec.
  163. DBGOUT(("MiniportQueryInformation(OID_IRDA_EXTRA_RCV_BOFS)"));
  164. GenericUlong = (ULONG)thisDev->portInfo.hwCaps.extraBOFsRequired;
  165. break;
  166. case OID_GEN_CURRENT_PACKET_FILTER:
  167. DBGOUT(("MiniportQueryInformation(OID_GEN_CURRENT_PACKET_FILTER)"));
  168. GenericUlong = NDIS_PACKET_TYPE_PROMISCUOUS;
  169. break;
  170. case OID_IRDA_MAX_RECEIVE_WINDOW_SIZE:
  171. DBGOUT(("MiniportQueryInformation(OID_IRDA_MAX_RECEIVE_WINDOW_SIZE)"));
  172. GenericUlong = MAX_RX_PACKETS;
  173. //GenericUlong = 1;
  174. break;
  175. case OID_GEN_VENDOR_DESCRIPTION:
  176. SourceBuffer = (PVOID)"NSC Infrared Port";
  177. SourceLength = 18;
  178. break;
  179. case OID_GEN_VENDOR_DRIVER_VERSION:
  180. // This value is used to know whether to update driver.
  181. GenericUlong = (NSC_MAJOR_VERSION << 16) +
  182. (NSC_MINOR_VERSION << 8) +
  183. NSC_LETTER_VERSION;
  184. break;
  185. case OID_GEN_DRIVER_VERSION:
  186. GenericUlong = (NDIS_MAJOR_VERSION << 8) + NDIS_MINOR_VERSION;
  187. SourceLength = 2;
  188. break;
  189. case OID_IRDA_MAX_SEND_WINDOW_SIZE:
  190. GenericUlong = 7;
  191. break;
  192. case OID_GEN_MEDIA_CONNECT_STATUS:
  193. GenericUlong = (ULONG) NdisMediaStateConnected;
  194. break;
  195. default:
  196. DBGERR(("MiniportQueryInformation(%d=0x%x), unsupported OID", Oid, Oid));
  197. result = NDIS_STATUS_NOT_SUPPORTED;
  198. break;
  199. }
  200. if (result == NDIS_STATUS_SUCCESS) {
  201. if (SourceLength > InformationBufferLength) {
  202. *BytesNeeded = SourceLength;
  203. result = NDIS_STATUS_INVALID_LENGTH;
  204. }
  205. else {
  206. *BytesNeeded = 0;
  207. *BytesWritten = SourceLength;
  208. NdisMoveMemory(InformationBuffer, SourceBuffer, SourceLength);
  209. }
  210. }
  211. DBGOUT(("MiniportQueryInformation succeeded (info <- %d)", *(UINT *)InformationBuffer));
  212. return result;
  213. }
  214. //////////////////////////////////////////////////////////////////////////
  215. // //
  216. // Function: MiniportSetInformation //
  217. // //
  218. // Description: //
  219. // Allow other layers of the network software (e.g., a transport //
  220. // driver) to control the miniport driver by changing information that //
  221. // the miniport driver maintains in its OIDs, such as the packet //
  222. // or multicast addresses. //
  223. // //
  224. //////////////////////////////////////////////////////////////////////////
  225. NDIS_STATUS MiniportSetInformation (
  226. IN NDIS_HANDLE MiniportAdapterContext,
  227. IN NDIS_OID Oid,
  228. IN PVOID InformationBuffer,
  229. IN ULONG InformationBufferLength,
  230. OUT PULONG BytesRead,
  231. OUT PULONG BytesNeeded)
  232. {
  233. NDIS_STATUS result = NDIS_STATUS_SUCCESS;
  234. IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
  235. UINT i,speedSupported;
  236. const baudRateInfo * CurrentLinkSpeed;
  237. if (InformationBufferLength >= sizeof(UINT)){
  238. UINT info = *(UINT *)InformationBuffer;
  239. *BytesRead = sizeof(UINT);
  240. *BytesNeeded = 0;
  241. switch (Oid){
  242. case OID_IRDA_LINK_SPEED:
  243. DBGOUT(("MiniportSetInformation(OID_IRDA_LINK_SPEED, %xh)",
  244. info));
  245. result = NDIS_STATUS_INVALID_DATA;
  246. CurrentLinkSpeed=thisDev->linkSpeedInfo;
  247. // Find the appropriate speed and set it
  248. speedSupported = NUM_BAUDRATES;
  249. for (i = 0; i < speedSupported; i++){
  250. if (supportedBaudRateTable[i].bitsPerSec == info){
  251. thisDev->linkSpeedInfo = &supportedBaudRateTable[i];
  252. result = NDIS_STATUS_SUCCESS;
  253. break;
  254. }
  255. }
  256. if (result == NDIS_STATUS_SUCCESS){
  257. if (CurrentLinkSpeed != thisDev->linkSpeedInfo) {
  258. //
  259. // different from the current
  260. //
  261. BOOLEAN DoItNow=TRUE;
  262. NdisAcquireSpinLock(&thisDev->QueueLock);
  263. if (!IsListEmpty(&thisDev->SendQueue)){
  264. //
  265. // packets queued, change after this one
  266. //
  267. thisDev->lastPacketAtOldSpeed = CONTAINING_RECORD(thisDev->SendQueue.Blink,
  268. NDIS_PACKET,
  269. MiniportReserved);
  270. DBGOUT(("delaying set-speed because send pkts queued"));
  271. DoItNow=FALSE;
  272. } else {
  273. //
  274. // no packets in the queue
  275. //
  276. if (thisDev->CurrentPacket != NULL) {
  277. //
  278. // the current packet is the only one
  279. //
  280. thisDev->lastPacketAtOldSpeed=thisDev->CurrentPacket;
  281. thisDev->setSpeedAfterCurrentSendPacket = TRUE;
  282. DBGOUT(("delaying set-speed because send pkts queued"));
  283. DoItNow=FALSE;
  284. }
  285. }
  286. if (DoItNow) {
  287. if (!SetSpeed(thisDev)){
  288. result = NDIS_STATUS_FAILURE;
  289. }
  290. thisDev->TransmitIsIdle=FALSE;
  291. }
  292. NdisReleaseSpinLock(&thisDev->QueueLock);
  293. if (DoItNow) {
  294. ProcessSendQueue(thisDev);
  295. }
  296. }
  297. }
  298. else {
  299. *BytesRead = 0;
  300. *BytesNeeded = 0;
  301. }
  302. break;
  303. case OID_IRDA_MEDIA_BUSY:
  304. DBGOUT(("MiniportSetInformation(OID_IRDA_MEDIA_BUSY, %xh)",
  305. info));
  306. // The protocol can use this OID to reset the busy field
  307. // in order to check it later for intervening activity.
  308. //
  309. thisDev->mediaBusy = (BOOLEAN)info;
  310. InterlockedExchange(&thisDev->RxInterrupts,0);
  311. result = NDIS_STATUS_SUCCESS;
  312. break;
  313. case OID_GEN_CURRENT_PACKET_FILTER:
  314. DBGOUT(
  315. ("MiniportSetInformation(OID_GEN_CURRENT_PACKET_FILTER, %xh)",
  316. info));
  317. result = NDIS_STATUS_SUCCESS;
  318. break;
  319. case OID_GEN_CURRENT_LOOKAHEAD:
  320. result = (info<=MAX_I_DATA_SIZE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_INVALID_LENGTH;
  321. break;
  322. // We don't support these
  323. //
  324. case OID_IRDA_RATE_SNIFF:
  325. case OID_IRDA_UNICAST_LIST:
  326. // These are query-only parameters.
  327. //
  328. case OID_IRDA_SUPPORTED_SPEEDS:
  329. case OID_IRDA_MAX_UNICAST_LIST_SIZE:
  330. case OID_IRDA_TURNAROUND_TIME:
  331. default:
  332. DBGERR(("MiniportSetInformation(OID=%d=0x%x, value=%xh) - unsupported OID", Oid, Oid, info));
  333. *BytesRead = 0;
  334. *BytesNeeded = 0;
  335. result = NDIS_STATUS_NOT_SUPPORTED;
  336. break;
  337. }
  338. }
  339. else {
  340. *BytesRead = 0;
  341. *BytesNeeded = sizeof(UINT);
  342. result = NDIS_STATUS_INVALID_LENGTH;
  343. }
  344. DBGOUT(("MiniportSetInformation succeeded"));
  345. return result;
  346. }