|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1989-1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: packet.c ! 8: ! 9: Abstract: ! 10: ! 11: This module contains code that implements the TP_PACKET object, which ! 12: describes an NDIS packet. ! 13: ! 14: Environment: ! 15: ! 16: Kernel mode ! 17: ! 18: Revision History: ! 19: ! 20: --*/ ! 21: ! 22: #include "st.h" ! 23: ! 24: // ! 25: // This is temporary; this is the quota that we charge for a receive ! 26: // packet for now, until we fix the problem with token-ring needing ! 27: // big packets and using all the memory. The number is the actual ! 28: // value for Ethernet. ! 29: // ! 30: ! 31: #if 1 ! 32: #define RECEIVE_BUFFER_QUOTA(_DeviceContext) 1533 ! 33: #else ! 34: #define RECEIVE_BUFFER_QUOTA(_DeviceContext) (_DeviceContext)->ReceiveBufferLength ! 35: #endif ! 36: ! 37: ! 38: ! 39: ! 40: VOID ! 41: StAllocateSendPacket( ! 42: IN PDEVICE_CONTEXT DeviceContext, ! 43: OUT PTP_PACKET *TransportSendPacket ! 44: ) ! 45: ! 46: /*++ ! 47: ! 48: Routine Description: ! 49: ! 50: This routine allocates storage for a send packet. Some initialization ! 51: is done here. ! 52: ! 53: NOTE: This routine is called with the device context spinlock ! 54: held, or at such a time as synchronization is unnecessary. ! 55: ! 56: Arguments: ! 57: ! 58: DeviceContext - Pointer to our device context to charge the packet to. ! 59: ! 60: TransportSendPacket - Returns a pointer to the packet, or NULL if no ! 61: storage can be allocated. ! 62: ! 63: Return Value: ! 64: ! 65: None. ! 66: ! 67: --*/ ! 68: ! 69: { ! 70: ! 71: PTP_PACKET Packet; ! 72: NDIS_STATUS NdisStatus; ! 73: PNDIS_PACKET NdisPacket; ! 74: PSEND_PACKET_TAG SendTag; ! 75: PNDIS_BUFFER NdisBuffer; ! 76: ! 77: if ((DeviceContext->MemoryLimit != 0) && ! 78: ((DeviceContext->MemoryUsage + DeviceContext->PacketLength) > ! 79: DeviceContext->MemoryLimit)) { ! 80: PANIC("ST: Could not allocate send packet: limit\n"); ! 81: StWriteResourceErrorLog (DeviceContext, DeviceContext->PacketLength, 107); ! 82: *TransportSendPacket = NULL; ! 83: return; ! 84: } ! 85: ! 86: Packet = (PTP_PACKET)ExAllocatePool (NonPagedPool, DeviceContext->PacketLength); ! 87: if (Packet == NULL) { ! 88: PANIC("ST: Could not allocate send packet: no pool\n"); ! 89: StWriteResourceErrorLog (DeviceContext, DeviceContext->PacketLength, 207); ! 90: *TransportSendPacket = NULL; ! 91: return; ! 92: } ! 93: RtlZeroMemory (Packet, DeviceContext->PacketLength); ! 94: ! 95: DeviceContext->MemoryUsage += DeviceContext->PacketLength; ! 96: ! 97: NdisAllocatePacket ( ! 98: &NdisStatus, ! 99: &NdisPacket, ! 100: DeviceContext->SendPacketPoolHandle); ! 101: ! 102: if (NdisStatus != NDIS_STATUS_SUCCESS) { ! 103: ExFreePool (Packet); ! 104: StWriteResourceErrorLog (DeviceContext, 0, 307); ! 105: *TransportSendPacket = NULL; ! 106: return; ! 107: } ! 108: ! 109: NdisAllocateBuffer( ! 110: &NdisStatus, ! 111: &NdisBuffer, ! 112: DeviceContext->NdisBufferPoolHandle, ! 113: Packet->Header, ! 114: DeviceContext->PacketHeaderLength); ! 115: ! 116: if (NdisStatus != NDIS_STATUS_SUCCESS) { ! 117: NdisFreePacket (NdisPacket); ! 118: ExFreePool (Packet); ! 119: *TransportSendPacket = NULL; ! 120: return; ! 121: } ! 122: ! 123: NdisChainBufferAtFront (NdisPacket, NdisBuffer); ! 124: ! 125: Packet->NdisPacket = NdisPacket; ! 126: SendTag = (PSEND_PACKET_TAG)NdisPacket->ProtocolReserved; ! 127: SendTag->Type = TYPE_I_FRAME; ! 128: SendTag->Packet = Packet; ! 129: SendTag->Owner = NULL; ! 130: ! 131: Packet->Type = ST_PACKET_SIGNATURE; ! 132: Packet->Size = sizeof (TP_PACKET); ! 133: Packet->Provider = DeviceContext; ! 134: ! 135: ++DeviceContext->PacketAllocated; ! 136: ! 137: *TransportSendPacket = Packet; ! 138: ! 139: } /* StAllocateSendPacket */ ! 140: ! 141: ! 142: VOID ! 143: StDeallocateSendPacket( ! 144: IN PDEVICE_CONTEXT DeviceContext, ! 145: IN PTP_PACKET TransportSendPacket ! 146: ) ! 147: ! 148: /*++ ! 149: ! 150: Routine Description: ! 151: ! 152: This routine frees storage for a send packet. ! 153: ! 154: NOTE: This routine is called with the device context spinlock ! 155: held, or at such a time as synchronization is unnecessary. ! 156: ! 157: Arguments: ! 158: ! 159: DeviceContext - Pointer to our device context to charge the packet to. ! 160: ! 161: TransportSendPacket - A pointer to the send packet. ! 162: ! 163: Return Value: ! 164: ! 165: None. ! 166: ! 167: --*/ ! 168: ! 169: { ! 170: PNDIS_PACKET NdisPacket = TransportSendPacket->NdisPacket; ! 171: PNDIS_BUFFER NdisBuffer; ! 172: ! 173: NdisUnchainBufferAtFront (NdisPacket, &NdisBuffer); ! 174: if (NdisBuffer != NULL) { ! 175: NdisFreeBuffer (NdisBuffer); ! 176: } ! 177: ! 178: NdisFreePacket (NdisPacket); ! 179: ExFreePool (TransportSendPacket); ! 180: ! 181: --DeviceContext->PacketAllocated; ! 182: DeviceContext->MemoryUsage -= DeviceContext->PacketLength; ! 183: ! 184: } /* StDeallocateSendPacket */ ! 185: ! 186: ! 187: VOID ! 188: StAllocateReceivePacket( ! 189: IN PDEVICE_CONTEXT DeviceContext, ! 190: OUT PNDIS_PACKET *TransportReceivePacket ! 191: ) ! 192: ! 193: /*++ ! 194: ! 195: Routine Description: ! 196: ! 197: This routine allocates storage for a receive packet. Some initialization ! 198: is done here. ! 199: ! 200: NOTE: This routine is called with the device context spinlock ! 201: held, or at such a time as synchronization is unnecessary. ! 202: ! 203: Arguments: ! 204: ! 205: DeviceContext - Pointer to our device context to charge the packet to. ! 206: ! 207: TransportReceivePacket - Returns a pointer to the packet, or NULL if no ! 208: storage can be allocated. ! 209: ! 210: Return Value: ! 211: ! 212: None. ! 213: ! 214: --*/ ! 215: ! 216: { ! 217: NDIS_STATUS NdisStatus; ! 218: PNDIS_PACKET NdisPacket; ! 219: PRECEIVE_PACKET_TAG ReceiveTag; ! 220: ! 221: // ! 222: // This does not count in DeviceContext->MemoryUsage because ! 223: // the storage is allocated when we allocate the packet pool. ! 224: // ! 225: ! 226: NdisAllocatePacket ( ! 227: &NdisStatus, ! 228: &NdisPacket, ! 229: DeviceContext->ReceivePacketPoolHandle); ! 230: ! 231: if (NdisStatus != NDIS_STATUS_SUCCESS) { ! 232: StWriteResourceErrorLog (DeviceContext, 0, 309); ! 233: *TransportReceivePacket = NULL; ! 234: return; ! 235: } ! 236: ! 237: ReceiveTag = (PRECEIVE_PACKET_TAG)(NdisPacket->ProtocolReserved); ! 238: ReceiveTag->PacketType = TYPE_AT_INDICATE; ! 239: ! 240: ++DeviceContext->ReceivePacketAllocated; ! 241: ! 242: *TransportReceivePacket = NdisPacket; ! 243: ! 244: } /* StAllocateReceivePacket */ ! 245: ! 246: ! 247: VOID ! 248: StDeallocateReceivePacket( ! 249: IN PDEVICE_CONTEXT DeviceContext, ! 250: IN PNDIS_PACKET TransportReceivePacket ! 251: ) ! 252: ! 253: /*++ ! 254: ! 255: Routine Description: ! 256: ! 257: This routine frees storage for a receive packet. ! 258: ! 259: NOTE: This routine is called with the device context spinlock ! 260: held, or at such a time as synchronization is unnecessary. ! 261: ! 262: Arguments: ! 263: ! 264: DeviceContext - Pointer to our device context to charge the packet to. ! 265: ! 266: TransportReceivePacket - A pointer to the packet. ! 267: ! 268: Return Value: ! 269: ! 270: None. ! 271: ! 272: --*/ ! 273: ! 274: { ! 275: ! 276: NdisFreePacket (TransportReceivePacket); ! 277: ! 278: --DeviceContext->ReceivePacketAllocated; ! 279: ! 280: } /* StDeallocateReceivePacket */ ! 281: ! 282: ! 283: VOID ! 284: StAllocateReceiveBuffer( ! 285: IN PDEVICE_CONTEXT DeviceContext, ! 286: OUT PBUFFER_TAG *TransportReceiveBuffer ! 287: ) ! 288: ! 289: /*++ ! 290: ! 291: Routine Description: ! 292: ! 293: This routine allocates storage for a receive buffer. Some initialization ! 294: is done here. ! 295: ! 296: NOTE: This routine is called with the device context spinlock ! 297: held, or at such a time as synchronization is unnecessary. ! 298: ! 299: Arguments: ! 300: ! 301: DeviceContext - Pointer to our device context to charge the packet to. ! 302: ! 303: TransportReceiveBuffer - Returns a pointer to the buffer, or NULL if no ! 304: storage can be allocated. ! 305: ! 306: Return Value: ! 307: ! 308: None. ! 309: ! 310: --*/ ! 311: ! 312: { ! 313: PBUFFER_TAG BufferTag; ! 314: NDIS_STATUS NdisStatus; ! 315: PNDIS_BUFFER NdisBuffer; ! 316: ! 317: ! 318: if ((DeviceContext->MemoryLimit != 0) && ! 319: ((DeviceContext->MemoryUsage + RECEIVE_BUFFER_QUOTA(DeviceContext)) > ! 320: DeviceContext->MemoryLimit)) { ! 321: PANIC("ST: Could not allocate receive buffer: limit\n"); ! 322: StWriteResourceErrorLog (DeviceContext, RECEIVE_BUFFER_QUOTA(DeviceContext), 108); ! 323: *TransportReceiveBuffer = NULL; ! 324: return; ! 325: } ! 326: ! 327: BufferTag = (PBUFFER_TAG)ExAllocatePool ( ! 328: NonPagedPoolCacheAligned, ! 329: DeviceContext->ReceiveBufferLength); ! 330: ! 331: if (BufferTag == NULL) { ! 332: PANIC("ST: Could not allocate receive buffer: no pool\n"); ! 333: StWriteResourceErrorLog (DeviceContext, DeviceContext->ReceiveBufferLength, 208); ! 334: *TransportReceiveBuffer = NULL; ! 335: return; ! 336: } ! 337: ! 338: DeviceContext->MemoryUsage += RECEIVE_BUFFER_QUOTA(DeviceContext); ! 339: ! 340: // ! 341: // point to the buffer for NDIS ! 342: // ! 343: ! 344: NdisAllocateBuffer( ! 345: &NdisStatus, ! 346: &NdisBuffer, ! 347: DeviceContext->NdisBufferPoolHandle, ! 348: BufferTag->Buffer, ! 349: DeviceContext->MaxReceivePacketSize); ! 350: ! 351: if (NdisStatus != NDIS_STATUS_SUCCESS) { ! 352: ExFreePool (BufferTag); ! 353: *TransportReceiveBuffer = NULL; ! 354: return; ! 355: } ! 356: ! 357: BufferTag->Length = DeviceContext->MaxReceivePacketSize; ! 358: BufferTag->NdisBuffer = NdisBuffer; ! 359: ! 360: ++DeviceContext->ReceiveBufferAllocated; ! 361: ! 362: *TransportReceiveBuffer = BufferTag; ! 363: ! 364: } /* StAllocateReceiveBuffer */ ! 365: ! 366: ! 367: VOID ! 368: StDeallocateReceiveBuffer( ! 369: IN PDEVICE_CONTEXT DeviceContext, ! 370: IN PBUFFER_TAG TransportReceiveBuffer ! 371: ) ! 372: ! 373: /*++ ! 374: ! 375: Routine Description: ! 376: ! 377: This routine frees storage for a receive buffer. ! 378: ! 379: NOTE: This routine is called with the device context spinlock ! 380: held, or at such a time as synchronization is unnecessary. ! 381: ! 382: Arguments: ! 383: ! 384: DeviceContext - Pointer to our device context to charge the packet to. ! 385: ! 386: TransportReceiveBuffer - A pointer to the buffer. ! 387: ! 388: Return Value: ! 389: ! 390: None. ! 391: ! 392: --*/ ! 393: ! 394: { ! 395: ! 396: NdisFreeBuffer (TransportReceiveBuffer->NdisBuffer); ! 397: ExFreePool (TransportReceiveBuffer); ! 398: ! 399: --DeviceContext->ReceiveBufferAllocated; ! 400: DeviceContext->MemoryUsage -= RECEIVE_BUFFER_QUOTA(DeviceContext); ! 401: ! 402: } /* StDeallocateReceiveBuffer */ ! 403: ! 404: ! 405: NTSTATUS ! 406: StCreatePacket( ! 407: PDEVICE_CONTEXT DeviceContext, ! 408: PTP_PACKET *Packet ! 409: ) ! 410: ! 411: /*++ ! 412: ! 413: Routine Description: ! 414: ! 415: This routine allocates a packet from the device context's pool, ! 416: and prepares the MAC and DLC headers for use by the connection. ! 417: ! 418: Arguments: ! 419: ! 420: DeviceContext - Pointer to our device context to charge the packet to. ! 421: ! 422: Packet - Pointer to a place where we will return a pointer to the ! 423: allocated packet. ! 424: ! 425: Return Value: ! 426: ! 427: NTSTATUS - status of operation. ! 428: ! 429: --*/ ! 430: ! 431: { ! 432: KIRQL oldirql; ! 433: PSINGLE_LIST_ENTRY s; ! 434: PTP_PACKET ThePacket; ! 435: ! 436: s = ExInterlockedPopEntryList ( ! 437: &DeviceContext->PacketPool, ! 438: &DeviceContext->Interlock); ! 439: ! 440: if (s == NULL) { ! 441: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql); ! 442: ++DeviceContext->PacketExhausted; ! 443: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql); ! 444: return STATUS_INSUFFICIENT_RESOURCES; ! 445: } ! 446: ! 447: ThePacket = CONTAINING_RECORD (s, TP_PACKET, Linkage); ! 448: ! 449: ThePacket->Provider = DeviceContext; // who owns this packet ! 450: ThePacket->PacketSent = FALSE; ! 451: ThePacket->PacketNoNdisBuffer = FALSE; ! 452: ! 453: *Packet = ThePacket; // return pointer to the packet. ! 454: return STATUS_SUCCESS; ! 455: } /* StCreatePacket */ ! 456: ! 457: ! 458: VOID ! 459: StDestroyPacket( ! 460: PTP_PACKET Packet ! 461: ) ! 462: ! 463: /*++ ! 464: ! 465: Routine Description: ! 466: ! 467: This routine destroys a packet, thereby returning it to the pool. If ! 468: it is determined that there is at least one connection waiting for a ! 469: packet to become available (and it just has), then the connection is ! 470: removed from the device context's list and AdvanceSend is called to ! 471: prep the connection further. ! 472: ! 473: Arguments: ! 474: ! 475: Packet - Pointer to a packet to be returned to the pool. ! 476: ! 477: Return Value: ! 478: ! 479: none. ! 480: ! 481: --*/ ! 482: ! 483: { ! 484: KIRQL oldirql1; ! 485: PDEVICE_CONTEXT DeviceContext; ! 486: PTP_CONNECTION Connection; ! 487: PLIST_ENTRY p; ! 488: PNDIS_BUFFER HeaderBuffer; ! 489: PNDIS_BUFFER NdisBuffer; ! 490: ! 491: ! 492: // ! 493: // Strip off and unmap the buffers describing data and header. ! 494: // ! 495: ! 496: NdisUnchainBufferAtFront (Packet->NdisPacket, &HeaderBuffer); ! 497: ! 498: // data buffers get thrown away ! 499: ! 500: if (Packet->PacketNoNdisBuffer) { ! 501: ! 502: // ! 503: // If the NDIS_BUFFER chain is not ours, then we can't ! 504: // start unchaining since that would mess up the queue; ! 505: // instead we just drop the rest of the chain. ! 506: // ! 507: ! 508: NdisReinitializePacket (Packet->NdisPacket); ! 509: ! 510: } else { ! 511: ! 512: // ! 513: // Return all the NDIS_BUFFERs to the system. ! 514: // ! 515: ! 516: NdisUnchainBufferAtFront (Packet->NdisPacket, &NdisBuffer); ! 517: while (NdisBuffer != NULL) { ! 518: NdisFreeBuffer (NdisBuffer); ! 519: NdisUnchainBufferAtFront (Packet->NdisPacket, &NdisBuffer); ! 520: } ! 521: ! 522: } ! 523: ! 524: ASSERT (HeaderBuffer != NULL); ! 525: NDIS_BUFFER_LINKAGE(HeaderBuffer) = (PNDIS_BUFFER)NULL; ! 526: ! 527: NdisChainBufferAtFront (Packet->NdisPacket, HeaderBuffer); ! 528: ! 529: ! 530: // ! 531: // Put the packet back for use again. ! 532: // ! 533: ! 534: DeviceContext = Packet->Provider; ! 535: ! 536: ExInterlockedPushEntryList ( ! 537: &DeviceContext->PacketPool, ! 538: (PSINGLE_LIST_ENTRY)&Packet->Linkage, ! 539: &DeviceContext->Interlock); ! 540: ! 541: // ! 542: // If there is a connection waiting to ship out more packets, then ! 543: // wake it up and start packetizing again. ! 544: // ! 545: // We do a quick check without the lock; there is a small ! 546: // window where we may not take someone off, but this ! 547: // window exists anyway and we assume that more packets ! 548: // will be freed in the future. ! 549: // ! 550: ! 551: if (IsListEmpty (&DeviceContext->PacketWaitQueue)) { ! 552: return; ! 553: } ! 554: ! 555: p = ExInterlockedRemoveHeadList( ! 556: &DeviceContext->PacketWaitQueue, ! 557: &DeviceContext->SpinLock); ! 558: ! 559: if (p != NULL) { ! 560: ! 561: // ! 562: // Remove a connection from the "packet starved" queue. ! 563: // ! 564: ! 565: Connection = CONTAINING_RECORD (p, TP_CONNECTION, PacketWaitLinkage); ! 566: ACQUIRE_SPIN_LOCK (&Connection->SpinLock, &oldirql1); ! 567: Connection->Flags &= ~CONNECTION_FLAGS_SUSPENDED; ! 568: ! 569: // ! 570: // Place the connection on the packetize queue and start ! 571: // packetizing the next connection to be serviced. If he ! 572: // is already on the packetize queue for some reason, then ! 573: // don't do this. ! 574: // ! 575: ! 576: Connection->SendState = CONNECTION_SENDSTATE_PACKETIZE; ! 577: ! 578: if (!(Connection->Flags & CONNECTION_FLAGS_STOPPING) && ! 579: !(Connection->Flags & CONNECTION_FLAGS_PACKETIZE)) { ! 580: ! 581: Connection->Flags |= CONNECTION_FLAGS_PACKETIZE; ! 582: ! 583: StReferenceConnection ("Packet available", Connection); ! 584: ! 585: ExInterlockedInsertTailList( ! 586: &DeviceContext->PacketizeQueue, ! 587: &Connection->PacketizeLinkage, ! 588: &DeviceContext->SpinLock); ! 589: } ! 590: ! 591: RELEASE_SPIN_LOCK (&Connection->SpinLock, oldirql1); ! 592: PacketizeConnections (DeviceContext); ! 593: ! 594: } ! 595: ! 596: } /* StDestroyPacket */ ! 597:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.