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.

2268 lines
73 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. llcrcv.c
  5. Abstract:
  6. The module implements the NDIS receive indication handling and
  7. its routing to upper protocol modules or to link state machines.
  8. To understand the link related procedure of this module, you should read
  9. Chapters 11 and 12 in IBM Token-Ring Architecture Reference.
  10. Contents:
  11. LlcNdisReceiveIndication
  12. LlcNdisReceiveComplete
  13. ProcessType1_Frames
  14. MakeRcvIndication
  15. ProcessType2_Frames
  16. ProcessNewSabme
  17. LlcTransferData
  18. LlcNdisTransferDataComplete
  19. safe_memcpy
  20. FramingDiscoveryCacheHit
  21. Author:
  22. Antti Saarenheimo (o-anttis) 18-MAY-1991
  23. Revision History:
  24. 19-Nov-1992 rfirth
  25. RtlMoveMemory on MIPS, copying from shared TR buffer fails (see rubric
  26. for safe_memcpy). Changed to private memory mover for this particular
  27. case
  28. 02-May-1994 rfirth
  29. Added caching for auto-framing discovery (TEST/XID/SABME-UA)
  30. --*/
  31. #include <dlc.h>
  32. #include <llc.h>
  33. //
  34. // private prototypes...
  35. //
  36. VOID
  37. safe_memcpy(
  38. OUT PUCHAR Destination,
  39. IN PUCHAR Source,
  40. IN ULONG Length
  41. );
  42. BOOLEAN
  43. FramingDiscoveryCacheHit(
  44. IN PADAPTER_CONTEXT pAdapterContext,
  45. IN PBINDING_CONTEXT pBindingContext
  46. );
  47. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  48. //
  49. // Local lookup tables to receive the correct frames for a direct station
  50. //
  51. static USHORT ReceiveMasks[LLC_PACKET_MAX] = {
  52. DLC_RCV_8022_FRAMES,
  53. DLC_RCV_MAC_FRAMES,
  54. DLC_RCV_DIX_FRAMES,
  55. DLC_RCV_OTHER_DESTINATION
  56. };
  57. static UCHAR FrameTypes[LLC_PACKET_MAX] = {
  58. LLC_DIRECT_8022,
  59. LLC_DIRECT_MAC,
  60. LLC_DIRECT_ETHERNET_TYPE,
  61. (UCHAR)(-1)
  62. };
  63. //
  64. // functions
  65. //
  66. NDIS_STATUS
  67. LlcNdisReceiveIndication(
  68. IN PADAPTER_CONTEXT pAdapterContext,
  69. IN NDIS_HANDLE MacReceiveContext,
  70. IN PVOID pHeadBuf,
  71. IN UINT cbHeadBuf,
  72. IN PVOID pLookBuf,
  73. IN UINT cbLookBuf,
  74. IN UINT cbPacketSize
  75. )
  76. /*++
  77. Routine Description:
  78. This routine receives control from the physical provider as an
  79. indication that a frame has been received on the physical link
  80. endpoint (That was from SteveJ's NBF, the guy must have a degree in
  81. the english literature). This routine is very time critical!
  82. We first check the frame type (token-ring, 802.3 ethernet or dix),
  83. then check its data link address (802.2 saps or ethernet type)
  84. and then we route it to the upper protocol that has opened the
  85. address, that the frame was sent to. The link level frames
  86. are first run through the protocol state machine, and only
  87. the accepted I- frames are indicated to upper level.
  88. Arguments:
  89. pAdapterContext - The Adapter Binding specified at initialization time
  90. MacReceiveContext - Note: different from binding handle, mac needs this
  91. to support re-entrant receive indications
  92. pHeadBuf - pointer to a buffer containing the packet header
  93. cbHeadBuf - size of the header
  94. pLookBuf - pointer to a buffer containing the negotiated minimum
  95. amount of buffer I get to look at, not including header
  96. cbLookBuf - the size of the above. May be less than asked for, if
  97. that's all there is
  98. cbPacketSize - Overall size of the packet, not including the header
  99. Assumes:
  100. pHeadBuf contains all the header information:
  101. 802.3 6 bytes destination address
  102. 6 bytes source address
  103. 2 bytes big-endian length or packet type (DIX frames)
  104. 802.5 1 byte Access Control
  105. 1 byte Frame Control
  106. 6 bytes destination address
  107. 6 bytes source address
  108. 0-18 bytes source routing
  109. FDDI 1 byte Frame Control
  110. 6 bytes destination address
  111. 6 bytes source address
  112. From this we can assume for Token Ring that if cbHeadBuf is >14 (decimal)
  113. then there IS source routing information in the packet
  114. Return Value:
  115. NDIS_STATUS:
  116. NDIS_STATUS_SUCCESS
  117. Packet accepted
  118. NDIS_STATUS_NOT_RECOGNIZED
  119. Packet not recognized by protocol
  120. NDIS_any_other_thing if I understand, but can't handle.
  121. --*/
  122. {
  123. LLC_HEADER llcHdr;
  124. LAN802_ADDRESS Source;
  125. LAN802_ADDRESS Destination;
  126. USHORT EthernetTypeOrLength;
  127. PDATA_LINK pLink;
  128. PLLC_SAP pSap;
  129. UCHAR PacketType = LLC_PACKET_8022;
  130. UCHAR cbLanHeader = 14;
  131. KIRQL OldIrql;
  132. UCHAR packet[36]; // enough space for 14-byte header, 18-byte source
  133. // routing, 1-byte DSAP, 1-byte SSAP & 2-byte LPDU
  134. PLLC_OBJECT pObject;
  135. UINT cbCopy;
  136. #ifdef NDIS40
  137. REFADD(&pAdapterContext->AdapterRefCnt, 'rvcR');
  138. if (InterlockedCompareExchange(
  139. &pAdapterContext->BindState,
  140. BIND_STATE_BOUND,
  141. BIND_STATE_BOUND) != BIND_STATE_BOUND)
  142. {
  143. REFDEL(&pAdapterContext->AdapterRefCnt, 'rvcR');
  144. return (NDIS_STATUS_ADAPTER_NOT_OPEN);
  145. }
  146. #endif // NDIS40
  147. UNREFERENCED_PARAMETER(OldIrql);
  148. ASSUME_IRQL(DISPATCH_LEVEL);
  149. //
  150. // we assume at least 13 bytes in the header for all media types. Also
  151. // assume that the header is no larger than the packet buffer
  152. //
  153. ASSERT(cbHeadBuf >= 13);
  154. ASSERT(cbHeadBuf <= sizeof(packet));
  155. if ( cbHeadBuf > LLC_MAX_LAN_HEADER ) {
  156. #ifdef NDIS40
  157. REFDEL(&pAdapterContext->AdapterRefCnt, 'rvcR');
  158. #endif // NDIS40
  159. return NDIS_STATUS_INVALID_PACKET;
  160. }
  161. if ( (cbHeadBuf < 13) || (cbHeadBuf > sizeof(packet)) ) {
  162. #ifdef NDIS40
  163. REFDEL(&pAdapterContext->AdapterRefCnt, 'rvcR');
  164. #endif // NDIS40
  165. return NDIS_STATUS_INVALID_PACKET;
  166. }
  167. LlcMemCpy(packet, pHeadBuf, cbHeadBuf);
  168. cbCopy = MIN(sizeof(packet) - cbHeadBuf, cbLookBuf);
  169. LlcMemCpy(packet+cbHeadBuf, pLookBuf, cbCopy);
  170. cbPacketSize += cbHeadBuf;
  171. //
  172. // First we do the inital checking for the frame and read
  173. // the destination and source address and LLC header to
  174. // DWORD aligned addresses. We avoid any bigendiand/
  175. // small endiand problematic by forgotting the second high
  176. // byte in the addresses. The lowest ULONG is used only as
  177. // an raw data. The bytes can be accesses in any way.
  178. // The macros read LLC header in a small endiand safe way.
  179. //
  180. switch (pAdapterContext->NdisMedium) {
  181. case NdisMedium802_3:
  182. LlcMemCpy(Destination.Node.auchAddress, packet, 6);
  183. LlcMemCpy(Source.Node.auchAddress, packet + 6, 6);
  184. //
  185. // The 802.3 LLC frames have always the length field!
  186. // A 802.3 MAC should discard all Ethernet frames
  187. // longer than 1500 bytes.
  188. //
  189. // X'80D5 is a special ethernet type used when 802.2 frame
  190. // is encapsulated inside a ethernet type header.
  191. // (Ethernet type/size is in a reverse order for
  192. // Intel architecture)
  193. //
  194. EthernetTypeOrLength = (USHORT)packet[12] * 256 + (USHORT)packet[13];
  195. if (EthernetTypeOrLength < 3) {
  196. #ifdef NDIS40
  197. REFDEL(&pAdapterContext->AdapterRefCnt, 'rvcR');
  198. #endif // NDIS40
  199. return NDIS_STATUS_INVALID_PACKET;
  200. }
  201. //
  202. // If the ethernet length/type field is more than 1500, the
  203. // frame is dix frame and the length field is a dix ethernet
  204. // address. Otherwise the frame is a normal 802.3 frame,
  205. // that has always LLC header inside it.
  206. //
  207. if (EthernetTypeOrLength > 1500) {
  208. if (EthernetTypeOrLength == 0x80D5) {
  209. //
  210. // This is a special 'IBM SNA over ethernet' type,
  211. // that consists of the length field, 1 byte padding
  212. // and complete 802.2 LLC header (including the info field).
  213. //
  214. if ( cbLookBuf < 3 ) {
  215. #ifdef NDIS40
  216. REFDEL(&pAdapterContext->AdapterRefCnt, 'rvcR');
  217. #endif // NDIS40
  218. return NDIS_STATUS_NOT_RECOGNIZED;
  219. }
  220. cbLanHeader = 17;
  221. (PUCHAR)pLookBuf += 3;
  222. cbLookBuf -= 3;
  223. //
  224. // The DIX frame size is stored as a big-endian USHORT at offset
  225. // 15 in the LAN header. Add 17 for the DIX LAN header:
  226. //
  227. // 6 bytes destination address
  228. // 6 bytes source address
  229. // 2 bytes DIX identifier (0x80D5)
  230. // 2 byte big-endian information frame length
  231. // 1 byte pad
  232. //
  233. pAdapterContext->cbPacketSize = (USHORT)packet[14] * 256
  234. + (USHORT)packet[15]
  235. + 17;
  236. if ( pAdapterContext->cbPacketSize > cbPacketSize ) {
  237. #ifdef NDIS40
  238. REFDEL(&pAdapterContext->AdapterRefCnt, 'rvcR');
  239. #endif // NDIS40
  240. return NDIS_STATUS_INVALID_PACKET;
  241. }
  242. //
  243. // we now keep an indicator which explicitly defines that this
  244. // frame has (SNA) DIX framing
  245. //
  246. pAdapterContext->IsSnaDixFrame = TRUE;
  247. } else {
  248. //
  249. // This is some other DIX format frame. We don't know what the
  250. // format of this is (app-specific). We hand the entire packet
  251. // to the app and let it sort out the format. The frame may be
  252. // padded in which case the app gets the padding too
  253. //
  254. //
  255. // This is still Ethernet, so cbHeadBuf is 14, even though
  256. // the actual LAN header is only 12
  257. //
  258. PacketType = LLC_PACKET_DIX;
  259. pAdapterContext->cbPacketSize = cbPacketSize;
  260. //
  261. // this frame is not SNA DIX, although it is generically a DIX
  262. // frame. It will be indicated via a specific DIX SAP, not as
  263. // a general ethernet frame
  264. //
  265. pAdapterContext->IsSnaDixFrame = FALSE;
  266. }
  267. } else {
  268. //
  269. // Ethernet packets include always the padding,
  270. // we use the actual size saved in 802.3 header.
  271. // Include also the header: 6 + 6 + 2
  272. //
  273. pAdapterContext->cbPacketSize = EthernetTypeOrLength + 14;
  274. //
  275. // this is an 802.3 frame - not DIX at all
  276. //
  277. pAdapterContext->IsSnaDixFrame = FALSE;
  278. }
  279. break;
  280. case NdisMedium802_5:
  281. LlcMemCpy(Destination.Node.auchAddress, packet + 2, 6);
  282. LlcMemCpy(Source.Node.auchAddress, packet + 8, 6);
  283. //
  284. // cbHeadBuf always has the correct LAN header length for Token Ring
  285. //
  286. cbLanHeader = (UCHAR)cbHeadBuf;
  287. pAdapterContext->cbPacketSize = cbPacketSize;
  288. //
  289. // bit7 and bit6 in FC byte defines the frame type in token ring.
  290. // 00 => MAC frame (no LLC), 01 => LLC, 10,11 => reserved.
  291. // We send all other frames to direct except 01 (LLC)
  292. //
  293. if ((packet[1] & 0xC0) == 0x40) {
  294. //
  295. // check if we have routing info?
  296. //
  297. if (Source.Node.auchAddress[0] & 0x80) {
  298. //
  299. // reset the source routing indicator in the
  300. // source address (it would mess up the link search)
  301. //
  302. Source.Node.auchAddress[0] &= 0x7f;
  303. //
  304. // Discard all invalid TR frames, they'd corrupt the memory
  305. //
  306. if (cbLanHeader > MAX_TR_LAN_HEADER_SIZE) {
  307. #ifdef NDIS40
  308. REFDEL(&pAdapterContext->AdapterRefCnt, 'rvcR');
  309. #endif // NDIS40
  310. return NDIS_STATUS_NOT_RECOGNIZED;
  311. }
  312. }
  313. } else {
  314. //
  315. // this is a MAC frame destined to direct station
  316. //
  317. PacketType = LLC_PACKET_MAC;
  318. }
  319. break;
  320. case NdisMediumFddi:
  321. LlcMemCpy(Destination.Node.auchAddress, packet + 1, 6);
  322. LlcMemCpy(Source.Node.auchAddress, packet + 7, 6);
  323. //
  324. // cbHeadBuf always has the correct LAN header length for FDDI
  325. //
  326. cbLanHeader = (UCHAR)cbHeadBuf;
  327. pAdapterContext->cbPacketSize = cbPacketSize;
  328. //
  329. // bit5 and bit4 in FC byte define the FDDI frame type:
  330. //
  331. // 00 => MAC or SMT
  332. // 01 => LLC
  333. // 10 => implementer (?)
  334. // 11 => reserved
  335. //
  336. // do same as TR: LLC frames to link/SAP, everything else to direct
  337. // station
  338. //
  339. if ((packet[0] & 0x30) != 0x10) {
  340. PacketType = LLC_PACKET_MAC;
  341. }
  342. break;
  343. #if LLC_DBG
  344. default:
  345. LlcInvalidObjectType();
  346. break;
  347. #endif
  348. }
  349. pAdapterContext->FrameType = FrameTypes[PacketType];
  350. //
  351. // Direct interface gets all non LLC frames and also all LLC frames
  352. // that were not sent to this station (ie. different destination
  353. // address field and having no broadcast bit (bit7) set in
  354. // destination address)). Ie. promiscuous mode, this data link
  355. // version does not support promiscuous mode.
  356. //
  357. if (Destination.Node.auchAddress[0] & pAdapterContext->IsBroadcast) {
  358. pAdapterContext->ulBroadcastAddress = Destination.Address.ulLow;
  359. pAdapterContext->usBroadcastAddress = Destination.Address.usHigh;
  360. } else {
  361. pAdapterContext->ulBroadcastAddress = 0;
  362. //
  363. // We must also be able to handle the promiscuous packets
  364. //
  365. if (Destination.Address.ulLow != pAdapterContext->Adapter.Address.ulLow
  366. && Destination.Address.usHigh != pAdapterContext->Adapter.Address.usHigh) {
  367. PacketType = LLC_PACKET_OTHER_DESTINATION;
  368. }
  369. }
  370. //
  371. // Setup the current receive indication context,
  372. // there can be only one simultaneous receive indication from
  373. // a network adapter simultaneously. We save the necessary
  374. // data into adapter context to save unnecessary stack operations
  375. //
  376. pAdapterContext->NdisRcvStatus = NDIS_STATUS_NOT_RECOGNIZED;
  377. pAdapterContext->LinkRcvStatus = STATUS_SUCCESS;
  378. pAdapterContext->pHeadBuf = (PUCHAR)pHeadBuf;
  379. pAdapterContext->cbHeadBuf = cbHeadBuf;
  380. pAdapterContext->pLookBuf = (PUCHAR)pLookBuf;
  381. pAdapterContext->cbLookBuf = cbLookBuf;
  382. pAdapterContext->RcvLanHeaderLength = (USHORT)cbLanHeader;
  383. ACQUIRE_DRIVER_LOCK();
  384. ACQUIRE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  385. switch(PacketType) {
  386. case LLC_PACKET_8022:
  387. //
  388. // Read the whole LLC frame (a maybe an extra byte,
  389. // if this is a U frame).
  390. // Note: Source and destination saps are swapped in
  391. // the received frames
  392. //
  393. Source.Address.SrcSap = llcHdr.S.Dsap = packet[cbLanHeader];
  394. llcHdr.S.Ssap = packet[cbLanHeader + 1];
  395. Source.Address.DestSap = llcHdr.S.Ssap & (UCHAR)0xfe;
  396. llcHdr.S.Command = packet[cbLanHeader + 2];
  397. llcHdr.S.Nr = packet[cbLanHeader + 3];
  398. if (pSap = pAdapterContext->apSapBindings[llcHdr.U.Dsap]) {
  399. //
  400. // The broadcast addresses cannot be destined to link stations
  401. //
  402. if (pAdapterContext->ulBroadcastAddress == 0) {
  403. SEARCH_LINK(pAdapterContext, Source, pLink);
  404. if (pLink) {
  405. //
  406. // Process all connection oriented frames, the procedure
  407. // will call ProcessType1_Frames, if it finds that the
  408. // frame is connectionless.
  409. // (We should bring the whole subprocedure here,
  410. // because it isn't called elsewhere).
  411. //
  412. ProcessType2_Frames(pAdapterContext, MacReceiveContext, pLink, llcHdr);
  413. } else {
  414. //
  415. // Process all connectionless frames and
  416. // SABMEs (connection requests to create a
  417. // new link station)
  418. //
  419. ProcessType1_Frames(pAdapterContext, MacReceiveContext, pSap, llcHdr);
  420. }
  421. } else {
  422. //
  423. // Process the broadcasts, this cannot have
  424. // nothing to do with the links
  425. //
  426. ProcessType1_Frames(pAdapterContext, MacReceiveContext, pSap, llcHdr);
  427. }
  428. } else {
  429. //
  430. // The SAP has not been defined, but we must still respond
  431. // to the TEST and XID commands sent to the NULL SAP.
  432. // They must be echoed back to the sender
  433. //
  434. if ((llcHdr.U.Dsap == LLC_SSAP_NULL)
  435. && !(llcHdr.U.Ssap & LLC_SSAP_RESPONSE)) {
  436. //
  437. // if the remote machine is already in the framing discovery
  438. // cache but is using the other framing type then discard this
  439. // TEST/XID command/response
  440. //
  441. // if (FramingDiscoveryCacheHit(pAdapterContext, pSap->Gen.pLlcBinding)) {
  442. // break;
  443. // }
  444. RespondTestOrXid(pAdapterContext, MacReceiveContext, llcHdr, LLC_SSAP_NULL);
  445. } else if (pAdapterContext->pDirectStation != NULL) {
  446. pAdapterContext->usRcvMask = ReceiveMasks[PacketType];
  447. MakeRcvIndication(pAdapterContext, MacReceiveContext, (PLLC_OBJECT)pAdapterContext->pDirectStation);
  448. }
  449. }
  450. break;
  451. case LLC_PACKET_DIX:
  452. //
  453. // Search the DIX packet from the database
  454. //
  455. pObject = (PLLC_OBJECT)pAdapterContext->aDixStations[EthernetTypeOrLength % MAX_DIX_TABLE];
  456. if (pObject) {
  457. pAdapterContext->EthernetType = EthernetTypeOrLength;
  458. } else {
  459. pObject = (PLLC_OBJECT)pAdapterContext->pDirectStation;
  460. if (pObject) {
  461. pAdapterContext->usRcvMask = ReceiveMasks[PacketType];
  462. }
  463. }
  464. if (pObject) {
  465. MakeRcvIndication(pAdapterContext, MacReceiveContext, pObject);
  466. }
  467. break;
  468. case LLC_PACKET_OTHER_DESTINATION:
  469. case LLC_PACKET_MAC:
  470. //
  471. // discard the return status of the direct stations!
  472. // The combining of the returns statuses would take too much time
  473. // NDIS 3.0 isn't actually any more intrested if frame is copied.
  474. //
  475. if (pObject = (PLLC_OBJECT)pAdapterContext->pDirectStation) {
  476. pAdapterContext->usRcvMask = ReceiveMasks[PacketType];
  477. MakeRcvIndication(pAdapterContext, MacReceiveContext, pObject);
  478. }
  479. break;
  480. #if LLC_DBG
  481. default:
  482. LlcInvalidObjectType();
  483. break;
  484. #endif
  485. }
  486. RELEASE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  487. RELEASE_DRIVER_LOCK();
  488. #ifdef NDIS40
  489. REFDEL(&pAdapterContext->AdapterRefCnt, 'rvcR');
  490. #endif // NDIS40
  491. return pAdapterContext->NdisRcvStatus;
  492. }
  493. VOID
  494. LlcNdisReceiveComplete(
  495. IN PADAPTER_CONTEXT pAdapterContext
  496. )
  497. /*++
  498. Routine Description:
  499. The routine handles the receive complete indications. The receive
  500. completion is made by NDIS when the network hardware have been
  501. enabled again for receive. In a UP Nt this does mean, that a
  502. new frame could be received, because we are still on DPC level and
  503. the receive indication is still in DPC queue to wait us to complete.
  504. Actually that is OK, because otherwise the stack would overflow,
  505. if there would be too many received packets.
  506. Arguments:
  507. pAdapterContext - adapter context
  508. Return Value:
  509. None
  510. --*/
  511. {
  512. #ifdef NDIS40
  513. REFADD(&pAdapterContext->AdapterRefCnt, 'pCxR');
  514. if (InterlockedCompareExchange(
  515. &pAdapterContext->BindState,
  516. BIND_STATE_BOUND,
  517. BIND_STATE_BOUND) != BIND_STATE_BOUND)
  518. {
  519. //
  520. // Must be in the middle of an unbind, otherwise NDIS would have never
  521. // called the receive handler.
  522. //
  523. REFDEL(&pAdapterContext->AdapterRefCnt, 'pCxR');
  524. return;
  525. }
  526. #endif // NDIS40
  527. //
  528. // seems that 3Com FDDI card is calling this at PASSIVE_LEVEL
  529. //
  530. ASSUME_IRQL(ANY_IRQL);
  531. ACQUIRE_DRIVER_LOCK();
  532. //
  533. // Skip the whole background process if there is nothing to do.
  534. // its the default case, when we are receiving I or UI data.
  535. //
  536. if (pAdapterContext->LlcPacketInSendQueue
  537. || !IsListEmpty(&pAdapterContext->QueueCommands)
  538. || !IsListEmpty(&pAdapterContext->QueueEvents)) {
  539. ACQUIRE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  540. BackgroundProcessAndUnlock(pAdapterContext);
  541. }
  542. RELEASE_DRIVER_LOCK();
  543. #ifdef NDIS40
  544. REFDEL(&pAdapterContext->AdapterRefCnt, 'pCxR');
  545. #endif // NDIS40
  546. }
  547. VOID
  548. ProcessType1_Frames(
  549. IN PADAPTER_CONTEXT pAdapterContext,
  550. IN NDIS_HANDLE MacReceiveContext,
  551. IN PLLC_SAP pSap,
  552. IN LLC_HEADER LlcHeader
  553. )
  554. /*++
  555. Routine Description:
  556. Route UI, TEST or XID frames to the LLC client
  557. Arguments:
  558. pAdapterContext - The Adapter Binding specified at initialization time.
  559. pSap - pointer to the SAP object of data link driver
  560. LlcHeader - 802.2 header is copied to stack to make its access fast
  561. Return Value:
  562. None.
  563. --*/
  564. {
  565. UCHAR DlcCommand;
  566. ASSUME_IRQL(DISPATCH_LEVEL);
  567. //
  568. // Update the counter, we must later check the lost frames
  569. // (no buffers available for the received UI- frames)
  570. //
  571. pSap->Statistics.FramesReceived++;
  572. //
  573. // We must use the link station state machine with any other
  574. // command except UI frames and broadcasts, if the link exists.
  575. //
  576. if ((LlcHeader.U.Command & ~LLC_U_POLL_FINAL) == LLC_UI) {
  577. pAdapterContext->FrameType = LLC_UI_FRAME;
  578. MakeRcvIndication(pAdapterContext, MacReceiveContext, (PLLC_OBJECT)pSap);
  579. return;
  580. //
  581. // Check next if the frame is a XID or TEST frame
  582. //
  583. } else if ((LlcHeader.U.Command & ~LLC_U_POLL_FINAL) == LLC_TEST) {
  584. //
  585. // if the remote machine is already in the framing discovery cache but
  586. // is using the other framing type then discard this TEST command/response
  587. //
  588. //
  589. // RLF 06/23/94
  590. //
  591. // If this is a Response from SAP 0 then don't check the cache. The
  592. // reason is that currently DLC will automatically generate responses
  593. // to TESTs and XIDs sent to SAP 0. It will generate 802.3 and DIX
  594. // irrespective of whether it is configured for DIX or not. The upshot
  595. // is that a DIX-only machine can currently send an 802.3 response
  596. // which when we run it through the cache, causes us to assume the other
  597. // machine is configured for 802.3, not DIX. In communicado.
  598. // For TEST and XIDs from SAP 0, we have to let the app receive the
  599. // duplicate and decide what to do with it
  600. //
  601. if (LlcHeader.U.Ssap != (LLC_SSAP_NULL | LLC_SSAP_RESPONSE)) {
  602. if (FramingDiscoveryCacheHit(pAdapterContext, pSap->Gen.pLlcBinding)) {
  603. return;
  604. }
  605. }
  606. if (!(LlcHeader.U.Ssap & LLC_SSAP_RESPONSE)) {
  607. //
  608. // The Test commands are always echoed back
  609. // (the Command/Response bit was reset => this is command)
  610. //
  611. RespondTestOrXid(pAdapterContext, MacReceiveContext, LlcHeader, pSap->SourceSap);
  612. pAdapterContext->NdisRcvStatus = NDIS_STATUS_SUCCESS;
  613. return;
  614. } else {
  615. DlcCommand = LLC_TEST_RESPONSE_NOT_FINAL;
  616. }
  617. } else if ((LlcHeader.U.Command & ~LLC_U_POLL_FINAL) == LLC_XID) {
  618. //
  619. // if the remote machine is already in the framing discovery cache but
  620. // is using the other framing type then discard this XID command/response
  621. //
  622. //
  623. // RLF 06/23/94
  624. //
  625. // If this is a Response from SAP 0 then don't check the cache. See above
  626. //
  627. if (LlcHeader.U.Ssap != (LLC_SSAP_NULL | LLC_SSAP_RESPONSE)) {
  628. if (FramingDiscoveryCacheHit(pAdapterContext, pSap->Gen.pLlcBinding)) {
  629. return;
  630. }
  631. }
  632. //
  633. // The upper level protocol may ask data link driver to handle the XIDs
  634. //
  635. if (!(LlcHeader.U.Ssap & LLC_SSAP_RESPONSE)) {
  636. if (pSap->OpenOptions & LLC_HANDLE_XID_COMMANDS) {
  637. RespondTestOrXid(pAdapterContext, MacReceiveContext, LlcHeader, pSap->SourceSap);
  638. pAdapterContext->NdisRcvStatus = NDIS_STATUS_SUCCESS;
  639. return;
  640. } else {
  641. DlcCommand = LLC_XID_COMMAND_NOT_POLL;
  642. }
  643. } else {
  644. DlcCommand = LLC_XID_RESPONSE_NOT_FINAL;
  645. }
  646. } else if ((LlcHeader.U.Command & ~LLC_U_POLL_FINAL) == LLC_SABME) {
  647. //
  648. // can't open a connection by broadcasting a SABME
  649. //
  650. if (pAdapterContext->ulBroadcastAddress != 0) {
  651. return;
  652. }
  653. //
  654. // if the remote machine is already in the framing discovery cache but
  655. // is using the other framing type then discard this SABME
  656. //
  657. if (FramingDiscoveryCacheHit(pAdapterContext, pSap->Gen.pLlcBinding)) {
  658. return;
  659. }
  660. //
  661. // This is a remote connection request
  662. //
  663. ProcessNewSabme(pAdapterContext, pSap, LlcHeader);
  664. pAdapterContext->NdisRcvStatus = NDIS_STATUS_SUCCESS;
  665. return;
  666. } else {
  667. return;
  668. }
  669. if (LlcHeader.auchRawBytes[2] & LLC_U_POLL_FINAL) {
  670. DlcCommand -= 2;
  671. }
  672. pAdapterContext->FrameType = DlcCommand;
  673. MakeRcvIndication(pAdapterContext, MacReceiveContext, (PLLC_OBJECT)pSap);
  674. }
  675. VOID
  676. MakeRcvIndication(
  677. IN PADAPTER_CONTEXT pAdapterContext,
  678. IN NDIS_HANDLE MacReceiveContext,
  679. IN PLLC_OBJECT pStation
  680. )
  681. /*++
  682. Routine Description:
  683. Procedure makes a generic receive indication for all frames
  684. received by SAP or direct stations.
  685. Arguments:
  686. pAdapterContext - adapter context of the received packet
  687. pStation - SAP or DIRECT station
  688. Return Value:
  689. None.
  690. --*/
  691. {
  692. ASSUME_IRQL(DISPATCH_LEVEL);
  693. //
  694. // SAP and direct stations can be shared by several link clients
  695. // (if they have been opened in shared mode). Route the packet
  696. // to all clints registered to this SAP or direct station
  697. // A link station may have only one owner.
  698. //
  699. for (; pStation; pStation = (PLLC_OBJECT)pStation->Gen.pNext) {
  700. //
  701. // Rotate the direct frames to all direct stations except if
  702. // the frame has already been captured by the current client.
  703. // We use 32-bit client context to identify the client,
  704. // that had already received the frame to its SAP or link station.
  705. //
  706. // Broadcasts are indicated only when they match with the
  707. // group or functional address defined for this binding.
  708. // The global broadcast is passed through, if it is enabled.
  709. //
  710. if (
  711. //
  712. // 1. Check is this is destinated frame (broadcast is null) or
  713. // if the packet is a broadcast with a matching group address
  714. //
  715. ((pAdapterContext->ulBroadcastAddress == 0)
  716. || (pAdapterContext->ulBroadcastAddress == 0xFFFFFFFFL)
  717. || ((pAdapterContext->ulBroadcastAddress & pStation->Gen.pLlcBinding->Functional.ulAddress)
  718. && ((pAdapterContext->ulBroadcastAddress & pStation->Gen.pLlcBinding->ulFunctionalZeroBits) == 0)
  719. && (pAdapterContext->usBroadcastAddress == pAdapterContext->usHighFunctionalBits))
  720. || ((pAdapterContext->ulBroadcastAddress == pStation->Gen.pLlcBinding->ulBroadcastAddress)
  721. && (pAdapterContext->usBroadcastAddress == pStation->Gen.pLlcBinding->usBroadcastAddress)))
  722. //
  723. // 2. If the station type is DIX, then the ethernet type
  724. // must be the same as the station's ethernet type
  725. && ((pStation->Gen.ObjectType != LLC_DIX_OBJECT)
  726. || (pStation->Dix.ObjectAddress == pAdapterContext->EthernetType))
  727. //
  728. // 3. If the packet is a direct frame, then its receive mask
  729. // must match with the received frame.
  730. //
  731. && ((pStation->Gen.ObjectType != LLC_DIRECT_OBJECT)
  732. || (pStation->Dir.OpenOptions & pAdapterContext->usRcvMask))) {
  733. UINT Status;
  734. //
  735. // Update the counter, we must later check the lost frames
  736. // (if no buffers available for the received frames)
  737. //
  738. pStation->Sap.Statistics.FramesReceived++;
  739. pAdapterContext->NdisRcvStatus = NDIS_STATUS_SUCCESS;
  740. if (pAdapterContext->cbPacketSize < pAdapterContext->RcvLanHeaderLength) {
  741. return;
  742. }
  743. Status = pStation->Gen.pLlcBinding->pfReceiveIndication(
  744. pStation->Gen.pLlcBinding->hClientContext,
  745. pStation->Gen.hClientHandle,
  746. MacReceiveContext,
  747. pAdapterContext->FrameType,
  748. pAdapterContext->pLookBuf,
  749. pAdapterContext->cbPacketSize - pAdapterContext->RcvLanHeaderLength
  750. );
  751. //
  752. // Protocol may discard the packet and its indication.
  753. //
  754. if (Status != STATUS_SUCCESS) {
  755. pStation->Sap.Statistics.DataLostCounter++;
  756. if (Status == DLC_STATUS_NO_RECEIVE_COMMAND) {
  757. pStation->Sap.Statistics.FramesDiscardedNoRcv++;
  758. }
  759. }
  760. }
  761. }
  762. }
  763. //
  764. // Vs - we will be sending this next.
  765. // Va - other side is expecting this next.
  766. // was:
  767. // if (pLink->Vs >= pLink->Va) {
  768. // if (pLink->Nr < pLink->Va || pLink->Nr > pLink->Vs) {
  769. // uchInput = LPDU_INVALID_r0;
  770. // }
  771. // } else {
  772. // if (pLink->Nr > pLink->Vs && pLink->Nr < pLink->Va) {
  773. // uchInput = LPDU_INVALID_r0;
  774. // }
  775. // }
  776. //
  777. int
  778. verify_pack(
  779. IN UCHAR VsMax, // pLink->VsMax
  780. IN UCHAR Vs, // pLink->Vs,
  781. IN UCHAR Va, // pLink->Va,
  782. IN UCHAR Nr, // pLink->Nr,
  783. IN OUT UCHAR *uchInput // &uchInput
  784. )
  785. {
  786. if( Va <= VsMax ){ // Not Wrapped around 127?
  787. if( Nr < Va ){
  788. // this frame is saying it is expecting
  789. // Nr which is less than what it was expecting (Va)
  790. *uchInput = LPDU_INVALID_r0;
  791. }else if ( VsMax < Nr ){
  792. // He can't expect (Nr) beyond what we sent (Vs).
  793. *uchInput = LPDU_INVALID_r0;
  794. }
  795. }else{ // Vs sent is less < Acked Va, ie. wrapped. And
  796. if( VsMax < Nr && Nr < Va ) {
  797. // Eg. expecting between Va=126..0=Vs, (wrap range).
  798. // and 0 ... Nr .. 126, is invalid.
  799. *uchInput = LPDU_INVALID_r0;
  800. }
  801. }
  802. return 0;
  803. }
  804. VOID
  805. ProcessType2_Frames(
  806. IN PADAPTER_CONTEXT pAdapterContext,
  807. IN NDIS_HANDLE MacReceiveContext,
  808. IN OUT PDATA_LINK pLink,
  809. IN LLC_HEADER LlcHeader
  810. )
  811. /*++
  812. Routine Description:
  813. Procedure preprocess LLC Type2 frames for the actual state machine.
  814. Type 2 LLC frames are: I, RR, RNR, REJ, SABME, DISC, UA, DM, FRMR.
  815. The data is indicated to the upper protocol module, if it sequence
  816. number of the I- frame is valid, but the receive may still fail,
  817. if the data packet is discarded by the 802.2 state machine.
  818. The data is first indicated to the client, because we must set
  819. first the state machine to the local busy state, if the upper
  820. protocol module has not enough buffers to receive the data.
  821. Arguments:
  822. pAdapterContext - The Adapter Binding specified at initialization time.
  823. pLink - link station data
  824. LlcHeader - LLC header
  825. Return Value:
  826. None.
  827. --*/
  828. {
  829. UCHAR uchInput;
  830. BOOLEAN boolPollFinal;
  831. BOOLEAN boolInitialLocalBusyUser;
  832. UINT status;
  833. ASSUME_IRQL(DISPATCH_LEVEL);
  834. //
  835. // The last received command is included in the DLC statistics
  836. //
  837. pLink->LastCmdOrRespReceived = LlcHeader.U.Command;
  838. //
  839. // Handle first I frames, they are the most common!
  840. //
  841. if (!(LlcHeader.U.Command & LLC_NOT_I_FRAME)) {
  842. //
  843. // Check first the sync of the I- frame: The send sequence
  844. // number should be what we are expected or some packets sare lost.
  845. //
  846. uchInput = IS_I_r0; // In Sequence Information frame by default
  847. //
  848. // we discard all I-frames, that are bigger than the
  849. // maximum defined for this link station.
  850. // This must be the best way to solve wrong packet size.
  851. // FRMR disconnects the packets and the invalid transmit
  852. // command should fail in the sending side.
  853. //
  854. pLink->Nr = LlcHeader.I.Nr & (UCHAR)0xfe;
  855. if (pLink->MaxIField + pAdapterContext->RcvLanHeaderLength
  856. + sizeof(LLC_HEADER) < pAdapterContext->cbPacketSize) {
  857. uchInput = LPDU_INVALID_r0;
  858. } else if ((LlcHeader.I.Ns & (UCHAR)0xfe) != pLink->Vr) {
  859. //
  860. // Out of Sequence Information frame (we didn't expect this!)
  861. //
  862. uchInput = OS_I_r0;
  863. //
  864. // When we are out of receive buffers, we want to know
  865. // the buffer space required by all expected frames.
  866. // There may be several coming I-frames in the send queues,
  867. // bridges and in the receive buffers of the adapter when a
  868. // link enters a local busy state. We save the size of
  869. // all received sequential I-frames during a local busy state
  870. // to know how much buffer space we must commit before we
  871. // can clear the local busy state.
  872. //
  873. if ((pLink->Flags & DLC_LOCAL_BUSY_BUFFER)
  874. && (LlcHeader.I.Ns & (UCHAR)0xfe) == pLink->VrDuringLocalBusy){
  875. pLink->VrDuringLocalBusy += 2;
  876. pLink->BufferCommitment += BufGetPacketSize(pAdapterContext->cbPacketSize);
  877. }
  878. //
  879. // The valid frames has modulo: Va <= Nr <= Vs,
  880. // Ie. the Receive sequence number should belong to
  881. // a frame that has been sent but not acknowledged.
  882. // The extra check in the beginning makes the most common
  883. // code path faster: usually the other is waiting the next frame.
  884. //
  885. } else if (pLink->Nr != pLink->Vs) {
  886. //
  887. // There may by something wrong with the receive sequence number
  888. //
  889. verify_pack( pLink->VsMax,
  890. pLink->Vs,
  891. pLink->Va,
  892. pLink->Nr,
  893. &uchInput );
  894. }
  895. //
  896. // We must first indcate the frame to the upper protocol and
  897. // then check, if it was accepted by the state machine.
  898. // If a I- frame cannot be received by the upper protocol
  899. // driver, then it must be dropped to the floor and be not
  900. // indicated to the state machine (=> the frame will be lost
  901. // for the LLC protocol)
  902. //
  903. //
  904. // RLF 04/13/93
  905. //
  906. // if the link is in local busy (user) state then don't indicate the
  907. // frame, but RNR it
  908. //
  909. // bug #193762
  910. //
  911. // AK 06/20/98
  912. //
  913. // Save the current user local busy flag. The receive indication
  914. // may release the driver lock (the ACQUIRE_SPIN_LOCK is a no-op because
  915. // the DLC_UNILOCK=1 in the sources file) it is possible that the link
  916. // state is different after the indication returns.
  917. //
  918. boolInitialLocalBusyUser = (pLink->Flags & DLC_LOCAL_BUSY_USER);
  919. if ((uchInput == IS_I_r0) && !(pLink->Flags & DLC_LOCAL_BUSY_USER)) {
  920. DLC_STATUS Status;
  921. pAdapterContext->LinkRcvStatus = STATUS_PENDING;
  922. if (pAdapterContext->cbPacketSize < pAdapterContext->RcvLanHeaderLength) {
  923. return;
  924. }
  925. Status = pLink->Gen.pLlcBinding->pfReceiveIndication(
  926. pLink->Gen.pLlcBinding->hClientContext,
  927. pLink->Gen.hClientHandle,
  928. MacReceiveContext,
  929. LLC_I_FRAME,
  930. pAdapterContext->pLookBuf,
  931. pAdapterContext->cbPacketSize - pAdapterContext->RcvLanHeaderLength
  932. );
  933. //
  934. // We use local busy to stop the send to the link.
  935. // IBM link station flow control management supports
  936. // local busy state enabling because of "out of receive buffers"
  937. // or "no outstanding receive".
  938. //
  939. if (Status != STATUS_SUCCESS) {
  940. if (Status == DLC_STATUS_NO_RECEIVE_COMMAND
  941. || Status == DLC_STATUS_OUT_OF_RCV_BUFFERS) {
  942. ACQUIRE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  943. //
  944. // We will enter to a local busy state because of
  945. // out of buffers. Save the buffer size required
  946. // to receive this data.
  947. //
  948. pLink->VrDuringLocalBusy = pLink->Vr;
  949. pLink->BufferCommitment = BufGetPacketSize(pAdapterContext->cbPacketSize);
  950. //
  951. // We do not need to care, if the local busy state
  952. // is already set or not. The state machine just
  953. // returns an error status, but we do not care
  954. // about it. The dlc status code trigger indication
  955. // to the upper levels, if the state machine accepted
  956. // the command.
  957. //
  958. pLink->Flags |= DLC_LOCAL_BUSY_BUFFER;
  959. pLink->DlcStatus.StatusCode |= INDICATE_LOCAL_STATION_BUSY;
  960. RunStateMachineCommand(pLink, ENTER_LCL_Busy);
  961. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  962. }
  963. }
  964. }
  965. ACQUIRE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  966. //
  967. // The most common case is handled as a special case.
  968. // We can save maybe 30 instrunctions.
  969. //
  970. if (uchInput == IS_I_r0 && pLink->State == LINK_OPENED) {
  971. UpdateVa(pLink);
  972. pLink->Vr += 2;
  973. pAdapterContext->LinkRcvStatus = STATUS_SUCCESS;
  974. //
  975. // IS_I_c1 = Update_Va; Rcv_BTU; [Send_ACK]
  976. // IS_I_r|IS_I_c0 = Update_Va; Rcv_BTU; TT2; Ir_Ct=N3; [RR_r](1)
  977. //
  978. if ((LlcHeader.I.Nr & LLC_I_S_POLL_FINAL)
  979. && !(LlcHeader.I.Ssap & LLC_SSAP_RESPONSE)) {
  980. StopTimer(&pLink->T2);
  981. pLink->Ir_Ct = pLink->N3;
  982. SendLlcFrame(pLink, (UCHAR)(DLC_RR_TOKEN | DLC_TOKEN_RESPONSE | 1));
  983. } else {
  984. SendAck(pLink);
  985. }
  986. } else {
  987. // bug #193762
  988. //
  989. // AK 06/20/98
  990. //
  991. // If the link was not busy (user) when this function was entered but
  992. // it is busy (user) now but not busy (system) then the frame must have
  993. // been accepted by the upper layer and we must adjust Acknowledge state
  994. // variable (Va) and Receive state variable (Vr). Otherwise we'll send
  995. // wrong N(r) in the RNR frame and we'll receive this same frame again when
  996. // we clear the local busy.
  997. //
  998. if(uchInput == IS_I_r0 &&
  999. !boolInitialLocalBusyUser &&
  1000. !(pLink->Flags & DLC_LOCAL_BUSY_BUFFER) &&
  1001. (pLink->Flags & DLC_LOCAL_BUSY_USER))
  1002. {
  1003. UpdateVa(pLink);
  1004. pLink->Vr += 2;
  1005. pAdapterContext->LinkRcvStatus = STATUS_SUCCESS;
  1006. }
  1007. uchInput += (UINT)(LlcHeader.I.Nr & LLC_I_S_POLL_FINAL);
  1008. if (!(LlcHeader.I.Ssap & LLC_SSAP_RESPONSE)) {
  1009. uchInput += DLC_TOKEN_COMMAND;
  1010. }
  1011. //
  1012. // Nr will be some garbage in the case of U commands,
  1013. // but the Poll/Final flag is not used when the U- commands
  1014. // are processed.
  1015. // ----
  1016. // If the state machine returns an error to link receive status,
  1017. // then the receive command completion cancels the received
  1018. // frame.
  1019. //
  1020. pAdapterContext->LinkRcvStatus = RunStateMachine(
  1021. pLink,
  1022. (USHORT)uchInput,
  1023. (BOOLEAN)((LlcHeader.S.Nr & LLC_I_S_POLL_FINAL) ? 1 : 0),
  1024. (BOOLEAN)(LlcHeader.S.Ssap & LLC_SSAP_RESPONSE)
  1025. );
  1026. }
  1027. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1028. //
  1029. // Update the error counters if something went wrong with
  1030. // the receive.
  1031. //
  1032. if (pAdapterContext->LinkRcvStatus != STATUS_SUCCESS) {
  1033. //
  1034. // We will count all I frames not actually acknowledged
  1035. // as errors (this could be counted also other way).
  1036. //
  1037. pLink->Statistics.I_FrameReceiveErrors++;
  1038. if (pLink->Statistics.I_FrameReceiveErrors == 0x80) {
  1039. pLink->DlcStatus.StatusCode |= INDICATE_DLC_COUNTER_OVERFLOW;
  1040. }
  1041. } else {
  1042. //
  1043. // update statistics: in-sequency frames OK, all others
  1044. // must be errors.
  1045. // This may not be the best place to count successful I-frames,
  1046. // because the state machine has not yet acknowledged this frame,
  1047. // We may be in a wrong state to receive any data (eg. local busy)
  1048. //
  1049. pLink->Statistics.I_FramesReceived++;
  1050. if (pLink->Statistics.I_FramesReceived == 0x8000) {
  1051. pLink->DlcStatus.StatusCode |= INDICATE_DLC_COUNTER_OVERFLOW;
  1052. }
  1053. pLink->pSap->Statistics.FramesReceived++;
  1054. }
  1055. //
  1056. // We may complete this only if the transfer data has
  1057. // already completed (and there is a receive completion
  1058. // packet built up in).
  1059. //
  1060. if (pLink->Gen.pLlcBinding->TransferDataPacket.pPacket != NULL
  1061. && pLink->Gen.pLlcBinding->TransferDataPacket.pPacket->Data.Completion.Status != NDIS_STATUS_PENDING) {
  1062. //
  1063. // The NDIS status is saved in the completion status, we
  1064. // will use state machine status instead, if the state
  1065. // machine returned an error.
  1066. //
  1067. if (pAdapterContext->LinkRcvStatus != STATUS_SUCCESS) {
  1068. pLink->Gen.pLlcBinding->TransferDataPacket.pPacket->Data.Completion.Status = pAdapterContext->LinkRcvStatus;
  1069. }
  1070. pLink->Gen.pLlcBinding->pfCommandComplete(
  1071. pLink->Gen.pLlcBinding->hClientContext,
  1072. pLink->Gen.pLlcBinding->TransferDataPacket.pPacket->Data.Completion.hClientHandle,
  1073. pLink->Gen.pLlcBinding->TransferDataPacket.pPacket
  1074. );
  1075. pLink->Gen.pLlcBinding->TransferDataPacket.pPacket = NULL;
  1076. }
  1077. //
  1078. // ******** EXIT ***********
  1079. //
  1080. return;
  1081. } else if (!(LlcHeader.S.Command & LLC_U_TYPE_BIT)) {
  1082. //
  1083. // Handle S (Supervisory) commands (RR, REJ, RNR)
  1084. //
  1085. switch (LlcHeader.S.Command) {
  1086. case LLC_RR:
  1087. uchInput = RR_r0;
  1088. break;
  1089. case LLC_RNR:
  1090. uchInput = RNR_r0;
  1091. break;
  1092. case LLC_REJ:
  1093. uchInput = REJ_r0;
  1094. break;
  1095. default:
  1096. uchInput = LPDU_INVALID_r0;
  1097. break;
  1098. }
  1099. //
  1100. // The valid frames has modulo: Va <= Nr <= Vs,
  1101. // Ie. the Receive sequence number should belong to
  1102. // a frame that has been sent but not acknowledged.
  1103. // The extra check in the beginning makes the most common
  1104. // code path faster: usually the other is waiting the next frame.
  1105. // (keep the rest code the same as in I path, even a very
  1106. // primitive optimizer will puts these code paths together)
  1107. //
  1108. pLink->Nr = LlcHeader.I.Nr & (UCHAR)0xfe;
  1109. if (pLink->Nr != pLink->Vs) {
  1110. //
  1111. // Check the received sequence number
  1112. //
  1113. verify_pack( pLink->VsMax,
  1114. pLink->Vs,
  1115. pLink->Va,
  1116. pLink->Nr,
  1117. &uchInput );
  1118. }
  1119. uchInput += (UINT)(LlcHeader.S.Nr & LLC_I_S_POLL_FINAL);
  1120. boolPollFinal = (BOOLEAN)(LlcHeader.S.Nr & LLC_I_S_POLL_FINAL);
  1121. if (!(LlcHeader.S.Ssap & LLC_SSAP_RESPONSE)) {
  1122. uchInput += DLC_TOKEN_COMMAND;
  1123. }
  1124. } else {
  1125. //
  1126. // Handle U (Unnumbered) command frames
  1127. // (FRMR, DM, UA, DISC, SABME, XID, TEST)
  1128. //
  1129. switch (LlcHeader.U.Command & ~LLC_U_POLL_FINAL) {
  1130. case LLC_DISC:
  1131. uchInput = DISC0;
  1132. break;
  1133. case LLC_SABME:
  1134. uchInput = SABME0;
  1135. break;
  1136. case LLC_DM:
  1137. uchInput = DM0;
  1138. break;
  1139. case LLC_UA:
  1140. uchInput = UA0;
  1141. break;
  1142. case LLC_FRMR:
  1143. uchInput = FRMR0;
  1144. break;
  1145. default:
  1146. //
  1147. // we don't handle XID and TEST frames here!
  1148. //
  1149. ProcessType1_Frames(pAdapterContext, MacReceiveContext, pLink->pSap, LlcHeader);
  1150. return;
  1151. break;
  1152. };
  1153. //
  1154. // We set an uniform poll/final bit for procedure call
  1155. //
  1156. boolPollFinal = FALSE;
  1157. if (LlcHeader.U.Command & LLC_U_POLL_FINAL) {
  1158. uchInput += 1;
  1159. boolPollFinal = TRUE;
  1160. }
  1161. }
  1162. ACQUIRE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1163. //
  1164. // Note: the 3rd parameter must be 0 or 1, fortunately the
  1165. // the poll/final bit is bit0 in S and I frames.
  1166. //
  1167. status = RunStateMachine(pLink,
  1168. (USHORT)uchInput,
  1169. boolPollFinal,
  1170. (BOOLEAN)(LlcHeader.S.Ssap & LLC_SSAP_RESPONSE)
  1171. );
  1172. //
  1173. // if this frame is a UA AND it was accepted by the FSM AND the framing type
  1174. // is currently unspecified then set it to the type in the UA frame received.
  1175. // If this is not an ethernet adapter or we are not in AUTO mode then the
  1176. // framing type for this link is set to the framing type in the binding
  1177. // context (as it was before)
  1178. //
  1179. if ((status == STATUS_SUCCESS)
  1180. && ((uchInput == UA0) || (uchInput == SABME0) || (uchInput == SABME1))
  1181. && (pLink->FramingType == LLC_SEND_UNSPECIFIED)) {
  1182. //
  1183. // RLF 05/09/94
  1184. //
  1185. // If we received a UA in response to a SABME that we sent out as DIX
  1186. // and 802.3, then record the framing type. This will be used for all
  1187. // subsequent frames sent on this link
  1188. //
  1189. pLink->FramingType = (IS_SNA_DIX_FRAME(pAdapterContext)
  1190. && IS_AUTO_BINDING(pLink->Gen.pLlcBinding))
  1191. ? LLC_SEND_802_3_TO_DIX
  1192. : pLink->Gen.pLlcBinding->InternalAddressTranslation
  1193. ;
  1194. }
  1195. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1196. }
  1197. VOID
  1198. ProcessNewSabme(
  1199. IN PADAPTER_CONTEXT pAdapterContext,
  1200. IN PLLC_SAP pSap,
  1201. IN LLC_HEADER LlcHeader
  1202. )
  1203. /*++
  1204. Routine Description:
  1205. Procedure processes the remote connection requtest: SABME.
  1206. It allocates a new link from the pool of closed links in
  1207. the SAP and runs the state machine.
  1208. Arguments:
  1209. pAdapterContext - The Adapter Binding specified at initialization time.
  1210. pSap - the current SAP handle
  1211. LlcHeader - LLC header
  1212. Return Value:
  1213. None.
  1214. --*/
  1215. {
  1216. PDATA_LINK pLink;
  1217. DLC_STATUS Status;
  1218. ASSUME_IRQL(DISPATCH_LEVEL);
  1219. RELEASE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  1220. //
  1221. // The destination sap cannot be a group SAP any more,
  1222. // thus we don't need to mask the lowest bit aways
  1223. //
  1224. Status = LlcOpenLinkStation(
  1225. pSap,
  1226. (UCHAR)(LlcHeader.auchRawBytes[DLC_SSAP_OFFSET] & 0xfe),
  1227. NULL,
  1228. pAdapterContext->pHeadBuf,
  1229. NULL, // no client handle => DLC driver must create it
  1230. (PVOID*)&pLink
  1231. );
  1232. ACQUIRE_SPIN_LOCK(&pAdapterContext->ObjectDataBase);
  1233. //
  1234. // We can do nothing, if we are out of resources
  1235. //
  1236. if (Status != STATUS_SUCCESS) {
  1237. return;
  1238. }
  1239. ACQUIRE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1240. //
  1241. // RLF 05/09/94
  1242. //
  1243. // We need to keep a per-connection indication of the framing type if the
  1244. // adapter was opened in AUTO mode (else we generate 802.3 UA to DIX SABME)
  1245. // Only do this for Ethernet adapters (we only set the SNA DIX frame
  1246. // indicator in that case)
  1247. //
  1248. pLink->FramingType = (IS_SNA_DIX_FRAME(pAdapterContext)
  1249. && IS_AUTO_BINDING(pLink->Gen.pLlcBinding))
  1250. ? LLC_SEND_802_3_TO_DIX
  1251. : pLink->Gen.pLlcBinding->InternalAddressTranslation
  1252. ;
  1253. //
  1254. // now create the Link Station by running the FSM with ACTIVATE_LS as input.
  1255. // This just initializes the link station 'object'. Then run the FSM again,
  1256. // this time with the SABME command as input
  1257. //
  1258. RunStateMachineCommand(pLink, ACTIVATE_LS);
  1259. RunStateMachine(
  1260. pLink,
  1261. (USHORT)((LlcHeader.U.Command & LLC_U_POLL_FINAL) ? SABME1 : SABME0),
  1262. (BOOLEAN)((LlcHeader.U.Command & LLC_U_POLL_FINAL) ? 1 : 0),
  1263. (BOOLEAN)TRUE
  1264. );
  1265. RELEASE_SPIN_LOCK(&pAdapterContext->SendSpinLock);
  1266. }
  1267. VOID
  1268. LlcTransferData(
  1269. IN PBINDING_CONTEXT pBindingContext,
  1270. IN NDIS_HANDLE MacReceiveContext,
  1271. IN PLLC_PACKET pPacket,
  1272. IN PMDL pMdl,
  1273. IN UINT uiCopyOffset,
  1274. IN UINT cbCopyLength
  1275. )
  1276. /*++
  1277. Routine Description:
  1278. This function copies only the data part of the received frame - that is
  1279. the area after the LLC and DLC headers. If NDIS handed us all the data
  1280. in the lookahead buffer, then WE can copy it out. Otherwise we have to
  1281. call NDIS to get the data.
  1282. If this is a DIX format frame, then NDIS thinks that the LAN header is
  1283. 14 bytes, but we know it is 17. We have to tell NDIS to copy from 3 bytes
  1284. further into the data part of the received frame than we would normally
  1285. have to
  1286. Arguments:
  1287. pBindingContext - binding handle
  1288. MacReceiveContext - For NdisTransferData
  1289. pPacket - receive context packet
  1290. pMdl - pointer to MDL describing data to copy
  1291. uiCopyOffset - offset from start of mapped buffer to copy from
  1292. cbCopyLength - length to copy
  1293. Return Value:
  1294. None.
  1295. --*/
  1296. {
  1297. PADAPTER_CONTEXT pAdapterContext = pBindingContext->pAdapterContext;
  1298. pPacket->Data.Completion.CompletedCommand = LLC_RECEIVE_COMPLETION;
  1299. //
  1300. // if the amount of data to copy is contained within the lookahead buffer
  1301. // then we can copy the data.
  1302. //
  1303. // Remember: pAdapterContext->cbLookBuf and pLookBuf have been correctly
  1304. // adjusted in the case of a DIX format frame
  1305. //
  1306. if (pAdapterContext->cbLookBuf - uiCopyOffset >= cbCopyLength) {
  1307. PUCHAR pSrcBuffer;
  1308. UINT BufferLength;
  1309. pSrcBuffer = pAdapterContext->pLookBuf + uiCopyOffset;
  1310. do {
  1311. if (cbCopyLength > MmGetMdlByteCount(pMdl)) {
  1312. BufferLength = MmGetMdlByteCount(pMdl);
  1313. } else {
  1314. BufferLength = cbCopyLength;
  1315. }
  1316. //
  1317. // In 386 memcpy is faster than RtlMoveMemory, it also
  1318. // makes the full register optimization much easier, because
  1319. // all registers are available (no proc calls within loop)
  1320. //
  1321. //
  1322. // !!!! Can't use LlcMemCpy here: On mips expands to RtlMoveMemory
  1323. // which uses FP registers. This won't work with shared memory
  1324. // on TR card
  1325. //
  1326. safe_memcpy(MmGetSystemAddressForMdl(pMdl), pSrcBuffer, BufferLength);
  1327. pMdl = pMdl->Next;
  1328. pSrcBuffer += BufferLength;
  1329. cbCopyLength -= BufferLength;
  1330. } while (cbCopyLength);
  1331. pPacket->Data.Completion.Status = STATUS_SUCCESS;
  1332. pBindingContext->TransferDataPacket.pPacket = pPacket;
  1333. } else {
  1334. //
  1335. // too bad: there is more data to copy than is available in the look
  1336. // ahead buffer. We have to call NDIS to perform the copy
  1337. //
  1338. UINT BytesCopied;
  1339. //
  1340. // if this is an Ethernet adapter and the received LAN header length is
  1341. // more than 14 bytes then this is a DIX frame. We need to let NDIS know
  1342. // that we want to copy data from 3 bytes in from where it thinks the
  1343. // DLC header starts
  1344. //
  1345. UINT additionalOffset = (pAdapterContext->NdisMedium == NdisMedium802_3)
  1346. ? (pAdapterContext->RcvLanHeaderLength > 14)
  1347. ? 3
  1348. : 0
  1349. : 0;
  1350. #if DBG
  1351. if (additionalOffset) {
  1352. ASSERT(pAdapterContext->RcvLanHeaderLength == 17);
  1353. }
  1354. #endif
  1355. //
  1356. // Theoretically NdisTransferData may not complete
  1357. // immediately, and we cannot add to the completion
  1358. // list, because the command is not really complete.
  1359. // We may save it to adapter context to wait the
  1360. // NdisTransferData to complete.
  1361. //
  1362. if (pBindingContext->TransferDataPacket.pPacket != NULL) {
  1363. //
  1364. // BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG
  1365. //
  1366. // If the same LLC client tries to receive the same buffer
  1367. // many times (eg. when receive a packet to a group sap) and
  1368. // if NDIS would complete those commands asynchronously, then
  1369. // we cannot receive the frame with NdisTransferData.
  1370. // Fortunately all NDIS implemnetations completes NdisTransferData
  1371. // synchronously.
  1372. // Solution: We could chain new packets to the existing data transfer
  1373. // packet, and copy the data, when the first data transfer request
  1374. // completes. This would mean a lot of code, that would never
  1375. // used by anyone. We would also need MDL to MDL copy function.
  1376. // The first data transfer could also be a smaller that another
  1377. // after it => would not work in a very general case, but
  1378. // would work with the group saps (all receives would be the same
  1379. // => direct MDL -> MDL copy would be OK.
  1380. //
  1381. // BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG-BUG
  1382. //
  1383. pPacket->Data.Completion.Status = DLC_STATUS_ASYNC_DATA_TRANSFER_FAILED;
  1384. pBindingContext->pfCommandComplete(pBindingContext->hClientContext,
  1385. pPacket->Data.Completion.hClientHandle,
  1386. pPacket
  1387. );
  1388. }
  1389. pBindingContext->TransferDataPacket.pPacket = pPacket;
  1390. pPacket->pBinding = pBindingContext;
  1391. ResetNdisPacket(&pBindingContext->TransferDataPacket);
  1392. NdisChainBufferAtFront((PNDIS_PACKET)&pBindingContext->TransferDataPacket, pMdl);
  1393. //
  1394. // ADAMBA - Removed pAdapterContext->RcvLanHeaderLength
  1395. // from ByteOffset (the fourth param).
  1396. //
  1397. NdisTransferData((PNDIS_STATUS)&pPacket->Data.Completion.Status,
  1398. pAdapterContext->NdisBindingHandle,
  1399. MacReceiveContext,
  1400. //
  1401. // if this is a DIX frame we have to move the data
  1402. // pointer ahead by the amount in additionalOffset
  1403. // (should always be 3 in this case) and reduce the
  1404. // amount of data to copy by the same number
  1405. //
  1406. uiCopyOffset + additionalOffset,
  1407. //
  1408. // we DON'T need to account for the additionalOffset
  1409. // in the length to be copied though
  1410. //
  1411. cbCopyLength,
  1412. (PNDIS_PACKET)&pBindingContext->TransferDataPacket,
  1413. &BytesCopied
  1414. );
  1415. }
  1416. //
  1417. // We must queue a packet for the final receive completion,
  1418. // But we cannot do it until TransferData is completed
  1419. // (it is actually always completed, but this code is just
  1420. // for sure).
  1421. //
  1422. if (pPacket->Data.Completion.Status != NDIS_STATUS_PENDING
  1423. && pAdapterContext->LinkRcvStatus != STATUS_PENDING) {
  1424. //
  1425. // We receive the data before it is checked by the link station.
  1426. // The upper protocol must just setup asynchronous receive
  1427. // and later in LLC_RECEIVE_COMPLETION handling to
  1428. // discard the receive, if it failed or accept if
  1429. // it was OK for NDIS and link station.
  1430. //
  1431. if (pAdapterContext->LinkRcvStatus != STATUS_SUCCESS) {
  1432. pPacket->Data.Completion.Status = pAdapterContext->LinkRcvStatus;
  1433. }
  1434. ACQUIRE_DRIVER_LOCK();
  1435. pBindingContext->pfCommandComplete(pBindingContext->hClientContext,
  1436. pPacket->Data.Completion.hClientHandle,
  1437. pPacket
  1438. );
  1439. RELEASE_DRIVER_LOCK();
  1440. pBindingContext->TransferDataPacket.pPacket = NULL;
  1441. }
  1442. }
  1443. VOID
  1444. LlcNdisTransferDataComplete(
  1445. IN PADAPTER_CONTEXT pAdapterContext,
  1446. IN PNDIS_PACKET pPacket,
  1447. IN NDIS_STATUS NdisStatus,
  1448. IN UINT uiBytesTransferred
  1449. )
  1450. /*++
  1451. Routine Description:
  1452. The routine handles NdisCompleteDataTransfer indication and
  1453. queues the indication of the completed receive operation.
  1454. Arguments:
  1455. pAdapterContext - adapter context
  1456. pPacket - NDIS packet used in the data transfer
  1457. NdisStatus - status of the completed data transfer
  1458. uiBytesTransferred - who needs this, I am not interested in
  1459. the partially succeeded data transfers,
  1460. Return Value:
  1461. None.
  1462. --*/
  1463. {
  1464. KIRQL OldIrql;
  1465. UNREFERENCED_PARAMETER(uiBytesTransferred);
  1466. UNREFERENCED_PARAMETER(OldIrql);
  1467. ASSUME_IRQL(DISPATCH_LEVEL);
  1468. #ifdef NDIS40
  1469. REFADD(&pAdapterContext->AdapterRefCnt, 'xefX');
  1470. if (InterlockedCompareExchange(
  1471. &pAdapterContext->BindState,
  1472. BIND_STATE_BOUND,
  1473. BIND_STATE_BOUND) != BIND_STATE_BOUND)
  1474. {
  1475. REFDEL(&pAdapterContext->AdapterRefCnt, 'xefX');
  1476. return;
  1477. }
  1478. #endif // NDIS40
  1479. ACQUIRE_DRIVER_LOCK();
  1480. if (((PLLC_TRANSFER_PACKET)pPacket)->pPacket != NULL) {
  1481. ((PLLC_TRANSFER_PACKET)pPacket)->pPacket->Data.Completion.Status = NdisStatus;
  1482. //
  1483. // I- frames have two statuses. The link state machine is executed
  1484. // after the NdisDataTransfer and thus its returned status may still
  1485. // cancel the command. There are no spin locks around the return status
  1486. // handling, but this should still work fine. It actually does not
  1487. // matter if we return NDIS or state machine error code
  1488. //
  1489. if (pAdapterContext->LinkRcvStatus != STATUS_PENDING) {
  1490. if (pAdapterContext->LinkRcvStatus != STATUS_SUCCESS) {
  1491. ((PLLC_TRANSFER_PACKET)pPacket)->pPacket->Data.Completion.Status = pAdapterContext->LinkRcvStatus;
  1492. }
  1493. ((PLLC_TRANSFER_PACKET)pPacket)->pPacket->pBinding->pfCommandComplete(
  1494. ((PLLC_TRANSFER_PACKET)pPacket)->pPacket->pBinding->hClientContext,
  1495. ((PLLC_TRANSFER_PACKET)pPacket)->pPacket->Data.Completion.hClientHandle,
  1496. ((PLLC_TRANSFER_PACKET)pPacket)->pPacket
  1497. );
  1498. ((PLLC_TRANSFER_PACKET)pPacket)->pPacket = NULL;
  1499. }
  1500. }
  1501. RELEASE_DRIVER_LOCK();
  1502. #ifdef NDIS40
  1503. REFDEL(&pAdapterContext->AdapterRefCnt, 'xefX');
  1504. #endif // NDIS40
  1505. }
  1506. VOID
  1507. safe_memcpy(
  1508. OUT PUCHAR Destination,
  1509. IN PUCHAR Source,
  1510. IN ULONG Length
  1511. )
  1512. /*++
  1513. Routine Description:
  1514. This is here because on a MIPS machine, LlcMemCpy expands to RtlMoveMemory
  1515. which wants to use 64-bit floating point (CP1) registers for memory moves
  1516. where both source and destination are aligned on 8-byte boundaries and
  1517. where the length is a multiple of 32 bytes. If the source or destination
  1518. buffer is actually the shared memory of a TR card, then the 64-bit moves
  1519. (saw it on read, presume same for write) can only access memory in 32-bit
  1520. chunks and 01 02 03 04 05 06 07 08 gets converted to 01 02 03 04 01 02 03 04.
  1521. So this function attempts to do basically the same, without all the smarts
  1522. as the original, but doesn't employ coprocessor registers to achieve the
  1523. move. Hence slower, but safer
  1524. Arguments:
  1525. Destination - where we're copying to
  1526. Source - where we're copying from
  1527. Length - how many bytes to move
  1528. Return Value:
  1529. None.
  1530. --*/
  1531. {
  1532. ULONG difference = (ULONG)((ULONG_PTR)Destination - (ULONG_PTR)Source);
  1533. INT i;
  1534. if (!(difference && Length)) {
  1535. return;
  1536. }
  1537. //
  1538. // if the destination overlaps the source then do reverse copy. Add a little
  1539. // optimization - a la RtlMoveMemory - try to copy as many bytes as DWORDS.
  1540. // However, on MIPS, both source and destination must be DWORD aligned to
  1541. // do this. If both aren't then fall-back to BYTE copy
  1542. //
  1543. if (difference < Length) {
  1544. if (!(((ULONG_PTR)Destination & 3) || ((ULONG_PTR)Source & 3))) {
  1545. Destination += Length;
  1546. Source += Length;
  1547. for (i = Length % 4; i; --i) {
  1548. *--Destination = *--Source;
  1549. }
  1550. for (i = Length / 4; i; --i) {
  1551. *--((PULONG)Destination) = *--((PULONG)Source);
  1552. }
  1553. } else {
  1554. Destination += Length;
  1555. Source += Length;
  1556. while (Length--) {
  1557. *--Destination = *--Source;
  1558. }
  1559. }
  1560. } else {
  1561. if (!(((ULONG_PTR)Destination & 3) || ((ULONG_PTR)Source & 3))) {
  1562. for (i = Length / 4; i; --i) {
  1563. *((PULONG)Destination)++ = *((PULONG)Source)++;
  1564. }
  1565. for (i = Length % 4; i; --i) {
  1566. *Destination++ = *Source++;
  1567. }
  1568. } else {
  1569. while (Length--) {
  1570. *Destination++ = *Source++;
  1571. }
  1572. }
  1573. }
  1574. }
  1575. BOOLEAN
  1576. FramingDiscoveryCacheHit(
  1577. IN PADAPTER_CONTEXT pAdapterContext,
  1578. IN PBINDING_CONTEXT pBindingContext
  1579. )
  1580. /*++
  1581. Routine Description:
  1582. This function is called when we receive a TEST/XID/SABME frame AND the
  1583. adapter binding was created with LLC_ETHERNET_TYPE_AUTO AND we opened an
  1584. ethernet adapter.
  1585. The frame has either 802.3 or DIX framing. For all command and response TEST
  1586. and XID frames and all SABME frames received, we keep note of the MAC address
  1587. where the frame originated and its framing type.
  1588. The first time we receive one of the above frames from a particular MAC
  1589. address, the info will not be in the cache. So we add it. Subsequent frames
  1590. of the above type (all others are passed through) with the same framing type
  1591. as that in the cache will be indicated to the higher layers. If one of the
  1592. above frame types arrives with THE OPPOSITE framing type (i.e. DIX instead
  1593. of 802.3) then when we look in the cache for the MAC address we will find
  1594. that it is already there, but with a different framing type (i.e. 802.3
  1595. instead of DIX). In this case, we assume that the frame is an automatic
  1596. duplicate and we discard it
  1597. NOTE: We don't have to worry about UA because we only expect one SABME to
  1598. be accepted: either we're sending the duplicate SABME and the target machine
  1599. is configured for 802.3 or DIX, BUT NOT BOTH, or the receiving machine is
  1600. another NT box running this DLC (with caching enabled!) and it will filter
  1601. out the duplicate. Hence, in both situations, only one UA response should be
  1602. generated per the SABME 'event'
  1603. ASSUMES: The tick count returned from the system never wraps (! 2^63/10^7
  1604. == 29,247+ years)
  1605. Arguments:
  1606. pAdapterContext - pointer to ADAPTER_CONTEXT which has been filled in with
  1607. pHeadBuf pointing to - at least - the first 14 bytes in
  1608. the frame header
  1609. pBindingContext - pointer to BINDING_CONTEXT containing the EthernetType
  1610. and if LLC_ETHERNET_TYPE_AUTO, the address of the framing
  1611. discovery cache
  1612. Return Value:
  1613. BOOLEAN
  1614. TRUE - the MAC address was found in the cache WITH THE OTHER FRAMING
  1615. TYPE. Therefore the current frame should be discarded
  1616. FALSE - the MAC address/framing type combination was not found. The
  1617. frame should be indicated to the higher layer. If caching is
  1618. enabled, the frame has been added to the cache
  1619. --*/
  1620. {
  1621. ULONG i;
  1622. ULONG lruIndex;
  1623. LARGE_INTEGER timeStamp;
  1624. NODE_ADDRESS nodeAddress;
  1625. PFRAMING_DISCOVERY_CACHE_ENTRY pCache;
  1626. UCHAR framingType;
  1627. //
  1628. // if the binding context was not created with LLC_ETHERNET_TYPE_AUTO (and
  1629. // therefore by implication, adapter is not ethernet) OR framing discovery
  1630. // caching is disabled (the value read from the registry was zero) then bail
  1631. // out with a not-found indication
  1632. //
  1633. if ((pBindingContext->EthernetType != LLC_ETHERNET_TYPE_AUTO)
  1634. || (pBindingContext->FramingDiscoveryCacheEntries == 0)) {
  1635. #if defined(DEBUG_DISCOVERY)
  1636. DbgPrint("FramingDiscoveryCacheHit: Not AUTO or 0 cache: returning FALSE\n");
  1637. #endif
  1638. return FALSE;
  1639. }
  1640. #if defined(DEBUG_DISCOVERY)
  1641. {
  1642. //
  1643. // even though this is debug code, we shouldn't really be
  1644. // indexing so far into pHeadBuf. Its only guaranteed to be
  1645. // 14 bytes long. Should be looking in pLookBuf[5] and [2]
  1646. //
  1647. UCHAR frame = (pAdapterContext->pHeadBuf[12] == 0x80)
  1648. ? pAdapterContext->pHeadBuf[19]
  1649. : pAdapterContext->pHeadBuf[16];
  1650. frame &= ~0x10; // knock off Poll/Final bit
  1651. DbgPrint("FramingDiscoveryCacheHit: Received: %02x-%02x-%02x-%02x-%02x-%02x %s %s (%02x)\n",
  1652. pAdapterContext->pHeadBuf[6],
  1653. pAdapterContext->pHeadBuf[7],
  1654. pAdapterContext->pHeadBuf[8],
  1655. pAdapterContext->pHeadBuf[9],
  1656. pAdapterContext->pHeadBuf[10],
  1657. pAdapterContext->pHeadBuf[11],
  1658. (pAdapterContext->pHeadBuf[12] == 0x80)
  1659. ? "DIX"
  1660. : "802.3",
  1661. (frame == 0xE3)
  1662. ? "TEST"
  1663. : (frame == 0xAF)
  1664. ? "XID"
  1665. : (frame == 0x6F)
  1666. ? "SABME"
  1667. : (frame == 0x63)
  1668. ? "UA"
  1669. : "???",
  1670. frame
  1671. );
  1672. }
  1673. #endif
  1674. //
  1675. // set up and perform a linear search of the cache (it should be reasonably
  1676. // small and the comparisons are ULONG & USHORT, so not time critical
  1677. //
  1678. lruIndex = 0;
  1679. //
  1680. // better make sure we don't get data misalignment on MIPS
  1681. //
  1682. nodeAddress.Words.Top4 = *(ULONG UNALIGNED *)&pAdapterContext->pHeadBuf[6];
  1683. nodeAddress.Words.Bottom2 = *(USHORT UNALIGNED *)&pAdapterContext->pHeadBuf[10];
  1684. pCache = pBindingContext->FramingDiscoveryCache;
  1685. //
  1686. // framingType is the type we are looking for in the cache, not the type
  1687. // in the frame
  1688. //
  1689. framingType = ((pAdapterContext->pHeadBuf[12] == 0x80)
  1690. && (pAdapterContext->pHeadBuf[13] == 0xD5))
  1691. ? FRAMING_TYPE_802_3
  1692. : FRAMING_TYPE_DIX
  1693. ;
  1694. //
  1695. // get the current tick count for comparison of time stamps
  1696. //
  1697. KeQueryTickCount(&timeStamp);
  1698. //
  1699. // linear search the cache
  1700. //
  1701. for (i = 0; i < pBindingContext->FramingDiscoveryCacheEntries; ++i) {
  1702. if (pCache[i].InUse) {
  1703. if ((pCache[i].NodeAddress.Words.Top4 == nodeAddress.Words.Top4)
  1704. && (pCache[i].NodeAddress.Words.Bottom2 == nodeAddress.Words.Bottom2)) {
  1705. //
  1706. // we found the destination MAC address. If it has the opposite
  1707. // framing type to that in the frame just received, return TRUE
  1708. // else FALSE. In both cases refresh the time stamp
  1709. //
  1710. pCache[i].TimeStamp = timeStamp;
  1711. #if defined(DEBUG_DISCOVERY)
  1712. DbgPrint("FramingDiscoveryCacheHit: Returning %s. Index = %d\n\n",
  1713. (pCache[i].FramingType == framingType) ? "TRUE" : "FALSE",
  1714. i
  1715. );
  1716. #endif
  1717. return (pCache[i].FramingType == framingType);
  1718. } else if (pCache[i].TimeStamp.QuadPart < timeStamp.QuadPart) {
  1719. //
  1720. // if we need to throw out a cache entry, we throw out the one
  1721. // with the oldest time stamp
  1722. //
  1723. timeStamp = pCache[i].TimeStamp;
  1724. lruIndex = i;
  1725. }
  1726. } else {
  1727. //
  1728. // we have hit an unused entry. The destination address/framing type
  1729. // cannot be in the cache: add the received address/framing type at
  1730. // this unused location
  1731. //
  1732. lruIndex = i;
  1733. break;
  1734. }
  1735. }
  1736. //
  1737. // the destination address/framing type combination are not in the cache.
  1738. // Add them. Throw out an entry if necessary
  1739. //
  1740. #if defined(DEBUG_DISCOVERY)
  1741. DbgPrint("FramingDiscoveryCacheHit: Adding/Throwing out %d (time stamp %08x.%08x\n",
  1742. lruIndex,
  1743. pCache[lruIndex].TimeStamp.HighPart,
  1744. pCache[lruIndex].TimeStamp.LowPart
  1745. );
  1746. #endif
  1747. pCache[lruIndex].NodeAddress.Words.Top4 = nodeAddress.Words.Top4;
  1748. pCache[lruIndex].NodeAddress.Words.Bottom2 = nodeAddress.Words.Bottom2;
  1749. pCache[lruIndex].InUse = TRUE;
  1750. pCache[lruIndex].FramingType = (framingType == FRAMING_TYPE_DIX)
  1751. ? FRAMING_TYPE_802_3
  1752. : FRAMING_TYPE_DIX
  1753. ;
  1754. pCache[lruIndex].TimeStamp = timeStamp;
  1755. //
  1756. // return FALSE meaning the destination address/framing type just received
  1757. // was not in the cache (but it is now)
  1758. //
  1759. #if defined(DEBUG_DISCOVERY)
  1760. DbgPrint("FramingDiscoveryCacheHit: Returning FALSE\n\n");
  1761. #endif
  1762. return FALSE;
  1763. }