home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / windr440.zip / windrive.zip / WinDriver / samples / pci_diag / pci_lib.c < prev    next >
C/C++ Source or Header  |  2000-03-30  |  15KB  |  464 lines

  1. //////////////////////////////////////////////////////////////////////
  2. // File - pci_lib.c
  3. //
  4. // Library for accessing a PCI card.
  5. // Code was generated by WinDriver Wizard.
  6. // It accesses hardware via WinDriver functions.
  7. // 
  8. //////////////////////////////////////////////////////////////////////
  9. #include <stdio.h>
  10. #include "pci_lib.h"
  11. #include "../../include/windrvr_int_thread.h"
  12.  
  13.  
  14. // this string is set to an error message, if one occurs
  15. CHAR PCI_ErrorString[1024];
  16.  
  17. // internal function used by PCI_Open()
  18. BOOL PCI_DetectCardElements(PCI_HANDLE hPCI);
  19.  
  20. DWORD PCI_CountCards (DWORD dwVendorID, DWORD dwDeviceID)
  21. {
  22.     WD_VERSION ver;
  23.     WD_PCI_SCAN_CARDS pciScan;
  24.     HANDLE hWD;
  25.  
  26.     PCI_ErrorString[0] = '\0';
  27.     hWD = WD_Open();
  28.     // check if handle valid & version OK
  29.     if (hWD==INVALID_HANDLE_VALUE) 
  30.     {
  31.         sprintf( PCI_ErrorString, "Failed opening " WD_PROD_NAME " device\n");
  32.         return 0;
  33.     }
  34.  
  35.     BZERO(ver);
  36.     WD_Version(hWD,&ver);
  37.     if (ver.dwVer<WD_VER) 
  38.     {
  39.         sprintf( PCI_ErrorString, "Incorrect " WD_PROD_NAME " version\n");
  40.         WD_Close (hWD);
  41.         return 0;
  42.     }
  43.  
  44.     BZERO(pciScan);
  45.     pciScan.searchId.dwVendorId = dwVendorID;
  46.     pciScan.searchId.dwDeviceId = dwDeviceID;
  47.     WD_PciScanCards (hWD, &pciScan);
  48.     WD_Close (hWD);
  49.     if (pciScan.dwCards==0)
  50.         sprintf( PCI_ErrorString, "no cards found\n");
  51.     return pciScan.dwCards;
  52. }
  53.  
  54. BOOL PCI_Open (PCI_HANDLE *phPCI, DWORD dwVendorID, DWORD dwDeviceID, DWORD nCardNum, DWORD options)
  55. {
  56.     PCI_HANDLE hPCI = (PCI_HANDLE) malloc (sizeof (PCI_STRUCT));
  57.  
  58.     WD_VERSION ver;
  59.     WD_PCI_SCAN_CARDS pciScan;
  60.     WD_PCI_CARD_INFO pciCardInfo;
  61.  
  62.     *phPCI = NULL;
  63.     PCI_ErrorString[0] = '\0';
  64.     BZERO(*hPCI);
  65.  
  66.     hPCI->cardReg.hCard = 0;
  67.     hPCI->hWD = WD_Open();
  68.  
  69.     // check if handle valid & version OK
  70.     if (hPCI->hWD==INVALID_HANDLE_VALUE)
  71.     {
  72.         sprintf( PCI_ErrorString, "Failed opening " WD_PROD_NAME " device\n");
  73.         goto Exit;
  74.     }
  75.  
  76.     BZERO(ver);
  77.     WD_Version(hPCI->hWD,&ver);
  78.     if (ver.dwVer<WD_VER)
  79.     {
  80.         sprintf( PCI_ErrorString, "Incorrect " WD_PROD_NAME " version\n");
  81.         goto Exit;
  82.     }
  83.  
  84.     BZERO(pciScan);
  85.     pciScan.searchId.dwVendorId = dwVendorID;
  86.     pciScan.searchId.dwDeviceId = dwDeviceID;
  87.     WD_PciScanCards (hPCI->hWD, &pciScan);
  88.     if (pciScan.dwCards==0) // Found at least one card
  89.     {
  90.         sprintf( PCI_ErrorString, "Could not find PCI card\n");
  91.         goto Exit;
  92.     }
  93.     if (pciScan.dwCards<=nCardNum)
  94.     {
  95.         sprintf( PCI_ErrorString, "Card out of range of available cards\n");
  96.         goto Exit;
  97.     }
  98.  
  99.     BZERO(pciCardInfo);
  100.     pciCardInfo.pciSlot = pciScan.cardSlot[nCardNum];
  101.     WD_PciGetCardInfo (hPCI->hWD, &pciCardInfo);
  102.     hPCI->pciSlot = pciCardInfo.pciSlot;
  103.     hPCI->cardReg.Card = pciCardInfo.Card;
  104.  
  105.     hPCI->fUseInt = (options & PCI_OPEN_USE_INT) ? TRUE : FALSE;
  106.     if (!hPCI->fUseInt)
  107.     {
  108.         DWORD i;
  109.         // Remove interrupt item if not needed
  110.         for (i=0; i<hPCI->cardReg.Card.dwItems; i++)
  111.         {
  112.             WD_ITEMS *pItem = &hPCI->cardReg.Card.Item[i];
  113.             if (pItem->item==ITEM_INTERRUPT)
  114.                 pItem->item = ITEM_NONE;
  115.         }
  116.     }
  117.     else
  118.     {
  119.         DWORD i;
  120.         // make interrupt resource sharable
  121.         for (i=0; i<hPCI->cardReg.Card.dwItems; i++)
  122.         {
  123.             WD_ITEMS *pItem = &hPCI->cardReg.Card.Item[i];
  124.             if (pItem->item==ITEM_INTERRUPT)
  125.                 pItem->fNotSharable = FALSE;
  126.         }
  127.     }
  128.  
  129.     hPCI->cardReg.fCheckLockOnly = FALSE;
  130.     WD_CardRegister (hPCI->hWD, &hPCI->cardReg);
  131.     if (hPCI->cardReg.hCard==0)
  132.     {
  133.         sprintf ( PCI_ErrorString, "Failed locking device\n");
  134.         goto Exit;
  135.     }
  136.  
  137.     if (!PCI_DetectCardElements(hPCI))
  138.     {
  139.         sprintf ( PCI_ErrorString, "Card does not have all items expected for PCI\n");
  140.         goto Exit;
  141.     }
  142.  
  143.     // Open finished OK
  144.     *phPCI = hPCI;
  145.     return TRUE;
  146.  
  147. Exit:
  148.     // Error during Open
  149.     if (hPCI->cardReg.hCard) 
  150.         WD_CardUnregister(hPCI->hWD, &hPCI->cardReg);
  151.     if (hPCI->hWD!=INVALID_HANDLE_VALUE)
  152.         WD_Close(hPCI->hWD);
  153.     free (hPCI);
  154.     return FALSE;
  155. }
  156.  
  157. void PCI_Close(PCI_HANDLE hPCI)
  158. {
  159.     // disable interrupts
  160.     if (PCI_IntIsEnabled(hPCI))
  161.         PCI_IntDisable(hPCI);
  162.  
  163.     // unregister card
  164.     if (hPCI->cardReg.hCard) 
  165.         WD_CardUnregister(hPCI->hWD, &hPCI->cardReg);
  166.  
  167.     // close WinDriver
  168.     WD_Close(hPCI->hWD);
  169.  
  170.     free (hPCI);
  171. }
  172.  
  173. void PCI_WritePCIReg(PCI_HANDLE hPCI, DWORD dwReg, DWORD dwData)
  174. {
  175.     WD_PCI_CONFIG_DUMP pciCnf;
  176.  
  177.     BZERO(pciCnf);
  178.     pciCnf.pciSlot = hPCI->pciSlot;
  179.     pciCnf.pBuffer = &dwData;
  180.     pciCnf.dwOffset = dwReg;
  181.     pciCnf.dwBytes = 4;
  182.     pciCnf.fIsRead = FALSE;
  183.     WD_PciConfigDump(hPCI->hWD,&pciCnf);
  184. }
  185.  
  186. DWORD PCI_ReadPCIReg(PCI_HANDLE hPCI, DWORD dwReg)
  187. {
  188.     WD_PCI_CONFIG_DUMP pciCnf;
  189.     DWORD dwVal;
  190.  
  191.     BZERO(pciCnf);
  192.     pciCnf.pciSlot = hPCI->pciSlot;
  193.     pciCnf.pBuffer = &dwVal;
  194.     pciCnf.dwOffset = dwReg;
  195.     pciCnf.dwBytes = 4;
  196.     pciCnf.fIsRead = TRUE;
  197.     WD_PciConfigDump(hPCI->hWD,&pciCnf);
  198.     return dwVal;
  199. }
  200.  
  201. BOOL PCI_DetectCardElements(PCI_HANDLE hPCI)
  202. {
  203.     DWORD i;
  204.     DWORD ad_sp;
  205.  
  206.     BZERO(hPCI->Int);
  207.     BZERO(hPCI->addrDesc);
  208.  
  209.     for (i=0; i<hPCI->cardReg.Card.dwItems; i++)
  210.     {
  211.         WD_ITEMS *pItem = &hPCI->cardReg.Card.Item[i];
  212.  
  213.         switch (pItem->item)
  214.         {
  215.         case ITEM_MEMORY:
  216.         case ITEM_IO:
  217.             {
  218.                 DWORD dwBytes;
  219.                 DWORD dwPhysAddr;
  220.                 BOOL fIsMemory;
  221.                 if (pItem->item==ITEM_MEMORY)
  222.                 {
  223.                     dwBytes = pItem->I.Mem.dwBytes;
  224.                     dwPhysAddr = pItem->I.Mem.dwPhysicalAddr;
  225.                     fIsMemory = TRUE;
  226.                 }
  227.                 else 
  228.                 {
  229.                     dwBytes = pItem->I.IO.dwBytes;
  230.                     dwPhysAddr = pItem->I.IO.dwAddr;
  231.                     fIsMemory = FALSE;
  232.                 }
  233.  
  234.                 for (ad_sp=0; ad_sp<PCI_ITEMS; ad_sp++)
  235.                 {
  236.                     DWORD dwPCIAddr;
  237.                     DWORD dwPCIReg;
  238.  
  239.                     if (PCI_IsAddrSpaceActive(hPCI, ad_sp)) continue;
  240.                     if (ad_sp<PCI_AD_EPROM) dwPCIReg = PCI_BAR0 + 4*ad_sp;
  241.                     else dwPCIReg = PCI_ERBAR;
  242.                     dwPCIAddr = PCI_ReadPCIReg(hPCI, dwPCIReg);
  243.                     if (dwPCIAddr & 1)
  244.                     {
  245.                         if (fIsMemory) continue;
  246.                         dwPCIAddr &= ~0x3;
  247.                     }
  248.                     else
  249.                     {
  250.                         if (!fIsMemory) continue;
  251.                         dwPCIAddr &= ~0xf;
  252.                     }
  253.                     if (dwPCIAddr==dwPhysAddr)
  254.                         break;
  255.                 }
  256.                 if (ad_sp<PCI_ITEMS)
  257.                 {
  258.                     DWORD j;
  259.                     hPCI->addrDesc[ad_sp].fActive = TRUE;
  260.                     hPCI->addrDesc[ad_sp].index = i;
  261.                     hPCI->addrDesc[ad_sp].fIsMemory = fIsMemory;
  262.                     hPCI->addrDesc[ad_sp].dwMask = 0;
  263.                     for (j=1; j<dwBytes && j!=0x80000000; j *= 2)
  264.                     {
  265.                         hPCI->addrDesc[ad_sp].dwMask = 
  266.                             (hPCI->addrDesc[ad_sp].dwMask << 1) | 1;
  267.                     }
  268.                 }
  269.             }
  270.             break;
  271.         case ITEM_INTERRUPT:
  272.             if (hPCI->Int.Int.hInterrupt) return FALSE;
  273.             hPCI->Int.Int.hInterrupt = pItem->I.Int.hInterrupt;
  274.             break;
  275.         }
  276.     }
  277.  
  278.     // check that all the items needed were found
  279.     // check if interrupt found
  280.     if (hPCI->fUseInt && !hPCI->Int.Int.hInterrupt) 
  281.     {
  282.         return FALSE;
  283.     }
  284.  
  285.     // check that at least one memory space was found
  286.     for (i = 0; i<PCI_ITEMS; i++)
  287.         if (PCI_IsAddrSpaceActive(hPCI, i)) break;
  288.     if (i==PCI_ITEMS) return FALSE;
  289.  
  290.     return TRUE;
  291. }
  292.  
  293. BOOL PCI_IsAddrSpaceActive(PCI_HANDLE hPCI, PCI_ADDR addrSpace){
  294.     return hPCI->addrDesc[addrSpace].fActive;
  295. }
  296.  
  297. // General read/write function
  298. void PCI_ReadWriteBlock(PCI_HANDLE hPCI, PCI_ADDR addrSpace, DWORD dwOffset, BOOL fRead, PVOID buf, DWORD dwBytes, PCI_MODE mode)
  299. {
  300.     WD_TRANSFER trans;
  301.     BOOL fMem = hPCI->addrDesc[addrSpace].fIsMemory;
  302.     // safty check: is the address range active
  303.     if (!PCI_IsAddrSpaceActive(hPCI, addrSpace)) return;
  304.     BZERO(trans);
  305.     if (fRead)
  306.     {
  307.         if (mode==PCI_MODE_BYTE) trans.cmdTrans = fMem ? RM_SBYTE : RP_SBYTE;
  308.         else if (mode==PCI_MODE_WORD) trans.cmdTrans = fMem ? RM_SWORD : RP_SWORD;
  309.         else if (mode==PCI_MODE_DWORD) trans.cmdTrans = fMem ? RM_SDWORD : RP_SDWORD;
  310.     }
  311.     else
  312.     {
  313.         if (mode==PCI_MODE_BYTE) trans.cmdTrans = fMem ? WM_SBYTE : WP_SBYTE;
  314.         else if (mode==PCI_MODE_WORD) trans.cmdTrans = fMem ? WM_SWORD : WP_SWORD;
  315.         else if (mode==PCI_MODE_DWORD) trans.cmdTrans = fMem ? WM_SDWORD : WP_SDWORD;
  316.     }
  317.     if (fMem)
  318.         trans.dwPort = hPCI->cardReg.Card.Item[hPCI->addrDesc[addrSpace].index].I.Mem.dwTransAddr;
  319.     else 
  320.         trans.dwPort = hPCI->cardReg.Card.Item[hPCI->addrDesc[addrSpace].index].I.IO.dwAddr;
  321.     trans.dwPort += dwOffset;
  322.  
  323.     trans.fAutoinc = TRUE;
  324.     trans.dwBytes = dwBytes;
  325.     trans.dwOptions = 0;
  326.     trans.Data.pBuffer = buf;
  327.     WD_Transfer (hPCI->hWD, &trans);
  328. }
  329.  
  330. BYTE PCI_ReadByte (PCI_HANDLE hPCI, PCI_ADDR addrSpace, DWORD dwOffset)
  331. {
  332.     BYTE data;
  333.     if (hPCI->addrDesc[addrSpace].fIsMemory)
  334.     {
  335.         PBYTE pData = (PBYTE) (hPCI->cardReg.Card.Item[hPCI->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset);
  336.         data = *pData; // read from the memory mapped range directly
  337.     }
  338.     else PCI_ReadWriteBlock( hPCI, addrSpace, dwOffset, TRUE, &data, sizeof (BYTE), PCI_MODE_BYTE);
  339.     return data;
  340. }
  341.  
  342. WORD PCI_ReadWord (PCI_HANDLE hPCI, PCI_ADDR addrSpace, DWORD dwOffset)
  343. {
  344.     WORD data;
  345.     if (hPCI->addrDesc[addrSpace].fIsMemory)
  346.     {
  347.         PWORD pData = (PWORD) (hPCI->cardReg.Card.Item[hPCI->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset);
  348.         data = *pData; // read from the memory mapped range directly
  349.     }
  350.     else PCI_ReadWriteBlock( hPCI, addrSpace, dwOffset, TRUE, &data, sizeof (WORD), PCI_MODE_WORD);
  351.     return data;
  352. }
  353.  
  354. DWORD PCI_ReadDword (PCI_HANDLE hPCI, PCI_ADDR addrSpace, DWORD dwOffset)
  355. {
  356.     DWORD data;
  357.     if (hPCI->addrDesc[addrSpace].fIsMemory)
  358.     {
  359.         PDWORD pData = (PDWORD) (hPCI->cardReg.Card.Item[hPCI->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset);
  360.         data = *pData; // read from the memory mapped range directly
  361.     }
  362.     else PCI_ReadWriteBlock( hPCI, addrSpace, dwOffset, TRUE, &data, sizeof (DWORD), PCI_MODE_DWORD);
  363.     return data;
  364. }
  365.  
  366. void PCI_WriteByte (PCI_HANDLE hPCI, PCI_ADDR addrSpace, DWORD dwOffset, BYTE data)
  367. {
  368.     if (hPCI->addrDesc[addrSpace].fIsMemory)
  369.     {
  370.         PBYTE pData = (PBYTE) (hPCI->cardReg.Card.Item[hPCI->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset);
  371.         *pData = data; // write to the memory mapped range directly
  372.     }
  373.     else PCI_ReadWriteBlock( hPCI, addrSpace, dwOffset, FALSE, &data, sizeof (BYTE), PCI_MODE_BYTE);
  374. }
  375.  
  376. void PCI_WriteWord (PCI_HANDLE hPCI, PCI_ADDR addrSpace, DWORD dwOffset, WORD data)
  377. {
  378.     if (hPCI->addrDesc[addrSpace].fIsMemory)
  379.     {
  380.         PWORD pData = (PWORD) (hPCI->cardReg.Card.Item[hPCI->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset);
  381.         *pData = data; // write to the memory mapped range directly
  382.     }
  383.     else PCI_ReadWriteBlock( hPCI, addrSpace, dwOffset, FALSE, &data, sizeof (WORD), PCI_MODE_WORD);
  384. }
  385.  
  386. void PCI_WriteDword (PCI_HANDLE hPCI, PCI_ADDR addrSpace, DWORD dwOffset, DWORD data)
  387. {
  388.     if (hPCI->addrDesc[addrSpace].fIsMemory)
  389.     {
  390.         PDWORD pData = (PDWORD) (hPCI->cardReg.Card.Item[hPCI->addrDesc[addrSpace].index].I.Mem.dwUserDirectAddr + dwOffset);
  391.         *pData = data; // write to the memory mapped range directly
  392.     }
  393.     else 
  394.         PCI_ReadWriteBlock( hPCI, addrSpace, dwOffset, FALSE, &data, sizeof (DWORD), PCI_MODE_DWORD);
  395. }
  396.  
  397. BOOL PCI_IntIsEnabled (PCI_HANDLE hPCI)
  398. {
  399.     if (!hPCI->fUseInt) return FALSE;
  400.     if (!hPCI->Int.hThread) return FALSE;
  401.     return TRUE;
  402. }
  403.  
  404. VOID PCI_IntHandler (PVOID pData)
  405. {
  406.     PCI_HANDLE hPCI = (PCI_HANDLE) pData;
  407.     PCI_INT_RESULT intResult;
  408.  
  409.     intResult.dwCounter = hPCI->Int.Int.dwCounter;
  410.     intResult.dwLost = hPCI->Int.Int.dwLost;
  411.     intResult.fStopped = hPCI->Int.Int.fStopped;
  412.     hPCI->Int.funcIntHandler(hPCI, &intResult);
  413. }
  414.  
  415. BOOL PCI_IntEnable (PCI_HANDLE hPCI, PCI_INT_HANDLER funcIntHandler)
  416. {
  417.     PCI_ADDR addrSpace;
  418.  
  419.     if (!hPCI->fUseInt) return FALSE;
  420.     // check if interrupt is already enabled
  421.     if (hPCI->Int.hThread) return FALSE;
  422.  
  423.     BZERO(hPCI->Int.Trans);
  424.     // This is a sample of handling interrupts:
  425.     // One transfer commands is issued. You will need to change this code.
  426.     // You must add transfer commands to CANCEL the source of the interrupt, otherwise, the
  427.     // PC will hang when an interrupt occurs!
  428.     addrSpace = PCI_AD_BAR0; // put the address space of the register here
  429.     if (hPCI->addrDesc[addrSpace].fIsMemory)
  430.     {
  431.         hPCI->Int.Trans[0].dwPort = hPCI->cardReg.Card.Item[hPCI->addrDesc[addrSpace].index].I.Mem.dwTransAddr;
  432.         hPCI->Int.Trans[0].cmdTrans = WM_DWORD;
  433.     }
  434.     else
  435.     {
  436.         hPCI->Int.Trans[0].dwPort = hPCI->cardReg.Card.Item[hPCI->addrDesc[addrSpace].index].I.IO.dwAddr;
  437.         hPCI->Int.Trans[0].cmdTrans = WP_DWORD;
  438.     }
  439.     hPCI->Int.Trans[0].dwPort += 0; // put the offset of the register from the beginning of the address space here
  440.     hPCI->Int.Trans[0].Data.Dword = 0; // put the data to write to the control register here
  441.     hPCI->Int.Int.dwCmds = 1;
  442.     hPCI->Int.Int.Cmd = hPCI->Int.Trans;
  443.     hPCI->Int.Int.dwOptions |= INTERRUPT_CMD_COPY;
  444.  
  445.     // this calls WD_IntEnable() and creates an interrupt handler thread
  446.     hPCI->Int.funcIntHandler = funcIntHandler;
  447.     if (!InterruptThreadEnable(&hPCI->Int.hThread, hPCI->hWD, &hPCI->Int.Int, PCI_IntHandler, (PVOID) hPCI))
  448.         return FALSE;
  449.  
  450.     return TRUE;
  451. }
  452.  
  453. void PCI_IntDisable (PCI_HANDLE hPCI)
  454. {
  455.     if (!hPCI->fUseInt) return;
  456.     if (!hPCI->Int.hThread) return;
  457.  
  458.     // this calls WD_IntDisable()
  459.     InterruptThreadDisable(hPCI->Int.hThread);
  460.  
  461.     hPCI->Int.hThread = NULL;
  462. }
  463.  
  464.