⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xsusbhostapi.c

📁 优龙YLP270开发板 光盘自带的BIOS和实验例程源码 强烈推荐
💻 C
📖 第 1 页 / 共 5 页
字号:
				  edP->CompletionParam,
				  hcP->HcFmNumber.rw.FrameNumber);
	}
	freeGeneralTransfer(tdP);
      }
      else { /* Iso format */
	itdP = (USB_IsoTransferDescriptor_T*)tdP;

	DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Done iso TD %x, cc %d, cbp %x, be %x\n",
		   itdP,
		   itdP->Control.s.ConditionCode,
		   itdP->BufferPage0.d,
		   tdP->BufferEnd.p);
	DM_CwDbgPrintf(DM_CW_USB_HOST_0, "   PSW0 %x PSW1 %x PSW2 %x  PSW3 %x\n",
		   itdP->OffsetPSW.PSW[0],
		   itdP->OffsetPSW.PSW[1],
		   itdP->OffsetPSW.PSW[2],
		   itdP->OffsetPSW.PSW[3]);
	DM_CwDbgPrintf(DM_CW_USB_HOST_0, "   PSW4 %x PSW5 %x PSW6 %x  PSW7 %x\n",
		   itdP->OffsetPSW.PSW[4],
		   itdP->OffsetPSW.PSW[5],
		   itdP->OffsetPSW.PSW[6],
		   itdP->OffsetPSW.PSW[7]);

	if (edP->CompletionFunction) {
	  int reason = edP->HeadP.s.Halted ? USBD_CompletionHalted :
	    USBD_CompletionNormal;
	  edP->CompletionFunction(reason,
				  itdP,
				  edP->CompletionParam,
				  hcP->HcFmNumber.rw.FrameNumber);
	}
	freeIsoTransfer(itdP);
      }
    }
  }
}

/*----------------------------------------------------------------------
 * Spoon feed TDs one per frame to the endpoint. There appear to be devices
 * which can not handle the constant barrage of INs when the whole list is
 * queued at once (Intel Video Phone).
 *
 * Observed device behaviour (Intel USB Camera):
 *
 * - SETUP sequence OK (ACK in following packet)
 * - NAKs issued to first IN after SETUP, regardless of SOF delay. This
 *   continues for the whole frame until the next SOF at which time the device
 *   responds. Note, the PC HC does not attempt a retry on the endpoint until
 *   the next SOF, we continue to issue INs and get NAKs.
 * - Sequence flows fine from here out, SOF -> SOF -> IN -> DATA -> ACK
 * - OUT flow is fine, SOF -> SOF -> OUT -> DATA -> ACK
 *
 * The device seems to loose track of toggle and issues DATA1 PIDs. This
 * results in a protocol violation and the HC halts the endpoint. Ouch. Of
 * course it sounds like a broken client but ...
 */
static
void spoonFeedTDs(USB_EndpointDescriptor_T* edP,
		  USB_TransferDescriptor_T* lastP,
		  void * isControl)
{

  int i;
  USB_TransferDescriptor_T * tdP;

// Keep compiler quiet
  i=0;
  tdP=NULL;
  return;    
//

  tdP = (USB_TransferDescriptor_T*)(edP->HeadP.s.HeadP << 4);

  for(i=0; edP->TailP.p != lastP; i++) {

    /* Wait for the start of frame
     */
    while(!hcP->HcInterruptStatus.rw.StartofFrame)
      /* Empty */ ;
/*
    IOW_REG_BITSET(struct HcInterruptStatus_S,&hcP->HcInterruptStatus.rw,
		   StartofFrame,1);
*/
    hcP->HcInterruptStatus.rw.StartofFrame = 1;

    while(!hcP->HcInterruptStatus.rw.StartofFrame)
      /* Empty */ ;
/*
    IOW_REG_BITSET(struct HcInterruptStatus_S,&hcP->HcInterruptStatus.rw,
		   StartofFrame,1);
*/
    hcP->HcInterruptStatus.rw.StartofFrame = 1;

    /* Advance one descriptor
     */
    edP->TailP.p = tdP->NextTD.p;
    tdP = tdP->NextTD.p;

    if (isControl) {
/*
      IOW_REG_FIELD(struct HcCommandStatus_S,&hcP->HcCommandStatus.rw,
		    ControlListFilled,1);
*/
      hcP->HcCommandStatus.rw.ControlListFilled = 1;
    }
    else {
/*
      IOW_REG_FIELD(struct HcCommandStatus_S,&hcP->HcCommandStatus.rw,
		    BulkListFilled,1);
*/
      hcP->HcCommandStatus.rw.BulkListFilled = 1;
    }
  }
}

