/*------------------------------------------------------------------- | initvs.c - main init code for VS1000/2000 NT device driver. Contains mostly initialization code. Copyright 1996-98 Comtrol Corporation. All rights reserved. |--------------------------------------------------------------------*/ #include "precomp.h" static int CatBindList(IN WCHAR *pwstr); static void GetBindingNames(void); static Nic *FindFreeNic(void); static int BindNameUsed(char *nicname); static int NicNameUsed(char *nicname); static void ScanForNewNicCards(void); static int reg_list_nt50_linkage(void); static int reg_list_nt40_linkage(void); /*---------------------------------------------------------------------- CatBindList - Given the multisz Wchar string read out of the registry, convert it to normal c-string multisz list. |----------------------------------------------------------------------*/ static int CatBindList(IN WCHAR *pwstr) { char *cstr; int size = 0; cstr = Driver.BindNames; MyKdPrint(D_Thread, ("CatBindList\n")) // cat on to end of existing list, so find end of list while (cstr[size] != 0) { //MyKdPrint(D_Thread, ("ExList:%s\n", &cstr[size])) while (cstr[size] != 0) ++size; ++size; // pass up string null to next string } cstr += size; MyKdPrint(D_Thread, ("CatList Size:%d\n", size)) if (*pwstr == 0) { MyKdPrint(D_Thread, ("Null List!\n")) } while ((*pwstr != 0) && (size < 7700)) { // first convert it past the list end and check if its already in the list WStrToCStr(cstr+4, pwstr, 200); if (!BindNameUsed(cstr+4)) { WStrToCStr(cstr, pwstr, 200); // put at end of list MyKdPrint(D_Thread, ("Bind: %s\n", cstr)) size = (strlen(cstr) + 1); cstr += size; *cstr = 0; // double null end of list *(cstr+1) = 0; } //----- Advance to the next string of the MULTI_SZ string while (*pwstr != 0) ++pwstr; ++pwstr; } return 0; // ok } /*---------------------------------------------------------------------- GetBindingNames - Reads Binding info to find possible nic-card export names from registry. Reads the list into Driver.BindNames multisz list. |----------------------------------------------------------------------*/ static void GetBindingNames(void) { if (Driver.BindNames == NULL) { Driver.BindNames = ExAllocatePool(PagedPool, 8000 * sizeof(WCHAR)); if (Driver.BindNames == NULL) { Eprintf("GetBindingNames no memory"); return; } } // clear list RtlZeroMemory( (PUCHAR)Driver.BindNames, sizeof(WCHAR)*2); #ifdef NT50 reg_list_nt50_linkage(); #else reg_list_nt40_linkage(); #endif } /*---------------------------------------------------------------------- FindFreeNic - Find an unused Nic structure to try and open. |----------------------------------------------------------------------*/ static Nic *FindFreeNic(void) { int i; #ifdef BREAK_NIC_STUFF for (i=VS1000_MAX_NICS-1; i>=0; i--) #else for (i=0; ipm, Driver.AutoMacDevExt->config->MacAddr); write_dev_mac(Driver.AutoMacDevExt); Driver.AutoMacDevExt = NULL; } if (ticks > 60) // every 60 seconds { // if any boxes are not in the init state of communications, // then assume that there may be a missing nic-card we need to // find in the system. SearchForNicsFlag = FALSE; ext = Driver.board_ext; while(ext) { if (ext->pm->state == ST_INIT) { SearchForNicsFlag = TRUE; } ext = ext->board_ext; // next } if (SearchForNicsFlag) { ticks = 0; // come back around after full 60 second timeout ScanForNewNicCards(); } else ticks -= 30; // come back around in 30 seconds } } Driver.threadHandle = NULL; // Terminate myself PsTerminateSystemThread( STATUS_SUCCESS ); } #ifdef NT50 /*----------------------------------------------------------------- reg_list_nt50_linkage - Find ethernet nic-card names in the registry. Official binding tells us what we are bound to via NT's binding rules. But, this binding process is combersome and has problems. Another technique is to search the registry and look for nic-card names to use. Under NT50, this is easier in that there is a Net class, and we can search it for cards with "Ethernet" linkage. So we do both, this gives some backward compatibility if we choose to install and get the proper bindings and/or if we want to avoid these binding shortcomings by hacking our own list of nic-cards from the registry. Installing as a protocol might solve some of the linkage problems, (and present new problems too.) NT4.0 and below stores this in "Services\Servicename\Linkage" area. NT5.0 PnP network card linkage info stored at: "REGISTRY\Machine\System\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}\0000\Linkage" Id to determine if node is ours(vs): "REGISTRY\Machine\System\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}\0000\ComponentId"= "vslinka_did" |------------------------------------------------------------------*/ static int reg_list_nt50_linkage(void) { static char *szLowerRange = {"LowerRange"}; static char *szNdiInterfaces = {"Ndi\\Interfaces"}; static char *szComponentId = {"ComponentId"}; static char *szLinkage = {"Linkage"}; static char *szBind = {"Bind"}; static char *szExport = {"Export"}; static char *szRegRMSCCNetGuid = {"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}"}; static char *szEthernet = {"Ethernet"}; static char tmpstr[200]; // make static, don't put too much on stack.. static char compstr[40]; static char nodestr[20]; WCHAR *wstr_ptr; char *buffer = NULL; char *data_ptr; HANDLE KeyHandle = NULL; HANDLE KeyHandle2 = NULL; HANDLE KeyHandle3 = NULL; int node_num = 0; int linkage_found = 0; int stat; #define OUR_BUF_SIZE (8000*2) MyKdPrint(D_Thread, ("Start RegFind Linkage\n")) stat = our_open_key(&KeyHandle, NULL, szRegRMSCCNetGuid, KEY_READ); if (stat) { MyKdPrint(D_Error, ("Failed OpenKey\n")) return 1; } buffer = ExAllocatePool(PagedPool, OUR_BUF_SIZE); if ( buffer == NULL ) { Eprintf("RegFindLinkage no memory"); return 1; } for(;;) { stat = our_enum_key(KeyHandle, node_num, buffer, OUR_BUF_SIZE, &data_ptr); ++node_num; if (stat) { MyKdPrint(D_Thread, ("Done\n")) break; } // does this come back as wchar? WStrToCStr(nodestr, (PWCHAR)data_ptr, 18); //if (strlen(data_ptr) < 18) // strcpy(nodestr, data_ptr); MyKdPrint(D_Thread, ("Got Key Node:%s.\n", nodestr)) // open up the sub-key (0000, 0001, etc..) stat = our_open_key(&KeyHandle2, KeyHandle, nodestr, KEY_READ); if (stat) { MyKdPrint(D_Error, ("Err 1X\n")) continue; } stat = our_query_value(KeyHandle2, szComponentId, buffer, OUR_BUF_SIZE, NULL, // pDataType &data_ptr); if (stat) { // no component id MyKdPrint(D_Thread, ("No compId\n")) compstr[0] = 0; } else { WStrToCStr(compstr, (PWCHAR)data_ptr, 38); } //if (strlen(data_ptr) < 38) // strcpy(compstr, data_ptr); MyKdPrint(D_Thread, ("Got compid:%s.\n", compstr)) if ((my_lstricmp(compstr, "vslink1_did") == 0) || (my_lstricmp(compstr, "vslink2_did") == 0)) { MyKdPrint(D_Thread, ("Match\n")) // open up the sub-key "Linkage" and get "Bind" multisz string stat = our_open_key(&KeyHandle3, KeyHandle2, szLinkage, KEY_READ); if (stat) { MyKdPrint(D_Thread, ("No Linkage\n")) continue; } stat = our_query_value(KeyHandle3, szBind, buffer, OUR_BUF_SIZE, NULL, // pDataType &data_ptr); if (stat) { // no component id MyKdPrint(D_Thread, ("No Bind\n")) continue; } MyKdPrint(D_Thread, ("Got bind!\n")) wstr_ptr = (PWCHAR)(data_ptr); #if DBG //while (*wstr_ptr != 0) // while more multisz strings //{ // WStrToCStr(tmpstr, wstr_ptr, 100); // MyKdPrint(D_Thread, ("Got Bind Name:%s.\n", tmpstr)) // while (*wstr_ptr != 0) // pass up this string // ++wstr_ptr; // ++wstr_ptr; //} //wstr_ptr = (PWCHAR)(data_ptr); #endif CatBindList(wstr_ptr); ++linkage_found; } else //------- not a VS node { // so check to see if its a ethernet nic-card which we can // use the exported name to add to our bind list // open up the sub-key "Ndi\\Interfaces" and get "LowerRange" multisz string stat = our_open_key(&KeyHandle3, KeyHandle2, szNdiInterfaces, KEY_READ); if (stat) { MyKdPrint(D_Thread, ("Not a e.nic-card\n")) continue; } stat = our_query_value(KeyHandle3, szLowerRange, buffer, OUR_BUF_SIZE, NULL, // pDataType &data_ptr); if (stat) { MyKdPrint(D_Thread, ("No LowRange\n")) continue; } WStrToCStr(tmpstr, (PWCHAR)data_ptr, 38); if (my_lstricmp(tmpstr, szEthernet) != 0) { MyKdPrint(D_Thread, ("Not Eth\n")) continue; } MyKdPrint(D_Thread, ("Found a Nic Card!\n")) // open up the sub-key "Linkage" and get "Export" multisz string stat = our_open_key(&KeyHandle3, KeyHandle2, szLinkage, KEY_READ); if (stat) { MyKdPrint(D_Thread, ("No Linkage on E card\n")) continue; } stat = our_query_value(KeyHandle3, szExport, buffer, OUR_BUF_SIZE, NULL, // pDataType &data_ptr); if (stat) { MyKdPrint(D_Thread, ("No Export on E.nic-card\n")) continue; } MyKdPrint(D_Thread, ("Got e.card export 2!\n")) wstr_ptr = (PWCHAR) data_ptr; #if DBG //while (*wstr_ptr != 0) // while more multisz strings //{ // WStrToCStr(tmpstr, wstr_ptr, 100); // MyKdPrint(D_Thread, ("Got E. Card Name:%s.\n", tmpstr)) // while (*wstr_ptr != 0) // pass up this string // ++wstr_ptr; // ++wstr_ptr; //} //wstr_ptr = (PWCHAR) data_ptr; #endif ++linkage_found; MyKdPrint(D_Thread, ("E card 3!\n")) CatBindList(wstr_ptr); } } // for if (KeyHandle != NULL) ZwClose(KeyHandle); if (KeyHandle2 != NULL) ZwClose(KeyHandle2); if (KeyHandle3 != NULL) ZwClose(KeyHandle3); if (buffer != NULL) ExFreePool(buffer); if (linkage_found == 0) { MyKdPrint(D_Thread, ("ERROR, No Ethernet found!\n")) } MyKdPrint(D_Thread, ("reg_list done\n")) return 1; // err, not found } #else /*---------------------------------------------------------------------------- nt40 |----------------------------------------------------------------------------*/ static int reg_list_nt40_linkage(void) { //static char *szLowerRange = {"LowerRange"}; //static char *szNdiInterfaces = {"Ndi\\Interfaces"}; //static char *szComponentId = {"ComponentId"}; //static char *szExport = {"Export"}; //static char *szRegRMSCCNetGuid = // {"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}"}; //static char *szEthernet = {"Ethernet"}; static char *szRegRMSCS = {"\\Registry\\Machine\\System\\CurrentControlSet\\Services"}; static char *szLinkage = {"Linkage"}; static char *szBind = {"Bind"}; static char tmpstr[200]; // make static, don't put too much on stack.. static char compstr[40]; static char nodestr[20]; WCHAR *wstr_ptr; char *buffer = NULL; char *data_ptr; HANDLE KeyHandle = NULL; HANDLE KeyHandle2 = NULL; HANDLE KeyHandle3 = NULL; int node_num = 0; int linkage_found = 0; int stat; OBJECT_ATTRIBUTES objAttribs; NTSTATUS status; #define OUR_BUF_SIZE (8000*2) MyKdPrint(D_Thread, ("Start RegFind Linkage\n")) MyKdPrint(D_Thread, ("str:%s\n", UToC1(&Driver.RegPath) )) buffer = ExAllocatePool(PagedPool, OUR_BUF_SIZE); if ( buffer == NULL ) { Eprintf("RegFindLinkage no memory"); return 1; } for (;;) { //--- open up our service key: controlset\services\vslinka InitializeObjectAttributes(&objAttribs, &Driver.RegPath, OBJ_CASE_INSENSITIVE, NULL, // root dir relative handle NULL); // security desc status = ZwOpenKey(&KeyHandle, KEY_READ, &objAttribs); if (status != STATUS_SUCCESS) { MyKdPrint(D_Error, ("Err 4D:%d\n", status)) break; } // open up the sub-key "Linkage" and get "Bind" multisz string stat = our_open_key(&KeyHandle2, KeyHandle, szLinkage, KEY_READ); if (stat) { MyKdPrint(D_Thread, ("No Linkage\n")) break; } stat = our_query_value(KeyHandle2, szBind, buffer, OUR_BUF_SIZE, NULL, // pDataType &data_ptr); if (stat) { // no component id MyKdPrint(D_Thread, ("No Bind\n")) break; } MyKdPrint(D_Thread, ("Got bind!\n")) wstr_ptr = (PWCHAR)(data_ptr); #if DBG while (*wstr_ptr != 0) // while more multisz strings { WStrToCStr(tmpstr, wstr_ptr, 100); MyKdPrint(D_Thread, ("Got Bind Name:%s.\n", tmpstr)) while (*wstr_ptr != 0) // pass up this string ++wstr_ptr; ++wstr_ptr; } MyKdPrint(D_Thread, ("bind 3!\n")) wstr_ptr = (PWCHAR)(data_ptr); #endif CatBindList(wstr_ptr); MyKdPrint(D_Thread, ("bind 4!\n")) ++linkage_found; break; // all done. } // now go nab tcpip's bindings... for (;;) { MyKdPrint(D_Thread, ("Get other Linkage\n")) stat = our_open_key(&KeyHandle, NULL, szRegRMSCS, KEY_READ); if (stat) { MyKdPrint(D_Thread, ("Failed OpenKey\n")) break; } // open up the sub-key "tcpip\\Linkage" and get "Bind" multisz string tmpstr[0] = 't'; tmpstr[1] = 'c'; tmpstr[2] = 'p'; tmpstr[3] = 'i'; tmpstr[4] = 'p'; tmpstr[5] = '\\'; tmpstr[6] = 0; strcat(tmpstr, szLinkage); stat = our_open_key(&KeyHandle2, KeyHandle, tmpstr, KEY_READ); if (stat) { MyKdPrint(D_Thread, ("No other binding\n")) break; } stat = our_query_value(KeyHandle2, szBind, buffer, OUR_BUF_SIZE, NULL, // pDataType &data_ptr); if (stat) { // no component id MyKdPrint(D_Thread, ("No other Bind\n")) break; } MyKdPrint(D_Thread, ("Got other bind!\n")) wstr_ptr = (PWCHAR)(data_ptr); #if DBG while (*wstr_ptr != 0) // while more multisz strings { WStrToCStr(tmpstr, wstr_ptr, 100); MyKdPrint(D_Thread, ("Got Bind Name:%s.\n", tmpstr)) while (*wstr_ptr != 0) // pass up this string ++wstr_ptr; ++wstr_ptr; } wstr_ptr = (PWCHAR)(data_ptr); #endif CatBindList(wstr_ptr); ++linkage_found; break; } if (KeyHandle != NULL) ZwClose(KeyHandle); if (KeyHandle2 != NULL) ZwClose(KeyHandle2); if (KeyHandle3 != NULL) ZwClose(KeyHandle3); if (buffer != NULL) ExFreePool(buffer); MyKdPrint(D_Thread, ("reg_list done\n")) if (linkage_found == 0) { MyKdPrint(D_Thread, ("ERROR, No Ethernet found!\n")) return 1; } return 0; // ok, linkage found } #endif /*---------------------------------------------------------------------- init_eth_start - start up ethernet work. |----------------------------------------------------------------------*/ int init_eth_start(void) { int stat,i; for (i=0; iconfig->NumPorts <= 8) // its a RHub device board_ext->config->IsHubDevice = 1; // setup default ClkRate if not specified if (board_ext->config->ClkRate == 0) { // use default if (board_ext->config->IsHubDevice) board_ext->config->ClkRate = DEF_RHUB_CLOCKRATE; else board_ext->config->ClkRate = DEF_VS_CLOCKRATE; } // setup default PreScaler if not specified if (board_ext->config->ClkPrescaler == 0) { // use default if (board_ext->config->IsHubDevice) board_ext->config->ClkPrescaler = DEF_RHUB_PRESCALER; else board_ext->config->ClkPrescaler = DEF_VS_PRESCALER; } stat = portman_init(board_ext->hd, board_ext->pm, board_ext->config->NumPorts, board_ext->UniqueId, board_ext->config->BackupServer, board_ext->config->BackupTimer, board_ext->config->MacAddr); if (stat != 0) { MyKdPrint(D_Init, ("Hdlc Failed Open\n")) return STATUS_SERIAL_NO_DEVICE_INITED; } #ifdef NT40 board_ext->config->HardwareStarted = TRUE; // tell ISR its ready to go board_ext->FdoStarted = 1; // ok to start using #endif return STATUS_SUCCESS; } /*---------------------------------------------------------------------- init_stop - unload thread, ndis nic cards, etc |----------------------------------------------------------------------*/ int init_stop(void) { int i; MyKdPrint(D_Init, ("Init Stop\n")) if (Driver.threadHandle != NULL) { ZwClose(Driver.threadHandle); Driver.threadHandle = NULL; // tell thread to kill itself time_stall(15); // wait 1.5 second } if (Driver.nics != NULL) { for (i=0; i>> Done Reading"); return 0; } #if 0 /*---------------------------------------------------------------------- is_mac_unused - Used for autoconfig of mac-address. |----------------------------------------------------------------------*/ int is_mac_used(DRIVER_MAC_STATUS *) { PSERIAL_DEVICE_EXTENSION board_ext; if (mac_entry->flags & FLAG_APPL_RUNNING) return 1; // its used board_ext = Driver.board_ext; while (board_ext != NULL) { if ((!board_ext->FdoStarted) || (!board_ext->config->HardwareStarted)) { board_ext = board_ext->board_ext; // next in chain return 1; // might be used } if (mac_match(ext->config->MacAddr, mac_entry->mac) return 1; // its used } board_ext = board_ext->board_ext; } return 0; // its not used } #endif