6def0baf1139633ea161fd224164f9652d46f47a
[reactos.git] / reactos / drivers / net / ndis / ndis / miniport.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/miniport.c
5 * PURPOSE: Routines used by NDIS miniport drivers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/08-2000 Created
9 */
10 #include <miniport.h>
11
12
13 /* Number of medias we know */
14 #define MEDIA_ARRAY_SIZE 15
15
16 static NDIS_MEDIUM MediaArray[MEDIA_ARRAY_SIZE] = {
17 NdisMedium802_3,
18 NdisMedium802_5,
19 NdisMediumFddi,
20 NdisMediumWan,
21 NdisMediumLocalTalk,
22 NdisMediumDix,
23 NdisMediumArcnetRaw,
24 NdisMediumArcnet878_2,
25 NdisMediumAtm,
26 NdisMediumWirelessWan,
27 NdisMediumIrda,
28 NdisMediumBpc,
29 NdisMediumCoWan,
30 NdisMedium1394,
31 NdisMediumMax
32 };
33
34
35 LIST_ENTRY MiniportListHead;
36 KSPIN_LOCK MiniportListLock;
37 LIST_ENTRY AdapterListHead;
38 KSPIN_LOCK AdapterListLock;
39
40
41 VOID MiniportWorker(
42 PVOID Context)
43 /*
44 * FUNCTION: Worker function for MiniportXxx functions
45 * ARGUMENTS:
46 * Context = Pointer to context information (MINIPORT_DRIVER)
47 */
48 {
49 }
50
51
52 PLOGICAL_ADAPTER MiniLocateDevice(
53 PNDIS_STRING AdapterName)
54 /*
55 * FUNCTION: Returns the logical adapter object for a specific adapter
56 * ARGUMENTS:
57 * AdapterName = Pointer to name of adapter
58 * RETURNS:
59 * Pointer to logical adapter object, or NULL if none was found.
60 * If found, the adapter is referenced for the caller. The caller
61 * is responsible for dereferencing after use
62 */
63 {
64 KIRQL OldIrql1;
65 KIRQL OldIrql2;
66 PLIST_ENTRY CurrentMEntry;
67 PLIST_ENTRY CurrentAEntry;
68 PMINIPORT_DRIVER Miniport;
69 PLOGICAL_ADAPTER Adapter;
70
71 NDIS_DbgPrint(DEBUG_MINIPORT, ("Called. AdapterName (0x%X).\n", AdapterName));
72
73 KeAcquireSpinLock(&MiniportListLock, &OldIrql1);
74 CurrentMEntry = MiniportListHead.Flink;
75 while (CurrentMEntry != &MiniportListHead) {
76 Miniport = CONTAINING_RECORD(CurrentMEntry, MINIPORT_DRIVER, ListEntry);
77
78 KeAcquireSpinLock(&AdapterListLock, &OldIrql2);
79 CurrentAEntry = AdapterListHead.Flink;
80 while (CurrentAEntry != &AdapterListHead) {
81 Adapter = CONTAINING_RECORD(CurrentAEntry, LOGICAL_ADAPTER, ListEntry);
82
83 if (RtlCompareUnicodeString(AdapterName, &Adapter->DeviceName, TRUE) == 0) {
84 ReferenceObject(Adapter);
85 KeReleaseSpinLock(&AdapterListLock, OldIrql2);
86 KeReleaseSpinLock(&MiniportListLock, OldIrql1);
87 return Adapter;
88 }
89
90 CurrentAEntry = CurrentAEntry->Flink;
91 }
92 KeReleaseSpinLock(&AdapterListLock, OldIrql2);
93
94 CurrentMEntry = CurrentMEntry->Flink;
95 }
96 KeReleaseSpinLock(&MiniportListLock, OldIrql1);
97
98 return NULL;
99 }
100
101
102 NDIS_STATUS
103 MiniQueryInformation(
104 PLOGICAL_ADAPTER Adapter,
105 NDIS_OID Oid,
106 ULONG Size,
107 PULONG BytesWritten)
108 /*
109 * FUNCTION: Queries a logical adapter for properties
110 * ARGUMENTS:
111 * Adapter = Pointer to the logical adapter object to query
112 * Oid = Specifies the oid to query for
113 * Size = If non-zero overrides the length in the adapter object
114 * BytesWritten = Address of buffer to place number of bytes written
115 * RETURNS:
116 * Status of operation
117 * NOTES:
118 * If the specified buffer is too small, a new buffer is allocated,
119 * and the query is attempted again
120 */
121 {
122 NDIS_STATUS NdisStatus;
123 ULONG BytesNeeded;
124
125 if (Adapter->QueryBufferLength == 0) {
126 Adapter->QueryBuffer = ExAllocatePool(NonPagedPool, 32);
127
128 if (!Adapter->QueryBuffer) {
129 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
130 return NDIS_STATUS_RESOURCES;
131 }
132
133 Adapter->QueryBufferLength = 32;
134 }
135
136 BytesNeeded = (Size = 0)? Adapter->QueryBufferLength : Size;
137
138 NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)(
139 Adapter, Oid, &BytesNeeded,
140 Adapter->QueryBufferLength,
141 BytesWritten, &BytesNeeded);
142
143 if ((NT_SUCCESS(NdisStatus)) || (NdisStatus == NDIS_STATUS_PENDING)) {
144 NDIS_DbgPrint(DEBUG_MINIPORT, ("Miniport returned status (0x%X).\n", NdisStatus));
145 return NdisStatus;
146 }
147
148 if (NdisStatus == NDIS_STATUS_INVALID_LENGTH) {
149 ExFreePool(Adapter->QueryBuffer);
150
151 Adapter->QueryBufferLength += BytesNeeded;
152 Adapter->QueryBuffer = ExAllocatePool(
153 NonPagedPool, Adapter->QueryBufferLength);
154
155 if (!Adapter->QueryBuffer) {
156 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
157 return NDIS_STATUS_RESOURCES;
158 }
159
160 NdisStatus = (*Adapter->Miniport->Chars.QueryInformationHandler)(
161 Adapter, Oid, Adapter->QueryBuffer, Size, BytesWritten, &BytesNeeded);
162 }
163
164 return NdisStatus;
165 }
166
167
168 VOID
169 EXPORT
170 NdisMCloseLog(
171 IN NDIS_HANDLE LogHandle)
172 {
173 UNIMPLEMENTED
174 }
175
176
177 NDIS_STATUS
178 EXPORT
179 NdisMCreateLog(
180 IN NDIS_HANDLE MiniportAdapterHandle,
181 IN UINT Size,
182 OUT PNDIS_HANDLE LogHandle)
183 {
184 UNIMPLEMENTED
185
186 return NDIS_STATUS_FAILURE;
187 }
188
189
190 VOID
191 EXPORT
192 NdisMDeregisterAdapterShutdownHandler(
193 IN NDIS_HANDLE MiniportHandle)
194 {
195 UNIMPLEMENTED
196 }
197
198
199 VOID
200 EXPORT
201 NdisMFlushLog(
202 IN NDIS_HANDLE LogHandle)
203 {
204 UNIMPLEMENTED
205 }
206
207
208 VOID
209 EXPORT
210 NdisMIndicateStatus(
211 IN NDIS_HANDLE MiniportAdapterHandle,
212 IN NDIS_STATUS GeneralStatus,
213 IN PVOID StatusBuffer,
214 IN UINT StatusBufferSize)
215 {
216 UNIMPLEMENTED
217 }
218
219
220 VOID
221 EXPORT
222 NdisMIndicateStatusComplete(
223 IN NDIS_HANDLE MiniportAdapterHandle)
224 {
225 UNIMPLEMENTED
226 }
227
228
229 VOID
230 EXPORT
231 NdisInitializeWrapper(
232 OUT PNDIS_HANDLE NdisWrapperHandle,
233 IN PVOID SystemSpecific1,
234 IN PVOID SystemSpecific2,
235 IN PVOID SystemSpecific3)
236 /*
237 * FUNCTION: Notifies the NDIS library that a new miniport is initializing
238 * ARGUMENTS:
239 * NdisWrapperHandle = Address of buffer to place NDIS wrapper handle
240 * SystemSpecific1 = Pointer to the driver's driver object
241 * SystemSpecific2 = Pointer to the driver's registry path
242 * SystemSpecific3 = Always NULL
243 */
244 {
245 PMINIPORT_DRIVER Miniport;
246
247 Miniport = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_DRIVER));
248 if (!Miniport) {
249 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
250 *NdisWrapperHandle = NULL;
251 return;
252 }
253
254 RtlZeroMemory(Miniport, sizeof(MINIPORT_DRIVER));
255
256 KeInitializeSpinLock(&Miniport->Lock);
257
258 Miniport->RefCount = 1;
259
260 ExInitializeWorkItem(&Miniport->WorkItem, MiniportWorker, Miniport);
261
262 Miniport->DriverObject = (PDRIVER_OBJECT)SystemSpecific1;
263 /* FIXME: Copy RegistryPath */
264 //Miniport->RegistryPath = SystemSpecific2;
265
266 /* Put miniport in global miniport list */
267 ExInterlockedInsertTailList(&MiniportListHead,
268 &Miniport->ListEntry,
269 &MiniportListLock);
270
271 *NdisWrapperHandle = Miniport;
272 }
273
274
275 VOID
276 EXPORT
277 NdisMRegisterAdapterShutdownHandler(
278 IN NDIS_HANDLE MiniportHandle,
279 IN PVOID ShutdownContext,
280 IN ADAPTER_SHUTDOWN_HANDLER ShutdownHandler)
281 {
282 UNIMPLEMENTED
283 }
284
285
286 NDIS_STATUS
287 EXPORT
288 NdisMRegisterMiniport(
289 IN NDIS_HANDLE NdisWrapperHandle,
290 IN PNDIS_MINIPORT_CHARACTERISTICS MiniportCharacteristics,
291 IN UINT CharacteristicsLength)
292 /*
293 * FUNCTION: Registers a miniport's MiniportXxx entry points with the NDIS library
294 * ARGUMENTS:
295 * NdisWrapperHandle = Pointer to handle returned by NdisMInitializeWrapper
296 * MiniportCharacteristics = Pointer to a buffer with miniport characteristics
297 * CharacteristicsLength = Number of bytes in characteristics buffer
298 * RETURNS:
299 * Status of operation
300 */
301 {
302 UINT MinSize;
303 NTSTATUS Status;
304 NDIS_STATUS NdisStatus;
305 UINT SelectedMediumIndex;
306 PLOGICAL_ADAPTER Adapter;
307 PMINIPORT_DRIVER Miniport = GET_MINIPORT_DRIVER(NdisWrapperHandle);
308
309 switch (MiniportCharacteristics->MajorNdisVersion) {
310 case 0x03:
311 MinSize = sizeof(NDIS30_MINIPORT_CHARACTERISTICS_S);
312 break;
313
314 case 0x04:
315 MinSize = sizeof(NDIS40_MINIPORT_CHARACTERISTICS_S);
316 break;
317
318 case 0x05:
319 MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS_S);
320 break;
321
322 default:
323 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics version.\n"));
324 return NDIS_STATUS_BAD_VERSION;
325 }
326
327 if (CharacteristicsLength < MinSize) {
328 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
329 return NDIS_STATUS_BAD_CHARACTERISTICS;
330 }
331
332 /* Check if mandatory MiniportXxx functions are specified */
333 if ((!MiniportCharacteristics->HaltHandler) ||
334 (!MiniportCharacteristics->InitializeHandler)||
335 (!MiniportCharacteristics->QueryInformationHandler) ||
336 (!MiniportCharacteristics->ResetHandler) ||
337 (!MiniportCharacteristics->SetInformationHandler)) {
338 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
339 return NDIS_STATUS_BAD_CHARACTERISTICS;
340 }
341
342 if (MiniportCharacteristics->MajorNdisVersion == 0x03) {
343 if (!MiniportCharacteristics->u1.SendHandler) {
344 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
345 return NDIS_STATUS_BAD_CHARACTERISTICS;
346 }
347 } else if (MiniportCharacteristics->MajorNdisVersion >= 0x04) {
348 /* NDIS 4.0+ */
349 if ((!MiniportCharacteristics->u1.SendHandler) &&
350 (!MiniportCharacteristics->SendPacketsHandler)) {
351 NDIS_DbgPrint(DEBUG_MINIPORT, ("Bad miniport characteristics.\n"));
352 return NDIS_STATUS_BAD_CHARACTERISTICS;
353 }
354 }
355
356 RtlCopyMemory(&Miniport->Chars, MiniportCharacteristics, MinSize);
357
358 Adapter = ExAllocatePool(NonPagedPool, sizeof(LOGICAL_ADAPTER));
359 if (!Adapter) {
360 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
361 return NDIS_STATUS_RESOURCES;
362 }
363
364 RtlZeroMemory(Adapter, sizeof(LOGICAL_ADAPTER));
365 KeInitializeSpinLock(&Adapter->Lock);
366 Adapter->RefCount = 1;
367 Adapter->Miniport = Miniport;
368
369 /* Create the device object for this adapter */
370 /* FIXME: Use GUIDs */
371 RtlInitUnicodeString(&Adapter->DeviceName, L"\\Device\\ne2000");
372 Status = IoCreateDevice(Miniport->DriverObject, 0, &Adapter->DeviceName,
373 FILE_DEVICE_PHYSICAL_NETCARD, 0, FALSE, &Adapter->DeviceObject);
374 if (!NT_SUCCESS(Status)) {
375 NDIS_DbgPrint(MIN_TRACE, ("Could not create device object.\n"));
376 ExFreePool(Adapter);
377 return NDIS_STATUS_FAILURE;
378 }
379
380 /* Put adapter in adapter list for this miniport */
381 ExInterlockedInsertTailList(&Miniport->AdapterListHead,
382 &Adapter->MiniportListEntry,
383 &Miniport->Lock);
384
385 /* Put adapter in global adapter list */
386 ExInterlockedInsertTailList(&AdapterListHead,
387 &Adapter->ListEntry,
388 &AdapterListLock);
389
390 /* Call MiniportInitialize */
391 (*Miniport->Chars.InitializeHandler)(
392 &NdisStatus,
393 &SelectedMediumIndex,
394 &MediaArray[0],
395 MEDIA_ARRAY_SIZE,
396 Adapter,
397 NULL /* FIXME: WrapperConfigurationContext */);
398
399 return NDIS_STATUS_SUCCESS;
400 }
401
402
403 VOID
404 EXPORT
405 NdisMResetComplete(
406 IN NDIS_HANDLE MiniportAdapterHandle,
407 IN NDIS_STATUS Status,
408 IN BOOLEAN AddressingReset)
409 {
410 UNIMPLEMENTED
411 }
412
413
414 VOID
415 EXPORT
416 NdisMSendComplete(
417 IN NDIS_HANDLE MiniportAdapterHandle,
418 IN PNDIS_PACKET Packet,
419 IN NDIS_STATUS Status)
420 {
421 UNIMPLEMENTED
422 }
423
424
425 VOID
426 EXPORT
427 NdisMSendResourcesAvailable(
428 IN NDIS_HANDLE MiniportAdapterHandle)
429 {
430 UNIMPLEMENTED
431 }
432
433
434 VOID
435 EXPORT
436 NdisMSetAttributes(
437 IN NDIS_HANDLE MiniportAdapterHandle,
438 IN NDIS_HANDLE MiniportAdapterContext,
439 IN BOOLEAN BusMaster,
440 IN NDIS_INTERFACE_TYPE AdapterType)
441 /*
442 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
443 * ARGUMENTS:
444 * MiniportAdapterHandle = Handle input to MiniportInitialize
445 * MiniportAdapterContext = Pointer to context information
446 * BusMaster = Specifies TRUE if the caller's NIC is a busmaster DMA device
447 * AdapterType = Specifies the I/O bus interface of the caller's NIC
448 */
449 {
450 PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(MiniportAdapterHandle);
451
452 Adapter->MiniportAdapterContext = MiniportAdapterHandle;
453 Adapter->Attributes = BusMaster? NDIS_ATTRIBUTE_BUS_MASTER : 0;
454 Adapter->AdapterType = AdapterType;
455 Adapter->AttributesSet = TRUE;
456 }
457
458
459 VOID
460 EXPORT
461 NdisMSetAttributesEx(
462 IN NDIS_HANDLE MiniportAdapterHandle,
463 IN NDIS_HANDLE MiniportAdapterContext,
464 IN UINT CheckForHangTimeInSeconds OPTIONAL,
465 IN ULONG AttributeFlags,
466 IN NDIS_INTERFACE_TYPE AdapterType)
467 /*
468 * FUNCTION: Informs the NDIS library of significant features of the caller's NIC
469 * ARGUMENTS:
470 * MiniportAdapterHandle = Handle input to MiniportInitialize
471 * MiniportAdapterContext = Pointer to context information
472 * CheckForHangTimeInSeconds = Specifies interval in seconds at which
473 * MiniportCheckForHang should be called
474 * AttributeFlags = Bitmask that indicates specific attributes
475 * AdapterType = Specifies the I/O bus interface of the caller's NIC
476 */
477 {
478 UNIMPLEMENTED
479 }
480
481
482 VOID
483 EXPORT
484 NdisMSleep(
485 IN ULONG MicrosecondsToSleep)
486 {
487 UNIMPLEMENTED
488 }
489
490
491 BOOLEAN
492 EXPORT
493 NdisMSynchronizeWithInterrupt(
494 IN PNDIS_MINIPORT_INTERRUPT Interrupt,
495 IN PVOID SynchronizeFunction,
496 IN PVOID SynchronizeContext)
497 {
498 UNIMPLEMENTED
499
500 return FALSE;
501 }
502
503
504 NDIS_STATUS
505 EXPORT
506 NdisMWriteLogData(
507 IN NDIS_HANDLE LogHandle,
508 IN PVOID LogBuffer,
509 IN UINT LogBufferSize)
510 {
511 UNIMPLEMENTED
512
513 return NDIS_STATUS_FAILURE;
514 }
515
516
517 VOID
518 EXPORT
519 NdisTerminateWrapper(
520 IN NDIS_HANDLE NdisWrapperHandle,
521 IN PVOID SystemSpecific)
522 /*
523 * FUNCTION: Releases resources allocated by a call to NdisMInitializeWrapper
524 * ARGUMENTS:
525 * NdisWrapperHandle = Handle returned by NdisMInitializeWrapper
526 * SystemSpecific = Always NULL
527 */
528 {
529 ExFreePool(NdisWrapperHandle);
530 }
531
532 /* EOF */