|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1990 Microsoft Corporation
4:
5: Module Name:
6:
7: send.c
8:
9: Abstract:
10:
11: This file contains the code for putting a packet through the
12: staged allocation for transmission.
13:
14: This is a process of
15:
16: 1) Calculating the what would need to be done to the
17: packet so that the packet can be transmitted on the hardware.
18:
19: 2) Potentially allocating adapter buffers and copying user data
20: to those buffers so that the packet data is transmitted under
21: the hardware constraints.
22:
23: 3) Allocating enough hardware ring entries so that the packet
24: can be transmitted.
25:
26: 4) Relinquish thos ring entries to the hardware.
27:
28: The overall structure and most of the code is taken from
29: the Lance driver by Tony Ercolano.
30:
31: Author:
32:
33: Anthony V. Ercolano (Tonye) 12-Sept-1990
34: Adam Barr (adamba) 16-Nov-1990
35:
36: Environment:
37:
38: Kernel Mode - Or whatever is the equivalent.
39:
40: Revision History:
41:
42:
43: --*/
44:
45: #pragma optimize("",off)
46:
47: #include <ndis.h>
48:
49: #include <tfilter.h>
50: #include <tokhrd.h>
51: #include <toksft.h>
52:
53:
54: #if DEVL
55: #define STATIC
56: #else
57: #define STATIC static
58: #endif
59:
60: #if DBG
61: extern INT IbmtokDbg;
62:
63: extern UCHAR Packets[5][64];
64: extern UCHAR NextPacket;
65: #endif
66:
67:
68:
69: #ifdef CHECK_DUP_SENDS
70:
71: //
72: // CHECK_DUP_SENDS enables checking ownership of packets, to
73: // make sure we are not given the same packet twice, or
74: // complete the same packet twice.
75: //
76:
77: #define PACKET_LIST_SIZE 50
78:
79: PNDIS_PACKET IbmtokPacketList[PACKET_LIST_SIZE];
80: IbmtokPacketListSize = 0;
81: IbmtokPacketsAdded = 0;
82: IbmtokPacketsRemoved = 0;
83:
84: VOID
85: IbmtokAddPacketToList(
86: PIBMTOK_ADAPTER Adapter,
87: PNDIS_PACKET NewPacket
88: )
89: {
90: INT i;
91:
92: ++IbmtokPacketsAdded;
93:
94: for (i=0; i<IbmtokPacketListSize; i++) {
95:
96: if (IbmtokPacketList[i] == NewPacket) {
97:
98: DbgPrint("IBMTOK: dup send of %lx\n", NewPacket);
99:
100: }
101:
102: }
103:
104: IbmtokPacketList[IbmtokPacketListSize] = NewPacket;
105: ++IbmtokPacketListSize;
106:
107: }
108:
109: VOID
110: IbmtokRemovePacketFromList(
111: PIBMTOK_ADAPTER Adapter,
112: PNDIS_PACKET OldPacket
113: )
114: {
115: INT i;
116:
117: ++IbmtokPacketsRemoved;
118:
119: for (i=0; i<IbmtokPacketListSize; i++) {
120:
121: if (IbmtokPacketList[i] == OldPacket) {
122:
123: break;
124:
125: }
126:
127: }
128:
129: if (i == IbmtokPacketListSize) {
130:
131: DbgPrint("IBMTOK: bad remove of %lx\n", OldPacket);
132:
133: } else {
134:
135: --IbmtokPacketListSize;
136: IbmtokPacketList[i] = IbmtokPacketList[IbmtokPacketListSize];
137:
138: }
139:
140: }
141: #endif // CHECK_DUP_SENDS
142:
143:
144: extern
145: NDIS_STATUS
146: IbmtokSend(
147: IN NDIS_HANDLE MacBindingHandle,
148: IN PNDIS_PACKET Packet
149: )
150:
151: /*++
152:
153: Routine Description:
154:
155: The IbmtokSend request instructs a MAC to transmit a packet through
156: the adapter onto the medium.
157:
158: Arguments:
159:
160: MacBindingHandle - The context value returned by the MAC when the
161: adapter was opened. In reality, it is a pointer to IBMTOK_OPEN.
162:
163: Packet - A pointer to a descriptor for the packet that is to be
164: transmitted.
165:
166: Return Value:
167:
168: The function value is the status of the operation.
169:
170:
171: --*/
172:
173: {
174:
175: //
176: // Holds the status that should be returned to the caller.
177: //
178: NDIS_STATUS StatusToReturn = NDIS_STATUS_PENDING;
179:
180: //
181: // Pointer to the adapter.
182: //
183: PIBMTOK_ADAPTER Adapter;
184:
185: ULONG PacketLength;
186:
187: Adapter = PIBMTOK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
188:
189: NdisQueryPacket(
190: Packet,
191: NULL,
192: NULL,
193: NULL,
194: &PacketLength
195: );
196:
197: //
198: // Check that the packet will go on the wire. Note: I do not
199: // check that we have enough receive space to receive a packet
200: // of this size -- it is up to a protocol to work this out.
201: //
202:
203: if ((PacketLength < 14) ||
204: (PacketLength > Adapter->MaxTransmittablePacket)) {
205:
206: return(NDIS_STATUS_INVALID_PACKET);
207:
208: }
209:
210: NdisAcquireSpinLock(&Adapter->Lock);
211:
212: Adapter->References++;
213:
214: if (Adapter->Unplugged) {
215:
216: StatusToReturn = NDIS_STATUS_DEVICE_FAILED;
217:
218: } else if (!Adapter->NotAcceptingRequests) {
219:
220: PIBMTOK_OPEN Open;
221: PIBMTOK_RESERVED Reserved = PIBMTOK_RESERVED_FROM_PACKET(Packet);
222:
223: Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
224:
225: if (!Open->BindingShuttingDown) {
226:
227: //
228: // We do not have to increment the open count. Since we hold
229: // the lock for the entire function we cannot have the open
230: // removed out from under us.
231: //
232:
233: //
234: // NOTE NOTE NOTE !!!!!!
235: //
236: // There is an assumption in the code that no pointer
237: // (which are really handles) to an ndis packet will have
238: // its low bit set. (Always have even byte alignment.)
239: //
240:
241: ASSERT(!((UINT)Packet & 1));
242:
243: //
244: // ALL packets go on the wire (loopback is done
245: // by the card).
246: //
247: #ifdef CHECK_DUP_SENDS
248: IbmtokAddPacketToList(Adapter, Packet);
249: #endif
250:
251: Reserved->MacBindingHandle = MacBindingHandle;
252: Reserved->Packet = Packet;
253:
254: if (Adapter->FirstTransmit == NULL) {
255:
256: Adapter->FirstTransmit = Packet;
257:
258: } else {
259:
260: PIBMTOK_RESERVED_FROM_PACKET(Adapter->LastTransmit)->Next = Packet;
261:
262: }
263:
264: Adapter->LastTransmit = Packet;
265:
266: Reserved->Next = NULL;
267:
268: //
269: // Increment the reference on the open since it
270: // will be leaving this packet around on the transmit
271: // queues.
272: //
273:
274: Open->References++;
275:
276: //
277: // This will send the transmit SRB command
278: // if the SRB is available.
279: //
280:
281: IbmtokProcessSrbRequests(
282: Adapter
283: );
284:
285: } else {
286:
287: StatusToReturn = NDIS_STATUS_CLOSING;
288:
289: }
290:
291: } else {
292:
293: if (Adapter->ResetInProgress) {
294:
295: StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
296:
297: } else if (Adapter->AdapterNotOpen) {
298:
299: StatusToReturn = NDIS_STATUS_FAILURE;
300:
301: } else {
302:
303: NdisWriteErrorLogEntry(
304: Adapter->NdisAdapterHandle,
305: NDIS_ERROR_CODE_DRIVER_FAILURE,
306: 2,
307: IBMTOK_ERRMSG_INVALID_STATE,
308: 2
309: );
310:
311: }
312:
313: }
314:
315:
316: //
317: // This macro assumes it is called with the lock held,
318: // and releases it.
319: //
320:
321: IBMTOK_DO_DEFERRED(Adapter);
322: return StatusToReturn;
323: }
324:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.