Beispiel #1
0
static ULONG
XenScsi_HwScsiFindAdapter(PVOID DeviceExtension, PVOID Reserved1, PVOID Reserved2, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PUCHAR Reserved3)
{
  ULONG i;
  PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
  PACCESS_RANGE access_range;
  PUCHAR ptr;
  USHORT type;
  PCHAR setting, value, value2;
  vscsiif_sring_t *sring;
  CHAR path[128];

  UNREFERENCED_PARAMETER(Reserved1);
  UNREFERENCED_PARAMETER(Reserved2);
  UNREFERENCED_PARAMETER(ArgumentString);
  UNREFERENCED_PARAMETER(Reserved3);

  FUNCTION_ENTER();
  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  
  xsdd->scsiport_paused = TRUE; /* wait for initial scan */

  KdPrint((__DRIVER_NAME "     BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
  KdPrint((__DRIVER_NAME "     BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));

  if (!ConfigInfo->BusInterruptVector)
  {
    KdPrint((__DRIVER_NAME "     No Interrupt assigned\n"));
    return SP_RETURN_BAD_CONFIG;
  }

  if (ConfigInfo->NumberOfAccessRanges != 1)
  {
    KdPrint((__DRIVER_NAME "     NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
    return SP_RETURN_BAD_CONFIG;
  }

  ptr = NULL;
  access_range = &((*(ConfigInfo->AccessRanges))[0]);
  KdPrint((__DRIVER_NAME "     RangeStart = %08x, RangeLength = %08x\n",
    access_range->RangeStart.LowPart, access_range->RangeLength));
  ptr = ScsiPortGetDeviceBase(
    DeviceExtension,
    ConfigInfo->AdapterInterfaceType,
    ConfigInfo->SystemIoBusNumber,
    access_range->RangeStart,
    access_range->RangeLength,
    !access_range->RangeInMemory);
  if (!ptr)
  {
    KdPrint((__DRIVER_NAME "     Unable to map range\n"));
    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));  
    return SP_RETURN_BAD_CONFIG;
  }
  sring = NULL;
  xsdd->event_channel = 0;
  while((type = GET_XEN_INIT_RSP(&ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
  {
    switch(type)
    {
    case XEN_INIT_TYPE_RING: /* frontend ring */
      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
      if (strcmp(setting, "ring-ref") == 0)
      {
        sring = (vscsiif_sring_t *)value;
        FRONT_RING_INIT(&xsdd->ring, sring, PAGE_SIZE);
      }
      break;
    //case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
    case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
      if (strcmp(setting, "event-channel") == 0)
      {
        xsdd->event_channel = PtrToUlong(value);
      }
      break;
    case XEN_INIT_TYPE_READ_STRING_BACK:
    case XEN_INIT_TYPE_READ_STRING_FRONT:
      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
      break;
    case XEN_INIT_TYPE_VECTORS:
      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_VECTORS\n"));
      if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
        ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
      {
        KdPrint((__DRIVER_NAME "     vectors mismatch (magic = %08x, length = %d)\n",
          ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
        KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
        return SP_RETURN_BAD_CONFIG;
      }
      else
        memcpy(&xsdd->vectors, value, sizeof(XENPCI_VECTORS));
      break;
    case XEN_INIT_TYPE_GRANT_ENTRIES:
      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
      xsdd->grant_entries = (USHORT)PtrToUlong(value);
      memcpy(&xsdd->grant_free_list, value2, sizeof(grant_ref_t) * xsdd->grant_entries);
      xsdd->grant_free = xsdd->grant_entries;
      break;
    default:
      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_%d\n", type));
      break;
    }
  }

  if (sring == NULL || xsdd->event_channel == 0)
  {
    KdPrint((__DRIVER_NAME "     Missing settings\n"));
    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    return SP_RETURN_BAD_CONFIG;
  }
  
  ConfigInfo->ScatterGather = TRUE;
  ConfigInfo->NumberOfPhysicalBreaks = VSCSIIF_SG_TABLESIZE - 1;
  ConfigInfo->MaximumTransferLength = VSCSIIF_SG_TABLESIZE * PAGE_SIZE;
  ConfigInfo->CachesData = FALSE;
  ConfigInfo->NumberOfBuses = 4; //SCSI_MAXIMUM_BUSES; //8
  ConfigInfo->MaximumNumberOfTargets = 16;
  ConfigInfo->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS; // 8
  ConfigInfo->BufferAccessScsiPortControlled = TRUE;
  if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
  {
    ConfigInfo->Master = TRUE;
    ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
    KdPrint((__DRIVER_NAME "     Dma64BitAddresses supported\n"));
  }
  else
  {
    ConfigInfo->Master = FALSE;
    KdPrint((__DRIVER_NAME "     Dma64BitAddresses not supported\n"));
  }
  ConfigInfo->InitiatorBusId[0] = 7;
  ConfigInfo->InitiatorBusId[1] = 7;
  ConfigInfo->InitiatorBusId[2] = 7;
  ConfigInfo->InitiatorBusId[3] = 7;
  xsdd->shadow_free = 0;
  memset(xsdd->shadows, 0, sizeof(vscsiif_shadow_t) * SHADOW_ENTRIES);
  for (i = 0; i < SHADOW_ENTRIES; i++)
  {
    xsdd->shadows[i].req.rqid = (USHORT)i;
    put_shadow_on_freelist(xsdd, &xsdd->shadows[i]);
  }

  if (!dump_mode)
  {
    InitializeListHead(&xsdd->dev_list_head);
    /* should do something if we haven't enumerated in a certain time */
    RtlStringCbCopyA(path, ARRAY_SIZE(path), xsdd->vectors.backend_path);
    RtlStringCbCatA(path, ARRAY_SIZE(path), "/vscsi-devs");
    xsdd->vectors.XenBus_AddWatch(xsdd->vectors.context, XBT_NIL, path,
      XenScsi_DevWatch, xsdd);
  }
  FUNCTION_EXIT();

  return SP_RETURN_FOUND;
}
Beispiel #2
0
VOID PrintFtlPkt(
    IN char *strPrefix,
    IN FLT_PKT* pFltPkt,
    IN ULONG uNewIp,
    IN BOOLEAN bOut
)
{
    TIME_FIELDS TimeFields;
    char Message[255];
    char MessagePart[30];
    LARGE_INTEGER time;

    KeQuerySystemTime(&time);
    ExSystemTimeToLocalTime(&time, &time);
    RtlTimeToTimeFields(&time, &TimeFields);

    RtlStringCbPrintfA(Message, sizeof(Message), "%02d:%02d:%02d.%03d ",
        TimeFields.Hour, TimeFields.Minute,
        TimeFields.Second, TimeFields.Milliseconds);

    if (!bOut) {
        RtlStringCbCatA(Message, sizeof(Message), "IN  ");
    }
    else {
        RtlStringCbCatA(Message, sizeof(Message), "OUT ");
    }

    RtlStringCbCatA(Message, sizeof(Message), strPrefix);
    RtlStringCbCatA(Message, sizeof(Message), " ");


    if (NULL == pFltPkt->pEth) {
        goto out;
    }

    RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "%02x-%02x-%02x-%02x-%02x-%02x",
        pFltPkt->pEth->ether_src[0],
        pFltPkt->pEth->ether_src[1],
        pFltPkt->pEth->ether_src[2],
        pFltPkt->pEth->ether_src[3],
        pFltPkt->pEth->ether_src[4],
        pFltPkt->pEth->ether_src[5]);
    RtlStringCbCatA(Message, sizeof(Message), MessagePart);
    RtlStringCbCatA(Message, sizeof(Message), "->");
    RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "%02x-%02x-%02x-%02x-%02x-%02x",
        pFltPkt->pEth->ether_dst[0],
        pFltPkt->pEth->ether_dst[1],
        pFltPkt->pEth->ether_dst[2],
        pFltPkt->pEth->ether_dst[3],
        pFltPkt->pEth->ether_dst[4],
        pFltPkt->pEth->ether_dst[5]);
    RtlStringCbCatA(Message, sizeof(Message), MessagePart);

    switch (pFltPkt->pEth->ether_type) {
    case ETHERNET_TYPE_ARP_NET:
        RtlStringCbCatA(Message, sizeof(Message), " ARP ");

        if (NULL == pFltPkt->pArp)
            goto out;

        if (ARP_REQUEST_CODE == pFltPkt->pArp->ea_hdr.ar_op) {
            RtlStringCbCatA(Message, sizeof(Message), "Request ");
        }
        else if (pFltPkt->pArp->ea_hdr.ar_op == ARP_REPLY_CODE) {
            RtlStringCbCatA(Message, sizeof(Message), "Reply   ");
        }

        RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "%d.%d.%d.%d",
            pFltPkt->pArp->arp_spa[0],
            pFltPkt->pArp->arp_spa[1],
            pFltPkt->pArp->arp_spa[2],
            pFltPkt->pArp->arp_spa[3]);
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);

        RtlStringCbCatA(Message, sizeof(Message), "->");

        PRINT_IP(MessagePart, pFltPkt->pArp->arp_tpa);
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);
        break;

    case ETHERNET_TYPE_IP_NET:

        RtlStringCbCatA(Message, sizeof(Message), " IP  ");

        if (NULL == pFltPkt->pIp)
            goto out;

        RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "ID %04x ", RtlUshortByteSwap(pFltPkt->pIp->ip_id));
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);

        PRINT_IP(MessagePart, &pFltPkt->pIp->ip_src);
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);
        if (uNewIp && bOut) {
            RtlStringCbCatA(Message, sizeof(Message), "[");
            PRINT_IP(MessagePart, &uNewIp);
            RtlStringCbCatA(Message, sizeof(Message), MessagePart);
            RtlStringCbCatA(Message, sizeof(Message), "]");
        }
        RtlStringCbCatA(Message, sizeof(Message), "->");
        PRINT_IP(MessagePart, &pFltPkt->pIp->ip_dst);
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);
        if (uNewIp && !bOut) {
            RtlStringCbCatA(Message, sizeof(Message), "[");
            PRINT_IP(MessagePart, &uNewIp);
            RtlStringCbCatA(Message, sizeof(Message), MessagePart);
            RtlStringCbCatA(Message, sizeof(Message), "]");
        }

        switch (pFltPkt->pIp->ip_proto) {
        case IPPROTO_TCP:
            RtlStringCbCatA(Message, sizeof(Message), " TCP");
            break;
        case IPPROTO_ICMP:
            RtlStringCbCatA(Message, sizeof(Message), " ICMP");
            break;
        case IPPROTO_UDP:
            RtlStringCbCatA(Message, sizeof(Message), " UDP");
            break;
        default:
            RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " proto=%04x", pFltPkt->pIp->ip_proto);
            RtlStringCbCatA(Message, sizeof(Message), MessagePart);
            break;
        }

        if (pFltPkt->pTcp) {

            RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " %d->%d ",
                RtlUshortByteSwap(pFltPkt->pTcp->th_sport),
                RtlUshortByteSwap(pFltPkt->pTcp->th_dport));

            if (pFltPkt->pTcp->th_flags & TCP_FIN_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "F");
            if (pFltPkt->pTcp->th_flags & TCP_SYN_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "S");
            if (pFltPkt->pTcp->th_flags & TCP_RST_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "R");
            if (pFltPkt->pTcp->th_flags & TCP_PSH_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "P");
            if (pFltPkt->pTcp->th_flags & TCP_URG_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "U");
            if (pFltPkt->pTcp->th_flags & TCP_ACK_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "A");
            // https://tools.ietf.org/html/rfc3168
            if (pFltPkt->pTcp->th_flags & TCP_ECE_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "E");
            if (pFltPkt->pTcp->th_flags & TCP_CWR_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "C");

            RtlStringCbCatA(Message, sizeof(Message), MessagePart);

            RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " SEQ:%u",
                RtlUlongByteSwap(pFltPkt->pTcp->th_seq));

            RtlStringCbCatA(Message, sizeof(Message), MessagePart);

            RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " ACK:%u",
                RtlUlongByteSwap(pFltPkt->pTcp->th_ack));

        }
        else if (pFltPkt->pUdp) {

            RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " %d->%d",
                RtlUshortByteSwap(pFltPkt->pUdp->uh_sport),
                RtlUshortByteSwap(pFltPkt->pUdp->uh_dport));

        }
        else if (pFltPkt->pIcmp) {

            RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " %d",
                RtlUshortByteSwap(pFltPkt->pIcmp->icmp_hun.idseq.id));

        }
        else {
            MessagePart[0] = 0;
        }
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);
        break;
    default:
        RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " UNK %04x", RtlUshortByteSwap(pFltPkt->pEth->ether_type));
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);
        break;
    }

