/****************************************************************************** * * File Name: * * NTSample.c * * Description: * * This sample demonstrates basic communication across an NT port between * two custom PLX applications. * * Revision History: * * 10-01-12 : PLX SDK v7.00 * ******************************************************************************/ #include #include #include #include "PlxApi.h" #if defined(_WIN32) #include "..\\Shared\\ConsFunc.h" #endif #if defined(PLX_LINUX) #include "ConsFunc.h" #endif #define NT_ENABLE #ifdef NT_ENABLE #include #include #include #include #include #include #include #include #include #endif /********************************************** * Definitions *********************************************/ #define NT_PCI_BUFFER_SIZE (1<<22) // Size of buffer for receiving data #define MAX_DEVICES_TO_LIST 50 // Max number of devices for user selection #define NT_MSG_SYSTEM_READY 0xFEEDFACE // Code passed between systems to signal ready #define NT_REQID_NO_SNOOP FALSE // Determine enable of No_Snoop bit #define NT_CONNECT_UNKNOWN 0 // NT standard connection (NT-Virtual <--> NT-Link) #define NT_CONNECT_STANDARD 1 // NT standard connection (NT-Virtual <--> NT-Link) #define NT_CONNECT_BACK_TO_BACK 2 // NT backj-to-back connection (NTV | NTL <--> NTL | NTV) #define NT_B2B_BAR_BASE 0x10000000 // Back-to-back NT Link side BARs base address //#define NT_B2B_BAR_BASE 0xe0000000 // Back-to-back NT Link side BARs base address #define PLX_TWONODE_SIGNATURE 0x77018111 // Determine connection type for Back-to-back ////////////// Direct Address Translation //////////// #define PLX_8000_BAR_2_TRAN_LOWER 0xC3C // BAR 2 lower 32-address translation reg. #define PLX_8000_BAR_2_TRAN_UPPER 0xC40 // BAR 2 upper 32-address translation reg. #define PLX_8000_BAR_4_TRAN_LOWER 0xC44 // BAR 4 lower 32-address translation reg. #define PLX_8000_BAR_4_TRAN_UPPER 0xC48 // BAR 4 upper 32-address translation reg. #define PLX_8500_BAR_2_LIMIT_LOWER 0xC4C // 8500-series BAR 2 limit lower 32-address #define PLX_8500_BAR_2_LIMIT_UPPER 0xC50 // 8500-series BAR 2 limit upper 32-address #define PLX_8500_BAR_4_LIMIT_LOWER 0xC54 // 8500-series BAR 4 limit lower 32-address #define PLX_8500_BAR_4_LIMIT_UPPER 0xC58 // 8500-series BAR 4 limit upper 32-address /********************************************** * Definitions *********************************************/ #define PlxBarMem_32(Va, offset) *(VU32*)((U8*)Va + offset) #define FileName "/usr/local/share/diag_env" typedef struct _PLX_NT_HOST { U8 NtConnectType; U8 bInitialized; U16 PlxChip; } PLX_NT_HOST; // PLX Direct Address Translation Strture typedef struct _PLX_DIRECT_ADDRESS { U64 DestinationAddr; U64 Size; } PLX_DIRECT_ADDRESS; void signalHandler(int signum); /********************************************** * Functions *********************************************/ S8 SelectDevice_NT( PLX_DEVICE_KEY *pKey ); S8 WaitForB2BConnection( VOID **pBarVa, U64 BarOffset, U32 VirRegOffset ); S8 WaitForConnection( PLX_DEVICE_OBJECT *pDevice ); PLX_STATUS PlxNT_DetermineConnectType( PLX_DEVICE_OBJECT *pDevice, PLX_NT_HOST *pRemHost ); PLX_STATUS PlxNT_B2B_Initialize( PLX_DEVICE_OBJECT *pDevice, PLX_NT_HOST *pRemHost ); PLX_STATUS PlxNT_B2B_Cleanup( PLX_DEVICE_OBJECT *pDevice, PLX_NT_HOST *pRemHost ); PLX_STATUS PlxPci_SetupNtB2BTranslation( PLX_DEVICE_OBJECT *pDevice, U8 BarIndex, PLX_DIRECT_ADDRESS DirAddr ); PLX_STATUS PlxPci_SetupNtTranslation( PLX_DEVICE_OBJECT *pDevice, U8 BarIndex, PLX_DIRECT_ADDRESS DirAddr ); VOID *BarVa; PLX_STATUS status; PLX_NT_HOST RemoteHost; PLX_PHYSICAL_MEM PhysBuffer; PLX_DEVICE_KEY DeviceKey; PLX_DEVICE_OBJECT Device; FILE *pFile; /****************************************************************************** * * Function : ntb_setup * * Description: ntb setup function * *****************************************************************************/ int ntb_setup(int plx_id) { BarVa = NULL; status = 0; memset(&RemoteHost, 0x0, sizeof(RemoteHost)); memset(&PhysBuffer, 0x0, sizeof(PhysBuffer)); memset(&DeviceKey, 0x0, sizeof(DeviceKey)); memset(&Device, 0x0, sizeof(Device)); pFile = NULL; U8 BarNum; U16 ReqId_Write, ReqId_Read; U16 LutIndex; U64 size; U64 sizeHB; U64 value; U64 BarOffset; U64 PhysAddr; U64 RemoteBuffSize; VU32 *pSysMem; // VOID *BarVa; //PLX_STATUS status; //PLX_NT_HOST RemoteHost; //PLX_DEVICE_KEY DeviceKey; //PLX_PHYSICAL_MEM PhysBuffer; PLX_PCI_BAR_PROP BarProp; //PLX_DEVICE_OBJECT Device; PLX_DIRECT_ADDRESS DirAddr; U64 BarOffset_Rem; U32 VirRegOffset; pFile = fopen(FileName, "a+"); if(pFile == NULL) { printf("open %s fail\n", FileName); return -1; } // Mark physical buffer as not allocated PhysBuffer.PhysicalAddr = 0; memset(&PhysBuffer, 0x0, sizeof(PhysBuffer)); memset(&DeviceKey, PCI_FIELD_IGNORE, sizeof(PLX_DEVICE_KEY)); status = PlxPci_DeviceFind(&DeviceKey, plx_id==0?1:0); if (status != ApiSuccess) { printf("ERROR: Unable to find NTB device.\n"); goto _ExitApp; } status = PlxPci_DeviceOpen(&DeviceKey, &Device); if (status != ApiSuccess) { printf("ERROR: Unable to select the NTB device.\n"); goto _ExitApp; } Cons_printf( "\nSelected: %.4x %.4x [b:%02x s:%02x f:%x]\n\n", DeviceKey.DeviceId, DeviceKey.VendorId, DeviceKey.bus, DeviceKey.slot, DeviceKey.function ); /************************************ * Display the NT side ***********************************/ Cons_printf( "Communicating from : %s side\n", (DeviceKey.NTPortType == PLX_NT_PORT_LINK) ? "LINK" : "VIRTUAL" ); /************************************ * Identify connection type ***********************************/ Cons_printf("Determine NT connect type : "); status = PlxNT_DetermineConnectType( &Device, &RemoteHost ); if ((status != ApiSuccess) || (RemoteHost.NtConnectType == NT_CONNECT_UNKNOWN)) { Cons_printf("ERROR: Unable to determine NT connect type\n"); goto _ExitApp; } Cons_printf( "%s\n", (RemoteHost.NtConnectType == NT_CONNECT_STANDARD) ? "Standard (NTV <---> NTL)" : "Back-to-Back (NTV-NTL <---> NTL-NTV)" ); /************************************ * Initialize back-to-back ***********************************/ if (RemoteHost.NtConnectType == NT_CONNECT_BACK_TO_BACK) { Cons_printf("Setup NT Back-to-Back : "); status = PlxNT_B2B_Initialize( &Device, &RemoteHost ); if (status != ApiSuccess) goto _ExitApp; Cons_printf("Ok\n"); } /************************************************************* * Get PCI BAR and map ************************************************************/ // Only PCI BAR 2 is currently supported BarNum = 2; Cons_printf("Get BAR %d properties : ", BarNum); status = PlxPci_PciBarProperties( &Device, BarNum, &BarProp ); if (status != ApiSuccess) { Cons_printf("ERROR: Unable to get PCI BAR properties\n"); goto _ExitApp; } Cons_printf("Ok (Size:%ld KB)\n", ((PLX_UINT_PTR)BarProp.Size >> 10)); // Map the BAR to a virtual address Cons_printf("Map BAR %d to user space : ", BarNum); status = PlxPci_PciBarMap( &Device, BarNum, &BarVa ); if (status != ApiSuccess) { Cons_printf("ERROR: Unable to map PCI BAR\n"); goto _ExitApp; } Cons_printf("Ok (VA:%p)\n", BarVa); /************************************************************* * Determine Requester ID & add LUT entry ************************************************************/ Cons_printf("Probe for write ReqID : "); status = PlxPci_Nt_ReqIdProbe( &Device, FALSE, // Probe for writes &ReqId_Write ); if (status != ApiSuccess) { Cons_printf("ERROR: Unable to probe ReqID, auto-add 0,0,0\n"); ReqId_Write = 0; } else { Cons_printf( "Ok (ReqID=%04X [b:%02X s:%02X f:%01X])\n", ReqId_Write, (ReqId_Write >> 8) & 0xFF, (ReqId_Write >> 3) & 0x1F, (ReqId_Write >> 0) & 0x03 ); } Cons_printf("Add write Req ID to LUT : "); // Default to auto-selected LUT index LutIndex = (U16)-1; if (PlxPci_Nt_LutAdd( &Device, &LutIndex, ReqId_Write, FALSE // Snoop must be disabled ) != ApiSuccess) { Cons_printf("ERROR: Unable to add LUT entry\n"); } else { Cons_printf( "Ok (LUT_Index=%d No_Snoop=%s)\n", LutIndex, (NT_REQID_NO_SNOOP) ? "ON" : "OFF" ); } if (RemoteHost.NtConnectType == NT_CONNECT_BACK_TO_BACK) { Cons_printf("Probe for read ReqID : "); if (PlxPci_Nt_ReqIdProbe( &Device, TRUE, // Probe for reads &ReqId_Read ) != ApiSuccess) { Cons_printf("ERROR: Unable to probe ReqID\n"); } else { Cons_printf( "Ok (ReqID=%04X [b:%02X s:%02X f:%01X])\n", ReqId_Read, (ReqId_Read >> 8) & 0xFF, (ReqId_Read >> 3) & 0x1F, (ReqId_Read >> 0) & 0x03 ); Cons_printf("Add read Req ID to LUT : "); if (ReqId_Read == ReqId_Write) { Cons_printf("-- Read Req ID matches write, skip LUT add --\n"); } else { // Default to auto-selected LUT index LutIndex = (U16)-1; if (PlxPci_Nt_LutAdd( &Device, &LutIndex, ReqId_Read, FALSE // Snoop must be disabled ) != ApiSuccess) { Cons_printf("ERROR: Unable to add LUT entry\n"); } else { Cons_printf("Ok (LUT_Index=%d No_Snoop=OFF)\n", LutIndex); } } } } /************************************************************* * Allocate & map PCI buffer ************************************************************/ Cons_printf("Allocate PCI buffer : "); // Set desired size of buffer PhysBuffer.Size = NT_PCI_BUFFER_SIZE; status = PlxPci_PhysicalMemoryAllocate( &Device, &PhysBuffer, TRUE ); if (status != ApiSuccess) { Cons_printf("ERROR: Unable to allocate buffer for data transfers\n"); goto _ExitApp; } Cons_printf( "Ok (PCI:%08lX Size:%ld B)\n", (PLX_UINT_PTR)PhysBuffer.PhysicalAddr, (PLX_UINT_PTR)PhysBuffer.Size ); //save readBuffer fprintf(pFile, "ntbReadWindow%d=0x%llx\n",plx_id, PhysBuffer.PhysicalAddr); Cons_printf("Map PCI buffer : "); status = PlxPci_PhysicalMemoryMap( &Device, &PhysBuffer ); if (status != ApiSuccess) { Cons_printf("ERROR: Unable to map to user space\n"); goto _ExitApp; } Cons_printf( "Ok (VA:%p)\n", PLX_INT_TO_PTR(PhysBuffer.UserAddr) ); // Setup a pointer to the buffer pSysMem = PLX_INT_TO_PTR(PhysBuffer.UserAddr); /************************************************************* * Post buffer properties for other side ************************************************************/ Cons_printf("Broadcast buffer properties: "); // Set mailbox to write if (DeviceKey.NTPortType == PLX_NT_PORT_LINK) value = 6; else value = 3; // Post buffer address PlxPci_PlxMailboxWrite( &Device, (U16)value, (U32)PhysBuffer.PhysicalAddr ); // Post buffer size PlxPci_PlxMailboxWrite( &Device, (U16)(value + 1), (U32)PhysBuffer.Size ); if (RemoteHost.NtConnectType == NT_CONNECT_BACK_TO_BACK) { PlxPci_PlxMailboxWrite( &Device, 0, PLX_TWONODE_SIGNATURE ); } Cons_printf("Ok\n"); #if 0 printf("after writing PLX_TWONODE_SIGNATURE by mailbox...\n");//check do { Plx_sleep(500); if (Cons_kbhit()) { if (Cons_getch() == 27) { break; } } } while (1); #endif /************************************************************ * Establish connection with other side ************************************************************/ BarOffset = 0; BarOffset_Rem = 0; VirRegOffset = 0; if (RemoteHost.NtConnectType == NT_CONNECT_BACK_TO_BACK) { switch (DeviceKey.DeviceId & 0xFF00) { case 0x8600: VirRegOffset = 0x10000; break; case 0x8700: VirRegOffset = 0x3E000; break; default: VirRegOffset = 0; } /************************************************************* * Set up NT translation *************************************************************/ Cons_printf("Setup B2B NT translation: "); // Convert BAR size to range size = ~((U32)BarProp.Size - 1); PhysAddr = NT_B2B_BAR_BASE; // Calculate BAR offset BarOffset = PhysAddr & ~size; //printf("\nBarOffset: 0x%llx\n", BarOffset);//check RemoteBuffSize = (U32)BarProp.Size; //printf("RemoteBuffSize: 0x%llx\n", RemoteBuffSize);//check //printf("(U32)BarProp.Size: 0x%x\n",(U32)BarProp.Size);//check //printf("BarProp.Size: 0x%llx\n",BarProp.Size);//Check // Verify we don't exceed BAR limits //if ((BarOffset + RemoteBuffSize) > (U32)BarProp.Size) if ((BarOffset + RemoteBuffSize) > BarProp.Size) { Cons_printf("ERROR: Remote buffer exceeds BAR space limits\n"); goto _ExitApp; } // Calculate base address for translation PhysAddr &= size; // Prepare for NT translation setup DirAddr.DestinationAddr = PhysAddr; DirAddr.Size = BarProp.Size; status = PlxPci_SetupNtTranslation( &Device, BarNum, DirAddr ); if (status != ApiSuccess) { Cons_printf("ERROR: Unable to setup NT translation\n"); goto _ExitApp; } Cons_printf("Ok (BAR offset:%08X)\n", BarOffset); #if 0 printf("after mapping link side CSR...\n");//Check do { Plx_sleep(500); if (Cons_kbhit()) { if (Cons_getch() == 27) { break; } } } while (1); #endif if ((WaitForB2BConnection( BarVa, BarOffset, VirRegOffset) ) != 0) { Cons_printf("ERROR: Unable to establish B2B connection\n"); goto _ExitApp; } value = PlxPci_PlxMailboxRead( &Device, 2, NULL ); if (value == NT_MSG_SYSTEM_READY) { PlxPci_PlxMailboxWrite( &Device, 2, 0 ); } else { //Wait for establishing connection of the other side do { value = PlxBarMem_32(BarVa, BarOffset+VirRegOffset+0x1c74); Plx_sleep(500); } while ( value == NT_MSG_SYSTEM_READY ); } PlxPci_PlxMailboxWrite( &Device, 0, 0 ); PlxPci_PlxMailboxWrite( &Device, 2, 0 ); } else { if (WaitForConnection( &Device ) != 0) { Cons_printf("ERROR: Unable to establish connection\n"); goto _ExitApp; } } /************************************************************* * Get buffer information from other side ************************************************************/ Cons_printf("Get buffer address : "); if (RemoteHost.NtConnectType == NT_CONNECT_BACK_TO_BACK) { PhysAddr = PlxBarMem_32(BarVa, BarOffset + VirRegOffset + 0x1c78); RemoteBuffSize = PlxBarMem_32(BarVa, BarOffset + VirRegOffset + 0x1c7c); Cons_printf("Ok Remote (Addr:%08X Size:%dB)\n", PhysAddr, RemoteBuffSize); sizeHB = PlxBarMem_32(BarVa, BarOffset + VirRegOffset + 0x10e4 + ((0x4)*(BarNum)) ); //printf("Get buffer address, sizeHB: 0x%llx\n", sizeHB);//check size = PlxBarMem_32(BarVa, BarOffset + VirRegOffset + 0x10e4 + ((0x4)*(BarNum-1))); size &= 0xFFFF0000; //printf("Get buffer address, size: 0x%llx\n", size);//check size = ((sizeHB << 32) | size); //printf("Get buffer address, size: 0x%llx\n", size);//check BarOffset_Rem = PhysAddr & ~size; //printf("Get buffer address, BarOffset_Rem: 0x%llx\n", BarOffset_Rem);//check } else { // Set mailbox to read if (DeviceKey.NTPortType == PLX_NT_PORT_LINK) value = 3; else value = 6; // Get buffer address PhysAddr = PlxPci_PlxMailboxRead( &Device, (S8)value, NULL ); // Get buffer size RemoteBuffSize = PlxPci_PlxMailboxRead( &Device, (U16)(value + 1), NULL ); Cons_printf("Ok (Addr:%08X Size:%dB)\n", PhysAddr, RemoteBuffSize); } /************************************************************* * Set up NT translation ************************************************************/ Cons_printf("Setup NT translation: "); if (RemoteHost.NtConnectType == NT_CONNECT_BACK_TO_BACK) { // Convert BAR size to range sizeHB = PlxPci_PlxRegisterRead( &Device, 0x1000 + 0xe4 + ((0x4)*(BarNum)) , NULL ); size = PlxPci_PlxRegisterRead( &Device, 0x1000 + 0xe4 + ((0x4)*(BarNum-1)), NULL ); size &= 0xFFFF0000; size = ((sizeHB << 32) | size); //printf("Setup NT translation, size: 0x%llx\n", size);//check // Calculate BAR offset BarOffset = PhysBuffer.PhysicalAddr & ~size; //printf("Setup NT translation, BarOffset: 0x%llx\n", BarOffset);//check // Verify we don't exceed BAR limits if ((BarOffset + RemoteBuffSize) > BarProp.Size) { Cons_printf("ERROR: Remote buffer exceeds BAR space limits\n"); goto _ExitApp; } // Calculate base address for translation PhysBuffer.PhysicalAddr &= size; // Prepare for NT translation setup DirAddr.DestinationAddr = PhysBuffer.PhysicalAddr; DirAddr.Size = BarProp.Size; status = PlxPci_SetupNtB2BTranslation( &Device, BarNum, DirAddr ); if (status != ApiSuccess) { Cons_printf("ERROR: Unable to setup NT B2B translation\n"); goto _ExitApp; } //check U64 u64Temp; u64Temp = NT_B2B_BAR_BASE+0x4000000; u64Temp = u64Temp << 32; DirAddr.DestinationAddr = u64Temp; DirAddr.Size = BarProp.Size; status = PlxPci_SetupNtTranslation( &Device, BarNum, DirAddr ); if (status != ApiSuccess) { Cons_printf("ERROR: Unable to setup NT translation\n"); goto _ExitApp; } Cons_printf("Ok Remote (BAR offset:%08X)\n", BarOffset_Rem); } else { // Convert BAR size to range size = ~((U32)BarProp.Size - 1); // Calculate BAR offset BarOffset = PhysAddr & ~size; // Verify we don't exceed BAR limits if ((BarOffset + RemoteBuffSize) > (U32)BarProp.Size) { Cons_printf("ERROR: Remote buffer exceeds BAR space limits\n"); goto _ExitApp; } // Calculate base address for translation PhysAddr &= size; // Prepare for NT translation setup DirAddr.DestinationAddr = PhysAddr; DirAddr.Size = BarProp.Size; status = PlxPci_SetupNtTranslation( &Device, BarNum, DirAddr ); if (status != ApiSuccess) { Cons_printf("ERROR: Unable to setup NT translation\n"); goto _ExitApp; } Cons_printf("Ok (BAR offset:%08X)\n", BarOffset); } //save write window fprintf(pFile, "ntbWriteWindow%d=0x%llx\n", plx_id, BarProp.Physical + BarOffset_Rem); //save window size fprintf(pFile, "ntbWindowSize%d=%lld\n", plx_id, PhysBuffer.Size); //save NT_B2B_BAR_BASE fprintf(pFile, "ntbB2bBarBase%d=0x%llx\n", plx_id, NT_B2B_BAR_BASE); //save Remote Buffer Size fprintf(pFile, "ntbRemoteBuffSize%d=%lld\n", plx_id, PhysBuffer.Size); fclose(pFile); signal(SIGTERM, signalHandler); return 0; do { Plx_sleep(500); } while (1); #if 0 //check speed //U64* buffer; // U32 sizeDW; U32 index; struct timeval StartTime; struct timeval EndTime; struct timeval spendTime; double costTime; // sizeDW = NT_PCI_BUFFER_SIZE/4; //buffer = (U64*)malloc(sizeof(U64)*sizeDW); gettimeofday(&StartTime, NULL); for(index=0; index "); Cons_scanf("%d", &i); } while (i > NumDevices); if (i == 0) return -1; // Return selected device information *pKey = DevKey_NT[i - 1]; return (S8)NumDevices; } /****************************************************************************** * * Function : WaitForConnection * * Description: * *****************************************************************************/ S8 WaitForB2BConnection( VOID **pBarVa, U64 BarOffset, U32 VirRegOffset ) { //char DispStat[] = "/|\\-"; S16 LoopCount = 180; U32 value; Cons_printf( "\n" "Wait for the other side (up to 90 secs...): " ); // Wait for other side to respond do { // Cons_printf("%c\b", DispStat[(LoopCount % 4)]); // Cons_fflush( stdout ); LoopCount--; // Small delay Plx_sleep(500); value = PlxBarMem_32(pBarVa, BarOffset+VirRegOffset+0x1c6c); //printf("WaitForB2BConnection, value --- 0x%x\n", value);//check //17-01-23 NtApp: remove them due to we don't want to catch STDIN while run in background. /* if (Cons_kbhit()) { if (Cons_getch() == 27) { LoopCount = -1; } } */ } while ((LoopCount > 0) && ( value != PLX_TWONODE_SIGNATURE)); if (LoopCount == 0) { Cons_printf("ERROR - Timeout\n"); return -1; } if (LoopCount == -1) { Cons_printf("User cancelled\n"); return -1; } #if 0 printf("get PLX_TWONODE_SIGNATURE of the other PCM's link side...\n");//check do { Plx_sleep(500); if (Cons_kbhit()) { if (Cons_getch() == 27) { break; } } } while (1); #endif PlxBarMem_32(pBarVa, BarOffset+VirRegOffset+0x1c74) = NT_MSG_SYSTEM_READY; #if 0 printf("after writing NT_MSG_SYSTEM_READY to the other PCM's link side CSR...\n");//check do { Plx_sleep(500); if (Cons_kbhit()) { if (Cons_getch() == 27) { break; } } } while (1); #endif Cons_printf("\n -- Connection established! sig %x--\n\n", value); return 0; } /****************************************************************************** * * Function : WaitForConnection * * Description: * *****************************************************************************/ S8 WaitForConnection( PLX_DEVICE_OBJECT *pDevice ) { char DispStat[] = "/|\\-"; S16 LoopCount; U16 MB_Read; U16 MB_Write; U32 RegValue; Cons_printf( "\n" "Wait for %s side (ESC to cancel): ", (pDevice->Key.NTPortType == PLX_NT_PORT_LINK) ? "Virtual" : "Link" ); // Set mailboxes to use if (pDevice->Key.NTPortType == PLX_NT_PORT_LINK) { MB_Read = 2; MB_Write = 5; } else { MB_Read = 5; MB_Write = 2; } // Notify other side ready to connect PlxPci_PlxMailboxWrite( pDevice, MB_Write, NT_MSG_SYSTEM_READY ); // Set counter LoopCount = 180; // Wait for other side to respond do { Cons_printf("%c\b", DispStat[(LoopCount % 4)]); Cons_fflush( stdout ); LoopCount--; // Small delay Plx_sleep(500); // Check for a message RegValue = PlxPci_PlxMailboxRead( pDevice, MB_Read, NULL ); // Check for ESC key to cancel if (Cons_kbhit()) { if (Cons_getch() == 27) { LoopCount = -1; } } } while ((LoopCount > 0) && (RegValue != NT_MSG_SYSTEM_READY)); // Clear connect message on fail if (LoopCount <= 0) { PlxPci_PlxMailboxWrite( pDevice, MB_Write, 0 ); } // Clear response message PlxPci_PlxMailboxWrite( pDevice, MB_Read, 0 ); if (LoopCount == 0) { Cons_printf("ERROR - Timeout\n"); return -1; } if (LoopCount == -1) { Cons_printf("User cancelled\n"); return -1; } Cons_printf("Ok\n"); Cons_printf("\n -- Connection established! --\n\n"); return 0; } /****************************************************************************** * * Function : PlxNT_DetermineConnectType * * Description: Attempts to detect the type of NT connection * *****************************************************************************/ PLX_STATUS PlxNT_DetermineConnectType( PLX_DEVICE_OBJECT *pDevice, PLX_NT_HOST *pRemHost ) { U32 RegValue; // Default to standard NT connection pRemHost->NtConnectType = NT_CONNECT_STANDARD; // NT-Virtual could be either type of connection if (pDevice->Key.NTPortType == PLX_NT_PORT_VIRTUAL) { // Probe some NT-Link registers to try & determine type // Check if BAR 0 assigned system address RegValue = PlxPci_PlxRegisterRead( pDevice, 0x1000 + 0x10, NULL ); RegValue &= ~0xF; if ((RegValue != 0) && ((RegValue & 0xFF000000) != NT_B2B_BAR_BASE)) goto _Exit_PlxNT_DetermineConnectType; // Check if BAR 2 assigned system address RegValue = PlxPci_PlxRegisterRead( pDevice, 0x1000 + 0x18, NULL ); RegValue &= ~0xF; if (RegValue != 0) goto _Exit_PlxNT_DetermineConnectType; RegValue = PlxPci_PlxRegisterRead( pDevice, 0x1000 + 0x1c, NULL ); if ((RegValue != 0) && ((RegValue & 0xFFFFFFC0) != (NT_B2B_BAR_BASE+0x4000000))) goto _Exit_PlxNT_DetermineConnectType; // Check if assigned system interrupt RegValue = PlxPci_PlxRegisterRead( pDevice, 0x1000 + 0x3C, NULL ); RegValue &= 0xFF; if ((RegValue != 0) && (RegValue != 0xFF)) goto _Exit_PlxNT_DetermineConnectType; // Passed all tests so likely Back-to-Back pRemHost->NtConnectType = NT_CONNECT_BACK_TO_BACK; } _Exit_PlxNT_DetermineConnectType: return ApiSuccess; } /****************************************************************************** * * Function : PlxNT_B2B_Initialize * * Description: Initializes 'hidden' resources for NT Back-to-Back connection * *****************************************************************************/ PLX_STATUS PlxNT_B2B_Initialize( PLX_DEVICE_OBJECT *pDevice, PLX_NT_HOST *pRemHost ) { U32 BarMask; U64 u64BarMask; U32 value; if (pRemHost->NtConnectType != NT_CONNECT_BACK_TO_BACK) return ApiInvalidState; // Verify BAR 2 is enabled BarMask = PlxPci_PlxRegisterRead( pDevice, 0x1000 + 0xE8, NULL ); u64BarMask = (U64)PlxPci_PlxRegisterRead(pDevice, 0x1000+0xEC, NULL); u64BarMask = (u64BarMask << 32) | BarMask; u64BarMask &= ~0xF; if (BarMask == 0) { Cons_printf("ERROR - NT-Link BAR 2 not enabled\n"); return ApiInsufficientResources; } // Set NT-Link side BAR 0 value = PlxPci_PlxRegisterRead(pDevice, 0x1000 + 0xE4, NULL); if(value == 0x0) { PlxPci_PlxRegisterWrite(pDevice, 0x1000 + 0xE4, 0x2); } PlxPci_PlxRegisterWrite( pDevice, 0x1000 + 0x10, NT_B2B_BAR_BASE ); //PlxPci_PlxRegisterWrite( pDevice, 0x1000 + 0x14, NT_B2B_BAR_BASE ); // Set NT-Link side BAR 2 //PlxPci_PlxRegisterWrite( pDevice, 0x1000 + 0x18, NT_B2B_BAR_BASE + 0x4000000); PlxPci_PlxRegisterWrite( pDevice, 0x1000 + 0x1C, NT_B2B_BAR_BASE + 0x4000000); #if 0//tom:The LUT has been set up by the EEPROM // Enable entry 0 for 0:0.0 in the NTL LUT PlxPci_PlxRegisterWrite( pDevice, 0x1000 + 0xC98, (0<<24) | (Plx_PciToReqId(0,0,0)<<4) | (1 << 0) ); // Enable entry 2 for 0:1.0 in the NTL LUT PlxPci_PlxRegisterWrite( pDevice, 0x1000 + 0xC98, (1<<24) | (Plx_PciToReqId(0,0,1)<<4) | (1 << 0) ); #endif // Enable device PlxPci_PlxRegisterWrite( pDevice, 0x1000 + 0x04, (0x7 << 0) ); // Mark connection initialized pRemHost->bInitialized = TRUE; return ApiSuccess; } /****************************************************************************** * * Function : PlxNT_B2B_Cleanup * * Description: Cleans up NT Back-to-Back connection * *****************************************************************************/ PLX_STATUS PlxNT_B2B_Cleanup( PLX_DEVICE_OBJECT *pDevice, PLX_NT_HOST *pRemHost ) { if (pRemHost->NtConnectType != NT_CONNECT_BACK_TO_BACK) return ApiInvalidState; // Do nothing if not initialized if (pRemHost->bInitialized == FALSE) return ApiSuccess; PlxPci_PlxMailboxWrite( pDevice, 0, 0 ); pRemHost->bInitialized = FALSE; return ApiSuccess; } /****************************************************************************** * * Function : PlxPci_SetupNtB2BTranslation * * Description: * *****************************************************************************/ PLX_STATUS PlxPci_SetupNtB2BTranslation( PLX_DEVICE_OBJECT *pDevice, U8 BarIndex, PLX_DIRECT_ADDRESS DirAddr ) { U16 DestBaseLow; U16 DestBaseHi; // Only BAR 2 currently supported if (BarIndex != 2) return ApiUnsupportedFunction; if (pDevice->Key.NTPortType == PLX_NT_PORT_LINK) { return ApiInvalidAddress; } if (BarIndex == 2) { DestBaseLow = PLX_8000_BAR_2_TRAN_LOWER + 0x1000; DestBaseHi = PLX_8000_BAR_2_TRAN_UPPER + 0x1000; } else { DestBaseLow = PLX_8000_BAR_4_TRAN_LOWER + 0x1000; DestBaseHi = PLX_8000_BAR_4_TRAN_UPPER + 0x1000; } PlxPci_PlxRegisterWrite( pDevice, DestBaseLow, (U32)DirAddr.DestinationAddr ); PlxPci_PlxRegisterWrite( pDevice, DestBaseHi, (U32)(DirAddr.DestinationAddr >> 32) ); return ApiSuccess; } /****************************************************************************** * * Function : PlxPci_SetupNtTranslation * * Description: * *****************************************************************************/ PLX_STATUS PlxPci_SetupNtTranslation( PLX_DEVICE_OBJECT *pDevice, U8 BarIndex, PLX_DIRECT_ADDRESS DirAddr ) { U16 DestBaseLow; U16 DestBaseHi; U16 DestLimitLow; U16 DestLimitHi; // Only BAR 2 currently supported if (BarIndex != 2) return ApiUnsupportedFunction; if (pDevice->Key.NTPortType == PLX_NT_PORT_LINK) { if (BarIndex == 2) { if (((DirAddr.DestinationAddr >> 32) != 0) || ((DirAddr.Size >> 32) != 0)) { return ApiInvalidAddress; } } } if (BarIndex == 2) { DestBaseLow = PLX_8000_BAR_2_TRAN_LOWER; DestBaseHi = PLX_8000_BAR_2_TRAN_UPPER; DestLimitLow = PLX_8500_BAR_2_LIMIT_LOWER; DestLimitHi = PLX_8500_BAR_2_LIMIT_UPPER; } else { DestBaseLow = PLX_8000_BAR_4_TRAN_LOWER; DestBaseHi = PLX_8000_BAR_4_TRAN_UPPER; DestLimitLow = PLX_8500_BAR_4_LIMIT_LOWER; DestLimitHi = PLX_8500_BAR_4_LIMIT_UPPER; } PlxPci_PlxRegisterWrite( pDevice, DestBaseLow, (U32)DirAddr.DestinationAddr ); PlxPci_PlxRegisterWrite( pDevice, DestBaseHi, (U32)(DirAddr.DestinationAddr >> 32) ); // Set limit registers to 0 on 8500 series if ((pDevice->Key.PlxChip & 0xFF00) == 0x8500) { PlxPci_PlxRegisterWrite( pDevice, DestLimitLow, 0 ); PlxPci_PlxRegisterWrite( pDevice, DestLimitHi, 0 ); } return ApiSuccess; }