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; }
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; }
/* 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(); }