out:
    RtlStringCbCatA(Message, sizeof(Message), "\n");

    DbgPrint(Message);
    return;
}
Beispiel #3
0
/* If Initialize fails then the watch still gets called but the waits will never be acked... */
static VOID
XenScsi_DevWatch(PCHAR path, PVOID DeviceExtension)
{
  PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
  CHAR tmp_path[128];
  PCHAR msg;
  PCHAR *devices;
  PCHAR value;
  scsi_dev_t *dev;
  ULONG i;
  ULONG dev_no;
  ULONG state;
  LARGE_INTEGER wait_time;
  #if DBG
  ULONG oldpause;
  #endif

  UNREFERENCED_PARAMETER(path);
  
  /* this can only be called from a watch and so is always serialised */
  FUNCTION_ENTER();

  #if DBG
  oldpause =
  #endif
    InterlockedExchange(&xsdd->shared_paused, SHARED_PAUSED_PASSIVE_PAUSED);
  ASSERT(oldpause == SHARED_PAUSED_SCSIPORT_UNPAUSED);
  
  while (InterlockedCompareExchange(&xsdd->shared_paused, SHARED_PAUSED_SCSIPORT_PAUSED, SHARED_PAUSED_SCSIPORT_PAUSED) != SHARED_PAUSED_SCSIPORT_PAUSED)
  {
    KdPrint((__DRIVER_NAME "     Waiting for pause...\n"));
    wait_time.QuadPart = -100 * 1000 * 10; /* 100ms */
    KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
  }
  
  KdPrint((__DRIVER_NAME "     Watch triggered on %s\n", path));
  RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.backend_path);
  RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs");
  msg = xsdd->vectors.XenBus_List(xsdd->vectors.context, XBT_NIL, tmp_path, &devices);
  if (msg)
  {
    /* this is pretty fatal ... */
    KdPrint((__DRIVER_NAME "     cannot read - %s\n", msg));
    return;
  }
  for (dev = (scsi_dev_t *)xsdd->dev_list_head.Flink;
    dev != (scsi_dev_t *)&xsdd->dev_list_head;
    dev = (scsi_dev_t *)dev->entry.Flink)
  {
    dev->validated = FALSE;
  }
  
  for (i = 0; devices[i]; i++)
  {
    if (strncmp(devices[i], "dev-", 4) != 0)
    {
      XenPci_FreeMem(devices[i]);
      break; /* not a dev so we are not interested */
    }
    dev_no = atoi(devices[i] + 4);
    RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.backend_path);
    RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs/");
    RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), devices[i]);
    RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/state");
    msg = xsdd->vectors.XenBus_Read(xsdd->vectors.context, XBT_NIL, tmp_path, &value);
    if (msg)
    {
      KdPrint((__DRIVER_NAME "     failed to read state for device %d\n", dev_no));
      state = 0;
    }
    else
      state = atoi(value);
    for (dev = (scsi_dev_t *)xsdd->dev_list_head.Flink;
      dev != (scsi_dev_t *)&xsdd->dev_list_head;
      dev = (scsi_dev_t * )dev->entry.Flink)
    {
      if (dev->dev_no == dev_no)
        break;
    }
    if (dev == (scsi_dev_t *)&xsdd->dev_list_head)
    {
      KdPrint((__DRIVER_NAME "     new dev %d\n", dev_no));
      dev = ExAllocatePoolWithTag(NonPagedPool, sizeof(scsi_dev_t), XENSCSI_POOL_TAG);
      dev->dev_no = dev_no;
      dev->state = state;
      dev->validated = TRUE;
      RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.backend_path);
      RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs/");
      RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), devices[i]);
      RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/v-dev");
      msg = xsdd->vectors.XenBus_Read(xsdd->vectors.context, XBT_NIL, tmp_path, &value);
      if (msg)
      {
        KdPrint((__DRIVER_NAME "     failed to read v-dev for device %d\n", dev_no));
        continue;
      }
      else
      {
        XenScsi_ParseBackendDevice(dev, value);
        // should verify that the controller = this
      }
      RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.path);
      RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs/");
      RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), devices[i]);
      RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/state");
      msg = xsdd->vectors.XenBus_Write(xsdd->vectors.context, XBT_NIL, tmp_path, "4");
      if (msg)
      {
        KdPrint((__DRIVER_NAME "     failed to write state %d to %s\n", 4, tmp_path));
        continue;
      }
      KdPrint((__DRIVER_NAME "     setting changes[%d]\n", dev->channel));
      xsdd->bus_changes[dev->channel] = 1;
      InsertTailList(&xsdd->dev_list_head, (PLIST_ENTRY)dev);
    }
    else
    {
      // need to manage state change
      // and write frontend state
      dev->state = state;
      dev->validated = TRUE;
      KdPrint((__DRIVER_NAME "     existing dev %d state = %d\n", dev_no, dev->state));
    }
    XenPci_FreeMem(devices[i]);
  }
  XenPci_FreeMem(devices);

  #if DBG
  oldpause =
  #endif
    InterlockedExchange(&xsdd->shared_paused, SHARED_PAUSED_PASSIVE_UNPAUSED);
  ASSERT(oldpause == SHARED_PAUSED_SCSIPORT_PAUSED);

  while (InterlockedCompareExchange(&xsdd->shared_paused, SHARED_PAUSED_SCSIPORT_UNPAUSED, SHARED_PAUSED_SCSIPORT_UNPAUSED) != SHARED_PAUSED_SCSIPORT_UNPAUSED)
  {
    KdPrint((__DRIVER_NAME "     Waiting for unpause...\n"));
    wait_time.QuadPart = -100 * 1000 * 10; /* 100ms */
    KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
  }
  KdPrint((__DRIVER_NAME "     Unpaused\n"));

  FUNCTION_EXIT();
}