|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1990-1992 Microsoft Corporation
4:
5: Module Name:
6:
7: sonic.c
8:
9: Abstract:
10:
11: This is the main file for the National Semiconductor SONIC
12: Ethernet controller. This driver conforms to the NDIS 3.0 interface.
13:
14: The overall structure and much of the code is taken from
15: the Lance NDIS driver by Tony Ercolano.
16:
17: Author:
18:
19: Anthony V. Ercolano (Tonye) 20-Jul-1990
20: Adam Barr (adamba) 14-Nov-1990
21:
22: Environment:
23:
24: Kernel Mode - Or whatever is the equivalent.
25:
26: Revision History:
27:
28:
29: --*/
30:
31: #include <ndis.h>
32:
33:
34: #include <efilter.h>
35: #include <sonichrd.h>
36: #include <sonicsft.h>
37:
38:
39:
40: //
41: // This variable is used to control debug output.
42: //
43:
44: #if DBG
45: INT SonicDbg = 0;
46: #endif
47:
48:
49: STATIC
50: VOID
51: SonicShutdown(
52: IN PVOID ShutdownContext
53: );
54:
55: STATIC
56: NDIS_STATUS
57: SonicOpenAdapter(
58: OUT PNDIS_STATUS OpenErrorStatus,
59: OUT NDIS_HANDLE *MacBindingHandle,
60: OUT PUINT SelectedMediumIndex,
61: IN PNDIS_MEDIUM MediumArray,
62: IN UINT MediumArraySize,
63: IN NDIS_HANDLE NdisBindingContext,
64: IN NDIS_HANDLE MacAdapterContext,
65: IN UINT OpenOptions,
66: IN PSTRING AddressingInformation OPTIONAL
67: );
68:
69: STATIC
70: NDIS_STATUS
71: SonicCloseAdapter(
72: IN NDIS_HANDLE MacBindingHandle
73: );
74:
75:
76: STATIC
77: VOID
78: SonicUnload(
79: IN NDIS_HANDLE MacMacContext
80: );
81:
82: STATIC
83: NDIS_STATUS
84: SonicAddAdapter(
85: IN NDIS_HANDLE MacMacContext,
86: IN NDIS_HANDLE ConfigurationHandle,
87: IN PNDIS_STRING AdapterName
88: );
89:
90: STATIC
91: VOID
92: SonicRemoveAdapter(
93: IN NDIS_HANDLE MacAdapterContext
94: );
95:
96: STATIC
97: NDIS_STATUS
98: SonicReset(
99: IN NDIS_HANDLE MacBindingHandle
100: );
101:
102: #if 0
103: STATIC
104: UINT
105: CalculateCRC(
106: IN UINT NumberOfBytes,
107: IN PCHAR Input
108: );
109: #endif
110:
111: STATIC
112: BOOLEAN
113: SonicSynchClearIsr(
114: IN PVOID Context
115: );
116:
117: STATIC
118: VOID
119: SonicStopChip(
120: IN PSONIC_ADAPTER Adapter
121: );
122:
123: STATIC
124: BOOLEAN
125: SetupRegistersAndInit(
126: IN PSONIC_ADAPTER Adapter
127: );
128:
129: STATIC
130: BOOLEAN
131: SonicInitialInit(
132: IN PSONIC_ADAPTER Adapter
133: );
134:
135: #ifdef NDIS_NT
136:
137: NTSTATUS
138: DriverEntry(
139: IN PDRIVER_OBJECT DriverObject,
140: IN PUNICODE_STRING RegistryPath
141: );
142:
143: #else
144:
145: NDIS_STATUS
146: DriverEntry(
147: VOID
148: );
149:
150: #endif
151:
152: STATIC
153: NDIS_STATUS
154: SonicRegisterAdapter(
155: IN NDIS_HANDLE NdisMacHandle,
156: IN NDIS_HANDLE ConfigurationHandle,
157: IN PNDIS_STRING DeviceName,
158: IN PUCHAR NetworkAddress,
159: IN UCHAR AdapterType,
160: IN UINT SlotNumber,
161: IN UINT Controller,
162: IN UINT MultifunctionAdapter,
163: IN UINT SonicInterruptVector,
164: IN UINT SonicInterruptLevel,
165: IN NDIS_INTERRUPT_MODE SonicInterruptMode,
166: IN UINT MaximumOpenAdapters
167: );
168:
169: typedef enum {
170: SonicHardwareOk,
171: SonicHardwareChecksum,
172: SonicHardwareConfig
173: } SONIC_HARDWARE_STATUS;
174:
175: STATIC
176: SONIC_HARDWARE_STATUS
177: SonicHardwareGetDetails(
178: IN PSONIC_ADAPTER Adapter,
179: IN UINT SlotNumber,
180: IN UINT Controller,
181: IN UINT MultifunctionAdapter,
182: OUT PULONG InitialPort,
183: OUT PULONG NumberOfPorts,
184: IN OUT PUINT InterruptVector,
185: IN OUT PUINT InterruptLevel,
186: OUT ULONG ErrorLogData[3]
187: );
188:
189: STATIC
190: BOOLEAN
191: SonicHardwareGetAddress(
192: IN PSONIC_ADAPTER Adapter,
193: OUT ULONG ErrorLogData[3]
194: );
195:
196: #ifdef SONIC_INTERNAL
197:
198: //
199: // These routines are support reading the address for the
200: // sonic internal implementation on the R4000 motherboards.
201: //
202:
203: STATIC
204: NTSTATUS
205: SonicHardwareSaveInformation(
206: IN PWSTR ValueName,
207: IN ULONG ValueType,
208: IN PVOID ValueData,
209: IN ULONG ValueLength,
210: IN PVOID Context,
211: IN PVOID EntryContext
212: );
213:
214: STATIC
215: BOOLEAN
216: SonicHardwareVerifyChecksum(
217: IN PSONIC_ADAPTER Adapter,
218: IN PUCHAR EthernetAddress,
219: OUT ULONG ErrorLogData[3]
220: );
221:
222: #endif
223:
224:
225: //
226: // Use the alloc_text pragma to specify the driver initialization routines
227: // (they can be paged out).
228: //
229:
230: #ifdef ALLOC_PRAGMA
231: #pragma alloc_text(init,DriverEntry)
232: #pragma alloc_text(init,SonicRegisterAdapter)
233: #pragma alloc_text(init,SonicInitialInit)
234: #pragma alloc_text(init,SonicAddAdapter)
235: #pragma alloc_text(init,SonicHardwareGetDetails)
236: #pragma alloc_text(init,SonicHardwareGetAddress)
237: #ifdef SONIC_INTERNAL
238: #pragma alloc_text(init,SonicHardwareSaveInformation)
239: #pragma alloc_text(init,SonicHardwareVerifyChecksum)
240: #endif
241: #endif
242:
243:
244:
245: NTSTATUS
246: DriverEntry(
247: IN PDRIVER_OBJECT DriverObject,
248: IN PUNICODE_STRING RegistryPath
249: )
250:
251: /*++
252:
253: Routine Description:
254:
255: This is the primary initialization routine for the sonic driver.
256: It is simply responsible for the intializing the wrapper and registering
257: the MAC. It then calls a system and architecture specific routine that
258: will initialize and register each adapter.
259:
260: Arguments:
261:
262: DriverObject - Pointer to driver object created by the system.
263:
264: Return Value:
265:
266: The status of the operation.
267:
268: --*/
269:
270: {
271:
272: //
273: // Receives the status of the NdisRegisterMac operation.
274: //
275: NDIS_STATUS Status;
276:
277: PSONIC_MAC SonicMac;
278:
279: NDIS_HANDLE SonicWrapperHandle;
280:
281: static const NDIS_STRING MacName = NDIS_STRING_CONST("SONIC");
282: NDIS_MAC_CHARACTERISTICS SonicChar;
283:
284:
285: //
286: // Initialize the wrapper.
287: //
288:
289: NdisInitializeWrapper(
290: &SonicWrapperHandle,
291: DriverObject,
292: RegistryPath,
293: NULL
294: );
295:
296: //
297: // Now allocate memory for our global structure.
298: //
299:
300: SONIC_ALLOC_MEMORY(&Status, &SonicMac, sizeof(SONIC_MAC));
301:
302: if (Status != NDIS_STATUS_SUCCESS) {
303:
304: return NDIS_STATUS_RESOURCES;
305:
306: }
307:
308: SonicMac->WrapperHandle = SonicWrapperHandle;
309:
310: //
311: // Initialize the MAC characteristics for the call to
312: // NdisRegisterMac.
313: //
314:
315: SonicChar.MajorNdisVersion = SONIC_NDIS_MAJOR_VERSION;
316: SonicChar.MinorNdisVersion = SONIC_NDIS_MINOR_VERSION;
317: SonicChar.OpenAdapterHandler = SonicOpenAdapter;
318: SonicChar.CloseAdapterHandler = SonicCloseAdapter;
319: SonicChar.SendHandler = SonicSend;
320: SonicChar.TransferDataHandler = SonicTransferData;
321: SonicChar.ResetHandler = SonicReset;
322: SonicChar.RequestHandler = SonicRequest;
323: SonicChar.QueryGlobalStatisticsHandler = SonicQueryGlobalStatistics;
324: SonicChar.UnloadMacHandler = SonicUnload;
325: SonicChar.AddAdapterHandler = SonicAddAdapter;
326: SonicChar.RemoveAdapterHandler = SonicRemoveAdapter;
327: SonicChar.Name = MacName;
328:
329:
330: NdisRegisterMac(
331: &Status,
332: &SonicMac->MacHandle,
333: SonicWrapperHandle,
334: (NDIS_HANDLE)SonicMac, // MacMacContext
335: &SonicChar,
336: sizeof(SonicChar)
337: );
338:
339: if (Status == NDIS_STATUS_SUCCESS) {
340:
341: return NDIS_STATUS_SUCCESS;
342:
343: }
344:
345:
346: //
347: // We can only get here if something went wrong with registering
348: // the mac or *all* of the adapters.
349: //
350:
351: NdisTerminateWrapper(SonicWrapperHandle, NULL);
352:
353: return NDIS_STATUS_FAILURE;
354:
355: }
356:
357: #if DBG
358: //
359: // Save this to retrieve it in the debugger.
360: //
361:
362: PVOID SonicAdapterAddress;
363: #endif
364:
365:
366: STATIC
367: NDIS_STATUS
368: SonicRegisterAdapter(
369: IN NDIS_HANDLE NdisMacHandle,
370: IN NDIS_HANDLE ConfigurationHandle,
371: IN PNDIS_STRING DeviceName,
372: IN PUCHAR NetworkAddress,
373: IN UCHAR AdapterType,
374: IN UINT SlotNumber,
375: IN UINT Controller,
376: IN UINT MultifunctionAdapter,
377: IN UINT SonicInterruptVector,
378: IN UINT SonicInterruptLevel,
379: IN NDIS_INTERRUPT_MODE SonicInterruptMode,
380: IN UINT MaximumOpenAdapters
381: )
382:
383: /*++
384:
385: Routine Description:
386:
387: This routine (and its interface) are not portable. They are
388: defined by the OS, the architecture, and the particular SONIC
389: implementation.
390:
391: This routine is responsible for the allocation of the datastructures
392: for the driver as well as any hardware specific details necessary
393: to talk with the device.
394:
395: Arguments:
396:
397: NdisMacHandle - The handle given back to the mac from ndis when
398: the mac registered itself.
399:
400: ConfigurationHandle - Config handle passed to MacAddAdapter.
401:
402: DeviceName - The string containing the name to give to the
403: device adapter.
404:
405: NetworkAddress - The network address, or NULL if the default
406: should be used.
407:
408: AdapterType - The type of the adapter; currently SONIC_ADAPTER_TYPE_EISA
409: and SONIC_ADAPTER_TYPE_INTERNAL are supported,
410:
411: SlotNumber - The slot number for the EISA card.
412:
413: Controller - The controller number for INTERNAL chips.
414:
415: MultifunctionAdapter - The INTERNAL bus number for INTERNAL chips.
416:
417: SonicInterruptVector - The interrupt vector to use for the adapter.
418:
419: SonicInterruptLevel - The interrupt request level to use for this
420: adapter.
421:
422: SonicInterruptMode - The interrupt mode to be use for this adapter.
423:
424: MaximumOpenAdapters - The maximum number of opens at any one time.
425:
426: Return Value:
427:
428: Returns a failure status if anything occurred that prevents the
429: initialization of the adapter.
430:
431: --*/
432:
433: {
434:
435: //
436: // Pointer for the adapter root.
437: //
438: PSONIC_ADAPTER Adapter;
439:
440: //
441: // Status of various NDIS calls.
442: //
443: NDIS_STATUS Status;
444:
445: //
446: // Holds information needed when registering the adapter.
447: //
448: NDIS_ADAPTER_INFORMATION AdapterInformation;
449:
450: //
451: // Number of ports needed
452: //
453: ULONG InitialPort;
454: ULONG NumberOfPorts;
455:
456: //
457: // Returned from SonicHardwareGetDetails; if it failed,
458: // we log an error and exit.
459: //
460: SONIC_HARDWARE_STATUS HardwareDetailsStatus;
461:
462: //
463: // Used to store error log data from SonicHardwareGetDetails.
464: //
465: ULONG ErrorLogData[3];
466:
467: //
468: // We put in this assertion to make sure that ushort are 2 bytes.
469: // if they aren't then the initialization block definition needs
470: // to be changed.
471: //
472: // Also all of the logic that deals with status registers assumes
473: // that control registers are only 2 bytes.
474: //
475:
476: ASSERT(sizeof(USHORT) == 2);
477:
478: //
479: // The Sonic uses four bytes four physical addresses, so we
480: // must ensure that this is the case (SONIC_PHYSICAL_ADDRESS)
481: // is defined as a ULONG).
482: //
483:
484: ASSERT(sizeof(SONIC_PHYSICAL_ADDRESS) == 4);
485:
486: //
487: // Allocate the Adapter block.
488: //
489:
490: SONIC_ALLOC_MEMORY(&Status, &Adapter, sizeof(SONIC_ADAPTER));
491:
492: if (Status == NDIS_STATUS_SUCCESS) {
493: #if DBG
494: SonicAdapterAddress = Adapter;
495: #endif
496:
497: SONIC_ZERO_MEMORY(
498: Adapter,
499: sizeof(SONIC_ADAPTER)
500: );
501:
502:
503: Adapter->AdapterType = AdapterType;
504: if (SonicInterruptMode == NdisInterruptLatched) {
505: Adapter->InterruptLatched = TRUE;
506: }
507: Adapter->PermanentAddressValid = FALSE;
508:
509: //
510: // Set up the AdapterInformation structure; zero it out
511: // first using sizeof (in case any fields are added).
512: //
513:
514: SONIC_ZERO_MEMORY (&AdapterInformation, sizeof(NDIS_ADAPTER_INFORMATION));
515: AdapterInformation.DmaChannel = 0;
516: AdapterInformation.Master = TRUE;
517: AdapterInformation.PhysicalMapRegistersNeeded =
518: SONIC_MAX_FRAGMENTS * SONIC_NUMBER_OF_TRANSMIT_DESCRIPTORS;
519: AdapterInformation.MaximumPhysicalMapping =
520: SONIC_LARGE_BUFFER_SIZE;
521:
522: //
523: // This returns the I/O ports used by the Sonic and may
524: // modify SonicInterruptVector and SonicInterruptLevel,
525: // as well as modiying some fields in Adapter.
526: //
527:
528: if ((HardwareDetailsStatus =
529: SonicHardwareGetDetails(
530: Adapter,
531: SlotNumber,
532: Controller,
533: MultifunctionAdapter,
534: &InitialPort,
535: &NumberOfPorts,
536: &SonicInterruptVector,
537: &SonicInterruptLevel,
538: ErrorLogData)) != SonicHardwareOk) {
539:
540: //
541: // If it fails, we call NdisRegisterAdapter anyway
542: // (so we can log an error using the NdisAdapterHandle),
543: // then return failure.
544: //
545:
546: AdapterInformation.NumberOfPortDescriptors = 0;
547:
548: } else {
549:
550: AdapterInformation.NumberOfPortDescriptors = 1;
551: AdapterInformation.PortDescriptors[0].InitialPort = InitialPort;
552: AdapterInformation.PortDescriptors[0].NumberOfPorts = NumberOfPorts;
553: AdapterInformation.PortDescriptors[0].PortOffset = (PVOID *)(&(Adapter->SonicPortAddress));
554:
555: }
556:
557: if (AdapterType == SONIC_ADAPTER_TYPE_EISA) {
558: AdapterInformation.AdapterType = NdisInterfaceEisa;
559: } else {
560: AdapterInformation.AdapterType = NdisInterfaceInternal;
561: }
562:
563: //
564: // Register the adapter with NDIS.
565: //
566:
567: if ((Status = NdisRegisterAdapter(
568: &Adapter->NdisAdapterHandle,
569: NdisMacHandle,
570: Adapter,
571: ConfigurationHandle,
572: DeviceName,
573: &AdapterInformation
574: )) == NDIS_STATUS_SUCCESS) {
575:
576: if (HardwareDetailsStatus != SonicHardwareOk) {
577:
578: //
579: // Log an error and exit.
580: //
581:
582: if (HardwareDetailsStatus == SonicHardwareChecksum) {
583:
584: NdisWriteErrorLogEntry(
585: Adapter->NdisAdapterHandle,
586: NDIS_ERROR_CODE_NETWORK_ADDRESS,
587: 6,
588: hardwareDetails,
589: SONIC_ERRMSG_HARDWARE_ADDRESS,
590: NDIS_STATUS_FAILURE,
591: ErrorLogData[0],
592: ErrorLogData[1],
593: ErrorLogData[2]
594: );
595:
596: } else {
597:
598: NdisWriteErrorLogEntry(
599: Adapter->NdisAdapterHandle,
600: NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
601: 0
602: );
603:
604: }
605:
606: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
607: SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
608: return NDIS_STATUS_FAILURE;
609:
610: }
611:
612:
613: //
614: // Allocate memory for all of the adapter structures.
615: //
616:
617: Adapter->NumberOfTransmitDescriptors =
618: SONIC_NUMBER_OF_TRANSMIT_DESCRIPTORS;
619: Adapter->NumberOfReceiveBuffers =
620: SONIC_NUMBER_OF_RECEIVE_BUFFERS;
621: Adapter->NumberOfReceiveDescriptors =
622: SONIC_NUMBER_OF_RECEIVE_DESCRIPTORS;
623:
624:
625: if (AllocateAdapterMemory(Adapter)) {
626:
627: //
628: // Get the network address. This writes
629: // an error log entry if it fails. This routine
630: // may do nothing on some systems, if
631: // SonicHardwareGetDetails has already determined
632: // the network address.
633: //
634:
635: if (!SonicHardwareGetAddress(Adapter, ErrorLogData)) {
636:
637: NdisWriteErrorLogEntry(
638: Adapter->NdisAdapterHandle,
639: NDIS_ERROR_CODE_NETWORK_ADDRESS,
640: 6,
641: hardwareDetails,
642: SONIC_ERRMSG_HARDWARE_ADDRESS,
643: NDIS_STATUS_FAILURE,
644: ErrorLogData[0],
645: ErrorLogData[1],
646: ErrorLogData[2]
647: );
648:
649: DeleteAdapterMemory(Adapter);
650: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
651: SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
652: return NDIS_STATUS_FAILURE;
653:
654: }
655:
656: //
657: // Initialize the current hardware address.
658: //
659:
660: SONIC_MOVE_MEMORY(
661: Adapter->CurrentNetworkAddress,
662: (NetworkAddress != NULL) ?
663: NetworkAddress :
664: Adapter->PermanentNetworkAddress,
665: ETH_LENGTH_OF_ADDRESS);
666:
667:
668: InitializeListHead(&Adapter->OpenBindings);
669: Adapter->OpenCount = 0;
670: Adapter->Removed = FALSE;
671: InitializeListHead(&Adapter->CloseList);
672: NdisAllocateSpinLock(&Adapter->Lock);
673:
674:
675: Adapter->LastTransmitDescriptor =
676: Adapter->TransmitDescriptorArea +
677: (Adapter->NumberOfTransmitDescriptors-1);
678: Adapter->NumberOfAvailableDescriptors =
679: Adapter->NumberOfTransmitDescriptors;
680: Adapter->AllocateableDescriptor =
681: Adapter->TransmitDescriptorArea;
682: Adapter->TransmittingDescriptor =
683: Adapter->TransmitDescriptorArea;
684: Adapter->FirstUncommittedDescriptor =
685: Adapter->TransmitDescriptorArea;
686: Adapter->PacketsSinceLastInterrupt = 0;
687:
688: Adapter->CurrentReceiveBufferIndex = 0;
689: Adapter->CurrentReceiveDescriptorIndex = 0;
690: Adapter->LastReceiveDescriptor =
691: &Adapter->ReceiveDescriptorArea[
692: Adapter->NumberOfReceiveDescriptors-1];
693:
694: Adapter->InterruptMaskRegister = SONIC_INT_DEFAULT_VALUE;
695: Adapter->ReceiveDescriptorsExhausted = FALSE;
696: Adapter->ReceiveBuffersExhausted = FALSE;
697: Adapter->ReceiveControlRegister = SONIC_RCR_DEFAULT_VALUE;
698:
699: Adapter->ProcessingReceiveInterrupt = FALSE;
700: Adapter->ProcessingGeneralInterrupt = FALSE;
701: Adapter->ProcessingDeferredOperations = FALSE;
702: Adapter->FirstLoopBack = NULL;
703: Adapter->LastLoopBack = NULL;
704: Adapter->FirstFinishTransmit = NULL;
705: Adapter->LastFinishTransmit = NULL;
706: Adapter->SendStageOpen = TRUE;
707: Adapter->AlreadyProcessingSendStage = FALSE;
708: Adapter->FirstSendStagePacket = NULL;
709: Adapter->LastSendStagePacket = NULL;
710:
711: Adapter->References = 1;
712:
713: Adapter->ResetInProgress = FALSE;
714: Adapter->IndicatingResetStart = FALSE;
715: Adapter->IndicatingResetEnd = FALSE;
716: Adapter->ResettingOpen = NULL;
717: Adapter->FirstInitialization = TRUE;
718:
719: SONIC_ZERO_MEMORY (&Adapter->GeneralMandatory, GM_ARRAY_SIZE * sizeof(ULONG));
720: SONIC_ZERO_MEMORY (&Adapter->GeneralOptionalByteCount, GO_COUNT_ARRAY_SIZE * sizeof(SONIC_LARGE_INTEGER));
721: SONIC_ZERO_MEMORY (&Adapter->GeneralOptionalFrameCount, GO_COUNT_ARRAY_SIZE * sizeof(ULONG));
722: SONIC_ZERO_MEMORY (&Adapter->GeneralOptional, (GO_ARRAY_SIZE - GO_ARRAY_START) * sizeof(ULONG));
723: SONIC_ZERO_MEMORY (&Adapter->MediaMandatory, MM_ARRAY_SIZE * sizeof(ULONG));
724: SONIC_ZERO_MEMORY (&Adapter->MediaOptional, MO_ARRAY_SIZE * sizeof(ULONG));
725:
726: //
727: // Initialize the CAM and associated things.
728: // At the beginning nothing is enabled since
729: // our filter is 0, although we do store
730: // our network address in the first slot.
731: //
732:
733: Adapter->MulticastCamEnableBits = 0x0000;
734: Adapter->CurrentPacketFilter = 0;
735: Adapter->CamDescriptorArea->CamEnable = 0x0000;
736: Adapter->CamDescriptorsUsed = 0x0001;
737: Adapter->CamDescriptorAreaSize = 1;
738:
739: NdisInitializeTimer(
740: &Adapter->DeferredTimer,
741: SonicTimerProcess,
742: (PVOID)Adapter);
743:
744: SONIC_LOAD_CAM_FRAGMENT(
745: &Adapter->CamDescriptorArea->CamFragments[0],
746: 0,
747: Adapter->CurrentNetworkAddress
748: );
749:
750:
751: if (!EthCreateFilter(
752: SONIC_CAM_ENTRIES-1, // maximum MC addresses
753: SonicChangeAddresses,
754: SonicChangeClass,
755: SonicCloseAction,
756: Adapter->CurrentNetworkAddress,
757: &Adapter->Lock,
758: &Adapter->FilterDB
759: )) {
760:
761: NdisWriteErrorLogEntry(
762: Adapter->NdisAdapterHandle,
763: NDIS_ERROR_CODE_OUT_OF_RESOURCES,
764: 2,
765: registerAdapter,
766: SONIC_ERRMSG_CREATE_FILTER
767: );
768:
769: DeleteAdapterMemory(Adapter);
770: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
771: NdisFreeSpinLock(&Adapter->Lock);
772: SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
773: return NDIS_STATUS_RESOURCES;
774:
775: } else {
776:
777: //
778: // Initialize the interrupt.
779: //
780:
781: NdisInitializeInterrupt(
782: &Status,
783: &Adapter->Interrupt,
784: Adapter->NdisAdapterHandle,
785: SonicInterruptService,
786: Adapter,
787: SonicDeferredProcessing,
788: SonicInterruptVector,
789: SonicInterruptLevel,
790: TRUE,
791: SonicInterruptMode
792: );
793:
794:
795: if (Status != NDIS_STATUS_SUCCESS) {
796:
797: NdisWriteErrorLogEntry(
798: Adapter->NdisAdapterHandle,
799: NDIS_ERROR_CODE_INTERRUPT_CONNECT,
800: 2,
801: registerAdapter,
802: SONIC_ERRMSG_INIT_INTERRUPT
803: );
804:
805: EthDeleteFilter(Adapter->FilterDB);
806: DeleteAdapterMemory(Adapter);
807: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
808: NdisFreeSpinLock(&Adapter->Lock);
809: SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
810: return Status;
811:
812: }
813:
814: //
815: // Start the card up. This writes an error
816: // log entry if it fails.
817: //
818:
819: if (!SonicInitialInit(Adapter)) {
820:
821: NdisRemoveInterrupt(&Adapter->Interrupt);
822: EthDeleteFilter(Adapter->FilterDB);
823: DeleteAdapterMemory(Adapter);
824: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
825: NdisFreeSpinLock(&Adapter->Lock);
826: SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
827: return NDIS_STATUS_FAILURE;
828:
829: } else {
830:
831: //
832: // Initialize the wake up timer to catch interrupts that
833: // don't complete. It fires continuously
834: // every 5 seconds, and we check if there are any
835: // uncompleted operations from the previous 5 second
836: // period.
837: //
838:
839: Adapter->WakeUpDpc = (PVOID)SonicWakeUpDpc;
840:
841: NdisInitializeTimer(&Adapter->WakeUpTimer,
842: (PVOID)(Adapter->WakeUpDpc),
843: Adapter );
844:
845: NdisSetTimer(
846: &Adapter->WakeUpTimer,
847: 5000
848: );
849:
850: NdisRegisterAdapterShutdownHandler(
851: Adapter->NdisAdapterHandle,
852: (PVOID)Adapter,
853: SonicShutdown
854: );
855:
856: return NDIS_STATUS_SUCCESS;
857:
858: }
859:
860: }
861:
862:
863: } else {
864:
865: //
866: // Call to AllocateAdapterMemory failed.
867: //
868:
869: NdisWriteErrorLogEntry(
870: Adapter->NdisAdapterHandle,
871: NDIS_ERROR_CODE_OUT_OF_RESOURCES,
872: 2,
873: registerAdapter,
874: SONIC_ERRMSG_ALLOC_MEMORY
875: );
876:
877: DeleteAdapterMemory(Adapter);
878: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
879: SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
880: return NDIS_STATUS_RESOURCES;
881:
882: }
883:
884: } else {
885:
886: //
887: // Call to NdisRegisterAdapter failed.
888: //
889:
890: SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
891: return Status;
892:
893: }
894:
895: } else {
896:
897: //
898: // Couldn't allocate adapter object.
899: //
900:
901: return Status;
902:
903: }
904:
905: }
906:
907: extern
908: BOOLEAN
909: SonicInitialInit(
910: IN PSONIC_ADAPTER Adapter
911: )
912:
913: /*++
914:
915: Routine Description:
916:
917: This routine sets up the initial init of the driver.
918:
919: Arguments:
920:
921: Adapter - The adapter for the hardware.
922:
923: Return Value:
924:
925: None.
926:
927: --*/
928:
929: {
930:
931: UINT Time = 50;
932:
933: //
934: // First we make sure that the device is stopped.
935: //
936:
937: SonicStopChip(Adapter);
938:
939: //
940: // Set up the registers.
941: //
942:
943: if (!SetupRegistersAndInit(Adapter)) {
944:
945: NdisWriteErrorLogEntry(
946: Adapter->NdisAdapterHandle,
947: NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
948: 3,
949: registerAdapter,
950: SONIC_ERRMSG_INITIAL_INIT
951: );
952:
953: return FALSE;
954:
955: }
956:
957:
958: //
959: // Delay execution for 1/2 second to give the sonic
960: // time to initialize.
961: //
962:
963: while (Time > 0) {
964:
965: if (!Adapter->FirstInitialization) {
966: break;
967: }
968:
969: NdisStallExecution(10000);
970: Time--;
971:
972: }
973:
974:
975: //
976: // The only way that first initialization could have
977: // been turned off is if we actually initialized.
978: //
979:
980: if (!Adapter->FirstInitialization) {
981:
982: //
983: // We actually did get the initialization.
984: //
985: // We can start the chip. We may not
986: // have any bindings to indicate to but this
987: // is unimportant.
988: //
989:
990: SonicStartChip(Adapter);
991:
992: return TRUE;
993:
994:
995: } else {
996:
997: NdisWriteErrorLogEntry(
998: Adapter->NdisAdapterHandle,
999: NDIS_ERROR_CODE_TIMEOUT,
1000: 2,
1001: registerAdapter,
1002: SONIC_ERRMSG_INITIAL_INIT
1003: );
1004:
1005: return FALSE;
1006:
1007: }
1008:
1009: }
1010:
1011: STATIC
1012: BOOLEAN
1013: SonicSynchClearIsr(
1014: IN PVOID Context
1015: )
1016:
1017: /*++
1018:
1019: Routine Description:
1020:
1021: This routine is used during a reset. It ensures that no
1022: interrupts will come through, and that any DPRs that run
1023: will find no interrupts to process.
1024:
1025: Arguments:
1026:
1027: Context - A pointer to a SONIC_ADAPTER structure.
1028:
1029: Return Value:
1030:
1031: Always returns true.
1032:
1033: --*/
1034:
1035: {
1036:
1037: PSONIC_ADAPTER Adapter = (PSONIC_ADAPTER)Context;
1038:
1039: SONIC_WRITE_PORT(Adapter, SONIC_INTERRUPT_STATUS, 0xffff);
1040: Adapter->IsrValue = 0;
1041:
1042: return TRUE;
1043:
1044: }
1045:
1046: extern
1047: VOID
1048: SonicStartChip(
1049: IN PSONIC_ADAPTER Adapter
1050: )
1051:
1052: /*++
1053:
1054: Routine Description:
1055:
1056: This routine is used to start an already initialized sonic.
1057:
1058: Arguments:
1059:
1060: Adapter - The adapter for the SONIC to start.
1061:
1062: Return Value:
1063:
1064: None.
1065:
1066: --*/
1067:
1068: {
1069:
1070: //
1071: // Take us out of reset mode if we are in it.
1072: //
1073:
1074: SONIC_WRITE_PORT(Adapter, SONIC_COMMAND,
1075: 0x0000
1076: );
1077:
1078: SONIC_WRITE_PORT(Adapter, SONIC_COMMAND,
1079: SONIC_CR_RECEIVER_ENABLE
1080: );
1081:
1082: }
1083:
1084: STATIC
1085: VOID
1086: SonicStopChip(
1087: IN PSONIC_ADAPTER Adapter
1088: )
1089:
1090: /*++
1091:
1092: Routine Description:
1093:
1094: This routine is used to stop a sonic.
1095:
1096: This routine is *not* portable. It is specific to the 386
1097: implementation of the sonic. On the bus master card the ACON bit
1098: must be set in csr3, whereas on the decstation, csr3 remains clear.
1099:
1100: Arguments:
1101:
1102: Adapter - The adapter for the SONIC to stop.
1103:
1104: Return Value:
1105:
1106: None.
1107:
1108: --*/
1109:
1110: {
1111:
1112: SONIC_WRITE_PORT(Adapter, SONIC_COMMAND,
1113: SONIC_CR_RECEIVER_DISABLE |
1114: SONIC_CR_SOFTWARE_RESET
1115: );
1116:
1117: }
1118:
1119: extern
1120: VOID
1121: SonicStartCamReload(
1122: IN PSONIC_ADAPTER Adapter
1123: )
1124:
1125: /*++
1126:
1127: Routine Description:
1128:
1129: This routine starts a CAM reload, which will cause an
1130: interrupt when it is done.
1131:
1132: Arguments:
1133:
1134: Adapter - The adapter for the SONIC to reload.
1135:
1136: Return Value:
1137:
1138: None.
1139:
1140: --*/
1141:
1142: {
1143:
1144: //
1145: // Move CAM Enable into the appropriate spot.
1146: //
1147:
1148: SONIC_LOAD_CAM_ENABLE(
1149: &Adapter->CamDescriptorArea->CamFragments[
1150: Adapter->CamDescriptorAreaSize],
1151: Adapter->CamDescriptorArea->CamEnable
1152: );
1153:
1154:
1155: //
1156: // Flush the CAM before we start the reload.
1157: //
1158:
1159: SONIC_FLUSH_WRITE_BUFFER(Adapter->CamDescriptorAreaFlushBuffer);
1160:
1161:
1162: SONIC_WRITE_PORT(Adapter, SONIC_CAM_DESCRIPTOR,
1163: SONIC_GET_LOW_PART_ADDRESS(Adapter->CamDescriptorAreaPhysical)
1164: );
1165:
1166: SONIC_WRITE_PORT(Adapter, SONIC_CAM_DESCRIPTOR_COUNT,
1167: (USHORT)Adapter->CamDescriptorAreaSize
1168: );
1169:
1170:
1171: //
1172: // Start the Load CAM, which will cause an interrupt
1173: // when it is done.
1174: //
1175:
1176: SONIC_WRITE_PORT(Adapter, SONIC_COMMAND,
1177: SONIC_CR_LOAD_CAM
1178: );
1179:
1180: }
1181:
1182: STATIC
1183: NDIS_STATUS
1184: SonicOpenAdapter(
1185: OUT PNDIS_STATUS OpenErrorStatus,
1186: OUT NDIS_HANDLE *MacBindingHandle,
1187: OUT PUINT SelectedMediumIndex,
1188: IN PNDIS_MEDIUM MediumArray,
1189: IN UINT MediumArraySize,
1190: IN NDIS_HANDLE NdisBindingContext,
1191: IN NDIS_HANDLE MacAdapterContext,
1192: IN UINT OpenOptions,
1193: IN PSTRING AddressingInformation OPTIONAL
1194: )
1195:
1196: /*++
1197:
1198: Routine Description:
1199:
1200: This routine is used to create an open instance of an adapter, in effect
1201: creating a binding between an upper-level module and the MAC module over
1202: the adapter.
1203:
1204: Arguments:
1205:
1206: OpenErrorStatus - Returns more information in some cases.
1207:
1208: MacBindingHandle - A pointer to a location in which the MAC stores
1209: a context value that it uses to represent this binding.
1210:
1211: SelectedMediumIndex - A pointer to a location in which the MAC stores
1212: the medium selected out of MediumArray.
1213:
1214: MediumArray - An array of media that the protocol can support.
1215:
1216: MediumArraySize - The number of elements in MediumArray.
1217:
1218: NdisBindingContext - A value to be recorded by the MAC and passed as
1219: context whenever an indication is delivered by the MAC for this binding.
1220:
1221: MacAdapterContext - The value associated with the adapter that is being
1222: opened when the MAC registered the adapter with NdisRegisterAdapter.
1223:
1224: OpenOptions - A bit mask containing flags with information about this
1225: binding.
1226:
1227: AddressingInformation - An optional pointer to a variable length string
1228: containing hardware-specific information that can be used to program the
1229: device. (This is not used by this MAC.)
1230:
1231: Return Value:
1232:
1233: The function value is the status of the operation. If the MAC does not
1234: complete this request synchronously, the value would be
1235: NDIS_STATUS_PENDING.
1236:
1237:
1238: --*/
1239:
1240: {
1241:
1242: //
1243: // The SONIC_ADAPTER that this open binding should belong too.
1244: //
1245: PSONIC_ADAPTER Adapter;
1246:
1247: //
1248: // Holds the status that should be returned to the caller.
1249: //
1250: NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
1251:
1252: //
1253: // Simple iteration variable, for scanning the medium array.
1254: //
1255: UINT i;
1256:
1257: //
1258: // Pointer to the space allocated for the binding.
1259: //
1260: PSONIC_OPEN NewOpen;
1261:
1262: //
1263: // Points to the MacReserved section of NewOpen->OpenCloseRequest.
1264: //
1265: PSONIC_REQUEST_RESERVED Reserved;
1266:
1267:
1268: //
1269: // If we are being removed, don't allow new opens.
1270: //
1271:
1272: Adapter = PSONIC_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
1273:
1274: if (Adapter->Removed) {
1275: return NDIS_STATUS_FAILURE;
1276: }
1277:
1278:
1279: //
1280: // Search for the 802.3 media type
1281: //
1282:
1283: for (i=0; i<MediumArraySize; i++) {
1284:
1285: if (MediumArray[i] == NdisMedium802_3) {
1286: break;
1287: }
1288:
1289: }
1290:
1291: if (i == MediumArraySize) {
1292:
1293: return NDIS_STATUS_UNSUPPORTED_MEDIA;
1294:
1295: }
1296:
1297: *SelectedMediumIndex = i;
1298:
1299:
1300: NdisAcquireSpinLock(&Adapter->Lock);
1301: Adapter->References++;
1302:
1303: NdisReleaseSpinLock(&Adapter->Lock);
1304:
1305: //
1306: // Allocate the space for the open binding. Fill in the fields.
1307: //
1308:
1309: SONIC_ALLOC_MEMORY(&StatusToReturn, &NewOpen, sizeof(SONIC_OPEN));
1310:
1311: if (StatusToReturn == NDIS_STATUS_SUCCESS) {
1312:
1313: *MacBindingHandle = BINDING_HANDLE_FROM_PSONIC_OPEN(NewOpen);
1314: InitializeListHead(&NewOpen->OpenList);
1315: NewOpen->NdisBindingContext = NdisBindingContext;
1316: NewOpen->References = 1;
1317: NewOpen->BindingShuttingDown = FALSE;
1318: NewOpen->OwningSonic = Adapter;
1319:
1320: NewOpen->OpenCloseRequest.RequestType = NdisRequestOpen;
1321: Reserved = PSONIC_RESERVED_FROM_REQUEST(&NewOpen->OpenCloseRequest);
1322: Reserved->OpenBlock = NewOpen;
1323: Reserved->Next = (PNDIS_REQUEST)NULL;
1324:
1325: NdisAcquireSpinLock(&Adapter->Lock);
1326:
1327: SonicQueueRequest(Adapter, &NewOpen->OpenCloseRequest);
1328:
1329: StatusToReturn = NDIS_STATUS_PENDING;
1330:
1331: } else {
1332:
1333: NdisWriteErrorLogEntry(
1334: Adapter->NdisAdapterHandle,
1335: NDIS_ERROR_CODE_OUT_OF_RESOURCES,
1336: 2,
1337: openAdapter,
1338: SONIC_ERRMSG_ALLOC_OPEN
1339: );
1340:
1341:
1342: NdisAcquireSpinLock(&Adapter->Lock);
1343:
1344: }
1345:
1346:
1347: //
1348: // This macro assumes it is called with the lock held,
1349: // and releases it.
1350: //
1351:
1352: SONIC_DO_DEFERRED(Adapter);
1353: return StatusToReturn;
1354: }
1355:
1356: STATIC
1357: NDIS_STATUS
1358: SonicCloseAdapter(
1359: IN NDIS_HANDLE MacBindingHandle
1360: )
1361:
1362: /*++
1363:
1364: Routine Description:
1365:
1366: This routine causes the MAC to close an open handle (binding).
1367:
1368: Arguments:
1369:
1370: MacBindingHandle - The context value returned by the MAC when the
1371: adapter was opened. In reality it is a PSONIC_OPEN.
1372:
1373: Return Value:
1374:
1375: The function value is the status of the operation.
1376:
1377:
1378: --*/
1379:
1380: {
1381:
1382: //
1383: // The SONIC_ADAPTER that this open binding should belong too.
1384: //
1385: PSONIC_ADAPTER Adapter;
1386:
1387: //
1388: // Holds the status that should be returned to the caller.
1389: //
1390: NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
1391:
1392: //
1393: // Pointer to the space allocated for the binding.
1394: //
1395: PSONIC_OPEN Open;
1396:
1397:
1398: Adapter = PSONIC_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
1399:
1400: //
1401: // Hold the lock while we update the reference counts for the
1402: // adapter and the open.
1403: //
1404:
1405: NdisAcquireSpinLock(&Adapter->Lock);
1406: Adapter->References++;
1407:
1408: Open = PSONIC_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
1409:
1410: //
1411: // Don't do anything if this binding is already closing.
1412: //
1413:
1414: if (!Open->BindingShuttingDown) {
1415:
1416: PSONIC_REQUEST_RESERVED Reserved = PSONIC_RESERVED_FROM_REQUEST(&Open->OpenCloseRequest);
1417:
1418: Open->OpenCloseRequest.RequestType = NdisRequestClose;
1419: Reserved->OpenBlock = Open;
1420: Reserved->Next = (PNDIS_REQUEST)NULL;
1421:
1422: ++Open->References;
1423:
1424: SonicQueueRequest(Adapter, &Open->OpenCloseRequest);
1425:
1426: //
1427: // Remove the creation reference.
1428: //
1429:
1430: --Open->References;
1431:
1432: StatusToReturn = NDIS_STATUS_PENDING;
1433:
1434: } else {
1435:
1436: StatusToReturn = NDIS_STATUS_CLOSING;
1437:
1438: }
1439:
1440: //
1441: // This macro assumes it is called with the lock held,
1442: // and releases it.
1443: //
1444:
1445: SONIC_DO_DEFERRED(Adapter);
1446: return StatusToReturn;
1447:
1448: }
1449:
1450: STATIC
1451: VOID
1452: SonicUnload(
1453: IN NDIS_HANDLE MacMacContext
1454: )
1455:
1456: /*++
1457:
1458: Routine Description:
1459:
1460: SonicUnload is called when the MAC is to unload itself.
1461:
1462: Arguments:
1463:
1464: None.
1465:
1466: Return Value:
1467:
1468: None.
1469:
1470: --*/
1471:
1472: {
1473:
1474: NDIS_STATUS Status;
1475:
1476: PSONIC_MAC SonicMac = (PSONIC_MAC)MacMacContext;
1477:
1478:
1479: NdisDeregisterMac(
1480: &Status,
1481: SonicMac->MacHandle
1482: );
1483:
1484: NdisTerminateWrapper(
1485: SonicMac->WrapperHandle,
1486: NULL
1487: );
1488:
1489: return;
1490:
1491: }
1492:
1493:
1494: STATIC
1495: NDIS_STATUS
1496: SonicAddAdapter(
1497: IN NDIS_HANDLE MacMacContext,
1498: IN NDIS_HANDLE ConfigurationHandle,
1499: IN PNDIS_STRING AdapterName
1500: )
1501:
1502: /*++
1503:
1504: Routine Description:
1505:
1506: SonicAddAdapter adds an adapter to the list supported
1507: by this MAC.
1508:
1509: Arguments:
1510:
1511: MacMacContext - The context passed to NdisRegisterMac (will be NULL).
1512:
1513: ConfigurationHandle - A handle to pass to NdisOpenConfiguration.
1514:
1515: AdapterName - The name to register with via NdisRegisterAdapter.
1516:
1517: Return Value:
1518:
1519: NDIS_STATUS_SUCCESS
1520: NDIS_STATUS_PENDING
1521:
1522: --*/
1523:
1524: {
1525:
1526: NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
1527: PSONIC_MAC SonicMac = (PSONIC_MAC)MacMacContext;
1528: NDIS_HANDLE ConfigHandle;
1529: NDIS_STRING AdapterTypeString = NDIS_STRING_CONST("AdapterType");
1530: #ifdef SONIC_INTERNAL
1531: NDIS_STRING MultifunctionAdapterString = NDIS_STRING_CONST("MultifunctionAdapter");
1532: NDIS_STRING NetworkControllerString = NDIS_STRING_CONST("NetworkController");
1533: #endif
1534: PNDIS_CONFIGURATION_PARAMETER ReturnedValue;
1535: PUCHAR NetworkAddress;
1536: UINT NetworkAddressLength;
1537: UCHAR AdapterType;
1538: UINT InterruptVector;
1539: UINT InterruptLevel;
1540: NDIS_INTERRUPT_MODE InterruptMode;
1541: UINT SlotNumber;
1542: UINT Controller = 0;
1543: UINT MultifunctionAdapter = 0;
1544:
1545: //
1546: // Open the configuration info.
1547: //
1548:
1549: NdisOpenConfiguration(
1550: &Status,
1551: &ConfigHandle,
1552: ConfigurationHandle
1553: );
1554:
1555: if (Status != NDIS_STATUS_SUCCESS) {
1556: return Status;
1557: }
1558:
1559:
1560: //
1561: // Check that adapter type is supported.
1562: // The default depends on the processor type.
1563: //
1564:
1565: AdapterType = SONIC_ADAPTER_TYPE_DEFAULT;
1566:
1567: NdisReadConfiguration(
1568: &Status,
1569: &ReturnedValue,
1570: ConfigHandle,
1571: &AdapterTypeString,
1572: NdisParameterInteger
1573: );
1574:
1575: if (Status == NDIS_STATUS_SUCCESS) {
1576:
1577: //
1578: // See if the adapter type is valid. We skip to AdapterTypeRecognized
1579: // if the AdapterType is known to this driver.
1580: //
1581:
1582: #ifdef SONIC_EISA
1583: if (ReturnedValue->ParameterData.IntegerData == SONIC_ADAPTER_TYPE_EISA) {
1584: goto AdapterTypeRecognized;
1585: }
1586: #endif
1587:
1588: #ifdef SONIC_INTERNAL
1589: if (ReturnedValue->ParameterData.IntegerData == SONIC_ADAPTER_TYPE_INTERNAL) {
1590: goto AdapterTypeRecognized;
1591: }
1592: #endif
1593:
1594: //
1595: // Card type not supported by this driver
1596: //
1597:
1598: #if DBG
1599: DbgPrint("SONIC: Error in adapter type: %lx\n", ReturnedValue->ParameterData.IntegerData);
1600: #endif
1601: NdisCloseConfiguration(ConfigHandle);
1602: return NDIS_STATUS_FAILURE;
1603:
1604:
1605: AdapterTypeRecognized:
1606:
1607: AdapterType = (UCHAR)ReturnedValue->ParameterData.IntegerData;
1608: }
1609:
1610: switch (AdapterType) {
1611:
1612: #ifdef SONIC_EISA
1613:
1614: case SONIC_ADAPTER_TYPE_EISA:
1615: {
1616:
1617: NDIS_EISA_FUNCTION_INFORMATION EisaData;
1618: USHORT Portzc88;
1619: UCHAR zc88Value;
1620: UCHAR Mask;
1621: UCHAR InitType;
1622: UCHAR PortValue;
1623: USHORT PortAddress;
1624: PUCHAR CurrentChar;
1625: BOOLEAN LastEntry;
1626:
1627: NdisReadEisaSlotInformation(
1628: &Status,
1629: ConfigurationHandle,
1630: &SlotNumber,
1631: &EisaData
1632: );
1633:
1634: if (Status != NDIS_STATUS_SUCCESS) {
1635:
1636: #if DBG
1637: DbgPrint("SONIC: Could not read EISA data\n");
1638: #endif
1639: NdisCloseConfiguration(ConfigHandle);
1640: return NDIS_STATUS_FAILURE;
1641:
1642: }
1643:
1644: CurrentChar = EisaData.InitializationData;
1645:
1646: Portzc88 = (SlotNumber << 12) + 0xc88;
1647:
1648: LastEntry = FALSE;
1649: while (!LastEntry) {
1650: InitType = *(CurrentChar++);
1651: PortAddress = *((USHORT UNALIGNED *)CurrentChar);
1652: CurrentChar += sizeof(USHORT);
1653:
1654: if ((InitType & 0x80) == 0) {
1655: LastEntry = TRUE;
1656: }
1657:
1658: PortValue = *(CurrentChar++);
1659:
1660: if (InitType & 0x40) {
1661: Mask = *(CurrentChar++);
1662: } else {
1663: Mask = 0;
1664: }
1665:
1666: //
1667: // The only port we care about is zc88 (z is the
1668: // slot number) since it has the interrupt in it.
1669: //
1670:
1671: if (PortAddress != Portzc88) {
1672: continue;
1673: }
1674:
1675: zc88Value &= Mask;
1676: zc88Value |= PortValue;
1677:
1678: }
1679:
1680: switch ((zc88Value & 0x06) >> 1) {
1681: case 0:
1682: InterruptVector = 5; break;
1683: case 1:
1684: InterruptVector = 9; break;
1685: case 2:
1686: InterruptVector = 10; break;
1687: case 3:
1688: InterruptVector = 11; break;
1689: }
1690:
1691: InterruptLevel = InterruptVector;
1692:
1693: if ((zc88Value & 0x01) != 0) {
1694: InterruptMode = NdisInterruptLatched;
1695: } else {
1696: InterruptMode = NdisInterruptLevelSensitive;
1697: }
1698:
1699: break;
1700:
1701: }
1702:
1703: #endif // SONIC_EISA
1704:
1705: #ifdef SONIC_INTERNAL
1706:
1707: case SONIC_ADAPTER_TYPE_INTERNAL:
1708: {
1709:
1710: //
1711: // For the internal adapter, we read the MultifunctionAdapter number
1712: // and NetworkController number, which are both optional. For
1713: // passing to SonicRegisterAdapter.
1714: //
1715:
1716: NdisReadConfiguration(
1717: &Status,
1718: &ReturnedValue,
1719: ConfigHandle,
1720: &MultifunctionAdapterString,
1721: NdisParameterInteger
1722: );
1723:
1724: if (Status == NDIS_STATUS_SUCCESS) {
1725:
1726: MultifunctionAdapter = ReturnedValue->ParameterData.IntegerData;
1727:
1728: }
1729:
1730: NdisReadConfiguration(
1731: &Status,
1732: &ReturnedValue,
1733: ConfigHandle,
1734: &NetworkControllerString,
1735: NdisParameterInteger
1736: );
1737:
1738: if (Status == NDIS_STATUS_SUCCESS) {
1739:
1740: Controller = ReturnedValue->ParameterData.IntegerData;
1741:
1742: }
1743:
1744: //
1745: // These are filled in by SonicHardwareGetDetails.
1746: //
1747:
1748: InterruptVector = 0;
1749: InterruptLevel = 0;
1750:
1751: //
1752: // The internal adapter is level-sensitive.
1753: //
1754:
1755: InterruptMode = NdisInterruptLevelSensitive;
1756:
1757: break;
1758:
1759: }
1760:
1761: #endif // SONIC_INTERNAL
1762:
1763: default:
1764:
1765: ASSERT(FALSE);
1766: break;
1767:
1768: }
1769:
1770:
1771: //
1772: // Read network address
1773: //
1774:
1775: NdisReadNetworkAddress(
1776: &Status,
1777: (PVOID *)&NetworkAddress,
1778: &NetworkAddressLength,
1779: ConfigHandle);
1780:
1781:
1782: //
1783: // Make sure that the address is the right length asnd
1784: // at least one of the bytes is non-zero.
1785: //
1786:
1787: if ((Status == NDIS_STATUS_SUCCESS) &&
1788: (NetworkAddressLength == ETH_LENGTH_OF_ADDRESS) &&
1789: ((NetworkAddress[0] |
1790: NetworkAddress[1] |
1791: NetworkAddress[2] |
1792: NetworkAddress[3] |
1793: NetworkAddress[4] |
1794: NetworkAddress[5]) != 0)) {
1795:
1796: #if DBG
1797: if (SonicDbg) {
1798: DbgPrint("SONIC: New Address = %.2x-%.2x-%.2x-%.2x-%.2x-%.2x\n",
1799: NetworkAddress[0],
1800: NetworkAddress[1],
1801: NetworkAddress[2],
1802: NetworkAddress[3],
1803: NetworkAddress[4],
1804: NetworkAddress[5]);
1805: }
1806: #endif
1807:
1808: } else {
1809:
1810: //
1811: // Tells SonicRegisterAdapter to use the
1812: // burned-in address.
1813: //
1814:
1815: NetworkAddress = NULL;
1816:
1817: }
1818:
1819: //
1820: // Used passed-in adapter name to register.
1821: //
1822:
1823: Status = SonicRegisterAdapter(
1824: SonicMac->MacHandle,
1825: ConfigurationHandle,
1826: AdapterName,
1827: NetworkAddress,
1828: AdapterType,
1829: SlotNumber,
1830: Controller,
1831: MultifunctionAdapter,
1832: InterruptVector,
1833: InterruptLevel,
1834: InterruptMode,
1835: 32);
1836:
1837:
1838: NdisCloseConfiguration(ConfigHandle);
1839:
1840:
1841: return Status; // should be NDIS_STATUS_SUCCESS
1842:
1843: }
1844:
1845: STATIC
1846: VOID
1847: SonicRemoveAdapter(
1848: IN NDIS_HANDLE MacAdapterContext
1849: )
1850:
1851: /*++
1852:
1853: Routine Description:
1854:
1855: SonicRemoveAdapter removes an adapter previously registered
1856: with NdisRegisterAdapter.
1857:
1858: Arguments:
1859:
1860: MacAdapterContext - The context value that the MAC passed
1861: to NdisRegisterAdapter; actually as pointer to a
1862: SONIC_ADAPTER.
1863:
1864: Return Value:
1865:
1866: None.
1867:
1868: --*/
1869:
1870: {
1871: PSONIC_ADAPTER Adapter;
1872: BOOLEAN Canceled;
1873:
1874: Adapter = PSONIC_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
1875:
1876: Adapter->Removed = TRUE;
1877:
1878: //
1879: // Stop the chip.
1880: //
1881:
1882: SonicStopChip (Adapter);
1883:
1884: NdisDeregisterAdapterShutdownHandler(Adapter->NdisAdapterHandle);
1885:
1886: ASSERT (Adapter->OpenCount == 0);
1887:
1888: //
1889: // There are no opens left, so remove ourselves.
1890: //
1891:
1892: //
1893: // Stop the deadman timer
1894: //
1895:
1896: NdisCancelTimer(&Adapter->WakeUpTimer, &Canceled);
1897:
1898: if ( !Canceled ) {
1899: NdisStallExecution(500000);
1900: }
1901:
1902: NdisRemoveInterrupt(&Adapter->Interrupt);
1903:
1904: EthDeleteFilter(Adapter->FilterDB);
1905:
1906: DeleteAdapterMemory(Adapter);
1907: NdisDeregisterAdapter(Adapter->NdisAdapterHandle);
1908:
1909: NdisFreeSpinLock(&Adapter->Lock);
1910: SONIC_FREE_MEMORY(Adapter, sizeof(SONIC_ADAPTER));
1911:
1912: }
1913:
1914: STATIC
1915: NDIS_STATUS
1916: SonicReset(
1917: IN NDIS_HANDLE MacBindingHandle
1918: )
1919:
1920: /*++
1921:
1922: Routine Description:
1923:
1924: The SonicReset request instructs the MAC to issue a hardware reset
1925: to the network adapter. The MAC also resets its software state. See
1926: the description of NdisReset for a detailed description of this request.
1927:
1928: Arguments:
1929:
1930: MacBindingHandle - The context value returned by the MAC when the
1931: adapter was opened. In reality, it is a pointer to SONIC_OPEN.
1932:
1933: Return Value:
1934:
1935: The function value is the status of the operation.
1936:
1937:
1938: --*/
1939:
1940: {
1941:
1942: //
1943: // Holds the status that should be returned to the caller.
1944: //
1945: NDIS_STATUS StatusToReturn = NDIS_STATUS_PENDING;
1946:
1947: PSONIC_ADAPTER Adapter =
1948: PSONIC_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
1949:
1950: //
1951: // Hold the locks while we update the reference counts on the
1952: // adapter and the open.
1953: //
1954:
1955: if (Adapter->Removed) {
1956:
1957: return(NDIS_STATUS_FAILURE);
1958:
1959: }
1960:
1961: NdisAcquireSpinLock(&Adapter->Lock);
1962:
1963: Adapter->References++;
1964:
1965: if (!Adapter->ResetInProgress && !Adapter->IndicatingResetStart) {
1966:
1967: PSONIC_OPEN Open;
1968:
1969: Open = PSONIC_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
1970:
1971: if (!Open->BindingShuttingDown) {
1972:
1973: Adapter->IndicatingResetStart = TRUE;
1974:
1975: if (!Adapter->IndicatingResetEnd) {
1976:
1977: //
1978: // Loop through, indicating RESET_START; we
1979: // don't bother with the StatusComplete
1980: // indication until RESET_END is indicated.
1981: //
1982:
1983: PSONIC_OPEN Open;
1984: PLIST_ENTRY CurrentLink;
1985:
1986: CurrentLink = Adapter->OpenBindings.Flink;
1987:
1988: while (CurrentLink != &Adapter->OpenBindings) {
1989:
1990: Open = CONTAINING_RECORD(
1991: CurrentLink,
1992: SONIC_OPEN,
1993: OpenList
1994: );
1995:
1996: Open->References++;
1997: NdisReleaseSpinLock(&Adapter->Lock);
1998:
1999: NdisIndicateStatus(
2000: Open->NdisBindingContext,
2001: NDIS_STATUS_RESET_START,
2002: NULL,
2003: 0
2004: );
2005:
2006: NdisAcquireSpinLock(&Adapter->Lock);
2007: Open->References--;
2008:
2009: CurrentLink = CurrentLink->Flink;
2010:
2011: }
2012:
2013:
2014: Adapter->IndicatingResetStart = FALSE;
2015:
2016: SetupForReset(
2017: Adapter,
2018: PSONIC_OPEN_FROM_BINDING_HANDLE(MacBindingHandle)
2019: );
2020: }
2021:
2022: Open->References++;
2023: Adapter->ResettingOpen = Open;
2024:
2025: StatusToReturn = NDIS_STATUS_PENDING;
2026:
2027: } else {
2028:
2029: StatusToReturn = NDIS_STATUS_CLOSING;
2030:
2031: }
2032:
2033: } else {
2034:
2035: StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
2036:
2037: }
2038:
2039:
2040: //
2041: // This macro assumes it is called with the lock held,
2042: // and releases it.
2043: //
2044:
2045: SONIC_DO_DEFERRED(Adapter);
2046: return StatusToReturn;
2047:
2048: }
2049:
2050: #if 0
2051: STATIC
2052: UINT
2053: CalculateCRC(
2054: IN UINT NumberOfBytes,
2055: IN PCHAR Input
2056: )
2057:
2058: /*++
2059:
2060: Routine Description:
2061:
2062: Calculates a 32 bit crc value over the input number of bytes.
2063:
2064: NOTE: This routine assumes UINTs are 32 bits.
2065:
2066: Arguments:
2067:
2068: NumberOfBytes - The number of bytes in the input.
2069:
2070: Input - An input "string" to calculate a CRC over.
2071:
2072: Return Value:
2073:
2074: A 32 bit crc value.
2075:
2076:
2077: --*/
2078:
2079: {
2080:
2081: const UINT POLY = 0x04c11db6;
2082: UINT CRCValue = 0xffffffff;
2083:
2084: ASSERT(sizeof(UINT) == 4);
2085:
2086: for (
2087: ;
2088: NumberOfBytes;
2089: NumberOfBytes--
2090: ) {
2091:
2092: UINT CurrentBit;
2093: UCHAR CurrentByte = *Input;
2094: Input++;
2095:
2096: for (
2097: CurrentBit = 8;
2098: CurrentBit;
2099: CurrentBit--
2100: ) {
2101:
2102: UINT CurrentCRCHigh = CRCValue >> 31;
2103:
2104: CRCValue <<= 1;
2105:
2106: if (CurrentCRCHigh ^ (CurrentByte & 0x01)) {
2107:
2108: CRCValue ^= POLY;
2109: CRCValue |= 0x00000001;
2110:
2111: }
2112:
2113: CurrentByte >>= 1;
2114:
2115: }
2116:
2117: }
2118:
2119: return CRCValue;
2120:
2121: }
2122: #endif
2123:
2124: extern
2125: VOID
2126: StartAdapterReset(
2127: IN PSONIC_ADAPTER Adapter
2128: )
2129:
2130: /*++
2131:
2132: Routine Description:
2133:
2134: This is the first phase of resetting the adapter hardware.
2135:
2136: It makes the following assumptions:
2137:
2138: 1) That the hardware has been stopped.
2139:
2140: 2) That it can not be preempted.
2141:
2142: 3) That no other adapter activity can occur.
2143:
2144: When this routine is finished all of the adapter information
2145: will be as if the driver was just initialized.
2146:
2147: Arguments:
2148:
2149: Adapter - The adapter whose hardware is to be reset.
2150:
2151: Return Value:
2152:
2153: None.
2154:
2155: --*/
2156: {
2157:
2158: //
2159: // These are used for cleaning the rings.
2160: //
2161:
2162: PSONIC_RECEIVE_DESCRIPTOR CurrentReceiveDescriptor;
2163: PSONIC_TRANSMIT_DESCRIPTOR CurrentTransmitDescriptor;
2164: UINT i;
2165: SONIC_PHYSICAL_ADDRESS SonicPhysicalAdr;
2166:
2167:
2168: //
2169: // Shut down the chip. We won't be doing any more work until
2170: // the reset is complete.
2171: //
2172:
2173: SonicStopChip(Adapter);
2174:
2175: //
2176: // Once the chip is stopped we can't get any more interrupts.
2177: // Any interrupts that are "queued" for processing could
2178: // only possibly service this reset. It is therefore safe for
2179: // us to clear the adapter global csr value.
2180: //
2181: Adapter->IsrValue = 0;
2182:
2183:
2184: Adapter->LastTransmitDescriptor =
2185: Adapter->TransmitDescriptorArea +
2186: (Adapter->NumberOfTransmitDescriptors-1);
2187: Adapter->NumberOfAvailableDescriptors =
2188: Adapter->NumberOfTransmitDescriptors;
2189: Adapter->AllocateableDescriptor =
2190: Adapter->TransmitDescriptorArea;
2191: Adapter->TransmittingDescriptor =
2192: Adapter->TransmitDescriptorArea;
2193: Adapter->FirstUncommittedDescriptor =
2194: Adapter->TransmitDescriptorArea;
2195: Adapter->PacketsSinceLastInterrupt = 0;
2196:
2197: Adapter->CurrentReceiveBufferIndex = 0;
2198: Adapter->CurrentReceiveDescriptorIndex = 0;
2199: Adapter->LastReceiveDescriptor =
2200: &Adapter->ReceiveDescriptorArea[
2201: Adapter->NumberOfReceiveDescriptors-1];
2202:
2203: Adapter->InterruptMaskRegister = SONIC_INT_DEFAULT_VALUE;
2204: Adapter->ReceiveDescriptorsExhausted = FALSE;
2205: Adapter->ReceiveBuffersExhausted = FALSE;
2206: Adapter->ReceiveControlRegister = SONIC_RCR_DEFAULT_VALUE;
2207:
2208: Adapter->SendStageOpen = TRUE;
2209:
2210: Adapter->AlreadyProcessingSendStage = FALSE;
2211:
2212: //
2213: // Clean the receive descriptors and initialize the link
2214: // fields.
2215: //
2216:
2217: SONIC_ZERO_MEMORY(
2218: Adapter->ReceiveDescriptorArea,
2219: (sizeof(SONIC_RECEIVE_DESCRIPTOR)*Adapter->NumberOfReceiveDescriptors)
2220: );
2221:
2222: for (
2223: i = 0, CurrentReceiveDescriptor = Adapter->ReceiveDescriptorArea;
2224: i < Adapter->NumberOfReceiveDescriptors;
2225: i++,CurrentReceiveDescriptor++
2226: ) {
2227:
2228: CurrentReceiveDescriptor->InUse = SONIC_OWNED_BY_SONIC;
2229:
2230: SonicPhysicalAdr = NdisGetPhysicalAddressLow(Adapter->ReceiveDescriptorAreaPhysical) +
2231: (i * sizeof(SONIC_RECEIVE_DESCRIPTOR));
2232:
2233: if (i == 0) {
2234:
2235: Adapter->ReceiveDescriptorArea[
2236: Adapter->NumberOfReceiveDescriptors-1].Link =
2237: SonicPhysicalAdr | SONIC_END_OF_LIST;
2238:
2239: } else {
2240:
2241: Adapter->ReceiveDescriptorArea[i-1].Link = SonicPhysicalAdr;
2242:
2243: }
2244:
2245: }
2246:
2247:
2248: //
2249: // Clean the transmit descriptors and initialize the link
2250: // fields.
2251: //
2252:
2253: SONIC_ZERO_MEMORY(
2254: Adapter->TransmitDescriptorArea,
2255: (sizeof(SONIC_TRANSMIT_DESCRIPTOR)*Adapter->NumberOfTransmitDescriptors)
2256: );
2257:
2258: for (
2259: i = 0, CurrentTransmitDescriptor = Adapter->TransmitDescriptorArea;
2260: i < Adapter->NumberOfTransmitDescriptors;
2261: i++,CurrentTransmitDescriptor++
2262: ) {
2263:
2264: SonicPhysicalAdr = NdisGetPhysicalAddressLow(Adapter->TransmitDescriptorAreaPhysical) +
2265: (i * sizeof(SONIC_TRANSMIT_DESCRIPTOR));
2266:
2267: if (i == 0) {
2268:
2269: Adapter->TransmitDescriptorArea[Adapter->NumberOfTransmitDescriptors-1].Link = SonicPhysicalAdr;
2270:
2271: } else {
2272:
2273: (CurrentTransmitDescriptor-1)->Link = SonicPhysicalAdr;
2274:
2275: }
2276:
2277: }
2278:
2279:
2280: //
2281: // Recover all of the adapter buffers.
2282: //
2283:
2284: {
2285:
2286: UINT i;
2287:
2288: for (
2289: i = 0;
2290: i < (SONIC_NUMBER_OF_SMALL_BUFFERS +
2291: SONIC_NUMBER_OF_MEDIUM_BUFFERS +
2292: SONIC_NUMBER_OF_LARGE_BUFFERS);
2293: i++
2294: ) {
2295:
2296: Adapter->SonicBuffers[i].Next = i+1;
2297:
2298: }
2299:
2300: Adapter->SonicBufferListHeads[0] = -1;
2301: Adapter->SonicBufferListHeads[1] = 0;
2302: Adapter->SonicBuffers[SONIC_NUMBER_OF_SMALL_BUFFERS-1].Next = -1;
2303: Adapter->SonicBufferListHeads[2] = SONIC_NUMBER_OF_SMALL_BUFFERS;
2304: Adapter->SonicBuffers[(SONIC_NUMBER_OF_SMALL_BUFFERS+
2305: SONIC_NUMBER_OF_MEDIUM_BUFFERS)-1].Next = -1;
2306: Adapter->SonicBufferListHeads[3] = SONIC_NUMBER_OF_SMALL_BUFFERS +
2307: SONIC_NUMBER_OF_MEDIUM_BUFFERS;
2308: Adapter->SonicBuffers[(SONIC_NUMBER_OF_SMALL_BUFFERS+
2309: SONIC_NUMBER_OF_MEDIUM_BUFFERS+
2310: SONIC_NUMBER_OF_LARGE_BUFFERS)-1].Next = -1;
2311:
2312: }
2313:
2314: //
2315: // Go through the various transmit lists and abort every packet.
2316: //
2317:
2318: {
2319:
2320: UINT i;
2321: PNDIS_PACKET Packet;
2322: PSONIC_PACKET_RESERVED Reserved;
2323: PSONIC_OPEN Open;
2324: PNDIS_PACKET Next;
2325:
2326: for (
2327: i = 0;
2328: i < 3;
2329: i++
2330: ) {
2331:
2332: switch (i) {
2333:
2334: case 0:
2335: Next = Adapter->FirstLoopBack;
2336: break;
2337: case 1:
2338: Next = Adapter->FirstFinishTransmit;
2339: break;
2340: case 2:
2341: Next = Adapter->FirstSendStagePacket;
2342: break;
2343:
2344: }
2345:
2346:
2347: while (Next) {
2348:
2349: Packet = Next;
2350: Reserved = PSONIC_RESERVED_FROM_PACKET(Packet);
2351: Next = Reserved->Next;
2352: Open =
2353: PSONIC_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
2354:
2355: //
2356: // The completion of the packet is one less reason
2357: // to keep the open around.
2358: //
2359:
2360: ASSERT(Open->References);
2361:
2362: NdisCompleteSend(
2363: Open->NdisBindingContext,
2364: Packet,
2365: NDIS_STATUS_REQUEST_ABORTED
2366: );
2367:
2368: Open->References--;
2369:
2370: }
2371:
2372: }
2373:
2374: Adapter->FirstLoopBack = NULL;
2375: Adapter->LastLoopBack = NULL;
2376: Adapter->FirstFinishTransmit = NULL;
2377: Adapter->LastFinishTransmit = NULL;
2378: Adapter->FirstSendStagePacket = NULL;
2379: Adapter->LastSendStagePacket = NULL;
2380: Adapter->GeneralOptional[GO_TRANSMIT_QUEUE_LENGTH - GO_ARRAY_START] = 0;
2381:
2382: }
2383:
2384: (VOID)SetupRegistersAndInit(Adapter);
2385:
2386: }
2387:
2388: STATIC
2389: BOOLEAN
2390: SetupRegistersAndInit(
2391: IN PSONIC_ADAPTER Adapter
2392: )
2393:
2394: /*++
2395:
2396: Routine Description:
2397:
2398: It is this routines responsibility to make sure that the
2399: initialization block is filled and the chip is initialized
2400: *but not* started.
2401:
2402: NOTE: This routine assumes that it is called with the lock
2403: acquired OR that only a single thread of execution is working
2404: with this particular adapter.
2405:
2406: Arguments:
2407:
2408: Adapter - The adapter whose hardware is to be initialized.
2409:
2410: Return Value:
2411:
2412: TRUE if the registers are initialized successfully.
2413:
2414: --*/
2415: {
2416:
2417: USHORT CommandRegister;
2418: UINT Time;
2419:
2420:
2421: SONIC_WRITE_PORT(Adapter, SONIC_DATA_CONFIGURATION,
2422: Adapter->DataConfigurationRegister
2423: );
2424:
2425: SONIC_WRITE_PORT(Adapter, SONIC_RECEIVE_CONTROL,
2426: Adapter->ReceiveControlRegister
2427: );
2428:
2429: SONIC_WRITE_PORT(Adapter, SONIC_INTERRUPT_MASK,
2430: Adapter->InterruptMaskRegister
2431: );
2432:
2433: SONIC_WRITE_PORT(Adapter, SONIC_INTERRUPT_STATUS,
2434: (USHORT)0xffff
2435: );
2436:
2437:
2438:
2439: SONIC_WRITE_PORT(Adapter, SONIC_UPPER_TRANSMIT_DESCRIPTOR,
2440: SONIC_GET_HIGH_PART_ADDRESS(
2441: NdisGetPhysicalAddressLow(Adapter->TransmitDescriptorAreaPhysical))
2442: );
2443:
2444: SONIC_WRITE_PORT(Adapter, SONIC_CURR_TRANSMIT_DESCRIPTOR,
2445: SONIC_GET_LOW_PART_ADDRESS(
2446: NdisGetPhysicalAddressLow(Adapter->TransmitDescriptorAreaPhysical))
2447: );
2448:
2449:
2450: SONIC_WRITE_PORT(Adapter, SONIC_UPPER_RECEIVE_DESCRIPTOR,
2451: SONIC_GET_HIGH_PART_ADDRESS(
2452: NdisGetPhysicalAddressLow(Adapter->ReceiveDescriptorAreaPhysical))
2453: );
2454:
2455: SONIC_WRITE_PORT(Adapter, SONIC_CURR_RECEIVE_DESCRIPTOR,
2456: SONIC_GET_LOW_PART_ADDRESS(
2457: NdisGetPhysicalAddressLow(Adapter->ReceiveDescriptorAreaPhysical))
2458: );
2459:
2460:
2461: //
2462: // The EOBC value cannot be odd (since the card register
2463: // wants it in words); in addition it appears that the
2464: // value in the register must be even, so this number
2465: // has to be a multiple of 4.
2466: //
2467: ASSERT((SONIC_END_OF_BUFFER_COUNT & 0x3) == 0);
2468:
2469: switch (Adapter->AdapterType) {
2470:
2471: #ifdef SONIC_EISA
2472:
2473: case SONIC_ADAPTER_TYPE_EISA:
2474:
2475: //
2476: // For the EISA card, set EOBC to 2 words more than real
2477: // size.
2478: //
2479:
2480: SONIC_WRITE_PORT(Adapter, SONIC_END_OF_BUFFER_WORD_COUNT,
2481: (SONIC_END_OF_BUFFER_COUNT / 2) + 2
2482: );
2483: break;
2484:
2485: #endif // SONIC_EISA
2486:
2487: #ifdef SONIC_INTERNAL
2488:
2489: case SONIC_ADAPTER_TYPE_INTERNAL:
2490:
2491: SONIC_WRITE_PORT(Adapter, SONIC_END_OF_BUFFER_WORD_COUNT,
2492: SONIC_END_OF_BUFFER_COUNT / 2
2493: );
2494: break;
2495:
2496: #endif // SONIC_INTERNAL
2497:
2498: default:
2499:
2500: ASSERT(FALSE);
2501: break;
2502:
2503: }
2504:
2505:
2506: SONIC_WRITE_PORT(Adapter, SONIC_UPPER_RECEIVE_RESOURCE,
2507: SONIC_GET_HIGH_PART_ADDRESS(
2508: NdisGetPhysicalAddressLow(Adapter->ReceiveResourceAreaPhysical))
2509: );
2510:
2511: SONIC_WRITE_PORT(Adapter, SONIC_RESOURCE_START,
2512: SONIC_GET_LOW_PART_ADDRESS(
2513: NdisGetPhysicalAddressLow(Adapter->ReceiveResourceAreaPhysical))
2514: );
2515:
2516: SONIC_WRITE_PORT(Adapter, SONIC_RESOURCE_END,
2517: (USHORT)(SONIC_GET_LOW_PART_ADDRESS(
2518: NdisGetPhysicalAddressLow(Adapter->ReceiveResourceAreaPhysical)) +
2519: sizeof(SONIC_RECEIVE_RESOURCE) *
2520: Adapter->NumberOfReceiveBuffers)
2521: );
2522:
2523: SONIC_WRITE_PORT(Adapter, SONIC_RESOURCE_READ,
2524: SONIC_GET_LOW_PART_ADDRESS(
2525: NdisGetPhysicalAddressLow(Adapter->ReceiveResourceAreaPhysical))
2526: );
2527:
2528: SONIC_WRITE_PORT(Adapter, SONIC_RESOURCE_WRITE,
2529: SONIC_GET_LOW_PART_ADDRESS(
2530: NdisGetPhysicalAddressLow(Adapter->ReceiveResourceAreaPhysical))
2531: );
2532:
2533:
2534: //
2535: // Now take us out of reset mode...
2536: //
2537:
2538: SONIC_WRITE_PORT(Adapter, SONIC_COMMAND,
2539: 0x0000
2540: );
2541:
2542: //
2543: // ...and issue the Read RRA command.
2544: //
2545:
2546: SONIC_WRITE_PORT(Adapter, SONIC_COMMAND,
2547: SONIC_CR_READ_RRA
2548: );
2549:
2550:
2551:
2552: //
2553: // Wait for 1/5 second for Read RRA to finish.
2554: //
2555:
2556: Time = 20;
2557:
2558: while (Time > 0) {
2559:
2560: NdisStallExecution(10000);
2561:
2562: SONIC_READ_PORT(Adapter, SONIC_COMMAND, &CommandRegister);
2563: if ((CommandRegister & SONIC_CR_READ_RRA) == 0) {
2564: break;
2565: }
2566:
2567: Time--;
2568:
2569: }
2570:
2571: if (Time == 0) {
2572:
2573: #if DBG
2574: DbgPrint("SONIC: Could not read RRA\n");
2575: #endif
2576: return FALSE;
2577:
2578: }
2579:
2580:
2581: //
2582: // This will cause a LOAD_CAM interrupt when it is done.
2583: //
2584:
2585: SonicStartCamReload(Adapter);
2586:
2587: return TRUE;
2588:
2589: }
2590:
2591: extern
2592: VOID
2593: SetupForReset(
2594: IN PSONIC_ADAPTER Adapter,
2595: IN PSONIC_OPEN Open
2596: )
2597:
2598: /*++
2599:
2600: Routine Description:
2601:
2602: This routine is used to fill in the who and why a reset is
2603: being set up as well as setting the appropriate fields in the
2604: adapter.
2605:
2606: NOTE: This routine must be called with the lock acquired.
2607:
2608: Arguments:
2609:
2610: Adapter - The adapter whose hardware is to be initialized.
2611:
2612: Open - A pointer to an sonic open structure.
2613:
2614: Return Value:
2615:
2616: None.
2617:
2618: --*/
2619: {
2620:
2621: PNDIS_REQUEST CurrentRequest;
2622: PNDIS_REQUEST * CurrentNextLocation;
2623: PSONIC_OPEN TmpOpen;
2624:
2625: PSONIC_REQUEST_RESERVED Reserved;
2626:
2627: //
2628: // Shut down the chip. We won't be doing any more work until
2629: // the reset is complete. We take it out of reset mode, however.
2630: //
2631:
2632: SonicStopChip(Adapter);
2633:
2634:
2635: //
2636: // Once the chip is stopped we can't get any more interrupts.
2637: // This call ensures that any ISR which is just about to run
2638: // will find no bits in the ISR, and any DPR which fires will
2639: // find nothing queued to do.
2640: //
2641:
2642: NdisSynchronizeWithInterrupt(
2643: &Adapter->Interrupt,
2644: SonicSynchClearIsr,
2645: (PVOID)Adapter);
2646:
2647:
2648: Adapter->ResetInProgress = TRUE;
2649:
2650: //
2651: // Shut down all of the transmit queues so that the
2652: // transmit portion of the chip will eventually calm down.
2653: //
2654:
2655: Adapter->SendStageOpen = FALSE;
2656:
2657: //
2658: // If there is a close at the top of the queue, then
2659: // it may be in two states:
2660: //
2661: // 1- Has interrupted, and the InterruptDpc got the
2662: // interrupt out of Adapter->IsrValue before we zeroed it.
2663: //
2664: // 2- Has interrupted, but we zeroed Adapter->IsrValue
2665: // before it read it, OR has not yet interrupted.
2666: //
2667: // In case 1, the interrupt will be processed and the
2668: // close will complete without our intervention. In
2669: // case 2, the open will not complete. In that case
2670: // the CAM will have been updated for that open, so
2671: // all that remains is for us to dereference the open
2672: // as would have been done in the interrupt handler.
2673: //
2674: // Closes that are not at the top of the queue we
2675: // leave in place; when we restart the queue after
2676: // the reset, they will get processed.
2677: //
2678:
2679: CurrentRequest = Adapter->FirstRequest;
2680:
2681: if (CurrentRequest) {
2682:
2683: Reserved = PSONIC_RESERVED_FROM_REQUEST(CurrentRequest);
2684:
2685: //
2686: // If the first request is a close, take it off the
2687: // queue, and "complete" it.
2688: //
2689:
2690: if (CurrentRequest->RequestType == NdisRequestClose) {
2691: Adapter->FirstRequest = Reserved->Next;
2692: --(Reserved->OpenBlock)->References;
2693: CurrentRequest = Adapter->FirstRequest;
2694: }
2695:
2696: CurrentNextLocation = &(Adapter->FirstRequest);
2697:
2698: while (CurrentRequest) {
2699:
2700: Reserved = PSONIC_RESERVED_FROM_REQUEST(CurrentRequest);
2701:
2702: if ((CurrentRequest->RequestType == NdisRequestClose) ||
2703: (CurrentRequest->RequestType == NdisRequestOpen)) {
2704:
2705: //
2706: // Opens are inoffensive, we just leave them
2707: // on the list. Closes that were not at the
2708: // head of the list were not processing and
2709: // can be left on also.
2710: //
2711:
2712: CurrentNextLocation = &(Reserved->Next);
2713:
2714: } else {
2715:
2716: //
2717: // Not a close, remove it from the list and
2718: // fail it.
2719: //
2720:
2721: *CurrentNextLocation = Reserved->Next;
2722: TmpOpen = Reserved->OpenBlock;
2723:
2724: NdisReleaseSpinLock(&Adapter->Lock);
2725:
2726: NdisCompleteRequest(
2727: TmpOpen->NdisBindingContext,
2728: CurrentRequest,
2729: NDIS_STATUS_RESET_IN_PROGRESS
2730: );
2731:
2732: NdisAcquireSpinLock(&Adapter->Lock);
2733:
2734: --TmpOpen->References;
2735:
2736: }
2737:
2738: CurrentRequest = *CurrentNextLocation;
2739:
2740: }
2741:
2742: Adapter->RequestInProgress = FALSE;
2743:
2744: }
2745:
2746: }
2747:
2748: #ifdef SONIC_INTERNAL
2749:
2750: //
2751: // The next routines are to support reading the registry to
2752: // obtain information about the internal sonic on the
2753: // MIPS R4000 motherboards.
2754: //
2755:
2756: //
2757: // This structure is used as the Context in the callbacks
2758: // to SonicHardwareSaveInformation.
2759: //
2760:
2761: typedef struct _SONIC_HARDWARE_INFO {
2762:
2763: //
2764: // These are read out of the "Configuration Data"
2765: // data.
2766: //
2767:
2768: CCHAR InterruptVector;
2769: KIRQL InterruptLevel;
2770: USHORT DataConfigurationRegister;
2771: LARGE_INTEGER PortAddress;
2772: BOOLEAN DataValid;
2773: UCHAR EthernetAddress[8];
2774: BOOLEAN AddressValid;
2775:
2776: //
2777: // This is set to TRUE if "Identifier" is equal to
2778: // "SONIC".
2779: //
2780:
2781: BOOLEAN SonicIdentifier;
2782:
2783: } SONIC_HARDWARE_INFO, *PSONIC_HARDWARE_INFO;
2784:
2785:
2786: STATIC
2787: NTSTATUS
2788: SonicHardwareSaveInformation(
2789: IN PWSTR ValueName,
2790: IN ULONG ValueType,
2791: IN PVOID ValueData,
2792: IN ULONG ValueLength,
2793: IN PVOID Context,
2794: IN PVOID EntryContext
2795: )
2796:
2797: /*++
2798:
2799: Routine Description:
2800:
2801: This routine is a callback routine for RtlQueryRegistryValues.
2802: It is called back with the data for the "Identifier" value
2803: and verifies that it is "SONIC", then is called back with
2804: the resource list and records the ports, interrupt number,
2805: and DCR value.
2806:
2807: Arguments:
2808:
2809: ValueName - The name of the value ("Identifier" or "Configuration
2810: Data").
2811:
2812: ValueType - The type of the value (REG_SZ or REG_BINARY).
2813:
2814: ValueData - The null-terminated data for the value.
2815:
2816: ValueLength - The length of ValueData (ignored).
2817:
2818: Context - A pointer to the SONIC_HARDWARE_INFO structure.
2819:
2820: EntryContext - FALSE for "Identifier", TRUE for "Configuration Data".
2821:
2822: Return Value:
2823:
2824: STATUS_SUCCESS
2825:
2826: --*/
2827:
2828: {
2829: PSONIC_HARDWARE_INFO HardwareInfo = (PSONIC_HARDWARE_INFO)Context;
2830:
2831: if ((BOOLEAN)EntryContext) {
2832:
2833: //
2834: // This is the "Configuration Data" callback.
2835: //
2836:
2837: if ((ValueType == REG_BINARY || ValueType == REG_FULL_RESOURCE_DESCRIPTOR) &&
2838: (ValueLength >= sizeof(CM_FULL_RESOURCE_DESCRIPTOR))) {
2839:
2840: BOOLEAN InterruptRead = FALSE;
2841: BOOLEAN PortAddressRead = FALSE;
2842: BOOLEAN DeviceSpecificRead = FALSE;
2843: UINT i;
2844:
2845: PCM_PARTIAL_RESOURCE_LIST ResourceList;
2846: PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
2847: PCM_SONIC_DEVICE_DATA SonicDeviceData;
2848:
2849: ResourceList =
2850: &((PCM_FULL_RESOURCE_DESCRIPTOR)ValueData)->PartialResourceList;
2851:
2852: for (i = 0; i < ResourceList->Count; i++) {
2853:
2854: ResourceDescriptor = &(ResourceList->PartialDescriptors[i]);
2855:
2856: switch (ResourceDescriptor->Type) {
2857:
2858: case CmResourceTypePort:
2859:
2860: HardwareInfo->PortAddress = ResourceDescriptor->u.Port.Start;
2861: PortAddressRead = TRUE;
2862: break;
2863:
2864: case CmResourceTypeInterrupt:
2865:
2866: HardwareInfo->InterruptVector = (CCHAR)ResourceDescriptor->u.Interrupt.Vector;
2867: HardwareInfo->InterruptLevel = (KIRQL)ResourceDescriptor->u.Interrupt.Level;
2868: InterruptRead = TRUE;
2869: break;
2870:
2871: case CmResourceTypeDeviceSpecific:
2872:
2873: if (i == ResourceList->Count-1) {
2874:
2875: SonicDeviceData = (PCM_SONIC_DEVICE_DATA)
2876: &(ResourceList->PartialDescriptors[ResourceList->Count]);
2877:
2878: //
2879: // Make sure we have enough room for each element we read.
2880: //
2881:
2882: if (ResourceDescriptor->u.DeviceSpecificData.DataSize >=
2883: (ULONG)(FIELD_OFFSET (CM_SONIC_DEVICE_DATA, EthernetAddress[0]))) {
2884:
2885: HardwareInfo->DataConfigurationRegister =
2886: SonicDeviceData->DataConfigurationRegister;
2887: DeviceSpecificRead = TRUE;
2888:
2889: //
2890: // Version.Revision later than 0.0 means that
2891: // the ethernet address is there too.
2892: //
2893:
2894: if ((SonicDeviceData->Version != 0) ||
2895: (SonicDeviceData->Revision != 0)) {
2896:
2897: if (ResourceDescriptor->u.DeviceSpecificData.DataSize >=
2898: (ULONG)(FIELD_OFFSET (CM_SONIC_DEVICE_DATA, EthernetAddress[0]) + 8)) {
2899:
2900: SONIC_MOVE_MEMORY(
2901: HardwareInfo->EthernetAddress,
2902: SonicDeviceData->EthernetAddress,
2903: 8);
2904:
2905: HardwareInfo->AddressValid = TRUE;
2906:
2907: }
2908:
2909: }
2910:
2911: }
2912:
2913: }
2914:
2915: break;
2916:
2917: }
2918:
2919: }
2920:
2921: //
2922: // Make sure we got all we wanted.
2923: //
2924:
2925: if (PortAddressRead && InterruptRead && DeviceSpecificRead) {
2926: HardwareInfo->DataValid = TRUE;
2927: }
2928:
2929: }
2930:
2931: } else {
2932:
2933: static const WCHAR SonicString[] = L"SONIC";
2934:
2935: //
2936: // This is the "Identifier" callback.
2937: //
2938:
2939: if ((ValueType == REG_SZ) &&
2940: (ValueLength >= sizeof(SonicString)) &&
2941: (RtlCompareMemory (ValueData, (PVOID)&SonicString, sizeof(SonicString)) == sizeof(SonicString))) {
2942:
2943: HardwareInfo->SonicIdentifier = TRUE;
2944:
2945: }
2946:
2947: }
2948:
2949: return STATUS_SUCCESS;
2950:
2951: }
2952:
2953:
2954: STATIC
2955: BOOLEAN
2956: SonicHardwareVerifyChecksum(
2957: IN PSONIC_ADAPTER Adapter,
2958: IN PUCHAR EthernetAddress,
2959: OUT ULONG ErrorLogData[3]
2960: )
2961:
2962: /*++
2963:
2964: Routine Description:
2965:
2966: This routine verifies that the checksum on the address
2967: for an internal sonic on a MIPS R4000 system is correct.
2968:
2969: Arguments:
2970:
2971: Adapter - The adapter which is being verified.
2972:
2973: EthernetAddress - A pointer to the address, with the checksum
2974: following it.
2975:
2976: ErrorLogData - If the checksum is bad, returns the address
2977: and the checksum we expected.
2978:
2979: Return Value:
2980:
2981: TRUE if the checksum is correct.
2982:
2983: --*/
2984:
2985: {
2986:
2987: //
2988: // Iteration variable.
2989: //
2990: UINT i;
2991:
2992: //
2993: // Holds the checksum value.
2994: //
2995: USHORT CheckSum = 0;
2996:
2997:
2998: //
2999: // The network address is stored in the first 6 bytes of
3000: // EthernetAddress. Following that is a zero byte followed
3001: // by a value such that the sum of a checksum on the six
3002: // bytes and this value is 0xff. The checksum is computed
3003: // by adding together the six bytes, with the carry being
3004: // wrapped back to the first byte.
3005: //
3006:
3007: for (i=0; i<6; i++) {
3008:
3009: CheckSum += EthernetAddress[i];
3010: if (CheckSum > 0xff) {
3011: CheckSum -= 0xff;
3012: }
3013:
3014: }
3015:
3016:
3017: if ((EthernetAddress[6] != 0x00) ||
3018: ((EthernetAddress[7] + CheckSum) != 0xff)) {
3019:
3020: ErrorLogData[0] = ((ULONG)(EthernetAddress[3]) << 24) +
3021: ((ULONG)(EthernetAddress[2]) << 16) +
3022: ((ULONG)(EthernetAddress[1]) << 8) +
3023: ((ULONG)(EthernetAddress[0]));
3024: ErrorLogData[1] = ((ULONG)(EthernetAddress[7]) << 24) +
3025: ((ULONG)(EthernetAddress[6]) << 16) +
3026: ((ULONG)(EthernetAddress[5]) << 8) +
3027: ((ULONG)(EthernetAddress[4]));
3028: ErrorLogData[2] = 0xff - CheckSum;
3029:
3030: return FALSE;
3031:
3032: }
3033:
3034: return TRUE;
3035:
3036: }
3037:
3038: #endif // SONIC_INTERNAL
3039:
3040:
3041: STATIC
3042: SONIC_HARDWARE_STATUS
3043: SonicHardwareGetDetails(
3044: IN PSONIC_ADAPTER Adapter,
3045: IN UINT SlotNumber,
3046: IN UINT Controller,
3047: IN UINT MultifunctionAdapter,
3048: OUT PULONG InitialPort,
3049: OUT PULONG NumberOfPorts,
3050: IN OUT PUINT InterruptVector,
3051: IN OUT PUINT InterruptLevel,
3052: OUT ULONG ErrorLogData[3]
3053: )
3054:
3055: /*++
3056:
3057: Routine Description:
3058:
3059: This routine gets the initial port and number of ports for
3060: the Sonic. It also sets Adapter->PortShift. The ports are
3061: numbered 0, 1, 2, etc. but may appear as 16- or 32-bit
3062: ports, so PortShift will be 1 or 2 depending on how wide
3063: the ports are.
3064:
3065: It also sets the value of Adapter->DataConfigurationRegister,
3066: and may modify InterruptVector, InterruptLevel, and
3067: Adapter->PermanentNetworkAddress.
3068:
3069: Arguments:
3070:
3071: Adapter - The adapter in question.
3072:
3073: SlotNumber - For the EISA card this is the slot number that the
3074: card is in.
3075:
3076: Controller - For the internal version, it is the
3077: NetworkController number.
3078:
3079: MultifunctionAdapter - For the internal version, it is the adapter number.
3080:
3081: InitialPort - The base of the Sonic ports.
3082:
3083: NumberOfPorts - The number of bytes of ports to map.
3084:
3085: InterruptVector - A pointer to the interrupt vector. Depending
3086: on the card type, this may be passed in or returned by
3087: this function.
3088:
3089: InterruptLevel - A pointer to the interrupt level. Depending
3090: on the card type, this may be passed in or returned by
3091: this function.
3092:
3093: ErrorLogData - If the return status is SonicHardwareChecksum,
3094: this returns 3 longwords to be included in the error log.
3095:
3096: Return Value:
3097:
3098: SonicHardwareOk if successful, SonicHardwareChecksum if the
3099: checksum is bad, SonicHardwareConfig for other problems.
3100:
3101: --*/
3102:
3103: {
3104:
3105: switch (Adapter->AdapterType) {
3106:
3107: #ifdef SONIC_EISA
3108:
3109: case SONIC_ADAPTER_TYPE_EISA:
3110:
3111: *InitialPort = (SlotNumber << 12);
3112: *NumberOfPorts = 0xD00;
3113: Adapter->PortShift = 1;
3114: Adapter->DataConfigurationRegister =
3115: SONIC_DCR_PROGRAMMABLE_OUTPUT_1 |
3116: SONIC_DCR_USER_DEFINABLE_1 |
3117: SONIC_DCR_3_WAIT_STATE |
3118: SONIC_DCR_BLOCK_MODE_DMA |
3119: SONIC_DCR_32_BIT_DATA_WIDTH |
3120: SONIC_DCR_8_WORD_RECEIVE_FIFO |
3121: SONIC_DCR_8_WORD_TRANSMIT_FIFO;
3122:
3123: return SonicHardwareOk;
3124: break;
3125:
3126: #endif // SONIC_EISA
3127:
3128: #ifdef SONIC_INTERNAL
3129:
3130: case SONIC_ADAPTER_TYPE_INTERNAL:
3131: {
3132:
3133: //
3134: // For MIPS R4000 systems, we have to query the registry to obtain
3135: // information about ports, interrupts, and the value to be
3136: // stored in the DCR register.
3137: //
3138:
3139: //
3140: // NOTE: The following code is NT-specific, since that is
3141: // currently the only system that runs on the MIPS R4000 hardware.
3142: //
3143: // We initialize an RTL_QUERY_TABLE to retrieve the Identifer
3144: // and ConfigurationData strings from the registry.
3145: //
3146:
3147: PWSTR ConfigDataPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter\\#\\NetworkController\\#";
3148: PWSTR IdentifierString = L"Identifier";
3149: PWSTR ConfigDataString = L"Configuration Data";
3150: RTL_QUERY_REGISTRY_TABLE QueryTable[4];
3151: SONIC_HARDWARE_INFO SonicHardwareInfo;
3152: NTSTATUS Status;
3153:
3154:
3155: //
3156: // Set up QueryTable to do the following:
3157: //
3158:
3159: //
3160: // 1) Call SonicSaveHardwareInformation for the "Identifier"
3161: // value.
3162: //
3163:
3164: QueryTable[0].QueryRoutine = SonicHardwareSaveInformation;
3165: QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
3166: QueryTable[0].Name = IdentifierString;
3167: QueryTable[0].EntryContext = (PVOID)FALSE;
3168: QueryTable[0].DefaultType = REG_NONE;
3169:
3170: //
3171: // 2) Call SonicSaveHardwareInformation for the "Configuration Data"
3172: // value.
3173: //
3174:
3175: QueryTable[1].QueryRoutine = SonicHardwareSaveInformation;
3176: QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED;
3177: QueryTable[1].Name = ConfigDataString;
3178: QueryTable[1].EntryContext = (PVOID)TRUE;
3179: QueryTable[1].DefaultType = REG_NONE;
3180:
3181: //
3182: // 3) Stop
3183: //
3184:
3185: QueryTable[2].QueryRoutine = NULL;
3186: QueryTable[2].Flags = 0;
3187: QueryTable[2].Name = NULL;
3188:
3189:
3190: //
3191: // Modify ConfigDataPath to replace the two # symbols with
3192: // the MultifunctionAdapter number and NetworkController number.
3193: //
3194:
3195: ConfigDataPath[67] = (WCHAR)('0' + MultifunctionAdapter);
3196: ConfigDataPath[87] = (WCHAR)('0' + Controller);
3197:
3198: SonicHardwareInfo.DataValid = FALSE;
3199: SonicHardwareInfo.AddressValid = FALSE;
3200: SonicHardwareInfo.SonicIdentifier = FALSE;
3201:
3202: Status = RtlQueryRegistryValues(
3203: RTL_REGISTRY_ABSOLUTE,
3204: ConfigDataPath,
3205: QueryTable,
3206: (PVOID)&SonicHardwareInfo,
3207: NULL);
3208:
3209: if (!NT_SUCCESS(Status)) {
3210: #if DBG
3211: DbgPrint ("SONIC: Could not read hardware information\n");
3212: #endif
3213: return SonicHardwareConfig;
3214: }
3215:
3216: if (SonicHardwareInfo.DataValid && SonicHardwareInfo.SonicIdentifier) {
3217:
3218: *InterruptVector = (UINT)SonicHardwareInfo.InterruptVector;
3219: *InterruptLevel = (UINT)SonicHardwareInfo.InterruptLevel;
3220: *InitialPort = SonicHardwareInfo.PortAddress.LowPart;
3221: *NumberOfPorts = 192;
3222: Adapter->PortShift = 2;
3223: Adapter->DataConfigurationRegister =
3224: SonicHardwareInfo.DataConfigurationRegister;
3225:
3226: if (SonicHardwareInfo.AddressValid) {
3227:
3228: if (!SonicHardwareVerifyChecksum(Adapter, SonicHardwareInfo.EthernetAddress, ErrorLogData)) {
3229: #if DBG
3230: DbgPrint("SONIC: Invalid registry network address checksum!!\n");
3231: #endif
3232: return SonicHardwareChecksum;
3233: }
3234:
3235: SONIC_MOVE_MEMORY(
3236: Adapter->PermanentNetworkAddress,
3237: SonicHardwareInfo.EthernetAddress,
3238: 8);
3239: Adapter->PermanentAddressValid = TRUE;
3240:
3241: }
3242:
3243: return SonicHardwareOk;
3244:
3245: } else {
3246:
3247: #if DBG
3248: DbgPrint ("SONIC: Incorrect registry hardware information\n");
3249: #endif
3250: return SonicHardwareConfig;
3251:
3252: }
3253:
3254: break;
3255:
3256: }
3257:
3258: #endif // SONIC_INTERNAL
3259:
3260: default:
3261:
3262: ASSERT(FALSE);
3263: break;
3264:
3265: }
3266:
3267: return SonicHardwareConfig;
3268:
3269: }
3270:
3271:
3272: STATIC
3273: BOOLEAN
3274: SonicHardwareGetAddress(
3275: IN PSONIC_ADAPTER Adapter,
3276: IN ULONG ErrorLogData[3]
3277: )
3278:
3279: /*++
3280:
3281: Routine Description:
3282:
3283: This routine gets the network address from the hardware.
3284:
3285: Arguments:
3286:
3287: Adapter - Where to store the network address.
3288:
3289: ErrorLogData - If the checksum is bad, returns the address
3290: and the checksum we expected.
3291:
3292: Return Value:
3293:
3294: TRUE if successful.
3295:
3296: --*/
3297:
3298: {
3299: #define NVRAM_READ_ONLY_BASE 0x8000b000
3300:
3301: //
3302: // Iteration variable.
3303: //
3304: UINT i;
3305:
3306:
3307: switch (Adapter->AdapterType) {
3308:
3309: #ifdef SONIC_EISA
3310:
3311: case SONIC_ADAPTER_TYPE_EISA:
3312:
3313: //
3314: // The EISA card has the address stored at ports xC90 to xC95,
3315: // where x is the slot number.
3316: //
3317:
3318: for (i = 0; i < 6; i++) {
3319:
3320: NdisRawReadPortUchar(
3321: Adapter->SonicPortAddress + 0xc90 + i,
3322: &Adapter->PermanentNetworkAddress[i]);
3323:
3324: }
3325:
3326: break;
3327:
3328: #endif // SONIC_EISA
3329:
3330: #ifdef SONIC_INTERNAL
3331:
3332: case SONIC_ADAPTER_TYPE_INTERNAL:
3333: {
3334:
3335: NDIS_STATUS Status;
3336: USHORT SiliconRevision;
3337:
3338: if (!Adapter->PermanentAddressValid) {
3339:
3340: //
3341: // Physical addresses for call to NdisMapIoSpace.
3342: //
3343:
3344: NDIS_PHYSICAL_ADDRESS NvRamPhysical =
3345: NDIS_PHYSICAL_ADDRESS_CONST(NVRAM_READ_ONLY_BASE, 0);
3346:
3347: //
3348: // Temporarily maps the NVRAM into our address space.
3349: //
3350: PVOID NvRamMapping;
3351:
3352:
3353:
3354: //
3355: // If PermanentAddressValid is still FALSE then the address
3356: // was not read by SonicHardwareGetDetails, so we must do it
3357: // here.
3358: //
3359:
3360: NdisMapIoSpace (
3361: &Status,
3362: &NvRamMapping,
3363: Adapter->NdisAdapterHandle,
3364: NvRamPhysical,
3365: 8
3366: );
3367:
3368: if (Status != NDIS_STATUS_SUCCESS) {
3369:
3370: NdisWriteErrorLogEntry(
3371: Adapter->NdisAdapterHandle,
3372: NDIS_ERROR_CODE_RESOURCE_CONFLICT,
3373: 0
3374: );
3375:
3376: return(FALSE);
3377:
3378: }
3379:
3380: //
3381: // Verify that the checksum matches.
3382: //
3383:
3384: if (!SonicHardwareVerifyChecksum(Adapter, (PUCHAR)NvRamMapping, ErrorLogData)) {
3385:
3386: #if DBG
3387: DbgPrint("SONIC: Invalid NVRAM network address checksum!!\n");
3388: #endif
3389: NdisUnmapIoSpace(Adapter->NdisAdapterHandle, NvRamMapping, 8);
3390: return FALSE;
3391:
3392: }
3393:
3394: //
3395: // Checksum is OK, save the address.
3396: //
3397:
3398: for (i=0; i<6; i++) {
3399: Adapter->PermanentNetworkAddress[i] = *((PUCHAR)NvRamMapping+i);
3400: }
3401: Adapter->PermanentAddressValid = TRUE;
3402:
3403: NdisUnmapIoSpace(Adapter->NdisAdapterHandle, NvRamMapping, 8);
3404:
3405: }
3406:
3407: //
3408: // The Data Configuration Register is already set up, but we
3409: // change the FIFO initialization for old revisions.
3410: //
3411:
3412: SONIC_READ_PORT(Adapter, SONIC_SILICON_REVISION, &SiliconRevision);
3413:
3414: if (SiliconRevision < 4) {
3415:
3416: Adapter->DataConfigurationRegister =
3417: (Adapter->DataConfigurationRegister & SONIC_DCR_FIFO_MASK) |
3418: SONIC_DCR_8_WORD_RECEIVE_FIFO |
3419: SONIC_DCR_8_WORD_TRANSMIT_FIFO;
3420:
3421: }
3422:
3423: break;
3424:
3425: }
3426:
3427: #endif // SONIC_INTERNAL
3428:
3429: default:
3430:
3431: ASSERT(FALSE);
3432: break;
3433:
3434: }
3435:
3436:
3437: #if DBG
3438: if (SonicDbg) {
3439: DbgPrint("SONIC: ");
3440: DbgPrint("[ %x-%x-%x-%x-%x-%x ]\n",
3441: (UCHAR)Adapter->PermanentNetworkAddress[0],
3442: (UCHAR)Adapter->PermanentNetworkAddress[1],
3443: (UCHAR)Adapter->PermanentNetworkAddress[2],
3444: (UCHAR)Adapter->PermanentNetworkAddress[3],
3445: (UCHAR)Adapter->PermanentNetworkAddress[4],
3446: (UCHAR)Adapter->PermanentNetworkAddress[5]);
3447: DbgPrint("\n");
3448: }
3449: #endif
3450:
3451: return TRUE;
3452:
3453: }
3454:
3455:
3456: VOID
3457: SonicShutdown(
3458: IN PVOID ShutdownContext
3459: )
3460:
3461: /*++
3462:
3463: Routine Description:
3464:
3465: Turns off the card during a powerdown of the system.
3466:
3467: Arguments:
3468:
3469: ShutdownContext - Really a pointer to the adapter structure.
3470:
3471: Return Value:
3472:
3473: None.
3474:
3475: --*/
3476:
3477: {
3478: PSONIC_ADAPTER Adapter = (PSONIC_ADAPTER)(ShutdownContext);
3479:
3480: NdisAcquireSpinLock(&Adapter->Lock);
3481:
3482: //
3483: // Set the flag
3484: //
3485:
3486: Adapter->Removed = TRUE;
3487:
3488: //
3489: // Shut down the chip. We won't be doing any more work until
3490: // the reset is complete.
3491: //
3492:
3493: SonicStopChip(Adapter);
3494:
3495: NdisStallExecution(250000);
3496:
3497: NdisReleaseSpinLock(&Adapter->Lock);
3498:
3499: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.