DWORD driver::rawio(DWORD ioctl, void *inbuf, DWORD insize, void *outbuf, DWORD outsize, OVERLAPPED *ovl) { TRACEV("[driver] [rawio] > Entering routine."); DWORD bytes; BOOL ret = DeviceIoControl(m_dev, ioctl, inbuf, insize, outbuf, outsize, &bytes, ovl); if(ret) { TRACEV("[driver] [rawio] Successfully sent IOCTL to driver"); TRACEV("[driver] [rawio] < Leaving routine."); return ERROR_SUCCESS; } else { DWORD err = GetLastError(); if (err == ERROR_IO_PENDING) { TRACEV("[driver] [rawio] IO_PENDING while sending IOCTL to driver"); err = ERROR_SUCCESS; } else { TRACEE("[driver] [rawio] ERROR sending IOCTL to driver"); } TRACEV("[driver] [rawio] < Leaving routine."); return err; } } // End of rawio()
bool driver::isrunning() { TRACEV("[driver] [isrunning] > Entering routine."); SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if(!manager) throw win32_error("OpenSCManager"); SC_HANDLE service = OpenService(manager, m_name.c_str(), SERVICE_ALL_ACCESS); if(!service) { DWORD err = GetLastError(); CloseServiceHandle(manager); throw win32_error("OpenService", err); } SERVICE_STATUS status; BOOL ret = QueryServiceStatus(service, &status); if(!ret) { DWORD err = GetLastError(); CloseServiceHandle(service); CloseServiceHandle(manager); throw win32_error("QueryServiceStatus", err); } CloseServiceHandle(service); CloseServiceHandle(manager); TRACEV("[driver] [isrunning] < Leaving routine."); return status.dwCurrentState == SERVICE_RUNNING; } // End of isrunning()
void pbfilter_base::start_thread() { TRACEV("[pbfilter_base] [start_thread] > Entering routine."); m_runthread = true; m_exitevt = CreateEvent(0, TRUE, FALSE, 0); if(!m_exitevt) throw win32_error("CreateEvent", 0); TRACEI("[pbfilter_base] [start_thread] creating thread_thunk"); m_thread = CreateThread(0, 0, thread_thunk, this, 0, 0); if(!m_thread) { DWORD err = GetLastError(); CloseHandle(m_exitevt); TRACEE("[pbfilter_base] [start_thread] ERROR creating thread_thunk!!"); throw win32_error("CreateThread", err); } TCHAR chBuf[256]; _stprintf_s(chBuf, sizeof(chBuf)/2, _T("[pbfilter_base] [start_thread] thread_thunk created with handle:[%p]"), m_thread); g_tlog.LogMessage(chBuf, TRACELOG_LEVEL_VERBOSE); TRACEV("[pbfilter_base] [start_thread] < Leaving routine."); } // End of start_thread()
void pbfilter_base::stop_thread() { TRACEV("[pbfilter_base] [stop_thread] > Entering routine."); m_runthread = false; SetEvent(m_exitevt); TRACEV("[pbfilter_base] [stop_thread] waiting for thread to terminate"); WaitForSingleObject(m_thread, INFINITE); CloseHandle(m_thread); CloseHandle(m_exitevt); TRACEV("[pbfilter_base] [stop_thread] < Leaving routine."); } // End of stop_thread()
void prov_pgm_wwpns() { /*------------------------------------------------------------------------*/ /* Local Variables */ /*------------------------------------------------------------------------*/ prov_adapter_info_t l_adapters[MAX_NUM_ADAPTERS]; int l_num_adapters = MAX_NUM_ADAPTERS; bool l_rc = false; int l_curr_adapter = 0; /*------------------------------------------------------------------------*/ /* Code */ /*------------------------------------------------------------------------*/ bzero(l_adapters, sizeof(l_adapters)); l_rc = provGetAllAdapters(l_adapters, &l_num_adapters); if(l_rc == false) { TRACEE("Error occurred in call to provGetAllAdapters. This is likely due to missing or invalid adapter VPD.\n"); } else { TRACEV("Got back %d adapters\n", l_num_adapters); for(l_curr_adapter = 0; l_curr_adapter < l_num_adapters; l_curr_adapter++) { l_rc = provInitAdapter(&l_adapters[l_curr_adapter]); if(l_rc == false) { TRACEE("Error init'ing adapter '%s'\n",l_adapters[l_curr_adapter].afu_name); } } } }
void prov_get_all_adapters() { /*------------------------------------------------------------------------*/ /* Local Variables */ /*------------------------------------------------------------------------*/ prov_adapter_info_t l_adapters[MAX_NUM_ADAPTERS]; int l_num_adapters = MAX_NUM_ADAPTERS; bool l_rc = false; int l_curr_adapter = 0; int l_curr_wwpn = 0; /*------------------------------------------------------------------------*/ /* Code */ /*------------------------------------------------------------------------*/ bzero(l_adapters, sizeof(l_adapters)); l_rc = provGetAllAdapters(l_adapters, &l_num_adapters); if(l_rc == false) { TRACEE("Error occurred in call to provGetAllAdapters\n"); } else { TRACEV("Got back %d adapters\n", l_num_adapters); for(l_curr_adapter = 0; l_curr_adapter < l_num_adapters; l_curr_adapter++) { TRACED("Adapter '%s'\n", l_adapters[l_curr_adapter].afu_name); TRACED("PCI Path '%s'\n", l_adapters[l_curr_adapter].pci_path); for(l_curr_wwpn = 0; l_curr_wwpn < MAX_WWPNS_PER_ADAPTER; l_curr_wwpn++) { TRACEI(" Port %d WWPN: 0x%s\n", l_curr_wwpn, l_adapters[l_curr_adapter].wwpn[l_curr_wwpn]); } } } }
void pbfilter_base::setblock(bool block) { TRACEV("[pbfilter_base] [setblock] > Entering routine."); TRACEI("[pbfilter_base] [setblock] acquiring lock"); mutex::scoped_lock lock(m_blocklock); if(block != m_block) { if (block) TRACEI("[pbfilter_base] [setblock] resetting m_block to: [true]") else TRACEI("[pbfilter_base] [setblock] resetting m_block to: [false]"); m_block = block; int data = block ? 1 : 0; TRACEI("[pbfilter_base] [setblock] sending block request to driver...") DWORD ret = m_filter.write(IOCTL_PEERBLOCK_HOOK, &data, sizeof(data)); TRACEI("[pbfilter_base] [setblock] ...block request sent") if(ret != ERROR_SUCCESS) { TRACEERR("[pbfilter_base] [setblock]", L"sending block request to driver", ret); throw win32_error("DeviceIoControl", ret); } } else {
DWORD driver::cancelio() { TRACEV("[driver] [cancelio] Entering routine."); BOOL ret = CancelIo(m_dev); return ret ? ERROR_SUCCESS : GetLastError(); } // End of cancelio()
int main (int argc, char *argv[]) { /*------------------------------------------------------------------------*/ /* Local Variables */ /*------------------------------------------------------------------------*/ int32_t rc = 0; /*-------------------------------------------------------------------------*/ /* Code */ /*-------------------------------------------------------------------------*/ memset(&g_args,0,sizeof(g_args)); argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, &g_args); if(g_args.loopback) { TRACEV("Calling prov_get_all_adapters\n"); bool l_success = prov_loopback(); if(!l_success) { rc = 1; //arbitrary non-zero RC } } if(g_args.list_afus) { TRACEV("Calling prov_get_all_adapters\n"); prov_get_all_adapters(); } if(g_args.wwpn_read) { TRACEV("Calling prov_get_wwpns\n"); prov_get_wwpns(); } if(g_args.wwpn_program) { TRACEV("Calling prov_pgm_wwpns\n"); prov_pgm_wwpns(); } return(rc); }
DWORD driver::getresult(OVERLAPPED *ovl) { TRACEV("[driver] [getresult] Entering routine."); DWORD bytes; BOOL ret = GetOverlappedResult(m_dev, ovl, &bytes, TRUE); return ret ? ERROR_SUCCESS : GetLastError(); } // End of getresult()
bool prov_loopback() { /*------------------------------------------------------------------------*/ /* Local Variables */ /*------------------------------------------------------------------------*/ prov_adapter_info_t l_adapters[MAX_NUM_ADAPTERS]; int l_num_adapters = MAX_NUM_ADAPTERS; bool l_rc = true; bool l_adapter_rc = false; int l_curr_adapter = 0; uint64_t l_loopback_time_us = 0; /*------------------------------------------------------------------------*/ /* Code */ /*------------------------------------------------------------------------*/ bzero(l_adapters, sizeof(l_adapters)); l_rc = provGetAllAdapters(l_adapters, &l_num_adapters); if(l_rc == false) { printf("ERROR: Error occurred in call to provGetAllAdapters. This is likely due to missing or invalid adapter VPD.\n"); } else { printf("Running Loopback Diagnostic Tests...\n"); l_loopback_time_us = (uint64_t)g_args.loopback_time * TIME_1S_US; TRACEV("Running time for test in microseconds: %"PRIu64"\n",l_loopback_time_us); TRACEV("Got back %d adapters\n", l_num_adapters); for(l_curr_adapter = 0; l_curr_adapter < l_num_adapters; l_curr_adapter++) { l_adapter_rc = provLoopbackTest(&l_adapters[l_curr_adapter], l_loopback_time_us); const char *l_result = (l_adapter_rc == true) ? "SUCCESS" : "FAIL"; printf("Adapter '%s' result: %s\n",l_adapters[l_curr_adapter].afu_name, l_result); if(l_adapter_rc == false) { //if any test fails, all tests fail l_rc = false; } } } return l_rc; }
bool wait_port_state(const uint8_t* i_afu_psa_addr, const int i_port_offset, const bool i_online) { //Locals bool l_rc = false; uint8_t i = 0; uint32_t mmio_data32 = 0; uint32_t l_target_status = FC_MTIP_STATUS_MASK_OFFLINE; if(i_online) { l_target_status = FC_MTIP_STATUS_MASK_ONLINE; } TRACEV("Waiting for port status mask equal to 0x%08x\n", l_target_status); //Code for(i=0; i<MAX_PORT_STATUS_RETRY_COUNT; i++) { //FC_MTIP_STATUS is 32-bit as per MTIP programming reference guide, page 50 //bit 4 of the register defines whether we are offline //bit 5 defines if we are online. mmio_data32 = in_mmio32((__u64*)&i_afu_psa_addr[FC_MTIP_STATUS + i_port_offset]); TRACEV("FC_MTIP_STATUS (0x%08X): 0x%08X\n", FC_MTIP_STATUS + i_port_offset, mmio_data32); //TODO: define a bitwise union for this structure to ease manipulation if( (mmio_data32 & 0x30) == l_target_status) { //port is now in desired state l_rc = true; TRACEV("Port state bits are 0x%02x.\n", l_target_status); if(i_online) { TRACEI("Port is now online\n"); } else { TRACEI("Port is now offline\n"); } break; //break inner for loop... } TRACEV("Sleeping to retry again...\n"); usleep(PORT_STATUS_RETRY_INTERVAL_US); } //rc is only set if we break out of the loop return l_rc; }
void * mmap_afu_wwpn_registers(int afu_master_fd) { //Locals void *l_ret_ptr = NULL; //Code TRACEI("Attempting to mmap 0x%016X bytes of problem state.\n", FC_PORT_MMAP_SIZE); l_ret_ptr = mmap(NULL, FC_PORT_MMAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, afu_master_fd, 0); TRACEV("MMAP AFU Master complete\n"); if (l_ret_ptr == MAP_FAILED) { TRACEE("Unable to mmap problem state regs. errno = %d (%s)\n", errno, strerror(errno)); l_ret_ptr = NULL; } return l_ret_ptr; }
/* * Exverror is called to raise the error exception. If the second argument * is not NULL then error prints an error message using printf style * formatting. It then raises the error exception. */ static void exverror(int cond, const char *msg, va_list ap) { #ifdef DEBUG if (msg) { TRACE(("exverror(%d, \"", cond)); TRACEV((msg, ap)); TRACE(("\") pid=%d\n", getpid())); } else TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid())); if (msg) #endif exvwarning(-1, msg, ap); flushall(); exraise(cond); /* NOTREACHED */ }
void driver::close() { TRACEI("[driver] [close] > Entering routine."); tstring strBuf = boost::str(tformat(_T("[driver] [close] closing driver - name: [%1%]")) % m_name.c_str() ); TRACEBUFI(strBuf); if(!m_loaded) { TRACEW("[driver] [close] Tried to close driver, but it wasn't loaded."); TRACEI("[driver] [close] < Leaving routine (without doing anything)."); return; } stop(); if(this->removable) { TRACEV("[driver] [close] driver is removable"); SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if(!manager) throw win32_error("OpenSCManager"); SC_HANDLE service = OpenService(manager, m_name.c_str(), SERVICE_ALL_ACCESS); if(!service) { DWORD err = GetLastError(); CloseServiceHandle(manager); throw win32_error("OpenService", err); } DeleteService(service); CloseServiceHandle(service); CloseServiceHandle(manager); } TRACEI("[driver] [close] unloaded driver"); m_loaded = false; TRACEI("[driver] [close] < Leaving routine."); } // End of close()
/* * Exverror is called to raise the error exception. If the second argument * is not NULL then error prints an error message using printf style * formatting. It then raises the error exception. */ static __printflike(2, 0) void exverror(int cond, const char *msg, va_list ap) { CLEAR_PENDING_INT; INTOFF; #ifdef DEBUG if (msg) { TRACE(("exverror(%d, \"", cond)); TRACEV((msg, ap)); TRACE(("\") pid=%d\n", getpid())); } else TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid())); #endif if (msg) exvwarning(-1, msg, ap); flushall(); exraise(cond); /* NOTREACHED */ }
bool provInitAdapter(const prov_adapter_info_t* i_adapter) { //Locals bool l_rc = false; uint64_t l_curr_wwpn = 0; uint8_t l_curr_port = 0; char l_afu_path[DEV_PATH_LENGTH] = {0}; //Code do { if(i_adapter == NULL) { TRACEE("Error! invalid args detected.\n"); l_rc = false; break; } snprintf(l_afu_path, sizeof(l_afu_path), "/dev/cxl/%sm", i_adapter->afu_name); TRACED("Setting up adapter '%s'...\n", l_afu_path); TRACEI("Initializing WWPN Data\n"); for(l_curr_port=0; l_curr_port < MAX_WWPNS_PER_ADAPTER; l_curr_port++) { l_curr_wwpn = strtoul(i_adapter->wwpn[l_curr_port],NULL,16); TRACEV("Initing AFU '%s' port %d\n", l_afu_path, l_curr_port); l_rc = initialize_wwpn(l_afu_path, l_curr_port, l_curr_wwpn); if(l_rc == false) { TRACEE("Error occurred while initializing WWPN Data.\n"); break; } } //finished! TRACED("SUCCESS: Initialization Complete!\n"); } while (0); return l_rc; }
int main(){ // Note that the console output is created by default // Create a formatted HTML file output TdOutputHandle html = td_createFileOutput("log.html", eTD_FMT_HTML); // Create a plain text output TdOutputHandle plain = td_createFileOutput("log.txt", eTD_FMT_PLAIN_TEXT); // Basic log macros LOGV("Verbose LOG"); LOGD("Debug LOG"); LOGI("Info LOG"); LOGW("Warning LOG"); LOGE("Error LOG"); // Tracing macro TRACEV("Verbose TRACE"); TRACED("Debug TRACE"); TRACEI("Info TRACE"); TRACEW("Warning TRACE"); TRACEE("Error TRACE"); // Destroy previously created outputs td_destroyOutput(html); td_destroyOutput(plain); system("pause"); return 0; }
bool provGetAdapterInfo(const char* i_pci_path, prov_adapter_info_t* o_info) { //Locals bool l_rc = true; FILE *l_vpd_file = NULL; char l_pci_path[DEV_PATH_LENGTH]; uint8_t l_vpd_buffer[MAX_VPD_SIZE]; int l_kw_length = 0; size_t n=0; //Code do { TRACEI("Reading WWPN data...\n"); if((i_pci_path == NULL) || (strlen(i_pci_path) == 0) || (strlen(i_pci_path) > DEV_PATH_LENGTH) || (o_info == NULL)) { TRACEI("Found null or invalid parm!\n"); l_rc = false; break; } bzero(l_pci_path, DEV_PATH_LENGTH); bzero(l_vpd_buffer, MAX_VPD_SIZE); bzero(o_info, sizeof(prov_adapter_info_t)); //generate the proper VPD path to get VPD snprintf(l_pci_path, DEV_PATH_LENGTH, "%s/%s", i_pci_path, "vpd"); TRACEV("Opening up '%s'\n", l_pci_path); l_vpd_file = fopen(l_pci_path, "rb"); if (l_vpd_file) { n = fread(l_vpd_buffer, 1, MAX_VPD_SIZE, l_vpd_file); } else { TRACEI("Unable to read file. Do you have permission to open '%s' ?", l_pci_path); l_rc = false; break; // error opening file } if(n < MAX_VPD_SIZE) { l_rc = false; TRACEI("Warning: Buffer underrun. This indicates a potential VPD format problem.\n"); break; } TRACEV("Searching for V5 and V6 KW data...\n"); l_kw_length = 16; l_rc = provFindVPDKw("V5", l_vpd_buffer, n, (uint8_t*)o_info->wwpn[0],&l_kw_length); if(l_rc == false) { TRACEE("Error: Unable to find Port name VPD for Port 1 (VPD KW V5)"); break; } l_kw_length = 16; l_rc = provFindVPDKw("V6", l_vpd_buffer, n, (uint8_t*)o_info->wwpn[1],&l_kw_length); if(l_rc == false) { TRACEE("Error: Unable to find Port name VPD for Port 1 (VPD KW V5)"); break; } //set up the output var strcpy(o_info->afu_name, "unknown"); strncpy(o_info->pci_path, i_pci_path, DEV_PATH_LENGTH); //TODO - need fns to get VPD data here and fill it in. //put data in successfully! l_rc = true; } while (0); //close the file on all paths, if it was opened if(l_vpd_file) { fclose(l_vpd_file); l_vpd_file = NULL; } return l_rc; }
DWORD driver::read(DWORD ioctl, void *buf, DWORD size, OVERLAPPED *ovl) { TRACEV("[driver] [read] Entering routine."); return rawio(ioctl, 0, 0, buf, size, ovl); } // End of read()
void driver::start(bool _gethandle) { TRACEV("[driver] [start] > Entering routine."); if(m_started) { TRACEI("[driver] [start] driver already started"); return; } TRACEI("[driver] [start] starting driver"); DWORD err = 0; SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if(!manager) { TRACEERR("[driver] [start]", L"ERROR: OpenSCManager", err = GetLastError()); throw win32_error("OpenSCManager"); } SC_HANDLE service = OpenService(manager, m_name.c_str(), SERVICE_ALL_ACCESS); if(!service) { CloseServiceHandle(manager); TRACEERR("[driver] [start]", L"ERROR: OpenService", err = GetLastError()); throw win32_error("OpenService", err); } if(!StartService(service, 0, NULL) && (err = GetLastError()) != ERROR_SERVICE_ALREADY_RUNNING) { bool startFailed = true; if (err == ERROR_SERVICE_DATABASE_LOCKED) { int numRetries = 0; do { TRACEW("[driver] [start] experiencing ERROR_SERVICE_DATABASE_LOCKED condition; waiting 10 seconds and trying again"); Sleep(10000); // 10 seconds err = 0; if (!StartService(service, 0, NULL) && (err = GetLastError()) != ERROR_SERVICE_ALREADY_RUNNING) // still having problems ++numRetries; else // either success, or another error break; } while (err == ERROR_SERVICE_DATABASE_LOCKED && numRetries < 6); if (numRetries < 6 && (err == 0 || err == ERROR_SERVICE_ALREADY_RUNNING)) { startFailed = false; TRACES("[driver] [start] successfully recovered from ERROR_SERVICE_DATABASE_LOCKED condition"); } else if (err == ERROR_SERVICE_DATABASE_LOCKED) { TRACEE("[driver] [start] cannot recover from ERROR_SERVICE_DATABASE_LOCKED condition; giving up"); } else { TRACEE("[driver] [start] cannot recover from ERROR_SERVICE_DATABASE_LOCKED condition; another error surfaced; giving up"); } } if (startFailed) { CloseServiceHandle(service); CloseServiceHandle(manager); TRACEERR("[driver] [start]", L"ERROR: StartService", err); throw win32_error("StartService", err); } } CloseServiceHandle(service); CloseServiceHandle(manager); if (_gethandle) { tstring strBuf = boost::str(tformat(_T("[driver] [start] getting handle to driver - devfile: [%1%]")) % m_devfile.c_str() ); TRACEBUFI(strBuf); m_dev = CreateFile(m_devfile.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if(m_dev == INVALID_HANDLE_VALUE) { TRACEERR("[driver] [start]", L"ERROR: CreateFile", err = GetLastError()); throw win32_error("CreateFile"); } m_stoppable = true; } else { m_stoppable = false; // should only be false for MS IpFilterDriver TRACEI("[driver] [start] flagging driver as not stoppable"); } TRACEI("[driver] [start] started driver"); m_started = true; TRACEV("[driver] [start] < Leaving routine."); } // End of start()
DWORD driver::write(DWORD ioctl, void *buf, DWORD size, OVERLAPPED *ovl) { TRACEV("[driver] [write] Entering routine."); return rawio(ioctl, buf, size, 0, 0, ovl); } // End of write()
void driver::load(const std::wstring &name, const std::wstring &file, const std::wstring &devfile) { TRACEV("[driver] [load(3)] > Entering routine."); if(m_loaded) throw std::exception("driver already loaded", 0); { tstring strBuf = boost::str(tformat(_T("[driver] [load(3)] loading driver - name: [%1%], file: [%2%], devfile: [%3%]")) % name.c_str() % file.c_str() % devfile.c_str() ); TRACEBUFI(strBuf); } m_name = name; m_file = file; m_devfile = devfile; SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if(!manager) throw win32_error("OpenSCManager"); SC_HANDLE service = CreateService(manager, m_name.c_str(), m_name.c_str(), SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, m_file.c_str(), NULL, NULL, NULL, NULL, NULL); if(!service) { DWORD err = 0; TRACEERR("[driver] [load(3)]", L"driver not currently installed as service", err = GetLastError()); err = 0; service = OpenService(manager, m_name.c_str(), SERVICE_ALL_ACCESS); if(!service) { TRACEERR("[driver] [load(3)]", L"opening service", err = GetLastError()); CloseServiceHandle(manager); throw win32_error("OpenService", err); } // make sure it has the same path as m_file. DWORD bytes; BOOL ret = QueryServiceConfig(service, NULL, 0, &bytes); if(ret || (err = GetLastError()) != ERROR_INSUFFICIENT_BUFFER) { TRACEERR("[driver] [load(3)]", L"calling QueryServiceConfig", err); CloseServiceHandle(service); CloseServiceHandle(manager); throw win32_error("QueryServiceConfig", err); } err = 0; // reset error-code, so that nobody else accidentally trips over it. QUERY_SERVICE_CONFIG *qsc = (QUERY_SERVICE_CONFIG*)malloc(bytes); if(!qsc) { TRACEERR("[driver] [load(3)]", L"allocating memory for QueryServiceConfig", err = GetLastError()); CloseServiceHandle(service); CloseServiceHandle(manager); throw std::bad_alloc(); } ret = QueryServiceConfig(service, qsc, bytes, &bytes); if(!ret) { TRACEERR("[driver] [load(3)]", L"second call to QueryServiceConfig", err = GetLastError()); CloseServiceHandle(service); CloseServiceHandle(manager); throw win32_error("QueryServiceConfig", err); } bool del = _wcsicmp(qsc->lpBinaryPathName, m_file.c_str()) != 0; if (del) { // check for e.g. \??\C:\WINDOWS\System32\DRIVERS\ipfltdrv.sys wchar_t * descr = _wgetenv(L"WINDIR"); if (descr) { wstring strFullPath(L"\\??\\"); strFullPath += descr; strFullPath += L"\\"; strFullPath += m_file; tstring strBuf = boost::str(tformat(_T("[driver] [load(3)] comparing against driver full-path:[%1%]")) % strFullPath ); TRACEBUFI(strBuf); del = _wcsicmp(qsc->lpBinaryPathName, strFullPath.c_str()) != 0; } else { TRACEW("[driver] [load(3)] WINDIR environment variable not found!"); } } tstring strBuf = boost::str(tformat(_T("[driver] [load(3)] service name: [%1%], file name: [%2%]")) % qsc->lpBinaryPathName % m_file.c_str() ); TRACEBUFI(strBuf); free(qsc); // paths don't match, remove service and recreate. if(del) { TRACEW("[driver] [load(3)] paths don't match, removing and recreating driver-service"); TCHAR buf[128]; // if it's not removable, bail out. if(!this->removable) { TRACEC("[driver] [load(3)] ERROR trying to remove driver-service"); CloseServiceHandle(service); CloseServiceHandle(manager); throw std::exception("unremovable service mismatch", 0); } // check if its running SERVICE_STATUS status; ret = QueryServiceStatus(service, &status); if(!ret) { TRACEERR("[driver] [load(3)]", L"ERROR calling QueryServiceStatus", err = GetLastError()); CloseServiceHandle(service); CloseServiceHandle(manager); throw win32_error("QueryServiceStatus", err); } // and stop it if it is. switch(status.dwCurrentState) { case SERVICE_STOPPED: TRACEI("[driver] [load(3)] service state: [SERVICE_STOPPED]"); break; case SERVICE_START_PENDING: TRACEI("[driver] [load(3)] service state: [SERVICE_START_PENDING]"); break; case SERVICE_STOP_PENDING: TRACEI("[driver] [load(3)] service state: [SERVICE_STOP_PENDING]"); break; case SERVICE_RUNNING: TRACEI("[driver] [load(3)] service state: [SERVICE_RUNNING]"); break; case SERVICE_CONTINUE_PENDING: TRACEI("[driver] [load(3)] service state: [SERVICE_CONTINUE_PENDING]"); break; case SERVICE_PAUSE_PENDING: TRACEI("[driver] [load(3)] service state: [SERVICE_PAUSE_PENDING]"); break; case SERVICE_PAUSED: TRACEI("[driver] [load(3)] service state: [SERVICE_PAUSED]"); break; default: swprintf_s(buf, _countof(buf), L"[driver] [load(3)] * ERROR: Unknown service state: [%u]", status.dwCurrentState); TRACEBUFE(buf); break; } if(status.dwCurrentState != SERVICE_STOPPED && status.dwCurrentState != SERVICE_STOP_PENDING) { ret = ControlService(service, SERVICE_CONTROL_STOP, &status); if(!ret) { TRACEERR("[driver] [load(3)]", L"ERROR stopping driver-service", err = GetLastError()); CloseServiceHandle(service); CloseServiceHandle(manager); throw win32_error("ControlService", err); } } // now delete the service. ret = DeleteService(service); err = GetLastError(); CloseServiceHandle(service); if(!ret && err != ERROR_SERVICE_MARKED_FOR_DELETE) { TRACEERR("[driver] [load(3)]", L"ERROR deleting driver-service", err); CloseServiceHandle(manager); throw win32_error("DeleteService", err); } // finally recreate it. service = CreateService(manager, m_name.c_str(), m_name.c_str(), SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, m_file.c_str(), NULL, NULL, NULL, NULL, NULL); if(!service && (err = GetLastError()) == ERROR_SERVICE_MARKED_FOR_DELETE) { TRACEW("[driver] [load(3)] Service marked for delete; trying closing/reopening SCM"); CloseServiceHandle(manager); Sleep(10000); manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (!manager) { TRACEERR("[driver] [load(3)]", L"ERROR while re-opening SCM", err = GetLastError()); throw win32_error("OpenSCManager 2", err); } service = CreateService(manager, m_name.c_str(), m_name.c_str(), SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, m_file.c_str(), NULL, NULL, NULL, NULL, NULL); } if(!service) { TRACEERR("[driver] [load(3)]", L"ERROR re-creating driver-service", err = GetLastError()); CloseServiceHandle(manager); throw win32_error("CreateService", err); } TRACEI("[driver] [load(3)] finished re-creating driver-service"); } } SERVICE_STATUS status; if(QueryServiceStatus(service, &status)) { if (status.dwCurrentState == SERVICE_RUNNING) { TRACES("[driver] [load(3)] Driver-service is running"); m_started = true; } else if (status.dwCurrentState == SERVICE_START_PENDING) { TRACEI("[driver] [load(3)] Driver-service is starting"); } else { TRACEI("[driver] [load(3)] driver-service not running"); TCHAR buf[128]; swprintf_s(buf, _countof(buf), L"[driver] [load(3)] - service state: [%u]", status.dwCurrentState); TRACEBUFW(buf); } } CloseServiceHandle(service); CloseServiceHandle(manager); m_loaded = true; TRACEV("[driver] [load(3)] < Leaving routine."); }
bool loopbackDiag(char* i_afu_path, const AFU_PORT_ID i_port, uint64_t i_test_time_us) { //Locals struct cxl_afu_h *afu_master_h = NULL; int afu_master_fd = 0; uint8_t *afu_psa_addr = NULL; uint64_t mmio_data = 0; int l_fc_port_offset = 0; bool l_rc = true; uint64_t l_init_txcount = 0; uint64_t l_init_errcount = 0; uint64_t l_init_passcount = 0; uint64_t l_txcount = 0; uint64_t l_errcount = 0; uint64_t l_passcount = 0; //Code do { if(i_port >= MAX_WWPNS_PER_ADAPTER) { TRACEE("Port number %d is not a valid port number. We only support up to %d numbers.\n", i_port, MAX_WWPNS_PER_ADAPTER); l_rc = false; break; } l_fc_port_offset = FC_PORT_BASE_OFFSET + (i_port * FC_PORT_REG_SIZE); TRACEV("Target reg bank for port %d = 0x%08x\n",i_port, l_fc_port_offset); TRACEI("Attempting to open device '%s'\n", i_afu_path); /* now that the AFU is started, lets set config options */ if ((afu_master_h = cxl_afu_open_dev(i_afu_path)) < 0) { TRACEE("Unable to open AFU Master cxl device. errno = %d (%s)\n", errno, strerror(errno)); l_rc = false; break; } TRACEV("Opened %p, now attempting to get FD\n", afu_master_h); afu_master_fd = cxl_afu_fd(afu_master_h); TRACEV("Got FD! = %d\n", afu_master_fd); if (cxl_afu_attach(afu_master_h, 0)) //no WEQ needed { TRACEE("Call to cxl_afu_attach failed. errno = %d (%s)\n", errno, strerror(errno)); l_rc = false; break; } afu_psa_addr = mmap_afu_wwpn_registers(afu_master_fd); if (!afu_psa_addr) { TRACEE("Error attempting to map AFU problem state registers. errno = %d (%s)\n", errno, strerror(errno)); l_rc = false; break; } //Loopback enables a special echo mode and checks tx and rx counts to make sure //the phy works correctly. The test is relatively short. TRACEI("Enabling loopback mode for adapter %s, port %d\n", i_afu_path, i_port); //first read back all test register counts. The AFU does not zero them l_init_txcount = in_mmio64((__u64*)&afu_psa_addr[FC_LOOPBACK_TXCNT + l_fc_port_offset]); l_init_errcount = in_mmio64((__u64*)&afu_psa_addr[FC_LOOPBACK_ERRCNT + l_fc_port_offset]); l_init_passcount = in_mmio64((__u64*)&afu_psa_addr[FC_LOOPBACK_PASSCNT + l_fc_port_offset]); //enable the test mmio_data = in_mmio64((__u64*)&afu_psa_addr[FC_CONFIG2 + l_fc_port_offset]); mmio_data |= (uint64_t)0x01 << 40; //set ECHO generator for this port (bit 40) out_mmio64((__u64*)&afu_psa_addr[FC_CONFIG2 + l_fc_port_offset], mmio_data); TRACEI("Waiting %"PRIu64" microseconds for the test to complete...\n", i_test_time_us); usleep(i_test_time_us); TRACEI("Disabling loopback mode.\n"); mmio_data = in_mmio64((__u64*)&afu_psa_addr[FC_CONFIG2 + l_fc_port_offset]); mmio_data &= ~((uint64_t)0x01 << 40); //clear ECHO generator for this port (bit 40) out_mmio64((__u64*)&afu_psa_addr[FC_CONFIG2 + l_fc_port_offset], mmio_data); TRACEI("Waiting for the link to quiesce...\n"); usleep(LOOPBACK_TEST_QUIET_PERIOD);//wait for quiesce and any final timeouts //check test results from HW - subtract out initial readings l_txcount = in_mmio64((__u64*)&afu_psa_addr[FC_LOOPBACK_TXCNT + l_fc_port_offset]) - l_init_txcount; l_errcount = in_mmio64((__u64*)&afu_psa_addr[FC_LOOPBACK_ERRCNT + l_fc_port_offset]) - l_init_errcount; l_passcount = in_mmio64((__u64*)&afu_psa_addr[FC_LOOPBACK_PASSCNT + l_fc_port_offset]) - l_init_passcount; if((l_txcount == 0) || (l_errcount != 0) || (l_txcount != l_passcount)) { TRACED("Loopback diagnostic failure detected. AFU: %s, port: %d, Tx Count: %"PRIu64", Pass Count: %"PRIu64", Error Count: %"PRIu64"\n", i_afu_path, i_port, l_txcount, l_passcount, l_errcount); l_rc = false; } else { TRACEV("Loopback test passed. AFU: %s, port: %d, Tx Count: %"PRIu64", Pass Count: %"PRIu64", Error Count: %"PRIu64"\n", i_afu_path, i_port, l_txcount, l_passcount, l_errcount); l_rc = true; } //done! munmap_afu_wwpn_registers((void *) afu_psa_addr); cxl_afu_free(afu_master_h); } while (0); return l_rc; }
bool initialize_wwpn(char* i_afu_path, const AFU_PORT_ID i_port, const uint64_t i_wwpn) { //Locals struct cxl_afu_h *afu_master_h = NULL; int afu_master_fd = 0; uint8_t *afu_psa_addr = NULL; uint32_t mmio_data32 = 0; uint64_t mmio_data = 0; int l_fc_port_offset = 0; //todo: replace all references with "l_fc_port_offset" bool l_rc = 0; //Code do { if(i_port >= MAX_WWPNS_PER_ADAPTER) { TRACEE("Port number %d is not a valid port number. We only support up to %d numbers.\n", i_port, MAX_WWPNS_PER_ADAPTER); l_rc = false; break; } if(i_wwpn == 0) { TRACEE("WWPN for %s port %d is zero and therefore invalid.\n", i_afu_path, i_port); l_rc = false; break; } l_fc_port_offset = FC_PORT_BASE_OFFSET + (i_port * FC_PORT_REG_SIZE); TRACEV("Target reg bank for port %d = 0x%08x\n",i_port, l_fc_port_offset); TRACEI("Attempting to open device '%s'\n", i_afu_path); /* now that the AFU is started, lets set config options */ if ((afu_master_h = cxl_afu_open_dev(i_afu_path)) < 0) { TRACEE("Unable to open AFU Master cxl device. errno = %d (%s)\n", errno, strerror(errno)); l_rc = false; break; } TRACEV("Opened %p, now attempting to get FD\n", afu_master_h); afu_master_fd = cxl_afu_fd(afu_master_h); TRACEV("Got FD! = %d\n", afu_master_fd); if (cxl_afu_attach(afu_master_h, 0)) //no WEQ needed { TRACEE("Call to cxl_afu_attach failed. errno = %d (%s)\n", errno, strerror(errno)); l_rc = false; break; } afu_psa_addr = mmap_afu_wwpn_registers(afu_master_fd); if (!afu_psa_addr) { TRACEE("Error attempting to map AFU problem state registers. errno = %d (%s)\n", errno, strerror(errno)); l_rc = -1; break; } //Take port offline //TRACED("Bringing port offline\n"); //get status bits for debug //TODO: maybe wrap up this print into a nice macro... mmio_data32 = in_mmio32((__u64*)&afu_psa_addr[FC_MTIP_STATUS + l_fc_port_offset]); TRACEV("FC_MTIP_STATUS (0x%08X): 0x%08X\n", FC_MTIP_STATUS + l_fc_port_offset, mmio_data32); mmio_data32 = in_mmio32((__u64*)&afu_psa_addr[FC_MTIP_CMDCONFIG + l_fc_port_offset]); TRACEV("FC_MTIP_CMDCONFIG (0x%08X): 0x%08X\n", FC_MTIP_CMDCONFIG + l_fc_port_offset, mmio_data32); mmio_data32 &= ~0x20; // clear ON_LINE mmio_data32 |= 0x40; // set OFF_LINE TRACEV("FC_MTIP_CMDCONFIG: Proposed: 0x%08X\n", mmio_data32); out_mmio32((__u64*)&afu_psa_addr[FC_MTIP_CMDCONFIG + l_fc_port_offset], mmio_data32); //wait for the port to be offline l_rc = wait_port_state(afu_psa_addr, l_fc_port_offset, false); if(l_rc == false) { TRACEE("Port not offline in time. Aborting.\n"); l_rc = -1; break; } //now we know we are offline, so write the PN... //read out the current PN //PN register is 64-bit as per spec mmio_data = in_mmio64((__u64*)&afu_psa_addr[FC_PNAME + l_fc_port_offset]); TRACEV("FC_PNAME: (0x%08X): 0x%"PRIx64"\n",FC_PNAME + l_fc_port_offset, mmio_data); TRACEI("Current Port Name is 0x%"PRIx64"\n", mmio_data); mmio_data = i_wwpn; TRACEI("New Port Name will be 0x%"PRIx64"\n", mmio_data); out_mmio64((__u64*)&afu_psa_addr[FC_PNAME + l_fc_port_offset], mmio_data); //bring the port back online //read control bits... mmio_data32 = in_mmio32((__u64*)&afu_psa_addr[FC_MTIP_CMDCONFIG + l_fc_port_offset]); TRACEV("FC_MTIP_CMDCONFIG (0x%08X): 0x%08X\n", FC_MTIP_CMDCONFIG + l_fc_port_offset, mmio_data32); mmio_data32 |= 0x20; // set ON_LINE mmio_data32 &= ~0x40; // clear OFF_LINE //TODO: ask todd - should we explicitly-set other bits? I needed to force the port into FC mode (set bit 1) //net result is we write 0x23 to the lowest byte TRACEV("FC_MTIP_CMDCONFIG: Proposed: 0x%08X\n", mmio_data32); out_mmio32((__u64*)&afu_psa_addr[FC_MTIP_CMDCONFIG + l_fc_port_offset], mmio_data32); //wait for the port to be online l_rc = wait_port_state(afu_psa_addr, l_fc_port_offset, true); if(l_rc == false) { TRACEE("Port not online in time.\n"); l_rc = -1; break; } //done! munmap_afu_wwpn_registers((void *) afu_psa_addr); cxl_afu_free(afu_master_h); TRACEI("Successfully programmed WWPN!\n"); l_rc = true; } while (0); return l_rc; }
error_t parse_opt (int key, char *arg, struct argp_state *state) { /*------------------------------------------------------------------------*/ /* Local Variables */ /*------------------------------------------------------------------------*/ static int32_t last_command = -1; //int32_t l_temp = 0; /*-------------------------------------------------------------------------*/ /* Code */ /*-------------------------------------------------------------------------*/ switch (key) { case PROV_LIST_AFUS: g_args.list_afus = 1; break; case PROV_WWPNS_READ: if((arg != NULL) && (strlen(arg) != 0)) { strncpy(g_args.target_adapter, arg, sizeof(g_args.target_adapter)); TRACEV("Setting target adapter to: '%s'\n", g_args.target_adapter); } g_args.wwpn_read = 1; break; case PROV_WWPNS_PGM: if((arg != NULL) && (strlen(arg) != 0)) { strncpy(g_args.target_adapter, arg, sizeof(g_args.target_adapter)); TRACEV("Setting target adapter to: '%s'\n", g_args.target_adapter); } g_args.wwpn_program = 1; break; case PROV_LOOPBACK: g_args.loopback = 1; g_args.loopback_time = LOOPBACK_TEST_DEFAULT_S; //choose a default value and then check to see if we have an arg if((arg != NULL) && (strlen(arg) != 0)) { g_args.loopback_time = atoi(arg); if((g_args.loopback_time < LOOPBACK_TEST_MIN_S) || (g_args.loopback_time > LOOPBACK_TEST_MAX_S)) { TRACED("Invalid loopback test time of %d. Defaulting to %d\n", g_args.loopback_time, LOOPBACK_TEST_DEFAULT_S); g_args.loopback_time = LOOPBACK_TEST_DEFAULT_S; } } break; case PROV_DEBUG: g_args.verbose = atoi (arg); TRACEI ("Set verbose level to %d\n", g_args.verbose); if (g_args.verbose >= 1) g_traceI = 1; if (g_args.verbose >= 2) g_traceF = 1; if (g_args.verbose >= 3) g_traceV = 1; break; case 0 : if((last_command == PROV_QUERY_AFU) && ((strncmp(arg,"/",1))) && // They may put input dir/file ((strncmp(arg,".",1)))) // after comp so look for it { TRACEI("Also Look for component %s\n",arg); last_command = PROV_QUERY_AFU; goto exit_no_set; } break; default: return (ARGP_ERR_UNKNOWN); } last_command = -1; TRACEF ("Last cmd\n"); return (0); exit_no_set: return(0); }