|
|
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.