Esempio n. 1
0
NTSTATUS
NICLinkDetection(
    PFDO_DATA         FdoData
    )
/*++

Routine Description:

    Timer function for postponed link negotiation. Called from
    the NICWatchDogEvtTimerFunc. After the link detection is over
    we will complete any pending ioctl or send IRPs.

Arguments:

    FdoData     Pointer to our FdoData

Return Value:

    NT status

--*/
{
    NTSTATUS                status = STATUS_SUCCESS;
    MEDIA_STATE             CurrMediaState;
    PNDISPROT_QUERY_OID     pQuery = NULL;
    PNDISPROT_SET_OID       pSet = NULL;
    PVOID                   DataBuffer;
    ULONG                   BytesWritten;
    NDIS_OID                Oid;
    PVOID                   InformationBuffer;
    size_t               bufSize;
    WDFREQUEST              request;

    //
    // Handle the link negotiation.
    //
    if (FdoData->bLinkDetectionWait)
    {
        status = ScanAndSetupPhy(FdoData);
    }
    else
    {
        status = PhyDetect(FdoData);
    }

    if (status == STATUS_PENDING)
    {
        return status;
    }

    //
    // Reset some variables for link detection
    //
    FdoData->bLinkDetectionWait = FALSE;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_DPC, "NICLinkDetection - negotiation done\n");


    WdfSpinLockAcquire(FdoData->Lock);
    MP_CLEAR_FLAG(FdoData, fMP_ADAPTER_LINK_DETECTION);

    WdfSpinLockRelease(FdoData->Lock);

    //
    // Any OID query request pending?
    //

    status = NICGetIoctlRequest(FdoData->PendingIoctlQueue,
                                IOCTL_NDISPROT_QUERY_OID_VALUE,
                                &request);

    if(NT_SUCCESS(status)) {
        status = WdfRequestRetrieveOutputBuffer(request, sizeof(NDISPROT_QUERY_OID), &DataBuffer, &bufSize);
        if(NT_SUCCESS(status)) {

            pQuery = (PNDISPROT_QUERY_OID)DataBuffer;
            Oid = pQuery->Oid;
            InformationBuffer = &pQuery->Data[0];
            switch(Oid)
            {
                case OID_GEN_LINK_SPEED:
                    *((PULONG)InformationBuffer) = FdoData->usLinkSpeed * 10000;
                    BytesWritten = sizeof(ULONG);

                    break;

                case OID_GEN_MEDIA_CONNECT_STATUS:
                default:
                    ASSERT(Oid == OID_GEN_MEDIA_CONNECT_STATUS);

                    CurrMediaState = NICIndicateMediaState(FdoData);

                    RtlMoveMemory(InformationBuffer,
                                  &CurrMediaState,
                                  sizeof(NDIS_MEDIA_STATE));

                    BytesWritten = sizeof(NDIS_MEDIA_STATE);
            }

            WdfRequestCompleteWithInformation(request, status, BytesWritten);
        }
    }

    //
    // Any OID set request pending?
    //
    status = NICGetIoctlRequest(FdoData->PendingIoctlQueue,
                            IOCTL_NDISPROT_SET_OID_VALUE,
                             &request);

    if(NT_SUCCESS(status)) {
        ULONG    PacketFilter;

        status = WdfRequestRetrieveOutputBuffer(request, sizeof(NDISPROT_SET_OID), &DataBuffer, &bufSize);
        if(NT_SUCCESS(status)) {

            pSet = (PNDISPROT_SET_OID)DataBuffer;
            Oid = pSet->Oid;
            InformationBuffer = &pSet->Data[0];
            if (Oid == OID_GEN_CURRENT_PACKET_FILTER)
            {

                RtlMoveMemory(&PacketFilter, InformationBuffer, sizeof(ULONG));


                WdfSpinLockAcquire(FdoData->Lock);

                status = NICSetPacketFilter(
                             FdoData,
                             PacketFilter);


                WdfSpinLockRelease(FdoData->Lock);

                if (status == STATUS_SUCCESS)
                {
                    FdoData->PacketFilter = PacketFilter;
                }

                WdfRequestCompleteWithInformation(request, status, 0);
            }
        }
    }

    //
    // Any read pending?
    //

    WdfSpinLockAcquire(FdoData->RcvLock);

    //
    // Start the NIC receive unit
    //
    status = NICStartRecv(FdoData);
    if (status != STATUS_SUCCESS)
    {
        MP_SET_HARDWARE_ERROR(FdoData);
    }


    WdfSpinLockRelease(FdoData->RcvLock);

    //
    // Send packets which have been queued while link detection was going on.
    //
    NICCheckForQueuedSends(FdoData);

    return status;
}
Esempio n. 2
0
/**
  This routine returns the current interrupt status and/or the transmitted buffer addresses.
  If the current interrupt status is returned, pending interrupts will be acknowledged by this
  command.  Transmitted buffer addresses that are written to the DB are removed from the transmit
  buffer queue.
  Normally, this command would be polled with interrupts disabled.
  The transmit buffers are returned in CdbPtr->DBaddr->TxBufer[0 - NumEntries].
  The interrupt status is returned in CdbPtr->StatFlags.

  @param  CdbPtr               Pointer to the command descriptor block.
  @param  AdapterInfo          Pointer to the NIC data structure information which
                               the UNDI driver is layering on..

  @return None

**/
VOID
UNDI_Status (
  IN  PXE_CDB           *CdbPtr,
  IN  NIC_DATA_INSTANCE *AdapterInfo
  )
{
  PXE_DB_GET_STATUS *DbPtr;
  PXE_DB_GET_STATUS TmpGetStatus;
  UINT16            Index;
  UINT16            Status;
  UINT16            NumEntries;
  RxFD              *RxPtr;

  //
  // Fill in temporary GetStatus storage.
  //
  RxPtr = &AdapterInfo->rx_ring[AdapterInfo->cur_rx_ind];

  if ((RxPtr->cb_header.status & RX_COMPLETE) != 0) {
    TmpGetStatus.RxFrameLen = RxPtr->ActualCount & 0x3fff;
  } else {
    TmpGetStatus.RxFrameLen = 0;
  }

  TmpGetStatus.reserved = 0;

  //
  // Fill in size of next available receive packet and
  // reserved field in caller's DB storage.
  //
  DbPtr = (PXE_DB_GET_STATUS *) (UINTN) CdbPtr->DBaddr;

  if (CdbPtr->DBsize > 0 && CdbPtr->DBsize < sizeof (UINT32) * 2) {
    CopyMem (DbPtr, &TmpGetStatus, CdbPtr->DBsize);
  } else {
    CopyMem (DbPtr, &TmpGetStatus, sizeof (UINT32) * 2);
  }

  //
  //
  //
  if ((CdbPtr->OpFlags & PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS) != 0) {
    //
    // DBsize of zero is invalid if Tx buffers are requested.
    //
    if (CdbPtr->DBsize == 0) {
      CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
      CdbPtr->StatCode  = PXE_STATCODE_INVALID_CDB;
      return ;
    }

    //
    // remember this b4 we overwrite
    //
    NumEntries = (UINT16) (CdbPtr->DBsize - sizeof (UINT64));

    //
    // We already filled in 2 UINT32s.
    //
    CdbPtr->DBsize = sizeof (UINT32) * 2;

    //
    // will claim any hanging free CBs
    //
    CheckCBList (AdapterInfo);

    if (AdapterInfo->xmit_done_head == AdapterInfo->xmit_done_tail) {
      CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY;
    } else {
      for (Index = 0; NumEntries >= sizeof (UINT64); Index++, NumEntries -= sizeof (UINT64)) {
        if (AdapterInfo->xmit_done_head != AdapterInfo->xmit_done_tail) {
          DbPtr->TxBuffer[Index]      = AdapterInfo->xmit_done[AdapterInfo->xmit_done_head];
          AdapterInfo->xmit_done_head = next (AdapterInfo->xmit_done_head);
          CdbPtr->DBsize += sizeof (UINT64);
        } else {
          break;
        }
      }
    }

    if (AdapterInfo->xmit_done_head != AdapterInfo->xmit_done_tail) {
      CdbPtr->StatFlags |= PXE_STATFLAGS_DB_WRITE_TRUNCATED;

    }
    //
    // check for a receive buffer and give it's size in db
    //
  }
  //
  //
  //
  if ((CdbPtr->OpFlags & PXE_OPFLAGS_GET_INTERRUPT_STATUS) != 0) {

    Status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus);
    AdapterInfo->Int_Status = (UINT16) (AdapterInfo->Int_Status | Status);

    //
    // acknoledge the interrupts
    //
    OutWord (AdapterInfo, (UINT16) (Status & 0xfc00), (UINT32) (AdapterInfo->ioaddr + SCBStatus));

    //
    // report all the outstanding interrupts
    //
    Status = AdapterInfo->Int_Status;
    if ((Status & SCB_STATUS_FR) != 0) {
      CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_RECEIVE;
    }

    if ((Status & SCB_STATUS_SWI) != 0) {
      CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_SOFTWARE;
    }
  }

  //
  // Return current media status
  //
  if ((CdbPtr->OpFlags & PXE_OPFLAGS_GET_MEDIA_STATUS) != 0) {
    AdapterInfo->PhyAddress = 0xFF;
    AdapterInfo->CableDetect = 1;

    if (!PhyDetect (AdapterInfo)) {
      CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_NO_MEDIA;
    }
  }

  return ;
}