/*----------------------------------------------------------------------
 * Send a datagram
 */
static
UINT sendMessage(USB_EndpointDescriptor_T * edP,
		void * setup,
		void * buffer,
		int bufSize,
		int varOK,
		USB_DirectionTD_T dir,
		int * length)
{
  USB_TransferDescriptor_T * firstP = edP->TailP.p;
  USB_TransferDescriptor_T * lastP = edP->TailP.p;
  USB_TransferDescriptor_T * tdP = edP->TailP.p;
  void * lBuffer = buffer;
  int lBufSize = bufSize;
  int nextFrame, lastFrame;
  int frameMatchRetry = 1000; /* 100ms */

  usbxStats.controlStarts++;

  DM_CwDbgPrintf(DM_CW_USB_HOST_0, "ED tail %x, head %x\n", edP->TailP.p, edP->HeadP.p);

  edP->TotalTransferBytes = 0;
  edP->TotalOutstandingTD = 0;

  /* If this is a setup message send the first packet
   */
  if (setup) {
    tdP->Control.s.Direction_PID = UsbTDSetup;
    tdP->Control.s.DelayInterrupt = USB_NoInterrupt;
    tdP->Control.s.DataToggle = USB_SetupToggle;
    tdP->Control.s.ConditionCode = UsbNotAccessed;
    tdP->Control.s.BufferRounding = USBD_VarNotOK;
    tdP->Control.s.EndpointId = edP->Control.s.EndpointId;
    tdP->CurrentBufferPointer.p = setup;
    tdP->BufferEnd.p = (char*)setup + 7;
    if ((tdP->NextTD.p = newGeneralTransfer()) == NULL)
    {
        usbxStats.noTransfer++;
        LOGERRORX(UsbHost.loggedError, ERR_L_USB, ERR_S_XSUSB_SENDMESSAGE, 1, ERR_T_NOTRANSFER,
                    usbxStats.noTransfer, 0, 0);  
        
        return UsbHost.loggedError;
    }
    lastP = tdP;
    tdP = tdP->NextTD.p;
    edP->TotalOutstandingTD++;
    {
      char * p = (char*)setup;
      DM_CwDbgPrintf(DM_CW_USB_HOST_0, "%08X %02X %02X %02X %02X %02X %02X %02X %02X\n",
	      setup,
	      p[0],p[1],p[2],p[3],
	      p[4],p[5],p[6],p[7]);
    }
  }

  /* Loop and build the data packets for the message body (if any). The
   * packets must be larger or equal to the maximum packet size for the
   * endpoint (endpoint processing will halt otherwise).
   */
  if (lBufSize || (setup == NULL)) {
    int bytes;
    int toggle = USB_SetupDataToggle;

    while(lBufSize > 0) {
      bytes = lBufSize;
      if (bytes > edP->Control.s.MaximumPacketSize)
	    bytes = edP->Control.s.MaximumPacketSize;
	
      tdP->Control.s.Direction_PID = dir;
      tdP->Control.s.DelayInterrupt = USB_NoInterrupt;

      /* Setup data must follow the toggle rules, however, we'll force the
       * ordering because we always start with DATA1.
       */
      if (setup)
      {
	    tdP->Control.s.DataToggle = toggle;
	    toggle ^= 1;
      }
      else
	    tdP->Control.s.DataToggle = USB_DataToggle;

      tdP->Control.s.ConditionCode = UsbNotAccessed;
      tdP->Control.s.BufferRounding = varOK;
      tdP->Control.s.EndpointId = edP->Control.s.EndpointId;
      tdP->Control.s.DataTransfer = 1; /* Mark for completion processing */
      tdP->Control.s.ByteCount = bytes; /* Mark for completion processing */
      tdP->CurrentBufferPointer.p = lBuffer;
      tdP->BufferEnd.p = (char*)lBuffer + bytes-1;
      if ((tdP->NextTD.p = newGeneralTransfer()) == NULL)
      {
	    if (firstP->NextTD.p != NULL)
	      freeGeneralTransferList(firstP->NextTD.p);
	    usbxStats.noTransfer++;
        LOGERRORX(UsbHost.loggedError, ERR_L_USB, ERR_S_XSUSB_SENDMESSAGE, 2, ERR_T_NOTRANSFER,
                    usbxStats.noTransfer, 0, 0);  

	    return UsbHost.loggedError;
      }
      lastP = tdP;
      tdP = tdP->NextTD.p;
      edP->TotalOutstandingTD++;

      lBuffer = (char*)lBuffer + bytes;
      lBufSize -= edP->Control.s.MaximumPacketSize;
    }
  }

  /* If this is a setup message send the status packet
   */
  if (setup) {
    if (dir == UsbTDIn)
      tdP->Control.s.Direction_PID = UsbTDOut;
    else
      tdP->Control.s.Direction_PID = UsbTDIn;
    tdP->Control.s.DelayInterrupt = USB_NoInterrupt;
    tdP->Control.s.DataToggle = USB_StatusToggle;
    tdP->Control.s.ConditionCode = UsbNotAccessed;
    tdP->Control.s.BufferRounding = USBD_VarNotOK;
    tdP->Control.s.EndpointId = edP->Control.s.EndpointId;
    tdP->CurrentBufferPointer.p = NULL;
    tdP->BufferEnd.p = NULL;
    if ((tdP->NextTD.p = newGeneralTransfer()) == NULL)
    {
        if (firstP->NextTD.p != NULL)
	      freeGeneralTransferList(firstP->NextTD.p);
        usbxStats.noTransfer++;
        LOGERRORX(UsbHost.loggedError, ERR_L_USB, ERR_S_XSUSB_SENDMESSAGE, 3, ERR_T_NOTRANSFER,
                  usbxStats.noTransfer, 0, 0);  
        return UsbHost.loggedError;
    }

    lastP = tdP;
    tdP = tdP->NextTD.p;
    edP->TotalOutstandingTD++;
  }

  /* Enable interrupts on the last packet for synchronization
   */
  lastP->Control.s.DelayInterrupt = 0;
  lastP->Control.s.LastTD = 1;

#if 1
  dumpTransferList(firstP);
#endif

  /* Update the tail pointer and kick the host controller
   */
#if 1
  edP->TailP.p = tdP;
  if (setup) {
    hcP->HcCommandStatus.rw.ControlListFilled = 1;
  }
  else {
    hcP->HcCommandStatus.rw.BulkListFilled = 1;
  }
#else
  spoonFeedTDs(edP, tdP, setup);
#endif


  /* Wait for the completion of the messages. Use the frame period to time
   * the wait.
   */
  nextFrame = (hccaP->HccaFrameNumber + USBX_TIMEOUT_FC) & 0xffff;
  lastFrame = hccaP->HccaFrameNumber;
  while ((edP->TotalOutstandingTD > 0) &&
	 !edP->HeadP.s.Halted &&
	 (debugUsbNoTimeout || /* Debug only */
	  (((hccaP->HccaFrameNumber & 0x8000) &&
	    !(nextFrame & 0x8000)) || /* Wrap */
	   (hccaP->HccaFrameNumber < nextFrame)))) {

    /* Check for dead host controller
     */
    if (hccaP->HccaFrameNumber == lastFrame) {
      if (--frameMatchRetry < 0)
	break;
    }
    else
      frameMatchRetry = 1000;

    if (hcP->HcInterruptStatus.rw.WritebackDoneHead)
      processDoneQueue(); /* Need interlock with interrupt */

// temp
//   if (loopbackMode)
//      USBR_CheckLoopback();

    DM_WaitUs(100);
  }

  /* If we did not receive all packets find out why
   */
  if (edP->TotalOutstandingTD > 0)
  {
        DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Outstanding requests, %d\n", edP->TotalOutstandingTD);

        // Check the endpoint queue status
        if (edP->HeadP.s.Halted)
        {

            DM_CwDbgPrintf(DM_CW_USB_HOST_1, "Processing on endpoint halted!\n");
            LOGERRORX(UsbHost.loggedError, ERR_L_USB, ERR_S_XSUSB_SENDMESSAGE, 1, ERR_T_EPHALTED,
                    0, 0, 0);  

            clearTDs(edP); /* Side effect will clear halted */
            usbxStats.halted++;
            return UsbHost.loggedError;
        }

        /* Must have been a timeout
         */
	    DM_CwDbgPrintf(DM_CW_USB_HOST_1, "HccaFrameNumber, %d\n", hccaP->HccaFrameNumber);
        LOGERRORX(UsbHost.loggedError, ERR_L_USB, ERR_S_XSUSB_SENDMESSAGE, 1, ERR_T_TIMEOUT,
                  0, 0, 0);  

        clearTDs(edP);
        usbxStats.timeout++;
        return UsbHost.loggedError;
    }

    *length = edP->TotalTransferBytes < USBD_BUFSIZ ? edP->TotalTransferBytes : 0;
	return UsbHost.loggedError;
}

