Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4269 lines
100 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. pc586.c
  5. Abstract:
  6. This is the main file for the Intel PC586
  7. Ethernet controller. This driver conforms to the NDIS 3.0 interface.
  8. The idea for handling loopback and sends simultaneously is largely
  9. adapted from the EtherLink II NDIS driver by Adam Barr.
  10. Author:
  11. Weldon Washburn (o-weldo, Intel) 30-OCT-1990 adapted from ...
  12. Anthony V. Ercolano (Tonye) 20-Jul-1990
  13. Environment:
  14. Kernel Mode - Or whatever is the equivalent on OS/2 and DOS.
  15. Revision History:
  16. --*/
  17. #include <ntos.h>
  18. #include <ndis.h>
  19. #include <filter.h>
  20. #include <pc586hrd.h>
  21. #include <pc586sft.h>
  22. ULONG ResetCount, SpuriousIntCount, BadRcvCount,
  23. RcvRestartCount, RcvSuspendCount;
  24. static
  25. NDIS_STATUS
  26. Pc586OpenAdapter(
  27. OUT NDIS_HANDLE *MacBindingHandle,
  28. IN NDIS_HANDLE RequestHandle,
  29. IN NDIS_HANDLE NdisBindingContext,
  30. IN NDIS_HANDLE MacAdapterContext,
  31. IN PSTRING AddressingInformation OPTIONAL
  32. );
  33. static
  34. NDIS_STATUS
  35. Pc586CloseAdapter(
  36. IN NDIS_HANDLE MacBindingHandle,
  37. IN NDIS_HANDLE RequestHandle
  38. );
  39. static
  40. NDIS_STATUS
  41. Pc586SetPacketFilter(
  42. IN NDIS_HANDLE MacBindingHandle,
  43. IN NDIS_HANDLE RequestHandle,
  44. IN UINT PacketFilter
  45. );
  46. static
  47. NDIS_STATUS
  48. Pc586AddMulticastAddress(
  49. IN NDIS_HANDLE MacBindingHandle,
  50. IN NDIS_HANDLE RequstHandle,
  51. IN PSTRING MulticastAddress
  52. );
  53. static
  54. NDIS_STATUS
  55. Pc586DeleteMulticastAddress(
  56. IN NDIS_HANDLE MacBindingHandle,
  57. IN NDIS_HANDLE RequestHandle,
  58. IN PSTRING MulticastAddress
  59. );
  60. static
  61. NDIS_STATUS
  62. Pc586QueryInformation(
  63. IN NDIS_HANDLE MacBindingHandle,
  64. IN NDIS_HANDLE RequestHandle,
  65. IN NDIS_INFORMATION_CLASS InformationClass,
  66. OUT PVOID Buffer,
  67. IN UINT BufferLength
  68. );
  69. static
  70. NDIS_STATUS
  71. Pc586SetInformation(
  72. IN NDIS_HANDLE MacBindingHandle,
  73. IN NDIS_HANDLE RequestHandle,
  74. IN NDIS_INFORMATION_CLASS InformationClass,
  75. IN PVOID Buffer,
  76. IN UINT BufferLength
  77. );
  78. static
  79. NDIS_STATUS
  80. Pc586Reset(
  81. IN NDIS_HANDLE MacBindingHandle,
  82. IN NDIS_HANDLE RequestHandle
  83. );
  84. static
  85. NDIS_STATUS
  86. Pc586Test(
  87. IN NDIS_HANDLE MacBindingHandle,
  88. IN NDIS_HANDLE RequestHandle
  89. );
  90. static
  91. NDIS_STATUS
  92. Pc586ChangeClass(
  93. IN UINT OldFilterClasses,
  94. IN UINT NewFilterClasses,
  95. IN NDIS_HANDLE NdisBindingContext,
  96. IN NDIS_HANDLE RequestHandle,
  97. IN BOOLEAN Set
  98. );
  99. static
  100. NDIS_STATUS
  101. Pc586AddMulticast(
  102. IN UINT CurrentAddressCount,
  103. IN CHAR CurrentAddresses[][MAC_LENGTH_OF_ADDRESS],
  104. IN UINT NewAddress,
  105. IN NDIS_HANDLE NdisBindingContext,
  106. IN NDIS_HANDLE RequestHandle
  107. );
  108. static
  109. NDIS_STATUS
  110. Pc586DeleteMulticast(
  111. IN UINT CurrentAddressCount,
  112. IN CHAR CurrentAddresses[][MAC_LENGTH_OF_ADDRESS],
  113. IN CHAR OldAddress[MAC_LENGTH_OF_ADDRESS],
  114. IN NDIS_HANDLE NdisBindingContext,
  115. IN NDIS_HANDLE RequestHandle
  116. );
  117. static
  118. VOID
  119. Pc586CloseAction(
  120. IN NDIS_HANDLE MacBindingHandle
  121. );
  122. static
  123. VOID
  124. ReturnAdapterResources(
  125. IN PPC586_ADAPTER Adapter
  126. );
  127. static
  128. VOID
  129. ProcessReceiveInterrupts(
  130. IN PPC586_ADAPTER Adapter
  131. );
  132. static
  133. BOOLEAN
  134. ProcessTransmitInterrupts(
  135. IN PPC586_ADAPTER Adapter
  136. );
  137. static
  138. VOID
  139. Pc586StandardInterruptDPC(
  140. IN PKDPC Dpc,
  141. IN PVOID Context,
  142. IN PVOID SystemArgument1,
  143. IN PVOID SystemArgument2
  144. );
  145. extern
  146. BOOLEAN
  147. Pc586ISR(
  148. IN PKINTERRUPT Interrupt,
  149. IN PVOID Context
  150. );
  151. static
  152. VOID
  153. ProcessInterrupt(
  154. IN PPC586_ADAPTER Adapter
  155. );
  156. static
  157. VOID
  158. SetInitBlockAndInit(
  159. IN PPC586_ADAPTER Adapter
  160. );
  161. static
  162. VOID
  163. StartAdapterReset(
  164. IN PPC586_ADAPTER Adapter
  165. );
  166. static
  167. VOID
  168. SetupForReset(
  169. IN PPC586_ADAPTER Adapter,
  170. IN PPC586_OPEN Open,
  171. IN NDIS_HANDLE RequestHandle,
  172. IN NDIS_REQUEST_TYPE RequestType
  173. );
  174. static
  175. BOOLEAN
  176. Pc586InitialInit(
  177. IN PPC586_ADAPTER Adapter
  178. );
  179. static
  180. VOID
  181. LoadMCAddress(
  182. IN PPC586_ADAPTER Adapter
  183. );
  184. //
  185. // ZZZ Non portable interface.
  186. //
  187. UINT ww_put = 0xff; // debug, set != 0 for 4 byte xfer in PutPacket();
  188. NTSTATUS
  189. DriverEntry(
  190. IN PDRIVER_OBJECT DriverObject
  191. )
  192. /*++
  193. Routine Description:
  194. This is the primary initialization routine for the pc586 driver.
  195. It is simply responsible for the intializing the wrapper and registering
  196. the MAC. It then calls a system and architecture specific routine that
  197. will initialize and register each adapter.
  198. Arguments:
  199. DriverObject - Pointer to driver object created by the system.
  200. Return Value:
  201. The status of the operation.
  202. --*/
  203. {
  204. //
  205. // Receives the status of the NdisRegisterMac operation.
  206. //
  207. NDIS_STATUS InitStatus;
  208. NDIS_HANDLE NdisMacHandle;
  209. NDIS_HANDLE NdisWrapperHandle;
  210. char MacName[] = "PC586";
  211. char Tmp[sizeof(NDIS_MAC_CHARACTERISTICS) + sizeof(MacName) - 1];
  212. PNDIS_MAC_CHARACTERISTICS Pc586Char = (PNDIS_MAC_CHARACTERISTICS)Tmp;
  213. //
  214. // Initialize the wrapper.
  215. //
  216. NdisInitializeWrapper(&NdisWrapperHandle,DriverObject,NULL,NULL);
  217. //
  218. // Initialize the MAC characteristics for the call to
  219. // NdisRegisterMac.
  220. //
  221. Pc586Char->MajorNdisVersion = PC586_NDIS_MAJOR_VERSION;
  222. Pc586Char->MinorNdisVersion = PC586_NDIS_MINOR_VERSION;
  223. Pc586Char->OpenAdapterHandler = Pc586OpenAdapter;
  224. Pc586Char->CloseAdapterHandler = Pc586CloseAdapter;
  225. Pc586Char->SetPacketFilterHandler = Pc586SetPacketFilter;
  226. Pc586Char->AddMulticastAddressHandler = Pc586AddMulticastAddress;
  227. Pc586Char->DeleteMulticastAddressHandler = Pc586DeleteMulticastAddress;
  228. Pc586Char->SendHandler = Pc586Send;
  229. Pc586Char->TransferDataHandler = Pc586TransferData;
  230. Pc586Char->QueryInformationHandler = Pc586QueryInformation;
  231. Pc586Char->SetInformationHandler = Pc586SetInformation;
  232. Pc586Char->ResetHandler = Pc586Reset;
  233. Pc586Char->TestHandler = Pc586Test;
  234. Pc586Char->NameLength = sizeof(MacName) - 1;
  235. PC586_MOVE_MEMORY(
  236. Pc586Char->Name,
  237. MacName,
  238. sizeof(MacName)
  239. );
  240. NdisRegisterMac(
  241. &InitStatus,
  242. &NdisMacHandle,
  243. NdisWrapperHandle,
  244. NULL,
  245. Pc586Char,
  246. sizeof(*Pc586Char)
  247. );
  248. if (InitStatus == NDIS_STATUS_SUCCESS) {
  249. //
  250. // We started our communication with the wrapper. We now
  251. // call a routine which will attempt to allocate and register
  252. // all of the adapters. It will return true if *any* of the
  253. // adapters were able to start.
  254. //
  255. if (Pc586StartAdapters(NdisMacHandle)) {
  256. return InitStatus;
  257. }
  258. }
  259. //
  260. // We can only get here if something went wrong with registering
  261. // the mac or *all* of the adapters.
  262. //
  263. NdisDeregisterMac(
  264. &InitStatus,
  265. NdisMacHandle
  266. );
  267. NdisTerminateWrapper(DriverObject);
  268. return NDIS_ADAPTER_NOT_FOUND;
  269. }
  270. extern
  271. BOOLEAN
  272. Pc586StartAdapters(
  273. IN NDIS_HANDLE NdisMacHandle
  274. )
  275. /*++
  276. Routine Description:
  277. This routine is used to initialize each adapter card/chip.
  278. Arguments:
  279. NdisMacHandle - The handle given by ndis when the mac was
  280. registered.
  281. Return Value:
  282. Returns false if *no* adatper was able to be initialized.
  283. --*/
  284. {
  285. BOOLEAN Status = FALSE;
  286. Status = Pc586RegisterAdapter(
  287. NdisMacHandle,
  288. (PSZ)"\\Device\\Pc586",
  289. (PVOID)PC586_DEFAULT_STATIC_RAM,
  290. (CCHAR)PC586_DEFAULT_INTERRUPT_VECTOR,
  291. (KIRQL)PC586_DEFAULT_INTERRUPT_IRQL,
  292. (UINT)16,
  293. (UINT)32
  294. ) || Status;
  295. return Status;
  296. }
  297. extern
  298. BOOLEAN
  299. Pc586RegisterAdapter(
  300. IN NDIS_HANDLE NdisMacHandle,
  301. IN PSZ DeviceName,
  302. IN PVOID Pc586BaseHardwareMemoryAddress,
  303. IN CCHAR Pc586InterruptVector,
  304. IN KIRQL Pc586InterruptIrql,
  305. IN UINT MaximumMulticastAddresses,
  306. IN UINT MaximumOpenAdapters
  307. )
  308. /*++
  309. Routine Description:
  310. This routine (and its interface) are not portable. They are
  311. defined by the OS, the architecture, and the particular PC586
  312. implementation.
  313. This routine is responsible for the allocation of the datastructures
  314. for the driver as well as any hardware specific details necessary
  315. to talk with the device.
  316. Arguments:
  317. NdisMacHandle - The handle given back to the mac from ndis when
  318. the mac registered itself.
  319. DeviceName - The zero terminated string containing the name
  320. to give to the device adapter.
  321. Pc586NetworkAddressAddress - The address containing the ethernet network
  322. address.
  323. Pc586BaseHardwareMemoryAddress - Given that this is an implementation
  324. that uses dual ported memory this is the base of the memory for the
  325. hardware.
  326. Pc586InterruptVector - The interrupt vector to used for the adapter.
  327. Pc586InterruptIrql - The interrupt request level to used for this
  328. adapter.
  329. MaximumMulticastAddresses - The maximum number of multicast
  330. addresses to filter at any one time.
  331. MaximumOpenAdatpers - The maximum number of opens at any one time.
  332. Return Value:
  333. Returns false if anything occurred that prevents the initialization
  334. of the adapter.
  335. --*/
  336. {
  337. STRING Tmp;
  338. UINT xx;
  339. //
  340. // Pointer for the adapter root.
  341. //
  342. PPC586_ADAPTER Adapter;
  343. PUCHAR CmdPromPhys, StaticRamPhys;
  344. //
  345. // We put in this assertion to make sure that ushort are 2 bytes.
  346. // if they aren't then the initialization block definition needs
  347. // to be changed.
  348. //
  349. // Also all of the logic that deals with status registers assumes
  350. // that control registers are only 2 bytes.
  351. //
  352. ASSERT(sizeof(USHORT) == 2);
  353. //
  354. // All of the code that manipulates physical addresses depends
  355. // on the fact that physical addresses are 4 byte quantities.
  356. //
  357. ASSERT(sizeof(PHYSICAL_ADDRESS) == 4);
  358. //
  359. // Allocate the Adapter block.
  360. //
  361. if (Adapter = PC586_ALLOC_PHYS(sizeof(PC586_ADAPTER))) {
  362. DbgPrint("PC586 &Adapter == %lx\n", Adapter);
  363. PC586_ZERO_MEMORY(
  364. Adapter,
  365. sizeof(PC586_ADAPTER)
  366. );
  367. Adapter->NdisMacHandle = NdisMacHandle;
  368. //
  369. // Allocate memory to hold the name of the device and initialize
  370. // a STRING in the adapter block to hold it.
  371. //
  372. RtlInitString(
  373. &Tmp,
  374. DeviceName
  375. );
  376. Adapter->DeviceName = PC586_ALLOC_PHYS(Tmp.Length+1);
  377. if (Adapter->DeviceName) {
  378. {
  379. PUCHAR S,D;
  380. D = Adapter->DeviceName;
  381. S = DeviceName;
  382. while (*S) {
  383. *D = *S;
  384. D++;
  385. S++;
  386. }
  387. *D = 0;
  388. }
  389. //
  390. // initialize hardware.
  391. //
  392. CmdPromPhys = (PUCHAR)Pc586BaseHardwareMemoryAddress;
  393. StaticRamPhys = (PUCHAR)Pc586BaseHardwareMemoryAddress;
  394. Adapter->CmdProm = (PUCHAR)MmMapIoSpace(
  395. (PHYSICAL_ADDRESS)CmdPromPhys, (ULONG)32*1024, FALSE);
  396. Adapter->StaticRam = Adapter->CmdProm;
  397. Adapter->Cb = (PCMD)(Adapter->StaticRam + OFFSETCU);
  398. Adapter->Tbd = (PTBD)(Adapter->StaticRam + OFFSETTBD);
  399. Adapter->Scp = (PSCP)(Adapter->StaticRam + OFFSETSCP);
  400. Adapter->Iscp = (PISCP)(Adapter->StaticRam + OFFSETISCP);
  401. Adapter->Scb = (PSCB)(Adapter->StaticRam + OFFSETSCB);
  402. Adapter->CAAddr = (PUSHORT)(Adapter->StaticRam + OFFSETCHANATT);
  403. Adapter->IntAddr = (PUSHORT)(Adapter->StaticRam + OFFSETINTENAB);
  404. Adapter->CommandBuffer = (PUSHORT)(Adapter->StaticRam + OFFSETTBUF);
  405. // hardware reset the 586
  406. ShuvWord( (PUSHORT)(Adapter->CmdProm + OFFSETRESET), (USHORT)CMD1);
  407. KeStallExecutionProcessor((ULONG)1000);
  408. ShuvWord( (PUSHORT)(Adapter->CmdProm + OFFSETRESET), (USHORT)CMD0);
  409. KeStallExecutionProcessor((ULONG)1000);
  410. // test to see if board is really present
  411. ShuvWord( (PUSHORT)(Adapter->StaticRam + OFFSETSCB), 0x5a5a);
  412. xx = PullWord((PUSHORT)(Adapter->StaticRam + OFFSETSCB) );
  413. // reset again to insure board in 8-bit mode (for reading PROM)
  414. ShuvWord( (PUSHORT)(Adapter->CmdProm + OFFSETRESET), (USHORT)CMD1);
  415. KeStallExecutionProcessor((ULONG)1000);
  416. ShuvWord( (PUSHORT)(Adapter->CmdProm + OFFSETRESET), (USHORT)CMD0);
  417. KeStallExecutionProcessor((ULONG)1000);
  418. if (xx != 0x5a5a) {
  419. DbgPrint("pc586 board not present\n");
  420. return FALSE;
  421. }
  422. else DbgPrint("pc586 board was found \n");
  423. // prom address should increment by one, however the pc586 board
  424. // is STUCK in word mode thus ++ by two
  425. Adapter->NetworkAddress[0] = (UCHAR)PromAddr(Adapter, 0);
  426. Adapter->NetworkAddress[1] = (UCHAR)PromAddr(Adapter, 2);
  427. Adapter->NetworkAddress[2] = (UCHAR)PromAddr(Adapter, 4);
  428. Adapter->NetworkAddress[3] = (UCHAR)PromAddr(Adapter, 6);
  429. Adapter->NetworkAddress[4] = (UCHAR)PromAddr(Adapter, 8);
  430. Adapter->NetworkAddress[5] = (UCHAR)PromAddr(Adapter, 10);
  431. DbgPrint("ethernet id = * %x %x %x %x %x %x * \n",
  432. Adapter->NetworkAddress[0] ,
  433. Adapter->NetworkAddress[1] ,
  434. Adapter->NetworkAddress[2] ,
  435. Adapter->NetworkAddress[3] ,
  436. Adapter->NetworkAddress[4] ,
  437. Adapter->NetworkAddress[5] );
  438. DbgPrint("Pc586 is mapped at virtual address %lx \n",
  439. Adapter->CmdProm);
  440. //
  441. // Initialize the interrupt.
  442. //
  443. KeInitializeInterrupt(
  444. &Adapter->Interrupt,
  445. Pc586ISR,
  446. Adapter,
  447. (PKSPIN_LOCK)NULL,
  448. Pc586InterruptVector,
  449. Pc586InterruptIrql,
  450. Pc586InterruptIrql,
  451. LevelSensitive,
  452. TRUE,
  453. 0,
  454. TRUE
  455. );
  456. //
  457. // Initialize our dpc.
  458. //
  459. KeInitializeDpc(
  460. &Adapter->InterruptDPC,
  461. Pc586StandardInterruptDPC,
  462. Adapter
  463. );
  464. //
  465. // Store the device name away
  466. //
  467. InitializeListHead(&Adapter->OpenBindings);
  468. InitializeListHead(&Adapter->CloseList);
  469. NdisAllocateSpinLock(&Adapter->Lock);
  470. Adapter->DoingProcessing = FALSE;
  471. Adapter->FirstLoopBack = NULL;
  472. Adapter->LastLoopBack = NULL;
  473. Adapter->FirstFinishTransmit = NULL;
  474. Adapter->LastFinishTransmit = NULL;
  475. Adapter->Stage4Open = TRUE;
  476. Adapter->Stage3Open = TRUE;
  477. Adapter->Stage2Open = TRUE;
  478. Adapter->Stage1Open = TRUE;
  479. Adapter->AlreadyProcessingStage4 = FALSE;
  480. Adapter->AlreadyProcessingStage3 = FALSE;
  481. Adapter->AlreadyProcessingStage2 = FALSE;
  482. Adapter->FirstStage1Packet = NULL;
  483. Adapter->LastStage1Packet = NULL;
  484. Adapter->FirstStage2Packet = NULL;
  485. Adapter->LastStage2Packet = NULL;
  486. Adapter->FirstStage3Packet = NULL;
  487. Adapter->LastStage3Packet = NULL;
  488. Adapter->ResetInProgress = FALSE;
  489. Adapter->ResettingOpen = NULL;
  490. if (!MacCreateFilter(
  491. MaximumMulticastAddresses,
  492. MaximumOpenAdapters,
  493. Pc586DeleteMulticast,
  494. Pc586AddMulticast,
  495. Pc586ChangeClass,
  496. Pc586CloseAction,
  497. &Adapter->Lock,
  498. &Adapter->FilterDB
  499. )) {
  500. DbgPrint(
  501. "Pc586Initialize - Unsuccessful filter create"
  502. " for %s\n",
  503. Adapter->DeviceName
  504. );
  505. PC586_FREE_PHYS(Adapter->DeviceName);
  506. PC586_FREE_PHYS(Adapter);
  507. return FALSE;
  508. } else {
  509. if (!Pc586InitialInit(Adapter)) {
  510. DbgPrint(
  511. "Pc586Initialize - %s is unloading.\n",
  512. Adapter->DeviceName
  513. );
  514. MacDeleteFilter(Adapter->FilterDB);
  515. PC586_FREE_PHYS(Adapter->DeviceName);
  516. PC586_FREE_PHYS(Adapter);
  517. return FALSE;
  518. } else {
  519. return TRUE;
  520. }
  521. }
  522. } else {
  523. DbgPrint(
  524. "Pc586Initialize - Unsuccesful allocation of"
  525. "name for %s.",
  526. DeviceName
  527. );
  528. PC586_FREE_PHYS(Adapter);
  529. return FALSE;
  530. }
  531. } else {
  532. DbgPrint(
  533. "Pc586Intialize -- Unsucssful allocation of adapter block"
  534. " for %s.\n",
  535. DeviceName
  536. );
  537. return FALSE;
  538. }
  539. }
  540. extern
  541. BOOLEAN
  542. Pc586InitialInit(
  543. IN PPC586_ADAPTER Adapter
  544. )
  545. /*++
  546. Routine Description:
  547. This routine sets up the initial init of the driver.
  548. ZZZ This routine is *not* portable. It is specific to NT.
  549. Arguments:
  550. Adapter - The adapter for the hardware.
  551. Return Value:
  552. None.
  553. --*/
  554. {
  555. LARGE_INTEGER Time;
  556. //
  557. // First we make sure that the device is stopped.
  558. //
  559. Pc586IntOff(Adapter);
  560. ShuvWord( (PUSHORT)(Adapter->CmdProm + OFFSETRESET), (USHORT)CMD1);
  561. NdisAcquireSpinLock(&Adapter->Lock);
  562. SetInitBlockAndInit(Adapter);
  563. NdisReleaseSpinLock(&Adapter->Lock);
  564. //
  565. // Delay execution for 1/2 second to give the pc586
  566. // time to initialize.
  567. //
  568. Time.QuadPart = Int32x32To64( -5 * 1000 * 1000 , 1);
  569. if (KeDelayExecutionThread(
  570. KernelMode,
  571. FALSE,
  572. (PLARGE_INTEGER)&Time
  573. ) != STATUS_SUCCESS) {
  574. DbgPrint(
  575. "PC586 - Couldn't delay to start %s.\n",
  576. Adapter->DeviceName);
  577. return FALSE;
  578. } else {
  579. STRING Name;
  580. RtlInitString(
  581. &Name,
  582. Adapter->DeviceName
  583. );
  584. //
  585. // start the chip after NdisRegister... We may not
  586. // have any bindings to indicate to but this
  587. // is unimportant.
  588. //
  589. if (NdisRegisterAdapter(
  590. &Adapter->NdisAdapterHandle,
  591. Adapter->NdisMacHandle,
  592. Adapter,
  593. &Name
  594. ) != NDIS_STATUS_SUCCESS) {
  595. DbgPrint(
  596. "Pc586Initialize -- Unsuccessful "
  597. "status from NdisRegisterAdapter for %s.\n",
  598. Adapter->DeviceName
  599. );
  600. return FALSE;
  601. } else {
  602. if (!KeConnectInterrupt(&Adapter->Interrupt)) {
  603. DbgPrint(
  604. "Pc586Initialize - Unsuccessful connect "
  605. "to interrupt for %s.\n",Adapter->DeviceName
  606. );
  607. return FALSE;
  608. }
  609. Pc586IntOn(Adapter);
  610. return TRUE;
  611. }
  612. }
  613. }
  614. extern
  615. BOOLEAN
  616. Pc586ISR(
  617. IN PKINTERRUPT Interrupt,
  618. IN PVOID Context
  619. )
  620. /*++
  621. Routine Description:
  622. Interrupt service routine for the pc586. It's main job is
  623. to get the value of ScbStatus and record the changes in the
  624. adapters own list of interrupt reasons.
  625. ZZZ This routine is *not* portable. It is specific to NT and
  626. to the pc586 card.
  627. Arguments:
  628. Interrupt - Interrupt object for the Pc586.
  629. Context - Really a pointer to the adapter.
  630. Return Value:
  631. Returns true if the CX|FR|CNA|RNR bit of of the pc586 was.
  632. --*/
  633. {
  634. //
  635. // Holds the pointer to the adapter.
  636. //
  637. PPC586_ADAPTER Adapter = Context;
  638. if (Adapter->Scb->ScbStatus & SCBINTMSK) {
  639. //
  640. // Insert the normal interrupt processing DPC.
  641. //
  642. KeInsertQueueDpc(
  643. &Adapter->InterruptDPC,
  644. NULL,
  645. NULL
  646. );
  647. return TRUE;
  648. } else {
  649. return FALSE;
  650. }
  651. }
  652. static
  653. VOID
  654. Pc586StandardInterruptDPC(
  655. IN PKDPC Dpc,
  656. IN PVOID Context,
  657. IN PVOID SystemArgument1,
  658. IN PVOID SystemArgument2
  659. )
  660. /*++
  661. Routine Description:
  662. This DPC routine is queued by the interrupt service routine
  663. and other routines within the driver that notice that
  664. some deferred processing needs to be done. It's main
  665. job is to call the interrupt processing code.
  666. ZZZ This routine is *not* portable. It is specific to NT.
  667. Arguments:
  668. DPC - The control object associated with this routine.
  669. Context - Really a pointer to the adapter.
  670. SystemArgument1(2) - Neither of these arguments used.
  671. Return Value:
  672. None.
  673. --*/
  674. {
  675. ProcessInterrupt(Context);
  676. }
  677. static
  678. NDIS_STATUS
  679. Pc586OpenAdapter(
  680. OUT NDIS_HANDLE *MacBindingHandle,
  681. IN NDIS_HANDLE RequestHandle,
  682. IN NDIS_HANDLE NdisBindingContext,
  683. IN NDIS_HANDLE MacAdapterContext,
  684. IN PSTRING AddressingInformation OPTIONAL
  685. )
  686. /*++
  687. Routine Description:
  688. This routine is used to create an open instance of an adapter, in effect
  689. creating a binding between an upper-level module and the MAC module over
  690. the adapter.
  691. Arguments:
  692. MacBindingHandle - A pointer to a location in which the MAC stores
  693. a context value that it uses to represent this binding.
  694. RequestHandle - A value supplied by the NDIS interface that the MAC
  695. must use when completing this request with the NdisCompleteRequest
  696. service, if the MAC completes this request asynchronously.
  697. NdisBindingContext - A value to be recorded by the MAC and passed as
  698. context whenever an indication is delivered by the MAC for this binding.
  699. MacAdapterContext - The value associated with the adapter that is being
  700. opened when the MAC registered the adapter with NdisRegisterAdapter.
  701. AddressingInformation - An optional pointer to a variable length string
  702. containing hardware-specific information that can be used to program the
  703. device. (This is not used by this MAC.)
  704. Return Value:
  705. The function value is the status of the operation. If the MAC does not
  706. complete this request synchronously, the value would be
  707. NDIS_STATUS_PENDING.
  708. --*/
  709. {
  710. //
  711. // The PC586_ADAPTER that this open binding should belong too.
  712. //
  713. PPC586_ADAPTER Adapter;
  714. //
  715. // Holds the status that should be returned to the caller.
  716. //
  717. NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  718. Adapter = PPC586_ADAPTER_FROM_CONTEXT_HANDLE(MacAdapterContext);
  719. NdisAcquireSpinLock(&Adapter->Lock);
  720. Adapter->References++;
  721. if (!Adapter->ResetInProgress) {
  722. //
  723. // Pointer to the space allocated for the binding.
  724. //
  725. PPC586_OPEN NewOpen;
  726. NdisReleaseSpinLock(&Adapter->Lock);
  727. //
  728. // Allocate the space for the open binding. Fill in the fields.
  729. //
  730. NewOpen = PC586_ALLOC_PHYS(sizeof(PC586_OPEN));
  731. *MacBindingHandle = BINDING_HANDLE_FROM_PPC586_OPEN(NewOpen);
  732. InitializeListHead(&NewOpen->OpenList);
  733. NewOpen->NdisBindingContext = NdisBindingContext;
  734. NewOpen->References = 0;
  735. NewOpen->BindingShuttingDown = FALSE;
  736. NewOpen->OwningPc586 = Adapter;
  737. NdisAcquireSpinLock(&Adapter->Lock);
  738. if (Adapter->ResetInProgress || !MacNoteFilterOpenAdapter(
  739. NewOpen->OwningPc586->FilterDB,
  740. NewOpen,
  741. NdisBindingContext,
  742. &NewOpen->FilterIndex
  743. )) {
  744. NdisReleaseSpinLock(&Adapter->Lock);
  745. PC586_FREE_PHYS(NewOpen);
  746. StatusToReturn = NDIS_STATUS_FAILURE;
  747. NdisAcquireSpinLock(&Adapter->Lock);
  748. } else {
  749. //
  750. // Everything has been filled in. Synchronize access to the
  751. // adapter block and link the new open adapter in and increment
  752. // the opens reference count to account for the fact that the
  753. // filter routines have a "reference" to the open.
  754. //
  755. InsertTailList(&Adapter->OpenBindings,&NewOpen->OpenList);
  756. NewOpen->References++;
  757. }
  758. } else {
  759. StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
  760. }
  761. PC586_DO_DEFERRED(Adapter);
  762. return StatusToReturn;
  763. }
  764. static
  765. NDIS_STATUS
  766. Pc586CloseAdapter(
  767. IN NDIS_HANDLE MacBindingHandle,
  768. IN NDIS_HANDLE RequestHandle
  769. )
  770. /*++
  771. Routine Description:
  772. This routine causes the MAC to close an open handle (binding).
  773. Arguments:
  774. MacBindingHandle - The context value returned by the MAC when the
  775. adapter was opened. In reality it is a PPC586_OPEN.
  776. RequestHandle - A value supplied by the NDIS interface that the
  777. MAC must use when completing this request with the NdisCompleteRequest
  778. service, if the MAC completes this request asynchronously.
  779. Return Value:
  780. The function value is the status of the operation.
  781. --*/
  782. {
  783. PPC586_ADAPTER Adapter;
  784. NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  785. Adapter = PPC586_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
  786. //
  787. // Hold the lock while we update the reference counts for the
  788. // adapter and the open.
  789. //
  790. NdisAcquireSpinLock(&Adapter->Lock);
  791. Adapter->References++;
  792. if (!Adapter->ResetInProgress) {
  793. PPC586_OPEN Open;
  794. Open = PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
  795. if (!Open->BindingShuttingDown) {
  796. Open->References++;
  797. StatusToReturn = MacDeleteFilterOpenAdapter(
  798. Adapter->FilterDB,
  799. Open->FilterIndex,
  800. RequestHandle
  801. );
  802. //
  803. // If the status is successful that merely implies that
  804. // we were able to delete the reference to the open binding
  805. // from the filtering code. If we have a successful status
  806. // at this point we still need to check whether the reference
  807. // count to determine whether we can close.
  808. //
  809. //
  810. // The delete filter routine can return a "special" status
  811. // that indicates that there is a current NdisIndicateReceive
  812. // on this binding. See below.
  813. //
  814. if (StatusToReturn == NDIS_STATUS_SUCCESS) {
  815. //
  816. // Check whether the reference count is two. If
  817. // it is then we can get rid of the memory for
  818. // this open.
  819. //
  820. // A count of two indicates one for this routine
  821. // and one for the filter which we *know* we can
  822. // get rid of.
  823. //
  824. if (Open->References == 2) {
  825. RemoveEntryList(&Open->OpenList);
  826. //
  827. // We are the only reference to the open. Remove
  828. // it from the open list and delete the memory.
  829. //
  830. RemoveEntryList(&Open->OpenList);
  831. PC586_FREE_PHYS(Open);
  832. } else {
  833. Open->CloseHandle = RequestHandle;
  834. Open->BindingShuttingDown = TRUE;
  835. //
  836. // Remove the open from the open list and put it on
  837. // the closing list.
  838. //
  839. RemoveEntryList(&Open->OpenList);
  840. InsertTailList(&Adapter->CloseList,&Open->OpenList);
  841. //
  842. // Account for this routines reference to the open
  843. // as well as reference because of the filtering.
  844. //
  845. Open->References -= 2;
  846. //
  847. // Change the status to indicate that we will
  848. // be closing this later.
  849. //
  850. StatusToReturn = NDIS_STATUS_PENDING;
  851. }
  852. } else if (StatusToReturn == NDIS_STATUS_PENDING) {
  853. Open->CloseHandle = RequestHandle;
  854. Open->BindingShuttingDown = TRUE;
  855. //
  856. // Remove the open from the open list and put it on
  857. // the closing list.
  858. //
  859. RemoveEntryList(&Open->OpenList);
  860. InsertTailList(&Adapter->CloseList,&Open->OpenList);
  861. //
  862. // Account for this routines reference to the open
  863. // as well as reference because of the filtering.
  864. //
  865. Open->References -= 2;
  866. } else if (StatusToReturn == NDIS_STATUS_CLOSING_INDICATING) {
  867. //
  868. // When we have this status it indicates that the filtering
  869. // code was currently doing an NdisIndicateReceive. It
  870. // would not be wise to delete the memory for the open at
  871. // this point. The filtering code will call our close action
  872. // routine upon return from NdisIndicateReceive and that
  873. // action routine will decrement the reference count for
  874. // the open.
  875. //
  876. Open->CloseHandle = RequestHandle;
  877. Open->BindingShuttingDown = TRUE;
  878. //
  879. // This status is private to the filtering routine. Just
  880. // tell the caller the the close is pending.
  881. //
  882. StatusToReturn = NDIS_STATUS_PENDING;
  883. //
  884. // Remove the open from the open list and put it on
  885. // the closing list.
  886. //
  887. RemoveEntryList(&Open->OpenList);
  888. InsertTailList(&Adapter->CloseList,&Open->OpenList);
  889. //
  890. // Account for this routines reference to the open.
  891. //
  892. Open->References--;
  893. } else {
  894. //
  895. // Account for this routines reference to the open.
  896. //
  897. Open->References--;
  898. }
  899. } else {
  900. StatusToReturn = NDIS_CLOSING;
  901. }
  902. } else {
  903. StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
  904. }
  905. PC586_DO_DEFERRED(Adapter);
  906. return StatusToReturn;
  907. }
  908. static
  909. NDIS_STATUS
  910. Pc586SetPacketFilter(
  911. IN NDIS_HANDLE MacBindingHandle,
  912. IN NDIS_HANDLE RequestHandle,
  913. IN UINT PacketFilter
  914. )
  915. /*++
  916. Routine Description:
  917. The Pc586SetPacketFilter request allows a protocol to control the types
  918. of packets that it receives from the MAC.
  919. Arguments:
  920. MacBindingHandle - The context value returned by the MAC when the
  921. adapter was opened. In reality, it is a pointer to PC586_OPEN.
  922. RequestHandle - A value supplied by the NDIS interface that the MAC
  923. must use when completing this request with the NdisCompleteRequest
  924. service, if the MAC completes this request asynchronously.
  925. PacketFilter - A bit mask that contains flags that correspond to specific
  926. classes of received packets. If a particular bit is set in the mask,
  927. then packet reception for that class of packet is enabled. If the
  928. bit is clear, then packets that fall into that class are not received
  929. by the client. A single exception to this rule is that if the promiscuous
  930. bit is set, then the client receives all packets on the network, regardless
  931. of the state of the other flags.
  932. Return Value:
  933. The function value is the status of the operation.
  934. --*/
  935. {
  936. //
  937. // Keeps track of the *MAC's* status. The status will only be
  938. // reset if the filter change action routine is called.
  939. //
  940. NDIS_STATUS StatusOfFilterChange = NDIS_STATUS_SUCCESS;
  941. //
  942. // Points to the adapter that this request is coming through.
  943. //
  944. PPC586_ADAPTER Adapter;
  945. Adapter = PPC586_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
  946. NdisAcquireSpinLock(&Adapter->Lock);
  947. Adapter->References++;
  948. if (!Adapter->ResetInProgress) {
  949. //
  950. // Pointer to the open that is changing the packet filters.
  951. //
  952. PPC586_OPEN Open = PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
  953. if (!Open->BindingShuttingDown) {
  954. //
  955. // Increment the open while it is going through the filtering
  956. // routines.
  957. //
  958. Open->References++;
  959. StatusOfFilterChange = MacFilterAdjust(
  960. Adapter->FilterDB,
  961. Open->FilterIndex,
  962. RequestHandle,
  963. PacketFilter,
  964. TRUE
  965. );
  966. Open->References--;
  967. } else {
  968. StatusOfFilterChange = NDIS_CLOSING;
  969. }
  970. } else {
  971. StatusOfFilterChange = NDIS_STATUS_RESET_IN_PROGRESS;
  972. }
  973. PC586_DO_DEFERRED(Adapter);
  974. return StatusOfFilterChange;
  975. }
  976. static
  977. NDIS_STATUS
  978. Pc586AddMulticastAddress(
  979. IN NDIS_HANDLE MacBindingHandle,
  980. IN NDIS_HANDLE RequestHandle,
  981. IN PSTRING MulticastAddress
  982. )
  983. /*++
  984. Routine Description:
  985. The Pc586AddMulticastAddress request adds a multicast address
  986. to the list of multicast/functional addresses that are enabled
  987. for packet reception. The address may subsequently be deleted
  988. using the Pc586DeleteMulticastAddress request.
  989. Arguments:
  990. MacBindingHandle - The context value returned by the MAC when the
  991. adapter was opened. In reality, it is a pointer to PC586_OPEN.
  992. RequestHandle - A value supplied by the NDIS interface that the MAC
  993. must use when completing this request with the NdisCompleteRequest
  994. service, if the MAC completes this request asynchronously.
  995. MulticastAddress - A pointer to a variable-length counted string
  996. containing the multicast or functional address as it appears in storage
  997. when received from the adapter. When specifying multicast or functional
  998. addresses, the multicast/functional address bit is automatically provided
  999. by the MAC itself; it is not necessary, by it is acceptable, to specify
  1000. the string.
  1001. Return Value:
  1002. The function value is the status of the operation.
  1003. --*/
  1004. {
  1005. //
  1006. // We call the filter database to add the address. If the
  1007. // address was already in the database then the call can be
  1008. // completed right away. If the address wasn't in the database then
  1009. // the action routine will be called. The action routine will be
  1010. // responsible for setting up any deferred processing.
  1011. //
  1012. NDIS_STATUS StatusOfAdd;
  1013. //
  1014. // Points to the adapter that this request is coming through.
  1015. //
  1016. PPC586_ADAPTER Adapter;
  1017. Adapter = PPC586_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
  1018. NdisAcquireSpinLock(&Adapter->Lock);
  1019. Adapter->References++;
  1020. if (!Adapter->ResetInProgress) {
  1021. PPC586_OPEN Open;
  1022. Open = PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
  1023. if (!Open->BindingShuttingDown) {
  1024. Open->References++;
  1025. StatusOfAdd = MacAddFilterAddress(
  1026. Open->OwningPc586->FilterDB,
  1027. Open->FilterIndex,
  1028. RequestHandle,
  1029. MulticastAddress->Buffer
  1030. );
  1031. Open->References--;
  1032. } else {
  1033. StatusOfAdd = NDIS_CLOSING;
  1034. }
  1035. } else {
  1036. StatusOfAdd = NDIS_STATUS_RESET_IN_PROGRESS;
  1037. }
  1038. PC586_DO_DEFERRED(Adapter);
  1039. return StatusOfAdd;
  1040. }
  1041. static
  1042. NDIS_STATUS
  1043. Pc586DeleteMulticastAddress(
  1044. IN NDIS_HANDLE MacBindingHandle,
  1045. IN NDIS_HANDLE RequestHandle,
  1046. IN PSTRING MulticastAddress
  1047. )
  1048. /*++
  1049. Routine Description:
  1050. The MacDeleteMulticastAddress request removes a multicast or functional
  1051. address from the list of multicast/functional addresses that are enabled
  1052. for packet reception. Once an address is removed from the list, packets
  1053. will no longer be received by the binding when they are directed to that
  1054. address.
  1055. Arguments:
  1056. MacBindingHandle - The context value returned by the MAC when the
  1057. adapter was opened. In reality, it is a pointer to PC586_OPEN.
  1058. RequestHandle - A value supplied by the NDIS interface that the MAC
  1059. must use when completing this request with the NdisCompleteRequest
  1060. service, if the MAC completes this request asynchronously.
  1061. MulticastAddress - A pointer to a variable-length counted string
  1062. containing the multicast or functional address as it appears in storage
  1063. when received from the adapter. When specifying multicast or functional
  1064. addresses, the multicast/functional address bit is automatically provided
  1065. by the MAC itself; it is not necessary, by it is acceptable, to specify
  1066. the string.
  1067. Return Value:
  1068. The function value is the status of the operation.
  1069. --*/
  1070. {
  1071. //
  1072. // We call the filter database to delete the address. If this
  1073. // is the last reference to the address then the delete address
  1074. // action routine is called.
  1075. //
  1076. NDIS_STATUS StatusOfDelete;
  1077. //
  1078. // Points to the adapter that this request is coming through.
  1079. //
  1080. PPC586_ADAPTER Adapter;
  1081. Adapter = PPC586_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
  1082. NdisAcquireSpinLock(&Adapter->Lock);
  1083. Adapter->References++;
  1084. if (!Adapter->ResetInProgress) {
  1085. PPC586_OPEN Open;
  1086. Open = PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
  1087. if (!Open->BindingShuttingDown) {
  1088. Open->References++;
  1089. StatusOfDelete = MacDeleteFilterAddress(
  1090. Open->OwningPc586->FilterDB,
  1091. Open->FilterIndex,
  1092. RequestHandle,
  1093. MulticastAddress->Buffer
  1094. );
  1095. Open->References--;
  1096. } else {
  1097. StatusOfDelete = NDIS_CLOSING;
  1098. }
  1099. } else {
  1100. StatusOfDelete = NDIS_STATUS_RESET_IN_PROGRESS;
  1101. }
  1102. PC586_DO_DEFERRED(Adapter);
  1103. return StatusOfDelete;
  1104. }
  1105. static
  1106. NDIS_STATUS
  1107. Pc586QueryInformation(
  1108. IN NDIS_HANDLE MacBindingHandle,
  1109. IN NDIS_HANDLE RequestHandle,
  1110. IN NDIS_INFORMATION_CLASS InformationClass,
  1111. OUT PVOID Buffer,
  1112. IN UINT BufferLength
  1113. )
  1114. /*++
  1115. Routine Description:
  1116. The Pc586QueryInformation request allows a protocol to inspect
  1117. the MAC's capabilities and current status. See the description
  1118. of NdisQueryInformation for a detailed description of this request.
  1119. Arguments:
  1120. MacBindingHandle - The context value returned by the MAC when the
  1121. adapter was opened. In reality, it is a pointer to PC586_OPEN.
  1122. RequestHandle - A value supplied by the NDIS interface that the MAC
  1123. must use when completing this request with the NdisCompleteRequest
  1124. service, if the MAC completes this request asynchronously.
  1125. InformationClass - A value indicating the class of the information
  1126. to be queried. See the description of NdisQueryInformation for valid
  1127. values.
  1128. Buffer - A pointer to a buffer into which the MAC copies the information.
  1129. See the description of NdisQueryInformation for buffer formats.
  1130. BufferLength - An unsigned integer specifying the maximum length of
  1131. the information buffer, in bytes.
  1132. Return Value:
  1133. The function value is the status of the operation.
  1134. --*/
  1135. {
  1136. PPC586_ADAPTER Adapter;
  1137. NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  1138. Adapter = PPC586_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
  1139. //
  1140. // Get and hold the lock while we update the reference counts.
  1141. //
  1142. NdisAcquireSpinLock(&Adapter->Lock);
  1143. Adapter->References++;
  1144. if (!Adapter->ResetInProgress) {
  1145. PPC586_OPEN Open;
  1146. Open = PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
  1147. if (!Open->BindingShuttingDown) {
  1148. Open->References++;
  1149. //
  1150. // The only information request that we actually support
  1151. // is the info identification service.
  1152. //
  1153. switch(InformationClass) {
  1154. case NdisInfoStationAddress:
  1155. case NdisInfoFunctionalAddress:
  1156. //
  1157. // Ensure that we have enough room to return the
  1158. // information.
  1159. //
  1160. if (BufferLength < MAC_LENGTH_OF_ADDRESS) {
  1161. StatusToReturn = NDIS_STATUS_FAILURE;
  1162. } else {
  1163. MAC_COPY_NETWORK_ADDRESS(
  1164. (PCHAR)Buffer,
  1165. (PCHAR)Adapter->NetworkAddress
  1166. );
  1167. }
  1168. break;
  1169. case NdisInfoIdentification:
  1170. //
  1171. // Let the protocol know that we adhere
  1172. // to the IEEE 802.3 communications standard.
  1173. //
  1174. // In addition return the ndis version.
  1175. //
  1176. if (BufferLength < sizeof(NDIS_INFO_IDENTIFICATION)) {
  1177. StatusToReturn = NDIS_STATUS_FAILURE;
  1178. break;
  1179. }
  1180. ((PNDIS_INFO_IDENTIFICATION)Buffer)->NdisVersion = 3;
  1181. ((PNDIS_INFO_IDENTIFICATION)Buffer)->MediumType =
  1182. NdisMedium802_3;
  1183. StatusToReturn = NDIS_STATUS_SUCCESS;
  1184. break;
  1185. default:
  1186. //
  1187. // ZZZ Need to implement query information services.
  1188. //
  1189. DbgPrint("PC586 - Information not yet implemented.\n");
  1190. StatusToReturn = NDIS_STATUS_FAILURE;
  1191. break;
  1192. }
  1193. Open->References--;
  1194. } else {
  1195. StatusToReturn = NDIS_CLOSING;
  1196. }
  1197. } else {
  1198. StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
  1199. }
  1200. PC586_DO_DEFERRED(Adapter);
  1201. return StatusToReturn;
  1202. }
  1203. static
  1204. NDIS_STATUS
  1205. Pc586SetInformation(
  1206. IN NDIS_HANDLE MacBindingHandle,
  1207. IN NDIS_HANDLE RequestHandle,
  1208. IN NDIS_INFORMATION_CLASS InformationClass,
  1209. IN PVOID Buffer,
  1210. IN UINT BufferLength
  1211. )
  1212. /*++
  1213. Routine Description:
  1214. The Pc586SetInformation request allows a protocol to control the MAC
  1215. by changing information maintained by the MAC. See the description
  1216. of NdisSetInformation for a detailed description of this request.
  1217. Arguments:
  1218. MacBindingHandle - The context value returned by the MAC when the
  1219. adapter was opened. In reality, it is a pointer to PC586_OPEN.
  1220. RequestHandle - A value supplied by the NDIS interface that the MAC
  1221. must use when completing this request with the NdisCompleteRequest
  1222. service, if the MAC completes this request asynchronously.
  1223. InformationClass - A value indicating the class of the information
  1224. to be set. See the description of NdisSetInformation for valid
  1225. values.
  1226. Buffer - A pointer to a buffer containg the information for the specified
  1227. class. See the description of NdisSetInformation for buffer formats.
  1228. BufferLength - An unsigned integer specifying the maximum length of
  1229. the information buffer, in bytes.
  1230. Return Value:
  1231. The function value is the status of the operation.
  1232. --*/
  1233. {
  1234. PPC586_ADAPTER Adapter;
  1235. NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  1236. Adapter = PPC586_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
  1237. //
  1238. // Hold the lock while we update the reference counts for the
  1239. // adapter and the open.
  1240. //
  1241. NdisAcquireSpinLock(&Adapter->Lock);
  1242. Adapter->References++;
  1243. if (!Adapter->ResetInProgress) {
  1244. PPC586_OPEN Open;
  1245. Open = PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
  1246. if (!Open->BindingShuttingDown) {
  1247. //
  1248. // ZZZ Need to implement set information services.
  1249. //
  1250. DbgPrint("PC586 - MacSetInformation not yet implemented.\n");
  1251. StatusToReturn = NDIS_STATUS_FAILURE;
  1252. } else {
  1253. StatusToReturn = NDIS_CLOSING;
  1254. }
  1255. } else {
  1256. StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
  1257. }
  1258. PC586_DO_DEFERRED(Adapter);
  1259. return StatusToReturn;
  1260. }
  1261. static
  1262. NDIS_STATUS
  1263. Pc586Reset(
  1264. IN NDIS_HANDLE MacBindingHandle,
  1265. IN NDIS_HANDLE RequestHandle
  1266. )
  1267. /*++
  1268. Routine Description:
  1269. The Pc586Reset request instructs the MAC to issue a hardware reset
  1270. to the network adapter. The MAC also resets its software state. See
  1271. the description of NdisReset for a detailed description of this request.
  1272. Arguments:
  1273. MacBindingHandle - The context value returned by the MAC when the
  1274. adapter was opened. In reality, it is a pointer to PC586_OPEN.
  1275. RequestHandle - A value supplied by the NDIS interface that the MAC
  1276. must use when completing this request with the NdisCompleteRequest
  1277. service, if the MAC completes this request asynchronously.
  1278. Return Value:
  1279. The function value is the status of the operation.
  1280. --*/
  1281. {
  1282. //
  1283. // Holds the status that should be returned to the caller.
  1284. //
  1285. NDIS_STATUS StatusToReturn = NDIS_STATUS_PENDING;
  1286. PPC586_ADAPTER Adapter =
  1287. PPC586_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
  1288. //
  1289. // Hold the locks while we update the reference counts on the
  1290. // adapter and the open.
  1291. //
  1292. NdisAcquireSpinLock(&Adapter->Lock);
  1293. Adapter->References++;
  1294. if (!Adapter->ResetInProgress) {
  1295. PPC586_OPEN Open;
  1296. Open = PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
  1297. if (!Open->BindingShuttingDown) {
  1298. Open->References++;
  1299. SetupForReset(
  1300. Adapter,
  1301. PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle),
  1302. RequestHandle,
  1303. NdisRequestReset
  1304. );
  1305. Open->References--;
  1306. } else {
  1307. StatusToReturn = NDIS_CLOSING;
  1308. }
  1309. } else {
  1310. StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
  1311. }
  1312. PC586_DO_DEFERRED(Adapter);
  1313. return StatusToReturn;
  1314. }
  1315. static
  1316. NDIS_STATUS
  1317. Pc586Test(
  1318. IN NDIS_HANDLE MacBindingHandle,
  1319. IN NDIS_HANDLE RequestHandle
  1320. )
  1321. /*++
  1322. Routine Description:
  1323. The Pc586Test request instructs the MAC to run hardware diagnostics
  1324. on the underlying network adapter without resetting the adapter.
  1325. Arguments:
  1326. MacBindingHandle - The context value returned by the MAC when the
  1327. adapter was opened. In reality, it is a pointer to PC586_OPEN.
  1328. RequestHandle - A value supplied by the NDIS interface that the MAC
  1329. must use when completing this request with the NdisCompleteRequest
  1330. service, if the MAC completes this request asynchronously.
  1331. Return Value:
  1332. The function value is the status of the operation.
  1333. --*/
  1334. {
  1335. PPC586_ADAPTER Adapter;
  1336. NDIS_STATUS StatusToReturn = NDIS_STATUS_SUCCESS;
  1337. Adapter = PPC586_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
  1338. //
  1339. // Hold the lock while we update the reference counts for the
  1340. // adapter and the open.
  1341. //
  1342. NdisAcquireSpinLock(&Adapter->Lock);
  1343. Adapter->References++;
  1344. if (!Adapter->ResetInProgress) {
  1345. PPC586_OPEN Open;
  1346. Open = PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle);
  1347. if (!Open->BindingShuttingDown) {
  1348. //
  1349. // ZZZ Need to implement test information service.
  1350. //
  1351. StatusToReturn = NDIS_STATUS_NOT_TESTABLE;
  1352. } else {
  1353. StatusToReturn = NDIS_CLOSING;
  1354. }
  1355. } else {
  1356. StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS;
  1357. }
  1358. PC586_DO_DEFERRED(Adapter);
  1359. return StatusToReturn;
  1360. }
  1361. static
  1362. NDIS_STATUS
  1363. Pc586ChangeClass(
  1364. IN UINT OldFilterClasses,
  1365. IN UINT NewFilterClasses,
  1366. IN NDIS_HANDLE MacBindingHandle,
  1367. IN NDIS_HANDLE RequestHandle,
  1368. IN BOOLEAN Set
  1369. )
  1370. /*++
  1371. Routine Description:
  1372. Action routine that will get called when a particular filter
  1373. class is first used or last cleared.
  1374. NOTE: This routine assumes that it is called with the lock
  1375. acquired.
  1376. Arguments:
  1377. OldFilterClasses - The values of the class filter before it
  1378. was changed.
  1379. NewFilterClasses - The current value of the class filter
  1380. MacBindingHandle - The context value returned by the MAC when the
  1381. adapter was opened. In reality, it is a pointer to PC586_OPEN.
  1382. RequestHandle - A value supplied by the NDIS interface that the MAC
  1383. must use when completing this request with the NdisCompleteRequest
  1384. service, if the MAC completes this request asynchronously.
  1385. Set - If true the change resulted from a set, otherwise the
  1386. change resulted from a open closing.
  1387. Return Value:
  1388. None.
  1389. --*/
  1390. {
  1391. PPC586_ADAPTER Adapter = PPC586_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
  1392. //
  1393. // Holds the change that should be returned to the filtering package.
  1394. //
  1395. NDIS_STATUS StatusOfChange;
  1396. if (Adapter->ResetInProgress) {
  1397. StatusOfChange = NDIS_STATUS_RESET_IN_PROGRESS;
  1398. } else {
  1399. //
  1400. // This local will hold the actual changes that occurred
  1401. // in the packet filtering that are of real interest.
  1402. //
  1403. UINT PacketChanges;
  1404. //
  1405. // The whole purpose of this routine is to determine whether
  1406. // the filtering changes need to result in the hardware being
  1407. // reset.
  1408. //
  1409. ASSERT(OldFilterClasses != NewFilterClasses);
  1410. //
  1411. // We only need to reset if there is a change of "state" with
  1412. // multicast, all multicast, or promiscuous.
  1413. //
  1414. PacketChanges = (OldFilterClasses ^ NewFilterClasses) &
  1415. (NDIS_PACKET_TYPE_PROMISCUOUS |
  1416. NDIS_PACKET_TYPE_ALL_MULTICAST |
  1417. NDIS_PACKET_TYPE_MULTICAST);
  1418. StatusOfChange = NDIS_STATUS_SUCCESS;
  1419. if (PacketChanges) {
  1420. //
  1421. // We had some "important" change. We first check to see if
  1422. // promiscuous filtering or all multicast has changed.
  1423. //
  1424. // Otherwise multicast addressing is changing. We only need
  1425. // to reset the hardware if somebody isn't already filtering for
  1426. // all multicast or promiscuous (which the above tests do
  1427. // *NOT* test for) and there are any multicast addresses.
  1428. //
  1429. if ((PacketChanges & NDIS_PACKET_TYPE_PROMISCUOUS) ||
  1430. (PacketChanges & NDIS_PACKET_TYPE_ALL_MULTICAST) ||
  1431. ((!(NewFilterClasses & (NDIS_PACKET_TYPE_PROMISCUOUS |
  1432. NDIS_PACKET_TYPE_ALL_MULTICAST))) &&
  1433. MAC_NUMBER_OF_FILTER_ADDRESSES(Adapter->FilterDB)
  1434. )) {
  1435. SetupForReset(
  1436. Adapter,
  1437. PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle),
  1438. RequestHandle,
  1439. NdisRequestSetPacketFilter
  1440. );
  1441. StatusOfChange = NDIS_STATUS_PENDING;
  1442. }
  1443. }
  1444. }
  1445. return StatusOfChange;
  1446. }
  1447. static
  1448. NDIS_STATUS
  1449. Pc586AddMulticast(
  1450. IN UINT CurrentAddressCount,
  1451. IN CHAR CurrentAddresses[][MAC_LENGTH_OF_ADDRESS],
  1452. IN UINT NewAddress,
  1453. IN NDIS_HANDLE MacBindingHandle,
  1454. IN NDIS_HANDLE RequestHandle
  1455. )
  1456. /*++
  1457. Routine Description:
  1458. Action routine that will get called when an address is added to
  1459. the filter that wasn't referenced by any other open binding.
  1460. NOTE: This routine assumes that it is called with the lock
  1461. acquired.
  1462. Arguments:
  1463. CurrentAddressCount - The number of addresses in the address array.
  1464. CurrentAddresses - An array of multicast addresses. Note that this
  1465. array already contains the new address.
  1466. NewAddress - The index in the array where the new address can be
  1467. located.
  1468. MacBindingHandle - The context value returned by the MAC when the
  1469. adapter was opened. In reality, it is a pointer to PC586_OPEN.
  1470. RequestHandle - A value supplied by the NDIS interface that the MAC
  1471. must use when completing this request with the NdisCompleteRequest
  1472. service, if the MAC completes this request asynchronously.
  1473. Return Value:
  1474. None.
  1475. --*/
  1476. {
  1477. PPC586_ADAPTER Adapter = PPC586_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
  1478. //
  1479. // Holds the status that should be returned to the filtering package.
  1480. //
  1481. NDIS_STATUS StatusOfAdd;
  1482. //
  1483. // Check to see if the device is already resetting. If it is
  1484. // then reject this add.
  1485. //
  1486. if (Adapter->ResetInProgress) {
  1487. StatusOfAdd = NDIS_STATUS_RESET_IN_PROGRESS;
  1488. } else {
  1489. UINT PacketFilters;
  1490. PacketFilters = MAC_QUERY_FILTER_CLASSES(Adapter->FilterDB);
  1491. //
  1492. // We don't need to do a reset if an open is promiscuous or
  1493. // an open is already accepting all multicast addresses.
  1494. //
  1495. if ((PacketFilters & NDIS_PACKET_TYPE_PROMISCUOUS) ||
  1496. (PacketFilters & NDIS_PACKET_TYPE_ALL_MULTICAST)) {
  1497. StatusOfAdd = NDIS_STATUS_SUCCESS;
  1498. } else {
  1499. //
  1500. // Make sure that multicast addresses are actually enabled.
  1501. // If not then there is no point in resetting.
  1502. //
  1503. if (PacketFilters & NDIS_PACKET_TYPE_MULTICAST) {
  1504. //
  1505. // We need to add this to the hardware multicast filtering.
  1506. //
  1507. SetupForReset(
  1508. Adapter,
  1509. PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle),
  1510. RequestHandle,
  1511. NdisRequestAddMulticast
  1512. );
  1513. StatusOfAdd = NDIS_STATUS_PENDING;
  1514. } else {
  1515. StatusOfAdd = NDIS_STATUS_SUCCESS;
  1516. }
  1517. }
  1518. }
  1519. return StatusOfAdd;
  1520. }
  1521. static
  1522. NDIS_STATUS
  1523. Pc586DeleteMulticast(
  1524. IN UINT CurrentAddressCount,
  1525. IN CHAR CurrentAddresses[][MAC_LENGTH_OF_ADDRESS],
  1526. IN CHAR OldAddress[MAC_LENGTH_OF_ADDRESS],
  1527. IN NDIS_HANDLE MacBindingHandle,
  1528. IN NDIS_HANDLE RequestHandle
  1529. )
  1530. /*++
  1531. Routine Description:
  1532. Action routine that will get called when a particular multicast
  1533. address is deleted for the last time.
  1534. NOTE: This routine assumes that it is called with the lock acquired.
  1535. Arguments:
  1536. CurrentAddressCount - The number of addresses in the address array.
  1537. CurrentAddresses - An array of multicast addresses. Note that this
  1538. array does not contain the old address.
  1539. OldAddress - The address that was deleted from the address filter.
  1540. MacBindingHandle - The context value returned by the MAC when the
  1541. adapter was opened. In reality, it is a pointer to PC586_OPEN.
  1542. RequestHandle - A value supplied by the NDIS interface that the MAC
  1543. must use when completing this request with the NdisCompleteRequest
  1544. service, if the MAC completes this request asynchronously.
  1545. Return Value:
  1546. None.
  1547. --*/
  1548. {
  1549. PPC586_ADAPTER Adapter = PPC586_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle);
  1550. //
  1551. // Holds the status that should be returned to the filtering
  1552. // package.
  1553. //
  1554. NDIS_STATUS StatusOfDelete;
  1555. //
  1556. // Check to see if the device is already resetting. If it is
  1557. // then reject this delete if the reset isn't coming from
  1558. // this MacBindingHandle. The reason we care about the binding
  1559. // handle is that when an open closes we may getting rid of multiple
  1560. // multicast addresses at one time.
  1561. //
  1562. if (Adapter->ResetInProgress) {
  1563. if (Adapter->ResettingOpen !=
  1564. PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle)) {
  1565. StatusOfDelete = NDIS_STATUS_RESET_IN_PROGRESS;
  1566. } else {
  1567. //
  1568. // If this open is causing the reset then any further deletes
  1569. // can only be pending (as was the first delete).
  1570. //
  1571. StatusOfDelete = NDIS_STATUS_PENDING;
  1572. }
  1573. } else {
  1574. UINT PacketFilters;
  1575. PacketFilters = MAC_QUERY_FILTER_CLASSES(Adapter->FilterDB);
  1576. //
  1577. // We don't need to do a reset if an open is promiscuous or
  1578. // an open is already accepting all multicast addresses.
  1579. //
  1580. if ((PacketFilters & NDIS_PACKET_TYPE_PROMISCUOUS) ||
  1581. (PacketFilters & NDIS_PACKET_TYPE_ALL_MULTICAST)) {
  1582. StatusOfDelete = NDIS_STATUS_SUCCESS;
  1583. } else {
  1584. //
  1585. // Make sure that multicast filtering is actually enabled
  1586. // since if multicast isn't then there is not point in
  1587. // resetting since nobody wants multicast addresses.
  1588. //
  1589. if (PacketFilters & NDIS_PACKET_TYPE_MULTICAST) {
  1590. //
  1591. // We need to delete this from the hardware multicast
  1592. // filtering.
  1593. //
  1594. SetupForReset(
  1595. Adapter,
  1596. PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle),
  1597. RequestHandle,
  1598. NdisRequestDeleteMulticast
  1599. );
  1600. StatusOfDelete = NDIS_STATUS_PENDING;
  1601. } else {
  1602. StatusOfDelete = NDIS_STATUS_SUCCESS;
  1603. }
  1604. }
  1605. }
  1606. return StatusOfDelete;
  1607. }
  1608. static
  1609. VOID
  1610. Pc586CloseAction(
  1611. IN NDIS_HANDLE MacBindingHandle
  1612. )
  1613. /*++
  1614. Routine Description:
  1615. Action routine that will get called when a particular binding
  1616. was closed while it was indicating through NdisIndicateReceive
  1617. All this routine needs to do is to decrement the reference count
  1618. of the binding.
  1619. NOTE: This routine assumes that it is called with the lock acquired.
  1620. Arguments:
  1621. MacBindingHandle - The context value returned by the MAC when the
  1622. adapter was opened. In reality, it is a pointer to PC586_OPEN.
  1623. Return Value:
  1624. None.
  1625. --*/
  1626. {
  1627. PPC586_OPEN_FROM_BINDING_HANDLE(MacBindingHandle)->References--;
  1628. }
  1629. static
  1630. VOID
  1631. ProcessInterrupt(
  1632. IN PPC586_ADAPTER Adapter
  1633. )
  1634. /*++
  1635. Routine Description:
  1636. Main routine for processing interrupts.
  1637. Arguments:
  1638. Adapter - The Adapter to process interrupts for.
  1639. Return Value:
  1640. None.
  1641. --*/
  1642. {
  1643. while (TRUE) {
  1644. NdisAcquireSpinLock(&Adapter->Lock);
  1645. if (Adapter->DoingProcessing) {
  1646. break;
  1647. } else {
  1648. //
  1649. // Check the interrupt source and other reasons
  1650. // for processing. If there are no reasons to
  1651. // process then exit this loop.
  1652. //
  1653. // Note that when we check the for processing sources
  1654. // that we "carefully" check to see if we are already
  1655. // processing one of the stage queues. We do this
  1656. // by checking the "AlreadyProcessingStageX" variables
  1657. // in the adapter. If any of these are true then
  1658. // we let whoever set that boolean take care of pushing
  1659. // the packet through the stage queues.
  1660. //
  1661. // By checking the "AlreadyProcessingStageX" variables
  1662. // we can prevent a possible priority inversion where
  1663. // we get "stuck" behind something that is processing
  1664. // at a lower priority level.
  1665. //
  1666. if (
  1667. (Adapter->Scb->ScbStatus &
  1668. (SCBINTMSK)) ||
  1669. Adapter->FirstLoopBack ||
  1670. (Adapter->ResetInProgress && (!Adapter->References)) ||
  1671. ((!(Adapter->AlreadyProcessingStage4 ||
  1672. Adapter->AlreadyProcessingStage3 ||
  1673. Adapter->AlreadyProcessingStage2)
  1674. ) &&
  1675. ((Adapter->FirstStage3Packet && Adapter->Stage4Open) ||
  1676. (Adapter->FirstStage2Packet && Adapter->Stage3Open) ||
  1677. (Adapter->FirstStage1Packet && Adapter->Stage2Open)
  1678. )
  1679. ) || (!IsListEmpty(&Adapter->CloseList))) {
  1680. Adapter->References++;
  1681. Adapter->DoingProcessing = TRUE;
  1682. } else {
  1683. break;
  1684. }
  1685. }
  1686. //
  1687. // Note that the following code depends on the fact that
  1688. // code above left the spinlock held.
  1689. //
  1690. //
  1691. // If we have a reset in progress and the adapters reference
  1692. // count is 1 (meaning no routine is in the interface and
  1693. // we are the only "active" interrupt processing routine) then
  1694. // it is safe to start the reset.
  1695. //
  1696. if (Adapter->ResetInProgress && (Adapter->References == 1)) {
  1697. StartAdapterReset(Adapter);
  1698. goto LoopBottom;
  1699. }
  1700. NdisReleaseSpinLock(&Adapter->Lock);
  1701. //
  1702. // note -- need to check for non-packet related errors.
  1703. //
  1704. //
  1705. // Check the interrupt vector and see if there are any
  1706. // more receives to process. After we process any
  1707. // other interrupt source we always come back to the top
  1708. // of the loop to check if any more receive packets have
  1709. // come in. This is to lessen the probability that we
  1710. // drop a receive.
  1711. //
  1712. if ( Adapter->Scb->ScbStatus & (SCBINTFR|SCBINTRNR) ) {
  1713. ProcessReceiveInterrupts(Adapter);
  1714. //
  1715. // We need to signal every open binding that the
  1716. // receives are complete. We increment the reference
  1717. // count on the open binding while we're doing indications
  1718. // so that the open can't be deleted out from under
  1719. // us while we're indicating (recall that we can't own
  1720. // the lock during the indication).
  1721. //
  1722. {
  1723. PPC586_OPEN Open;
  1724. PLIST_ENTRY CurrentLink;
  1725. NdisAcquireSpinLock(&Adapter->Lock);
  1726. CurrentLink = Adapter->OpenBindings.Flink;
  1727. while (CurrentLink != &Adapter->OpenBindings) {
  1728. Open = CONTAINING_RECORD(
  1729. CurrentLink,
  1730. PC586_OPEN,
  1731. OpenList
  1732. );
  1733. Open->References++;
  1734. NdisReleaseSpinLock(&Adapter->Lock);
  1735. NdisIndicateReceiveComplete(Open->NdisBindingContext);
  1736. NdisAcquireSpinLock(&Adapter->Lock);
  1737. Open->References--;
  1738. CurrentLink = CurrentLink->Flink;
  1739. }
  1740. NdisReleaseSpinLock(&Adapter->Lock);
  1741. }
  1742. }
  1743. //
  1744. // Process the transmit interrupts if there are any.
  1745. //
  1746. if ( Adapter->Scb->ScbStatus & (SCBINTCX|SCBINTCNA) ) {
  1747. ProcessTransmitInterrupts(Adapter);
  1748. Adapter->Scb->ScbCmd =
  1749. (USHORT)(Adapter->Scb->ScbStatus & (SCBINTCX|SCBINTCNA));
  1750. if (Adapter->Scb->ScbCmd) ChanAttn(Adapter);
  1751. }
  1752. //
  1753. // Only try to push a packet through the stage queues
  1754. // if somebody else isn't already doing it and
  1755. // there is some hope of moving some packets
  1756. // ahead.
  1757. //
  1758. NdisAcquireSpinLock(&Adapter->Lock);
  1759. if ((!(Adapter->AlreadyProcessingStage4 ||
  1760. Adapter->AlreadyProcessingStage3 ||
  1761. Adapter->AlreadyProcessingStage2)
  1762. ) &&
  1763. ((Adapter->FirstStage3Packet && Adapter->Stage4Open) ||
  1764. (Adapter->FirstStage2Packet && Adapter->Stage3Open) ||
  1765. (Adapter->FirstStage1Packet && Adapter->Stage2Open)
  1766. )
  1767. ) {
  1768. Pc586StagedAllocation(Adapter);
  1769. }
  1770. NdisReleaseSpinLock(&Adapter->Lock);
  1771. //
  1772. // Process the loopback queue.
  1773. //
  1774. // NOTE: Incase anyone ever figures out how to make this
  1775. // loop more reentriant, special care needs to be taken that
  1776. // loopback packets and regular receive packets are NOT being
  1777. // indicated at the same time. While the filter indication
  1778. // routines can handle this, I doubt that the transport can.
  1779. //
  1780. Pc586ProcessLoopback(Adapter);
  1781. //
  1782. // If there are any opens on the closing list and their
  1783. // reference counts are zero then complete the close and
  1784. // delete them from the list.
  1785. //
  1786. // ZZZ This really needs to be improved. Currently if
  1787. // there are any outstanding sends, they are not canceled.
  1788. //
  1789. NdisAcquireSpinLock(&Adapter->Lock);
  1790. if (!IsListEmpty(&Adapter->CloseList)) {
  1791. PPC586_OPEN Open;
  1792. Open = CONTAINING_RECORD(
  1793. Adapter->CloseList.Flink,
  1794. PC586_OPEN,
  1795. OpenList
  1796. );
  1797. if (!Open->References) {
  1798. NdisReleaseSpinLock(&Adapter->Lock);
  1799. NdisCompleteRequest(
  1800. Open->NdisBindingContext,
  1801. Open->CloseHandle,
  1802. NdisRequestCloseAdapter,
  1803. NDIS_STATUS_SUCCESS
  1804. );
  1805. NdisAcquireSpinLock(&Adapter->Lock);
  1806. RemoveEntryList(&Open->OpenList);
  1807. PC586_FREE_PHYS(Open);
  1808. }
  1809. }
  1810. //
  1811. // NOTE: This code assumes that the above code left
  1812. // the spinlock acquired.
  1813. //
  1814. // Bottom of the interrupt processing loop. Another dpc
  1815. // could be coming in at this point to process interrupts.
  1816. // We clear the flag that says we're processing interrupts
  1817. // so that some invocation of the DPC can grab it and process
  1818. // any further interrupts.
  1819. //
  1820. LoopBottom:;
  1821. Adapter->DoingProcessing = FALSE;
  1822. Adapter->References--;
  1823. NdisReleaseSpinLock(&Adapter->Lock);
  1824. }
  1825. //
  1826. // The only way to get out of the loop (via the break above) is
  1827. // while we're still holding the spin lock.
  1828. //
  1829. NdisReleaseSpinLock(&Adapter->Lock);
  1830. }
  1831. static
  1832. VOID
  1833. ProcessReceiveInterrupts(
  1834. IN PPC586_ADAPTER Adapter
  1835. )
  1836. /*++
  1837. Routine Description:
  1838. Process the packets that have finished receiving.
  1839. NOTE: This routine assumes that no other thread of execution
  1840. is processing receives!
  1841. Get all the enet packets the 586 has for the CPU and put them in
  1842. in NDIS buffers
  1843. Arguments:
  1844. Adapter - The adapter to indicate to.
  1845. Return Value:
  1846. None.
  1847. --*/
  1848. {
  1849. PFD Fd;
  1850. PRBD LastRbd, FirstRbd;
  1851. UINT PacketLength;
  1852. NdisAcquireSpinLock(&Adapter->Lock);
  1853. r1:
  1854. for(Fd = Adapter->BeginFd; ; Fd = Adapter->BeginFd ) {
  1855. if (Fd == NULL) {
  1856. DbgPrint("RcvPacket(): Fd == NULL\n");
  1857. KeBugCheck(9);
  1858. }
  1859. if (Fd->FdStatus & CSCMPLT)
  1860. {
  1861. Adapter->BeginFd =
  1862. (PFD)Pc586ToVirt(Adapter, Fd->FdNxtOfst);
  1863. FirstRbd = (PRBD)Pc586ToVirt(Adapter, Fd->FdRbdOfst);
  1864. if (Fd->FdRbdOfst != 0xffff) {
  1865. // scan for the end of the rbd's connected to the Fd
  1866. PacketLength = 14; // 6 source, 6 dest, 2 length bytes
  1867. for( LastRbd = FirstRbd; ; LastRbd = (PRBD)
  1868. Pc586ToVirt(Adapter, LastRbd->RbdNxtOfst)) {
  1869. PacketLength += (LastRbd->RbdStatus & CSRBDCNTMSK);
  1870. if ( (LastRbd->RbdSize & 0x3fff) != RCVBUFSIZE) DbgPrint("PC586->ProcessReceiveInterrupts(): LastRbd->RbdSize = 0x%lx, H/W alignment problem\n", LastRbd->RbdSize);
  1871. if (((LastRbd->RbdStatus & CSEOF) == CSEOF) ||
  1872. ((LastRbd->RbdSize & CSEL) == CSEL)) break;
  1873. }
  1874. Adapter->BeginRbd =
  1875. (PRBD)Pc586ToVirt(Adapter, LastRbd->RbdNxtOfst);
  1876. if (Fd->FdStatus & CSOK) {
  1877. NdisReleaseSpinLock(&Adapter->Lock);
  1878. PutPacket(Adapter, Fd, PacketLength);
  1879. NdisAcquireSpinLock(&Adapter->Lock);
  1880. }
  1881. else BadRcvCount++;
  1882. }
  1883. if (Fd->FdCmd & CSEL) {
  1884. ReQFd(Adapter, Fd);
  1885. break;
  1886. }
  1887. else ReQFd(Adapter, Fd);
  1888. }
  1889. else break;
  1890. }
  1891. // ack the rcv status bits
  1892. WaitScb(Adapter);
  1893. Adapter->Scb->ScbCmd =
  1894. (USHORT)(Adapter->Scb->ScbStatus & (SCBINTFR | SCBINTRNR));
  1895. if (Adapter->Scb->ScbCmd) ChanAttn(Adapter);
  1896. WaitScb(Adapter);
  1897. RuStart(Adapter);
  1898. WaitScb(Adapter);
  1899. if ( Adapter->Scb->ScbStatus & (SCBINTFR | SCBINTRNR) ) goto r1;
  1900. NdisReleaseSpinLock(&Adapter->Lock);
  1901. }
  1902. VOID
  1903. PutPacket(
  1904. IN PPC586_ADAPTER Adapter,
  1905. IN PFD Fd,
  1906. IN UINT PacketLength
  1907. )
  1908. /*++
  1909. Routine Description:
  1910. Takes one packet off of the 586's receive ring and "Indicates"
  1911. it to upper layer network software.
  1912. Arguments:
  1913. Adapter - The adapter that a packet came in on.
  1914. Return Value:
  1915. None.
  1916. --*/
  1917. {
  1918. PUSHORT ShortAddr;
  1919. PUSHORT Buffer;
  1920. PRBD Rbd;
  1921. USHORT xx;
  1922. USHORT ByteCount, LookaheadIndex;
  1923. PC586_RECEIVE_CONTEXT Context;
  1924. Rbd = (PRBD)Pc586ToVirt(Adapter, Fd->FdRbdOfst);
  1925. if (Rbd == NULL) return;
  1926. Buffer = (PUSHORT)Pc586ToVirt(Adapter, Rbd->RbdBuff);
  1927. if (Buffer == NULL) return;
  1928. ByteCount = (USHORT)(Rbd->RbdStatus & CSRBDCNTMSK);
  1929. // Ndis wants a) destination address, b) source address
  1930. // c) length field and d) the data, all contiguous
  1931. LookaheadIndex = 0;
  1932. ShortAddr = (PUSHORT)Fd->FdDest;
  1933. Adapter->LookaheadBufferNdis[LookaheadIndex++] = *ShortAddr++;
  1934. Adapter->LookaheadBufferNdis[LookaheadIndex++] = *ShortAddr++;
  1935. Adapter->LookaheadBufferNdis[LookaheadIndex++] = *ShortAddr++;
  1936. ShortAddr = (PUSHORT)Fd->FdSrc;
  1937. Adapter->LookaheadBufferNdis[LookaheadIndex++] = *ShortAddr++;
  1938. Adapter->LookaheadBufferNdis[LookaheadIndex++] = *ShortAddr++;
  1939. Adapter->LookaheadBufferNdis[LookaheadIndex++] = *ShortAddr++;
  1940. Adapter->LookaheadBufferNdis[LookaheadIndex++] = Fd->FdLength;
  1941. if (ww_put == 0) { /*88888888888*/
  1942. for (xx=0; xx < (USHORT)(Rbd->RbdStatus & CSRBDCNTMSK); xx+=2)
  1943. Adapter->LookaheadBufferNdis[LookaheadIndex++] = *Buffer++;
  1944. } else { /*88888888888*/
  1945. for (xx=0; xx < (USHORT)(Rbd->RbdStatus & CSRBDCNTMSK); xx+=4) {
  1946. *(PULONG)(&(Adapter->LookaheadBufferNdis[LookaheadIndex])) =
  1947. *(PULONG)(Buffer);
  1948. LookaheadIndex += 2;
  1949. Buffer += 2;
  1950. }
  1951. } /*88888888888*/
  1952. //
  1953. // Check just before we do indications that we aren't
  1954. // resetting.
  1955. //
  1956. NdisAcquireSpinLock(&Adapter->Lock);
  1957. if (Adapter->ResetInProgress) {
  1958. NdisReleaseSpinLock(&Adapter->Lock);
  1959. return;
  1960. }
  1961. NdisReleaseSpinLock(&Adapter->Lock);
  1962. // set lsb to indicate nonloopback packet
  1963. Context.a.FrameDescriptor = (UINT)Fd | 0x01;
  1964. MacFilterIndicateReceive(
  1965. Adapter->FilterDB,
  1966. (NDIS_HANDLE)Context.a.WholeThing,
  1967. (PCHAR)Adapter->LookaheadBufferNdis,
  1968. (PVOID)Adapter->LookaheadBufferNdis,
  1969. (UINT)(LOOKAHEADBUFFERSIZE * 2),
  1970. PacketLength
  1971. );
  1972. }
  1973. VOID
  1974. ReQFd(
  1975. IN PPC586_ADAPTER Adapter,
  1976. IN PFD Fd
  1977. )
  1978. /*++
  1979. Routine Description:
  1980. requeue frame
  1981. Arguments:
  1982. Adapter - the net card the packet came in on.
  1983. Fd - The 586 frame descriptor that holds the enet packet
  1984. Return Value:
  1985. None.
  1986. --*/
  1987. {
  1988. PRBD LastRbd, FirstRbd;
  1989. FirstRbd = (PRBD)Pc586ToVirt(Adapter, Fd->FdRbdOfst);
  1990. Fd->FdStatus = 0;
  1991. Fd->FdCmd = CSEL | CSSUSPND; // will be the last fd on the list
  1992. Fd->FdRbdOfst = 0xffff;
  1993. Adapter->EndFd->FdCmd = 0; // no longer the last
  1994. Adapter->EndFd = Fd;
  1995. if (FirstRbd != NULL) {
  1996. for(
  1997. LastRbd = FirstRbd;
  1998. (LastRbd->RbdStatus & CSEOF) != CSEOF &&
  1999. (LastRbd->RbdSize & CSEL) != CSEL;
  2000. LastRbd = (PRBD)Pc586ToVirt(Adapter, LastRbd->RbdNxtOfst)
  2001. )
  2002. LastRbd->RbdStatus = 0;
  2003. LastRbd->RbdStatus = 0;
  2004. LastRbd->RbdSize |= CSEL; // new end of rbd list
  2005. Adapter->EndRbd->RbdSize &= ~CSEL;
  2006. if ( (Adapter->EndRbd->RbdSize & 0x3fff) != RCVBUFSIZE) DbgPrint("PC586-> ReQFd: Adapter->EndRbd->RbdSize = 0x%lx, H/W alignment problems\n", LastRbd->RbdSize);
  2007. Adapter->EndRbd = LastRbd;
  2008. }
  2009. }
  2010. VOID
  2011. RuStart(
  2012. IN PPC586_ADAPTER Adapter
  2013. )
  2014. /*++
  2015. Routine Description:
  2016. restart the receive unit if necessary
  2017. Arguments:
  2018. Adapter - the net card from which a bunch of packets were rcv'd.
  2019. Return Value:
  2020. None.
  2021. --*/
  2022. {
  2023. PSCB Scb;
  2024. PFD BeginFd;
  2025. Scb = (PSCB)(Adapter->StaticRam + OFFSETSCB);
  2026. BeginFd = Adapter->BeginFd;
  2027. // if RU already running - leave it alone
  2028. if ((Scb->ScbStatus & SCBRUSMSK) == SCBRUSREADY) return;
  2029. if ((Scb->ScbStatus & SCBRUSMSK) == SCBRUSSUSPND) {
  2030. RcvSuspendCount++;
  2031. WaitScb(Adapter);
  2032. Scb->ScbCmd = SCBRUCRSUM;
  2033. ChanAttn(Adapter);
  2034. return;
  2035. }
  2036. if (BeginFd->FdStatus & CSCMPLT)
  2037. // The RU is not ready but it just completed an Fd
  2038. // do NOT restart RU -- this will wipe out the just completed Fd
  2039. // There will be a second interrupt that will remove the Fd via
  2040. // RcvPacket()
  2041. return;
  2042. // if we get here, then RU is not ready and no completed fd's are
  2043. // available therefore "start" not "resume" the RU
  2044. RcvRestartCount++;
  2045. BeginFd->FdRbdOfst = VirtToPc586(Adapter,
  2046. (PCHAR)Adapter->BeginRbd);
  2047. WaitScb(Adapter);
  2048. Scb->ScbCmd = SCBRUCSTRT;
  2049. Scb->ScbRfaOfst = VirtToPc586(Adapter, (PCHAR)BeginFd);
  2050. ChanAttn(Adapter);
  2051. return;
  2052. }
  2053. static
  2054. VOID
  2055. StartAdapterReset(
  2056. IN PPC586_ADAPTER Adapter
  2057. )
  2058. /*++
  2059. Routine Description:
  2060. This is the first phase of resetting the adapter hardware.
  2061. It makes the following assumptions:
  2062. 1) That the hardware has been stopped.
  2063. 2) That it can not be preempted.
  2064. 3) That no other adapter activity can occur.
  2065. When this routine is finished all of the adapter information
  2066. will be as if the driver was just initialized.
  2067. Arguments:
  2068. Adapter - The adapter whose hardware is to be reset.
  2069. Return Value:
  2070. None.
  2071. --*/
  2072. {
  2073. Adapter->Stage4Open = TRUE;
  2074. Adapter->Stage3Open = TRUE;
  2075. Adapter->Stage2Open = TRUE;
  2076. Adapter->Stage1Open = TRUE;
  2077. Adapter->AlreadyProcessingStage4 = FALSE;
  2078. Adapter->AlreadyProcessingStage3 = FALSE;
  2079. Adapter->AlreadyProcessingStage2 = FALSE;
  2080. //
  2081. // Go through the various transmit lists and abort every packet.
  2082. //
  2083. {
  2084. UINT i;
  2085. PNDIS_PACKET Packet;
  2086. PPC586_RESERVED Reserved;
  2087. PPC586_OPEN Open;
  2088. PNDIS_PACKET Next;
  2089. for (
  2090. i = 0;
  2091. i < 5;
  2092. i++
  2093. ) {
  2094. switch (i) {
  2095. case 0:
  2096. Next = Adapter->FirstLoopBack;
  2097. break;
  2098. case 1:
  2099. Next = Adapter->FirstFinishTransmit;
  2100. break;
  2101. case 2:
  2102. Next = Adapter->FirstStage3Packet;
  2103. break;
  2104. case 3:
  2105. Next = Adapter->FirstStage2Packet;
  2106. break;
  2107. case 4:
  2108. Next = Adapter->FirstStage1Packet;
  2109. break;
  2110. }
  2111. while (Next) {
  2112. Packet = Next;
  2113. Reserved = PPC586_RESERVED_FROM_PACKET(Packet);
  2114. Next = Reserved->Next;
  2115. Open =
  2116. PPC586_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
  2117. //
  2118. // The completion of the packet is one less reason
  2119. // to keep the open around.
  2120. //
  2121. ASSERT(Open->References);
  2122. Open->References--;
  2123. NdisCompleteSend(
  2124. Open->NdisBindingContext,
  2125. Reserved->RequestHandle,
  2126. NDIS_STATUS_REQUEST_ABORTED
  2127. );
  2128. }
  2129. }
  2130. Adapter->FirstLoopBack = NULL;
  2131. Adapter->LastLoopBack = NULL;
  2132. Adapter->FirstFinishTransmit = NULL;
  2133. Adapter->LastFinishTransmit = NULL;
  2134. Adapter->FirstStage3Packet = NULL;
  2135. Adapter->LastStage3Packet = NULL;
  2136. Adapter->FirstStage2Packet = NULL;
  2137. Adapter->LastStage2Packet = NULL;
  2138. Adapter->FirstStage1Packet = NULL;
  2139. Adapter->LastStage1Packet = NULL;
  2140. }
  2141. SetInitBlockAndInit(Adapter);
  2142. Pc586IntOn(Adapter);
  2143. }
  2144. static
  2145. VOID
  2146. SetInitBlockAndInit(
  2147. IN PPC586_ADAPTER Adapter
  2148. )
  2149. /*++
  2150. Routine Description:
  2151. It is this routines responsibility to make sure that the
  2152. initialization block is filled and the chip is initialized
  2153. *but not* started.
  2154. NOTE: ZZZ This routine is NT specific.
  2155. NOTE: This routine assumes that it is called with the lock
  2156. acquired OR that only a single thread of execution is working
  2157. with this particular adapter.
  2158. Arguments:
  2159. Adapter - The adapter whose hardware is to be initialized.
  2160. Return Value:
  2161. None.
  2162. --*/
  2163. {
  2164. //
  2165. // Fill in the adapters initialization block.
  2166. //
  2167. PISCP Iscp;
  2168. ULONG xx;
  2169. PSCB Scb;
  2170. PPC586_OPEN ResettingOpen;
  2171. NDIS_REQUEST_TYPE ResetRequestType;
  2172. PPC586_OPEN Open;
  2173. PLIST_ENTRY CurrentLink;
  2174. //
  2175. // Possibly undefined request handle for the reset request.
  2176. //
  2177. NDIS_HANDLE ResetRequestHandle;
  2178. ResetCount++;
  2179. // shut off interrupts
  2180. Pc586IntOff(Adapter);
  2181. // drop chan attn -- even though it should not be raised at this point
  2182. ShuvWord( (PUSHORT)(Adapter->CmdProm + OFFSETCHANATT) , CMD0);
  2183. // hardware reset the 586
  2184. ShuvWord( (PUSHORT)(Adapter->CmdProm + OFFSETRESET), (USHORT)CMD1);
  2185. KeStallExecutionProcessor((ULONG)1000);
  2186. ShuvWord( (PUSHORT)(Adapter->CmdProm + OFFSETRESET), CMD0);
  2187. KeStallExecutionProcessor((ULONG)1000);
  2188. // esi loopback - until diagnostics are run
  2189. ShuvWord( (PUSHORT)(Adapter->CmdProm + OFFSETNORMMODE),
  2190. (USHORT)CMD1);
  2191. //16 bit for AT bus
  2192. ShuvWord( (PUSHORT)(Adapter->CmdProm + OFFSET16BXFER),
  2193. (USHORT)CMD1);
  2194. BuildCu(Adapter); // inits scp, iscp, scb, db, tdb and tbuf
  2195. BuildRu(Adapter); // inits scb, fd's, rbd's rbufs
  2196. Iscp = (PISCP) (Adapter->StaticRam + OFFSETISCP);
  2197. Iscp->IscpBusy = 1; // per user man. reset protocol
  2198. // chan attn to feed 586 its data structs
  2199. ChanAttn(Adapter);
  2200. Scb = (PSCB)(Adapter->StaticRam + OFFSETSCB);
  2201. for(xx=0; xx<0xffff; xx++)
  2202. if ( Scb->ScbStatus==(SCBINTCX | SCBINTCNA) ) goto SIB1;
  2203. DbgPrint("pc586 SetInitBlockAndInit(): first chan attn failed\n");
  2204. return;
  2205. SIB1:
  2206. Scb->ScbCmd = SCBACKCX | SCBACKCNA;
  2207. ChanAttn(Adapter); // to clear the reset's ack
  2208. // diag cmd (no. 7) will busy wait for completion
  2209. if (Diagnose586(Adapter) == FALSE) {
  2210. DbgPrint("pc586 Diagnose586() failed\n");
  2211. return;
  2212. }
  2213. if (Config586(Adapter) == FALSE) {
  2214. DbgPrint("pc586 Config586() failed\n");
  2215. return;
  2216. }
  2217. LoadMCAddress(Adapter);
  2218. // now turn esi loopback off, rcv started
  2219. ShuvWord( (PUSHORT)(Adapter->CmdProm + OFFSETNORMMODE),
  2220. (USHORT)CMD1);
  2221. WaitScb(Adapter);
  2222. RuStart(Adapter);
  2223. //
  2224. // This initialization is from either a
  2225. // reset or test. ZZZ Test not yet implemented.
  2226. //
  2227. //
  2228. // This will point (possibly null) to the open that
  2229. // initiated the reset.
  2230. //
  2231. Adapter->ResetInProgress = FALSE;
  2232. //
  2233. // We save off the open that caused this reset incase
  2234. // we get *another* reset while we're indicating the
  2235. // last reset is done.
  2236. //
  2237. ResettingOpen = Adapter->ResettingOpen;
  2238. ResetRequestType = Adapter->ResetRequestType;
  2239. ResetRequestHandle = Adapter->ResetRequestHandle;
  2240. //
  2241. // We need to signal every open binding that the
  2242. // reset is complete. We increment the reference
  2243. // count on the open binding while we're doing indications
  2244. // so that the open can't be deleted out from under
  2245. // us while we're indicating (recall that we can't own
  2246. // the lock during the indication).
  2247. //
  2248. CurrentLink = Adapter->OpenBindings.Flink;
  2249. while (CurrentLink != &Adapter->OpenBindings) {
  2250. Open = CONTAINING_RECORD(
  2251. CurrentLink,
  2252. PC586_OPEN,
  2253. OpenList
  2254. );
  2255. Open->References++;
  2256. NdisReleaseSpinLock(&Adapter->Lock);
  2257. NdisIndicateStatus(
  2258. Open->NdisBindingContext,
  2259. NDIS_STATUS_RESET,
  2260. 0
  2261. );
  2262. NdisIndicateStatusComplete(Open->NdisBindingContext);
  2263. NdisAcquireSpinLock(&Adapter->Lock);
  2264. Open->References--;
  2265. CurrentLink = CurrentLink->Flink;
  2266. }
  2267. //
  2268. // Look to see which open initiated the reset.
  2269. //
  2270. // If the reset was initiated by an open because it
  2271. // was closing we will let the closing binding loop
  2272. // further on in this routine indicate that the
  2273. // request was complete. ZZZ (Still need to code
  2274. // this part.)
  2275. //
  2276. // If the reset was initiated for some obscure hardware
  2277. // reason that can't be associated with a particular
  2278. // open (e.g. memory error on receiving a packet) then
  2279. // we won't have an initiating request so we can't
  2280. // indicate. (The ResettingOpen pointer will be
  2281. // NULL in this case.)
  2282. //
  2283. if (ResettingOpen &&
  2284. (ResetRequestType != NdisRequestCloseAdapter)) {
  2285. NdisReleaseSpinLock(&Adapter->Lock);
  2286. NdisCompleteRequest(
  2287. ResettingOpen->NdisBindingContext,
  2288. ResetRequestHandle,
  2289. ResetRequestType,
  2290. NDIS_STATUS_SUCCESS
  2291. );
  2292. NdisAcquireSpinLock(&Adapter->Lock);
  2293. ResettingOpen->References--;
  2294. }
  2295. }
  2296. static
  2297. VOID
  2298. SetupForReset(
  2299. IN PPC586_ADAPTER Adapter,
  2300. IN PPC586_OPEN Open,
  2301. IN NDIS_HANDLE RequestHandle,
  2302. IN NDIS_REQUEST_TYPE RequestType
  2303. )
  2304. /*++
  2305. Routine Description:
  2306. This routine is used to fill in the who and why a reset is
  2307. being set up as well as setting the appropriate fields in the
  2308. adapter.
  2309. NOTE: This routine must be called with the lock acquired.
  2310. Arguments:
  2311. Adapter - The adapter whose hardware is to be initialized.
  2312. Open - A (possibly NULL) pointer to an pc586 open structure.
  2313. The reason it could be null is if the adapter is initiating the
  2314. reset on its own.
  2315. RequestHandle - If open is not null then the request handle of the
  2316. request that is causing the reset.
  2317. RequestType - If the open is not null then the request type that
  2318. is causing the reset.
  2319. Return Value:
  2320. None.
  2321. --*/
  2322. {
  2323. //
  2324. // Shut down the chip. We won't be doing any more work until
  2325. // the reset is complete.
  2326. //
  2327. Pc586IntOff(Adapter);
  2328. //
  2329. // Once the chip is stopped we can't get any more interrupts.
  2330. // Any interrupts that are "queued" for processing could
  2331. // only possibly service this reset.
  2332. //
  2333. Adapter->ResetInProgress = TRUE;
  2334. //
  2335. // Shut down all of the transmit queues so that the
  2336. // transmit portion of the chip will eventually calm down.
  2337. //
  2338. Adapter->Stage4Open = FALSE;
  2339. Adapter->Stage3Open = FALSE;
  2340. Adapter->Stage2Open = FALSE;
  2341. Adapter->Stage1Open = FALSE;
  2342. Adapter->ResetRequestHandle = RequestHandle;
  2343. Adapter->ResettingOpen = Open;
  2344. Adapter->ResetRequestType = RequestType;
  2345. //
  2346. // If there is a valid open we should up the reference count
  2347. // so that the open can't be deleted before we indicate that
  2348. // their request is finished.
  2349. //
  2350. if (Open) {
  2351. Open->References++;
  2352. }
  2353. }
  2354. static
  2355. BOOLEAN
  2356. ProcessTransmitInterrupts(
  2357. IN PPC586_ADAPTER Adapter
  2358. )
  2359. /*++
  2360. Routine Description:
  2361. Process the packets that have finished transmitting.
  2362. NOTE: This routine assumes that it is being executed in a
  2363. single thread of execution.
  2364. Arguments:
  2365. Adapter - The adapter that was sent from.
  2366. Return Value:
  2367. This function will return TRUE if it finished up the
  2368. send on a packet. It will return FALSE if for some
  2369. reason there was no packet to process.
  2370. --*/
  2371. {
  2372. //
  2373. // Pointer to the packet that started this transmission.
  2374. //
  2375. PNDIS_PACKET OwningPacket;
  2376. //
  2377. // Points to the reserved part of the OwningPacket.
  2378. //
  2379. PPC586_RESERVED Reserved;
  2380. //
  2381. // Get a pointer to the owning packet and the reserved part of
  2382. // the packet.
  2383. //
  2384. OwningPacket = Adapter->OwningPacket;
  2385. if (OwningPacket == NULL) return FALSE;
  2386. Reserved = PPC586_RESERVED_FROM_PACKET(OwningPacket);
  2387. //
  2388. // Check that the host does indeed own this entire packet.
  2389. //
  2390. if ( !(Adapter->Cb->CmdStatus & CSCMPLT) ||
  2391. (Adapter->Cb->CmdStatus & CSBUSY) ) {
  2392. //
  2393. // We don't own the command block. We return FALSE to indicate
  2394. // that we don't have any more packets to work on.
  2395. //
  2396. return FALSE;
  2397. } else {
  2398. ReturnAdapterResources(Adapter);
  2399. NdisAcquireSpinLock(&Adapter->Lock);
  2400. Adapter->OwningPacket = NULL;
  2401. if (Reserved->STAGE.STAGE4.ReadyToComplete) {
  2402. //
  2403. // The binding that is submitting this packet.
  2404. //
  2405. PPC586_OPEN Open =
  2406. PPC586_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle);
  2407. //
  2408. // While we're indicating we increment the reference
  2409. // count so that the open can't be deleted out
  2410. // from under us.
  2411. //
  2412. Open->References++;
  2413. //
  2414. // Along with at least one reference because of the coming
  2415. // indication there should be a reference because of the
  2416. // packet to indicate.
  2417. //
  2418. ASSERT(Open->References > 1);
  2419. //
  2420. // Either the packet is done with loopback or
  2421. // the packet didn't need to be loopbacked. In
  2422. // any case we can let the protocol know that the
  2423. // send is complete after we remove the packet from
  2424. // the finish transmit queue.
  2425. //
  2426. Pc586RemovePacketOnFinishTrans(
  2427. Adapter,
  2428. OwningPacket
  2429. );
  2430. NdisReleaseSpinLock(&Adapter->Lock);
  2431. NdisCompleteSend(
  2432. Open->NdisBindingContext,
  2433. Reserved->RequestHandle,
  2434. NDIS_STATUS_SUCCESS
  2435. );
  2436. NdisAcquireSpinLock(&Adapter->Lock);
  2437. //
  2438. // We reduce the count by two to account for the fact
  2439. // that we aren't indicating to the open and that one
  2440. // less packet is owned by this open.
  2441. //
  2442. Open->References -= 2;
  2443. } else {
  2444. //
  2445. // Let the loopback queue know that the hardware
  2446. // is finished with the packet, and record whether
  2447. // it could transmit or not.
  2448. //
  2449. Reserved->STAGE.STAGE4.ReadyToComplete = TRUE;
  2450. Reserved->STAGE.STAGE4.SuccessfulTransmit = TRUE;
  2451. //
  2452. // Decrement the reference count by one since it
  2453. // was incremented by one when the packet was given
  2454. // to be transmitted.
  2455. //
  2456. PPC586_OPEN_FROM_BINDING_HANDLE(
  2457. Reserved->MacBindingHandle
  2458. )->References--;
  2459. }
  2460. //
  2461. // Since we've given back some ring entries we should
  2462. // open of stage3 if it was closed and we are not resetting.
  2463. //
  2464. if ((!Adapter->Stage3Open) && (!Adapter->ResetInProgress)) {
  2465. Adapter->Stage3Open = TRUE;
  2466. }
  2467. NdisReleaseSpinLock(&Adapter->Lock);
  2468. return TRUE;
  2469. }
  2470. }
  2471. static
  2472. VOID
  2473. ReturnAdapterResources(
  2474. IN PPC586_ADAPTER Adapter
  2475. )
  2476. /*++
  2477. Routine Description
  2478. Return staged resources.
  2479. Arguments:
  2480. Adapter - The adapter that the packet came through
  2481. Return Value:
  2482. None.
  2483. --*/
  2484. {
  2485. NdisAcquireSpinLock(&Adapter->Lock);
  2486. //
  2487. // If stage 2 as closed and we aren't resetting then open
  2488. // it back up.
  2489. //
  2490. if ((!Adapter->Stage2Open) && (!Adapter->ResetInProgress)) {
  2491. Adapter->Stage2Open = TRUE;
  2492. }
  2493. NdisReleaseSpinLock(&Adapter->Lock);
  2494. }
  2495. VOID
  2496. LoadMCAddress(
  2497. IN PPC586_ADAPTER Adapter
  2498. )
  2499. /*++
  2500. Routine Description:
  2501. Download multicast addresses to 82586 chip by using a 586 command.
  2502. Arguments:
  2503. Adapter - the network chip to be loaded with multicast addresses.
  2504. Return Value:
  2505. None.
  2506. --*/
  2507. {
  2508. PSCB Scb;
  2509. PCMD Cb;
  2510. ULONG xx;
  2511. UINT PacketFilters;
  2512. Scb = Adapter->Scb;
  2513. Cb = Adapter->Cb;
  2514. // first ack the status bits
  2515. WaitScb(Adapter);
  2516. Scb->ScbCmd = (USHORT)(Scb->ScbStatus & SCBINTMSK);
  2517. if (Scb->ScbCmd) ChanAttn(Adapter);
  2518. //
  2519. // Set up the address filtering.
  2520. //
  2521. // First get hold of the combined packet filter.
  2522. //
  2523. PacketFilters = MAC_QUERY_FILTER_CLASSES(Adapter->FilterDB);
  2524. if (PacketFilters & NDIS_PACKET_TYPE_PROMISCUOUS) {
  2525. DbgPrint("PC586 driver - promiscuous mode not supported\n");
  2526. } else if (PacketFilters & NDIS_PACKET_TYPE_ALL_MULTICAST) {
  2527. DbgPrint("PC586 driver - all multicast mode not supported\n");
  2528. } else if (PacketFilters & NDIS_PACKET_TYPE_MULTICAST) {
  2529. //
  2530. // At least one open binding wants multicast addresses.
  2531. //
  2532. USHORT MulticastAddresses[MAX_MULTICAST_ADDRESS]
  2533. [ MAC_LENGTH_OF_ADDRESS / 2 ];
  2534. UINT NumberOfAddresses;
  2535. MacQueryFilterAddresses(
  2536. Adapter->FilterDB,
  2537. &NumberOfAddresses,
  2538. (PCHAR)MulticastAddresses
  2539. );
  2540. ASSERT(sizeof(UINT) == 4);
  2541. if (NumberOfAddresses == 0) return;
  2542. for (
  2543. xx = 0;
  2544. xx < NumberOfAddresses;
  2545. xx++
  2546. ) {
  2547. Cb->PRMTR.PrmMcSet.McAddress[xx][0] =
  2548. MulticastAddresses[xx][0];
  2549. Cb->PRMTR.PrmMcSet.McAddress[xx][1] =
  2550. MulticastAddresses[xx][1];
  2551. Cb->PRMTR.PrmMcSet.McAddress[xx][2] =
  2552. MulticastAddresses[xx][2];
  2553. /* 8888
  2554. yy.c.b = MulticastAddresses[xx][2];
  2555. zz.c.a[0] = yy.c.a[1];
  2556. zz.c.a[1] = yy.c.a[0];
  2557. Cb->PRMTR.PrmMcSet.McAddress[xx][0] = zz.c.b;
  2558. yy.c.b = MulticastAddresses[xx][1];
  2559. zz.c.a[0] = yy.c.a[1];
  2560. zz.c.a[1] = yy.c.a[0];
  2561. Cb->PRMTR.PrmMcSet.McAddress[xx][1] = zz.c.b;
  2562. yy.c.b = MulticastAddresses[xx][0];
  2563. zz.c.a[0] = yy.c.a[1];
  2564. zz.c.a[1] = yy.c.a[0];
  2565. Cb->PRMTR.PrmMcSet.McAddress[xx][2] = zz.c.b;
  2566. 8888 */
  2567. }
  2568. // McCnt is the total number of bytes in the McAddress[] field
  2569. Cb->PRMTR.PrmMcSet.McCnt = (USHORT)NumberOfAddresses * 6;
  2570. // now do the multicast address command
  2571. WaitScb(Adapter);
  2572. Cb->CmdStatus = 0;
  2573. Cb->CmdCmd = CSCMDMCSET | CSEL;
  2574. Scb->ScbCmd = SCBCUCSTRT;
  2575. ChanAttn(Adapter);
  2576. WaitScb(Adapter);
  2577. for(xx=0; xx<0xfffff; xx++)
  2578. if (Cb->CmdStatus & CSOK) {
  2579. Scb->ScbCmd = (USHORT)(Scb->ScbStatus & SCBINTMSK);
  2580. if (Scb->ScbCmd) ChanAttn(Adapter);
  2581. return;
  2582. }
  2583. DbgPrint("pc586 LoadMCAddress() mc command failed\n");
  2584. return;
  2585. }
  2586. }
  2587. VOID
  2588. ShuvWord(
  2589. IN PUSHORT VirtAddr,
  2590. IN USHORT Value
  2591. )
  2592. /*++
  2593. Routine Description:
  2594. Utility to write to pc586 memory mapped hardware.
  2595. Arguments:
  2596. VirtAddr - virtual address of the memory mapped item.
  2597. Value - what's to be written at memory mapped address.
  2598. Return Value:
  2599. None.
  2600. --*/
  2601. {
  2602. *VirtAddr = Value;
  2603. }
  2604. VOID
  2605. ShuvByte(
  2606. IN PUCHAR VirtAddr,
  2607. IN UCHAR Value
  2608. )
  2609. /*++
  2610. Routine Description:
  2611. Same as ShuvWord only for 8-bit quantity.
  2612. Arguments:
  2613. See ShuvWord
  2614. Return Value:
  2615. None.
  2616. --*/
  2617. {
  2618. *VirtAddr = Value;
  2619. }
  2620. USHORT
  2621. PullWord(
  2622. IN PUSHORT VirtAddr
  2623. )
  2624. /*++
  2625. Routine Description:
  2626. Gets a 16-bit quantity at a given pc586 memory mapped hardware address.
  2627. Arguments:
  2628. VirtAddr - address at which to retrieve a value.
  2629. Return Value:
  2630. The data at VirtAddr address.
  2631. --*/
  2632. {
  2633. USHORT Value;
  2634. return (Value = *VirtAddr);
  2635. }
  2636. VOID
  2637. BuildCu(
  2638. IN PPC586_ADAPTER Adapter
  2639. )
  2640. /*++
  2641. Routine Description:
  2642. Sets up 586 command unit data structures.
  2643. Arguments:
  2644. Adapter - points to the memory map of the net card to be set up.
  2645. Return Value:
  2646. None.
  2647. --*/
  2648. {
  2649. PCMD Cb;
  2650. PTBD Tbd;
  2651. PSCP Scp;
  2652. PISCP Iscp;
  2653. PSCB Scb;
  2654. Cb = Adapter->Cb;
  2655. Tbd = Adapter->Tbd;
  2656. Scp = Adapter->Scp;
  2657. Iscp = Adapter->Iscp;
  2658. Scb = Adapter->Scb;
  2659. Scp->ScpSysBus = 0;
  2660. Scp->ScpIscp = OFFSETISCP;
  2661. Scp->ScpIscpBase = 0;
  2662. Iscp->IscpBusy = 1;
  2663. Iscp->IscpScbOfst = OFFSETSCB;
  2664. Iscp->IscpScbBase = 0;
  2665. Scb->ScbStatus = 0;
  2666. Scb->ScbCmd = 0;
  2667. Scb->ScbCblOfst = OFFSETCU;
  2668. Scb->ScbRfaOfst = OFFSETRU;
  2669. Scb->ScbCrcErr = 0;
  2670. Scb->ScbAlnErr = 0;
  2671. Scb->ScbRscErr = 0;
  2672. Scb->ScbOvrnErr = 0;
  2673. Cb->CmdStatus = 0;
  2674. Cb->CmdCmd = CSEL;
  2675. Cb->CmdNxtOfst = OFFSETCU;
  2676. Tbd->TbdCount = 0;
  2677. Tbd->TbdNxtOfst = 0xffff;
  2678. Tbd->TbdBuff = 0;
  2679. Tbd->TbdBuffBase = 0;
  2680. }
  2681. VOID
  2682. BuildRu(
  2683. IN PPC586_ADAPTER Adapter
  2684. )
  2685. /*++
  2686. Routine Description:
  2687. Sets up the receive data structures for 586 receive unit.
  2688. Arguments:
  2689. Adapter - points to net card's memory map to be written on.
  2690. Return Value:
  2691. None.
  2692. --*/
  2693. {
  2694. PFD Fd;
  2695. ULONG xx;
  2696. typedef struct _RUBUF {
  2697. RBD r;
  2698. CHAR RbdPad[2]; // puts RBuffer on 4 byte boundry
  2699. UCHAR RBuffer[RCVBUFSIZE];
  2700. } RUBUF, *PRUBUF;
  2701. PRUBUF Rbd;
  2702. // FIRST BUILD THE FRAME DESCRIPTOR LIST
  2703. Fd = (PFD)(Adapter->StaticRam + OFFSETRU);
  2704. for (xx=0; xx<NFD; xx++) {
  2705. Fd->FdStatus = 0;
  2706. Fd->FdCmd = 0;
  2707. // point to the next fd
  2708. Fd->FdNxtOfst = VirtToPc586(Adapter, (PUCHAR)(Fd +1));
  2709. Fd->FdRbdOfst = 0xffff; // must be 0xffff, see manual
  2710. Fd++;
  2711. }
  2712. Adapter->EndFd = --Fd;
  2713. Fd->FdNxtOfst = OFFSETRU; // Fd's are now in a circular list
  2714. Fd->FdCmd = CSEL | CSSUSPND; // end of receive Fd list
  2715. Fd = Adapter->BeginFd =(PFD)(Adapter->StaticRam + OFFSETRU);
  2716. // SECOND BUILD THE RECEIVE BUFFER DESCRIPTOR LIST
  2717. Rbd = (PRUBUF)(Adapter->StaticRam + OFFSETRBD);
  2718. Adapter->BeginRbd = (PRBD)(Adapter->StaticRam + OFFSETRBD);
  2719. // make the first Fd point to the first Rbd
  2720. Fd->FdRbdOfst = VirtToPc586(Adapter, (PUCHAR)Rbd);
  2721. for(xx=0; xx<NRBD; xx++) {
  2722. Rbd->r.RbdStatus = 0;
  2723. Rbd->r.RbdNxtOfst = VirtToPc586(Adapter, (PUCHAR)(Rbd+1) );
  2724. Rbd->r.RbdBuff = VirtToPc586(Adapter, (PUCHAR)Rbd->RBuffer);
  2725. Rbd->r.RbdBuffBase = 0;
  2726. Rbd->r.RbdSize = RCVBUFSIZE;
  2727. Rbd++;
  2728. }
  2729. // fixup very last Rbd on the list
  2730. Rbd--;
  2731. Adapter->EndRbd = (PRBD)(Rbd);
  2732. Rbd->r.RbdNxtOfst = OFFSETRBD;
  2733. Rbd->r.RbdSize |= CSEL;
  2734. }
  2735. BOOLEAN
  2736. Diagnose586(
  2737. IN PPC586_ADAPTER Adapter
  2738. )
  2739. /*++
  2740. Routine Description:
  2741. Runs 82586 diagnostics to see if chip is functioning.
  2742. Arguments:
  2743. Adapter - points to net card in question.
  2744. Return Value:
  2745. True - if card checks out ok.
  2746. --*/
  2747. {
  2748. PSCB Scb;
  2749. PCMD Cb;
  2750. ULONG xx;
  2751. Scb = Adapter->Scb;
  2752. Cb = Adapter->Cb;
  2753. // first ack the status bits
  2754. WaitScb(Adapter);
  2755. Scb->ScbCmd = (USHORT)(Scb->ScbStatus & SCBINTMSK);
  2756. if (Scb->ScbCmd) ChanAttn(Adapter);
  2757. // now do the diagnose
  2758. WaitScb(Adapter);
  2759. Cb->CmdStatus = 0;
  2760. Cb->CmdCmd = CSCMDDGNS | CSEL;
  2761. Scb->ScbCmd = SCBCUCSTRT;
  2762. ChanAttn(Adapter);
  2763. WaitScb(Adapter);
  2764. for(xx=0; xx<0xfff; xx++)
  2765. if (Cb->CmdStatus & CSOK) {
  2766. Scb->ScbCmd = (USHORT)(Scb->ScbStatus & SCBINTMSK);
  2767. if (Scb->ScbCmd) ChanAttn(Adapter);
  2768. return TRUE;
  2769. }
  2770. return FALSE;
  2771. }
  2772. BOOLEAN
  2773. Config586(
  2774. IN PPC586_ADAPTER Adapter
  2775. )
  2776. /*++
  2777. Routine Description:
  2778. Configures 586 network chip for standard configuration.
  2779. Arguments:
  2780. Adapter - points to the netcard that holds 586 to be configured.
  2781. Return Value:
  2782. TRUE - if configuration went well.
  2783. --*/
  2784. {
  2785. PSCB Scb;
  2786. PCMD Cb;
  2787. ULONG xx;
  2788. PUSHORT Addr, Addr2;
  2789. Scb = Adapter->Scb;
  2790. Cb = Adapter->Cb;
  2791. // first ack the status bits
  2792. WaitScb(Adapter);
  2793. Scb->ScbCmd = (USHORT)(Scb->ScbStatus & SCBINTMSK);
  2794. if (Scb->ScbCmd) ChanAttn(Adapter);
  2795. // now do configuration
  2796. WaitScb(Adapter);
  2797. Cb->CmdStatus = 0;
  2798. Cb->CmdCmd = CSCMDCONF | CSEL;
  2799. Cb->PRMTR.PrmConf.CnfFifoByte = 0x080c;
  2800. Cb->PRMTR.PrmConf.CnfAddMode = 0x2600;
  2801. Cb->PRMTR.PrmConf.CnfPriData = 0x6000;
  2802. Cb->PRMTR.PrmConf.CnfSlot = 0xf200;
  2803. Cb->PRMTR.PrmConf.CnfHrdwr = 0x0000;
  2804. Cb->PRMTR.PrmConf.CnfMinLen = 0x0040;
  2805. Scb->ScbCmd = SCBCUCSTRT;
  2806. ChanAttn(Adapter);
  2807. WaitScb(Adapter);
  2808. for(xx=0; xx<0xfff; xx++)
  2809. if (Cb->CmdStatus & CSOK) goto c1;
  2810. return FALSE;
  2811. c1:
  2812. Scb->ScbCmd = (USHORT)(Scb->ScbStatus & SCBINTMSK);
  2813. if (Scb->ScbCmd) ChanAttn(Adapter);
  2814. // next, download ethernet address to 586 chip
  2815. WaitScb(Adapter);
  2816. Cb->CmdStatus = 0;
  2817. Cb->CmdCmd = CSCMDIASET | CSEL;
  2818. Addr = (PUSHORT)Adapter->NetworkAddress;
  2819. Addr2 = (PUSHORT)Cb->PRMTR.PrmIaSet;
  2820. for(xx=0; xx<MAC_LENGTH_OF_ADDRESS/2; xx++) {
  2821. *Addr2 = *Addr;
  2822. *Addr2++;
  2823. *Addr++;
  2824. }
  2825. Scb->ScbCmd = SCBCUCSTRT;
  2826. ChanAttn(Adapter);
  2827. for(xx=0; xx<0xfff; xx++)
  2828. if (Cb->CmdStatus & CSOK) goto c2;
  2829. return FALSE;
  2830. c2:
  2831. Scb->ScbCmd = (USHORT)(Scb->ScbStatus & SCBINTMSK);
  2832. ChanAttn(Adapter);
  2833. return TRUE;
  2834. }
  2835. USHORT
  2836. PromAddr(
  2837. IN PPC586_ADAPTER Adapter,
  2838. IN ULONG Index
  2839. )
  2840. /*++
  2841. Routine Description:
  2842. Pulls the unique enet id out of the netcard's special eprom.
  2843. Arguments:
  2844. Adapter - points to the card to get the address from.
  2845. Index - index of which byte of enet address to get.
  2846. Return Value:
  2847. Bytes of e-net address.
  2848. --*/
  2849. {
  2850. PUCHAR CmdProm;
  2851. CmdProm = Adapter->CmdProm;
  2852. CmdProm += OFFSETADDRPROM;
  2853. CmdProm += Index;
  2854. return *CmdProm;
  2855. }
  2856. VOID
  2857. ChanAttn(
  2858. IN PPC586_ADAPTER Adapter
  2859. )
  2860. /*++
  2861. Routine Description:
  2862. Tickles the network card to get the 82586's attention.
  2863. Arguments:
  2864. Adapter - points to the card in question.
  2865. Return Value:
  2866. None.
  2867. --*/
  2868. {
  2869. // first byte of word is 1 - this sets the CA
  2870. // second byte of word is 0 - this clears the CA
  2871. ShuvWord(Adapter->CAAddr, 0x01);
  2872. }
  2873. VOID
  2874. WaitScb(
  2875. IN PPC586_ADAPTER Adapter
  2876. )
  2877. /*++
  2878. Routine Description:
  2879. This routine waits a reasonable length of time for the 586 to
  2880. read and dispatch a previous command.
  2881. Arguments:
  2882. Adapter - points to net card in question
  2883. Return Value:
  2884. TRUE - if 586 failed.
  2885. FALSE - if 586 dispatched previous command within time limit.
  2886. --*/
  2887. {
  2888. PSCB Scb;
  2889. ULONG xx;
  2890. Scb = Adapter->Scb;
  2891. for (xx=0; xx<0xffff; xx++)
  2892. if (Scb->ScbCmd == 0) return;
  2893. DbgPrint("pc586 WaitScb() - timed out\n");
  2894. return;
  2895. }
  2896. USHORT
  2897. VirtToPc586(
  2898. IN PPC586_ADAPTER Adapter,
  2899. IN PUCHAR KernelVirtAddr
  2900. )
  2901. /*++
  2902. Routine Description:
  2903. The CPU's 32-bit addresses are converted to 16-bit addresses that are
  2904. compatible with 82586.
  2905. Arguments:
  2906. Adapter - points to net card in question.
  2907. KernelVirtAddr - the address to be converted.
  2908. Return Value:
  2909. 586 style address.
  2910. --*/
  2911. {
  2912. USHORT Addr586;
  2913. // 586 uses 0xffff for null as "c" uses zero for null
  2914. if (KernelVirtAddr == NULL)
  2915. return 0xffff;
  2916. if ( (KernelVirtAddr > Adapter->StaticRam + 32*1024 ) ||
  2917. (KernelVirtAddr < Adapter->StaticRam -1 ) ) {
  2918. DbgPrint("VirtToPc586(): wild kernel virt addr of 0x%x\n",
  2919. KernelVirtAddr);
  2920. return 0xffff;
  2921. }
  2922. Addr586 = (USHORT)(KernelVirtAddr - Adapter->StaticRam);
  2923. return Addr586;
  2924. }
  2925. PUCHAR
  2926. Pc586ToVirt(
  2927. IN PPC586_ADAPTER Adapter,
  2928. IN USHORT Addr586
  2929. )
  2930. /*++
  2931. Routine Description:
  2932. Converts from 82586 style 16-bit address to flat 32-bit CPU address.
  2933. Arguments:
  2934. Adapter - points to network card in question.
  2935. Addr586 - 586 16-bit address to be converted.
  2936. Return Value:
  2937. A flat 32-bit CPU address.
  2938. --*/
  2939. {
  2940. if (Addr586 == 0xffff) return NULL;
  2941. if (Addr586 > 0x7fff) {
  2942. DbgPrint("Pc586ToVirt(): wild 586 pointer of 0x%x\n", Addr586);
  2943. return NULL;
  2944. }
  2945. return (Adapter->StaticRam + Addr586);
  2946. }
  2947. static
  2948. VOID
  2949. Pc586IntOn(
  2950. IN PPC586_ADAPTER Adapter
  2951. )
  2952. /*++
  2953. Routine Description:
  2954. Flips a switch on the network card to connect 586 interrupts to host CPU.
  2955. Arguments:
  2956. Adapter - points to network card in question.
  2957. Return Value:
  2958. None.
  2959. --*/
  2960. {
  2961. ShuvWord( (PUSHORT)(Adapter->IntAddr),
  2962. (USHORT)CMD1 );
  2963. }
  2964. static
  2965. VOID
  2966. Pc586IntOff(
  2967. IN PPC586_ADAPTER Adapter
  2968. )
  2969. /*++
  2970. Routine Description:
  2971. Flips switch on network card to disconnect 586 interrupts from
  2972. host CPU.
  2973. Arguments:
  2974. Adapter - points to netcard in question.
  2975. Return Value:
  2976. None.
  2977. --*/
  2978. {
  2979. ShuvWord( (PUSHORT)(Adapter->IntAddr),
  2980. (USHORT)CMD0 );
  2981. }