Пример #1
0
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()
Пример #2
0
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()
Пример #3
0
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()
Пример #4
0
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()
Пример #5
0
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);
            }
        }
    }
    
}
Пример #6
0
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]);
            }
        }
    }
}
Пример #7
0
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
	{
Пример #8
0
DWORD driver::cancelio()
{
	TRACEV("[driver] [cancelio]    Entering routine.");
	BOOL ret = CancelIo(m_dev);
	return ret ? ERROR_SUCCESS : GetLastError();

} // End of cancelio()
Пример #9
0
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);
}
Пример #10
0
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()
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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;
}
Пример #14
0
/*
 * 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 */
}
Пример #15
0
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()
Пример #16
0
/*
 * 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 */
}
Пример #17
0
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;
}
Пример #18
0
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;
}
Пример #19
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;
}
Пример #20
0
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()
Пример #21
0
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()
Пример #22
0
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()
Пример #23
0
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.");
}
Пример #24
0
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;
    
}
Пример #25
0
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;
    
}
Пример #26
0
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);
    
}