/*----------------------------------------------------------------------
 * Start an isochronous transfer, assume buffers are in non cached space
 */
extern
UINT XsUsbHostStartIsoTransfer(USB_EndpointDescriptor_T * edP,
			                char * bufP,
			                int length,
			                USBD_CompletionCallback_T completion,
			                USBD_CallbackParam_T param)
{
#define ISO_FRAMES 8
  USB_IsoTransferDescriptor_T * itdP = edP->TailP.ip;
  int startFrame = edP->IsoStartFrame + ISO_FRAMES;
  int i;

  usbxStats.isoStarts++;

  /* Check to see if the endpoint has halted and kick it if so.
   */
#if 0
  if (edP->HeadP.s.Halted) { /* Endpoint halted ?? */
    edP->HeadP.s.Halted = 0;
    //return UsbdHalted;
  }
#endif

  if (startFrame < hcP->HcFmNumber.rw.FrameNumber+1)
    startFrame = hcP->HcFmNumber.rw.FrameNumber+1;

  DM_CwDbgPrintf(DM_CW_USB_HOST_0, "Start ISO %x, buf %x, frame %x, start %x\n",
	itdP,
	bufP,
	hcP->HcFmNumber.rw.FrameNumber,
	startFrame);

  if (length != ISO_FRAMES * edP->Control.s.MaximumPacketSize)
  {
        usbxStats.badIsoBuffer++;
        DM_CwDbgPrintf(DM_CW_USB_HOST_1, "Incorrect isochronous buffer length %d\n", length);
        LOGERRORX(UsbHost.loggedError, ERR_L_USB, ERR_S_XSUSB_STARTISO, 1, ERR_T_UNEXPECTED,
                                    usbxStats.badIsoBuffer, UsbdBadIsoBuffer, 0);  
    	return UsbHost.loggedError;
  }

  /* Start at the end of the last descriptor if we're queuing in the
   * active window, otherwise start on the next frame
   */
  itdP->Control.s.StartFrame = startFrame;
  itdP->Control.s.EndpointId = edP->Control.s.EndpointId;
  itdP->Control.s.DelayInterrupt = 0;
  itdP->Control.s.FrameCount = ISO_FRAMES-1;
  itdP->Control.s.ConditionCode = UsbNotAccessed;
  itdP->BufferPage0.s.BufferPage = (unsigned)bufP >> 12;
  if ((itdP->NextTD.p = newIsoTransfer()) == NULL)
  {
        usbxStats.noTransfer++;
        LOGERRORX(UsbHost.loggedError, ERR_L_USB, ERR_S_XSUSB_STARTISO, 2, ERR_T_NOTRANSFER,
                                    usbxStats.noTransfer, UsbdNoTransfer, 0);  
    	return UsbHost.loggedError;
  }

  itdP->BufferEnd.p = bufP + length - 1;
  for (i=0; i < 8; i++) {
    /* Note there are two encodings of UsbNotAccessed. The offset field is
     * actually 13 bits, the MSB is the low bit of the condition code. We
     * use UsbNotAccessed0 here and then allow the LSB to be set with the
     * MSB of the offset. Interesting bit sharing ...
     *
     * Note also bit 12 is 0 is the offset is is page0 of the buffer, this
     * is not the same as the value of the buffer's bit 12.
     */
    itdP->OffsetPSW.Offset[i] = (UsbNotAccessed0 << 12) |
      ((unsigned)bufP & 0xfff) |
      (((unsigned)bufP ^ (unsigned)itdP->BufferPage0.p) & 0x1000);

    bufP += edP->Control.s.MaximumPacketSize;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -